diff --git a/src/sbbs3/answer.cpp b/src/sbbs3/answer.cpp
index 78f620a4342d2e68a74601ad7d897cb3a21bc731..dd40ac1c92d2886e054fe5547cf4e750fa660c09 100644
--- a/src/sbbs3/answer.cpp
+++ b/src/sbbs3/answer.cpp
@@ -44,7 +44,7 @@ bool sbbs_t::answer()
 	char 	tmp[MAX_PATH+1];
 	char 	tmp2[MAX_PATH+1];
 	int		i,l,in;
-	struct tm * tm;
+	struct tm tm;
 	struct in_addr addr;
 
 	useron.number=0;
@@ -52,15 +52,14 @@ bool sbbs_t::answer()
 	/* Caller ID is IP address */
 	addr.s_addr=client_addr;
 	strcpy(cid,inet_ntoa(addr)); 
-	
-    tm=localtime(&now); 
-	if(tm==NULL)
-		return(false);
+
+	memset(&tm,0,sizeof(tm));
+    localtime_r(&now,&tm); 
 
 	sprintf(str,"%s  %s %s %02d %u            Node %3u"
-		,hhmmtostr(&cfg,tm,str2)
-		,wday[tm->tm_wday]
-        ,mon[tm->tm_mon],tm->tm_mday,tm->tm_year+1900,cfg.node_num);
+		,hhmmtostr(&cfg,&tm,str2)
+		,wday[tm.tm_wday]
+        ,mon[tm.tm_mon],tm.tm_mday,tm.tm_year+1900,cfg.node_num);
 	logline("@ ",str);
 
 	sprintf(str,"%s  %s [%s]", connection, client_name, cid);
diff --git a/src/sbbs3/atcodes.cpp b/src/sbbs3/atcodes.cpp
index 8d5e4e2b991bb6803a83cebf74d9b3bf537d45c5..662d98d92932f783cc15d3c32e4ccac66854092c 100644
--- a/src/sbbs3/atcodes.cpp
+++ b/src/sbbs3/atcodes.cpp
@@ -92,7 +92,6 @@ char* sbbs_t::atcode(char* sp, char* str)
     stats_t stats;
     node_t  node;
 	struct	tm tm;
-	struct	tm * tm_p;
 
 	str[0]=0;
 
