xtrn_sec.cpp 47.9 KB
Newer Older
1
2
3
4
5
6
/* Synchronet external program/door section and drop file routines */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
7
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 *																			*
 * This program is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU General Public License				*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

#include "sbbs.h"
23
#include "pcbdefs.hpp"
24
#include "qbbsdefs.hpp"
25
26
27
28
29

/****************************************************************************/
/* This is the external programs (doors) section of the bbs                 */
/* Return 1 if no externals available, 0 otherwise. 						*/
/****************************************************************************/
30
int sbbs_t::xtrn_sec(const char* section)
31
{
32
	char	str[MAX_PATH+1];
33

34
35
36
	if(cfg.xtrnsec_mod[0] == '\0') {
		errormsg(WHERE, ERR_CHK, "xtrnsec_mod", 0);
		return 1;
37
	}
38
39
	SAFEPRINTF2(str, "%s %s", cfg.xtrnsec_mod, section);
	return exec_bin(str, &main_csi);
40
41
}

42
const char *hungupstr="\1n\1h%s\1n hung up on \1h%s\1n %s\r\n";
43
44
45
46

/****************************************************************************/
/* Convert from unix time (seconds since 1/70) to julian (days since 1900)	*/
/****************************************************************************/
47
int unixtojulian(time_t unix_time)
48
49
50
{
	int days[12]={0,31,59,90,120,151,181,212,243,273,304,334};
	long j;
51
	struct tm tm;
52

53
	if(localtime_r(&unix_time,&tm)==NULL)
54
		return(0);
55
56
	j=36525L*(1900+tm.tm_year);
	if(!(j%100) && (tm.tm_mon+1)<3)
57
58
		j--;
	j=(j-(1900*36525))/100;
59
	j+=tm.tm_mday+days[tm.tm_mon];
60
61
62
63
64
65
	return(j);
}

/****************************************************************************/
/* Convert julian date into unix format 									*/
/****************************************************************************/
66
67
68
#ifdef __BORLANDC__
#pragma argsused
#endif
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
time_t juliantounix(ulong j)
{
#if 0 /* julian time */
    int days[2][12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
                       0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335};
    long temp;
	int leap,counter;
	struct tm tm;

	if(!j) return(0L);

	tm.tm_year=((100L*j)/36525L)-1900;
	temp=(long)date.da_year*36525L;
	date.da_year+=1900;
	j-=temp/100L;

	if (!(temp%100)) {
		j++;
87
88
		leap=1; 
	}
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
	else leap=0;

	for(date.da_mon=counter=0;counter<12;counter++)
		if(days[leap][counter]<j)
			date.da_mon=counter;

	date.da_day=j-days[leap][date.da_mon];
	date.da_mon++;	/* go from 0 to 1 based */

	curtime.ti_hour=curtime.ti_min=curtime.ti_sec=0;
	return(dostounix(&date,&curtime));
#else
	return((time_t)-1);
#endif
}

105
106
107
108
109
#ifdef __unix__
static void lfexpand(char *str, ulong misc)
{
	char *p;
	char newstr[1024];
rswindell's avatar
rswindell committed
110
	size_t len=0;
111
112
113
114

	if(misc&XTRN_NATIVE)
		return;

rswindell's avatar
rswindell committed
115
	for(p=str;*p && len < sizeof(newstr)-2;p++) {
116
117
118
119
120
121
122
123
124
125
126
127
		if(*p=='\n')
			newstr[len++]='\r';
		newstr[len++]=*p;
	}

	newstr[len]=0;
	strcpy(str,newstr);
}
#else
	#define lfexpand(str, misc)
#endif

