diff --git a/src/sbbs3/baja.c b/src/sbbs3/baja.c
index d734d1f4f5852acd5fa3b60538c9e1f7858c5e7f..7a14d26116798af2e4b3bee04cfecb96c1eb74b7 100644
--- a/src/sbbs3/baja.c
+++ b/src/sbbs3/baja.c
@@ -314,7 +314,7 @@ void newvar(char* src, char *in)
 		if(i<vars)
 			return;
 	}
-	if((var_name=(uint32_t *)realloc(var_name,sizeof(int32_t)*(vars+1)))==NULL) {
+	if((var_name=(uint32_t *)realloc_or_free(var_name,sizeof(int32_t)*(vars+1)))==NULL) {
 		printf("Too many (%"PRIu32") variables!\n",vars);
 		bail(1); }
 	var_name[vars]=l;
@@ -522,14 +522,14 @@ void compile(char *src)
 			if(sp)
 				*sp=0;
 			truncsp(arg2);
-			if((define_str=(char **)realloc(define_str,sizeof(char *)*(defines+1)))
+			if((define_str=(char **)realloc_or_free(define_str,sizeof(char *)*(defines+1)))
 				==NULL) {
 				printf("Too many defines.\n");
 				bail(1); }
 			if((define_str[defines]=(char *)malloc(strlen(arg)+1))==NULL) {
 				printf("Too many defines.\n");
 				bail(1); }
-			if((define_val=(char **)realloc(define_val,sizeof(char *)*(defines+1)))
+			if((define_val=(char **)realloc_or_free(define_val,sizeof(char *)*(defines+1)))
 				==NULL) {
 				printf("Too many defines.\n");
 				bail(1); }
@@ -721,11 +721,11 @@ void compile(char *src)
 				printf("!SYNTAX ERROR (duplicate label name):\n");
 				printf(linestr,src,line,p);
 				bail(1); }
-			if((label_name=(char **)realloc(label_name,sizeof(char *)*(labels+1)))
+			if((label_name=(char **)realloc_or_free(label_name,sizeof(char *)*(labels+1)))
 				==NULL) {
 				printf("Too many labels.\n");
 				bail(1); }
-			if((label_indx=(uint *)realloc(label_indx,sizeof(int)*(labels+1)))
+			if((label_indx=(uint *)realloc_or_free(label_indx,sizeof(int)*(labels+1)))
 				==NULL) {
 				printf("Too many labels.\n");
 				bail(1); }
@@ -741,19 +741,19 @@ void compile(char *src)
 			sp=strchr(arg,' ');
 			if(sp)
 				*sp=0;
-			if((goto_label=(char **)realloc(goto_label,sizeof(char *)*(gotos+1)))
+			if((goto_label=(char **)realloc_or_free(goto_label,sizeof(char *)*(gotos+1)))
 				==NULL) {
 				printf("Too many gotos.\n");
 				bail(1); }
-			if((goto_file=(char **)realloc(goto_file,sizeof(char *)*(gotos+1)))
+			if((goto_file=(char **)realloc_or_free(goto_file,sizeof(char *)*(gotos+1)))
 				==NULL) {
 				printf("Too many gotos.\n");
 				bail(1); }
-			if((goto_indx=(uint *)realloc(goto_indx,sizeof(int)*(gotos+1)))
+			if((goto_indx=(uint *)realloc_or_free(goto_indx,sizeof(int)*(gotos+1)))
 				==NULL) {
 				printf("Too many gotos.\n");
 				bail(1); }
-			if((goto_line=(uint *)realloc(goto_line,sizeof(int)*(gotos+1)))
+			if((goto_line=(uint *)realloc_or_free(goto_line,sizeof(int)*(gotos+1)))
 				==NULL) {
 				printf("Too many gotos.\n");
 				bail(1); }
@@ -775,19 +775,19 @@ void compile(char *src)
 			sp=strchr(arg,' ');
 			if(sp)
 				*sp=0;
-			if((call_label=(char **)realloc(call_label,sizeof(char *)*(calls+1)))
+			if((call_label=(char **)realloc_or_free(call_label,sizeof(char *)*(calls+1)))
 				==NULL) {
 				printf("Too many calls.\n");
 				bail(1); }
-			if((call_file=(char **)realloc(call_file,sizeof(char *)*(calls+1)))
+			if((call_file=(char **)realloc_or_free(call_file,sizeof(char *)*(calls+1)))
 				==NULL) {
 				printf("Too many calls.\n");
 				bail(1); }
-			if((call_indx=(uint *)realloc(call_indx,sizeof(int)*(calls+1)))
+			if((call_indx=(uint *)realloc_or_free(call_indx,sizeof(int)*(calls+1)))
 				==NULL) {
 				printf("Too many calls.\n");
 				bail(1); }
-			if((call_line=(uint *)realloc(call_line,sizeof(int)*(calls+1)))
+			if((call_line=(uint *)realloc_or_free(call_line,sizeof(int)*(calls+1)))
 				==NULL) {
 				printf("Too many calls.\n");
 				bail(1); }
diff --git a/src/sbbs3/dupefind.c b/src/sbbs3/dupefind.c
index cc3ab002771cd7f3cca5f18fc8af0c9c7e0cbb5e..343ba4f90702bb835ccdde2aaff49a352c7c35e6 100644
--- a/src/sbbs3/dupefind.c
+++ b/src/sbbs3/dupefind.c
@@ -196,7 +196,7 @@ int main(int argc,char **argv)
 							}
 							if(g==total_found) {
 								++total_found;
-								if((foundcrc = realloc(foundcrc
+								if((foundcrc = realloc_or_free(foundcrc
 									,total_found*sizeof(uint32_t)))==NULL) {
 									printf("Out of memory reallocating\r\n");
 									return(1); 
diff --git a/src/sbbs3/execmisc.cpp b/src/sbbs3/execmisc.cpp
index bd5883f2112d6a5c97759f4ffc3f88a569e48564..61131f49cbcddba9d87b3882546e9fac6aa68251 100644
--- a/src/sbbs3/execmisc.cpp
+++ b/src/sbbs3/execmisc.cpp
@@ -117,9 +117,9 @@ int sbbs_t::exec_misc(csi_t* csi, const char *path)
 						return(0);
 					}
 					csi->str_vars++;
-					csi->str_var=(char **)realloc(csi->str_var
+					csi->str_var=(char **)realloc_or_free(csi->str_var
 						,sizeof(char *)*csi->str_vars);
-					csi->str_var_name=(uint32_t *)realloc(csi->str_var_name
+					csi->str_var_name=(uint32_t *)realloc_or_free(csi->str_var_name
 						,sizeof(int32_t)*csi->str_vars);
 					if(csi->str_var==NULL
 						|| csi->str_var_name==NULL) { /* REALLOC failed */
@@ -147,9 +147,9 @@ int sbbs_t::exec_misc(csi_t* csi, const char *path)
 						return(0);
 					}
 					csi->int_vars++;
-					csi->int_var=(int32_t *)realloc(csi->int_var
+					csi->int_var=(int32_t *)realloc_or_free(csi->int_var
 						,sizeof(char *)*csi->int_vars);
-					csi->int_var_name=(uint32_t *)realloc(csi->int_var_name
+					csi->int_var_name=(uint32_t *)realloc_or_free(csi->int_var_name
 						,sizeof(int32_t)*csi->int_vars);
 					if(csi->int_var==NULL
 						|| csi->int_var_name==NULL) { /* REALLOC failed */
@@ -177,9 +177,9 @@ int sbbs_t::exec_misc(csi_t* csi, const char *path)
 						return(0);
 					}
 					global_str_vars++;
-					global_str_var=(char **)realloc(global_str_var
+					global_str_var=(char **)realloc_or_free(global_str_var
 						,sizeof(char *)*global_str_vars);
-					global_str_var_name=(uint32_t *)realloc(global_str_var_name
+					global_str_var_name=(uint32_t *)realloc_or_free(global_str_var_name
 						,sizeof(int32_t)*global_str_vars);
 					if(global_str_var==NULL
 						|| global_str_var_name==NULL) { /* REALLOC failed */
@@ -208,9 +208,9 @@ int sbbs_t::exec_misc(csi_t* csi, const char *path)
 						return(0);
 					}
 					global_int_vars++;
-					global_int_var=(int32_t *)realloc(global_int_var
+					global_int_var=(int32_t *)realloc_or_free(global_int_var
 						,sizeof(char *)*global_int_vars);
-					global_int_var_name=(uint32_t *)realloc(global_int_var_name
+					global_int_var_name=(uint32_t *)realloc_or_free(global_int_var_name
 						,sizeof(int32_t)*global_int_vars);
 					if(global_int_var==NULL
 						|| global_int_var_name==NULL) { /* REALLOC failed */
@@ -470,9 +470,9 @@ int sbbs_t::exec_misc(csi_t* csi, const char *path)
 								break;
 					if(pp && *pp!=csi->str && i==MAX_SYSVARS) {
 						if(*pp)
-							*pp=(char *)realloc(*pp,strlen(*pp)+strlen(tmp)+1);
+							*pp=(char *)realloc_or_free(*pp,strlen(*pp)+strlen(tmp)+1);
 						else
-							*pp=(char *)realloc(*pp,strlen(tmp)+1);
+							*pp=(char *)realloc_or_free(*pp,strlen(tmp)+1);
 					}
 					if(pp && *pp)
 						strcat(*pp,tmp);
@@ -499,9 +499,9 @@ int sbbs_t::exec_misc(csi_t* csi, const char *path)
 									break;
 						if(pp && *pp!=csi->str && i==MAX_SYSVARS) {
 							if(*pp)
-								*pp=(char *)realloc(*pp,strlen(*pp)+strlen(tmp)+1);
+								*pp=(char *)realloc_or_free(*pp,strlen(*pp)+strlen(tmp)+1);
 							else
-								*pp=(char *)realloc(*pp,strlen(tmp)+1);
+								*pp=(char *)realloc_or_free(*pp,strlen(tmp)+1);
 						}
 						if(pp && *pp)
 							strcat(*pp,tmp);
@@ -519,9 +519,9 @@ int sbbs_t::exec_misc(csi_t* csi, const char *path)
 								break;
 					if(*pp1!=csi->str && (!*pp1 || i==MAX_SYSVARS)) {
 						if(*pp1)
-							*pp1=(char *)realloc(*pp1,strlen(*pp1)+strlen(*pp2)+1);
+							*pp1=(char *)realloc_or_free(*pp1,strlen(*pp1)+strlen(*pp2)+1);
 						else
-							*pp1=(char *)realloc(*pp1,strlen(*pp2)+1);
+							*pp1=(char *)realloc_or_free(*pp1,strlen(*pp2)+1);
 					}
 					if(*pp1 != NULL)
 						strcat(*pp1,*pp2);
diff --git a/src/sbbs3/fixsmb.c b/src/sbbs3/fixsmb.c
index 54e8420cd48eb138078e681f1cdc738e074db269..3c1b9c12ffe90a3e28c93b52ee34ff80c44ba241 100644
--- a/src/sbbs3/fixsmb.c
+++ b/src/sbbs3/fixsmb.c
@@ -232,7 +232,7 @@ int fixsmb(char* sub)
 		}
 		if(!dupe_msgnum) {
 			total++;
-			if((numbers = realloc(numbers, total * sizeof(*numbers))) == NULL) {
+			if((numbers = realloc_or_free(numbers, total * sizeof(*numbers))) == NULL) {
 				fprintf(stderr, "realloc failure: %lu\n", total * sizeof(*numbers));
 				return EXIT_FAILURE;
 			}
diff --git a/src/sbbs3/jsexec.c b/src/sbbs3/jsexec.c
index 6ca4fd6a099e982c572f338d5ee6adc226abb7bc..800909b4420897c54b90ff757e4f1313148c1949 100644
--- a/src/sbbs3/jsexec.c
+++ b/src/sbbs3/jsexec.c
@@ -1043,7 +1043,7 @@ long js_exec(const char *fname, const char* buf, char** args)
 			if(line_no==1 && strncmp(line,"#!",2)==0)
 				strcpy(line,"\n");	/* To keep line count correct */
 			len=strlen(line);
-			if((js_buf=realloc(js_buf,js_buflen+len))==NULL) {
+			if((js_buf=realloc_or_free(js_buf,js_buflen+len))==NULL) {
 				lprintf(LOG_ERR,"!Error allocating %lu bytes of memory"
 					,(ulong)(js_buflen+len));
 				if(fp!=stdin)
diff --git a/src/sbbs3/qwk.cpp b/src/sbbs3/qwk.cpp
index 336c69d02c6a46eb13c1baa85691c9f99103e23e..28c9a3b0083064467cdd94fa2604437ab389a752 100644
--- a/src/sbbs3/qwk.cpp
+++ b/src/sbbs3/qwk.cpp
@@ -217,7 +217,7 @@ void sbbs_t::update_qwkroute(char *via)
 				if(i<total_qwknodes && qwknode[i].time>t)
 					continue;
 				if(i==total_qwknodes) {
-					if((qwknode=(struct qwknode*)realloc(qwknode,sizeof(struct qwknode)*(i+1)))==NULL) {
+					if((qwknode=(struct qwknode*)realloc_or_free(qwknode,sizeof(struct qwknode)*(i+1)))==NULL) {
 						errormsg(WHERE,ERR_ALLOC,via,sizeof(struct qwknode)*(i+1));
 						break;
 					}
@@ -249,7 +249,7 @@ void sbbs_t::update_qwkroute(char *via)
 			if(!stricmp(qwknode[i].id,node))
 				break;
 		if(i==total_qwknodes) {		/* Not in list */
-			if((qwknode=(struct qwknode*)realloc(qwknode,sizeof(struct qwknode)*(total_qwknodes+1)))==NULL) {
+			if((qwknode=(struct qwknode*)realloc_or_free(qwknode,sizeof(struct qwknode)*(total_qwknodes+1)))==NULL) {
 				errormsg(WHERE,ERR_ALLOC,node,sizeof(struct qwknode)*(total_qwknodes+1));
 				break;
 			}
diff --git a/src/sbbs3/qwknodes.c b/src/sbbs3/qwknodes.c
index 904115d1895a7e5aa56ae66c3c0b49b35a0df626..a20faa60f08a04f248d94ae6ee43e098060a741e 100644
--- a/src/sbbs3/qwknodes.c
+++ b/src/sbbs3/qwknodes.c
@@ -314,7 +314,7 @@ int main(int argc, char **argv)
 						break;
 				if(l==total_crcs) {
 					total_crcs++;
-					if((crc=(uint32_t *)realloc(crc
+					if((crc=(uint32_t *)realloc_or_free(crc
 						,sizeof(uint32_t)*total_crcs))==NULL) {
 						printf("Error allocating %lu bytes\n"
 							,sizeof(uint32_t)*total_crcs);
diff --git a/src/sbbs3/rechocfg.c b/src/sbbs3/rechocfg.c
index d0e03f2b108c21b559861db1cc203a9e77b4314e..b74552379efb7b007ce204d96efd0823f4e966bc 100644
--- a/src/sbbs3/rechocfg.c
+++ b/src/sbbs3/rechocfg.c
@@ -324,7 +324,7 @@ bool sbbsecho_read_ini(sbbsecho_cfg_t* cfg)
 	/******************/
 	str_list_t archivelist = iniGetSectionList(ini, "archive:");
 	cfg->arcdefs = strListCount(archivelist);
-	if((cfg->arcdef = realloc(cfg->arcdef, sizeof(arcdef_t)*cfg->arcdefs)) == NULL) {
+	if((cfg->arcdef = realloc_or_free(cfg->arcdef, sizeof(arcdef_t)*cfg->arcdefs)) == NULL) {
 		strListFree(&archivelist);
 		return false;
 	}
@@ -348,7 +348,7 @@ bool sbbsecho_read_ini(sbbsecho_cfg_t* cfg)
 	if(cfg->sort_nodelist)
 		strListSortAlphaCase(nodelist);
 	cfg->nodecfgs = strListCount(nodelist);
-	if((cfg->nodecfg = realloc(cfg->nodecfg, sizeof(nodecfg_t)*cfg->nodecfgs)) == NULL) {
+	if((cfg->nodecfg = realloc_or_free(cfg->nodecfg, sizeof(nodecfg_t)*cfg->nodecfgs)) == NULL) {
 		strListFree(&nodelist);
 		return false;
 	}
@@ -427,7 +427,7 @@ bool sbbsecho_read_ini(sbbsecho_cfg_t* cfg)
 	/**************/
 	str_list_t echolists = iniGetSectionList(ini, "echolist:");
 	cfg->listcfgs = strListCount(echolists);
-	if((cfg->listcfg = realloc(cfg->listcfg, sizeof(echolist_t)*cfg->listcfgs)) == NULL) {
+	if((cfg->listcfg = realloc_or_free(cfg->listcfg, sizeof(echolist_t)*cfg->listcfgs)) == NULL) {
 		strListFree(&echolists);
 		return false;
 	}
@@ -451,7 +451,7 @@ bool sbbsecho_read_ini(sbbsecho_cfg_t* cfg)
 	/***********/
 	str_list_t domains = iniGetSectionList(ini, "domain:");
 	cfg->domain_count = strListCount(domains);
-	if((cfg->domain_list = realloc(cfg->domain_list, sizeof(struct fido_domain)*cfg->domain_count)) == NULL) {
+	if((cfg->domain_list = realloc_or_free(cfg->domain_list, sizeof(struct fido_domain)*cfg->domain_count)) == NULL) {
 		strListFree(&domains);
 		return false;
 	}
@@ -473,7 +473,7 @@ bool sbbsecho_read_ini(sbbsecho_cfg_t* cfg)
 	/**********/
 	str_list_t robots = iniGetSectionList(ini, "robot:");
 	cfg->robot_count = strListCount(robots);
-	if((cfg->robot_list = realloc(cfg->robot_list, sizeof(struct robot)*cfg->robot_count)) == NULL) {
+	if((cfg->robot_list = realloc_or_free(cfg->robot_list, sizeof(struct robot)*cfg->robot_count)) == NULL) {
 		strListFree(&robots);
 		return false;
 	}
diff --git a/src/sbbs3/sbbsecho.c b/src/sbbs3/sbbsecho.c
index 7f796064684bd37336708d785d8b605a05e28c75..ce36daa55e5593fab457180f6d8143a8bbc1e4e5 100644
--- a/src/sbbs3/sbbsecho.c
+++ b/src/sbbs3/sbbsecho.c
@@ -1661,7 +1661,7 @@ void alter_areas(str_list_t add_area, str_list_t del_area, fidoaddr_t addr, cons
 
 						++cfg.area[u].links;
 						if((cfg.area[u].link=(fidoaddr_t *)
-							realloc(cfg.area[u].link,sizeof(fidoaddr_t)
+							realloc_or_free(cfg.area[u].link,sizeof(fidoaddr_t)
 							*(cfg.area[u].links)))==NULL) {
 							lprintf(LOG_ERR,"ERROR line %d allocating memory for area "
 								"#%u links.",__LINE__,u+1);
@@ -2440,7 +2440,7 @@ int attachment(const char *bundlename, fidoaddr_t dest, enum attachment_mode mod
 				continue;
 			num_mfncrc++;
 			p=getfname(hdr.subj);
-			if((mfncrc=(uint32_t *)realloc(mfncrc,num_mfncrc*sizeof(uint32_t)))==NULL) {
+			if((mfncrc=(uint32_t *)realloc_or_free(mfncrc,num_mfncrc*sizeof(uint32_t)))==NULL) {
 				lprintf(LOG_ERR,"ERROR line %d allocating %lu for bundle name crc"
 					,__LINE__,num_mfncrc*sizeof(uint32_t));
 				continue;
@@ -3931,7 +3931,7 @@ void gen_psb(addrlist_t *seenbys, addrlist_t *paths, const char *inbuf, uint16_t
 					addr.point=atoi(p2+1);
 				if(!addr.zone)
 					addr.zone=zone; 		/* Was 1 */
-				if((seenbys->addr=(fidoaddr_t *)realloc(seenbys->addr
+				if((seenbys->addr=(fidoaddr_t *)realloc_or_free(seenbys->addr
 					,sizeof(fidoaddr_t)*(seenbys->addrs+1)))==NULL) {
 					lprintf(LOG_ERR,"ERROR line %d allocating memory for message "
 						"seenbys.",__LINE__);
@@ -3951,7 +3951,7 @@ void gen_psb(addrlist_t *seenbys, addrlist_t *paths, const char *inbuf, uint16_t
 		}
 	}
 	else {
-		if((seenbys->addr=(fidoaddr_t *)realloc(seenbys->addr
+		if((seenbys->addr=(fidoaddr_t *)realloc_or_free(seenbys->addr
 			,sizeof(fidoaddr_t)))==NULL) {
 			lprintf(LOG_ERR,"ERROR line %d allocating memory for message seenbys."
 				,__LINE__);
@@ -3992,7 +3992,7 @@ void gen_psb(addrlist_t *seenbys, addrlist_t *paths, const char *inbuf, uint16_t
 					addr.point=atoi(p2+1);
 				if(!addr.zone)
 					addr.zone=zone; 		/* Was 1 */
-				if((paths->addr=(fidoaddr_t *)realloc(paths->addr
+				if((paths->addr=(fidoaddr_t *)realloc_or_free(paths->addr
 					,sizeof(fidoaddr_t)*(paths->addrs+1)))==NULL) {
 					lprintf(LOG_ERR,"ERROR line %d allocating memory for message "
 						"paths.",__LINE__);
@@ -4009,7 +4009,7 @@ void gen_psb(addrlist_t *seenbys, addrlist_t *paths, const char *inbuf, uint16_t
 		}
 	}
 	else {
-		if((paths->addr=(fidoaddr_t *)realloc(paths->addr
+		if((paths->addr=(fidoaddr_t *)realloc_or_free(paths->addr
 			,sizeof(fidoaddr_t)))==NULL) {
 			lprintf(LOG_ERR,"ERROR line %d allocating memory for message paths."
 				,__LINE__);
@@ -6454,7 +6454,7 @@ int main(int argc, char **argv)
 					break;
 				}
 				if((cfg.area[areanum].link=(fidoaddr_t *)
-					realloc(cfg.area[areanum].link
+					realloc_or_free(cfg.area[areanum].link
 					,sizeof(fidoaddr_t)*(cfg.area[areanum].links+1)))==NULL) {
 					printf("\n");
 					lprintf(LOG_ERR,"ERROR allocating memory for area #%u links."
diff --git a/src/sbbs3/scfg/scfg.c b/src/sbbs3/scfg/scfg.c
index 3f1085ee3e321964dd0f561aa17c751f17ddab3f..0e5c1e165200fdd20ea477313823b8e97b52f442 100644
--- a/src/sbbs3/scfg/scfg.c
+++ b/src/sbbs3/scfg/scfg.c
@@ -378,7 +378,7 @@ void set_cfg_filename(const char* hostname)
 	if(hostname == NULL)
 		sbbs_get_ini_fname(cfg.filename, cfg.ctrl_dir);
 	else
-		snprintf(cfg.filename, sizeof cfg.filename, "%ssbbs.%s.ini", cfg.ctrl_dir, hostname);
+		snprintf(cfg.filename, sizeof cfg.filename, "%ssbbs%s%s.ini", cfg.ctrl_dir, *hostname ? ".":"", hostname);
 }
 
 int main(int argc, char **argv)
@@ -1122,7 +1122,7 @@ void txt_cfg()
 				uifc.helpbuf=0;
 				continue;
 			}
-			if((cfg.txtsec=(txtsec_t **)realloc(cfg.txtsec
+			if((cfg.txtsec=(txtsec_t **)realloc_or_free(cfg.txtsec
 				,sizeof(txtsec_t *)*(cfg.total_txtsecs+1)))==NULL) {
 				errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_txtsecs+1);
 				cfg.total_txtsecs=0;
@@ -1311,7 +1311,7 @@ void shell_cfg()
 				uifc.helpbuf=0;
 				continue;
 			}
-			if((cfg.shell=(shell_t **)realloc(cfg.shell
+			if((cfg.shell=(shell_t **)realloc_or_free(cfg.shell
 				,sizeof(shell_t *)*(cfg.total_shells+1)))==NULL) {
 				errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_shells+1);
 				cfg.total_shells=0;
diff --git a/src/sbbs3/scfg/scfgchat.c b/src/sbbs3/scfg/scfgchat.c
index adf8681f8e0027f3d55eade993cd23c4a142b33d..0fe46efe9e941e218b61985ae39eebeaf8029ff3 100644
--- a/src/sbbs3/scfg/scfgchat.c
+++ b/src/sbbs3/scfg/scfgchat.c
@@ -67,7 +67,7 @@ void page_cfg()
 			if(uifc.input(WIN_MID|WIN_SAV,0,0,"Command Line",str,50
 				,K_EDIT)<1)
 				continue;
-			if((cfg.page=(page_t **)realloc(cfg.page,sizeof(page_t *)*(cfg.total_pages+1)))
+			if((cfg.page=(page_t **)realloc_or_free(cfg.page,sizeof(page_t *)*(cfg.total_pages+1)))
 				==NULL) {
 				errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_pages+1);
 				cfg.total_pages=0;
@@ -266,7 +266,7 @@ void chan_cfg()
 				uifc.helpbuf=0;
 				continue; 
 			}
-			if((cfg.chan=(chan_t **)realloc(cfg.chan,sizeof(chan_t *)*(cfg.total_chans+1)))
+			if((cfg.chan=(chan_t **)realloc_or_free(cfg.chan,sizeof(chan_t *)*(cfg.total_chans+1)))
 				==NULL) {
 				errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_chans+1);
 				cfg.total_chans=0;
@@ -542,7 +542,7 @@ void chatact_cfg(uint setnum)
 			if(uifc.input(WIN_MID|WIN_SAV,0,0,"",out,LEN_CHATACTOUT
 				,K_MSG)<1)
 				continue;
-			if((cfg.chatact=(chatact_t **)realloc(cfg.chatact
+			if((cfg.chatact=(chatact_t **)realloc_or_free(cfg.chatact
 				,sizeof(chatact_t *)*(cfg.total_chatacts+1)))==NULL) {
 				errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_chatacts+1);
 				cfg.total_chatacts=0;
@@ -671,7 +671,7 @@ void guru_cfg()
 				uifc.helpbuf=0;
 				continue; 
 			}
-			if((cfg.guru=(guru_t **)realloc(cfg.guru,sizeof(guru_t *)*(cfg.total_gurus+1)))
+			if((cfg.guru=(guru_t **)realloc_or_free(cfg.guru,sizeof(guru_t *)*(cfg.total_gurus+1)))
 				==NULL) {
 				errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_gurus+1);
 				cfg.total_gurus=0;
@@ -827,7 +827,7 @@ void actsets_cfg()
 			if(uifc.input(WIN_MID|WIN_SAV,0,0,"Chat Action Set Name",str,25
 				,0)<1)
 				continue;
-			if((cfg.actset=(actset_t **)realloc(cfg.actset,sizeof(actset_t *)*(cfg.total_actsets+1)))
+			if((cfg.actset=(actset_t **)realloc_or_free(cfg.actset,sizeof(actset_t *)*(cfg.total_actsets+1)))
 				==NULL) {
 				errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_actsets+1);
 				cfg.total_actsets=0;
diff --git a/src/sbbs3/scfg/scfgnet.c b/src/sbbs3/scfg/scfgnet.c
index c7036cf78dfe00e4f7f4091b024aeca85d15b05f..6150d4157235b1b63dff3a4eaadcf9aa10248d1a 100644
--- a/src/sbbs3/scfg/scfgnet.c
+++ b/src/sbbs3/scfg/scfgnet.c
@@ -53,9 +53,9 @@ bool new_qhub(unsigned new_qhubnum)
 
 bool new_qhub_sub(qhub_t* qhub, int subnum, sub_t* sub, unsigned confnum)
 {
-	if((qhub->sub=realloc(qhub->sub, sizeof(*qhub->sub)*(qhub->subs+1)))==NULL
-		|| (qhub->conf=(ushort *)realloc(qhub->conf, sizeof(*qhub->conf)*(qhub->subs+1)))==NULL
-		|| (qhub->mode=(uchar *)realloc(qhub->mode, sizeof(*qhub->mode)*(qhub->subs+1)))==NULL) {
+	if((qhub->sub=realloc_or_free(qhub->sub, sizeof(*qhub->sub)*(qhub->subs+1)))==NULL
+		|| (qhub->conf=(ushort *)realloc_or_free(qhub->conf, sizeof(*qhub->conf)*(qhub->subs+1)))==NULL
+		|| (qhub->mode=(uchar *)realloc_or_free(qhub->mode, sizeof(*qhub->mode)*(qhub->subs+1)))==NULL) {
 		/* ToDo: report error */
 		return false;
 	}
@@ -628,7 +628,7 @@ void net_cfg()
 								} else
 									newfaddr = savfaddr;
 
-								if((cfg.faddr=(faddr_t *)realloc(cfg.faddr
+								if((cfg.faddr=(faddr_t *)realloc_or_free(cfg.faddr
 									,sizeof(faddr_t)*(cfg.total_faddrs+1)))==NULL) {
 									errormsg(WHERE,ERR_ALLOC,nulstr
 										,sizeof(faddr_t)*cfg.total_faddrs+1);
diff --git a/src/sbbs3/scfg/scfgxfr1.c b/src/sbbs3/scfg/scfgxfr1.c
index b4972dc989eec944d471c866f036bfc96cafcb00..45574f4696a8601eeab3324aa1f43397b9ee946a 100644
--- a/src/sbbs3/scfg/scfgxfr1.c
+++ b/src/sbbs3/scfg/scfgxfr1.c
@@ -369,7 +369,7 @@ void xfer_opts()
 						continue;
 					}
 					if(msk == MSK_INS) {
-						if((cfg.fview=(fview_t **)realloc(cfg.fview
+						if((cfg.fview=(fview_t **)realloc_or_free(cfg.fview
 							,sizeof(fview_t *)*(cfg.total_fviews+1)))==NULL) {
 							errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_fviews+1);
 							cfg.total_fviews=0;
@@ -499,7 +499,7 @@ void xfer_opts()
 						continue;
 					}
 					if(msk == MSK_INS) {
-						if((cfg.ftest=(ftest_t **)realloc(cfg.ftest
+						if((cfg.ftest=(ftest_t **)realloc_or_free(cfg.ftest
 							,sizeof(ftest_t *)*(cfg.total_ftests+1)))==NULL) {
 							errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_ftests+1);
 							cfg.total_ftests=0;
@@ -653,7 +653,7 @@ void xfer_opts()
 						continue;
 					}
 					if(msk == MSK_INS) {
-						if((cfg.dlevent=(dlevent_t **)realloc(cfg.dlevent
+						if((cfg.dlevent=(dlevent_t **)realloc_or_free(cfg.dlevent
 							,sizeof(dlevent_t *)*(cfg.total_dlevents+1)))==NULL) {
 							errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_dlevents+1);
 							cfg.total_dlevents=0;
@@ -800,7 +800,7 @@ void xfer_opts()
 						continue;
 					}
 					if(msk == MSK_INS) {
-						if((cfg.fextr=(fextr_t **)realloc(cfg.fextr
+						if((cfg.fextr=(fextr_t **)realloc_or_free(cfg.fextr
 							,sizeof(fextr_t *)*(cfg.total_fextrs+1)))==NULL) {
 							errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_fextrs+1);
 							cfg.total_fextrs=0;
@@ -939,7 +939,7 @@ void xfer_opts()
 						continue;
 					}
 					if(msk == MSK_INS) {
-						if((cfg.fcomp=(fcomp_t **)realloc(cfg.fcomp
+						if((cfg.fcomp=(fcomp_t **)realloc_or_free(cfg.fcomp
 							,sizeof(fcomp_t *)*(cfg.total_fcomps+1)))==NULL) {
 							errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_fcomps+1);
 							cfg.total_fcomps=0;
diff --git a/src/sbbs3/scfg/scfgxfr2.c b/src/sbbs3/scfg/scfgxfr2.c
index 7655e610a0660450f54369b488627a5675dbb7b7..f8d6804f6b78d516969fce876a28ef2e3f1aff38 100644
--- a/src/sbbs3/scfg/scfgxfr2.c
+++ b/src/sbbs3/scfg/scfgxfr2.c
@@ -1021,7 +1021,7 @@ void xfer_cfg()
 							break;
 						if(j==cfg.total_dirs) {
 
-							if((cfg.dir=(dir_t **)realloc(cfg.dir
+							if((cfg.dir=(dir_t **)realloc_or_free(cfg.dir
 								,sizeof(dir_t *)*(cfg.total_dirs+1)))==NULL) {
 								errormsg(WHERE,ERR_ALLOC,"dir",cfg.total_dirs+1);
 								cfg.total_dirs=0;
diff --git a/src/sbbs3/scfg/scfgxtrn.c b/src/sbbs3/scfg/scfgxtrn.c
index 02b4755674bf159a07aed7b893443493b9397358..fdade3f7b30da8c1325cb1776385548d7afd5a28 100644
--- a/src/sbbs3/scfg/scfgxtrn.c
+++ b/src/sbbs3/scfg/scfgxtrn.c
@@ -2338,7 +2338,7 @@ int natvpgm_cfg()
 			if(uifc.input(WIN_MID|WIN_SAV,0,0,"Native Program Name",str,12
 				,0)<1)
 				continue;
-			if((cfg.natvpgm=(natvpgm_t **)realloc(cfg.natvpgm
+			if((cfg.natvpgm=(natvpgm_t **)realloc_or_free(cfg.natvpgm
 				,sizeof(natvpgm_t *)*(cfg.total_natvpgms+1)))==NULL) {
 				errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_natvpgms+1);
 				cfg.total_natvpgms=0;
@@ -2640,7 +2640,7 @@ void hotkey_cfg(void)
 				,K_UPPER|K_NOSPACE)<1)
 				continue;
 
-			if((cfg.hotkey=(hotkey_t **)realloc(cfg.hotkey
+			if((cfg.hotkey=(hotkey_t **)realloc_or_free(cfg.hotkey
 				,sizeof(hotkey_t *)*(cfg.total_hotkeys+1)))==NULL) {
 				errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_hotkeys+1);
 				cfg.total_hotkeys=0;
diff --git a/src/sbbs3/smbutil.c b/src/sbbs3/smbutil.c
index 3f8f226abcb1e9f1188fbba6c037bc5aa33e0baa..a445aeb935be289787c867f97119b2c94956225b 100644
--- a/src/sbbs3/smbutil.c
+++ b/src/sbbs3/smbutil.c
@@ -212,7 +212,7 @@ void postmsg(char type, char* to, char* to_number, char* to_address,
 		i=fread(buf,1,sizeof(buf),fp);
 		if(i<1)
 			break;
-		if((msgtxt = realloc(msgtxt,msgtxtlen+i+1))==NULL) {
+		if((msgtxt = realloc_or_free(msgtxt,msgtxtlen+i+1))==NULL) {
 			fprintf(errfp,"\n%s!realloc(%ld) failure\n",beep,msgtxtlen+i+1);
 			bail(1);
 		}
diff --git a/src/sbbs3/targets.mk b/src/sbbs3/targets.mk
index 07471770bf8ec6ccc553889f24a8df18574e3999..8e0f19a6cdc8778383ab4125ea84bf570422e7c8 100644
--- a/src/sbbs3/targets.mk
+++ b/src/sbbs3/targets.mk
@@ -10,6 +10,7 @@ WEBSRVR		= $(LIBODIR)/$(LIBPREFIX)websrvr$(SOFILE)
 MAILSRVR	= $(LIBODIR)/$(LIBPREFIX)mailsrvr$(SOFILE)
 SERVICES	= $(LIBODIR)/$(LIBPREFIX)services$(SOFILE)
 SBBSCON		= $(EXEODIR)/sbbs$(EXEFILE)
+SBBSMONO	= $(EXEODIR)/sbbsmono$(EXEFILE)
 JSEXEC		= $(EXEODIR)/jsexec$(EXEFILE)
 JSDOOR		= $(EXEODIR)/jsdoor$(EXEFILE)
 NODE		= $(EXEODIR)/node$(EXEFILE)
@@ -58,7 +59,9 @@ console:	$(JS_DEPS) xpdev-mt smblib \
 		dlls \
 		$(SBBSCON) $(JSEXEC)
 
-utils:		scfg uedit umonitor $(UTILS)
+utils:	smblib xpdev-mt xpdev ciolib-mt uifc-mt \
+		$(LIBODIR) $(OBJODIR) $(MTOBJODIR) $(EXEODIR) \
+		$(UTILS)
 
 gtkutils: gtkmonitor gtkchat gtkuseredit gtkuserlist
 
@@ -66,6 +69,10 @@ dlls:	$(JS_DEPS) smblib xpdev-mt \
 		$(MTOBJODIR) $(LIBODIR) \
 		$(SBBS) $(FTPSRVR) $(MAILSRVR) $(SERVICES)
 
+mono:	xpdev-mt smblib \
+		$(MTOBJODIR) $(EXEODIR) \
+		$(SBBSMONO)
+
 .PHONY: scfg
 scfg:
 	$(MAKE) -C scfg $(MAKEFLAGS)
@@ -142,6 +149,7 @@ $(WEBSRVR):
 $(MAILSRVR):
 $(SERVICES): 
 $(SBBSCON): $(XPDEV-MT_LIB) $(SMBLIB)
+$(SBBSMONO): $(XPDEV-MT_LIB) $(SMBLIB)
 $(JSEXEC): $(XPDEV-MT_LIB) $(SMBLIB)
 $(JSDOOR): $(XPDEV-MT_LIB)
 $(NODE): $(XPDEV_LIB)
diff --git a/src/xpdev/genwrap.c b/src/xpdev/genwrap.c
index bccfadfd8e9ef98cf5081cb2cbeff5230db3a27c..b56d1c8a09996baa36472972e97e82ca64045e6c 100644
--- a/src/xpdev/genwrap.c
+++ b/src/xpdev/genwrap.c
@@ -1117,7 +1117,7 @@ BOOL terminate_pid(pid_t pid)
 
 /****************************************************************************/
 /* Re-entrant (thread-safe) version of strerror()							*/
-/* GNU (not POSIX) inspired API											*/
+/* GNU (not POSIX) inspired API												*/
 /****************************************************************************/
 char* safe_strerror(int errnum, char *buf, size_t buflen)
 {
@@ -1136,3 +1136,15 @@ char* safe_strerror(int errnum, char *buf, size_t buflen)
 #endif
 	return buf;
 }
+
+/****************************************************************************/
+/* Common realloc mistake: 'p' nulled but not freed upon failure			*/
+/* [memleakOnRealloc]														*/
+/****************************************************************************/
+void* realloc_or_free(void* p, size_t size)
+{
+	void* n = realloc(p, size);
+	if(n == NULL)
+		free(p);
+	return n;
+}
diff --git a/src/xpdev/genwrap.h b/src/xpdev/genwrap.h
index ea118bcacf5d4d28f8c66c88f772a02d1ea2b8fc..4556d437a46e867e4f7daa67a50eb85200277fa8 100644
--- a/src/xpdev/genwrap.h
+++ b/src/xpdev/genwrap.h
@@ -394,6 +394,8 @@ msclock_t	msclock(void);
 DLLEXPORT BOOL		check_pid(pid_t);
 DLLEXPORT BOOL		terminate_pid(pid_t);
 
+DLLEXPORT void*		realloc_or_free(void* p, size_t size);
+
 #if defined(__cplusplus)
 }
 #endif