@@ -209,11 +208,7 @@ char* sbbs_t::atcode(char* sp, char* str)
 
 	if(!strcmp(sp,"TIME") || !strcmp(sp,"SYSTIME")) {
 		now=time(NULL);
-		tm_p=localtime(&now);
-		if(tm_p!=NULL)
-			tm=*tm_p;
-		else
-			memset(&tm,0,sizeof(tm));
+		memset(&tm,0,sizeof(tm));
 		sprintf(str,"%02d:%02d %s"
 			,tm.tm_hour==0 ? 12
 			: tm.tm_hour>12 ? tm.tm_hour-12
@@ -426,11 +421,8 @@ char* sbbs_t::atcode(char* sp, char* str)
 		return(unixtodstr(&cfg,useron.laston,str));
 
 	if(!strcmp(sp,"LASTTIMEON")) {
-		tm_p=localtime(&useron.laston);
-		if(tm_p)
-			tm=*tm_p;
-		else
-			memset(&tm,0,sizeof(tm));
+		memset(&tm,0,sizeof(tm));
+		localtime_r(&useron.laston,&tm);
 		sprintf(str,"%02d:%02d %s"
 			,tm.tm_hour==0 ? 12
 			: tm.tm_hour>12 ? tm.tm_hour-12
diff --git a/src/sbbs3/bat_xfer.cpp b/src/sbbs3/bat_xfer.cpp
index 0e5ce35efb84de7ac73ef4cd2aee07550553c699..fe64aa14296dacf6e37e19e95c3bebe8fe5fba36 100644
--- a/src/sbbs3/bat_xfer.cpp
+++ b/src/sbbs3/bat_xfer.cpp
@@ -347,7 +347,7 @@ void sbbs_t::start_batch_download()
     uint	i,xfrprot;
     ulong	totalcdt,totalsize,totaltime;
     time_t	start,end,t;
-	struct	tm * tm;
+	struct	tm tm;
 
 	if(useron.rest&FLAG('D')) {     /* Download restriction */
 		bputs(text[R_Download]);
@@ -454,10 +454,8 @@ void sbbs_t::start_batch_download()
 	t=now;
 	if(cur_cps) 
 		t+=(totalsize/(ulong)cur_cps);
-	tm=localtime(&t);
-	if(tm==NULL)
-		return;
-	thisnode.aux=(tm->tm_hour*60)+tm->tm_min;
+	localtime_r(&t,&tm);
+	thisnode.aux=(tm.tm_hour*60)+tm.tm_min;
 	thisnode.action=action;
 	putnodedat(cfg.node_num,&thisnode); /* calculate ETA */
 	start=time(NULL);
diff --git a/src/sbbs3/chat.cpp b/src/sbbs3/chat.cpp
index f9bbe59441a7a63d49490fd3b43de49c5ccce551..88c61d696c0b1c0f920dc0fff146ad59f82bb028 100644
--- a/src/sbbs3/chat.cpp
+++ b/src/sbbs3/chat.cpp
@@ -1381,15 +1381,10 @@ void sbbs_t::guruchat(char *line, char *gurubuf, int gurunum)
 	int		file;
 	uint 	c,i,j,k;
 	long 	len;
-	struct	tm *tm_p;
 	struct	tm tm;
 
 	now=time(NULL);
-	tm_p=localtime(&now);
-	if(tm_p)
-		tm=*tm_p;
-	else
-		memset(&tm,0,sizeof(tm));
+	localtime_r(&now,&tm);
 
 	for(i=0;i<100;i++) {
 		if((answer[i]=(char *)MALLOC(513))==NULL) {
diff --git a/src/sbbs3/chk_ar.cpp b/src/sbbs3/chk_ar.cpp
index 1519cbd82da324682dd723b37a99c9fcf47695e5..6325c7609be0dad9b2d02d0a978d9eb69abdf008 100644
--- a/src/sbbs3/chk_ar.cpp
+++ b/src/sbbs3/chk_ar.cpp
@@ -42,7 +42,7 @@ bool sbbs_t::ar_exp(uchar **ptrptr, user_t* user)
 	bool	result,_not,_or,equal;
 	uint	i,n,artype,age;
 	ulong	l;
-	struct tm * tm;
+	struct tm tm;
 
 	result = true;
 
@@ -203,9 +203,9 @@ bool sbbs_t::ar_exp(uchar **ptrptr, user_t* user)
 				break;
 			case AR_DAY:
 				now=time(NULL);
-				tm=localtime(&now);
-				if(tm==NULL || (equal && tm->tm_wday!=(int)n) 
-					|| (!equal && tm->tm_wday<(int)n))
+				localtime_r(&now,&tm);
+				if((equal && tm.tm_wday!=(int)n) 
+					|| (!equal && tm.tm_wday<(int)n))
 					result=_not;
 				else
 					result=!_not;
@@ -382,8 +382,8 @@ bool sbbs_t::ar_exp(uchar **ptrptr, user_t* user)
 				break;
 			case AR_TIME:
 				now=time(NULL);
-				tm=localtime(&now);
-				if(tm==NULL || (tm->tm_hour*60)+tm->tm_min<(int)i)
+				localtime_r(&now,&tm);
+				if((tm.tm_hour*60)+tm.tm_min<(int)i)
 					result=_not;
 				else
 					result=!_not;
diff --git a/src/sbbs3/con_out.cpp b/src/sbbs3/con_out.cpp
index 95e3fb968a6a8711b5e6bb15493c9327557db1db..b6f444ef39a37aeab5698254c360105d413e9a63 100644
--- a/src/sbbs3/con_out.cpp
+++ b/src/sbbs3/con_out.cpp
@@ -267,7 +267,7 @@ void sbbs_t::ctrl_a(char x)
 {
 	int		i;
 	char	tmp1[128],atr=curatr;
-	struct	tm * tm;
+	struct	tm tm;
 
 	if(x && (uchar)x<ESC) {    /* Ctrl-A through Ctrl-Z for users with MF only */
 		if(!(useron.flags1&FLAG(x+64)))
@@ -336,12 +336,11 @@ void sbbs_t::ctrl_a(char x)
 			break;
 		case 'T':   /* Time */
 			now=time(NULL);
-			tm=localtime(&now);
-			if(tm!=NULL)
-				bprintf("%02d:%02d %s"
-					,tm->tm_hour==0 ? 12
-					: tm->tm_hour>12 ? tm->tm_hour-12
-					: tm->tm_hour, tm->tm_min, tm->tm_hour>11 ? "pm":"am");
+			localtime_r(&now,&tm);
+			bprintf("%02d:%02d %s"
+				,tm.tm_hour==0 ? 12
+				: tm.tm_hour>12 ? tm.tm_hour-12
+				: tm.tm_hour, tm.tm_min, tm.tm_hour>11 ? "pm":"am");
 			break;
 		case 'D':   /* Date */
 			now=time(NULL);
diff --git a/src/sbbs3/data.cpp b/src/sbbs3/data.cpp
index b75633d012cfc72fb727dbce074f33f3f679c677..f88e0a31a127a9d4f4ee5a79bd4acf7a121f6695 100644
--- a/src/sbbs3/data.cpp
+++ b/src/sbbs3/data.cpp
@@ -168,13 +168,11 @@ void sbbs_t::gettimeleft(void)
     time_t  eventtime=0;
 	time_t	thisevent;
     long    tleft;
-    struct  tm *tm, last_tm;
+    struct  tm tm, last_tm;
 
 	now=time(NULL);
 
-	tm=localtime(&now);
-	if(tm==NULL)
-		return;
+	localtime_r(&now,&tm);
 	if(useron.exempt&FLAG('T')) {   /* Time online exemption */
 		timeleft=cfg.level_timepercall[useron.level]*60;
 		if(timeleft<10)             /* never get below 10 for exempt users */
@@ -199,22 +197,16 @@ void sbbs_t::gettimeleft(void)
 			continue;
 		if(!(cfg.event[i]->misc&EVENT_FORCE)
 			|| (!(cfg.event[i]->misc&EVENT_EXCL) && cfg.event[i]->node!=cfg.node_num)
-			|| !(cfg.event[i]->days&(1<<tm->tm_wday)))
+			|| !(cfg.event[i]->days&(1<<tm.tm_wday)))
 			continue;
 
-		tm=localtime(&cfg.event[i]->last);
-		if(tm)
-			last_tm=*tm;
-		else
-			memset(&last_tm,0,sizeof(last_tm));
-		tm=localtime(&now);
-		if(tm==NULL)
-			return;
-		tm->tm_hour=cfg.event[i]->time/60;   /* hasn't run yet today */
-		tm->tm_min=cfg.event[i]->time-(tm->tm_hour*60);
-		tm->tm_sec=0;
-		thisevent=mktime(tm);
-		if(tm->tm_mday==last_tm.tm_mday && tm->tm_mon==last_tm.tm_mon)
+		localtime_r(&cfg.event[i]->last,&last_tm);
+		localtime_r(&now,&tm);
+		tm.tm_hour=cfg.event[i]->time/60;   /* hasn't run yet today */
+		tm.tm_min=cfg.event[i]->time-(tm.tm_hour*60);
+		tm.tm_sec=0;
+		thisevent=mktime(&tm);
+		if(tm.tm_mday==last_tm.tm_mday && tm.tm_mon==last_tm.tm_mon)
 			thisevent+=24L*60L*60L;     /* already ran today, so add 24hrs */
 		if(!eventtime || thisevent<eventtime)
 			eventtime=thisevent; 
diff --git a/src/sbbs3/date_str.c b/src/sbbs3/date_str.c
index 19e4c7c59add3f4fecb2b94ba12a9b982c564899..a809a4515b6d3f08bdc54986bac9fe82f55bd243 100644
--- a/src/sbbs3/date_str.c
+++ b/src/sbbs3/date_str.c
@@ -94,27 +94,26 @@ time_t DLLCALL dstrtounix(scfg_t* cfg, char *instr)
 /****************************************************************************/
 char* DLLCALL unixtodstr(scfg_t* cfg, time_t unix_time, char *str)
 {
-	struct tm* tm;
+	struct tm tm;
 
 	if(!unix_time)
 		strcpy(str,"00/00/00");
 	else {
-		tm=localtime(&unix_time);
-		if(tm==NULL) {
+		if(localtime_r(&unix_time,&tm)==NULL) {
 			strcpy(str,"00/00/00");
 			return(str);
 		}
-		if(tm->tm_mon>11) {	  /* DOS leap year bug */
-			tm->tm_mon=0;
-			tm->tm_year++; }
-		if(tm->tm_mday>31)
-			tm->tm_mday=1;
+		if(tm.tm_mon>11) {	  /* DOS leap year bug */
+			tm.tm_mon=0;
+			tm.tm_year++; }
+		if(tm.tm_mday>31)
+			tm.tm_mday=1;
 		if(cfg->sys_misc&SM_EURODATE)
-			sprintf(str,"%02u/%02u/%02u",tm->tm_mday,tm->tm_mon+1
-				,TM_YEAR(tm->tm_year));
+			sprintf(str,"%02u/%02u/%02u",tm.tm_mday,tm.tm_mon+1
+				,TM_YEAR(tm.tm_year));
 		else
-			sprintf(str,"%02u/%02u/%02u",tm->tm_mon+1,tm->tm_mday
-				,TM_YEAR(tm->tm_year)); }
+			sprintf(str,"%02u/%02u/%02u",tm.tm_mon+1,tm.tm_mday
+				,TM_YEAR(tm.tm_year)); }
 	return(str);
 }
 
@@ -154,35 +153,34 @@ char* DLLCALL timestr(scfg_t* cfg, time_t *intime, char* str)
 {
     char*		mer;
 	uchar		hour;
-    struct tm*	gm;
+    struct tm	tm;
 
-	gm=localtime(intime);
-	if(gm==NULL) {
+	if(localtime_r(intime,&tm)==NULL) {
 		strcpy(str,"Invalid Time");
 		return(str); 
 	}
 	if(cfg->sys_misc&SM_MILITARY) {
 		sprintf(str,"%s %s %02u %4u %02u:%02u:%02u"
-			,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,1900+gm->tm_year
-			,gm->tm_hour,gm->tm_min,gm->tm_sec);
+			,wday[tm.tm_wday],mon[tm.tm_mon],tm.tm_mday,1900+tm.tm_year
+			,tm.tm_hour,tm.tm_min,tm.tm_sec);
 		return(str); 
 	}
-	if(gm->tm_hour>=12) {
-		if(gm->tm_hour==12)
+	if(tm.tm_hour>=12) {
+		if(tm.tm_hour==12)
 			hour=12;
 		else
-			hour=gm->tm_hour-12;
+			hour=tm.tm_hour-12;
 		mer="pm"; 
 	} else {
-		if(gm->tm_hour==0)
+		if(tm.tm_hour==0)
 			hour=12;
 		else
-			hour=gm->tm_hour;
+			hour=tm.tm_hour;
 		mer="am"; 
 	}
 	sprintf(str,"%s %s %02u %4u %02u:%02u %s"
-		,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,1900+gm->tm_year
-		,hour,gm->tm_min,mer);
+		,wday[tm.tm_wday],mon[tm.tm_mon],tm.tm_mday,1900+tm.tm_year
+		,hour,tm.tm_min,mer);
 	return(str);
 }
 
@@ -350,13 +348,9 @@ char* DLLCALL zonestr(short zone)
 /****************************************************************************/
 char* DLLCALL msgdate(when_t when, char* buf)
 {
-	struct tm	tm;
-	struct tm*	tm_p;
+	struct tm tm;
 	
-	tm_p=localtime((const time_t*)&when.time);
-	if(tm_p!=NULL)
-		tm=*tm_p;
-	else
+	if(localtime_r((const time_t*)&when.time,&tm)==NULL)
 		memset(&tm,0,sizeof(tm));
 	sprintf(buf,"%s, %d %s %d %02d:%02d:%02d %s"
 		,wday[tm.tm_wday]
diff --git a/src/sbbs3/execfunc.cpp b/src/sbbs3/execfunc.cpp
index 7be723c86a747969cb4c542e7f7d2f174d043092..ad2d87b7b8bfbcc25d04a9c68a7bdf4f4d9c41ed 100644
--- a/src/sbbs3/execfunc.cpp
+++ b/src/sbbs3/execfunc.cpp
@@ -47,7 +47,7 @@ int sbbs_t::exec_function(csi_t *csi)
 	uint 	i,j,k;
 	long	l;
 	node_t	node;
-	struct	tm * tm;
+	struct	tm tm;
 
 	switch(*(csi->ip++)) {
 
@@ -239,22 +239,20 @@ int sbbs_t::exec_function(csi_t *csi)
 		case CS_SYSTEM_LOG:                 /* System log */
 			if(!chksyspass())
 				return(0);
-			tm=localtime(&now);
-			if(tm==NULL)
+			if(localtime_r(&now,&tm)==NULL)
 				return(0);
 			sprintf(str,"%slogs/%2.2d%2.2d%2.2d.log", cfg.data_dir
-				,tm->tm_mon+1,tm->tm_mday,TM_YEAR(tm->tm_year));
+				,tm.tm_mon+1,tm.tm_mday,TM_YEAR(tm.tm_year));
 			printfile(str,0);
 			return(0);
 		case CS_SYSTEM_YLOG:                /* Yesterday's log */
 			if(!chksyspass())
 				return(0);
 			now-=(ulong)60L*24L*60L;
-			tm=localtime(&now);
-			if(tm==NULL)
+			if(localtime_r(&now,&tm)==NULL)
 				return(0);
 			sprintf(str,"%slogs/%2.2d%2.2d%2.2d.log",cfg.data_dir
-				,tm->tm_mon+1,tm->tm_mday,TM_YEAR(tm->tm_year));
+				,tm.tm_mon+1,tm.tm_mday,TM_YEAR(tm.tm_year));
 			printfile(str,0);
 			return(0);
 		case CS_SYSTEM_STATS:               /* System Statistics */
diff --git a/src/sbbs3/execmisc.cpp b/src/sbbs3/execmisc.cpp
index f137061bf7e7e673f83a5951f7ccc6f814e54c44..fa4cd0e90df57c4c5f3d5e9690d829eb6ae2c890 100644
--- a/src/sbbs3/execmisc.cpp
+++ b/src/sbbs3/execmisc.cpp
@@ -47,7 +47,7 @@ int sbbs_t::exec_misc(csi_t* csi, char *path)
 	void	*vp;
 	va_list arglist[64];
 	struct	dirent *de;
-    struct  tm *tm_p;
+    struct  tm tm;
 
 	switch(*(csi->ip++)) {
 		case CS_VAR_INSTRUCTION:
@@ -518,10 +518,11 @@ int sbbs_t::exec_misc(csi_t* csi, char *path)
 					lp=getintvar(csi,*(long *)csi->ip);
 					csi->ip+=4;
 					if(pp && lp) {
-						tm_p=localtime((time_t *)lp);
-						if(tm_p) {
-							strftime(buf,128,str,tm_p);
-							*pp=copystrvar(csi,*pp,buf); } }
+						if(localtime_r((time_t *)lp,&tm)!=NULL) {
+							strftime(buf,128,str,&tm);
+							*pp=copystrvar(csi,*pp,buf); 
+						} 
+					}
 					return(0);
 				case TIME_STR:
 					pp=getstrvar(csi,*(long *)csi->ip);
diff --git a/src/sbbs3/fido.cpp b/src/sbbs3/fido.cpp
index 94152094e69b12b5537a5d6964bbf484558feec4..5fc2f4941559cfa3c09a739083e5160f25ed6a99 100644
--- a/src/sbbs3/fido.cpp
+++ b/src/sbbs3/fido.cpp
@@ -105,7 +105,7 @@ bool sbbs_t::netmail(char *into, char *title, long mode)
 	long	length,l;
 	faddr_t addr;
 	fmsghdr_t hdr;
-	struct tm * tm;
+	struct tm tm;
 
 	if(useron.etoday>=cfg.level_emailperday[useron.level] && !SYSOP) {
 		bputs(text[TooManyEmailsToday]);
@@ -170,11 +170,10 @@ bool sbbs_t::netmail(char *into, char *title, long mode)
 	}
 
 	now=time(NULL);
-	tm=localtime(&now);
-	if(tm!=NULL)
+	if(localtime_r(&now,&tm)!=NULL)
 		sprintf(hdr.time,"%02u %3.3s %02u  %02u:%02u:%02u"
-			,tm->tm_mday,mon[tm->tm_mon],TM_YEAR(tm->tm_year)
-			,tm->tm_hour,tm->tm_min,tm->tm_sec);
+			,tm.tm_mday,mon[tm.tm_mon],TM_YEAR(tm.tm_year)
+			,tm.tm_hour,tm.tm_min,tm.tm_sec);
 
 	hdr.destzone	=addr.zone;
 	hdr.destnet 	=addr.net;
diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c
index af25a37654e7b20455be423276c09db6a3ba6a51..771c3c599a869353af3fcb38fe9269f4b5c14fda 100644
--- a/src/sbbs3/ftpsrvr.c
+++ b/src/sbbs3/ftpsrvr.c
@@ -2244,7 +2244,6 @@ static void ctrl_thread(void* arg)
 	node_t		node;
 	client_t	client;
 	struct tm	tm;
-	struct tm *	tm_p;
 	struct tm 	cur_tm;
 #ifdef JAVASCRIPT
 	jsval		js_val;
@@ -2873,22 +2872,16 @@ static void ctrl_thread(void* arg)
 				sockprintf(sock, "150 Directory of %s%s", local_dir, p);
 
 				now=time(NULL);
-				tm_p=localtime(&now);
-				if(tm_p==NULL) 
+				if(localtime_r(&now,&cur_tm)==NULL) 
 					memset(&cur_tm,0,sizeof(cur_tm));
-				else
-					cur_tm=*tm_p;
 			
 				glob(path,0,NULL,&g);
 				for(i=0;i<(int)g.gl_pathc;i++) {
 					if(detail) {
 						f.size=flength(g.gl_pathv[i]);
 						t=fdate(g.gl_pathv[i]);
-						tm_p=localtime(&t);
-						if(tm_p==NULL)
+						if(localtime_r(&t,&tm)==NULL)
 							memset(&tm,0,sizeof(tm));
-						else
-							tm=*tm_p;
 						fprintf(fp,"%crw-r--r--   1 %-8s local %9ld %s %2d "
 							,isdir(g.gl_pathv[i]) ? 'd':'-'
 							,scfg.sys_id
@@ -3072,11 +3065,8 @@ static void ctrl_thread(void* arg)
 				}
 				if(!strnicmp(cmd,"MDTM ",5)) {
 					t=fdate(fname);
-					tm_p=gmtime(&t);	/* specifically use GMT/UTC representation */
-					if(tm_p==NULL)
+					if(gmtime_r(&t,&tm)==NULL) /* specifically use GMT/UTC representation */
 						memset(&tm,0,sizeof(tm));
-					else
-						tm=*tm_p;
 					sockprintf(sock,"213 %u%02u%02u%02u%02u%02u"
 						,1900+tm.tm_year,tm.tm_mon+1,tm.tm_mday
 						,tm.tm_hour,tm.tm_min,tm.tm_sec);					
@@ -3166,11 +3156,8 @@ static void ctrl_thread(void* arg)
 				detail=FALSE;
 			sockprintf(sock,"150 Opening ASCII mode data connection for /bin/ls.");
 			now=time(NULL);
-			tm_p=localtime(&now);
-			if(tm_p==NULL) 
+			if(localtime_r(&now,&cur_tm)==NULL) 
 				memset(&cur_tm,0,sizeof(cur_tm));
-			else
-				cur_tm=*tm_p;
 
 			/* ASCII Index File */
 			if(startup->options&FTP_OPT_INDEX_FILE && startup->index_file_name[0]
@@ -3216,11 +3203,8 @@ static void ctrl_thread(void* arg)
 							t=time(NULL);
 							l=10240;
 						};
-						tm_p=localtime(&t);
-						if(tm_p==NULL) 
+						if(localtime_r(&t,&tm)==NULL) 
 							memset(&tm,0,sizeof(tm));
-						else
-							tm=*tm_p;
 						fprintf(fp,"-r--r--r--   1 %-*s %-8s %9ld %s %2d %02d:%02d %s.qwk\r\n"
 							,NAME_LEN
 							,scfg.sys_id
@@ -3291,11 +3275,8 @@ static void ctrl_thread(void* arg)
 							}
 							else {
 								t=fdate(np);
-								tm_p=localtime(&t);
-								if(tm_p==NULL)
+								if(localtime_r(&t,&tm)==NULL)
 									memset(&tm,0,sizeof(tm));
-								else
-									tm=*tm_p;
 								fprintf(fp,"-r--r--r--   1 %-*s %-8s %9ld %s %2d %02d:%02d %s\r\n"
 									,NAME_LEN
 									,scfg.sys_id
@@ -3370,11 +3351,8 @@ static void ctrl_thread(void* arg)
 						f.size=flength(g.gl_pathv[i]);
 						getfiledat(&scfg,&f);
 						t=fdate(g.gl_pathv[i]);
-						tm_p=localtime(&t);
-						if(tm_p==NULL)
+						if(localtime_r(&t,&tm)==NULL)
 							memset(&tm,0,sizeof(tm));
-						else
-							tm=*tm_p;
 						if(filedat) {
 							if(f.misc&FM_ANON)
 								SAFECOPY(str,ANONYMOUS);
@@ -3837,11 +3815,8 @@ static void ctrl_thread(void* arg)
 				sockprintf(sock,"213 %lu",flength(fname));
 			else if(getdate && success) {
 				t=fdate(fname);
-				tm_p=gmtime(&t);	/* specifically use GMT/UTC representation */
-				if(tm_p==NULL)
+				if(gmtime_r(&t,&tm)==NULL)	/* specifically use GMT/UTC representation */
 					memset(&tm,0,sizeof(tm));
-				else
-					tm=*tm_p;
 				sockprintf(sock,"213 %u%02u%02u%02u%02u%02u"
 					,1900+tm.tm_year,tm.tm_mon+1,tm.tm_mday
 					,tm.tm_hour,tm.tm_min,tm.tm_sec);
@@ -4327,6 +4302,7 @@ void DLLCALL ftp_server(void* arg)
 	char			path[MAX_PATH+1];
 	char			error[256];
 	char			compiler[32];
+	char			str[256];
 	SOCKADDR_IN		server_addr;
 	SOCKADDR_IN		client_addr;
 	socklen_t		client_addr_len;
@@ -4408,7 +4384,7 @@ void DLLCALL ftp_server(void* arg)
 
 		t=time(NULL);
 		lprintf("Initializing on %.24s with options: %lx"
-			,ctime(&t),startup->options);
+			,ctime_r(&t,str,sizeof(str)),startup->options);
 
 		/* Initial configuration and load from CNF files */
 		SAFECOPY(scfg.ctrl_dir, startup->ctrl_dir);
diff --git a/src/sbbs3/js_global.c b/src/sbbs3/js_global.c
index 5161d970ec098744f2bf43fdb6e20bb9e00ad126..46d33d779d5f95fc25be8ad2a2114edec0f57fa0 100644
--- a/src/sbbs3/js_global.c
+++ b/src/sbbs3/js_global.c
@@ -692,7 +692,7 @@ js_strftime(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 	char		str[128];
 	char*		fmt;
 	time_t		t=time(NULL);
-	struct tm*	tm_p;
+	struct tm	tm;
 
 	if(!JSVAL_IS_STRING(argv[0])) {
 		JS_ReportError(cx,nostringarg);
@@ -704,9 +704,9 @@ js_strftime(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 		JS_ValueToInt32(cx,argv[1],(int32*)&t);
 
 	strcpy(str,"-Invalid time-");
-	tm_p=localtime(&t);
-	if(tm_p)
-		strftime(str,sizeof(str),fmt,tm_p);
+	if(localtime_r(&t,&tm)==NULL)
+		memset(&tm,0,sizeof(tm));
+	strftime(str,sizeof(str),fmt,&tm);
 
 	*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, str));
 	return(JS_TRUE);
diff --git a/src/sbbs3/listfile.cpp b/src/sbbs3/listfile.cpp
index 8afc0a199fa25c6347e249c1d9c8c3ea1d7469c9..aee20603886ac56b141a75d176c5f57e9cbebc5c 100644
--- a/src/sbbs3/listfile.cpp
+++ b/src/sbbs3/listfile.cpp
@@ -858,7 +858,7 @@ int sbbs_t::listfileinfo(uint dirnum, char *filespec, long mode)
 	long	usrcdt;
     time_t	start,end,t;
     file_t	f;
-	struct	tm * tm;
+	struct	tm tm;
 
 	sprintf(str,"%sxfer.ixt",cfg.data_dir);
 	if(mode==FI_USERXFER) {
@@ -1281,10 +1281,8 @@ int sbbs_t::listfileinfo(uint dirnum, char *filespec, long mode)
 						getnodedat(cfg.node_num,&thisnode,1);
 						action=NODE_DLNG;
 						t=now+f.timetodl;
-						tm=localtime(&t);
-						if(tm==NULL)
-							break;
-						thisnode.aux=(tm->tm_hour*60)+tm->tm_min;
+						localtime_r(&t,&tm);
+						thisnode.aux=(tm.tm_hour*60)+tm.tm_min;
 						putnodedat(cfg.node_num,&thisnode); /* calculate ETA */
 						start=time(NULL);
 						error=protocol(cmdstr(cfg.prot[i]->dlcmd,path,nulstr,NULL),false);
diff --git a/src/sbbs3/logfile.cpp b/src/sbbs3/logfile.cpp
index 39b9f76dbcfa039e8d75572a9fd5b2d40ee0b87c..a530919337aaf8d64e016d0a0645970212ae9757 100644
--- a/src/sbbs3/logfile.cpp
+++ b/src/sbbs3/logfile.cpp
@@ -138,20 +138,19 @@ bool sbbs_t::syslog(char* code, char *entry)
 	char	str[128];
 	char	tmp[64];
 	int		file;
-	struct tm * tm;
+	struct tm tm;
 
 	now=time(NULL);
-	tm=localtime(&now);
-	if(tm==NULL)
+	if(localtime_r(&now,&tm)==NULL)
 		return(false);
-	sprintf(fname,"%slogs/%2.2d%2.2d%2.2d.log",cfg.data_dir,tm->tm_mon+1,tm->tm_mday
-		,TM_YEAR(tm->tm_year));
+	sprintf(fname,"%slogs/%2.2d%2.2d%2.2d.log",cfg.data_dir,tm.tm_mon+1,tm.tm_mday
+		,TM_YEAR(tm.tm_year));
 	if((file=nopen(fname,O_WRONLY|O_APPEND|O_CREAT))==-1) {
 		lprintf("!ERRROR %d opening/creating %s",errno,fname); 
 		return(false);
 	}
 
-	sprintf(str,"%-2.2s %s  %s\r\n\r\n",code, hhmmtostr(&cfg,tm,tmp), entry);
+	sprintf(str,"%-2.2s %s  %s\r\n\r\n",code, hhmmtostr(&cfg,&tm,tmp), entry);
 	write(file,str,strlen(str));
 	close(file);
 
diff --git a/src/sbbs3/logon.cpp b/src/sbbs3/logon.cpp
index 223cbe536682d59fb7cccddf1367ea233094c713..064c8c023dee6bcf2c876e5c959afcd9e8ec8109 100644
--- a/src/sbbs3/logon.cpp
+++ b/src/sbbs3/logon.cpp
@@ -52,14 +52,11 @@ bool sbbs_t::logon()
 	uint	i,j,mailw;
 	ulong	totallogons;
 	node_t	node;
-	struct	tm* tm_p;
 	struct	tm	tm;
 
 	now=time(NULL);
-	tm_p=localtime(&now);
-	if(tm_p==NULL)
+	if(localtime_r(&now,&tm)==NULL)
 		return(false);
-	tm=*tm_p;
 
 	if(!useron.number)
 		return(false);
@@ -567,7 +564,7 @@ ulong sbbs_t::logonstats()
     time_t update_t=0;
     stats_t stats;
     node_t node;
-	struct tm * tm, update_tm;
+	struct tm tm, update_tm;
 
 	memset(&stats,0,sizeof(stats));
 	sprintf(str,"%sdsts.dab",cfg.ctrl_dir);
@@ -580,15 +577,12 @@ ulong sbbs_t::logonstats()
 	close(dsts);
 	if(update_t>now+(24L*60L*60L)) /* More than a day in the future? */
 		errormsg(WHERE,ERR_CHK,"Daily stats time stamp",update_t);
-	tm = localtime(&update_t);
-	if(tm==NULL)
+	if(localtime_r(&update_t,&update_tm)==NULL)
 		return(0);
-	update_tm=*tm;
-	tm = localtime(&now);
-	if(tm==NULL)
+	if(localtime_r(&now,&tm)==NULL)
 		return(0);
-	if((tm->tm_mday>update_tm.tm_mday && tm->tm_mon==update_tm.tm_mon)
-		|| tm->tm_mon>update_tm.tm_mon || tm->tm_year>update_tm.tm_year) {
+	if((tm.tm_mday>update_tm.tm_mday && tm.tm_mon==update_tm.tm_mon)
+		|| tm.tm_mon>update_tm.tm_mon || tm.tm_year>update_tm.tm_year) {
 
 		sprintf(str,"New Day - Prev: %s ",timestr(&update_t));
 		logentry("!=",str);
diff --git a/src/sbbs3/logout.cpp b/src/sbbs3/logout.cpp
index df1580f8ce9834ffda13ca1345ee0fc52982bbf5..884919499ec4a3f71e84e8fc5f44eb65a7597bb4 100644
--- a/src/sbbs3/logout.cpp
+++ b/src/sbbs3/logout.cpp
@@ -48,18 +48,16 @@ void sbbs_t::logout()
 	int 	i,j;
 	ushort	ttoday;
 	node_t	node;
-	struct	tm * tm, tm_now;
+	struct	tm tm;
 
 	now=time(NULL);
-	tm=localtime(&now);
-	if(tm==NULL)
+	if(localtime_r(&now,&tm)==NULL)
 		return;
-	tm_now=*tm;
 
 	if(!useron.number) {				 /* Not logged in, so do nothing */
 		if(!online) {
 			sprintf(str,"%s  T:%3u sec\r\n"
-				,hhmmtostr(&cfg,tm,tmp)
+				,hhmmtostr(&cfg,&tm,tmp)
 				,(uint)(now-answertime));
 			logline("@-",str); }
 		return; 
@@ -159,7 +157,7 @@ void sbbs_t::logout()
 		putuserrec(&cfg,useron.number,U_CURSUB,8,cfg.sub[usrsub[curgrp][cursub[curgrp]]]->code);
 	if(usrlibs>0)
 		putuserrec(&cfg,useron.number,U_CURDIR,8,cfg.dir[usrdir[curlib][curdir[curlib]]]->code);
-	hhmmtostr(&cfg,&tm_now,str);
+	hhmmtostr(&cfg,&tm,str);
 	strcat(str,"  ");
 	if(sys_status&SS_USERON)
 		sprintf(tmp,"T:%3u   R:%3lu   P:%3lu   E:%3lu   F:%3lu   "
@@ -230,23 +228,20 @@ void sbbs_t::logofflist()
 {
     char str[256];
     int file;
-    struct tm * tm, tm_now;
+    struct tm tm, tm_now;
 
-	tm=localtime(&now);
-	if(tm==NULL)
+	if(localtime_r(&now,&tm_now)==NULL)
 		return;
-	tm_now=*tm;
-	tm=localtime(&logontime);
-	if(tm==NULL)
+	if(localtime_r(&logontime,&tm)==NULL)
 		return;
-	sprintf(str,"%slogs/%2.2d%2.2d%2.2d.LOL",cfg.data_dir,tm->tm_mon+1,tm->tm_mday
-		,TM_YEAR(tm->tm_year));
+	sprintf(str,"%slogs/%2.2d%2.2d%2.2d.LOL",cfg.data_dir,tm.tm_mon+1,tm.tm_mday
+		,TM_YEAR(tm.tm_year));
 	if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
 		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_APPEND);
 		return; }
 	sprintf(str,"%-*.*s %-2d %-8.8s %2.2d:%2.2d %2.2d:%2.2d %3d%3ld%3ld%3ld%3ld"
 		"%3ld%3ld\r\n",LEN_ALIAS,LEN_ALIAS,useron.alias,cfg.node_num,connection
-		,tm->tm_hour,tm->tm_min,tm_now.tm_hour,tm_now.tm_min
+		,tm.tm_hour,tm.tm_min,tm_now.tm_hour,tm_now.tm_min
 		,(int)(now-logontime)/60,posts_read,logon_posts,logon_emails
 		,logon_fbacks,logon_uls,logon_dls);
 	write(file,str,strlen(str));
diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c
index eae8691c2ff2508d8a3efb72d85ddc0cfd2d6459..0fd80b6adcd6f91ddadb5d093dcce03c9f68e586 100644
--- a/src/sbbs3/mailsrvr.c
+++ b/src/sbbs3/mailsrvr.c
@@ -2893,6 +2893,7 @@ const char* DLLCALL mail_ver(void)
 void DLLCALL mail_server(void* arg)
 {
 	char			path[MAX_PATH+1];
+	char			str[256];
 	char			error[256];
 	char			compiler[32];
 	SOCKADDR_IN		server_addr;
@@ -2972,7 +2973,7 @@ void DLLCALL mail_server(void* arg)
 
 		t=time(NULL);
 		lprintf("Initializing on %.24s with options: %lx"
-			,ctime(&t),startup->options);
+			,ctime_r(&t,str,sizeof(str)),startup->options);
 
 		/* Initial configuration and load from CNF files */
 		SAFECOPY(scfg.ctrl_dir,startup->ctrl_dir);
diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp
index a0d543c113aeff371db68074590106dd860e886d..1eb266032b9922b53464301c461ae9119c49d3ae 100644
--- a/src/sbbs3/main.cpp
+++ b/src/sbbs3/main.cpp
@@ -1189,7 +1189,7 @@ void event_thread(void* arg)
 	glob_t		g;
 	sbbs_t*		sbbs = (sbbs_t*) arg;
 	struct tm	now_tm;
-	struct tm*	tm;
+	struct tm	tm;
 
 	eprintf("BBS Events thread started");
 
@@ -1216,7 +1216,7 @@ void event_thread(void* arg)
 	while(!sbbs->terminated && telnet_socket!=INVALID_SOCKET) {
 
 		now=time(NULL);
-		now_tm=*localtime(&now);
+		localtime_r(&now,&now_tm);
 
 		if(now-lastsemchk>=sbbs->cfg.node_sem_check) {
 			check_semaphores=true;
@@ -1494,13 +1494,15 @@ void event_thread(void* arg)
 				}
 			}
 
-			tm=localtime(&sbbs->cfg.qhub[i]->last); /* Qnet call out based on time */
-			if((tm==NULL || sbbs->cfg.qhub[i]->last==-1L					/* or frequency */
+			/* Qnet call out based on time */
+			if(localtime_r(&sbbs->cfg.qhub[i]->last,&tm)==NULL)
+				memset(&tm,0,sizeof(tm));
+			if((sbbs->cfg.qhub[i]->last==-1L					/* or frequency */
 				|| ((sbbs->cfg.qhub[i]->freq
 					&& (now-sbbs->cfg.qhub[i]->last)/60>sbbs->cfg.qhub[i]->freq)
 					|| (sbbs->cfg.qhub[i]->time
 						&& (now_tm.tm_hour*60)+now_tm.tm_min>=sbbs->cfg.qhub[i]->time
-						&& (now_tm.tm_mday!=tm->tm_mday || now_tm.tm_mon!=tm->tm_mon)))
+						&& (now_tm.tm_mday!=tm.tm_mday || now_tm.tm_mon!=tm.tm_mon)))
 						&& sbbs->cfg.qhub[i]->days&(1<<now_tm.tm_wday))) {
 				sprintf(str,"%sqnet/%s.now"
 					,sbbs->cfg.data_dir,sbbs->cfg.qhub[i]->id);
@@ -1565,13 +1567,15 @@ void event_thread(void* arg)
 			if(sbbs->cfg.phub[i]->node<first_node 
 				|| sbbs->cfg.phub[i]->node>last_node)
 				continue;
-			tm=localtime(&sbbs->cfg.phub[i]->last);	  /* PostLink call out based on time */
-			if(tm==NULL || sbbs->cfg.phub[i]->last==-1
+			/* PostLink call out based on time */
+			if(localtime_r(&sbbs->cfg.phub[i]->last,&tm)==NULL)
+				memset(&tm,0,sizeof(tm));
+			if(sbbs->cfg.phub[i]->last==-1
 				|| (((sbbs->cfg.phub[i]->freq								/* or frequency */
 					&& (now-sbbs->cfg.phub[i]->last)/60>sbbs->cfg.phub[i]->freq)
 				|| (sbbs->cfg.phub[i]->time
 					&& (now_tm.tm_hour*60)+now_tm.tm_min>=sbbs->cfg.phub[i]->time
-				&& (now_tm.tm_mday!=tm->tm_mday || now_tm.tm_mon!=tm->tm_mon)))
+				&& (now_tm.tm_mday!=tm.tm_mday || now_tm.tm_mon!=tm.tm_mon)))
 				&& sbbs->cfg.phub[i]->days&(1<<now_tm.tm_wday))) {
 
 				sbbs->cfg.phub[i]->last=time(NULL);
@@ -1609,13 +1613,14 @@ void event_thread(void* arg)
 				&& !(sbbs->cfg.event[i]->misc&EVENT_EXCL))
 				continue;	// ignore non-exclusive events for other instances
 
-			tm=localtime(&sbbs->cfg.event[i]->last);
-			if(tm==NULL || sbbs->cfg.event[i]->last==-1 ||
+			if(localtime_r(&sbbs->cfg.event[i]->last,&tm)==NULL)
+				memset(&tm,0,sizeof(tm));
+			if(sbbs->cfg.event[i]->last==-1 ||
 				(((sbbs->cfg.event[i]->freq 
 					&& (now-sbbs->cfg.event[i]->last)/60>sbbs->cfg.event[i]->freq)
 				|| 	(!sbbs->cfg.event[i]->freq 
 					&& (now_tm.tm_hour*60)+now_tm.tm_min>=sbbs->cfg.event[i]->time
-				&& (now_tm.tm_mday!=tm->tm_mday || now_tm.tm_mon!=tm->tm_mon)))
+				&& (now_tm.tm_mday!=tm.tm_mday || now_tm.tm_mon!=tm.tm_mon)))
 				&& sbbs->cfg.event[i]->days&(1<<now_tm.tm_wday))) 
 			{
 				if(sbbs->cfg.event[i]->misc&EVENT_EXCL) { /* exclusive event */
@@ -2032,13 +2037,13 @@ bool sbbs_t::init()
 		if(filelength(fileno(logfile_fp))) {
 			log(crlf);
 			now=time(NULL);
-			struct tm * tm=localtime(&now);
-			if(tm!=NULL)
+			struct tm tm;
+			localtime_r(&now,&tm);
 			sprintf(str,"%s  %s %s %02d %u  "
 				"End of preexisting log entry (possible crash)"
-				,hhmmtostr(&cfg,tm,tmp)
-				,wday[tm->tm_wday]
-				,mon[tm->tm_mon],tm->tm_mday,tm->tm_year+1900);
+				,hhmmtostr(&cfg,&tm,tmp)
+				,wday[tm.tm_wday]
+				,mon[tm.tm_mon],tm.tm_mday,tm.tm_year+1900);
 			logline("L!",str);
 			log(crlf);
 			catsyslog(1); 
@@ -2751,7 +2756,7 @@ void sbbs_t::catsyslog(int crash)
 	char HUGE16 *buf;
 	int  i,file;
 	long length;
-	struct tm * tm;
+	struct tm tm;
 
 	if(logfile_fp==NULL) {
 		sprintf(str,"%snode.log",cfg.node_dir);
@@ -2773,11 +2778,9 @@ void sbbs_t::catsyslog(int crash)
 			return; 
 		}
 		now=time(NULL);
-		tm=localtime(&now);
-		if(tm==NULL)
-			return;
-		sprintf(str,"%slogs/%2.2d%2.2d%2.2d.log",cfg.data_dir,tm->tm_mon+1,tm->tm_mday
-			,TM_YEAR(tm->tm_year));
+		localtime_r(&now,&tm);
+		sprintf(str,"%slogs/%2.2d%2.2d%2.2d.log",cfg.data_dir,tm.tm_mon+1,tm.tm_mday
+			,TM_YEAR(tm.tm_year));
 		if((file=nopen(str,O_WRONLY|O_APPEND|O_CREAT))==-1) {
 			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_APPEND|O_CREAT);
 			FREE((char *)buf);
@@ -3425,7 +3428,7 @@ void DLLCALL bbs_thread(void* arg)
 
 	t=time(NULL);
 	lprintf("Initializing on %.24s with options: %lx"
-		,ctime(&t),startup->options);
+		,ctime_r(&t,str,sizeof(str)),startup->options);
 
 	if(chdir(startup->ctrl_dir)!=0)
 		lprintf("!ERROR %d changing directory to: %s", errno, startup->ctrl_dir);
diff --git a/src/sbbs3/msgtoqwk.cpp b/src/sbbs3/msgtoqwk.cpp
index c1792f5086e00062e4d2a7323d8e205f07a2ccd2..8fef0899730ef479ed66711b5a1d57f85a210b02 100644
--- a/src/sbbs3/msgtoqwk.cpp
+++ b/src/sbbs3/msgtoqwk.cpp
@@ -52,7 +52,6 @@ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, int subnum
 	long	l,size=0,offset;
 	int 	i;
 	struct	tm	tm;
-	struct	tm* tm_p;
 	smbmsg_t	orig_msg;
 
 	offset=ftell(qwk_fp);
@@ -331,10 +330,7 @@ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, int subnum
 		size++;
 		fputc(SP,qwk_fp); }
 
-	tm_p=localtime((time_t *)&msg->hdr.when_written.time);
-	if(tm_p)
-		tm=*tm_p;
-	else
+	if(localtime_r((time_t *)&msg->hdr.when_written.time,&tm)==NULL)
 		memset(&tm,0,sizeof(tm));
 
 	sprintf(tmp,"%02u-%02u-%02u%02u:%02u"
diff --git a/src/sbbs3/pack_qwk.cpp b/src/sbbs3/pack_qwk.cpp
index 5d1bd5e2c43b0d920fa2d55a34207baf0ac9d425..3a16734a05aecb62efb582afe58703eb161a6fa8 100644
--- a/src/sbbs3/pack_qwk.cpp
+++ b/src/sbbs3/pack_qwk.cpp
@@ -62,7 +62,7 @@ bool sbbs_t::pack_qwk(char *packet, ulong *msgcnt, bool prepack)
 	FILE	*stream,*qwk,*personal,*ndx;
 	DIR*	dir;
 	DIRENT*	dirent;
-	struct	tm* tm;
+	struct	tm tm;
 	smbmsg_t msg;
 
 	ex=EX_OUTL|EX_OUTR;	/* Need sh for wildcard expansion */
@@ -109,8 +109,7 @@ bool sbbs_t::pack_qwk(char *packet, ulong *msgcnt, bool prepack)
 			return(false); }
 
 		now=time(NULL);
-		tm=localtime(&now);
-		if(tm==NULL)
+		if(localtime_r(&now,&tm)==NULL)
 			return(false);
 
 		fprintf(stream,"%s\r\n%s\r\n%s\r\n%s, Sysop\r\n0000,%s\r\n"
@@ -120,8 +119,8 @@ bool sbbs_t::pack_qwk(char *packet, ulong *msgcnt, bool prepack)
 			,cfg.node_phone
 			,cfg.sys_op
 			,cfg.sys_id
-			,tm->tm_mon+1,tm->tm_mday,tm->tm_year+1900
-			,tm->tm_hour,tm->tm_min,tm->tm_sec);
+			,tm.tm_mon+1,tm.tm_mday,tm.tm_year+1900
+			,tm.tm_hour,tm.tm_min,tm.tm_sec);
 		k=0;
 		for(i=0;i<usrgrps;i++)
 			for(j=0;j<usrsubs[i];j++)
diff --git a/src/sbbs3/sbbscon.c b/src/sbbs3/sbbscon.c
index b6bbb9bceb6337ef3ce0f866fd0cf299b0b95498..b5650c7e9d4a7aee8a8534c3db519b5925fcd207 100644
--- a/src/sbbs3/sbbscon.c
+++ b/src/sbbs3/sbbscon.c
@@ -365,7 +365,7 @@ static int bbs_lputs(char *str)
 	char		logline[512];
 	char		tstr[64];
 	time_t		t;
-	struct tm*	tm_p;
+	struct tm	tm;
 
 #ifdef __unix__
 	if (is_daemon)  {
@@ -380,13 +380,12 @@ static int bbs_lputs(char *str)
 #endif
 
 	t=time(NULL);
-	tm_p=localtime(&t);
-	if(tm_p==NULL)
+	if(localtime_r(&t,&tm)==NULL)
 		tstr[0]=0;
 	else
 		sprintf(tstr,"%d/%d %02d:%02d:%02d "
-			,tm_p->tm_mon+1,tm_p->tm_mday
-			,tm_p->tm_hour,tm_p->tm_min,tm_p->tm_sec);
+			,tm.tm_mon+1,tm.tm_mday
+			,tm.tm_hour,tm.tm_min,tm.tm_sec);
 
 	sprintf(logline,"%s     %.*s",tstr,(int)sizeof(logline)-32,str);
 	truncsp(logline);
@@ -419,7 +418,7 @@ static int ftp_lputs(char *str)
 	char		logline[512];
 	char		tstr[64];
 	time_t		t;
-	struct tm*	tm_p;
+	struct tm	tm;
 
 #ifdef __unix__
 	if (is_daemon)  {
@@ -434,13 +433,12 @@ static int ftp_lputs(char *str)
 #endif
 
 	t=time(NULL);
-	tm_p=localtime(&t);
-	if(tm_p==NULL)
+	if(localtime_r(&t,&tm)==NULL)
 		tstr[0]=0;
 	else
 		sprintf(tstr,"%d/%d %02d:%02d:%02d "
-			,tm_p->tm_mon+1,tm_p->tm_mday
-			,tm_p->tm_hour,tm_p->tm_min,tm_p->tm_sec);
+			,tm.tm_mon+1,tm.tm_mday
+			,tm.tm_hour,tm.tm_min,tm.tm_sec);
 
 	sprintf(logline,"%sftp  %.*s",tstr,(int)sizeof(logline)-32,str);
 	truncsp(logline);
@@ -473,7 +471,7 @@ static int mail_lputs(char *str)
 	char		logline[512];
 	char		tstr[64];
 	time_t		t;
-	struct tm*	tm_p;
+	struct tm	tm;
 
 #ifdef __unix__
 	if (is_daemon)  {
@@ -488,13 +486,12 @@ static int mail_lputs(char *str)
 #endif
 
 	t=time(NULL);
-	tm_p=localtime(&t);
-	if(tm_p==NULL)
+	if(localtime_r(&t,&tm)==NULL)
 		tstr[0]=0;
 	else
 		sprintf(tstr,"%d/%d %02d:%02d:%02d "
-			,tm_p->tm_mon+1,tm_p->tm_mday
-			,tm_p->tm_hour,tm_p->tm_min,tm_p->tm_sec);
+			,tm.tm_mon+1,tm.tm_mday
+			,tm.tm_hour,tm.tm_min,tm.tm_sec);
 
 	sprintf(logline,"%smail %.*s",tstr,(int)sizeof(logline)-32,str);
 	truncsp(logline);
@@ -527,7 +524,7 @@ static int services_lputs(char *str)
 	char		logline[512];
 	char		tstr[64];
 	time_t		t;
-	struct tm*	tm_p;
+	struct tm	tm;
 
 #ifdef __unix__
 	if (is_daemon)  {
@@ -542,13 +539,12 @@ static int services_lputs(char *str)
 #endif
 
 	t=time(NULL);
-	tm_p=localtime(&t);
-	if(tm_p==NULL)
+	if(localtime_r(&t,&tm)==NULL)
 		tstr[0]=0;
 	else
 		sprintf(tstr,"%d/%d %02d:%02d:%02d "
-			,tm_p->tm_mon+1,tm_p->tm_mday
-			,tm_p->tm_hour,tm_p->tm_min,tm_p->tm_sec);
+			,tm.tm_mon+1,tm.tm_mday
+			,tm.tm_hour,tm.tm_min,tm.tm_sec);
 
 	sprintf(logline,"%ssrvc %.*s",tstr,(int)sizeof(logline)-32,str);
 	truncsp(logline);
@@ -581,7 +577,7 @@ static int event_lputs(char *str)
 	char		logline[512];
 	char		tstr[64];
 	time_t		t;
-	struct tm*	tm_p;
+	struct tm	tm;
 
 #ifdef __unix__
 	if (is_daemon)  {
@@ -596,13 +592,12 @@ static int event_lputs(char *str)
 #endif
 
 	t=time(NULL);
-	tm_p=localtime(&t);
-	if(tm_p==NULL)
+	if(localtime_r(&t,&tm)==NULL)
 		tstr[0]=0;
 	else
 		sprintf(tstr,"%d/%d %02d:%02d:%02d "
-			,tm_p->tm_mon+1,tm_p->tm_mday
-			,tm_p->tm_hour,tm_p->tm_min,tm_p->tm_sec);
+			,tm.tm_mon+1,tm.tm_mday
+			,tm.tm_hour,tm.tm_min,tm.tm_sec);
 
 	sprintf(logline,"%sevnt %.*s",tstr,(int)sizeof(logline)-32,str);
 	truncsp(logline);
@@ -619,7 +614,7 @@ static int web_lputs(char *str)
 	char		logline[512];
 	char		tstr[64];
 	time_t		t;
-	struct tm*	tm_p;
+	struct tm	tm;
 
 #ifdef __unix__
 	if (is_daemon)  {
@@ -634,13 +629,12 @@ static int web_lputs(char *str)
 #endif
 
 	t=time(NULL);
-	tm_p=localtime(&t);
-	if(tm_p==NULL)
+	if(localtime_r(&t,&tm)==NULL)
 		tstr[0]=0;
 	else
 		sprintf(tstr,"%d/%d %02d:%02d:%02d "
-			,tm_p->tm_mon+1,tm_p->tm_mday
-			,tm_p->tm_hour,tm_p->tm_min,tm_p->tm_sec);
+			,tm.tm_mon+1,tm.tm_mday
+			,tm.tm_hour,tm.tm_min,tm.tm_sec);
 
 	sprintf(logline,"%shttp %.*s",tstr,(int)sizeof(logline)-32,str);
 	truncsp(logline);
diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c
index 6c8671f1846ffdb19ba3a289a555ced3ffd70f95..b78e6468a0938d6602c43ea90b8f6435d5394349 100644
--- a/src/sbbs3/services.c
+++ b/src/sbbs3/services.c
@@ -1220,6 +1220,7 @@ void DLLCALL services_thread(void* arg)
 	char			error[256];
 	char			host_ip[32];
 	char			compiler[32];
+	char			str[128];
 	char			cmd[128];
 	SOCKADDR_IN		addr;
 	SOCKADDR_IN		client_addr;
@@ -1294,7 +1295,7 @@ void DLLCALL services_thread(void* arg)
 
 		t=time(NULL);
 		lprintf("Initializing on %.24s with options: %lx"
-			,ctime(&t),startup->options);
+			,ctime_r(&t,str,sizeof(str)),startup->options);
 
 		/* Initial configuration and load from CNF files */
 		SAFECOPY(scfg.ctrl_dir, startup->ctrl_dir);
diff --git a/src/sbbs3/str.cpp b/src/sbbs3/str.cpp
index e4e0b985c7cec089c466a27743fb5c7d20447d8a..5daf1b4d48860449d2ceb54c51ddc9b29f0ef056 100644
--- a/src/sbbs3/str.cpp
+++ b/src/sbbs3/str.cpp
@@ -497,19 +497,16 @@ bool sbbs_t::inputnstime(time_t *dt)
 {
 	int hour;
 	struct tm tm;
-	struct tm * tp;
 	bool pm=false;
 	char str[256];
 
 	bputs(text[NScanDate]);
 	bputs(timestr(dt));
 	CRLF;
-	tp=localtime(dt);
-	if(tp==NULL) {
+	if(localtime_r(dt,&tm)==NULL) {
 		errormsg(WHERE,ERR_CHK,"time ptr",0);
 		return(FALSE);
 	}
-	tm=*tp;
 
 	bputs(text[NScanYear]);
 	ultoa(tm.tm_year+1900,str,10);
@@ -778,17 +775,16 @@ void sbbs_t::user_info()
 	char	str[128];
 	char	tmp[128];
 	char	tmp2[128];
-	struct	tm * tm;
+	struct	tm tm;
 
 	bprintf(text[UserStats],useron.alias,useron.number);
 
-	tm=localtime(&useron.laston);
-	if(tm!=NULL)
+	if(localtime_r(&useron.laston,&tm)!=NULL)
 		bprintf(text[UserDates]
 			,unixtodstr(&cfg,useron.firston,str)
 			,unixtodstr(&cfg,useron.expire,tmp)
 			,unixtodstr(&cfg,useron.laston,tmp2)
-			,tm->tm_hour,tm->tm_min);
+			,tm.tm_hour,tm.tm_min);
 
 	bprintf(text[UserTimes]
 		,useron.timeon,useron.ttoday
diff --git a/src/sbbs3/tmp_xfer.cpp b/src/sbbs3/tmp_xfer.cpp
index 09402aaf18b3850e29ef3bfe46c2aa48fd82afe2..f1e85ac8094e1fc4aaae6957d86d1ddfa2d55096 100644
--- a/src/sbbs3/tmp_xfer.cpp
+++ b/src/sbbs3/tmp_xfer.cpp
@@ -52,7 +52,7 @@ void sbbs_t::temp_xfer()
     time_t	start,end,t;
     file_t	f;
 	glob_t	g;
-	struct	tm * tm;
+	struct	tm tm;
 
 	if(!usrlibs)
 		return;
@@ -170,10 +170,9 @@ void sbbs_t::temp_xfer()
 					t=now;
 					if(cur_cps) 
 						t+=(f.size/(ulong)cur_cps);
-					tm=localtime(&t);
-					if(tm==NULL)
+					if(localtime_r(&t,&tm)==NULL)
 						break;
-					thisnode.aux=(tm->tm_hour*60)+tm->tm_min;
+					thisnode.aux=(tm.tm_hour*60)+tm.tm_min;
 
 					putnodedat(cfg.node_num,&thisnode); /* calculate ETA */
 					start=time(NULL);
diff --git a/src/sbbs3/userdat.c b/src/sbbs3/userdat.c
index 13b6516e0a73024481ba674797d7bd16cfb2d82b..c727c75327812c8ebc0dc9e9746b40e6e23c05ca 100644
--- a/src/sbbs3/userdat.c
+++ b/src/sbbs3/userdat.c
@@ -569,33 +569,32 @@ int DLLCALL putusername(scfg_t* cfg, int number, char *name)
 char DLLCALL getage(scfg_t* cfg, char *birth)
 {
 	char	age;
-	struct	tm * tm;
+	struct	tm tm;
 	time_t	now;
 
 	if(!atoi(birth) || !atoi(birth+3))	/* Invalid */
 		return(0);
 
 	now=time(NULL);
-	tm=localtime(&now);
-	if(tm==NULL)
+	if(localtime_r(&now,&tm)==NULL)
 		return(0);
-	age=(tm->tm_year)-(((birth[6]&0xf)*10)+(birth[7]&0xf));
+	age=(tm.tm_year)-(((birth[6]&0xf)*10)+(birth[7]&0xf));
 	if(age>105)
 		age-=105;
-	tm->tm_mon++;	/* convert to 1 based */
+	tm.tm_mon++;	/* convert to 1 based */
 	if(cfg->sys_misc&SM_EURODATE) {		/* DD/MM/YY format */
 		if(atoi(birth)>31 || atoi(birth+3)>12)
 			return(0);
-		if(((birth[3]&0xf)*10)+(birth[4]&0xf)>tm->tm_mon ||
-			(((birth[3]&0xf)*10)+(birth[4]&0xf)==tm->tm_mon &&
-			((birth[0]&0xf)*10)+(birth[1]&0xf)>tm->tm_mday))
+		if(((birth[3]&0xf)*10)+(birth[4]&0xf)>tm.tm_mon ||
+			(((birth[3]&0xf)*10)+(birth[4]&0xf)==tm.tm_mon &&
+			((birth[0]&0xf)*10)+(birth[1]&0xf)>tm.tm_mday))
 			age--; }
 	else {							/* MM/DD/YY format */
 		if(atoi(birth)>12 || atoi(birth+3)>31)
 			return(0);
-		if(((birth[0]&0xf)*10)+(birth[1]&0xf)>tm->tm_mon ||
-			(((birth[0]&0xf)*10)+(birth[1]&0xf)==tm->tm_mon &&
-			((birth[3]&0xf)*10)+(birth[4]&0xf)>tm->tm_mday))
+		if(((birth[0]&0xf)*10)+(birth[1]&0xf)>tm.tm_mon ||
+			(((birth[0]&0xf)*10)+(birth[1]&0xf)==tm.tm_mon &&
+			((birth[3]&0xf)*10)+(birth[4]&0xf)>tm.tm_mday))
 			age--; }
 	if(age<0)
 		return(0);
@@ -1037,7 +1036,7 @@ static BOOL ar_exp(scfg_t* cfg, uchar **ptrptr, user_t* user)
 	uint	i,n,artype=AR_LEVEL,age;
 	ulong	l;
 	time_t	now;
-	struct tm * tm;
+	struct tm tm;
 
 	result = TRUE;
 
@@ -1179,9 +1178,9 @@ static BOOL ar_exp(scfg_t* cfg, uchar **ptrptr, user_t* user)
 				break;
 			case AR_DAY:
 				now=time(NULL);
-				tm=localtime(&now);
-				if(tm==NULL || (equal && tm->tm_wday!=(int)n) 
-					|| (!equal && tm->tm_wday<(int)n))
+				localtime_r(&now,&tm);
+				if((equal && tm.tm_wday!=(int)n) 
+					|| (!equal && tm.tm_wday<(int)n))
 					result=not;
 				else
 					result=!not;
@@ -1281,8 +1280,8 @@ static BOOL ar_exp(scfg_t* cfg, uchar **ptrptr, user_t* user)
 				break;
 			case AR_TIME:
 				now=time(NULL);
-				tm=localtime(&now);
-				if(tm==NULL || (tm->tm_hour*60)+tm->tm_min<(int)i)
+				localtime_r(&now,&tm);
+				if((tm.tm_hour*60)+tm.tm_min<(int)i)
 					result=not;
 				else
 					result=!not;
@@ -1600,7 +1599,7 @@ void DLLCALL subtract_cdt(scfg_t* cfg, user_t* user, long amt)
 BOOL DLLCALL logoutuserdat(scfg_t* cfg, user_t* user, time_t now, time_t logontime)
 {
 	char str[128];
-	struct tm* tm, tm_now;
+	struct tm tm, tm_now;
 
 	user->tlast=(now-logontime)/60;
 
@@ -1610,17 +1609,14 @@ BOOL DLLCALL logoutuserdat(scfg_t* cfg, user_t* user, time_t now, time_t logonti
 	adjustuserrec(cfg,user->number,U_TTODAY,5,user->tlast);
 
 	/* Convert time_t to struct tm */
-	tm=localtime(&now);
-	if(tm==NULL)
+	if(localtime_r(&now,&tm_now)==NULL)
 		return(FALSE);
-	tm_now=*tm;
 
-	tm=localtime(&logontime);
-	if(tm==NULL)
+	if(localtime_r(&logontime,&tm)==NULL)
 		return(FALSE);
 
 	/* Reset daily stats if new day */
-	if(tm->tm_mday!=tm_now.tm_mday) 
+	if(tm.tm_mday!=tm_now.tm_mday) 
 		resetdailyuserdat(cfg, user);
 
 	return(TRUE);
diff --git a/src/sbbs3/useredit.cpp b/src/sbbs3/useredit.cpp
index 1519e93b93777e667c2898d8f1a19445ff90cd9e..cb5eb704c284e7fc1ca28382d315fce829c4cbea 100644
--- a/src/sbbs3/useredit.cpp
+++ b/src/sbbs3/useredit.cpp
@@ -58,7 +58,7 @@ void sbbs_t::useredit(int usernumber)
 	uint	i,j,k;
 	long	l;
 	user_t	user;
-	struct	tm * tm;
+	struct	tm tm;
 
 	if(online==ON_REMOTE && console&(CON_R_ECHO|CON_R_INPUT) && !chksyspass())
 		return;
@@ -121,12 +121,11 @@ void sbbs_t::useredit(int usernumber)
 				,user.comment);
 		else
 			CRLF;
-		tm=localtime(&user.laston);
-		if(tm==NULL)
+		if(localtime_r(&user.laston,&tm)==NULL)
 			return;
 		bprintf(text[UserDates]
 			,unixtodstr(&cfg,user.firston,str),unixtodstr(&cfg,user.expire,tmp)
-			,unixtodstr(&cfg,user.laston,tmp2),tm->tm_hour, tm->tm_min);
+			,unixtodstr(&cfg,user.laston,tmp2),tm.tm_hour, tm.tm_min);
 
 		bprintf(text[UserTimes]
 			,user.timeon,user.ttoday,cfg.level_timeperday[user.level]
diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c
index d628841ba54a1001e3f4fff32341a70bc5e065c5..9661186047fbb051cf95aeec286c866b66ac18ba 100644
--- a/src/sbbs3/websrvr.c
+++ b/src/sbbs3/websrvr.c
@@ -661,7 +661,7 @@ static BOOL send_headers(http_session_t *session, const char *status)
 	time_t	ti;
 	char	status_line[MAX_REQUEST_LINE];
 	struct stat	stats;
-	struct tm	*t;
+	struct tm	tm;
 	linked_list	*p;
 
 	SAFECOPY(status_line,status);
@@ -689,8 +689,9 @@ static BOOL send_headers(http_session_t *session, const char *status)
 
 	/* General Headers */
 	ti=time(NULL);
-	t=gmtime(&ti);
-	sockprintf(session->socket,"%s: %s, %02d %s %04d %02d:%02d:%02d GMT",get_header(HEAD_DATE),days[t->tm_wday],t->tm_mday,months[t->tm_mon],t->tm_year+1900,t->tm_hour,t->tm_min,t->tm_sec);
+	if(gmtime_r(&ti,&tm)==NULL)
+		memset(&tm,0,sizeof(tm));
+	sockprintf(session->socket,"%s: %s, %02d %s %04d %02d:%02d:%02d GMT",get_header(HEAD_DATE),days[tm.tm_wday],tm.tm_mday,months[tm.tm_mon],tm.tm_year+1900,tm.tm_hour,tm.tm_min,tm.tm_sec);
 	if(session->req.keep_alive)
 		sockprintf(session->socket,"%s: %s",get_header(HEAD_CONNECTION),"Keep-Alive");
 	else
@@ -716,11 +717,11 @@ static BOOL send_headers(http_session_t *session, const char *status)
 		sockprintf(session->socket,"%s: %s",get_header(HEAD_TYPE)
 			,session->req.mime_type);
 
-		t=gmtime(&stats.st_mtime);
+		gmtime_r(&stats.st_mtime,&tm);
 		sockprintf(session->socket,"%s: %s, %02d %s %04d %02d:%02d:%02d GMT"
 			,get_header(HEAD_LASTMODIFIED)
-			,days[t->tm_wday],t->tm_mday,months[t->tm_mon]
-			,t->tm_year+1900,t->tm_hour,t->tm_min,t->tm_sec);
+			,days[tm.tm_wday],tm.tm_mday,months[tm.tm_mon]
+			,tm.tm_year+1900,tm.tm_hour,tm.tm_min,tm.tm_sec);
 	} else 
 		if(ret)
 			sockprintf(session->socket,"%s: 0",get_header(HEAD_LENGTH));
@@ -2061,7 +2062,7 @@ void DLLCALL web_server(void* arg)
 
 		t=time(NULL);
 		lprintf("Initializing on %.24s with options: %lx"
-			,ctime(&t),startup->options);
+			,ctime_r(&t,logstr,sizeof(logstr)),startup->options);
 
 		lprintf("Root HTML directory: %s", root_dir);
 		lprintf("Error HTML directory: %s", error_dir);
diff --git a/src/sbbs3/xtrn.cpp b/src/sbbs3/xtrn.cpp
index be50781572365135a8fc99f5fd7f6ddc901ed82d..c88144503c853c6487102efc1fa919acdd82780a 100644
--- a/src/sbbs3/xtrn.cpp
+++ b/src/sbbs3/xtrn.cpp
@@ -253,7 +253,7 @@ int sbbs_t::external(char* cmdline, long mode, char* startup_dir)
 	DWORD	retval;
 	DWORD	last_error;
 	DWORD	loop_since_io=0;
-	struct	tm * tm_p;
+	struct	tm tm;
 	sbbsexec_start_t start;
 	OPENVXDHANDLE OpenVxDHandle;
 
@@ -296,7 +296,8 @@ int sbbs_t::external(char* cmdline, long mode, char* startup_dir)
 	SAFECOPY(realcmdline, fullcmdline);	// for errormsg if failed to execute
 
 	now=time(NULL);
-	tm_p=localtime(&now);
+	if(localtime_r(&now,&tm)==NULL)
+		memset(&tm,0,sizeof(tm));
 
 	OpenVxDHandle=GetAddressOfOpenVxDHandle();
 
@@ -327,19 +328,18 @@ int sbbs_t::external(char* cmdline, long mode, char* startup_dir)
 		putenv(sbbsdata);
 		putenv(sbbsexec);
 		putenv(sbbsnnum);
-		if(tm_p!=NULL) {		/* date/time env vars */
-			sprintf(env_day			,"DAY=%02u"			,tm_p->tm_mday);
-			sprintf(env_weekday		,"WEEKDAY=%s"		,wday[tm_p->tm_wday]);
-			sprintf(env_monthname	,"MONTHNAME=%s"		,mon[tm_p->tm_mon]);
-			sprintf(env_month		,"MONTH=%02u"		,tm_p->tm_mon+1);
-			sprintf(env_year		,"YEAR=%u"			,1900+tm_p->tm_year);
-			putenv(env_day);
-			putenv(env_weekday);
-			putenv(env_monthname);
-			putenv(env_month);
-			if(putenv(env_year))
-        		errormsg(WHERE,ERR_WRITE,"environment",0);
-		}
+		/* date/time env vars */
+		sprintf(env_day			,"DAY=%02u"			,tm.tm_mday);
+		sprintf(env_weekday		,"WEEKDAY=%s"		,wday[tm.tm_wday]);
+		sprintf(env_monthname	,"MONTHNAME=%s"		,mon[tm.tm_mon]);
+		sprintf(env_month		,"MONTH=%02u"		,tm.tm_mon+1);
+		sprintf(env_year		,"YEAR=%u"			,1900+tm.tm_year);
+		putenv(env_day);
+		putenv(env_weekday);
+		putenv(env_monthname);
+		putenv(env_month);
+		if(putenv(env_year))
+        	errormsg(WHERE,ERR_WRITE,"environment",0);
 
     } else { // DOS external
 
@@ -361,13 +361,12 @@ int sbbs_t::external(char* cmdline, long mode, char* startup_dir)
 		fprintf(fp, "SBBSDATA=%s\n", cfg.data_dir);
 		fprintf(fp, "SBBSEXEC=%s\n", cfg.exec_dir);
         fprintf(fp, "SBBSNNUM=%d\n", cfg.node_num);
-		if(tm_p!=NULL) {	/* date/time env vars */
-			fprintf(fp, "DAY=%02u\n", tm_p->tm_mday);
-			fprintf(fp, "WEEKDAY=%s\n",wday[tm_p->tm_wday]);
-			fprintf(fp, "MONTHNAME=%s\n",mon[tm_p->tm_mon]);
-			fprintf(fp, "MONTH=%02u\n",tm_p->tm_mon+1);
-			fprintf(fp, "YEAR=%u\n",1900+tm_p->tm_year);
-		}
+		/* date/time env vars */
+		fprintf(fp, "DAY=%02u\n", tm.tm_mday);
+		fprintf(fp, "WEEKDAY=%s\n",wday[tm.tm_wday]);
+		fprintf(fp, "MONTHNAME=%s\n",mon[tm.tm_mon]);
+		fprintf(fp, "MONTH=%02u\n",tm.tm_mon+1);
+		fprintf(fp, "YEAR=%u\n",1900+tm.tm_year);
         fclose(fp);
 
         sprintf(fullcmdline, "%sDOSXTRN.EXE %s", cfg.exec_dir, str);
diff --git a/src/sbbs3/xtrn_sec.cpp b/src/sbbs3/xtrn_sec.cpp
index d37b7ba9923dd7d27a15ce437a50298ab964ede9..a3385dd477d7dbc90d8ee65f643bda638661dd3f 100644
--- a/src/sbbs3/xtrn_sec.cpp
+++ b/src/sbbs3/xtrn_sec.cpp
@@ -218,16 +218,15 @@ int unixtojulian(time_t unix_time)
 {
 	int days[12]={0,31,59,90,120,151,181,212,243,273,304,334};
 	long j;
-	struct tm * tm;
+	struct tm tm;
 
-	tm=localtime(&unix_time);
-	if(tm==NULL)
+	if(localtime_r(&unix_time,&tm)==NULL)
 		return(0);
-	j=36525L*(1900+tm->tm_year);
-	if(!(j%100) && (tm->tm_mon+1)<3)
+	j=36525L*(1900+tm.tm_year);
+	if(!(j%100) && (tm.tm_mon+1)<3)
 		j--;
 	j=(j-(1900*36525))/100;
-	j+=tm->tm_mday+days[tm->tm_mon];
+	j+=tm.tm_mday+days[tm.tm_mon];
 	return(j);
 }
 
@@ -307,8 +306,8 @@ void sbbs_t::xtrndat(char *name, char *dropdir, uchar type, ulong tleft
 	int		i,file;
 	ushort	w;
 	long	l;
-	struct tm * tm;
-	struct tm * tl;
+	struct tm tm;
+	struct tm tl;
 	stats_t stats;
 
 	if(type==XTRN_SBBS) {	/* SBBS XTRN.DAT file */
@@ -564,29 +563,27 @@ void sbbs_t::xtrndat(char *name, char *dropdir, uchar type, ulong tleft
 		lfexpand(str,misc);
 		write(file,str,strlen(str));
 
-		tm=localtime(&ns_time);
-		if(tm!=NULL)
+		localtime_r(&ns_time,&tm);
 		sprintf(str,"%c\n%c\n%u\n%lu\n%02d/%02d/%02d\n"
 			,(useron.misc&(NO_EXASCII|ANSI|COLOR))==ANSI
 				? 'Y':'N'                       /* 39: ANSI supported but NG mode */
 			,'Y'                                /* 40: Use record locking */
 			,14 								/* 41: BBS default color */
 			,useron.min 						/* 42: Time credits in minutes */
-			,tm->tm_mon+1						/* 43: File new-scan date */
-			,tm->tm_mday
-			,TM_YEAR(tm->tm_year));
+			,tm.tm_mon+1						/* 43: File new-scan date */
+			,tm.tm_mday
+			,TM_YEAR(tm.tm_year));
 		lfexpand(str,misc);
 		write(file,str,strlen(str));
 
-		tm=localtime(&logontime);
-		tl=localtime(&useron.laston);
-		if(tm!=NULL && tl!=NULL)
+		localtime_r(&logontime,&tm);
+		localtime_r(&useron.laston,&tl);
 		sprintf(str,"%02d:%02d\n%02d:%02d\n%u\n%u\n%lu\n"
 			"%lu\n%s\n%u\n%u\n"
-			,tm->tm_hour						/* 44: Time of this call */
-			,tm->tm_min
-			,tl->tm_hour						/* 45: Time of last call */
-			,tl->tm_min
+			,tm.tm_hour						/* 44: Time of this call */
+			,tm.tm_min
+			,tl.tm_hour						/* 45: Time of last call */
+			,tl.tm_min
 			,999								/* 46: Max daily files available */
 			,0									/* 47: Files downloaded so far today */
 			,useron.ulb/1024UL					/* 48: Total Kbytes uploaded */
@@ -680,9 +677,8 @@ void sbbs_t::xtrndat(char *name, char *dropdir, uchar type, ulong tleft
 		str2pas(useron.phone,str);
 		write(file,str,13); 					/* DataPhone */
 		write(file,str,13); 					/* HomePhone */
-		tm=localtime(&useron.laston);
-		if(tm!=NULL)
-			sprintf(tmp,"%02d:%02d",tm->tm_hour,tm->tm_min);
+		localtime_r(&useron.laston,&tm);
+		sprintf(tmp,"%02d:%02d",tm.tm_hour,tm.tm_min);
 		str2pas(tmp,str);
 		write(file,str,6);						/* LastTime */
 		unixtodstr(&cfg,useron.laston,tmp);
@@ -742,9 +738,8 @@ void sbbs_t::xtrndat(char *name, char *dropdir, uchar type, ulong tleft
 		write(file,&c,1);						/* NetMailEntered */
 		write(file,&c,1);						/* EchoMailEntered */
 
-		tm=localtime(&logontime);
-		if(tm!=NULL)
-			sprintf(tmp,"%02d:%02d",tm->tm_hour,tm->tm_min);
+		localtime_r(&logontime,&tm);
+		sprintf(tmp,"%02d:%02d",tm.tm_hour,tm.tm_min);
 		str2pas(tmp,str);
 		write(file,str,6);						/* LoginTime */
 		unixtodstr(&cfg,logontime,tmp);
@@ -833,20 +828,18 @@ void sbbs_t::xtrndat(char *name, char *dropdir, uchar type, ulong tleft
 		lfexpand(str,misc);
 		write(file,str,strlen(str));
 
-		tm=localtime(&now);
-		if(tm!=NULL)
+		localtime_r(&now,&tm);
 		sprintf(str,"%lu\n%02d:%02d\n%02d:%02d %02d/%02d/%02d\n%s\n"
 			,tleft								/* Time left in seconds */
-			,tm->tm_hour,tm->tm_min 			/* Current time HH:MM */
-			,tm->tm_hour,tm->tm_min 			/* Current time and date HH:MM */
-			,tm->tm_mon+1,tm->tm_mday			/* MM/DD/YY */
-			,TM_YEAR(tm->tm_year)
+			,tm.tm_hour,tm.tm_min 			/* Current time HH:MM */
+			,tm.tm_hour,tm.tm_min 			/* Current time and date HH:MM */
+			,tm.tm_mon+1,tm.tm_mday			/* MM/DD/YY */
+			,TM_YEAR(tm.tm_year)
 			,nulstr);							/* Conferences with access */
 		lfexpand(str,misc);
 		write(file,str,strlen(str));
 
-		tm=localtime(&useron.laston);
-		if(tm!=NULL)
+		localtime_r(&useron.laston,&tm);
 		sprintf(str,"%u\n%u\n%u\n%u\n%s\n%s %02u:%02u\n"
 			,0									/* Daily download total */
 			,0									/* Max download files */
@@ -854,20 +847,19 @@ void sbbs_t::xtrndat(char *name, char *dropdir, uchar type, ulong tleft
 			,0									/* Max download k total */
 			,useron.phone						/* User phone number */
 			,unixtodstr(&cfg,useron.laston,tmp)	/* Last on date and time */
-			,tm->tm_hour						/* MM/DD/YY  HH:MM */
-			,tm->tm_min);
+			,tm.tm_hour						/* MM/DD/YY  HH:MM */
+			,tm.tm_min);
 		lfexpand(str,misc);
 		write(file,str,strlen(str));
 
-		tm=localtime(&ns_time);
-		if(tm!=NULL)
+		localtime_r(&ns_time,&tm);
 		sprintf(str,"%s\n%s\n%02d/%02d/%02d\n%u\n%lu\n%u"
 			"\n%u\n%u\n"
 			,useron.misc&EXPERT 				/* Expert or Novice mode */
 				? "EXPERT":"NOVICE"
 			,"All"                              /* Transfer Protocol */
-			,tm->tm_mon+1,tm->tm_mday			/* File new-scan date */
-			,TM_YEAR(tm->tm_year)				/* in MM/DD/YY */
+			,tm.tm_mon+1,tm.tm_mday			/* File new-scan date */
+			,TM_YEAR(tm.tm_year)				/* in MM/DD/YY */
 			,useron.logons						/* Total logons */
 			,rows								/* Screen length */
 			,0									/* Highest message read */
@@ -887,12 +879,11 @@ void sbbs_t::xtrndat(char *name, char *dropdir, uchar type, ulong tleft
 		lfexpand(str,misc);
 		write(file,str,strlen(str));
 
-		tm=localtime(&now);
-		if(tm!=NULL)
+		localtime_r(&now,&tm);
 		sprintf(str,"%02d/%02d/%02d %02d:%02d\n%u\n%u\n"
-			,tm->tm_mon+1,tm->tm_mday			/* Current date MM/DD/YY */
-			,TM_YEAR(tm->tm_year)
-			,tm->tm_hour,tm->tm_min 			/* Current time HH:MM */
+			,tm.tm_mon+1,tm.tm_mday			/* Current date MM/DD/YY */
+			,TM_YEAR(tm.tm_year)
+			,tm.tm_hour,tm.tm_min 			/* Current time HH:MM */
 			,cfg.node_num						/* Node number */
 			,0);								/* Door number */
 		lfexpand(str,misc);
@@ -936,18 +927,17 @@ void sbbs_t::xtrndat(char *name, char *dropdir, uchar type, ulong tleft
 			,useron.pass);						/* User's password */
 		write(file,str,27);
 
-		tm=localtime(&logontime);
-		if(tm==NULL)
+		if(localtime_r(&logontime,&tm)==NULL)
 			i=0;
 		else
-			i=(tm->tm_hour*60)+tm->tm_min;
+			i=(tm.tm_hour*60)+tm.tm_min;
 		write(file,&i,2);						/* Logon time in min since mid */
 
 		now=time(NULL);
 		i=-(((now-starttime)/60)+useron.ttoday);/* Negative minutes used */
 		write(file,&i,2);
 
-		sprintf(str,"%02d:%02d",tm->tm_hour,tm->tm_min);
+		sprintf(str,"%02d:%02d",tm.tm_hour,tm.tm_min);
 		write(file,str,5);
 
 		i=cfg.level_timepercall[useron.level];	/* Time allowed on */
@@ -1046,9 +1036,8 @@ void sbbs_t::xtrndat(char *name, char *dropdir, uchar type, ulong tleft
 		write(file,useron.phone,14);	/* Home or Voice Phone */
 		i=unixtojulian(useron.laston);
 		write(file,&i,2);				/* Date last on */
-		tm=localtime(&useron.laston);
-		if(tm!=NULL)
-			sprintf(str,"%02d:%02d",tm->tm_hour,tm->tm_min);
+		localtime_r(&useron.laston,&tm);
+		sprintf(str,"%02d:%02d",tm.tm_hour,tm.tm_min);
 		write(file,str,6);				/* Last time on */
 		if(useron.misc&EXPERT)
 			i=1;
@@ -1114,12 +1103,11 @@ void sbbs_t::xtrndat(char *name, char *dropdir, uchar type, ulong tleft
 		}
 
 		now=time(NULL);
-		tm=localtime(&now);
-		if(tm==NULL)
+		if(localtime_r(&now,&tm)==NULL)
 			l=0;
 		else
-			l=((((long)tm->tm_hour*60L)+(long)tm->tm_min)*60L)
-				+(long)tm->tm_sec;
+			l=((((long)tm.tm_hour*60L)+(long)tm.tm_min)*60L)
+				+(long)tm.tm_sec;
 
 		strcpy(tmp,name);
 		if((p=strchr(tmp,SP))!=NULL)
@@ -1138,12 +1126,11 @@ void sbbs_t::xtrndat(char *name, char *dropdir, uchar type, ulong tleft
 		lfexpand(str,misc);
 		write(file,str,strlen(str));
 
-		tm=localtime(&logontime);
-		if(tm==NULL)
+		if(localtime_r(&logontime,&tm)==NULL)
 			l=0;
 		else
-			l=((((long)tm->tm_hour*60L)+(long)tm->tm_min)*60L)
-				+(long)tm->tm_sec;
+			l=((((long)tm.tm_hour*60L)+(long)tm.tm_min)*60L)
+				+(long)tm.tm_sec;
 
 		sprintf(str,"%s\n%s\n%u\n%u\n%u\n%u\n%lu\n%lu\n%s\n"
 			"%s\n%s\n%lu\n%s\n%u\n%u\n%u\n%u\n%u\n%lu\n%u\n"