128
129
130
/****************************************************************************/
/* Creates various types of xtrn (Doors, Chains, etc.) data (drop) files.	*/
/****************************************************************************/
131
void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tleft
132
133
					,ulong misc)
{
134
	char	str[1024],tmp2[128],*p;
135
	char 	tmp[512];
deuce's avatar
64-bit    
deuce committed
136
137
	/* TODO: 16-bit i */
	int16_t	i;
138
	FILE*	fp;
deuce's avatar
64-bit    
deuce committed
139
	int32_t	l;
140
141
	struct tm tm;
	struct tm tl;
142
	stats_t stats;
143
	long term = term_supports();
144

145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
	char	node_dir[MAX_PATH+1];
	char	ctrl_dir[MAX_PATH+1];
	char	data_dir[MAX_PATH+1];
	char	exec_dir[MAX_PATH+1];
	char	text_dir[MAX_PATH+1];
	char	temp_dir[MAX_PATH+1];

	SAFECOPY(node_dir,cfg.node_dir);
	SAFECOPY(ctrl_dir,cfg.ctrl_dir);
	SAFECOPY(data_dir,cfg.data_dir);
	SAFECOPY(exec_dir,cfg.exec_dir);
	SAFECOPY(text_dir,cfg.text_dir);
	SAFECOPY(temp_dir,cfg.temp_dir);

	if(!(misc&XTRN_NATIVE)) {
160
#ifdef _WIN32
161
162
		/* Put Micros~1 shortened paths in drop files when running 16-bit DOS programs */
		GetShortPathName(cfg.node_dir,node_dir,sizeof(node_dir));
163
		GetShortPathName(cfg.ctrl_dir,ctrl_dir,sizeof(ctrl_dir));
164
165
166
167
		GetShortPathName(cfg.data_dir,data_dir,sizeof(data_dir));
		GetShortPathName(cfg.exec_dir,exec_dir,sizeof(exec_dir));
		GetShortPathName(cfg.text_dir,text_dir,sizeof(text_dir));
		GetShortPathName(cfg.temp_dir,temp_dir,sizeof(temp_dir));
168
169
#elif defined(__linux__) && defined(USE_DOSEMU)
		/* These drive mappings must match the Linux/DOSEMU patch in xtrn.cpp: */
170
171
172
173
174
175
		SAFECOPY(node_dir, DOSEMU_NODE_DIR);
		SAFECOPY(ctrl_dir, DOSEMU_CTRL_DIR);
		SAFECOPY(data_dir, DOSEMU_DATA_DIR);
		SAFECOPY(exec_dir, DOSEMU_EXEC_DIR);
		SAFECOPY(text_dir, DOSEMU_TEXT_DIR);
		SAFECOPY(temp_dir, DOSEMU_TEMP_DIR);
176
#endif
177
178
179
	}


180
	if(type==XTRN_SBBS) {	/* SBBS XTRN.DAT file */
Rob Swindell's avatar
Rob Swindell committed
181
		SAFECOPY(tmp,"XTRN.DAT");
182
183
		if(misc&XTRN_LWRCASE)
			strlwr(tmp);
Rob Swindell's avatar
Rob Swindell committed
184
		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
185
		(void)removecase(str);
186
		if((fp=fnopen(NULL,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT)) == NULL) {
187
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
188
189
			return; 
		}
190

191
		safe_snprintf(str, sizeof(str), "%s\n%s\n%s\n%s\n"
192
193
194
195
			,name								/* User name */
			,cfg.sys_name						/* System name */
			,cfg.sys_op 						/* Sysop name */
			,cfg.sys_guru); 					/* Guru name */
196
		lfexpand(str,misc);
197
		fwrite(str,strlen(str),1,fp);
198

199
		safe_snprintf(str, sizeof(str), "%s\n%s\n%u\n%u\n%lu\n%s\n%lu\n%lu\n"
200
201
			,ctrl_dir							/* Ctrl dir */
			,data_dir							/* Data dir */
202
203
204
			,cfg.sys_nodes						/* Total system nodes */
			,cfg.node_num						/* Current node */
			,tleft								/* User Timeleft in seconds */
205
206
			,(term & ANSI)						/* User ANSI ? (Yes/Mono/No) */
				? (term & COLOR)
207
208
209
				? "Yes":"Mono":"No"
			,rows								/* User Screen lines */
			,useron.cdt+useron.freecdt);		/* User Credits */
210
		lfexpand(str,misc);
211
		fwrite(str,strlen(str),1,fp);
212

213
		safe_snprintf(str, sizeof(str), "%u\n%u\n%s\n%c\n%u\n%s\n"
214
215
			,useron.level						/* User main level */
			,useron.level						/* User transfer level */
216
			,getbirthmmddyy(&cfg, useron.birth, tmp, sizeof(tmp)) /* User birthday (MM/DD/YY) */
217
			,useron.sex ? useron.sex : '?'		/* User sex (M/F) */
218
219
			,useron.number						/* User number */
			,useron.phone); 					/* User phone number */
220
		lfexpand(str,misc);
221
		fwrite(str,strlen(str),1,fp);
222

223
		safe_snprintf(str, sizeof(str), "%u\n%u\n%x\n%lu\n%s\n%s\n"
224
			"%s\n%s\n%s\n%s\n%s\n%s\n%lu\n"
225
			,misc&(XTRN_STDIO|XTRN_CONIO) ? 0:cfg.com_port		/* Com port or 0 if !FOSSIL */
226
227
228
229
230
231
232
233
234
235
236
			,cfg.com_irq						/* Com IRQ */
			,cfg.com_base						/* Com base in hex */
			,dte_rate							/* Com rate */
			,"Yes"								/* Hardware flow ctrl Y/N */
			,"Yes"								/* Locked DTE rate Y/N */
			,cfg.mdm_init						/* Modem initialization string */
			,cfg.mdm_spec						/* Modem special init string */
			,cfg.mdm_term						/* Modem terminal mode init str */
			,cfg.mdm_dial						/* Modem dial string */
			,cfg.mdm_offh						/* Modem off-hook string */
			,cfg.mdm_answ						/* Modem answer string */
237
			,0L
238
			);
239
		lfexpand(str,misc);
240
		fwrite(str,strlen(str),1,fp);
241

Rob Swindell's avatar
Rob Swindell committed
242
		SAFEPRINTF(str,"%u\n",cfg.total_xtrns);
243
		lfexpand(str,misc);
244
		fwrite(str,strlen(str),1,fp);			/* Total external programs */
245
246

		for(i=0;i<cfg.total_xtrns;i++) {		/* Each program's name */
Rob Swindell's avatar
Rob Swindell committed
247
248
249
			if(SYSOP || chk_ar(cfg.xtrn[i]->ar,&useron,&client)) {
				SAFECOPY(str,cfg.xtrn[i]->name);
			} else
250
				str[0]=0;						/* Blank if no access */
rswindell's avatar
rswindell committed
251
			SAFECAT(str,"\n");
252
			lfexpand(str,misc);
253
			fwrite(str,strlen(str),1,fp);
254
		}
255

Rob Swindell's avatar
Rob Swindell committed
256
		SAFEPRINTF2(str,"%s\n%s\n"
257
258
259
			,ltoaf(useron.flags1,tmp)			/* Main flags */
			,ltoaf(useron.flags2,tmp2)			/* Transfer flags */
			);
260
		lfexpand(str,misc);
261
		fwrite(str,strlen(str),1,fp);
262

Rob Swindell's avatar
Rob Swindell committed
263
		safe_snprintf(str, sizeof(str), "%s\n%s\n%lx\n%s\n%s\n%s\n"
264
265
			,ltoaf(useron.exempt,tmp)			/* Exemptions */
			,ltoaf(useron.rest,tmp2)			/* Restrictions */
266
			,(long)useron.expire				/* Expiration date in unix form */
267
268
269
270
			,useron.address 					/* Address */
			,useron.location					/* City/State */
			,useron.zipcode 					/* Zip/Postal code */
			);
271
		lfexpand(str,misc);
272
		fwrite(str,strlen(str),1,fp);
273

274
		safe_snprintf(str, sizeof(str), "%s\n%s\n%d\n%s\n%lu\n%s\n%s\n%s\n%s\n"
275
			"%" PRIx32 "\n%d\n"
276
277
			,ltoaf(useron.flags3,tmp)			/* Flag set #3 */
			,ltoaf(useron.flags4,tmp2)			/* Flag set #4 */
278
			,0									/* Time-slice type */
279
280
			,useron.name						/* Real name/company */
			,cur_rate							/* DCE rate */
281
282
283
			,exec_dir
			,text_dir
			,temp_dir
284
285
			,cfg.sys_id
			,cfg.node_misc
286
			,misc&(XTRN_STDIO|XTRN_CONIO) ? INVALID_SOCKET : client_socket_dup
287
			);
288
		lfexpand(str,misc);
289
		fwrite(str,strlen(str),1,fp);
290

291
		fclose(fp); 
292
	}
293
294

	else if(type==XTRN_WWIV) {	/*	WWIV CHAIN.TXT File */
Rob Swindell's avatar
Rob Swindell committed
295
		SAFECOPY(tmp,"CHAIN.TXT");
296
297
		if(misc&XTRN_LWRCASE)
			strlwr(tmp);
Rob Swindell's avatar
Rob Swindell committed
298
		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
299
		(void)removecase(str);
300
		if((fp=fnopen(NULL, str, O_WRONLY|O_CREAT|O_TRUNC)) == NULL) {
301
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
302
303
			return; 
		}
304

305
306
307
		if(tleft>0x7fff)	/* Reduce time-left for broken 16-bit doors		*/
			tleft=0x7fff;	/* That interpret this value as a signed short	*/

308
		safe_snprintf(str, sizeof(str), "%u\n%s\n%s\n%s\n%u\n%c\n"
309
310
311
312
313
			,useron.number						/* User number */
			,name								/* User name */
			,useron.name						/* User real name */
			,nulstr 							/* User call sign */
			,getage(&cfg,useron.birth)			/* User age */
314
			,useron.sex ? useron.sex : '?');	/* User sex (M/F) */
315
		strupr(str);
316
		lfexpand(str,misc);
317
		fwrite(str,strlen(str),1,fp);
318

319
		safe_snprintf(str, sizeof(str), "%lu\n%s\n%lu\n%ld\n%u\n%u\n%u\n%d\n%u\n"
320
321
			,useron.cdt+useron.freecdt			/* Gold */
			,unixtodstr(&cfg,useron.laston,tmp)	/* User last on date */
322
			,cols 								/* User screen width */
323
324
325
326
			,rows								/* User screen length */
			,useron.level						/* User SL */
			,0									/* Cosysop? */
			,SYSOP								/* Sysop? (1/0) */
327
			,INT_TO_BOOL(term & ANSI)			/* ANSI ? (1/0) */
328
			,online==ON_REMOTE);				/* Remote (1/0) */
329
		lfexpand(str,misc);
330
		fwrite(str,strlen(str),1,fp);
331

332
		safe_snprintf(str, sizeof(str), "%lu\n%s\n%s\n%s\n%lu\n%d\n%s\n%s\n"
333
			"%u\n%u\n%lu\n%u\n%lu\n%u\n%s\n"
334
			,tleft								/* Time left in seconds */
335
336
			,node_dir							/* Gfiles dir (log dir) */
			,data_dir							/* Data dir */
337
			,"node.log"                         /* Name of log file */
338
339
340
341
342
343
344
345
346
347
348
			,dte_rate							/* DTE rate */
			,cfg.com_port						/* COM port number */
			,cfg.sys_name						/* System name */
			,cfg.sys_op 						/* Sysop name */
			,0									/* Logon time (sec past 12am) */
			,0									/* Current time (sec past 12am) */
			,useron.ulb/1024UL					/* User uploaded kbytes */
			,useron.uls 						/* User uploaded files */
			,useron.dlb/1024UL					/* User downloaded kbytes */
			,useron.dls 						/* User downloaded files */
			,"8N1");                            /* Data, parity, stop bits */
349
		lfexpand(str,misc);
350
		fwrite(str,strlen(str),1,fp);
351

352
		fclose(fp); 
353
	}
354
355

	else if(type==XTRN_GAP) {	/* Gap DOOR.SYS File */
Rob Swindell's avatar
Rob Swindell committed
356
		SAFECOPY(tmp,"DOOR.SYS");
357
358
		if(misc&XTRN_LWRCASE)
			strlwr(tmp);
Rob Swindell's avatar
Rob Swindell committed
359
		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
360
		(void)removecase(str);
361
		if((fp=fnopen(NULL,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT)) == NULL) {
362
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
363
364
			return; 
		}
365

366
367
368
		if(tleft>0x7fff)	/* Reduce time-left for broken 16-bit doors		*/
			tleft=0x7fff;	/* That interpret this value as a signed short	*/

Rob Swindell's avatar
Rob Swindell committed
369
		SAFEPRINTF(str,"COM%d:\n"
370
			,online==ON_REMOTE ? cfg.com_port:0);	/* 01: COM port - 0 if Local */
Rob Swindell's avatar
Rob Swindell committed
371

372
		lfexpand(str,misc);
373
		fwrite(str,strlen(str),1,fp);
374
375
376
377
378
379
380
381
		/* Note about door.sys, line 2 (April-24-2005):
		   It *should* be the DCE rate (any number, including the popular modem
		   DCE rates of 14400, 28800, and 33600).  However, according to Deuce,
		   doors created with the DMlib door kit choke with "Error -25: Illegal
		   baud rate" if this isn't a valid FOSSIL baud (DTE) rate, so we're
		   changing this value to the DTE rate until/unless some other doors
		   have an issue with that. <sigh>
		*/
Rob Swindell's avatar
Rob Swindell committed
382
		safe_snprintf(str, sizeof(str), "%lu\n%u\n%u\n%lu\n%c\n%c\n%c\n%c\n"
383
			,dte_rate /* was cur_rate */		/* 02: DCE rate, see note above */
384
385
386
			,8									/* 03: Data bits */
			,cfg.node_num						/* 04: Node number */
			,dte_rate							/* 05: DTE rate */
387
			,'Y'								/* 06: Screen display */
388
389
390
			,'Y'                                /* 07: Printer toggle */
			,'Y'                                /* 08: Page bell */
			,'Y');                              /* 09: Caller alarm */
391
		lfexpand(str,misc);
392
		fwrite(str,strlen(str),1,fp);
393

Rob Swindell's avatar
Rob Swindell committed
394
		safe_snprintf(str, sizeof(str), "%s\n%s\n%s\n%s\n%s\n"
395
396
397
398
399
			,name								/* 10: User name */
			,useron.location					/* 11: User location */
			,useron.phone						/* 12: User home phone */
			,useron.phone						/* 13: User work/data phone */
			,useron.pass);						/* 14: User password */
400
		lfexpand(str,misc);
401
		fwrite(str,strlen(str),1,fp);
402

Rob Swindell's avatar
Rob Swindell committed
403
		safe_snprintf(str, sizeof(str), "%u\n%u\n%s\n%lu\n%lu\n%s\n"
404
405
406
407
408
			,useron.level						/* 15: User security level */
			,useron.logons						/* 16: User total logons */
			,unixtodstr(&cfg,useron.laston,tmp)	/* 17: User last on date */
			,tleft								/* 18: User time left in sec */
			,tleft/60							/* 19: User time left in min */
409
410
			,(term & NO_EXASCII)				/* 20: GR if COLOR ANSI */
				? "7E" : (term & (ANSI|COLOR)) == (ANSI|COLOR) ? "GR" : "NG");
411
		lfexpand(str,misc);
412
		fwrite(str,strlen(str),1,fp);
413

Rob Swindell's avatar
Rob Swindell committed
414
		safe_snprintf(str, sizeof(str), "%lu\n%c\n%s\n%u\n%s\n%u\n%c\n%u\n%u\n"
415
			,rows								/* 21: User screen length */
416
			,(useron.misc&EXPERT) ? 'Y':'N'     /* 22: Expert? (Y/N) */
417
418
419
420
			,ltoaf(useron.flags1,tmp2)			/* 23: Registered conferences */
			,0									/* 24: Conference came from */
			,unixtodstr(&cfg,useron.expire,tmp)	/* 25: User expiration date */
			,useron.number						/* 26: User number */
421
			,useron.prot                        /* 27: Default protocol */
422
423
			,useron.uls 						/* 28: User total uploads */
			,useron.dls);						/* 29: User total downloads */
424
		lfexpand(str,misc);
425
		fwrite(str,strlen(str),1,fp);
426

427
		safe_snprintf(str, sizeof(str), "%u\n%lu\n%s\n%s\n%s\n%s"
428
			"\n%s\n%02d:%02d\n%c\n"
429
430
			,0									/* 30: Kbytes downloaded today */
			,(useron.cdt+useron.freecdt)/1024UL /* 31: Max Kbytes to download today */
431
			,getbirthmmddyy(&cfg, useron.birth, tmp, sizeof(tmp))	/* 32: User birthday (MM/DD/YY) */
432
433
			,node_dir							/* 33: Path to MAIN directory */
			,data_dir							/* 34: Path to GEN directory */
434
435
436
437
438
			,cfg.sys_op 						/* 35: Sysop name */
			,nulstr 							/* 36: Alias name */
			,0 // sys_eventtime/60				/* 37: Event time HH:MM */
			,0 // sys_eventtime%60
			,'Y');                              /* 38: Error correcting connection */
439
		lfexpand(str,misc);
440
		fwrite(str,strlen(str),1,fp);
441

442
		localtime_r(&ns_time,&tm);
443
		safe_snprintf(str, sizeof(str), "%c\n%c\n%u\n%" PRIu32 "\n%02d/%02d/%02d\n"
444
			,(term & (NO_EXASCII|ANSI|COLOR)) == ANSI
445
446
				? 'Y':'N'                       /* 39: ANSI supported but NG mode */
			,'Y'                                /* 40: Use record locking */
447
			,cfg.color[clr_external]			/* 41: BBS default color */
448
			,useron.min 						/* 42: Time credits in minutes */
449
450
451
			,tm.tm_mon+1						/* 43: File new-scan date */
			,tm.tm_mday
			,TM_YEAR(tm.tm_year));
452
		lfexpand(str,misc);
453
		fwrite(str,strlen(str),1,fp);
454

deuce's avatar
deuce committed
455
		localtime_r(&logontime,&tm);
456
		localtime32(&useron.laston,&tl);
Rob Swindell's avatar
Rob Swindell committed
457
		safe_snprintf(str, sizeof(str), "%02d:%02d\n%02d:%02d\n%u\n%u\n%lu\n"
458
			"%lu\n%s\n%u\n%u\n"
459
			,tm.tm_hour							/* 44: Time of this call */
460
			,tm.tm_min
461
			,tl.tm_hour							/* 45: Time of last call */
462
			,tl.tm_min
463
464
465
466
467
468
469
			,999								/* 46: Max daily files available */
			,0									/* 47: Files downloaded so far today */
			,useron.ulb/1024UL					/* 48: Total Kbytes uploaded */
			,useron.dlb/1024UL					/* 49: Total Kbytes downloaded */
			,useron.comment 					/* 50: User comment */
			,0									/* 51: Total doors opened */
			,useron.posts); 					/* 52: User message left */
470
		lfexpand(str,misc);
471
		fwrite(str,strlen(str),1,fp);
472

473
		fclose(fp);
474
	}
475
476

	else if(type==XTRN_RBBS || type==XTRN_RBBS1) {
Rob Swindell's avatar
Rob Swindell committed
477
478
479
480
481
		if(type==XTRN_RBBS) {
			SAFEPRINTF(tmp,"DORINFO%X.DEF",cfg.node_num);   /* support 1-F */
		} else {
			SAFECOPY(tmp,"DORINFO1.DEF");
		}
482
483
		if(misc&XTRN_LWRCASE)
			strlwr(tmp);
Rob Swindell's avatar
Rob Swindell committed
484
		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
485
		(void)removecase(str);
486
		if((fp = fnopen(NULL,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT)) == NULL) {
487
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
488
489
			return; 
		}
490

Rob Swindell's avatar
Rob Swindell committed
491
		SAFECOPY(tmp,cfg.sys_op);
492
		p=strchr(tmp,' ');
493
494
495
		if(p)
			*(p++)=0;
		else
496
			p=(char*)nulstr;
497

Rob Swindell's avatar
Rob Swindell committed
498
		safe_snprintf(str, sizeof(str), "%s\n%s\n%s\nCOM%d\n%lu BAUD,N,8,1\n%u\n"
499
500
501
502
503
504
505
			,cfg.sys_name						/* Name of BBS */
			,tmp								/* Sysop's firstname */
			,p									/* Sysop's lastname */
			,online==ON_REMOTE ? cfg.com_port:0 /* COM port number, 0 if local */
			,dte_rate							/* DTE rate */
			,0);								/* Network type */
		strupr(str);
506
		lfexpand(str,misc);
507
		fwrite(str,strlen(str),1,fp);
508

Rob Swindell's avatar
Rob Swindell committed
509
		SAFECOPY(tmp,name);
510
		p=strchr(tmp,' ');
511
512
513
		if(p)
			*(p++)=0;
		else
514
			p=(char*)nulstr;
515
		safe_snprintf(str, sizeof(str), "%s\n%s\n%s\n%d\n%u\n%lu\n"
516
517
518
			,tmp								/* User's firstname */
			,p									/* User's lastname */
			,useron.location					/* User's city */
519
			,INT_TO_BOOL(term & ANSI)			/* 1=ANSI 0=ASCII */
520
521
522
			,useron.level						/* Security level */
			,tleft/60); 						/* Time left in minutes */
		strupr(str);
523
		lfexpand(str,misc);
524
		fwrite(str,strlen(str),1,fp);
525

526
		fclose(fp);
527

Rob Swindell's avatar
Rob Swindell committed
528
		SAFECOPY(tmp,"EXITINFO.BBS");
529
530
		if(misc&XTRN_LWRCASE)
			strlwr(tmp);
Rob Swindell's avatar
Rob Swindell committed
531
		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
532
		(void)removecase(str);
533
		if((fp=fnopen(NULL,str,O_WRONLY|O_CREAT|O_TRUNC)) == NULL) {
534
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
535
536
			return; 
		}
537
		getstats(&cfg,0,&stats);
538
539
540
541
542
543
544
		QBBS::exitinfo exitinfo{};
		exitinfo.BaudRate = (uint16_t)dte_rate;
		exitinfo.SysInfo.CallCount = stats.logons;
		exitinfo.UserInfo.Name = name;
		exitinfo.UserInfo.Location = useron.location;
		exitinfo.UserInfo.DataPhone = useron.phone;
		exitinfo.UserInfo.HomePhone = useron.phone;
545
		localtime32(&useron.laston,&tm);
Rob Swindell's avatar
Rob Swindell committed
546
		SAFEPRINTF2(tmp,"%02d:%02d",tm.tm_hour,tm.tm_min);
547
		exitinfo.UserInfo.LastTime = tmp;
548
		unixtodstr(&cfg,useron.laston,tmp);
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
		exitinfo.UserInfo.LastDate = tmp;
		if(useron.misc&DELETED) exitinfo.UserInfo.Attrib |= QBBS::USER_ATTRIB_DELETED;
		if(useron.misc&CLRSCRN) exitinfo.UserInfo.Attrib |= QBBS::USER_ATTRIB_CLRSCRN;
		if(useron.misc&UPAUSE)	exitinfo.UserInfo.Attrib |= QBBS::USER_ATTRIB_MORE;
		if(term & ANSI)			exitinfo.UserInfo.Attrib |= QBBS::USER_ATTRIB_ANSI;
		if(useron.sex=='F')     exitinfo.UserInfo.Attrib |= QBBS::USER_ATTRIB_FEMALE;
		exitinfo.UserInfo.Flags = useron.flags1;
		exitinfo.UserInfo.TimesPosted = useron.posts;
		exitinfo.UserInfo.SecLvl = useron.level;
		exitinfo.UserInfo.Ups = useron.uls;
		exitinfo.UserInfo.Downs = useron.dls;
		exitinfo.UserInfo.UpK = (uint16_t)(useron.ulb/1024UL);
		exitinfo.UserInfo.DownK = (uint16_t)(useron.dlb/1024UL);
		exitinfo.UserInfo.TodayK = (uint16_t)(logon_dlb/1024UL);
		exitinfo.UserInfo.ScreenLength = (int16_t)rows;
deuce's avatar
deuce committed
564
		localtime_r(&logontime,&tm);
Rob Swindell's avatar
Rob Swindell committed
565
		SAFEPRINTF2(tmp,"%02d:%02d",tm.tm_hour,tm.tm_min);
566
		exitinfo.LoginTime = tmp;
567
		unixtodstr(&cfg,(time32_t)logontime,tmp);
568
569
		exitinfo.LoginDate = tmp;
		exitinfo.TimeLimit = cfg.level_timepercall[useron.level];
570
		exitinfo.Credit = (uint32_t)MIN(useron.cdt, UINT32_MAX);
571
572
573
574
575
576
577
578
579
580
581
		exitinfo.UserRecNum = useron.number;
		exitinfo.WantChat = (sys_status & SS_SYSPAGE);
		exitinfo.ScreenClear = (useron.misc & CLRSCRN);
		exitinfo.MorePrompts = (useron.misc & UPAUSE);
		exitinfo.GraphicsMode = !(term & NO_EXASCII);
		exitinfo.ExternEdit = (useron.xedit);
		exitinfo.ScreenLength = (int16_t)rows;
		exitinfo.MNP_Connect = true;
		exitinfo.ANSI_Capable = (term & ANSI);
		exitinfo.RIP_Active = (term & RIP);

582
583
		fwrite(&exitinfo, sizeof(exitinfo), 1, fp);
		fclose(fp);
584
	}
585
586

	else if(type==XTRN_WILDCAT) { /* WildCat CALLINFO.BBS File */
Rob Swindell's avatar
Rob Swindell committed
587
		SAFECOPY(tmp,"CALLINFO.BBS");
588
589
		if(misc&XTRN_LWRCASE)
			strlwr(tmp);
Rob Swindell's avatar
Rob Swindell committed
590
		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
591
		(void)removecase(str);
592
		if((fp=fnopen(NULL,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT)) == NULL) {
593
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
594
595
			return; 
		}
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619

		if(online==ON_LOCAL) i=5;
		else
			switch(dte_rate) {
				case 300:
					i=1;
					break;
				case 1200:
					i=2;
					break;
				case 2400:
					i=0;
					break;
				case 9600:
					i=3;
					break;
				case 19200:
					i=4;
					break;
				case 38400:
					i=6;
					break;
				default:
					i=7;
620
621
					break; 
		}
Rob Swindell's avatar
Rob Swindell committed
622
		safe_snprintf(str, sizeof(str), "%s\n%u\n%s\n%u\n%lu\n%s\n%s\n%u\n"
623
624
625
626
627
			,name								/* User name */
			,i									/* DTE rate */
			,useron.location					/* User location */
			,useron.level						/* Security level */
			,tleft/60							/* Time left in min */
628
			,(term & ANSI) ? "COLOR":"MONO"		/* ANSI ??? */
629
630
			,useron.pass						/* Password */
			,useron.number);					/* User number */
631
		lfexpand(str,misc);
632
		fwrite(str,strlen(str),1,fp);
633

634
		localtime_r(&now,&tm);
Rob Swindell's avatar
Rob Swindell committed
635
		safe_snprintf(str, sizeof(str), "%lu\n%02d:%02d\n%02d:%02d %02d/%02d/%02d\n%s\n"
636
			,tleft								/* Time left in seconds */
637
638
639
640
			,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)
641
			,nulstr);							/* Conferences with access */
642
		lfexpand(str,misc);
643
		fwrite(str,strlen(str),1,fp);
644

645
		localtime32(&useron.laston,&tm);
Rob Swindell's avatar
Rob Swindell committed
646
		safe_snprintf(str, sizeof(str), "%u\n%u\n%u\n%u\n%s\n%s %02u:%02u\n"
647
648
649
650
651
652
			,0									/* Daily download total */
			,0									/* Max download files */
			,0									/* Daily download k total */
			,0									/* Max download k total */
			,useron.phone						/* User phone number */
			,unixtodstr(&cfg,useron.laston,tmp)	/* Last on date and time */
653
654
			,tm.tm_hour						/* MM/DD/YY  HH:MM */
			,tm.tm_min);
655
		lfexpand(str,misc);
656
		fwrite(str,strlen(str),1,fp);
657

658
		localtime_r(&ns_time,&tm);
Rob Swindell's avatar
Rob Swindell committed
659
		safe_snprintf(str, sizeof(str), "%s\n%s\n%02d/%02d/%02d\n%u\n%lu\n%u"
660
			"\n%u\n%u\n"
661
662
663
			,useron.misc&EXPERT 				/* Expert or Novice mode */
				? "EXPERT":"NOVICE"
			,"All"                              /* Transfer Protocol */
664
665
			,tm.tm_mon+1,tm.tm_mday			/* File new-scan date */
			,TM_YEAR(tm.tm_year)				/* in MM/DD/YY */
666
667
668
669
670
			,useron.logons						/* Total logons */
			,rows								/* Screen length */
			,0									/* Highest message read */
			,useron.uls 						/* Total files uploaded */
			,useron.dls);						/* Total files downloaded */
671
		lfexpand(str,misc);
672
		fwrite(str,strlen(str),1,fp);
673

Rob Swindell's avatar
Rob Swindell committed
674
		safe_snprintf(str, sizeof(str), "%u\n%s\nCOM%u\n%s\n%lu\n%s\n%s\n"
675
676
677
			,8									/* Data bits */
			,online==ON_LOCAL?"LOCAL":"REMOTE"  /* Online local or remote */
			,cfg.com_port						/* COMx port */
678
			,getbirthmmddyy(&cfg, useron.birth, tmp, sizeof(tmp))	/* User birthday (MM/DD/YY) */
679
680
681
			,dte_rate							/* DTE rate */
			,"FALSE"                            /* Already connected? */
			,"Normal Connection");              /* Normal or ARQ connect */
682
		lfexpand(str,misc);
683
		fwrite(str,strlen(str),1,fp);
684

685
		localtime_r(&now,&tm);
Rob Swindell's avatar
Rob Swindell committed
686
		safe_snprintf(str, sizeof(str), "%02d/%02d/%02d %02d:%02d\n%u\n%u\n"
687
688
689
			,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 */
690
691
			,cfg.node_num						/* Node number */
			,0);								/* Door number */
692
		lfexpand(str,misc);
693
		fwrite(str,strlen(str),1,fp);
694

695
		fclose(fp);
696
	}
