xtrn_sec.cpp 47.8 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);
Rob Swindell's avatar
Rob Swindell committed
443
		safe_snprintf(str, sizeof(str), "%c\n%c\n%u\n%lu\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
570
571
572
573
574
575
576
577
578
579
580
581
		exitinfo.LoginDate = tmp;
		exitinfo.TimeLimit = cfg.level_timepercall[useron.level];
		exitinfo.Credit = useron.cdt;
		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
774
775
776
777
778
779
780
781
782
783
		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;
		user.fixed.ulTotDnldBytes = useron.dlb;
		user.fixed.ulTotUpldBytes = useron.ulb;
		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"
875
876
877
878
879
			,tmp								/* User name */
			,cur_rate							/* Actual BPS rate */
			,online==ON_LOCAL ? 0: cfg.com_port /* COM Port */
			,dte_rate							/* DTE rate */
			,tleft);							/* Time left in sec */
880
		lfexpand(str,misc);