diff --git a/src/conio/win32cio.c b/src/conio/win32cio.c
index 59470235b34d0157d7d820f843764e3482dbe7fc..e1c4ac8f6bd3eba2f568ff5aaa79ce809daa3922 100644
--- a/src/conio/win32cio.c
+++ b/src/conio/win32cio.c
@@ -1,5 +1,3 @@
-/* $Id: win32cio.c,v 1.115 2020/06/27 00:04:45 deuce Exp $ */
-
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
@@ -13,21 +11,9 @@
  * 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 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.	*
  ****************************************************************************/
 
@@ -720,8 +706,9 @@ int win32_gettext(int left, int top, int right, int bottom, void* buf)
 	reg.Top=top-1;
 	reg.Bottom=bottom-1;
 	ci=(CHAR_INFO *)alloca(sizeof(CHAR_INFO)*(bs.X*bs.Y));
-	if((h=GetStdHandle(STD_OUTPUT_HANDLE)) != INVALID_HANDLE_VALUE)
-		ReadConsoleOutput(h,ci,bs,bc,&reg);
+	if((h=GetStdHandle(STD_OUTPUT_HANDLE)) == INVALID_HANDLE_VALUE)
+		return 0; // failure
+	ReadConsoleOutput(h,ci,bs,bc,&reg);
 	for(y=0;y<=(bottom-top);y++) {
 		for(x=0;x<=(right-left);x++) {
 			bu[((y*bs.X)+x)*2]=ci[(y*bs.X)+x].Char.AsciiChar;
diff --git a/src/encode/base64.c b/src/encode/base64.c
index 00a9645c37a4e06fbaa441b8e3a5c508045f2208..80090aa5f9b4ea064a238a4e414357bf070ef477 100644
--- a/src/encode/base64.c
+++ b/src/encode/base64.c
@@ -1,37 +1,21 @@
-/* base64.c */
-
 /* Base64 encoding/decoding routines */
 
-/* $Id: base64.c,v 1.29 2018/03/09 08:56:28 deuce Exp $ */
-
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
  *																			*
  * Copyright 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				*
+ * 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 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		*
+ * See the GNU Lesser General Public License for more details: lgpl.txt or	*
+ * http://www.fsf.org/copyleft/lesser.html									*
  *																			*
  * 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.	*
  ****************************************************************************/
 
@@ -109,8 +93,6 @@ int b64_encode(char *target, size_t tlen, const char *source, size_t slen)  {
 	char	enc;
 	int		buf;
 	
-	if(slen==0)
-		slen=strlen(source);
 	inp=source;
 	if(source==target)  {
 		tmpbuf=(char *)malloc(tlen);
diff --git a/src/sbbs3/addfiles.c b/src/sbbs3/addfiles.c
index 2e6f304b622d3c007f4ca303df2d17289adeb343..a79d406def0039ac8049244f29d9f8d3397b3e9b 100644
--- a/src/sbbs3/addfiles.c
+++ b/src/sbbs3/addfiles.c
@@ -660,6 +660,7 @@ void synclist(char *inpath, int dirnum)
 		printf("\nDeleting %s\n",listpath);
 		remove(listpath);
 	}
+	fclose(stream);
 }
 
 char *usage="\nusage: addfiles code [.alt_path] [-opts] +list "
diff --git a/src/sbbs3/ansiterm.cpp b/src/sbbs3/ansiterm.cpp
index d130acb177e9198cf99a35fc23ff5bfea2ea4f56..348f3c84b14b02f6f56221d89def2fd9bed32275 100644
--- a/src/sbbs3/ansiterm.cpp
+++ b/src/sbbs3/ansiterm.cpp
@@ -1,9 +1,5 @@
-/* ansiterm.cpp */
-
 /* Synchronet ANSI terminal functions */
 
-/* $Id: ansiterm.cpp,v 1.27 2020/05/24 08:26:09 rswindell Exp $ */
-
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
@@ -17,21 +13,9 @@
  * 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.	*
  ****************************************************************************/
 
@@ -264,7 +248,7 @@ bool sbbs_t::ansi_getxy(int* x, int* y)
             else if(ch=='R' && rsp)
             	break;
 			else {
-				str[rsp + 1] = 0;
+				str[rsp] = 0;
 #ifdef _DEBUG
 				char dbg[128];
 				c_escape_str(str, dbg, sizeof(dbg), /* Ctrl-only? */true);
diff --git a/src/sbbs3/atcodes.cpp b/src/sbbs3/atcodes.cpp
index f4384eaea74f410c31c4a93c25781a4af9b336f1..28f8c44829d1ee56e9b96d219dc26ced494873e4 100644
--- a/src/sbbs3/atcodes.cpp
+++ b/src/sbbs3/atcodes.cpp
@@ -181,8 +181,8 @@ int sbbs_t::show_atcode(const char *instr, JSObject* obj)
 	if(thousep)
 		cp = separate_thousands(cp, separated, sizeof(separated), ',');
 
+	char upper[128];
 	if(uppercase) {
-		char upper[128];
 		SAFECOPY(upper, cp);
 		strupr(upper);
 		cp = upper;
@@ -1726,10 +1726,10 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen, long* pmode, bool
 			return(current_msg_from);
 		return(str);
 	}
-	if(!strcmp(sp,"MSG_FROM_NAME") && current_msg_from!=NULL) {
+	if(!strcmp(sp,"MSG_FROM_NAME") && current_msg != NULL && current_msg_from != NULL) {
 		if(current_msg->hdr.attr&MSG_ANONYMOUS && !SYSOP)
 			return(text[Anonymous]);
-		if(pmode != NULL && current_msg != NULL)
+		if(pmode != NULL)
 			*pmode |= (current_msg->hdr.auxattr & MSG_HFIELDS_UTF8);
 		return(current_msg_from);
 	}
diff --git a/src/sbbs3/con_out.cpp b/src/sbbs3/con_out.cpp
index b0e05b9f9988bee062f7870666ca33387c2c5c6d..804924a46245e471a32391efb6b6e003cb0a8692 100644
--- a/src/sbbs3/con_out.cpp
+++ b/src/sbbs3/con_out.cpp
@@ -1,7 +1,4 @@
 /* Synchronet console output routines */
-// vi: tabstop=4
-
-/* $Id: con_out.cpp,v 1.142 2020/08/04 04:26:03 rswindell Exp $ */
 
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
@@ -16,21 +13,9 @@
  * 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.	*
  ****************************************************************************/
 
@@ -1113,7 +1098,7 @@ void sbbs_t::ctrl_a(char x)
 	}
 	switch(toupper(x)) {
 		case '+':	/* push current attribute */
-			if(attr_sp<(int)sizeof(attr_stack))
+			if(attr_sp<(int)(sizeof(attr_stack) / sizeof(attr_stack[0])))
 				attr_stack[attr_sp++]=curatr;
 			break;
 		case '-':	/* pop current attribute OR optimized "normal" */
diff --git a/src/sbbs3/delfiles.c b/src/sbbs3/delfiles.c
index 60e47ead8ab5be9bfda79428e30365bd5186cdf4..a017ff8b2bfbccefccab6493aacf8b75bf3e4f4f 100644
--- a/src/sbbs3/delfiles.c
+++ b/src/sbbs3/delfiles.c
@@ -114,7 +114,7 @@ int main(int argc, char **argv)
 	backslash(cfg.ctrl_dir);
 
 	load_cfg(&cfg, /* text: */NULL, /* prep: */TRUE, /* node: */FALSE, str, sizeof(str));
-	chdir(cfg.ctrl_dir);
+	(void)chdir(cfg.ctrl_dir);
 
 	dirnum=libnum=-1;
 	if(argv[1][0]=='*')
diff --git a/src/sbbs3/dupefind.c b/src/sbbs3/dupefind.c
index 2b66764bf449a49b529473c296af7aff1bae28c1..b2ec2b19909c224dd7715626813c735defc53499 100644
--- a/src/sbbs3/dupefind.c
+++ b/src/sbbs3/dupefind.c
@@ -115,8 +115,7 @@ int main(int argc,char **argv)
 		fprintf(stderr,"!ERROR loading configuration files: %s\n",str);
 		return(1);
 	}
-
-	chdir(cfg.ctrl_dir);
+	(void)chdir(cfg.ctrl_dir);
 
 	lputs("\n");
 
diff --git a/src/sbbs3/email.cpp b/src/sbbs3/email.cpp
index 164468676d8ccceea110d89da3b52cb46f8a4db8..6efc906d7ae10bdc5f53cbb8525adfc7367e1c89 100644
--- a/src/sbbs3/email.cpp
+++ b/src/sbbs3/email.cpp
@@ -1,9 +1,5 @@
-/* email.cpp */
-
 /* Synchronet email function - for sending private e-mail */
 
-/* $Id: email.cpp,v 1.79 2020/04/15 02:27:10 rswindell Exp $ */
-
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
@@ -17,21 +13,9 @@
  * 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.	*
  ****************************************************************************/
 
@@ -85,6 +69,7 @@ bool sbbs_t::email(int usernumber, const char *top, const char *subj, long mode,
 		bputs(text[UnknownUser]);
 		return(false); 
 	}
+	str[0] = '\0';
 	getuserrec(&cfg,usernumber,U_MISC,8,str);
 	l=ahtoul(str);
 	if(l&(DELETED|INACTIVE)) {              /* Deleted or Inactive User */
@@ -92,8 +77,9 @@ bool sbbs_t::email(int usernumber, const char *top, const char *subj, long mode,
 		return(false); 
 	}
 	if((l&NETMAIL) && (cfg.sys_misc&SM_FWDTONET) && !(mode & WM_NOFWD) && !(useron.rest&FLAG('M'))) {
-		getuserrec(&cfg,usernumber,U_NETMAIL,LEN_NETMAIL,str);
-		if(is_supported_netmail_addr(&cfg, str)) {
+		str[0] = '\0'
+		if(getuserrec(&cfg,usernumber,U_NETMAIL,LEN_NETMAIL,str) == 0
+			&& is_supported_netmail_addr(&cfg, str)) {
 			bprintf(text[UserNetMail],str);
 			if((mode & WM_FORCEFWD) || yesno(text[ForwardMailQ])) /* Forward to netmail address */
 				return(netmail(str, subj, mode, resmb, remsg));
@@ -109,7 +95,7 @@ bool sbbs_t::email(int usernumber, const char *top, const char *subj, long mode,
 	action=NODE_SMAL;
 	nodesync();
 
-	sprintf(str,"%sfeedback.*", cfg.exec_dir);
+	SAFEPRINTF(str,"%sfeedback.*", cfg.exec_dir);
 	if(usernumber==cfg.node_valuser && useron.fbacks && fexist(str)) {
 		exec_bin("feedback",&main_csi);
 		if(main_csi.logic!=LOGIC_TRUE)
@@ -145,15 +131,15 @@ bool sbbs_t::email(int usernumber, const char *top, const char *subj, long mode,
 	if(mode&WM_FILE) {
 		if(!checkfname(title)) {
 			bputs(text[BadFilename]);
-			remove(msgpath);
+			(void)remove(msgpath);
 			return(false);
 		}
-		sprintf(str2,"%sfile/%04u.in", cfg.data_dir,usernumber);
-		MKDIR(str2);
-		sprintf(str2,"%sfile/%04u.in/%s", cfg.data_dir,usernumber,title);
+		SAFEPRINTF2(str2,"%sfile/%04u.in", cfg.data_dir,usernumber);
+		(void)MKDIR(str2);
+		SAFEPRINTF3(str2,"%sfile/%04u.in/%s", cfg.data_dir,usernumber,title);
 		if(fexistcase(str2)) {
 			bputs(text[FileAlreadyThere]);
-			remove(msgpath);
+			(void)remove(msgpath);
 			return(false); 
 		}
 		xfer_prot_menu(XFER_UPLOAD);
@@ -167,7 +153,7 @@ bool sbbs_t::email(int usernumber, const char *top, const char *subj, long mode,
 		ch=(char)getkeys(str,0);
 		if(ch==text[YNQP][2] || sys_status&SS_ABORT) {
 			bputs(text[Aborted]);
-			remove(msgpath);
+			(void)remove(msgpath);
 			return(false); 
 		}
 		for(x=0;x<cfg.total_prots;x++)
@@ -184,7 +170,7 @@ bool sbbs_t::email(int usernumber, const char *top, const char *subj, long mode,
 			bprintf(text[FileNBytesReceived],title,ultoac(l,tmp));
 		else {
 			bprintf(text[FileNotReceived],title);
-			remove(msgpath);
+			(void)remove(msgpath);
 			return(false); 
 		} 
 	}
@@ -290,13 +276,13 @@ bool sbbs_t::email(int usernumber, const char *top, const char *subj, long mode,
 	username(&cfg,usernumber,str);
 	smb_hfield_str(&msg,RECIPIENT,str);
 
-	sprintf(str,"%u",usernumber);
+	SAFEPRINTF(str,"%u",usernumber);
 	smb_hfield_str(&msg,RECIPIENTEXT,str);
 
 	SAFECOPY(str,useron.alias);
 	smb_hfield_str(&msg,SENDER,str);
 
-	sprintf(str,"%u",useron.number);
+	SAFEPRINTF(str,"%u",useron.number);
 	smb_hfield_str(&msg,SENDEREXT,str);
 
 	if(useron.misc&NETMAIL) {
diff --git a/src/sbbs3/execmisc.cpp b/src/sbbs3/execmisc.cpp
index f0701e0b38cb4cd5ee46f42731aeb1860651cfc5..97ce59e1d5a09bc6602c5363a0a410d5ac9c88ec 100644
--- a/src/sbbs3/execmisc.cpp
+++ b/src/sbbs3/execmisc.cpp
@@ -1,9 +1,5 @@
-/* execmisc.cpp */
-
 /* Synchronet miscellaneous command shell/module routines */
 
-/* $Id: execmisc.cpp,v 1.58 2020/04/11 04:01:35 rswindell Exp $ */
-
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
@@ -17,21 +13,9 @@
  * 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.	*
  ****************************************************************************/
 
@@ -437,7 +421,7 @@ int sbbs_t::exec_misc(csi_t* csi, char *path)
 
 					if(pp1) {	/* ASCII */
 						if(!pp2) {
-							if(!strnicmp(*pp2,"0x",2)) {
+							if(!strnicmp(*pp1,"0x",2)) {
 								l=strtol((*pp1)+2,0,16);
 								ultoa(*lp2,tmp,16); 
 							}
diff --git a/src/sbbs3/fmsgdump.c b/src/sbbs3/fmsgdump.c
index b1d2a935659c8af35ffc2f9bcc8b427bd4f47a89..b42cf75b54494c98222934f9a7fd774495de45bb 100644
--- a/src/sbbs3/fmsgdump.c
+++ b/src/sbbs3/fmsgdump.c
@@ -91,8 +91,10 @@ int msgdump(FILE* fp, const char* fname)
 	printf("Attr: 0x%04hX %s\n", hdr.attr, fmsgattr_str(hdr.attr));
 	printf("To  : %.*s (%u:%u/%u.%u)\n", (int)sizeof(hdr.to)-1, hdr.to
 		,hdr.destzone, hdr.destnet, hdr.destnode, hdr.destpoint);
+	TERMINATE(hdr.from);
 	printf("From: %.*s (%u:%u/%u.%u)\n", (int)sizeof(hdr.from)-1, hdr.from
 		,hdr.origzone, hdr.orignet, hdr.orignode, hdr.origpoint);
+	TERMINATE(hdr.time);
 	printf("Time: %.*s\n", (int)sizeof(hdr.time)-1, hdr.time);
 
 	if(end <= sizeof(hdr)+1) {
diff --git a/src/sbbs3/getmsg.cpp b/src/sbbs3/getmsg.cpp
index 2028eaa8f6182a36cdec89853459e331d46c8a8c..ed04a09958e96e3df015fa372e9cf15cc2919db9 100644
--- a/src/sbbs3/getmsg.cpp
+++ b/src/sbbs3/getmsg.cpp
@@ -154,7 +154,7 @@ const char* sbbs_t::msghdr_field(const smbmsg_t* msg, const char* str, char* buf
 	if(buf == NULL)
 		buf = msgghdr_field_cp437_str;
 
-	strncpy(buf, str, sizeof(msgghdr_field_cp437_str));
+	strncpy(buf, str, sizeof(msgghdr_field_cp437_str) - 1);
 	utf8_to_cp437_str(buf);
 
 	return buf;
@@ -363,7 +363,7 @@ void sbbs_t::download_msg_attachments(smb_t* smb, smbmsg_t* msg, bool del)
 	char* txt;
 	int attachment_index = 0;
 	bool found = true;
-	while((txt=smb_getmsgtxt(smb, msg, 0)) != NULL && found) {
+	while(found && (txt=smb_getmsgtxt(smb, msg, 0)) != NULL) {
 		char filename[MAX_PATH+1] = {0};
 		uint32_t filelen = 0;
 		uint8_t* filedata;
@@ -428,7 +428,7 @@ void sbbs_t::download_msg_attachments(smb_t* smb, smbmsg_t* msg, bool del)
 							if(cfg.prot[i]->dlcmd[0]
 								&& chk_ar(cfg.prot[i]->ar,&useron,&client)) {
 								sprintf(tmp,"%c",cfg.prot[i]->mnemonic);
-								strcat(str,tmp);
+								SAFECAT(str,tmp);
 							}
 						ch=(char)getkeys(str,0);
 						for(i=0;i<cfg.total_prots;i++)
diff --git a/src/sbbs3/getstr.cpp b/src/sbbs3/getstr.cpp
index 92308498de39dea168df3553ccf20afb2142d456..e2ebd271a7e99e57b4cd5977b6187985592fc8bc 100644
--- a/src/sbbs3/getstr.cpp
+++ b/src/sbbs3/getstr.cpp
@@ -1,7 +1,4 @@
 /* Synchronet string input routines */
-// vi: tabstop=4
-
-/* $Id: getstr.cpp,v 1.40 2020/05/08 08:25:49 rswindell Exp $ */
 
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
@@ -16,21 +13,9 @@
  * 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.	*
  ****************************************************************************/
 
@@ -77,7 +62,7 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode, const str_list_t h
 	}
 	else str1[0]=0;
 	if(mode&K_EDIT)
-		strcat(str1,strout);
+		SAFECAT(str1,strout);
 	else
 		strout[0]=0;
 	if(strlen(str1)>maxlen)
@@ -338,7 +323,7 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode, const str_list_t h
 				for(x=0;x<(maxlen-l)/2;x++)
 					str2[x]=' ';
 				str2[x]=0;
-				strcat(str2,str1);
+				SAFECAT(str2,str1);
 				strcpy(strout,str2);
 				l=strlen(strout);
 				if(mode&K_NOECHO)
diff --git a/src/sbbs3/js_bbs.cpp b/src/sbbs3/js_bbs.cpp
index 9fa989eac100d545254fd88068aab476b495bd20..f1a4241889c28c14865f21fec981d84ec726787e 100644
--- a/src/sbbs3/js_bbs.cpp
+++ b/src/sbbs3/js_bbs.cpp
@@ -1454,18 +1454,15 @@ js_text(JSContext *cx, uintN argc, jsval *arglist)
 	if((sbbs=js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist)))==NULL)
 		return(JS_FALSE);
 
-	JS_SET_RVAL(cx, arglist, JSVAL_VOID);
+	JS_SET_RVAL(cx, arglist, JSVAL_NULL);
 
 	if(argc && JSVAL_IS_NUMBER(argv[0])) {
 		if(!JS_ValueToECMAUint32(cx,argv[0],&i))
 			return JS_FALSE;
 	}
-	i--;
 
-	if(i<0 || i>=TOTAL_TEXT)
-		JS_SET_RVAL(cx, arglist, JSVAL_NULL);
-	else {
-		JSString* js_str = JS_NewStringCopyZ(cx, sbbs->text[i]);
+	if(i > 0 && i <= TOTAL_TEXT) {
+		JSString* js_str = JS_NewStringCopyZ(cx, sbbs->text[i - 1]);
 		if(js_str==NULL)
 			return(JS_FALSE);
 		JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
@@ -1495,10 +1492,9 @@ js_replace_text(JSContext *cx, uintN argc, jsval *arglist)
 		if(!JS_ValueToECMAUint32(cx,argv[0],&i))
 			return JS_FALSE;
 	}
-	i--;
-
-	if(i<0 || i>=TOTAL_TEXT)
+	if(i < 1 || i > TOTAL_TEXT)
 		return(JS_TRUE);
+	i--;
 
 	if(sbbs->text[i]!=sbbs->text_sav[i] && sbbs->text[i]!=nulstr)
 		free(sbbs->text[i]);
@@ -2192,12 +2188,15 @@ js_sendfile(JSContext *cx, uintN argc, jsval *arglist)
 	}
 
 	JSVALUE_TO_MSTRING(cx, argv[0], cstr, NULL);
-	if(cstr==NULL)
+	if(cstr==NULL) {
+		free(cstr);
+		free(desc);
 		return JS_FALSE;
+	}
 	rc=JS_SUSPENDREQUEST(cx);
 	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->sendfile(cstr, prot, desc, autohang)));
 	free(cstr);
-	FREE_AND_NULL(desc);
+	free(desc);
 	JS_RESUMEREQUEST(cx, rc);
 
 	return(JS_TRUE);
@@ -3550,8 +3549,11 @@ js_listfileinfo(JSContext *cx, uintN argc, jsval *arglist)
 
 	for(uintN i=1;i<argc;i++) {
 		if(JSVAL_IS_NUMBER(argv[i])) {
-			if(!JS_ValueToECMAUint32(cx,argv[i],&mode))
+			if(!JS_ValueToECMAUint32(cx,argv[i],&mode)) {
+				if(fspec != def)
+					free(fspec);
 				return JS_FALSE;
+			}
 		}
 		else if(JSVAL_IS_STRING(argv[i])) {
 			js_str = JS_ValueToString(cx, argv[i]);
@@ -3644,10 +3646,17 @@ js_forward_msg(JSContext *cx, uintN argc, jsval *arglist)
 
 	for(n=0; n<argc; n++) {
 		if(JSVAL_IS_OBJECT(argv[n]) && !JSVAL_IS_NULL(argv[n])) {
-			if((hdrobj=JSVAL_TO_OBJECT(argv[n]))==NULL)
+			if((hdrobj=JSVAL_TO_OBJECT(argv[n]))==NULL) {
+				free(to);
+				free(subject);
+				free(comment);
 				return JS_FALSE;
+			}
 			if(!js_GetMsgHeaderObjectPrivates(cx, hdrobj, &smb, &msg, /* post_t */NULL)) {
 				JS_ReportError(cx, "msg hdr object lacks privates");
+				free(to);
+				free(subject);
+				free(comment);
 				return JS_FALSE;
 			}
 		} else if(JSVAL_IS_STRING(argv[n])) {
@@ -3666,9 +3675,9 @@ js_forward_msg(JSContext *cx, uintN argc, jsval *arglist)
 		JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->forwardmsg(smb, msg, to, subject, comment)));
 		JS_RESUMEREQUEST(cx, rc);
 	}
-	FREE_AND_NULL(subject);
-	FREE_AND_NULL(comment);
-	FREE_AND_NULL(to);
+	free(subject);
+	free(comment);
+	free(to);
 
 	return JS_TRUE;
 }
diff --git a/src/sbbs3/js_console.cpp b/src/sbbs3/js_console.cpp
index c754d269dffd183c00b615dba1681a347c9002b5..500d177f885d24a2ef205b7482eaf7999cacce14 100644
--- a/src/sbbs3/js_console.cpp
+++ b/src/sbbs3/js_console.cpp
@@ -810,8 +810,10 @@ js_getkeys(JSContext *cx, uintN argc, jsval *arglist)
 
 	for(i=0;i<argc;i++) {
 		if(JSVAL_IS_NUMBER(argv[i])) {
-			if(!JS_ValueToInt32(cx, argv[i], &val))
+			if(!JS_ValueToInt32(cx, argv[i], &val)) {
+				free(cstr);
 				return JS_FALSE;
+			}
 			if(!maxnum_specified) {
 				maxnum_specified = true;
 				maxnum = val;
@@ -821,6 +823,7 @@ js_getkeys(JSContext *cx, uintN argc, jsval *arglist)
 		}
 		if(JSVAL_IS_STRING(argv[i])) {
 			js_str = JS_ValueToString(cx, argv[i]);
+			free(cstr);
 			JSSTRING_TO_MSTRING(cx, js_str, cstr, NULL);
 			if(cstr==NULL)
 				return JS_FALSE;
@@ -829,7 +832,7 @@ js_getkeys(JSContext *cx, uintN argc, jsval *arglist)
 
 	rc=JS_SUSPENDREQUEST(cx);
 	val=sbbs->getkeys(cstr, maxnum, mode);
-	FREE_AND_NULL(cstr);
+	free(cstr);
 	JS_RESUMEREQUEST(cx, rc);
 
 	if(val==-1) {			// abort
@@ -955,8 +958,10 @@ js_yesno(JSContext *cx, uintN argc, jsval *arglist)
 	if(cstr==NULL)
 		return JS_FALSE;
 	if(argc > 1 && JSVAL_IS_NUMBER(argv[1])) {
-		if(!JS_ValueToInt32(cx, argv[1], &mode))
+		if(!JS_ValueToInt32(cx, argv[1], &mode)) {
+			free(cstr);
 			return JS_FALSE;
+		}
 	}
 	rc=JS_SUSPENDREQUEST(cx);
 	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->yesno(cstr, mode)));
@@ -987,8 +992,10 @@ js_noyes(JSContext *cx, uintN argc, jsval *arglist)
 	if(cstr==NULL)
 		return JS_FALSE;
 	if(argc > 1 && JSVAL_IS_NUMBER(argv[1])) {
-		if(!JS_ValueToInt32(cx, argv[1], &mode))
+		if(!JS_ValueToInt32(cx, argv[1], &mode)) {
+			free(cstr);
 			return JS_FALSE;
+		}
 	}
 	rc=JS_SUSPENDREQUEST(cx);
 	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->noyes(cstr, mode)));
@@ -1218,8 +1225,10 @@ js_print(JSContext *cx, uintN argc, jsval *arglist)
 		JSVALUE_TO_RASTRING(cx, argv[0], cstr, &cstr_sz, NULL);
 		if(cstr==NULL)
 		    return(JS_FALSE);
-		if(!JS_ValueToInt32(cx, argv[1], &pmode))
+		if(!JS_ValueToInt32(cx, argv[1], &pmode)) {
+			free(cstr);
 			return JS_FALSE;
+		}
 		rc=JS_SUSPENDREQUEST(cx);
 		sbbs->bputs(cstr, pmode);
 		JS_RESUMEREQUEST(cx, rc);
@@ -1233,8 +1242,7 @@ js_print(JSContext *cx, uintN argc, jsval *arglist)
 		sbbs->bputs(cstr);
 		JS_RESUMEREQUEST(cx, rc);
 	}
-	if(cstr)
-		free(cstr);
+	free(cstr);
 
     return(JS_TRUE);
 }
@@ -1258,7 +1266,7 @@ js_strlen(JSContext *cx, uintN argc, jsval *arglist)
 		return(JS_FALSE);
 
 	if(argc > 1)
-		JS_ValueToInt32(cx, argv[1], &pmode);
+		(void)JS_ValueToInt32(cx, argv[1], &pmode);
 
 	JSSTRING_TO_MSTRING(cx, str, cstr, NULL);
 	if(cstr==NULL)
diff --git a/src/sbbs3/js_cryptcert.c b/src/sbbs3/js_cryptcert.c
index 37a53eabc864a1fa3e1635191ceed3a8c562f05e..79f9d1f1c7fc42b16f84550f2693b68ec8c28f6c 100644
--- a/src/sbbs3/js_cryptcert.c
+++ b/src/sbbs3/js_cryptcert.c
@@ -1570,16 +1570,17 @@ js_cryptcert_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 		tiny = JSVAL_TO_INT(idval);
 	else {
 		size_t i;
-		char *name;
+		char *name = NULL;
 
 		JSVALUE_TO_MSTRING(cx, idval, name, NULL);
 		HANDLE_PENDING(cx, name);
-		for (i = 0; js_cryptcert_properties[i].name; i++) {
+		for (i = 0; name != NULL && js_cryptcert_properties[i].name; i++) {
 			if (strcmp(name, js_cryptcert_properties[i].name) == 0) {
 				tiny = js_cryptcert_properties[i].tinyid;
 				break;
 			}
 		}
+		free(name);
 		if (!js_cryptcert_properties[i].name)
 			return JS_TRUE;
 	}
@@ -2348,16 +2349,17 @@ js_cryptcert_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp
 		tiny = JSVAL_TO_INT(idval);
 	else {
 		size_t i;
-		char *name;
+		char *name = NULL;
 
 		JSVALUE_TO_MSTRING(cx, idval, name, NULL);
 		HANDLE_PENDING(cx, name);
-		for (i = 0; js_cryptcert_properties[i].name; i++) {
+		for (i = 0; name != NULL && js_cryptcert_properties[i].name; i++) {
 			if (strcmp(name, js_cryptcert_properties[i].name) == 0) {
 				tiny = js_cryptcert_properties[i].tinyid;
 				break;
 			}
 		}
+		free(name);
 		if (!js_cryptcert_properties[i].name)
 			return JS_TRUE;
 	}
diff --git a/src/sbbs3/js_cryptcon.c b/src/sbbs3/js_cryptcon.c
index 1a8030438e99962ac930e6b56193d46698980feb..c4111d2627213c4a5558a97c2847252cefa07284 100644
--- a/src/sbbs3/js_cryptcon.c
+++ b/src/sbbs3/js_cryptcon.c
@@ -131,6 +131,7 @@ static int js_ecc_to_prop(unsigned char *data, size_t len, size_t *off, JSContex
 			memcpy(y, z, zcnt);
 			y64 = malloc(zcnt*4/3+3);
 			if (y64 == NULL) {
+				free(x);
 				free(y);
 				return 0;
 			}
diff --git a/src/sbbs3/js_file.c b/src/sbbs3/js_file.c
index 53739e69369b4b59dd742e738d1be7ebb28e9b63..a72bef1c88a8e2c61e022b2bfba13fa49ea6dec4 100644
--- a/src/sbbs3/js_file.c
+++ b/src/sbbs3/js_file.c
@@ -1305,7 +1305,7 @@ js_iniSetObject(JSContext *cx, uintN argc, jsval *arglist)
 			JS_DestroyIdArray(cx,id_array);
 			return JS_FALSE;
 		}
-		JS_GetProperty(cx,object,cp,&set_argv[2]);
+		(void)JS_GetProperty(cx,object,cp,&set_argv[2]);
 		FREE_AND_NULL(cp);
 		if(!js_iniSetValue_internal(cx,obj,3,set_argv,&list)) {
 			rval = JSVAL_FALSE;
@@ -1469,15 +1469,17 @@ js_iniSetAllObjects(JSContext *cx, uintN argc, jsval *arglist)
     if(!JS_GetArrayLength(cx, array, &count))
 		return(JS_TRUE);
 
-	if(argc>1)
+	if(argc>1) {
 		JSVALUE_TO_MSTRING(cx, argv[1], name, NULL);
-	HANDLE_PENDING(cx, name);
-	if(name==NULL) {
-		JS_ReportError(cx, "Invalid NULL name property");
-		return JS_FALSE;
+		HANDLE_PENDING(cx, name);
+		if(name==NULL) {
+			JS_ReportError(cx, "Invalid NULL name property");
+			return JS_FALSE;
+		}
 	}
-
 	if((p=(private_t*)js_GetClassPrivate(cx, obj, &js_file_class))==NULL) {
+		if(name != name_def)
+			free(name);
 		return(JS_FALSE);
 	}
 
@@ -2331,7 +2333,7 @@ static JSBool js_file_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict,
 			if(!JS_ValueToInt32(cx,*vp,&i))
 				return(JS_FALSE);
 			rc=JS_SUSPENDREQUEST(cx);
-			CHMOD(p->name,i);
+			(void)CHMOD(p->name,i);
 			JS_RESUMEREQUEST(cx, rc);
 			break;
 		case FILE_PROP_ETX:
diff --git a/src/sbbs3/js_global.c b/src/sbbs3/js_global.c
index 5683f10f234f77c00badb8926a2f25be772fa8e7..60f2536910beb323f38cafe9a53e06a50d4626fb 100644
--- a/src/sbbs3/js_global.c
+++ b/src/sbbs3/js_global.c
@@ -464,10 +464,10 @@ js_load(JSContext *cx, uintN argc, jsval *arglist)
 			JS_RESUMEREQUEST(bg->cx, brc);
 		}
 		else {
-			JS_GetProperty(exec_cx, exec_obj, "argv", &old_js_argv);
-			JS_AddValueRoot(exec_cx, &old_js_argv);
-			JS_GetProperty(exec_cx, exec_obj, "argc", &old_js_argc);
-			JS_AddValueRoot(exec_cx, &old_js_argc);
+			if(JS_GetProperty(exec_cx, exec_obj, "argv", &old_js_argv))
+				JS_AddValueRoot(exec_cx, &old_js_argv);
+			if(JS_GetProperty(exec_cx, exec_obj, "argc", &old_js_argc))
+				JS_AddValueRoot(exec_cx, &old_js_argc);
 			restore_args = TRUE;
 		}
 
@@ -1685,71 +1685,61 @@ js_html_encode(JSContext *cx, uintN argc, jsval *arglist)
 
 	if(argc>5 && JSVAL_IS_OBJECT(argv[5])) {
 		stateobj=JSVAL_TO_OBJECT(argv[5]);
-		JS_GetProperty(cx,stateobj,"fg",&val);
-		if(JSVAL_IS_NUMBER(val)) {
+		if(JS_GetProperty(cx,stateobj,"fg",&val) && JSVAL_IS_NUMBER(val)) {
 			if(!JS_ValueToInt32(cx, val, &fg)) {
 				free(inbuf);
 				return JS_FALSE;
 			}
 		}
-		JS_GetProperty(cx,stateobj,"bg",&val);
-		if(JSVAL_IS_NUMBER(val)) {
+		if(JS_GetProperty(cx,stateobj,"bg",&val) && JSVAL_IS_NUMBER(val)) {
 			if(!JS_ValueToInt32(cx, val, &bg)) {
 				free(inbuf);
 				return JS_FALSE;
 			}
 		}
-		JS_GetProperty(cx,stateobj,"lastcolor",&val);
-		if(JSVAL_IS_NUMBER(val)) {
+		if(JS_GetProperty(cx,stateobj,"lastcolor",&val) && JSVAL_IS_NUMBER(val)) {
 			if(!JS_ValueToInt32(cx, val, &lastcolor)) {
 				free(inbuf);
 				return JS_FALSE;
 			}
 		}
-		JS_GetProperty(cx,stateobj,"blink",&val);
-		if(JSVAL_IS_BOOLEAN(val)) {
+		if(JS_GetProperty(cx,stateobj,"blink",&val) && JSVAL_IS_BOOLEAN(val)) {
 			if(!JS_ValueToBoolean(cx, val, &blink)) {
 				free(inbuf);
 				return JS_FALSE;
 			}
 		}
-		JS_GetProperty(cx,stateobj,"bold",&val);
-		if(JSVAL_IS_BOOLEAN(val)) {
+		if(JS_GetProperty(cx,stateobj,"bold",&val) && JSVAL_IS_BOOLEAN(val)) {
 			if(!JS_ValueToBoolean(cx, val, &bold)) {
 				free(inbuf);
 				return JS_FALSE;
 			}
 		}
-		JS_GetProperty(cx,stateobj,"hpos",&val);
-		if(JSVAL_IS_NUMBER(val)) {
+		if(JS_GetProperty(cx,stateobj,"hpos",&val) && JSVAL_IS_NUMBER(val)) {
 			if(!JS_ValueToInt32(cx, val, &hpos)) {
 				free(inbuf);
 				return JS_FALSE;
 			}
 		}
-		JS_GetProperty(cx,stateobj,"currrow",&val);
-		if(JSVAL_IS_NUMBER(val)) {
+		if(JS_GetProperty(cx,stateobj,"currrow",&val) && JSVAL_IS_NUMBER(val)) {
 			if(!JS_ValueToInt32(cx, val, &currrow)) {
 				free(inbuf);
 				return JS_FALSE;
 			}
 		}
-		JS_GetProperty(cx,stateobj,"wraphpos",&val);
-		if(JSVAL_IS_NUMBER(val)) {
+		if(JS_GetProperty(cx,stateobj,"wraphpos",&val) && JSVAL_IS_NUMBER(val)) {
 			if(!JS_ValueToInt32(cx, val, &wraphpos)) {
 				free(inbuf);
 				return JS_FALSE;
 			}
 		}
-		JS_GetProperty(cx,stateobj,"wrapvpos",&val);
-		if(JSVAL_IS_NUMBER(val)) {
+		if(JS_GetProperty(cx,stateobj,"wrapvpos",&val) && JSVAL_IS_NUMBER(val)) {
 			if(!JS_ValueToInt32(cx, val, &wrapvpos)) {
 				free(inbuf);
 				return JS_FALSE;
 			}
 		}
-		JS_GetProperty(cx,stateobj,"wrappos",&val);
-		if(JSVAL_IS_NUMBER(val)) {
+		if(JS_GetProperty(cx,stateobj,"wrappos",&val) && JSVAL_IS_NUMBER(val)) {
 			if(!JS_ValueToInt32(cx, val, &wrappos)) {
 				free(inbuf);
 				return JS_FALSE;
@@ -4310,8 +4300,10 @@ js_utf8_encode(JSContext *cx, uintN argc, jsval *arglist)
 			return JS_FALSE;
 		}
 		int32 codepoint = 0;
-		if(!JS_ValueToInt32(cx, argv[0], &codepoint))
+		if(!JS_ValueToInt32(cx, argv[0], &codepoint)) {
+			free(outbuf);
 			return JS_FALSE;
+		}
 		int result = utf8_putc(outbuf, len - 1, codepoint);
 		if(result < 1) {
 			free(outbuf);
diff --git a/src/sbbs3/js_msgbase.c b/src/sbbs3/js_msgbase.c
index fdde31ba8cb6dc00ae381c7113bfb9afb1e586cd..67802039352ed7ccc79008ece14310abfd100b4a 100644
--- a/src/sbbs3/js_msgbase.c
+++ b/src/sbbs3/js_msgbase.c
@@ -1584,8 +1584,8 @@ static JSBool js_get_msg_header_resolve(JSContext *cx, JSObject *obj, jsid id)
 			ushort		aliascrc,namecrc,sysop=crc16("sysop",0);
 
 			/* dig a client object out of the global object */
-			JS_GetProperty(cx, JS_GetGlobalObject(cx), "client", &cov);
-			if(JSVAL_IS_OBJECT(cov)) {
+			if(JS_GetProperty(cx, JS_GetGlobalObject(cx), "client", &cov)
+				&& JSVAL_IS_OBJECT(cov)) {
 				JSObject *obj = JSVAL_TO_OBJECT(cov);
 				JSClass	*cl;
 
@@ -1594,8 +1594,8 @@ static JSBool js_get_msg_header_resolve(JSContext *cx, JSObject *obj, jsid id)
 			}
 
 			/* dig a user object out of the global object */
-			JS_GetProperty(cx, JS_GetGlobalObject(cx), "user", &cov);
-			if(JSVAL_IS_OBJECT(cov)) {
+			if(JS_GetProperty(cx, JS_GetGlobalObject(cx), "user", &cov)
+				&& JSVAL_IS_OBJECT(cov)) {
 				JSObject *obj = JSVAL_TO_OBJECT(cov);
 				JSClass	*cl;
 
@@ -2057,6 +2057,7 @@ js_dump_msg_header(JSContext *cx, uintN argc, jsval *arglist)
 			JSObject* array;
 			if((array = JS_NewArrayObject(cx, 0, NULL)) == NULL) {
 				JS_ReportError(cx, "JS_NewArrayObject failure");
+				strListFree(&list);
 				return JS_FALSE;
 			}
 			JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(array));
diff --git a/src/sbbs3/js_socket.c b/src/sbbs3/js_socket.c
index eae72e8d77053b4234506763e609230c85dde233..f8eda7283965ed25f236be2f4c45a9a34b770eac 100644
--- a/src/sbbs3/js_socket.c
+++ b/src/sbbs3/js_socket.c
@@ -1,7 +1,4 @@
 /* Synchronet JavaScript "Socket" Object */
-// vi: tabstop=4
-
-/* $Id: js_socket.c,v 1.247 2020/08/09 02:29:52 rswindell Exp $ */
 
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
@@ -16,21 +13,9 @@
  * 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.	*
  ****************************************************************************/
 
@@ -1193,7 +1178,7 @@ js_recvfrom(JSContext *cx, uintN argc, jsval *arglist)
 			JS_ValueToInt32(cx,argv[n],&len);
 	}
 
-	addrlen=sizeof(addr);
+	addrlen=sizeof(addr.addr);
 
 	if(binary) {	/* Binary/Integer Data */
 
@@ -2872,8 +2857,8 @@ js_listening_socket_constructor(JSContext *cx, uintN argc, jsval *arglist)
 
 	if((p=(js_socket_private_t*)malloc(sizeof(js_socket_private_t)))==NULL) {
 		JS_ReportError(cx,"malloc failed");
-		if(protocol)
-			free(protocol);
+		free(protocol);
+		free(set);
 		return(JS_FALSE);
 	}
 	memset(p,0,sizeof(js_socket_private_t));
diff --git a/src/sbbs3/js_system.c b/src/sbbs3/js_system.c
index 2be8cd4ea69cc5c25f067098127acbb389a84bf8..a41f3f257eb9153f39acf5d9b49d033ea6f68a83 100644
--- a/src/sbbs3/js_system.c
+++ b/src/sbbs3/js_system.c
@@ -1024,6 +1024,7 @@ js_findstr(JSContext *cx, uintN argc, jsval *arglist)
 	}
 	if((js_str=JS_ValueToString(cx, argv[1]))==NULL) {
 		JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(JS_FALSE));
+		free(fname);
 		return(JS_TRUE);
 	}
 	JSSTRING_TO_MSTRING(cx, js_str, str, NULL);
diff --git a/src/sbbs3/js_uifc.c b/src/sbbs3/js_uifc.c
index 1eea6c0288bff25f6843fee8788a0bb1e9e0a9ea..7fd0a832508fa4f268b0ceb2a5da4b390cea9780 100644
--- a/src/sbbs3/js_uifc.c
+++ b/src/sbbs3/js_uifc.c
@@ -860,8 +860,10 @@ js_uifc_list(JSContext *cx, uintN argc, jsval *arglist)
 		}
 		if(!JSVAL_IS_OBJECT(argv[argn]))
 			continue;
-		if((objarg = JSVAL_TO_OBJECT(argv[argn]))==NULL)
+		if((objarg = JSVAL_TO_OBJECT(argv[argn]))==NULL) {
+			free(title);
 			return(JS_FALSE);
+		}
 		if(JS_IsArrayObject(cx, objarg)) {
 			if(!JS_GetArrayLength(cx, objarg, &numopts))
 				return(JS_TRUE);
@@ -1000,8 +1002,10 @@ js_uifc_getstrxy(JSContext *cx, uintN argc, jsval *arglist)
 	if(argn<argc && JSVAL_IS_STRING(argv[argn])) {
 		JSVALUE_TO_MSTRING(cx, argv[argn], org, NULL);
 		argn++;
-		if(JS_IsExceptionPending(cx))
+		if(JS_IsExceptionPending(cx)) {
+			free(org);
 			return JS_FALSE;
+		}
 		if(org==NULL)
 			return(JS_TRUE);
 	}
@@ -1050,7 +1054,7 @@ js_uifc_showbuf(JSContext *cx, uintN argc, jsval *arglist)
 	JSObject *obj=JS_THIS_OBJECT(cx, arglist);
 	jsval *argv=JS_ARGV(cx, arglist);
 	char*		str;
-	char*		title;
+	char*		title = NULL;
 	int32		left=0;
 	int32		top=0;
 	int32		width=0;
@@ -1073,8 +1077,10 @@ js_uifc_showbuf(JSContext *cx, uintN argc, jsval *arglist)
 	if (!JS_ValueToInt32(cx, argv[argn++], &mode))
 		return JS_FALSE;
 	JSVALUE_TO_MSTRING(cx, argv[argn++], title, NULL);
-	if(JS_IsExceptionPending(cx))
+	if(JS_IsExceptionPending(cx)) {
+		free(title);
 		return JS_FALSE;
+	}
 	if(title==NULL)
 		return(JS_TRUE);
 	JSVALUE_TO_MSTRING(cx, argv[argn++], str, NULL);
diff --git a/src/sbbs3/jsexec.c b/src/sbbs3/jsexec.c
index bfc8566b7a3bf0976024429ad8428ba48b3bff7f..ea585973b4cf3bfcedcaf227ed7d1642378011d2 100644
--- a/src/sbbs3/jsexec.c
+++ b/src/sbbs3/jsexec.c
@@ -996,7 +996,7 @@ long js_exec(const char *fname, const char* buf, char** args)
 
 	JS_SetOperationCallback(js_cx, js_OperationCallback);
 
-	if(buf != NULL) {
+	if(fname == NULL && buf != NULL) {
 		SAFECOPY(path, "cmdline");
 		fp = NULL;
 		js_buf = (char*)buf;
@@ -1053,6 +1053,7 @@ long js_exec(const char *fname, const char* buf, char** args)
 		if(buf != NULL) {
 			JSVALUE_TO_MSTRING(js_cx, rval, p, NULL);
 			mfprintf(statfp,"Result (%s): %s", JS_GetTypeName(js_cx, JS_TypeOfValue(js_cx, rval)), p);
+			free(p);
 		}
 		JS_GetProperty(js_cx, js_glob, "exit_code", &rval);
 		if(rval!=JSVAL_VOID && JSVAL_IS_NUMBER(rval)) {
diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c
index fa4066cffd7689ec49d00c1c44aa39021148cc8d..a6acd01b248479aeee70acdc64bab290c2c7c89f 100644
--- a/src/sbbs3/mailsrvr.c
+++ b/src/sbbs3/mailsrvr.c
@@ -2376,9 +2376,8 @@ js_mailproc(SOCKET sock, client_t* client, user_t* user, struct mailproc* mailpr
 		/* ToDo: Set operational callback */
 		success=JS_ExecuteScript(*js_cx, js_scope, js_script, &rval);
 
-		JS_GetProperty(*js_cx, js_scope, "exit_code", &rval);
-
-		if(rval!=JSVAL_VOID && JSVAL_IS_NUMBER(rval))
+		if(JS_GetProperty(*js_cx, js_scope, "exit_code", &rval)
+			&& rval!=JSVAL_VOID && JSVAL_IS_NUMBER(rval))
 			JS_ValueToInt32(*js_cx,rval,result);
 
 		js_EvalOnExit(*js_cx, js_scope, &js_callback);
diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp
index 86e16cd41594888803c1419a0e18e5b1527b77a6..b8d3373aedbba83a91f36e1a3af6014c72753061 100644
--- a/src/sbbs3/main.cpp
+++ b/src/sbbs3/main.cpp
@@ -1134,8 +1134,10 @@ js_prompt(JSContext *cx, uintN argc, jsval *arglist)
 		argn++;
 	}
 	if(argc > argn && JSVAL_IS_NUMBER(argv[argn])) {
-		if(!JS_ValueToInt32(cx,argv[argn], &mode))
+		if(!JS_ValueToInt32(cx,argv[argn], &mode)) {
+			free(prompt);
 			return JS_FALSE;
+		}
 		argn++;
 	}
 
@@ -1778,14 +1780,14 @@ void sbbs_t::send_telnet_cmd(uchar cmd, uchar opt)
             lprintf(LOG_DEBUG,"sending telnet cmd: %s"
                 ,telnet_cmd_desc(cmd));
 		sprintf(buf,"%c%c",TELNET_IAC,cmd);
-		sendsocket(client_socket, buf, 2);
+		(void)sendsocket(client_socket, buf, 2);
 	} else {
 		if(startup->options&BBS_OPT_DEBUG_TELNET)
 			lprintf(LOG_DEBUG,"sending telnet cmd: %s %s"
 				,telnet_cmd_desc(cmd)
 				,telnet_opt_desc(opt));
 		sprintf(buf,"%c%c%c",TELNET_IAC,cmd,opt);
-		sendsocket(client_socket, buf, 3);
+		(void)sendsocket(client_socket, buf, 3);
 	}
 }
 
@@ -2083,7 +2085,7 @@ void input_thread(void *arg)
 		if(sbbs->passthru_socket_active == true) {
 			BOOL writable = FALSE;
 			if(socket_check(sbbs->passthru_socket, NULL, &writable, 1000) && writable)
-				sendsocket(sbbs->passthru_socket, (char*)wrbuf, wr);
+				(void)sendsocket(sbbs->passthru_socket, (char*)wrbuf, wr);
 			else
 				lprintf(LOG_WARNING, "Node %d could not write to passthru socket (writable=%d)"
 					, sbbs->cfg.node_num, (int)writable);
@@ -2496,10 +2498,10 @@ void output_thread(void* arg)
 			}
 			/* Spy on the user remotely */
 			if(spy_socket[sbbs->cfg.node_num-1]!=INVALID_SOCKET)
-				sendsocket(spy_socket[sbbs->cfg.node_num-1],(char*)buf+bufbot,i);
+				(void)sendsocket(spy_socket[sbbs->cfg.node_num-1],(char*)buf+bufbot,i);
 #ifdef __unix__
 			if(uspy_socket[sbbs->cfg.node_num-1]!=INVALID_SOCKET)
-				sendsocket(uspy_socket[sbbs->cfg.node_num-1],(char*)buf+bufbot,i);
+				(void)sendsocket(uspy_socket[sbbs->cfg.node_num-1],(char*)buf+bufbot,i);
 #endif
 		}
 
@@ -2681,7 +2683,7 @@ void event_thread(void* arg)
 					} else {
 						char badpkt[MAX_PATH+1];
 						SAFEPRINTF2(badpkt, "%s.%lx.bad", g.gl_pathv[i], time(NULL));
-						remove(badpkt);
+						(void)remove(badpkt);
 						if(rename(g.gl_pathv[i], badpkt) == 0)
 							sbbs->lprintf(LOG_NOTICE, "%s renamed to %s", g.gl_pathv[i], badpkt);
 						else
@@ -4031,10 +4033,10 @@ void sbbs_t::spymsg(const char* msg)
 	}
 
 	if(cfg.node_num && spy_socket[cfg.node_num-1]!=INVALID_SOCKET)
-		sendsocket(spy_socket[cfg.node_num-1],str,strlen(str));
+		(void)sendsocket(spy_socket[cfg.node_num-1],str,strlen(str));
 #ifdef __unix__
 	if(cfg.node_num && uspy_socket[cfg.node_num-1]!=INVALID_SOCKET)
-		sendsocket(uspy_socket[cfg.node_num-1],str,strlen(str));
+		(void)sendsocket(uspy_socket[cfg.node_num-1],str,strlen(str));
 #endif
 }
 
diff --git a/src/sbbs3/msgtoqwk.cpp b/src/sbbs3/msgtoqwk.cpp
index 4babd17e1797227f1118d44a7b07f91c05fcad6f..c3a6504129eb13d59bb0c62cba7aa14109496817 100644
--- a/src/sbbs3/msgtoqwk.cpp
+++ b/src/sbbs3/msgtoqwk.cpp
@@ -559,7 +559,7 @@ long sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, smb_t* smb
 
 	fseek(qwk_fp,offset,SEEK_SET);
 	fwrite(str,QWK_BLOCK_LEN,1,qwk_fp);
-	fseek(qwk_fp,size,SEEK_CUR);
+	(void)fseek(qwk_fp,size,SEEK_CUR);
 
 	return(size);
 }
diff --git a/src/sbbs3/netmail.cpp b/src/sbbs3/netmail.cpp
index abbdf0e219f35207fac1e87bc772bb5d4aa93a56..79de111408432433f23b6617119d0dd26c43d344 100644
--- a/src/sbbs3/netmail.cpp
+++ b/src/sbbs3/netmail.cpp
@@ -191,7 +191,7 @@ bool sbbs_t::netmail(const char *into, const char *title, long mode, smb_t* resm
 	if(mode&WM_FILE) {
 		SAFECOPY(fname, subj);
 		sprintf(str,"%sfile/%04u.out", cfg.data_dir, useron.number);
-		MKDIR(str);
+		(void)MKDIR(str);
 		SAFECOPY(tmp, cfg.data_dir);
 		if(tmp[0]=='.')    /* Relative path */
 			sprintf(tmp,"%s%s", cfg.node_dir, cfg.data_dir);
@@ -375,7 +375,10 @@ void sbbs_t::qwktonetmail(FILE *rep, char *block, char *into, uchar fromhub)
 		return; 
 	}
 	memcpy((char *)qwkbuf,block,QWK_BLOCK_LEN);
-	fread(qwkbuf+QWK_BLOCK_LEN,n-1,QWK_BLOCK_LEN,rep);
+	if(fread(qwkbuf+QWK_BLOCK_LEN, QWK_BLOCK_LEN, n-1, rep) != n-1) {
+		errormsg(WHERE, ERR_READ, "QWK block", n-1);
+		return;
+	}
 
 	size_t kludge_hdrlen = 0;
 	char* beg = qwkbuf + QWK_BLOCK_LEN;
@@ -874,7 +877,7 @@ void sbbs_t::qwktonetmail(FILE *rep, char *block, char *into, uchar fromhub)
 		l++;
 	}
 	l=0;
-	write(fido,&l,1);	/* Null terminator */
+	write(fido,(BYTE*)&l,sizeof(BYTE));	/* Null terminator */
 	close(fido);
 	free((char *)qwkbuf);
 	if(cfg.netmail_sem[0])		/* update semaphore file */
@@ -1010,7 +1013,7 @@ bool sbbs_t::inetmail(const char *into, const char *subj, long mode, smb_t* resm
 
 	if(mode&WM_FILE) {
 		SAFEPRINTF2(str2,"%sfile/%04u.out",cfg.data_dir,useron.number);
-		MKDIR(str2);
+		(void)MKDIR(str2);
 		SAFEPRINTF3(str2,"%sfile/%04u.out/%s",cfg.data_dir,useron.number,title);
 		if(fexistcase(str2)) {
 			strListFree(&rcpt_list);
diff --git a/src/sbbs3/ntsvcs.c b/src/sbbs3/ntsvcs.c
index 3c9dacef726a9e56f4e67f58d1b3505d64337288..9275ff7a5df969ca3d7f49944cd8abc585bd9288 100644
--- a/src/sbbs3/ntsvcs.c
+++ b/src/sbbs3/ntsvcs.c
@@ -1,7 +1,5 @@
 /* Synchronet BBS as a set of Windows NT Services */
 
-/* $Id: ntsvcs.c,v 1.53 2020/08/17 18:21:08 rswindell Exp $ */
-
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
@@ -15,21 +13,9 @@
  * 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.	*
  ****************************************************************************/
 
@@ -295,7 +281,7 @@ static int svc_lputs(void* p, int level, const char* str)
 	}
 
 	if(svc->log_handle == INVALID_HANDLE_VALUE) {
-		sprintf(fname,"\\\\.\\mailslot\\%s.log",svc->name);
+		SAFEPRINTF(fname,"\\\\.\\mailslot\\%s.log",svc->name);
 		svc->log_handle = CreateFile(
 			fname,					/* pointer to name of the file */
 			GENERIC_WRITE,			/* access (read-write) mode */
@@ -310,7 +296,7 @@ static int svc_lputs(void* p, int level, const char* str)
 		len=sizeof(msg);
 		if(!WriteFile(svc->log_handle,&msg,len,&wr,NULL) || wr!=len) {
 			/* This most likely indicates the server closed the mailslot */
-			sprintf(debug,"!ERROR %d writing %u bytes to %s pipe (wr=%d)"
+			safe_snprintf(debug, sizeof(debug), "!ERROR %d writing %u bytes to %s pipe (wr=%d)"
 				,GetLastError(),len,svc->name,wr);
 			OutputDebugString(debug);
 			/* So close the handle and attempt re-open next time */
@@ -376,7 +362,7 @@ static void read_ini(sbbs_ntsvc_t* svc)
 		services_startup=svc->startup;
 
 	if((fp=fopen(ini_file,"r"))!=NULL) {
-		sprintf(str,"Reading %s",ini_file);
+		SAFEPRINTF(str,"Reading %s",ini_file);
 		svc_lputs(NULL,LOG_INFO,str);
 	}
 
@@ -437,11 +423,11 @@ static void WINAPI svc_main(sbbs_ntsvc_t* svc, DWORD argc, LPTSTR *argv)
 			(*svc->log_level)=strtol(argv[++i],NULL,0);
 	}
 
-	sprintf(str,"Starting NT Service: %s",svc->display_name);
+	SAFEPRINTF(str,"Starting NT Service: %s",svc->display_name);
 	svc_lputs(svc,LOG_INFO,str);
 
     if((svc->status_handle = RegisterServiceCtrlHandler(svc->name, svc->ctrl_handler))==0) {
-		sprintf(str,"!ERROR %d registering service control handler",GetLastError());
+		SAFEPRINTF(str,"!ERROR %d registering service control handler",GetLastError());
 		svc_lputs(NULL,LOG_ERR,str);
 		return;
 	}
@@ -535,7 +521,7 @@ static BOOL register_event_source(char* name, char* path)
 	LONG	retval;
 	char*	value;
 
-	sprintf(keyname,"system\\CurrentControlSet\\services\\eventlog\\application\\%s",name);
+	SAFEPRINTF(keyname,"system\\CurrentControlSet\\services\\eventlog\\application\\%s",name);
 
 	retval=RegCreateKeyEx(
 		HKEY_LOCAL_MACHINE,			/* handle to an open key */
@@ -605,7 +591,7 @@ static const char* start_type_desc(DWORD start_type)
 		case SERVICE_NOT_INSTALLED:			return("Not installed");
 	}
 
-	sprintf(str,"Start_type: %d", start_type);
+	SAFEPRINTF(str,"Start_type: %d", start_type);
 	return(str);
 }
 
@@ -623,7 +609,7 @@ static const char* state_desc(DWORD state)
 		case SERVICE_PAUSED:				return("Paused");
 	}
 
-	sprintf(str,"State: %d", state);
+	SAFEPRINTF(str,"State: %d", state);
 	return(str);
 }
 
@@ -655,7 +641,7 @@ static const char* control_desc(DWORD ctrl)
 		case SERVICE_CONTROL_SYSOP_UNAVAILABLE:	
 			return("Sysop Unavailable");
 	}
-	sprintf(str,"Control: %d", ctrl);
+	SAFEPRINTF(str,"Control: %d", ctrl);
 	return(str);
 }
 
@@ -688,6 +674,7 @@ static DWORD get_service_info(SC_HANDLE hSCManager, char* name, DWORD* state)
 		&size			/* address of variable for bytes needed */
 		) || GetLastError()!=ERROR_INSUFFICIENT_BUFFER) {
 		printf("\n!Unexpected QueryServiceConfig ERROR %u\n",err=GetLastError());
+		CloseServiceHandle(hService);
 		return(-1);
 	}
 
@@ -696,6 +683,7 @@ static DWORD get_service_info(SC_HANDLE hSCManager, char* name, DWORD* state)
 
 	if((service_config=malloc(size))==NULL) {
 		printf("\n!ERROR allocating %u bytes of memory\n", size);
+		CloseServiceHandle(hService);
 		return(-1);
 	}
 
@@ -706,6 +694,7 @@ static DWORD get_service_info(SC_HANDLE hSCManager, char* name, DWORD* state)
 		&size			/* address of variable for bytes needed */
 		)) {
 		printf("\n!QueryServiceConfig ERROR %u\n",GetLastError());
+		CloseServiceHandle(hService);
 		free(service_config);
 		return(-1);
 	}
@@ -719,7 +708,7 @@ static DWORD get_service_info(SC_HANDLE hSCManager, char* name, DWORD* state)
 /****************************************************************************/
 /* Utility function to create a service with description (on Win2K+)		*/
 /****************************************************************************/
-static SC_HANDLE create_service(HANDLE hSCMlib, SC_HANDLE hSCManager
+static void create_service(HANDLE hSCMlib, SC_HANDLE hSCManager
 								,char* name, char* display_name, char* description, char* path
 								,BOOL autostart)
 {
@@ -758,8 +747,6 @@ static SC_HANDLE create_service(HANDLE hSCMlib, SC_HANDLE hSCManager
 		register_event_source(name,path);
 		register_event_source(NTSVC_NAME_EVENT,path);	/* Create SynchronetEvent event source */
 	}
-
-	return(hService);
 }
 
 /****************************************************************************/
@@ -774,8 +761,6 @@ static int install(const char* svc_name)
 
 	printf("Installing Synchronet NT Services...\n");
 
-	hSCMlib = LoadLibrary("ADVAPI32.DLL");
-
     if(GetModuleFileName(NULL,path,sizeof(path))==0)
     {
         fprintf(stderr,"!ERROR %d getting module file name\n",GetLastError());
@@ -792,6 +777,8 @@ static int install(const char* svc_name)
 		return(-1);
 	}
 
+	hSCMlib = LoadLibrary("ADVAPI32.DLL");
+
 	for(i=0;ntsvc_list[i]!=NULL;i++)
 		if(svc_name==NULL	/* All? */
 			|| !stricmp(ntsvc_list[i]->name, svc_name)
@@ -1212,7 +1199,7 @@ int main(int argc, char** argv)
     bbs_startup.terminated=svc_terminated;
 	bbs_startup.clients=svc_clients;
 	bbs_startup.login_attempt_list=&login_attempt_list;
-    strcpy(bbs_startup.ctrl_dir,ctrl_dir);
+    SAFECOPY(bbs_startup.ctrl_dir,ctrl_dir);
 
 	/* Initialize FTP startup structure */
     memset(&ftp_startup,0,sizeof(ftp_startup));
@@ -1224,7 +1211,7 @@ int main(int argc, char** argv)
     ftp_startup.terminated=svc_terminated;
 	ftp_startup.clients=svc_clients;
 	ftp_startup.login_attempt_list=&login_attempt_list;
-    strcpy(ftp_startup.ctrl_dir,ctrl_dir);
+    SAFECOPY(ftp_startup.ctrl_dir,ctrl_dir);
 
 	/* Initialize Web Server startup structure */
     memset(&web_startup,0,sizeof(web_startup));
@@ -1236,7 +1223,7 @@ int main(int argc, char** argv)
     web_startup.terminated=svc_terminated;
 	web_startup.clients=svc_clients;
 	web_startup.login_attempt_list=&login_attempt_list;
-    strcpy(web_startup.ctrl_dir,ctrl_dir);
+    SAFECOPY(web_startup.ctrl_dir,ctrl_dir);
 
 	/* Initialize Mail Server startup structure */
     memset(&mail_startup,0,sizeof(mail_startup));
@@ -1248,7 +1235,7 @@ int main(int argc, char** argv)
     mail_startup.terminated=svc_terminated;
 	mail_startup.clients=svc_clients;
 	mail_startup.login_attempt_list=&login_attempt_list;
-    strcpy(mail_startup.ctrl_dir,ctrl_dir);
+    SAFECOPY(mail_startup.ctrl_dir,ctrl_dir);
 
 	/* Initialize Services startup structure */
     memset(&services_startup,0,sizeof(services_startup));
@@ -1260,11 +1247,11 @@ int main(int argc, char** argv)
     services_startup.terminated=svc_terminated;
 	services_startup.clients=svc_clients;
 	services_startup.login_attempt_list=&login_attempt_list;
-    strcpy(services_startup.ctrl_dir,ctrl_dir);
+    SAFECOPY(services_startup.ctrl_dir,ctrl_dir);
 
 	/* Read .ini file here */
 	if((fp=fopen(ini_file,"r"))!=NULL) {
-		sprintf(str,"Reading %s",ini_file);
+		SAFEPRINTF(str,"Reading %s",ini_file);
 		svc_lputs(NULL,LOG_INFO,str);
 	}
 
@@ -1283,7 +1270,7 @@ int main(int argc, char** argv)
 		fclose(fp);
 
 	if(chdir(ctrl_dir)!=0) {
-		sprintf(str,"!ERROR %d (%s) changing directory to: %s", errno, strerror(errno), ctrl_dir);
+		safe_snprintf(str, sizeof(str), "!ERROR %d (%s) changing directory to: %s", errno, strerror(errno), ctrl_dir);
 		svc_lputs(NULL,LOG_ERR,str);
 	}
 
@@ -1332,7 +1319,7 @@ int main(int argc, char** argv)
 		if(StartServiceCtrlDispatcher(ServiceDispatchTable))
 			return(0);
 
-		sprintf(str,"!ERROR %u starting service control dispatcher",GetLastError());
+		safe_snprintf(str, sizeof(str), "!ERROR %u starting service control dispatcher",GetLastError());
 		printf("%s\n\n",str);
 		OutputDebugString(str); 
 	}
diff --git a/src/sbbs3/pktdump.c b/src/sbbs3/pktdump.c
index 7915cee1002ae2a3f143d00a7f631fef4dc4e7e9..f6bffc7af804b830cb14d6177630b3c8f063a22a 100644
--- a/src/sbbs3/pktdump.c
+++ b/src/sbbs3/pktdump.c
@@ -222,6 +222,7 @@ int pktdump(FILE* fp, const char* fname, FILE* good, FILE* bad)
 			,pkdmsg.orignet, pkdmsg.orignode
 			,pkdmsg.destnet, pkdmsg.destnode);
 		printf("Attribute: 0x%04X (%s)\n",pkdmsg.attr, fmsgattr_str(pkdmsg.attr));
+		TERMINATE(pkdmsg.time);
 		printf("Date/Time: %s\n",pkdmsg.time);
 	
 		/* Display variable-length fields */
diff --git a/src/sbbs3/prntfile.cpp b/src/sbbs3/prntfile.cpp
index d20aaa0d35afa4e21c7aa30e315e5e7355116a12..49e7459d62d1eaa09848b5a914801f6c0f10746a 100644
--- a/src/sbbs3/prntfile.cpp
+++ b/src/sbbs3/prntfile.cpp
@@ -1,10 +1,5 @@
-/* prntfile.cpp */
-// vi: tabstop=4
-
 /* Synchronet file print/display routines */
 
-/* $Id: prntfile.cpp,v 1.47 2020/05/26 03:07:05 rswindell Exp $ */
-
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
@@ -18,21 +13,9 @@
  * 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.	*
  ****************************************************************************/
 
@@ -285,7 +268,8 @@ bool sbbs_t::menu(const char *code, long mode, JSObject* obj)
 			}
 			if(menu_exists(code, next, path))
 				break;
-			menu_exists(code, last, path);
+			if(!menu_exists(code, last, path))
+				return false;
 		} while(0);
 	}
 
diff --git a/src/sbbs3/qwknodes.c b/src/sbbs3/qwknodes.c
index ad81a66c1c11bb90ecaa3cb56f6d51d00afe510e..ca13d0407f356974e05307e462a4c5ea29c55388 100644
--- a/src/sbbs3/qwknodes.c
+++ b/src/sbbs3/qwknodes.c
@@ -289,7 +289,7 @@ int main(int argc, char **argv)
 			fprintf(stderr,"%-5u\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))
+			if(max_age && now-msg.idx.time>((time_t)max_age*24UL*60UL*60UL))
 				continue;
 			if((j=smb_lockmsghdr(&smb,&msg))!=0) {
 				printf("smb_lockmsghdr returned %d\n",j);
diff --git a/src/sbbs3/qwktomsg.cpp b/src/sbbs3/qwktomsg.cpp
index b1b2908bd6550b335ada64759882c779eb629412..437cf3594e0c4a12f5514a574bd8c119ed8b6596 100644
--- a/src/sbbs3/qwktomsg.cpp
+++ b/src/sbbs3/qwktomsg.cpp
@@ -252,7 +252,7 @@ bool sbbs_t::qwk_import_msg(FILE *qwk_fp, char *hdrblk, ulong blocks
 		(hdrblk[0]=='*' || hdrblk[0]=='-' || hdrblk[0]=='`'))
 		msg->hdr.attr|=MSG_READ;
 
-	if(subnum!=INVALID_SUB && !fromhub && cfg.sub[subnum]->mod_ar!=NULL && cfg.sub[subnum]->mod_ar[0]
+	if(subnum!=INVALID_SUB && !fromhub && cfg.sub[subnum]->mod_ar[0]
 		&& chk_ar(cfg.sub[subnum]->mod_ar,&useron,&client))
 		msg->hdr.attr|=MSG_MODERATED;
 	if(subnum!=INVALID_SUB && !fromhub && cfg.sub[subnum]->misc&SUB_SYSPERM
diff --git a/src/sbbs3/sbbs.zip b/src/sbbs3/sbbs.zip
new file mode 100644
index 0000000000000000000000000000000000000000..a1b430583d33673bd6f7b819a26767b04e8623b2
Binary files /dev/null and b/src/sbbs3/sbbs.zip differ
diff --git a/src/sbbs3/sbbs_ini.c b/src/sbbs3/sbbs_ini.c
index 6404d597e59b91c6721a7e8101c828c1d1ea1aad..a416a4536a49434d37ce4528d50e024640bb416b 100644
--- a/src/sbbs3/sbbs_ini.c
+++ b/src/sbbs3/sbbs_ini.c
@@ -70,7 +70,7 @@ void sbbs_get_ini_fname(char* ini_file, char* ctrl_dir, char* pHostName)
 
 #if defined(_WINSOCKAPI_)	 
 	WSADATA WSAData;	 
-    WSAStartup(MAKEWORD(1,1), &WSAData); /* req'd for gethostname */	 
+    (void)WSAStartup(MAKEWORD(1,1), &WSAData); /* req'd for gethostname */	 
 #endif	 
 
 #if defined(__unix__) && defined(PREFIX)
diff --git a/src/sbbs3/sbbscon.c b/src/sbbs3/sbbscon.c
index 76541722779f55f9e52cc268e61129fa03a28037..22f0474c463da00a690b5eba0240350271dbaffd 100644
--- a/src/sbbs3/sbbscon.c
+++ b/src/sbbs3/sbbscon.c
@@ -1431,7 +1431,7 @@ int main(int argc, char** argv)
     bbs_startup.clients=status_term_clients;
 #endif
 	bbs_startup.login_attempt_list=&login_attempt_list;
-    strcpy(bbs_startup.ctrl_dir,ctrl_dir);
+    SAFECOPY(bbs_startup.ctrl_dir,ctrl_dir);
 
 #ifdef __unix__
 
@@ -1454,7 +1454,7 @@ int main(int argc, char** argv)
 	status_startup.setuid=do_setuid;
 	status_startup.clients=status_status_clients;
 	status_startup.status=status_status_status;	// Heh.
-    strcpy(status_startup.ctrl_dir,ctrl_dir);
+    SAFECOPY(status_startup.ctrl_dir,ctrl_dir);
 #endif
 
 	/* Initialize FTP startup structure */
@@ -1477,8 +1477,8 @@ int main(int argc, char** argv)
 	ftp_startup.status=status_ftp_status;
 #endif
 	ftp_startup.login_attempt_list=&login_attempt_list;
-    strcpy(ftp_startup.index_file_name,"00index");
-    strcpy(ftp_startup.ctrl_dir,ctrl_dir);
+    SAFECOPY(ftp_startup.index_file_name,"00index");
+    SAFECOPY(ftp_startup.ctrl_dir,ctrl_dir);
 
 	/* Initialize Web Server startup structure */
     memset(&web_startup,0,sizeof(web_startup));
@@ -1500,7 +1500,7 @@ int main(int argc, char** argv)
 	web_startup.status=status_web_status;
 #endif
 	web_startup.login_attempt_list=&login_attempt_list;
-    strcpy(web_startup.ctrl_dir,ctrl_dir);
+    SAFECOPY(web_startup.ctrl_dir,ctrl_dir);
 
 	/* Initialize Mail Server startup structure */
     memset(&mail_startup,0,sizeof(mail_startup));
@@ -1522,7 +1522,7 @@ int main(int argc, char** argv)
 	mail_startup.status=status_mail_status;
 #endif
 	mail_startup.login_attempt_list=&login_attempt_list;
-    strcpy(mail_startup.ctrl_dir,ctrl_dir);
+    SAFECOPY(mail_startup.ctrl_dir,ctrl_dir);
 
 	/* Initialize Services startup structure */
     memset(&services_startup,0,sizeof(services_startup));
@@ -1544,7 +1544,7 @@ int main(int argc, char** argv)
 	services_startup.status=status_services_status;
 #endif
 	services_startup.login_attempt_list=&login_attempt_list;
-    strcpy(services_startup.ctrl_dir,ctrl_dir);
+    SAFECOPY(services_startup.ctrl_dir,ctrl_dir);
 
 	/* Pre-INI command-line switches */
 	for(i=1;i<argc;i++) {
@@ -1552,7 +1552,7 @@ int main(int argc, char** argv)
 		while(*arg=='-')
 			arg++;
 		if(strcspn(arg,"\\/")!=strlen(arg)) {
-			strcpy(ini_file,arg);
+			SAFECOPY(ini_file,arg);
 			continue;
 		}
 		if(stricmp(arg, "version") == 0) {
@@ -2341,7 +2341,7 @@ int main(int argc, char** argv)
 							login_attempt=node->data;
 							localtime32(&login_attempt->time,&tm);
 							if(inet_addrtop(&login_attempt->addr, ip_addr, sizeof(ip_addr))==NULL)
-								strcpy(ip_addr, "<invalid address>");
+								SAFECOPY(ip_addr, "<invalid address>");
 							printf("%lu attempts (%lu duplicate) from %s, last via %s on %u/%u %02u:%02u:%02u (user: %s, password: %s)\n"
 								,login_attempt->count
 								,login_attempt->dupes
diff --git a/src/sbbs3/sbbsecho.c b/src/sbbs3/sbbsecho.c
index d0582fc0cc62f7b11db6dd2d0b3feb3a65d4c836..f5d085fa855d81f19525df2d21355549fed529ef 100644
--- a/src/sbbs3/sbbsecho.c
+++ b/src/sbbs3/sbbsecho.c
@@ -774,7 +774,7 @@ bool bso_lock_node(fidoaddr_t dest)
 		if(terminated)
 			return false;
 		SLEEP(cfg.bso_lock_delay*1000);
-		mkpath(outbound); // Just in case something (e.g. Argus) deleted the outbound directory
+		(void)mkpath(outbound); // Just in case something (e.g. Argus) deleted the outbound directory
 	}
 	strListPush(&locked_bso_nodes, fname);
 	lprintf(LOG_DEBUG, "Node (%s) successfully locked via: %s", smb_faddrtoa(&dest, NULL), fname);
@@ -4633,7 +4633,7 @@ int import_netmail(const char* path, fmsghdr_t hdr, FILE* fp, const char* inboun
 				SAFEPRINTF2(str,"%s%s", inbound, tp);
 			}
 			SAFEPRINTF2(tmp,"%sfile/%04u.in",scfg.data_dir,usernumber);
-			mkpath(tmp);
+			(void)mkpath(tmp);
 			backslash(tmp);
 			SAFECAT(tmp,tp);
 			lprintf(LOG_DEBUG, "Moving attachment from %s to %s", str, tmp);
@@ -5307,7 +5307,7 @@ int export_netmail(void)
 				lprintf(LOG_DEBUG, "MIME attachment decoded: %s (%lu bytes)", filename, (ulong)filelen);
 				char outdir[MAX_PATH+1];
 				SAFEPRINTF2(outdir, "%sfile/%04u.out", scfg.data_dir, msg.idx.from);
-				mkpath(outdir);
+				(void)mkpath(outdir);
 				char fpath[MAX_PATH+1];
 				SAFEPRINTF2(fpath, "%s/%s", outdir, filename);
 				FILE* fp = fopen(fpath, "wb");
@@ -6377,7 +6377,7 @@ int main(int argc, char **argv)
 	cfg.areas=0;		/* Total number of areas in AREAS.BBS */
 	cfg.area=NULL;
 
-	fexistcase(cfg.areafile);
+	(void)fexistcase(cfg.areafile);
 	if((stream = fopen(cfg.areafile,"r")) == NULL) {
 		lprintf(LOG_NOTICE, "Could not open Area File (%s): %s", cfg.areafile, strerror(errno));
 	} else {
diff --git a/src/sbbs3/scfg/scfg.c b/src/sbbs3/scfg/scfg.c
index 57159ee95785ef0c033ea7e64f264565bef1a0c9..e5d10b37783b7dfcfead6843bafe95923cb95df2 100644
--- a/src/sbbs3/scfg/scfg.c
+++ b/src/sbbs3/scfg/scfg.c
@@ -663,16 +663,13 @@ int main(int argc, char **argv)
 				break;
 			case -1:
 				i=0;
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
 				uifc.helpbuf=
 					"`Exit SCFG:`\n"
 					"\n"
 					"If you want to exit the Synchronet configuration utility, select `Yes`.\n"
 					"Otherwise, select `No` or hit ~ ESC ~.\n"
 				;
-				i=uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,0,"Exit SCFG",opt);
+				i=uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,0,"Exit SCFG",uifcYesNoOpts);
 				if(!i)
 					bail(0);
 				break; 
@@ -792,9 +789,6 @@ int save_changes(int mode)
 		uifc.changes=0;
 		return(0);
 	}
-	strcpy(opt[0],"Yes");
-	strcpy(opt[1],"No");
-	opt[2][0]=0;
 	uifc.helpbuf=
 		"`Save Changes:`\n"
 		"\n"
@@ -803,7 +797,7 @@ int save_changes(int mode)
 		"these changes, select `No`. If you are not sure and want to review the\n"
 		"configuration before deciding, hit ~ ESC ~.\n"
 	;
-	i=uifc.list(mode|WIN_SAV,0,0,0,&i,0,"Save Changes",opt);
+	i=uifc.list(mode|WIN_SAV,0,0,0,&i,0,"Save Changes",uifcYesNoOpts);
 	if(i!=-1)
 		uifc.changes=0;
 	return(i);
@@ -858,14 +852,12 @@ void txt_cfg()
 		int msk = i & MSK_ON;
 		i &= MSK_OFF;
 		if (msk == MSK_INS) {
-			strcpy(str,"");
 			uifc.helpbuf=
 				"`Text Section Name:`\n"
 				"\n"
 				"This is the name of this text section.\n"
 			;
-			if(uifc.input(WIN_MID|WIN_SAV,0,0,"Text Section Name",str,40
-				,K_EDIT)<1)
+			if(uifc.input(WIN_MID|WIN_SAV,0,0,"Text Section Name",str,40,K_NONE)<1)
 				continue;
 			SAFECOPY(code,str);
 			prep_code(code,/* prefix: */NULL);
@@ -900,8 +892,8 @@ void txt_cfg()
 				continue; 
 			}
 			memset((txtsec_t *)cfg.txtsec[i],0,sizeof(txtsec_t));
-			strcpy(cfg.txtsec[i]->name,str);
-			strcpy(cfg.txtsec[i]->code,code);
+			SAFECOPY(cfg.txtsec[i]->name,str);
+			SAFECOPY(cfg.txtsec[i]->code,code);
 			cfg.total_txtsecs++;
 			uifc.changes=1;
 			continue; 
@@ -948,14 +940,14 @@ void txt_cfg()
 						"\n"
 						"This is the name of this text section.\n"
 					;
-					strcpy(str,cfg.txtsec[i]->name);	/* save */
+					SAFECOPY(str,cfg.txtsec[i]->name);	/* save */
 					if(!uifc.input(WIN_MID|WIN_SAV,0,10
 						,"Text File Section Name"
 						,cfg.txtsec[i]->name,sizeof(cfg.txtsec[i]->name)-1,K_EDIT))
-						strcpy(cfg.txtsec[i]->name,str);
+						SAFECOPY(cfg.txtsec[i]->name,str);
 					break;
 				case 1:
-					strcpy(str,cfg.txtsec[i]->code);
+					SAFECOPY(str,cfg.txtsec[i]->code);
 					uifc.helpbuf=
 						"`Text Section Internal Code:`\n"
 						"\n"
@@ -966,7 +958,7 @@ void txt_cfg()
 					uifc.input(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
 						,str,LEN_CODE,K_EDIT|K_UPPER);
 					if(code_ok(str))
-						strcpy(cfg.txtsec[i]->code,str);
+						SAFECOPY(cfg.txtsec[i]->code,str);
 					else {
 						uifc.helpbuf=invalid_code;
 						uifc.msg("Invalid Code");
@@ -1030,14 +1022,12 @@ void shell_cfg()
 		int msk = i & MSK_ON;
 		i &= MSK_OFF;
 		if (msk == MSK_INS) {
-			strcpy(str,"Menu Shell");
 			uifc.helpbuf=
 				"`Command Shell Name:`\n"
 				"\n"
 				"This is the descriptive name of this command shell.\n"
 			;
-			if(uifc.input(WIN_MID|WIN_SAV,0,0,"Command Shell Name",str,40
-				,K_EDIT)<1)
+			if(uifc.input(WIN_MID|WIN_SAV,0,0,"Command Shell Name",str,40,K_NONE)<1)
 				continue;
 			SAFECOPY(code,str);
 			prep_code(code,/* prefix: */NULL);
@@ -1076,8 +1066,8 @@ void shell_cfg()
 				continue; 
 			}
 			memset((shell_t *)cfg.shell[i],0,sizeof(shell_t));
-			strcpy(cfg.shell[i]->name,str);
-			strcpy(cfg.shell[i]->code,code);
+			SAFECOPY(cfg.shell[i]->name,str);
+			SAFECOPY(cfg.shell[i]->code,code);
 			cfg.total_shells++;
 			uifc.changes=1;
 			continue; 
@@ -1138,14 +1128,14 @@ void shell_cfg()
 						"\n"
 						"This is the descriptive name of this command shell.\n"
 					;
-					strcpy(str,cfg.shell[i]->name);    /* save */
+					SAFECOPY(str,cfg.shell[i]->name);    /* save */
 					if(!uifc.input(WIN_MID|WIN_SAV,0,10
 						,"Command Shell Name"
 						,cfg.shell[i]->name,sizeof(cfg.shell[i]->name)-1,K_EDIT))
-						strcpy(cfg.shell[i]->name,str);
+						SAFECOPY(cfg.shell[i]->name,str);
 					break;
 				case 1:
-					strcpy(str,cfg.shell[i]->code);
+					SAFECOPY(str,cfg.shell[i]->code);
 					uifc.helpbuf=
 						"`Command Shell Internal Code:`\n"
 						"\n"
@@ -1160,7 +1150,7 @@ void shell_cfg()
 					uifc.input(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
 						,str,LEN_CODE,K_EDIT|K_UPPER);
 					if(code_ok(str))
-						strcpy(cfg.shell[i]->code,str);
+						SAFECOPY(cfg.shell[i]->code,str);
 					else {
 						uifc.helpbuf=invalid_code;
 						uifc.msg("Invalid Code");
@@ -1168,7 +1158,7 @@ void shell_cfg()
 					}
 					break;
 				case 2:
-					sprintf(str,"%s Command Shell",cfg.shell[i]->name);
+					SAFEPRINTF(str,"%s Command Shell",cfg.shell[i]->name);
 					getar(str,cfg.shell[i]->arstr);
 					break; 
 			} 
@@ -1233,7 +1223,7 @@ void getar(char *desc, char *inar)
 	char str[128],ar[128];
 	int i,j,len,done=0,n;
 
-	strcpy(ar,inar);
+	SAFECOPY(ar,inar);
 	while(!done) {
 	len=strlen(ar);
 	if(len>=30) {	  /* Needs to be shortened */
@@ -1267,7 +1257,7 @@ void getar(char *desc, char *inar)
 			else
 				strncat(str,ar+i,1); 
 		}
-		strcpy(ar,str);
+		SAFECOPY(ar,str);
 		len=strlen(ar); 
 	}
 
@@ -1290,7 +1280,7 @@ void getar(char *desc, char *inar)
 			else
 				strncat(str,ar+i,1); 
 		}
-		strcpy(ar,str);
+		SAFECOPY(ar,str);
         len=strlen(ar); 
 	}
 
@@ -1309,7 +1299,7 @@ void getar(char *desc, char *inar)
 			else
 				strncat(str,ar+i,1); 
 		}
-		strcpy(ar,str);
+		SAFECOPY(ar,str);
         len=strlen(ar); 
 	}
 
@@ -1326,7 +1316,7 @@ void getar(char *desc, char *inar)
 			if(j==7)
 				strncat(str,ar+i,1); 
 		}
-        strcpy(ar,str);
+        SAFECOPY(ar,str);
         len=strlen(ar); 
 	}
 
@@ -1440,7 +1430,7 @@ void getar(char *desc, char *inar)
 			else
 				strncat(str,ar+i,1); 
 }
-		strcpy(ar,str);
+		SAFECOPY(ar,str);
 		len=strlen(ar); 
 }
 	if(len>=30) {				  /* Remove all spaces and &s */
@@ -1449,7 +1439,7 @@ void getar(char *desc, char *inar)
 		for(i=0;i<n;i++)
 			if(ar[i]!=' ' && ar[i]!='&')
 				strncat(str,ar+i,1);
-		strcpy(ar,str);
+		SAFECOPY(ar,str);
 		len=strlen(ar); 
 	}
 	i=0;
@@ -1509,16 +1499,13 @@ void getar(char *desc, char *inar)
 			break;
 		case 1:
 			i=1;
-			strcpy(opt[0],"Yes");
-			strcpy(opt[1],"No");
-			opt[2][0]=0;
 			uifc.helpbuf=
 				"`Clear Requirements:`\n"
 				"\n"
 				"If you wish to clear the current requirement string, select `Yes`.\n"
 				"Otherwise, select `No`.\n"
 			;
-			i=uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,0,"Are You Sure",opt);
+			i=uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,0,"Are You Sure",uifcYesNoOpts);
 			if(!i) {
 				ar[0]=0;
 				uifc.changes=1; 
diff --git a/src/sbbs3/scfg/scfgchat.c b/src/sbbs3/scfg/scfgchat.c
index 63397d2939370b5d1e916cdff37078c8c9b5e9a8..3b50754d588ad15793cdfe57c51cb1042cc9055e 100644
--- a/src/sbbs3/scfg/scfgchat.c
+++ b/src/sbbs3/scfg/scfgchat.c
@@ -82,7 +82,7 @@ void page_cfg()
 				continue; 
 			}
 			memset((page_t *)cfg.page[i],0,sizeof(page_t));
-			strcpy(cfg.page[i]->cmd,str);
+			SAFECOPY(cfg.page[i]->cmd,str);
 			cfg.total_pages++;
 			uifc.changes=1;
 			continue; 
@@ -135,10 +135,10 @@ void page_cfg()
 						SCFG_CMDLINE_PREFIX_HELP
 						SCFG_CMDLINE_SPEC_HELP
 					;
-					strcpy(str,cfg.page[i]->cmd);
+					SAFECOPY(str,cfg.page[i]->cmd);
 					if(!uifc.input(WIN_MID|WIN_SAV,0,10,"Command Line"
 						,cfg.page[i]->cmd,sizeof(cfg.page[i]->cmd)-1,K_EDIT))
-						strcpy(cfg.page[i]->cmd,str);
+						SAFECOPY(cfg.page[i]->cmd,str);
 					break;
 				case 1:
 					getar(str,cfg.page[i]->arstr);
@@ -311,8 +311,8 @@ void chan_cfg()
 				continue; 
 			}
 			memset((chan_t *)cfg.chan[i],0,sizeof(chan_t));
-			strcpy(cfg.chan[i]->name,str);
-			strcpy(cfg.chan[i]->code,code);
+			SAFECOPY(cfg.chan[i]->name,str);
+			SAFECOPY(cfg.chan[i]->code,code);
 			cfg.total_chans++;
 			uifc.changes=1;
 			continue; 
@@ -372,10 +372,10 @@ void chan_cfg()
 						"\n"
 						"This is the name or description of the chat channel.\n"
 					;
-					strcpy(str,cfg.chan[i]->name);
+					SAFECOPY(str,cfg.chan[i]->name);
 					if(!uifc.input(WIN_MID|WIN_SAV,0,10,"Chat Channel Name"
 						,cfg.chan[i]->name,sizeof(cfg.chan[i]->name)-1,K_EDIT))
-						strcpy(cfg.chan[i]->name,str);
+						SAFECOPY(cfg.chan[i]->name,str);
 					break;
 				case 1:
 					uifc.helpbuf=
@@ -385,12 +385,12 @@ void chan_cfg()
 						"to it internally. This code is usually an abbreviation of the chat\n"
 						"channel name.\n"
 					;
-					strcpy(str,cfg.chan[i]->code);
+					SAFECOPY(str,cfg.chan[i]->code);
 					if(!uifc.input(WIN_MID|WIN_SAV,0,10,"Internal Code"
 						,str,LEN_CODE,K_UPPER|K_EDIT))
 						break;
 					if(code_ok(str))
-						strcpy(cfg.chan[i]->code,str);
+						SAFECOPY(cfg.chan[i]->code,str);
 					else {
 						uifc.helpbuf=invalid_code;
 						uifc.msg("Invalid Code");
@@ -574,8 +574,8 @@ void chatact_cfg(uint setnum)
 				continue; 
 			}
 			memset((chatact_t *)cfg.chatact[chatnum[i]],0,sizeof(chatact_t));
-			strcpy(cfg.chatact[chatnum[i]]->cmd,cmd);
-			strcpy(cfg.chatact[chatnum[i]]->out,out);
+			SAFECOPY(cfg.chatact[chatnum[i]]->cmd,cmd);
+			SAFECOPY(cfg.chatact[chatnum[i]]->out,out);
 			cfg.chatact[chatnum[i]]->actset=setnum;
 			cfg.total_chatacts++;
 			uifc.changes=1;
@@ -608,10 +608,10 @@ void chatact_cfg(uint setnum)
 			"\n"
 			"This is the command that triggers this chat action.\n"
 		;
-		strcpy(str,cfg.chatact[chatnum[i]]->cmd);
+		SAFECOPY(str,cfg.chatact[chatnum[i]]->cmd);
 		if(!uifc.input(WIN_MID|WIN_SAV,0,10,"Chat Action Command"
 			,cfg.chatact[chatnum[i]]->cmd,LEN_CHATACTCMD,K_EDIT|K_UPPER)) {
-			strcpy(cfg.chatact[chatnum[i]]->cmd,str);
+			SAFECOPY(cfg.chatact[chatnum[i]]->cmd,str);
 			continue; 
 		}
 		uifc.helpbuf=
@@ -619,10 +619,10 @@ void chatact_cfg(uint setnum)
 			"\n"
 			"This is the output string that results from this chat action.\n"
 		;
-		strcpy(str,cfg.chatact[chatnum[i]]->out);
+		SAFECOPY(str,cfg.chatact[chatnum[i]]->out);
 		if(!uifc.input(WIN_MID|WIN_SAV,0,10,""
 			,cfg.chatact[chatnum[i]]->out,LEN_CHATACTOUT,K_EDIT|K_MSG))
-			strcpy(cfg.chatact[chatnum[i]]->out,str); 
+			SAFECOPY(cfg.chatact[chatnum[i]]->out,str); 
 	}
 }
 
@@ -703,8 +703,8 @@ void guru_cfg()
 				continue; 
 			}
 			memset((guru_t *)cfg.guru[i],0,sizeof(guru_t));
-			strcpy(cfg.guru[i]->name,str);
-			strcpy(cfg.guru[i]->code,code);
+			SAFECOPY(cfg.guru[i]->name,str);
+			SAFECOPY(cfg.guru[i]->code,code);
 			cfg.total_gurus++;
 			uifc.changes=1;
 			continue; 
@@ -754,10 +754,10 @@ void guru_cfg()
 						"\n"
 						"This is the name of the selected Guru.\n"
 					;
-					strcpy(str,cfg.guru[i]->name);
+					SAFECOPY(str,cfg.guru[i]->name);
 					if(!uifc.input(WIN_MID|WIN_SAV,0,10,"Guru Name"
 						,cfg.guru[i]->name,sizeof(cfg.guru[i]->name)-1,K_EDIT))
-						strcpy(cfg.guru[i]->name,str);
+						SAFECOPY(cfg.guru[i]->name,str);
 					break;
 				case 1:
 	uifc.helpbuf=
@@ -766,12 +766,12 @@ void guru_cfg()
 		"Every Guru must have its own unique code for Synchronet to refer to\n"
 		"it internally. This code is usually an abbreviation of the Guru name.\n"
 	;
-					strcpy(str,cfg.guru[i]->code);
+					SAFECOPY(str,cfg.guru[i]->code);
 					if(!uifc.input(WIN_MID|WIN_SAV,0,0,"Guru Internal Code"
 						,str,LEN_CODE,K_EDIT|K_UPPER))
 						break;
 					if(code_ok(str))
-						strcpy(cfg.guru[i]->code,str);
+						SAFECOPY(cfg.guru[i]->code,str);
 					else {
 						uifc.helpbuf=invalid_code;
 						uifc.msg("Invalid Code");
@@ -847,7 +847,7 @@ void actsets_cfg()
 				continue; 
 			}
 			memset((actset_t *)cfg.actset[i],0,sizeof(actset_t));
-			strcpy(cfg.actset[i]->name,str);
+			SAFECOPY(cfg.actset[i]->name,str);
 			cfg.total_actsets++;
 			uifc.changes=1;
 			continue; 
@@ -898,10 +898,10 @@ void actsets_cfg()
 						"\n"
 						"This is the name of the selected action set.\n"
 					;
-					strcpy(str,cfg.actset[i]->name);
+					SAFECOPY(str,cfg.actset[i]->name);
 					if(!uifc.input(WIN_MID|WIN_SAV,0,10,"Action Set Name"
 						,cfg.actset[i]->name,sizeof(cfg.actset[i]->name)-1,K_EDIT))
-						strcpy(cfg.actset[i]->name,str);
+						SAFECOPY(cfg.actset[i]->name,str);
 					break;
 				case 1:
 					chatact_cfg(i);
diff --git a/src/sbbs3/scfg/scfgnet.c b/src/sbbs3/scfg/scfgnet.c
index 2cbe15d1e86125b63cce5ef559288cf958341de0..235ce384be7edc32ca998dbe80abbe47e290bdcf 100644
--- a/src/sbbs3/scfg/scfgnet.c
+++ b/src/sbbs3/scfg/scfgnet.c
@@ -135,7 +135,7 @@ uint getsub(void)
 		opt[k][0]=0;
 		sprintf(str,"Select %s Sub-board",cfg.grp[i]->sname);
 		j=uifc.list(WIN_RHT|WIN_BOT|WIN_SAV,0,0,45,&sub_dflt,&sub_bar,str,opt);
-		if(j==-1)
+		if(j==-1 || j >= cfg.total_subs)
 			continue;
 		sub_dflt++;
 		sub_bar++;
diff --git a/src/sbbs3/scfg/scfgnode.c b/src/sbbs3/scfg/scfgnode.c
index 3903fbabb677a4d1d1f65e48937bf48055d3cec5..526d8a0ccfea7ac65b39af6379df76068f870fa7 100644
--- a/src/sbbs3/scfg/scfgnode.c
+++ b/src/sbbs3/scfg/scfgnode.c
@@ -97,7 +97,7 @@ void node_menu()
 			}
 			continue; 
 		}
-		if(msk == MSK_INS) {
+		if(msk == MSK_INS && cfg.sys_nodes < MAX_NODES) {
 			SAFECOPY(cfg.node_dir,cfg.node_path[cfg.sys_nodes-1]);
 			i=cfg.sys_nodes+1;
 			load_node_cfg(&cfg,error, sizeof(error));
diff --git a/src/sbbs3/scfg/scfgxtrn.c b/src/sbbs3/scfg/scfgxtrn.c
index af09a19b4d687083963e9dd4786bde606ef184ce..720b1885dfe6f54b9a8bda4159aa6ed3a4d197b1 100644
--- a/src/sbbs3/scfg/scfgxtrn.c
+++ b/src/sbbs3/scfg/scfgxtrn.c
@@ -539,7 +539,7 @@ void tevents_cfg()
 					done=1;
 					break;
 				case 0:
-					strcpy(str,cfg.event[i]->code);
+					SAFECOPY(str,cfg.event[i]->code);
 					uifc.helpbuf=
 						"`Timed Event Internal Code:`\n"
 						"\n"
@@ -550,7 +550,7 @@ void tevents_cfg()
 					uifc.input(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
 						,str,LEN_CODE,K_EDIT|K_UPPER);
 					if(code_ok(str))
-						strcpy(cfg.event[i]->code,str);
+						SAFECOPY(cfg.event[i]->code,str);
 					else {
 						uifc.helpbuf=invalid_code;
 						uifc.msg("Invalid Code");
@@ -1067,10 +1067,10 @@ void xtrn_cfg(uint section)
 						"\n"
 						"This is the name or description of the online program (door).\n"
 					;
-					strcpy(str,cfg.xtrn[i]->name);
+					SAFECOPY(str,cfg.xtrn[i]->name);
 					if(!uifc.input(WIN_MID|WIN_SAV,0,10,"Online Program Name"
 						,cfg.xtrn[i]->name,sizeof(cfg.xtrn[i]->name)-1,K_EDIT))
-						strcpy(cfg.xtrn[i]->name,str);
+						SAFECOPY(cfg.xtrn[i]->name,str);
 					break;
 				case 1:
 					uifc.helpbuf=
@@ -1080,11 +1080,11 @@ void xtrn_cfg(uint section)
 						"refer to it internally. This code is usually an abbreviation of the\n"
 						"online program name.\n"
 					;
-					strcpy(str,cfg.xtrn[i]->code);
+					SAFECOPY(str,cfg.xtrn[i]->code);
 					uifc.input(WIN_MID|WIN_SAV,0,10,"Internal Code"
 						,str,LEN_CODE,K_UPPER|K_EDIT);
 					if(code_ok(str))
-						strcpy(cfg.xtrn[i]->code,str);
+						SAFECOPY(cfg.xtrn[i]->code,str);
 					else {
 						uifc.helpbuf=invalid_code;
 						uifc.msg("Invalid Code");
@@ -1745,13 +1745,13 @@ void xedit_cfg()
 						"\n"
 						"This is the name or description of the external editor.\n"
 					;
-					strcpy(str,cfg.xedit[i]->name);
+					SAFECOPY(str,cfg.xedit[i]->name);
 					if(!uifc.input(WIN_MID|WIN_SAV,0,10,"External Editor Name"
 						,cfg.xedit[i]->name,sizeof(cfg.xedit[i]->name)-1,K_EDIT))
-						strcpy(cfg.xedit[i]->name,str);
+						SAFECOPY(cfg.xedit[i]->name,str);
 					break;
 				case 1:
-					strcpy(str,cfg.xedit[i]->code);
+					SAFECOPY(str,cfg.xedit[i]->code);
 					uifc.helpbuf=
 						"`External Editor Internal Code:`\n"
 						"\n"
@@ -1762,7 +1762,7 @@ void xedit_cfg()
 					uifc.input(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
 						,str,LEN_CODE,K_EDIT|K_UPPER);
 					if(code_ok(str))
-						strcpy(cfg.xedit[i]->code,str);
+						SAFECOPY(cfg.xedit[i]->code,str);
 					else {
 						uifc.helpbuf=invalid_code;
 						uifc.msg("Invalid Code");
@@ -2211,7 +2211,7 @@ int natvpgm_cfg()
 				continue; 
 			}
 			memset((natvpgm_t *)cfg.natvpgm[i],0,sizeof(natvpgm_t));
-			strcpy(cfg.natvpgm[i]->name,str);
+			SAFECOPY(cfg.natvpgm[i]->name,str);
 			cfg.total_natvpgms++;
 			uifc.changes=TRUE;
 			continue; 
@@ -2231,10 +2231,10 @@ int natvpgm_cfg()
 			"\n"
 			"This is the executable filename of the Native external program.\n"
 		;
-		strcpy(str,cfg.natvpgm[i]->name);
+		SAFECOPY(str,cfg.natvpgm[i]->name);
 		if(uifc.input(WIN_MID|WIN_SAV,0,5,"Native Program Name",str,12
 			,K_EDIT)>0)
-			strcpy(cfg.natvpgm[i]->name,str);
+			SAFECOPY(cfg.natvpgm[i]->name,str);
 		}
 	return(0);
 }
@@ -2384,14 +2384,14 @@ void xtrnsec_cfg()
 						"\n"
 						"This is the name of this section.\n"
 					;
-					strcpy(str,cfg.xtrnsec[i]->name);	 /* save */
+					SAFECOPY(str,cfg.xtrnsec[i]->name);	 /* save */
 					if(!uifc.input(WIN_MID|WIN_SAV,0,10
 						,"Program Section Name"
 						,cfg.xtrnsec[i]->name,sizeof(cfg.xtrnsec[i]->name)-1,K_EDIT))
-						strcpy(cfg.xtrnsec[i]->name,str);
+						SAFECOPY(cfg.xtrnsec[i]->name,str);
 					break;
 				case 1:
-					strcpy(str,cfg.xtrnsec[i]->code);
+					SAFECOPY(str,cfg.xtrnsec[i]->code);
 					uifc.helpbuf=
 						"`Online Program Section Internal Code:`\n"
 						"\n"
@@ -2402,7 +2402,7 @@ void xtrnsec_cfg()
 					uifc.input(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
 						,str,LEN_CODE,K_EDIT|K_UPPER);
 					if(code_ok(str))
-						strcpy(cfg.xtrnsec[i]->code,str);
+						SAFECOPY(cfg.xtrnsec[i]->code,str);
 					else {
 						uifc.helpbuf=invalid_code;
 						uifc.msg("Invalid Code");
diff --git a/src/sbbs3/scfgsave.c b/src/sbbs3/scfgsave.c
index 29b2a217ca0f703963e4596cbc6d43ef6545f548..cbf258496d70fc21f1694ff40631713dc5d882ac 100644
--- a/src/sbbs3/scfgsave.c
+++ b/src/sbbs3/scfgsave.c
@@ -822,7 +822,7 @@ BOOL DLLCALL write_file_cfg(scfg_t* cfg, int backup_level)
 							SAFEPRINTF(str, "%sdirs", cfg->data_dir);
 						prep_dir(str, path, sizeof(path));
 					}
-					mkpath(path);
+					(void)mkpath(path);
 				}
 
 				put_str(cfg->dir[i]->upload_sem, stream);
diff --git a/src/sbbs3/sexyz.c b/src/sbbs3/sexyz.c
index be9e21651d3681ab15a5b7be01cfe0f9b18c2cfc..c82e7a0f91ebbb740d5ce2d610f792733c071e5f 100755
--- a/src/sbbs3/sexyz.c
+++ b/src/sbbs3/sexyz.c
@@ -252,7 +252,7 @@ char* dszlog_filename(char* str)
 	static char	path[MAX_PATH+1];
 
 #ifdef _WIN32
-	char sfpath[MAX_PATH+1];
+	static char sfpath[MAX_PATH+1];
 	if(dszlog_short) {
 		SAFECOPY(sfpath,str);
 		GetShortPathName(str,sfpath,sizeof(sfpath));
diff --git a/src/sbbs3/smbactiv.c b/src/sbbs3/smbactiv.c
index e8893372499206fde39dee622e0c6703b8d1204d..b46d8171b8daeafc7e7de21299f28420f668ae2f 100644
--- a/src/sbbs3/smbactiv.c
+++ b/src/sbbs3/smbactiv.c
@@ -113,8 +113,7 @@ int main(int argc, char **argv)
 		fprintf(stderr,"!ERROR loading configuration files: %s\n",str);
 		return(1);
 	}
-
-	chdir(cfg.ctrl_dir);
+	(void)chdir(cfg.ctrl_dir);
 
 	if((sub_status=(sub_status_t *)MALLOC
 		(cfg.total_subs*sizeof(sub_status_t)))==NULL) {
diff --git a/src/sbbs3/smbutil.c b/src/sbbs3/smbutil.c
index daeddf3447cea63e9142a36d89ddc6e482dccf38..47afdaf4cbf7fb7d300d65fbf4b8031c7487c72b 100644
--- a/src/sbbs3/smbutil.c
+++ b/src/sbbs3/smbutil.c
@@ -1075,6 +1075,9 @@ void packmsgs(ulong packable)
 			smb_close_ha(&smb);
 			smb_close_da(&smb); 
 		}
+		if(tmp_sdt != NULL) fclose(tmp_sdt);
+		if(tmp_shd != NULL) fclose(tmp_shd);
+		if(tmp_sid != NULL) fclose(tmp_sid);
 		fprintf(errfp,"\n%s!Error opening temp files\n",beep);
 		return; 
 	}
diff --git a/src/sbbs3/str.cpp b/src/sbbs3/str.cpp
index d5286bf4b9552119d7be21dc89a92457d6429c99..7f2ae5bd18b1f3f534f73a3cf1189083036cc8a8 100644
--- a/src/sbbs3/str.cpp
+++ b/src/sbbs3/str.cpp
@@ -1,7 +1,5 @@
 /* Synchronet high-level string i/o routines */
 
-/* $Id: str.cpp,v 1.88 2020/04/23 02:40:19 rswindell Exp $ */
-
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
@@ -15,21 +13,9 @@
  * 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.	*
  ****************************************************************************/
 
@@ -154,7 +140,7 @@ void sbbs_t::sif(char *fname, char *answers, long len)
 		return; 
 	}
 	length=(long)filelength(file);
-	if((buf=(char *)malloc(length))==0) {
+	if((buf=(char *)calloc(length + 1, 1))==0) {
 		close(file);
 		errormsg(WHERE,ERR_ALLOC,str,length);
 		answers[0]=0;
@@ -322,7 +308,7 @@ void sbbs_t::sof(char *fname, char *answers, long len)
 		return; 
 	}
 	length=(long)filelength(file);
-	if((buf=(char *)malloc(length))==0) {
+	if((buf=(char *)calloc(length + 1, 1))==0) {
 		close(file);
 		errormsg(WHERE,ERR_ALLOC,str,length);
 		answers[0]=0;
@@ -1229,10 +1215,8 @@ void sbbs_t::change_user(void)
 		return;
 	if((i=finduser(str))==0)
 		return;
-	if(online==ON_REMOTE) {
-		getuserrec(&cfg,i,U_LEVEL,2,str);
-		if(atoi(str)>logon_ml) {
-			getuserrec(&cfg,i,U_PASS,LEN_PASS,tmp);
+	if(getuserrec(&cfg,i,U_LEVEL,2,str) == 0 && atoi(str)>logon_ml) {
+		if(getuserrec(&cfg,i,U_PASS,LEN_PASS,tmp) == 0) {
 			bputs(text[ChUserPwPrompt]);
 			console|=CON_R_ECHOX;
 			getstr(str,8,K_UPPER);
diff --git a/src/sbbs3/telgate.cpp b/src/sbbs3/telgate.cpp
index f713cdf79f9ad786742f0e7d9c7dc8d2af3cbc36..6facfc018fc298483f459c92391ec6e5c20234d4 100644
--- a/src/sbbs3/telgate.cpp
+++ b/src/sbbs3/telgate.cpp
@@ -1,7 +1,5 @@
 /* Synchronet telnet gateway routines */
 
-/* $Id: telgate.cpp,v 1.46 2019/08/04 17:49:51 deuce Exp $ */
-
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
@@ -15,21 +13,9 @@
  * 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.	*
  ****************************************************************************/
 
@@ -133,7 +119,7 @@ void sbbs_t::telnet_gate(char* destaddr, ulong mode, char* client_user_name, cha
 			p+=sprintf(p,"%s/%lu",terminal, cur_rate);
 		p++;	// Add NULL
 		l=p-(char*)buf;
-		sendsocket(remote_socket,(char*)buf,l);
+		(void)sendsocket(remote_socket,(char*)buf,l);
 		mode|=TG_NOLF;	/* Send LF (to remote host) when Telnet client sends CRLF (when not in binary mode) */
 	}
 
diff --git a/src/sbbs3/textgen.c b/src/sbbs3/textgen.c
index 4eaa6a74cc956a78299ea9666aefbf9b6fe89644..56af31bea39519c44a825c2b2f0f586155d3e140 100644
--- a/src/sbbs3/textgen.c
+++ b/src/sbbs3/textgen.c
@@ -29,7 +29,7 @@ char *readtext(FILE *stream, char **comment_ret)
 	if(*(p+1)=='\\') {	/* merge multiple lines */
 		for(cp=p+2; *cp && IS_WHITESPACE(*cp); cp++);
 		truncsp(cp);
-		strcat(comment, cp);
+		SAFECAT(comment, cp);
 		while(strlen(buf)<2000) {
 			if(!fgets(str,255,stream))
 				return(NULL);
@@ -41,7 +41,7 @@ char *readtext(FILE *stream, char **comment_ret)
 			if(p && *(p+1)=='\\') {
 				for(cp=p+2; *cp && IS_WHITESPACE(*cp); cp++);
 				truncsp(cp);
-				strcat(comment, cp);
+				SAFECAT(comment, cp);
 				continue;
 			}
 			break; 
@@ -49,7 +49,7 @@ char *readtext(FILE *stream, char **comment_ret)
 	}
 	else {
 		for(cp=p+2; *cp && IS_WHITESPACE(*cp); cp++);
-		strcat(comment, cp);
+		SAFECAT(comment, cp);
 		truncsp(comment);
 	}
 	*(p)=0;
@@ -200,7 +200,7 @@ int main(int argc, char **argv)
 		p = getenv("SBBSEXEC");
 	if(p==NULL)
 		p = "/sbbs/exec";
-	sprintf(path,"%s/load/text.js",p);
+	SAFEPRINTF(path,"%s/load/text.js",p);
 	if((text_js=fopen(path, "w"))==NULL) {
 		perror(path);
 		return __LINE__;
diff --git a/src/sbbs3/un_qwk.cpp b/src/sbbs3/un_qwk.cpp
index 9b0472baf389f9cdd6893715b856febbc2a62335..0d35a98cc6325465695361370cbc5eab6d366745 100644
--- a/src/sbbs3/un_qwk.cpp
+++ b/src/sbbs3/un_qwk.cpp
@@ -1,7 +1,5 @@
 /* Synchronet QWK unpacking routine */
 
-/* $Id: un_qwk.cpp,v 1.66 2020/08/10 00:43:42 rswindell Exp $ */
-
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
@@ -15,21 +13,9 @@
  * 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.	*
  ****************************************************************************/
 
@@ -145,7 +131,12 @@ bool sbbs_t::unpack_qwk(char *packet,uint hubnum)
 			break;
 		}
 		fseek(qwk,l,SEEK_SET);
-		fread(block,QWK_BLOCK_LEN,1,qwk);
+		if(fread(block,QWK_BLOCK_LEN,1,qwk) != 1) {
+			errormsg(WHERE, ERR_READ, packet, QWK_BLOCK_LEN);
+			blocks=1;
+			errors++;
+			continue;
+		}
 		if(block[0]<' ' || block[0]&0x80) {
 			lprintf(LOG_NOTICE,"!Invalid QWK message status (%02X) at offset %lu in %s"
 				,block[0], l, packet);
@@ -392,8 +383,9 @@ bool sbbs_t::unpack_qwk(char *packet,uint hubnum)
 		}
 
 		// Create directory if necessary
-		sprintf(inbox,"%sqnet/%s.in",cfg.data_dir,cfg.qhub[hubnum]->id);
-		MKDIR(inbox);
+		SAFEPRINTF2(inbox,"%sqnet/%s.in",cfg.data_dir,cfg.qhub[hubnum]->id);
+		if(MKDIR(inbox) != 0)
+			errormsg(WHERE, ERR_CREATE, inbox, 0);
 
 		// Copy files
 		SAFEPRINTF2(fname,"%s/%s",inbox,dirent->d_name);
diff --git a/src/sbbs3/un_rep.cpp b/src/sbbs3/un_rep.cpp
index 206c0d83e3e139f97fc9151a6b069583b235390a..6e77cdc4da5efb533aa866bd53d6d74889108c02 100644
--- a/src/sbbs3/un_rep.cpp
+++ b/src/sbbs3/un_rep.cpp
@@ -1,7 +1,4 @@
 /* Synchronet QWK replay (REP) packet unpacking routine */
-// vi: tabstop=4
-
-/* $Id: un_rep.cpp,v 1.80 2020/08/10 00:43:43 rswindell Exp $ */
 
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
@@ -16,21 +13,9 @@
  * 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.	*
  ****************************************************************************/
 
@@ -631,7 +616,7 @@ bool sbbs_t::unpack_rep(char* repfile)
 
 			// Create directory if necessary
 			SAFEPRINTF2(inbox,"%sqnet/%s.in",cfg.data_dir,useron.alias);
-			MKDIR(inbox);
+			(void)MKDIR(inbox);
 
 			SAFEPRINTF2(fname,"%s/%s",inbox,dirent->d_name);
 			mv(str,fname,1);
diff --git a/src/sbbs3/userdat.c b/src/sbbs3/userdat.c
index e3c7513cea5ce8af89ade7987df20dca17c00ca3..95916141c5f315018e7aee4aff61350f65ff978d 100644
--- a/src/sbbs3/userdat.c
+++ b/src/sbbs3/userdat.c
@@ -2217,8 +2217,11 @@ int getuserrec(scfg_t* cfg, int usernumber,int start, int length, char *str)
 	}
 	lseek(file,(long)((long)(usernumber-1)*U_LEN)+start,SEEK_SET);
 
-	if(length==0)	/* auto-length */
+	if(length < 1) { /* auto-length */
 		length=user_rec_len(start);
+		if(length < 1)
+			return -5;
+	}
 
 	i=0;
 	while(i<LOOP_NODEDAB
@@ -2336,8 +2339,11 @@ ulong adjustuserrec(scfg_t* cfg, int usernumber, int start, int length, long adj
 
 	lseek(file,(long)((long)(usernumber-1)*U_LEN)+start,SEEK_SET);
 
-	if(length==0)	/* auto-length */
+	if(length < 1) { /* auto-length */
 		length=user_rec_len(start);
+		if(length < 1)
+			return 0;
+	}
 
 	i=0;
 	while(i<LOOP_NODEDAB
diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c
index 7dd644519c2b1db67604110cb94a391449c06eff..c366dc07a6ee4169bb2be8ade3f0460751c9cca2 100644
--- a/src/sbbs3/websrvr.c
+++ b/src/sbbs3/websrvr.c
@@ -568,7 +568,7 @@ static int writebuf(http_session_t	*session, const char *buf, size_t len)
 		ResetEvent(session->outbuf.empty_event);
 		avail=RingBufFree(&session->outbuf);
 		if(!avail) {
-			WaitForEvent(session->outbuf.empty_event, 1);
+			(void)WaitForEvent(session->outbuf.empty_event, 1);
 			continue;
 		}
 		if(avail > len-sent)
@@ -3394,8 +3394,8 @@ static BOOL exec_js_webctrl(http_session_t* session, char *name, char* script, c
 			js_parse_query(session,session->req.post_data);
 		}
 	}
-	JS_GetProperty(session->js_cx,session->js_glob,"js",&val);
-	if (JSVAL_IS_OBJECT(val)) {
+	if(JS_GetProperty(session->js_cx,session->js_glob,"js",&val)
+		&& JSVAL_IS_OBJECT(val)) {
 		if((js_str=JS_NewStringCopyZ(session->js_cx, curdir))!=NULL) {
 			JS_DefineProperty(session->js_cx, JSVAL_TO_OBJECT(val), "startup_dir", STRING_TO_JSVAL(js_str)
 				,NULL,NULL,JSPROP_ENUMERATE);
@@ -3425,10 +3425,11 @@ static BOOL exec_js_webctrl(http_session_t* session, char *name, char* script, c
 		JS_ReportPendingException(session->js_cx);
 		if (rewrite && JSVAL_IS_BOOLEAN(rval) && JSVAL_TO_BOOLEAN(rval)) {
 			session->req.send_location = MOVED_STAT;
-			JS_GetProperty(session->js_cx,session->js_request,"request_string",&val);
-			JSVALUE_TO_STRBUF(session->js_cx, val, redir_req, sizeof(redir_req), NULL);
-			safe_snprintf(session->redir_req,sizeof(session->redir_req),"%s %s%s%s",methods[session->req.method]
-				,redir_req,session->http_ver<HTTP_1_0?"":" ",http_vers[session->http_ver]);
+			if(JS_GetProperty(session->js_cx,session->js_request,"request_string",&val)) {
+				JSVALUE_TO_STRBUF(session->js_cx, val, redir_req, sizeof(redir_req), NULL);
+				safe_snprintf(session->redir_req,sizeof(session->redir_req),"%s %s%s%s",methods[session->req.method]
+					,redir_req,session->http_ver<HTTP_1_0?"":" ",http_vers[session->http_ver]);
+			}
 		}
 		JS_RemoveObjectRoot(session->js_cx, &session->js_glob);
 	} while(0);
@@ -4357,7 +4358,7 @@ static int cgi_write_in(void *arg, char *buf, size_t bufsz)
 	int wr;
 	struct cgi_data *cd = (struct cgi_data *)arg;
 
-	WriteFile(cd->wrpipe, buf, bufsz, &wr, /* Overlapped: */NULL);
+	(void)WriteFile(cd->wrpipe, buf, bufsz, &wr, /* Overlapped: */NULL);
 	return wr;
 }
 
@@ -5004,6 +5005,7 @@ static BOOL exec_cgi(http_session_t *session)
 	/* Create the child input pipe. */
 	if(!CreatePipe(&startup_info.hStdInput,&wrinpipe,&sa,0 /* default buffer size */)) {
 		lprintf(LOG_ERR,"%04d !ERROR %d creating stdin pipe",session->socket,GetLastError());
+		CloseHandle(rdoutpipe);
 		return(FALSE);
 	}
 
@@ -5261,10 +5263,10 @@ js_writefunc(JSContext *cx, uintN argc, jsval *arglist, BOOL writeln)
 			/* "Fast Mode" requested? */
 			jsval		val;
 			JSObject*	reply;
-			JS_GetProperty(cx, session->js_glob, "http_reply", &val);
-			reply=JSVAL_TO_OBJECT(val);
-			JS_GetProperty(cx, reply, "fast", &val);
-			if(JSVAL_IS_BOOLEAN(val) && JSVAL_TO_BOOLEAN(val)) {
+			if(JS_GetProperty(cx, session->js_glob, "http_reply", &val))
+				reply=JSVAL_TO_OBJECT(val);
+			if(JS_GetProperty(cx, reply, "fast", &val)
+				&& JSVAL_IS_BOOLEAN(val) && JSVAL_TO_BOOLEAN(val)) {
 				session->req.keep_alive=FALSE;
 				rc=JS_SUSPENDREQUEST(cx);
 				if(!ssjs_send_headers(session,FALSE)) {
@@ -5685,10 +5687,10 @@ js_write_template(JSContext *cx, uintN argc, jsval *arglist)
 			/* "Fast Mode" requested? */
 			jsval		val;
 			JSObject*	reply;
-			JS_GetProperty(cx, session->js_glob, "http_reply", &val);
-			reply=JSVAL_TO_OBJECT(val);
-			JS_GetProperty(cx, reply, "fast", &val);
-			if(JSVAL_IS_BOOLEAN(val) && JSVAL_TO_BOOLEAN(val)) {
+			if(JS_GetProperty(cx, session->js_glob, "http_reply", &val))
+				reply=JSVAL_TO_OBJECT(val);
+			if(JS_GetProperty(cx, reply, "fast", &val)
+				&& JSVAL_IS_BOOLEAN(val) && JSVAL_TO_BOOLEAN(val)) {
 				session->req.keep_alive=FALSE;
 				if(!ssjs_send_headers(session,FALSE)) {
 					free(template);
@@ -5841,22 +5843,23 @@ static BOOL js_setup(http_session_t* session)
 static BOOL ssjs_send_headers(http_session_t* session,int chunked)
 {
 	jsval		val;
-	JSObject*	reply;
-	JSIdArray*	heads;
-	JSObject*	headers;
+	JSObject*	reply = NULL;
+	JSIdArray*	heads = NULL;
+	JSObject*	headers = NULL;
 	int			i, h;
 	char		str[MAX_REQUEST_LINE+1];
 	char		*p=NULL,*p2=NULL;
 	size_t		p_sz=0, p2_sz=0;
 
 	JS_BEGINREQUEST(session->js_cx);
-	JS_GetProperty(session->js_cx,session->js_glob,"http_reply",&val);
-	reply = JSVAL_TO_OBJECT(val);
-	JS_GetProperty(session->js_cx,reply,"status",&val);
-	JSVALUE_TO_STRBUF(session->js_cx, val, session->req.status, sizeof(session->req.status), NULL);
-	JS_GetProperty(session->js_cx,reply,"header",&val);
-	headers = JSVAL_TO_OBJECT(val);
-	heads=JS_Enumerate(session->js_cx,headers);
+	if(JS_GetProperty(session->js_cx,session->js_glob,"http_reply",&val))
+		reply = JSVAL_TO_OBJECT(val);
+	if(JS_GetProperty(session->js_cx,reply,"status",&val))
+		JSVALUE_TO_STRBUF(session->js_cx, val, session->req.status, sizeof(session->req.status), NULL);
+	if(JS_GetProperty(session->js_cx,reply,"header",&val)) {
+		headers = JSVAL_TO_OBJECT(val);
+		heads=JS_Enumerate(session->js_cx,headers);
+	}
 	if(heads != NULL) {
 		for(i=0;i<heads->length;i++)  {
 			JS_IdToValue(session->js_cx,heads->vector[i],&val);
@@ -5868,8 +5871,8 @@ static BOOL ssjs_send_headers(http_session_t* session,int chunked)
 					free(p2);
 				return FALSE;
 			}
-			JS_GetProperty(session->js_cx,headers,p,&val);
-			JSVALUE_TO_RASTRING(session->js_cx, val, p2, &p2_sz, NULL);
+			if(JS_GetProperty(session->js_cx,headers,p,&val))
+				JSVALUE_TO_RASTRING(session->js_cx, val, p2, &p2_sz, NULL);
 			if(JS_IsExceptionPending(session->js_cx)) {
 				if(p)
 					free(p);
diff --git a/src/sbbs3/writemsg.cpp b/src/sbbs3/writemsg.cpp
index 67c0d9d33110fc7c6a73da10e5cbe89fb8a494fe..6b748a7e09c29f9742cbe5a4b54bcb565934e888 100644
--- a/src/sbbs3/writemsg.cpp
+++ b/src/sbbs3/writemsg.cpp
@@ -78,7 +78,7 @@ bool sbbs_t::quotemsg(smb_t* smb, smbmsg_t* msg, bool tails)
 		useron_xedit = 0;
 
 	quotes_fname(useron_xedit,fname,sizeof(fname));
-	removecase(fname);
+	(void)removecase(fname);
 
 	if((fp=fopen(fname,"wb"))==NULL) {
 		errormsg(WHERE,ERR_OPEN,fname,0);
@@ -300,9 +300,9 @@ bool sbbs_t::writemsg(const char *fname, const char *top, char *subj, long mode,
 		mode|=WM_NOTOP;
 
 	msg_tmp_fname(useron_xedit, msgtmp, sizeof(msgtmp));
-	removecase(msgtmp);
+	(void)removecase(msgtmp);
 	SAFEPRINTF(tagfile,"%seditor.tag",cfg.temp_dir);
-	removecase(tagfile);
+	(void)removecase(tagfile);
 	SAFEPRINTF(draft_desc, "draft.%s.msg", subnum >= cfg.total_subs ? "mail" : cfg.sub[subnum]->code);
 	SAFEPRINTF3(draft, "%suser/%04u.%s", cfg.data_dir, useron.number, draft_desc);
 
@@ -311,7 +311,7 @@ bool sbbs_t::writemsg(const char *fname, const char *top, char *subj, long mode,
 		if(mv(draft, msgtmp, /* copy: */true) == 0) {
 			lprintf(LOG_NOTICE, "draft message restored: %s (%lu bytes)", draft, (ulong)flength(msgtmp));
 			draft_restored = true;
-			removecase(quotes_fname(useron_xedit, str, sizeof(str)));
+			(void)removecase(quotes_fname(useron_xedit, str, sizeof(str)));
 		} else
 			lprintf(LOG_ERR, "ERROR %d (%s) restoring draft message: %s", errno, strerror(errno), draft);
 	}
@@ -456,7 +456,7 @@ bool sbbs_t::writemsg(const char *fname, const char *top, char *subj, long mode,
 		} 
 	}
 	else {
-		removecase(quotes_fname(useron_xedit, str, sizeof(str)));
+		(void)removecase(quotes_fname(useron_xedit, str, sizeof(str)));
 	}
 
 	if(!online || sys_status&SS_ABORT) {
@@ -575,7 +575,7 @@ bool sbbs_t::writemsg(const char *fname, const char *top, char *subj, long mode,
 
 		if(!draft_restored) {
 			if(!linesquoted)
-				removecase(msgtmp);
+				(void)removecase(msgtmp);
 			else {
 				qlen=(long)flength(msgtmp);
 				qtime=(long)fdate(msgtmp); 
@@ -678,7 +678,7 @@ bool sbbs_t::writemsg(const char *fname, const char *top, char *subj, long mode,
 
 	now=time(NULL);
 	bputs(text[Saving]);
-	removecase(fname);
+	(void)removecase(fname);
 	if((stream=fnopen(NULL,fname,O_WRONLY|O_CREAT|O_TRUNC))==NULL) {
 		errormsg(WHERE,ERR_OPEN,fname,O_WRONLY|O_CREAT|O_TRUNC);
 		free(buf);
@@ -736,7 +736,7 @@ bool sbbs_t::writemsg(const char *fname, const char *top, char *subj, long mode,
 		}
 	}
 
-	remove(draft);
+	(void)remove(draft);
 	fclose(stream);
 	free((char *)buf);
 	bprintf(text[SavedNBytes],l,lines);
@@ -781,10 +781,10 @@ void sbbs_t::editor_inf(int xeditnum, const char *to, const char* from, const ch
 	xeditnum--;
 
 	SAFEPRINTF(path,"%sresult.ed",cfg.node_dir);
-	removecase(path);
+	(void)removecase(path);
 	if(cfg.xedit[xeditnum]->misc&QUICKBBS) {
 		SAFEPRINTF2(path,"%s%s",cfg.node_dir, cfg.xedit[xeditnum]->misc&XTRN_LWRCASE ? "msginf":"MSGINF");
-		removecase(path);
+		(void)removecase(path);
 		if((fp=fopen(path,"wb"))==NULL) {
 			errormsg(WHERE,ERR_OPEN,path,O_WRONLY|O_CREAT|O_TRUNC);
 			return; 
@@ -804,7 +804,7 @@ void sbbs_t::editor_inf(int xeditnum, const char *to, const char* from, const ch
 	}
 	else {
 		SAFEPRINTF2(path,"%s%s",cfg.node_dir,cfg.xedit[xeditnum]->misc&XTRN_LWRCASE ? "editor.inf" : "EDITOR.INF");
-		removecase(path);
+		(void)removecase(path);
 		if((fp=fopen(path,"wb"))==NULL) {
 			errormsg(WHERE,ERR_OPEN,path,O_WRONLY|O_CREAT|O_TRUNC);
 			return; 
@@ -1123,7 +1123,7 @@ ulong sbbs_t::msgeditor(char *buf, const char *top, char *title)
 				upload:
 				char	fname[MAX_PATH + 1];
 				SAFEPRINTF(fname, "%sUPLOAD.MSG", cfg.temp_dir);
-				removecase(fname);
+				(void)removecase(fname);
 				if(!recvfile(fname, prot, /* autohang: */false)) {
 					bprintf(text[FileNotReceived], "File");
 					continue;
@@ -1210,7 +1210,7 @@ bool sbbs_t::editfile(char *fname, bool msg)
 	else
 		maxlines=MAX_LINES;
 	quotes_fname(useron_xedit, path, sizeof(path));
-	removecase(path);
+	(void)removecase(path);
 
 	if(useron_xedit) {
 
@@ -1218,7 +1218,8 @@ bool sbbs_t::editfile(char *fname, bool msg)
 
 		msg_tmp_fname(useron_xedit, msgtmp, sizeof(msgtmp));
 		if(stricmp(msgtmp,path)) {
-			removecase(msgtmp);
+			if(removecase(msgtmp) != 0)
+				errormsg(WHERE, ERR_REMOVE, msgtmp, 0);
 			if(fexistcase(path))
 				CopyFile(path, msgtmp, /* failIfExists: */FALSE);
 		}
@@ -1246,8 +1247,8 @@ bool sbbs_t::editfile(char *fname, bool msg)
 		rioctl(IOSM|PAUSE|ABORT); 
 		return true; 
 	}
-	if((buf=(char *)malloc(maxlines*MAX_LINE_LEN))==NULL) {
-		errormsg(WHERE,ERR_ALLOC,nulstr,maxlines*MAX_LINE_LEN);
+	if((buf=(char *)malloc((maxlines*MAX_LINE_LEN) + 1))==NULL) {
+		errormsg(WHERE,ERR_ALLOC,nulstr, (maxlines*MAX_LINE_LEN) + 1);
 		return false; 
 	}
 	if((file=nopen(fname,O_RDONLY))!=-1) {
@@ -1589,7 +1590,8 @@ bool sbbs_t::editmsg(smb_t* smb, smbmsg_t *msg)
 		return false;
 
 	msg_tmp_fname(useron.xedit, msgtmp, sizeof(msgtmp));
-	removecase(msgtmp);
+	if(removecase(msgtmp) != 0)
+		return false;
 	msgtotxt(smb, msg, msgtmp, /* header: */false, /* mode: */GETMSGTXT_ALL);
 	if(!editfile(msgtmp, /* msg: */true))
 		return false;
diff --git a/src/sbbs3/xtrn.cpp b/src/sbbs3/xtrn.cpp
index 9f39b4d633ec903a13e2e2c33037a60c7b8a43ec..e79970ee1e8a59eac0c14d16eb3c519dc7ae168a 100644
--- a/src/sbbs3/xtrn.cpp
+++ b/src/sbbs3/xtrn.cpp
@@ -18,6 +18,7 @@
  *																			*
  * Note: If this box doesn't appear square, then you need to fix your tabs.	*
  ****************************************************************************/
+
 #include "sbbs.h"
 #include "cmdshell.h"
 #include "telnet.h"
@@ -445,11 +446,11 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
 		GetShortPathName(cfg.data_dir,data_dir,sizeof(data_dir));
 		GetShortPathName(cfg.exec_dir,exec_dir,sizeof(exec_dir));
 
-		sprintf(path,"%sDOSXTRN.RET", cfg.node_dir);
-		remove(path);
+		SAFEPRINTF(path,"%sDOSXTRN.RET", cfg.node_dir);
+		(void)remove(path);
 
     	// Create temporary environment file
-    	sprintf(path,"%sDOSXTRN.ENV", node_dir);
+    	SAFEPRINTF(path,"%sDOSXTRN.ENV", node_dir);
         FILE* fp=fopen(path,"w");
         if(fp==NULL) {
 			XTRN_CLEANUP;
@@ -554,6 +555,7 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
 		// Create the child output pipe (override default 4K buffer size)
 		if(!CreatePipe(&rdoutpipe,&startup_info.hStdOutput,&sa,sizeof(buf))) {
 			errormsg(WHERE,ERR_CREATE,"stdout pipe",0);
+			strListFreeBlock(env_block);
 			return(GetLastError());
 		}
 		startup_info.hStdError=startup_info.hStdOutput;
@@ -561,6 +563,8 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
 		// Create the child input pipe.
 		if(!CreatePipe(&startup_info.hStdInput,&wrinpipe,&sa,sizeof(buf))) {
 			errormsg(WHERE,ERR_CREATE,"stdin pipe",0);
+			CloseHandle(rdoutpipe);
+			strListFreeBlock(env_block);
 			return(GetLastError());
 		}
 
@@ -830,7 +834,10 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
     		sprintf(str,"%sDOSXTRN.RET", cfg.node_dir);
 			FILE* fp=fopen(str,"r");
 			if(fp!=NULL) {
-				fscanf(fp,"%d",&retval);
+				if(fscanf(fp,"%d",&retval) != 1) {
+					lprintf(LOG_ERR, "Node %d Error reading return value from %s", cfg.node_num, str);
+					retval = -1;
+				}
 				fclose(fp);
 			}
 		}
diff --git a/src/sbbs3/xtrn_sec.cpp b/src/sbbs3/xtrn_sec.cpp
index 859e5e2b69626a8178037c95306e634964e2a415..2ee165883fd27925e60b07cbfea35281b2dc51ae 100644
--- a/src/sbbs3/xtrn_sec.cpp
+++ b/src/sbbs3/xtrn_sec.cpp
@@ -193,7 +193,7 @@ void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tl
 		if(misc&XTRN_LWRCASE)
 			strlwr(tmp);
 		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
-		removecase(str);
+		(void)removecase(str);
 		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT))==-1) {
 			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
 			return; 
@@ -307,7 +307,7 @@ void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tl
 		if(misc&XTRN_LWRCASE)
 			strlwr(tmp);
 		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
-		removecase(str);
+		(void)removecase(str);
 		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT))==-1) {
 			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
 			return; 
@@ -368,7 +368,7 @@ void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tl
 		if(misc&XTRN_LWRCASE)
 			strlwr(tmp);
 		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
-		removecase(str);
+		(void)removecase(str);
 		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT))==-1) {
 			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
 			return; 
@@ -493,7 +493,7 @@ void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tl
 		if(misc&XTRN_LWRCASE)
 			strlwr(tmp);
 		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
-		removecase(str);
+		(void)removecase(str);
 		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT))==-1) {
 			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
 			return; 
@@ -540,7 +540,7 @@ void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tl
 		if(misc&XTRN_LWRCASE)
 			strlwr(tmp);
 		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
-		removecase(str);
+		(void)removecase(str);
 		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
 			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
 			return; 
@@ -677,7 +677,7 @@ void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tl
 		if(misc&XTRN_LWRCASE)
 			strlwr(tmp);
 		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
-		removecase(str);
+		(void)removecase(str);
 		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT))==-1) {
 			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
 			return; 
@@ -789,7 +789,7 @@ void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tl
 		if(misc&XTRN_LWRCASE)
 			strlwr(tmp);
 		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
-		removecase(str);
+		(void)removecase(str);
 		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
 			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
 			return; 
@@ -890,7 +890,7 @@ void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tl
 		if(misc&XTRN_LWRCASE)
 			strlwr(tmp);
 		safe_snprintf(str, sizeof(str), "%s%s",dropdir,tmp);
-		removecase(str);
+		(void)removecase(str);
 		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
 			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
 			return; 
@@ -997,7 +997,7 @@ void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tl
 		if(misc&XTRN_LWRCASE)
 			strlwr(tmp);
 		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
-		removecase(str);
+		(void)removecase(str);
 		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT))==-1) {
 			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
 			return; 
@@ -1072,7 +1072,7 @@ void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tl
 		if(misc&XTRN_LWRCASE)
 			strlwr(tmp);
 		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
-		removecase(str);
+		(void)removecase(str);
 		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT))==-1) {
 			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
 			return; 
@@ -1097,7 +1097,7 @@ void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tl
 		if(misc&XTRN_LWRCASE)
 			strlwr(tmp);
 		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
-		removecase(str);
+		(void)removecase(str);
 		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT))==-1) {
 			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
 			return; 
@@ -1122,7 +1122,7 @@ void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tl
 		if(misc&XTRN_LWRCASE)
 			strlwr(tmp);
 		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
-		removecase(str);
+		(void)removecase(str);
 		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT))==-1) {
 			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
 			return; 
@@ -1164,7 +1164,7 @@ void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tl
 		if(misc&XTRN_LWRCASE)
 			strlwr(tmp);
 		SAFEPRINTF2(str, "%s%s",dropdir,tmp);
-		removecase(str);
+		(void)removecase(str);
 		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT))==-1) {
 			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
 			return; 
@@ -1576,9 +1576,9 @@ bool sbbs_t::exec_xtrn(uint xtrnnum)
 	}
 
 	SAFEPRINTF(str,"%shangup.now",cfg.node_dir);
-	removecase(str);
+	(void)removecase(str);
 	SAFEPRINTF2(str,"%sfile/%04u.dwn",cfg.data_dir,useron.number);
-	removecase(str);
+	(void)removecase(str);
 
 	mode=0; 	
 	if(cfg.xtrn[xtrnnum]->misc&XTRN_SH)
@@ -1590,7 +1590,7 @@ bool sbbs_t::exec_xtrn(uint xtrnnum)
 	mode|=(cfg.xtrn[xtrnnum]->misc&(XTRN_CHKTIME|XTRN_NATIVE|XTRN_NOECHO|WWIVCOLOR));
 	if(cfg.xtrn[xtrnnum]->misc&MODUSERDAT) {		/* Delete MODUSER.DAT */
 		SAFEPRINTF(str,"%sMODUSER.DAT",dropdir);	/* if for some weird  */
-		removecase(str);							/* reason it's there  */
+		(void)removecase(str);						/* reason it's there  */
 	}
 
 	char drop_file[MAX_PATH + 1];
@@ -1636,7 +1636,7 @@ bool sbbs_t::exec_xtrn(uint xtrnnum)
 	if(fexistcase(str)) {
 		lprintf(LOG_NOTICE,"Node %d External program requested hangup (%s signaled)"
 			,cfg.node_num, str);
-		removecase(str);
+		(void)removecase(str);
 		hangup(); 
 	}
 	else if(!online) {
diff --git a/src/smblib/smblib.c b/src/smblib/smblib.c
index d0ce6c6334d02a5c72e9123d6e268355a1529753..4501968541b454fb79d7bad328dddfe87043ca9b 100644
--- a/src/smblib/smblib.c
+++ b/src/smblib/smblib.c
@@ -1707,7 +1707,7 @@ BOOL SMBCALL smb_msg_is_utf8(const smbmsg_t* msg)
 uint16_t SMBCALL smb_voted_already(smb_t* smb, uint32_t msgnum, const char* name, enum smb_net_type net_type, void* net_addr)
 {
 	uint16_t votes = 0;
-	smbmsg_t msg;
+	smbmsg_t msg = {0};
 
 	if(smb->sid_fp==NULL) {
 		safe_snprintf(smb->last_error, sizeof(smb->last_error), "%s index not open", __FUNCTION__);
diff --git a/src/xpdev/dirwrap.c b/src/xpdev/dirwrap.c
index f084c44339406b518ffc4459c939b542079a4ada..ca2f10ba4090ebc15b01021518b2cfc491fab7f4 100644
--- a/src/xpdev/dirwrap.c
+++ b/src/xpdev/dirwrap.c
@@ -764,7 +764,7 @@ long DLLCALL delfiles(const char *inpath, const char *spec, size_t keep)
 	for(i = 0; i < g.gl_pathc && files < g.gl_pathc - keep; i++) {
 		if(isdir(g.gl_pathv[i]))
 			continue;
-		CHMOD(g.gl_pathv[i],S_IWRITE);	/* In case it's been marked RDONLY */
+		(void)CHMOD(g.gl_pathv[i],S_IWRITE);	/* In case it's been marked RDONLY */
 		if(remove(g.gl_pathv[i])==0)
 			files++;
 		else
diff --git a/src/xpdev/filewrap.c b/src/xpdev/filewrap.c
index 15922e61b51d2ea778b860a08635bde2b9a5dcc8..62c1670a59dd0ae032765205d7bcba50826845ba 100644
--- a/src/xpdev/filewrap.c
+++ b/src/xpdev/filewrap.c
@@ -1,9 +1,5 @@
-/* filewrap.c */
-
 /* File-related system-call wrappers */
 
-/* $Id: filewrap.c,v 1.50 2019/08/31 20:59:39 rswindell Exp $ */
-
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
@@ -17,21 +13,9 @@
  * 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 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.	*
  ****************************************************************************/
 
@@ -283,10 +267,10 @@ int lock(int file, off_t offset, off_t size)
    
 	pos=tell(file);
 	if(offset!=pos)
-		lseek(file, offset, SEEK_SET);
+		(void)lseek(file, offset, SEEK_SET);
 	i=_locking(file,LK_NBLCK,(long)size);
 	if(offset!=pos)
-		lseek(file, pos, SEEK_SET);
+		(void)lseek(file, pos, SEEK_SET);
 	return(i);
 }
 
@@ -297,10 +281,10 @@ int unlock(int file, off_t offset, off_t size)
    
 	pos=tell(file);
 	if(offset!=pos)
-		lseek(file, offset, SEEK_SET);
+		(void)lseek(file, offset, SEEK_SET);
 	i=_locking(file,LK_UNLCK,(long)size);
 	if(offset!=pos)
-		lseek(file, pos, SEEK_SET);
+		(void)lseek(file, pos, SEEK_SET);
 	return(i);
 }
 
diff --git a/src/xpdev/gen_defs.h b/src/xpdev/gen_defs.h
index ecbd93a3a62b566d371bca466a63a5ae06f39be3..f59cfb498c2598543f412e69487a78d19185c28b 100644
--- a/src/xpdev/gen_defs.h
+++ b/src/xpdev/gen_defs.h
@@ -420,7 +420,7 @@ typedef struct {
 #ifdef SAFECOPY_USES_SPRINTF
 #define SAFECOPY(dst,src)                   sprintf(dst,"%.*s",(int)sizeof(dst)-1,src)
 #else   /* strncpy is faster */
-#define SAFECOPY(dst,src)                   (strncpy(dst,src,sizeof(dst)), TERMINATE(dst))
+#define SAFECOPY(dst,src)                   (strncpy(dst,(src)==NULL?"(null)":(src),sizeof(dst)), TERMINATE(dst))
 #endif
 
 #define SAFECAT(dst, src) do { \
diff --git a/src/xpdev/link_list.c b/src/xpdev/link_list.c
index 25ba010c7cc9f00765e98f0612307e73340c87d0..a9cb941d52802413f53e602e41b96f5c580bd0e6 100644
--- a/src/xpdev/link_list.c
+++ b/src/xpdev/link_list.c
@@ -1,7 +1,5 @@
 /* Double-Linked-list library */
 
-/* $Id: link_list.c,v 1.64 2019/08/04 19:38:53 rswindell Exp $ */
-
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
@@ -15,21 +13,9 @@
  * 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 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.	*
  ****************************************************************************/
 
@@ -45,11 +31,8 @@
 
 link_list_t* DLLCALL listInit(link_list_t* list, long flags)
 {
-	if((flags&LINK_LIST_MALLOC) || list==NULL) {
-		if((list=(link_list_t*)malloc(sizeof(link_list_t)))==NULL)
-			return(NULL);
-		flags |= LINK_LIST_MALLOC;
-	}
+	if(list == NULL)
+		return NULL;
 
 	memset(list,0,sizeof(link_list_t));
 
@@ -140,9 +123,6 @@ BOOL DLLCALL listFree(link_list_t* list)
 	}
 #endif
 
-	if(list->flags&LINK_LIST_MALLOC)
-		free(list);
-
 	return(TRUE);
 }
 
diff --git a/src/xpdev/link_list.h b/src/xpdev/link_list.h
index df74da4b276421645b247d43026406309bf2cb03..1360ed3d3e6e9d1cc1501582787f03028cb21e4b 100644
--- a/src/xpdev/link_list.h
+++ b/src/xpdev/link_list.h
@@ -1,7 +1,5 @@
 /* Double-Linked-list library */
 
-/* $Id: link_list.h,v 1.29 2019/08/02 02:36:28 rswindell Exp $ */
-
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
@@ -15,21 +13,9 @@
  * 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 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.	*
  ****************************************************************************/
 
@@ -53,7 +39,7 @@ extern "C" {
 #define LAST_NODE				((list_node_t*)-1)		/* Special value to specify last node in list */
 
 /* Valid link_list_t.flags and list_node_t.flags bits */
-#define LINK_LIST_MALLOC		(1<<0)	/* List/node allocated with malloc() */
+#define LINK_LIST_MALLOC		(1<<0)	/* Node data allocated with malloc() */
 #define LINK_LIST_ALWAYS_FREE	(1<<1)	/* ALWAYS free node data in listFreeNodes() */
 #define LINK_LIST_NEVER_FREE	(1<<2)	/* NEVER free node data (careful of memory leaks!) */
 #define LINK_LIST_MUTEX			(1<<3)	/* Mutex-protected linked-list */
diff --git a/src/xpdev/xpmap.c b/src/xpdev/xpmap.c
index 3987903da159b9499c555c52ce67044b61599463..065d58356375016dd99ff0361885b16ca8010ef4 100644
--- a/src/xpdev/xpmap.c
+++ b/src/xpdev/xpmap.c
@@ -1,9 +1,5 @@
-/* xpmap.c */
-
 /* mmap() style cross-platform development wrappers */
 
-/* $Id: xpmap.c,v 1.8 2018/07/24 01:13:10 rswindell Exp $ */
-
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
@@ -17,21 +13,9 @@
  * 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 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.	*
  ****************************************************************************/
 
@@ -147,8 +131,10 @@ struct xpmapping* DLLCALL xpmap(const char *filename, enum xpmap_type type)
 		return NULL;
 	addr=MapViewOfFile(md, maccess, 0, 0, size);
 	ret=(struct xpmapping *)malloc(sizeof(struct xpmapping));
-	if(ret==NULL)
+	if(ret==NULL) {
+		CloseHandle(md);
 		return NULL;
+	}
 	ret->addr=addr;
 	ret->fd=(HANDLE)fd;
 	ret->md=md;