697
698

	else if(type==XTRN_PCBOARD) { /* PCBoard Files */
Rob Swindell's avatar
Rob Swindell committed
699
		SAFECOPY(tmp,"PCBOARD.SYS");
700
701
		if(misc&XTRN_LWRCASE)
			strlwr(tmp);
Rob Swindell's avatar
Rob Swindell committed
702
		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
703
		(void)removecase(str);
704
		if((fp = fnopen(NULL, str,O_WRONLY|O_CREAT|O_TRUNC)) == NULL) {
705
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
706
707
			return; 
		}
708
709
710
711
712
713
714
		PCBoard::sys sys{};
		sys.Screen = true;
		sys.PageBell = sys_status & SS_SYSPAGE;
		sys.Alarm = startup->sound.answer[0] && !sound_muted(&cfg);
		sys.ErrorCorrected = true;
		sys.GraphicsMode = (term & NO_EXASCII) ? 'N' : 'Y';
		sys.UserNetStatus = (thisnode.misc & NODE_POFF) ? 'U' : 'A'; /* Node chat status ([A]vailable or [U]navailable) */
Rob Swindell's avatar
Rob Swindell committed
715
		SAFEPRINTF(tmp, "%lu", dte_rate);
716
717
718
		sys.ModemSpeed = tmp;
		sys.CarrierSpeed = connection;
		sys.UserRecNo = useron.number;
Rob Swindell's avatar
Rob Swindell committed
719
		SAFECOPY(tmp,name);
720
		p=strchr(tmp,' ');
721
		if(p) *p=0;
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
		sys.FirstName = tmp;
		sys.Password = useron.pass;
		if(localtime_r(&logontime,&tm) != NULL)
			sys.LogonMinute = (tm.tm_hour*60) + tm.tm_min;
		SAFEPRINTF2(tmp, "%02d:%02d", tm.tm_hour, tm.tm_min);
		sys.LogonTime = tmp;
		now = time(NULL);
		sys.TimeUsed = -(int16_t)(((now-starttime)/60)+(time_t)useron.ttoday);/* Negative minutes used */
		sys.PwrdTimeAllowed = cfg.level_timepercall[useron.level];
		sys.Name = name;
		sys.MinutesLeft = (int16_t)(tleft/60);
		sys.NodeNum = (uint8_t)cfg.node_num;
		sys.EventTime = "00:00";
		sys.UseAnsi = INT_TO_BOOL(term & ANSI);
		sys.YesChar = yes_key();
		sys.NoChar = no_key();
		sys.Conference2 = cursubnum;

		fwrite(&sys, sizeof(sys), 1, fp);
		fclose(fp);
742

Rob Swindell's avatar
Rob Swindell committed
743
		SAFECOPY(tmp,"USERS.SYS");
744
745
		if(misc&XTRN_LWRCASE)
			strlwr(tmp);
746
		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
747
		(void)removecase(str);
748
		if((fp = fnopen(NULL, str,O_WRONLY|O_CREAT|O_TRUNC)) == NULL) {
749
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
750
751
			return; 
		}
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
		PCBoard::usersys user{};
		user.hdr.Version = PCBoard::Version;
		user.hdr.SizeOfRec = sizeof(user.fixed);
		SAFECOPY(user.fixed.Name, name);
		SAFECOPY(user.fixed.City, useron.location);
		SAFECOPY(user.fixed.Password, useron.pass);
		SAFECOPY(user.fixed.BusDataPhone, useron.phone);
		SAFECOPY(user.fixed.HomeVoicePhone, useron.phone);
		user.fixed.ExpertMode = INT_TO_BOOL(useron.misc & EXPERT);
		user.fixed.Protocol = useron.prot;
		user.fixed.SecurityLevel = useron.level;
		user.fixed.NumTimesOn = useron.logons;
		user.fixed.PageLen = (uint8_t)rows;
		user.fixed.NumUploads = useron.uls;
		user.fixed.NumDownloads = useron.dls;
		user.fixed.DailyDnldBytes = (uint32_t)logon_dlb;
		SAFECOPY(user.fixed.UserComment, useron.note);
		SAFECOPY(user.fixed.SysopComment, useron.comment);
		user.fixed.ElapsedTimeOn = (int16_t)(now-starttime)/60;
		user.fixed.RegExpDate = unixtojulian(useron.expire);
		user.fixed.ExpSecurityLevel = cfg.expired_level;
		user.fixed.LastConference = cursubnum;
774
775
		user.fixed.ulTotDnldBytes = (uint32_t)MIN(useron.dlb, UINT32_MAX);
		user.fixed.ulTotUpldBytes = (uint32_t)MIN(useron.ulb, UINT32_MAX);
776
777
778
779
780
781
782
783
		user.fixed.DeleteFlag = INT_TO_BOOL(useron.misc & DELETED);
		user.fixed.RecNum = useron.number;
		user.fixed.MsgsLeft = useron.posts + useron.emails + useron.fbacks;
		if(useron.misc & CLRSCRN)
			user.fixed.PackedFlags |= PCBoard::USER_FLAG_MSGCLEAR;

		fwrite(&user, sizeof(user), 1, fp);
		fclose(fp);
784
	}
785
786

	else if(type==XTRN_SPITFIRE) {	 /* SpitFire SFDOORS.DAT File */
Rob Swindell's avatar
Rob Swindell committed
787
		SAFECOPY(tmp,"SFDOORS.DAT");
788
789
		if(misc&XTRN_LWRCASE)
			strlwr(tmp);
Rob Swindell's avatar
Rob Swindell committed
790
		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
791
		(void)removecase(str);
792
		if((fp = fnopen(NULL,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT)) == NULL) {
793
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
794
795
			return; 
		}
796
797

		now=time(NULL);
798
		if(localtime_r(&now,&tm)==NULL)
799
800
			l=0;
		else
801
802
			l=((((long)tm.tm_hour*60L)+(long)tm.tm_min)*60L)
				+(long)tm.tm_sec;
803

Rob Swindell's avatar
Rob Swindell committed
804
		SAFECOPY(tmp,name);
805
		if((p=strchr(tmp,' '))!=NULL)
806
807
			*p=0;

Rob Swindell's avatar
Rob Swindell committed
808
		safe_snprintf(str, sizeof(str), "%u\n%s\n%s\n%s\n%lu\n%u\n%lu\n%" PRId32 "\n"
809
810
811
812
813
814
815
816
817
			,useron.number						/* User number */
			,name								/* User name */
			,useron.pass						/* Password */
			,tmp								/* User's first name */
			,dte_rate							/* DTE Rate */
			,cfg.com_port						/* COM Port */
			,tleft/60							/* Time left in minutes */
			,l									/* Seconds since midnight (now) */
			);
818
		lfexpand(str,misc);
819
		fwrite(str, strlen(str), 1, fp);
820

deuce's avatar
deuce committed
821
		if(localtime_r(&logontime,&tm)==NULL)
822
823
			l=0;
		else
824
825
			l=((((long)tm.tm_hour*60L)+(long)tm.tm_min)*60L)
				+(long)tm.tm_sec;
826

Rob Swindell's avatar
Rob Swindell committed
827
		safe_snprintf(str, sizeof(str), "%s\n%s\n%u\n%u\n%u\n%u\n%" PRId32 "\n%lu\n%s\n"
828
829
			"%s\n%s\n%lu\n%s\n%u\n%u\n%u\n%u\n%u\n%lu\n%u\n"
			"%lu\n%lu\n%s\n%s\n"
830
			,dropdir
831
			,(term & ANSI) ? "TRUE":"FALSE"		/* ANSI ? True or False */
832
833
834
835
836
			,useron.level						/* Security level */
			,useron.uls 						/* Total uploads */
			,useron.dls 						/* Total downloads */
			,cfg.level_timepercall[useron.level]/* Minutes allowed this call */
			,l									/* Secs since midnight (logon) */
837
			,(long)(starttime-logontime)		/* Extra time in seconds */
838
839
840
841
842
843
844
845
846
847
			,"FALSE"                            /* Sysop next? */
			,"FALSE"                            /* From Front-end? */
			,"FALSE"                            /* Software Flow Control? */
			,dte_rate							/* DTE Rate */
			,"FALSE"                            /* Error correcting connection? */
			,0									/* Current conference */
			,0									/* Current file dir */
			,cfg.node_num						/* Node number */
			,15 								/* Downloads allowed per day */
			,0									/* Downloads already this day */
848
			,100000L 							/* Download bytes allowed/day */
849
850
851
852
853
854
			,0									/* Downloaded bytes already today */
			,useron.ulb/1024L					/* Kbytes uploaded */
			,useron.dlb/1024L					/* Kbytes downloaded */
			,useron.phone						/* Phone Number */
			,useron.location					/* City, State */
			);
855
		lfexpand(str,misc);
856
		fwrite(str, strlen(str), 1, fp);
857

858
		fclose(fp);
859
	}
860
861

	else if(type==XTRN_UTI) { /* UTI v2.1 - UTIDOOR.TXT */
Rob Swindell's avatar
Rob Swindell committed
862
		SAFECOPY(tmp,"UTIDOOR.TXT");
863
864
		if(misc&XTRN_LWRCASE)
			strlwr(tmp);
Rob Swindell's avatar
Rob Swindell committed
865
		SAFEPRINTF2(str,"%s%s",dropdir,tmp);
866
		(void)removecase(str);
867
		if((fp = fnopen(NULL,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT)) == NULL) {
868
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
869
870
			return; 
		}
871

Rob Swindell's avatar
Rob Swindell committed
872
		SAFECOPY(tmp,name);
873
		strupr(tmp);
Rob Swindell's avatar
Rob Swindell committed
874
		safe_snprintf(str, sizeof(str), "%s\n%lu\n%u\n%lu\n%lu\n"