xtrn_sec.cpp 55 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
/* xtrn_sec.cpp */

/* Synchronet external program/door section and drop file routines */

/* $Id$ */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
11
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 *																			*
 * 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										*
 *																			*
 * Anonymous FTP access to the most recent released source is available at	*
 * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
 *																			*
 * Anonymous CVS access to the development source and modification history	*
 * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
 *     (just hit return, no password is necessary)							*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * You are encouraged to submit any modifications (preferably in Unix diff	*
 * format) via e-mail to mods@synchro.net									*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

#include "sbbs.h"

/****************************************************************************/
/* This is the external programs (doors) section of the bbs                 */
/* Return 1 if no externals available, 0 otherwise. 						*/
/****************************************************************************/
int sbbs_t::xtrn_sec()
{
46
	char	str[MAX_PATH+1];
47
48
49
50
	int		xsec;
	uint	i,j,k,*usrxtrn,usrxtrns,*usrxsec,usrxsecs;
	long	l;

51
52
53
54
55
	if(useron.rest&FLAG('X')) {
		bputs(text[R_ExternalPrograms]);
		return(1);
	}

56
57
	if(!cfg.total_xtrns || !cfg.total_xtrnsecs) {
		bputs(text[NoXtrnPrograms]);
58
59
		return(1); 
	}
60

deuce's avatar
deuce committed
61
	if((usrxtrn=(uint *)malloc(cfg.total_xtrns*sizeof(int)))==NULL) {
62
		errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_xtrns);
63
64
		return(1); 
	}
deuce's avatar
deuce committed
65
	if((usrxsec=(uint *)malloc(cfg.total_xtrnsecs*sizeof(int)))==NULL) {
66
		errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_xtrnsecs);
deuce's avatar
deuce committed
67
		free(usrxtrn);
68
69
		return(1); 
	}
70
71
72

	while(online) {
		for(i=0,usrxsecs=0;i<cfg.total_xtrnsecs;i++)
rswindell's avatar
rswindell committed
73
			if(chk_ar(cfg.xtrnsec[i]->ar,&useron,&client))
74
75
76
				usrxsec[usrxsecs++]=i;
		if(!usrxsecs) {
			bputs(text[NoXtrnPrograms]);
deuce's avatar
deuce committed
77
78
			free(usrxtrn);
			free(usrxsec);
79
80
			return(1); 
		}
81
		if(usrxsecs>1) {
82
			if(menu_exists("xtrn_sec")) {
83
				menu("xtrn_sec");
84
85
86
87
				xsec=getnum(usrxsecs);
				if(xsec<=0)
					break;
				xsec--;
88
89
				xsec=usrxsec[xsec]; 
			}
90
91
92
93
			else {
				for(i=0;i<cfg.total_xtrnsecs;i++)
					uselect(1,i,"External Program Section"
						,cfg.xtrnsec[i]->name,cfg.xtrnsec[i]->ar);
94
95
				xsec=uselect(0,0,0,0,0); 
			}
96
			if(xsec==-1)
97
98
				break; 
		}
99
100
101
		else
			xsec=0;

rswindell's avatar
rswindell committed
102
		while(!chk_ar(cfg.xtrnsec[xsec]->ar,&useron,&client))
103
104
105
106
			xsec++;

		if(xsec>=cfg.total_xtrnsecs) {
			bputs(text[NoXtrnPrograms]);
deuce's avatar
deuce committed
107
108
			free(usrxtrn);
			free(usrxsec);
109
110
			return(1); 
		}
111
112
113
114
115

		while(online) {
			for(i=0,usrxtrns=0;i<cfg.total_xtrns; i++) {
				if(cfg.xtrn[i]->sec!=xsec)
					continue;
116
				if(cfg.xtrn[i]->event && cfg.xtrn[i]->misc&EVENTONLY)
117
					continue;
rswindell's avatar
rswindell committed
118
				if(!chk_ar(cfg.xtrn[i]->ar,&useron,&client))
119
					continue;
120
121
				usrxtrn[usrxtrns++]=i; 
			}
122
123
124
			if(!usrxtrns) {
				bputs(text[NoXtrnPrograms]);
				pause();
125
126
				break; 
			}
127
128
			sprintf(str,"xtrn%u",xsec+1);
			if(menu_exists(str)) {
129
130
				menu(str); 
			}
131
132
133
134
135
			else {
				bprintf(text[XtrnProgLstHdr],cfg.xtrnsec[xsec]->name);
				bputs(text[XtrnProgLstTitles]);
				if(usrxtrns>=10) {
					bputs("     ");
136
137
					bputs(text[XtrnProgLstTitles]); 
				}
138
139
140
141
				CRLF;
				bputs(text[XtrnProgLstUnderline]);
				if(usrxtrns>=10) {
					bputs("     ");
142
143
					bputs(text[XtrnProgLstUnderline]); 
				}
144
145
146
147
148
149
150
151
152
153
154
155
156
157
				CRLF;
				if(usrxtrns>=10)
					j=(usrxtrns/2)+(usrxtrns&1);
				else
					j=usrxtrns;
				for(i=0;i<j && !msgabort();i++) {
					bprintf(text[XtrnProgLstFmt],i+1
						,cfg.xtrn[usrxtrn[i]]->name,cfg.xtrn[usrxtrn[i]]->cost);
					if(usrxtrns>=10) {
						k=(usrxtrns/2)+i+(usrxtrns&1);
						if(k<usrxtrns) {
							bputs("     ");
							bprintf(text[XtrnProgLstFmt],k+1
								,cfg.xtrn[usrxtrn[k]]->name
158
159
160
161
162
								,cfg.xtrn[usrxtrn[k]]->cost); 
						}
					}
					CRLF; 
				}
163
				ASYNC;
164
165
				mnemonics(text[WhichXtrnProg]); 
			}
166
167
168
169
170
171
172
			getnodedat(cfg.node_num,&thisnode,1);
			thisnode.aux=0; /* aux is 0, only if at menu */
			putnodedat(cfg.node_num,&thisnode);
			action=NODE_XTRN;
			SYNC;
			if((l=getnum(usrxtrns))<1)
				break;
173
			l--;
174
175
			sprintf(str,"xtrn/%s",cfg.xtrn[usrxtrn[l]]->code);
			if(menu_exists(str)) {
176
177
178
179
				menu(str);
				lncntr=0;
			}
			exec_xtrn(usrxtrn[l]); 
180

181
182
			if(cfg.xtrn[usrxtrn[l]]->misc&XTRN_PAUSE)
				lncntr=2;	/* force a pause before CLS */
183
		}
184
		if(usrxsecs<2)
185
186
			break; 
	}
deuce's avatar
deuce committed
187
188
	free(usrxtrn);
	free(usrxsec);
189
190
191
192
	return(0);
}


193
const char *hungupstr="\1n\1h%s\1n hung up on \1h%s\1n %s\r\n";
194
195
196
197

/****************************************************************************/
/* Convert C string to pascal string										*/
/****************************************************************************/
198
void str2pas(const char *instr, char *outstr)
199
200
201
202
203
204
205
206
207
208
209
{
	int i;

	outstr[0]=(char)strlen(instr);
	for(i=0;i<outstr[0];i++)
		outstr[i+1]=instr[i];
}

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

216
	if(localtime_r(&unix_time,&tm)==NULL)
217
		return(0);
218
219
	j=36525L*(1900+tm.tm_year);
	if(!(j%100) && (tm.tm_mon+1)<3)
220
221
		j--;
	j=(j-(1900*36525))/100;
222
	j+=tm.tm_mday+days[tm.tm_mon];
223
224
225
226
227
228
	return(j);
}

/****************************************************************************/
/* Convert julian date into unix format 									*/
/****************************************************************************/
229
230
231
#ifdef __BORLANDC__
#pragma argsused
#endif
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
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++;
250
251
		leap=1; 
	}
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
	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
}

268
269
270
271
272
#ifdef __unix__
static void lfexpand(char *str, ulong misc)
{
	char *p;
	char newstr[1024];
rswindell's avatar
rswindell committed
273
	size_t len=0;
274
275
276
277

	if(misc&XTRN_NATIVE)
		return;

rswindell's avatar
rswindell committed
278
	for(p=str;*p && len < sizeof(newstr)-2;p++) {
279
280
281
282
283
284
285
286
287
288
289
290
		if(*p=='\n')
			newstr[len++]='\r';
		newstr[len++]=*p;
	}

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

291
292
293
/****************************************************************************/
/* Creates various types of xtrn (Doors, Chains, etc.) data (drop) files.	*/
/****************************************************************************/
294
void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tleft
295
296
					,ulong misc)
{
297
298
	char	str[1024],tmp2[128],c,*p;
	char 	tmp[512];
deuce's avatar
64-bit    
deuce committed
299
300
301
302
303
	/* TODO: 16-bit i */
	int16_t	i;
	int		file;
	uint16_t	w;
	int32_t	l;
304
305
	struct tm tm;
	struct tm tl;
306
307
	stats_t stats;

308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
	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)) {
323
#ifdef _WIN32
324
325
		/* Put Micros~1 shortened paths in drop files when running 16-bit DOS programs */
		GetShortPathName(cfg.node_dir,node_dir,sizeof(node_dir));
326
		GetShortPathName(cfg.ctrl_dir,ctrl_dir,sizeof(ctrl_dir));
327
328
329
330
		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));
331
332
333
334
335
336
337
#elif defined(__linux__) && defined(USE_DOSEMU)
		/* These drive mappings must match the Linux/DOSEMU patch in xtrn.cpp: */
		SAFECOPY(node_dir, "D:");
		SAFECOPY(ctrl_dir, "F:");
		SAFECOPY(data_dir, "G:");
		SAFECOPY(exec_dir, "H:");
#endif
338
339
340
	}


341
	if(type==XTRN_SBBS) {	/* SBBS XTRN.DAT file */
342
343
344
345
		strcpy(tmp,"XTRN.DAT");
		if(misc&XTRN_LWRCASE)
			strlwr(tmp);
		sprintf(str,"%s%s",dropdir,tmp);
rswindell's avatar
rswindell committed
346
		removecase(str);
347
348
		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT))==-1) {
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
349
350
			return; 
		}
351

352
		sprintf(str,"%s\n%s\n%s\n%s\n"
353
354
355
356
			,name								/* User name */
			,cfg.sys_name						/* System name */
			,cfg.sys_op 						/* Sysop name */
			,cfg.sys_guru); 					/* Guru name */
357
		lfexpand(str,misc);
358
359
		write(file,str,strlen(str));

360
		sprintf(str,"%s\n%s\n%u\n%u\n%lu\n%s\n%lu\n%lu\n"
361
362
			,ctrl_dir							/* Ctrl dir */
			,data_dir							/* Data dir */
363
364
365
			,cfg.sys_nodes						/* Total system nodes */
			,cfg.node_num						/* Current node */
			,tleft								/* User Timeleft in seconds */
366
367
			,term_supports(ANSI)				/* User ANSI ? (Yes/Mono/No) */
				? term_supports(COLOR)
368
369
370
				? "Yes":"Mono":"No"
			,rows								/* User Screen lines */
			,useron.cdt+useron.freecdt);		/* User Credits */
371
		lfexpand(str,misc);
372
373
		write(file,str,strlen(str));

374
		sprintf(str,"%u\n%u\n%s\n%c\n%u\n%s\n"
375
376
377
			,useron.level						/* User main level */
			,useron.level						/* User transfer level */
			,useron.birth						/* User birthday */
378
			,useron.sex ? useron.sex : '?'		/* User sex (M/F) */
379
380
			,useron.number						/* User number */
			,useron.phone); 					/* User phone number */
381
		lfexpand(str,misc);
382
383
		write(file,str,strlen(str));

384
385
		sprintf(str,"%u\n%u\n%x\n%lu\n%s\n%s\n"
			"%s\n%s\n%s\n%s\n%s\n%s\n%lu\n"
386
			,misc&(XTRN_STDIO|XTRN_CONIO) ? 0:cfg.com_port		/* Com port or 0 if !FOSSIL */
387
388
389
390
391
392
393
394
395
396
397
			,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 */
398
			,0L
399
			);
400
		lfexpand(str,misc);
401
402
		write(file,str,strlen(str));

403
		sprintf(str,"%u\n",cfg.total_xtrns);
404
		lfexpand(str,misc);
405
406
407
		write(file,str,strlen(str));			/* Total external programs */

		for(i=0;i<cfg.total_xtrns;i++) {		/* Each program's name */
rswindell's avatar
rswindell committed
408
			if(SYSOP || chk_ar(cfg.xtrn[i]->ar,&useron,&client))
409
410
411
				strcpy(str,cfg.xtrn[i]->name);
			else
				str[0]=0;						/* Blank if no access */
rswindell's avatar
rswindell committed
412
			SAFECAT(str,"\n");
413
			lfexpand(str,misc);
414
415
			write(file,str,strlen(str)); 
		}
416

417
		sprintf(str,"%s\n%s\n"
418
419
420
			,ltoaf(useron.flags1,tmp)			/* Main flags */
			,ltoaf(useron.flags2,tmp2)			/* Transfer flags */
			);
421
		lfexpand(str,misc);
422
423
		write(file,str,strlen(str));

424
		sprintf(str,"%s\n%s\n%lx\n%s\n%s\n%s\n"
425
426
			,ltoaf(useron.exempt,tmp)			/* Exemptions */
			,ltoaf(useron.rest,tmp2)			/* Restrictions */
427
			,(long)useron.expire				/* Expiration date in unix form */
428
429
430
431
			,useron.address 					/* Address */
			,useron.location					/* City/State */
			,useron.zipcode 					/* Zip/Postal code */
			);
432
		lfexpand(str,misc);
433
434
		write(file,str,strlen(str));

435
		sprintf(str,"%s\n%s\n%d\n%s\n%lu\n%s\n%s\n%s\n%s\n"
436
			"%" PRIx32 "\n%d\n"
437
438
			,ltoaf(useron.flags3,tmp)			/* Flag set #3 */
			,ltoaf(useron.flags4,tmp2)			/* Flag set #4 */
439
			,0									/* Time-slice type */
440
441
			,useron.name						/* Real name/company */
			,cur_rate							/* DCE rate */
442
443
444
			,exec_dir
			,text_dir
			,temp_dir
445
446
			,cfg.sys_id
			,cfg.node_misc
447
			,misc&(XTRN_STDIO|XTRN_CONIO) ? INVALID_SOCKET : client_socket_dup
448
			);
449
		lfexpand(str,misc);
450
451
		write(file,str,strlen(str));

452
453
		close(file); 
	}
454
455

	else if(type==XTRN_WWIV) {	/*	WWIV CHAIN.TXT File */
456
457
458
459
		strcpy(tmp,"CHAIN.TXT");
		if(misc&XTRN_LWRCASE)
			strlwr(tmp);
		sprintf(str,"%s%s",dropdir,tmp);
rswindell's avatar
rswindell committed
460
		removecase(str);
461
462
		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT))==-1) {
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
463
464
			return; 
		}
465

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

469
		sprintf(str,"%u\n%s\n%s\n%s\n%u\n%c\n"
470
471
472
473
474
			,useron.number						/* User number */
			,name								/* User name */
			,useron.name						/* User real name */
			,nulstr 							/* User call sign */
			,getage(&cfg,useron.birth)			/* User age */
475
			,useron.sex ? useron.sex : '?');	/* User sex (M/F) */
476
		strupr(str);
477
		lfexpand(str,misc);
478
479
		write(file,str,strlen(str));

deuce's avatar
deuce committed
480
		sprintf(str,"%lu\n%s\n%lu\n%ld\n%u\n%u\n%u\n%ld\n%u\n"
481
482
			,useron.cdt+useron.freecdt			/* Gold */
			,unixtodstr(&cfg,useron.laston,tmp)	/* User last on date */
483
			,cols 								/* User screen width */
484
485
486
487
			,rows								/* User screen length */
			,useron.level						/* User SL */
			,0									/* Cosysop? */
			,SYSOP								/* Sysop? (1/0) */
488
			,term_supports(ANSI)				/* ANSI ? (1/0) */
489
			,online==ON_REMOTE);				/* Remote (1/0) */
490
		lfexpand(str,misc);
491
492
		write(file,str,strlen(str));

493
494
		sprintf(str,"%lu\n%s\n%s\n%s\n%lu\n%d\n%s\n%s\n"
			"%u\n%u\n%lu\n%u\n%lu\n%u\n%s\n"
495
			,tleft								/* Time left in seconds */
496
497
			,node_dir							/* Gfiles dir (log dir) */
			,data_dir							/* Data dir */
498
			,"node.log"                         /* Name of log file */
499
500
501
502
503
504
505
506
507
508
509
			,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 */
510
		lfexpand(str,misc);
511
512
		write(file,str,strlen(str));

513
514
		close(file); 
	}
515
516

	else if(type==XTRN_GAP) {	/* Gap DOOR.SYS File */
517
518
519
520
		strcpy(tmp,"DOOR.SYS");
		if(misc&XTRN_LWRCASE)
			strlwr(tmp);
		sprintf(str,"%s%s",dropdir,tmp);
rswindell's avatar
rswindell committed
521
		removecase(str);
522
523
		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT))==-1) {
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
524
525
			return; 
		}
526

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

530
531
#if 0
		if(misc&XTRN_NATIVE) {
532
			if(misc&(XTRN_STDIO|XTRN_CONIO)) {
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
				strcpy(str,"COM0:STDIO\n");
			}
			else {
				sprintf(str,"COM0:SOCKET%d\n",
					client_socket_dup
				);
			}
		}
		else {
			sprintf(str,"COM%d:\n"
				,online==ON_REMOTE ? cfg.com_port:0);	/* 01: COM port - 0 if Local */
		}
#else
		sprintf(str,"COM%d:\n"
			,online==ON_REMOTE ? cfg.com_port:0);	/* 01: COM port - 0 if Local */
#endif
		lfexpand(str,misc);
		write(file,str,strlen(str));
551
552
553
554
555
556
557
558
		/* 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>
		*/
559
		sprintf(str,"%lu\n%u\n%u\n%lu\n%c\n%c\n%c\n%c\n"
560
			,dte_rate /* was cur_rate */		/* 02: DCE rate, see note above */
561
562
563
			,8									/* 03: Data bits */
			,cfg.node_num						/* 04: Node number */
			,dte_rate							/* 05: DTE rate */
564
			,'Y'								/* 06: Screen display */
565
566
567
			,'Y'                                /* 07: Printer toggle */
			,'Y'                                /* 08: Page bell */
			,'Y');                              /* 09: Caller alarm */
568
		lfexpand(str,misc);
569
570
		write(file,str,strlen(str));

571
		sprintf(str,"%s\n%s\n%s\n%s\n%s\n"
572
573
574
575
576
			,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 */
577
		lfexpand(str,misc);
578
579
		write(file,str,strlen(str));

580
		sprintf(str,"%u\n%u\n%s\n%lu\n%lu\n%s\n"
581
582
583
584
585
586
587
			,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 */
			,useron.misc&NO_EXASCII 			/* 20: GR if COLOR ANSI */
				? "7E" : (useron.misc&(ANSI|COLOR))==(ANSI|COLOR) ? "GR" : "NG");
588
		lfexpand(str,misc);
589
590
		write(file,str,strlen(str));

591
		sprintf(str,"%lu\n%c\n%s\n%u\n%s\n%u\n%c\n%u\n%u\n"
592
			,rows								/* 21: User screen length */
593
			,(useron.misc&EXPERT) ? 'Y':'N'     /* 22: Expert? (Y/N) */
594
595
596
597
			,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 */
598
			,useron.prot                        /* 27: Default protocol */
599
600
			,useron.uls 						/* 28: User total uploads */
			,useron.dls);						/* 29: User total downloads */
601
		lfexpand(str,misc);
602
603
		write(file,str,strlen(str));

604
605
		sprintf(str,"%u\n%lu\n%s\n%s\n%s\n%s"
			"\n%s\n%02d:%02d\n%c\n"
606
607
608
			,0									/* 30: Kbytes downloaded today */
			,(useron.cdt+useron.freecdt)/1024UL /* 31: Max Kbytes to download today */
			,useron.birth						/* 32: User birthday */
609
610
			,node_dir							/* 33: Path to MAIN directory */
			,data_dir							/* 34: Path to GEN directory */
611
612
613
614
615
			,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 */
616
		lfexpand(str,misc);
617
618
		write(file,str,strlen(str));

619
		localtime_r(&ns_time,&tm);
620
		sprintf(str,"%c\n%c\n%u\n%lu\n%02d/%02d/%02d\n"
621
622
623
			,(useron.misc&(NO_EXASCII|ANSI|COLOR))==ANSI
				? 'Y':'N'                       /* 39: ANSI supported but NG mode */
			,'Y'                                /* 40: Use record locking */
624
			,cfg.color[clr_external]			/* 41: BBS default color */
625
			,useron.min 						/* 42: Time credits in minutes */
626
627
628
			,tm.tm_mon+1						/* 43: File new-scan date */
			,tm.tm_mday
			,TM_YEAR(tm.tm_year));
629
		lfexpand(str,misc);
630
631
		write(file,str,strlen(str));

deuce's avatar
deuce committed
632
		localtime_r(&logontime,&tm);
633
		localtime32(&useron.laston,&tl);
634
635
		sprintf(str,"%02d:%02d\n%02d:%02d\n%u\n%u\n%lu\n"
			"%lu\n%s\n%u\n%u\n"
636
			,tm.tm_hour							/* 44: Time of this call */
637
			,tm.tm_min
638
			,tl.tm_hour							/* 45: Time of last call */
639
			,tl.tm_min
640
641
642
643
644
645
646
			,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 */
647
		lfexpand(str,misc);
648
649
		write(file,str,strlen(str));

650
651
		close(file); 
	}
652
653
654

	else if(type==XTRN_RBBS || type==XTRN_RBBS1) {
		if(type==XTRN_RBBS)
655
			sprintf(tmp,"DORINFO%X.DEF",cfg.node_num);   /* support 1-F */
656
		else
657
658
659
660
			sprintf(tmp,"DORINFO1.DEF");
		if(misc&XTRN_LWRCASE)
			strlwr(tmp);
		sprintf(str,"%s%s",dropdir,tmp);
rswindell's avatar
rswindell committed
661
		removecase(str);
662
663
		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT))==-1) {
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
664
665
			return; 
		}
666
667

		strcpy(tmp,cfg.sys_op);
668
		p=strchr(tmp,' ');
669
670
671
672
673
		if(p)
			*(p++)=0;
		else
			p=nulstr;

674
		sprintf(str,"%s\n%s\n%s\nCOM%d\n%lu BAUD,N,8,1\n%u\n"
675
676
677
678
679
680
681
			,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);
682
		lfexpand(str,misc);
683
684
685
		write(file,str,strlen(str));

		strcpy(tmp,name);
686
		p=strchr(tmp,' ');
687
688
689
690
		if(p)
			*(p++)=0;
		else
			p=nulstr;
deuce's avatar
deuce committed
691
		sprintf(str,"%s\n%s\n%s\n%ld\n%u\n%lu\n"
692
693
694
			,tmp								/* User's firstname */
			,p									/* User's lastname */
			,useron.location					/* User's city */
695
			,term_supports(ANSI)				/* 1=ANSI 0=ASCII */
696
697
698
			,useron.level						/* Security level */
			,tleft/60); 						/* Time left in minutes */
		strupr(str);
699
		lfexpand(str,misc);
700
701
702
703
		write(file,str,strlen(str));

		close(file);

704
705
706
707
		strcpy(tmp,"EXITINFO.BBS");
		if(misc&XTRN_LWRCASE)
			strlwr(tmp);
		sprintf(str,"%s%s",dropdir,tmp);
rswindell's avatar
rswindell committed
708
		removecase(str);
709
710
		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
711
712
			return; 
		}
713
		w=(WORD)dte_rate;
deuce's avatar
64-bit    
deuce committed
714
		write(file,&w,sizeof(w));			/* BaudRate */
715
716
		/* SysInfo */
		getstats(&cfg,0,&stats);
deuce's avatar
64-bit    
deuce committed
717
		write(file,&stats.logons,sizeof(stats.logons)); /* CallCount */
718
719
720
721
722
		write(file,nulstr,36);					/* LastCallerName */
		write(file,nulstr,36);					/* LastCallerAlias */
		write(file,nulstr,92);					/* ExtraSpace */
		/* TimeLogInfo */
		write(file,nulstr,9);					/* StartDate */
deuce's avatar
64-bit    
deuce committed
723
724
		write(file,nulstr,24*sizeof(int16_t));	/* BusyPerHour */
		write(file,nulstr,7*sizeof(int16_t));		/* BusyPerDay */
725
726
727
728
729
730
731
732
733
734
		/* UserInfo */
		str2pas(name,str);				/* Name */
		write(file,str,36);
		str2pas(useron.location,str);
		write(file,str,26); 					/* City */
		str2pas(useron.pass,str);
		write(file,str,16); 					/* Pwd */
		str2pas(useron.phone,str);
		write(file,str,13); 					/* DataPhone */
		write(file,str,13); 					/* HomePhone */
735
		localtime32(&useron.laston,&tm);
736
		sprintf(tmp,"%02d:%02d",tm.tm_hour,tm.tm_min);
737
738
739
740
741
742
743
744
745
		str2pas(tmp,str);
		write(file,str,6);						/* LastTime */
		unixtodstr(&cfg,useron.laston,tmp);
		str2pas(tmp,str);
		write(file,str,9);						/* LastDate */
		c=0;
		if(useron.misc&DELETED) c|=(1<<0);
		if(useron.misc&CLRSCRN) c|=(1<<1);
		if(useron.misc&UPAUSE)	 c|=(1<<2);
746
		if(term_supports(ANSI))	c|=(1<<3);
747
748
749
750
		if(useron.sex=='F')     c|=(1<<7);
		write(file,&c,1);						/* Attrib */
		write(file,&useron.flags1,4);			/* Flags */
		w=0;
deuce's avatar
64-bit    
deuce committed
751
752
753
754
		write(file,&w,sizeof(w)); 			/* Credit */
		write(file,&w,sizeof(w)); 			/* Pending */
		write(file,&useron.posts,sizeof(useron.posts));/* TimesPosted */
		write(file,&w,sizeof(w)); 			/* HighMsgRead */
755
		w=useron.level;
deuce's avatar
64-bit    
deuce committed
756
		write(file,&w,sizeof(w)); 			/* SecLvl */
757
		w=0;
deuce's avatar
64-bit    
deuce committed
758
759
760
		write(file,&w,sizeof(w)); 			/* Times */
		write(file,&useron.uls,sizeof(useron.uls));	/* Ups */
		write(file,&useron.dls,sizeof(useron.dls));	/* Downs */
761
		w=(ushort)(useron.ulb/1024UL);
deuce's avatar
64-bit    
deuce committed
762
		write(file,&w,sizeof(w)); 			/* UpK */
763
		w=(ushort)(useron.dlb/1024UL);
deuce's avatar
64-bit    
deuce committed
764
		write(file,&w,sizeof(w)); 			/* DownK */
765
		w=(ushort)(logon_dlb/1024UL);
deuce's avatar
64-bit    
deuce committed
766
		write(file,&w,sizeof(w)); 			/* TodayK */
767
		w=0;
deuce's avatar
64-bit    
deuce committed
768
769
770
771
		write(file,&w,sizeof(w)); 			/* Elapsed */
		write(file,&w,sizeof(w)); 			/* Len */
		write(file,&w,sizeof(w)); 			/* CombinedPtr */
		write(file,&w,sizeof(w)); 			/* AliasPtr */
772
		l=0;
deuce's avatar
64-bit    
deuce committed
773
		write(file,&l,sizeof(l));			/* Birthday (as a long?) */
774
775
776
		/* EventInfo */
		c=0;
		write(file,&c,sizeof(char));			/* Status */
deuce's avatar
64-bit    
deuce committed
777
		write(file,&l /* sys_eventtime */,sizeof(l));	/* RunTime */
778
779
780
781
782
783
784
785
786
787
		write(file,&c,sizeof(char));			/* ErrorLevel */
		c='\xff';
		write(file,&c,sizeof(char));			/* Days */
		// c=sys_eventnode==node_num || sys_misc&SM_TIMED_EX ? 1 : 0;
		c=0;
		write(file,&c,sizeof(char));			/* Forced */
		if(!cfg.total_events)
			l=0;
		else
			l=cfg.event[0]->last;
deuce's avatar
64-bit    
deuce committed
788
		write(file,&l,sizeof(l));			/* LastTimeRun */
789
790
791
792
793
794
795
		memset(str,0,40);
		write(file,str,7);						/* Spare */

		c=0;
		write(file,&c,1);						/* NetMailEntered */
		write(file,&c,1);						/* EchoMailEntered */

deuce's avatar
deuce committed
796
		localtime_r(&logontime,&tm);
797
		sprintf(tmp,"%02d:%02d",tm.tm_hour,tm.tm_min);
798
799
		str2pas(tmp,str);
		write(file,str,6);						/* LoginTime */
800
		unixtodstr(&cfg,(time32_t)logontime,tmp);
801
802
		str2pas(tmp,str);
		write(file,str,9);						/* LoginDate */
deuce's avatar
64-bit    
deuce committed
803
804
805
806
		write(file,&cfg.level_timepercall[useron.level],sizeof(int16_t));  /* TmLimit */
		write(file,&logontime,sizeof(logontime));	/* LoginSec */
		write(file,&useron.cdt,sizeof(useron.cdt));	/* Credit */
		write(file,&useron.number,sizeof(useron.number)); /* UserRecNum */
rswindell's avatar
rswindell committed
807
		i=0;
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
		write(file,&i,2);						/* ReadThru */
		write(file,&i,2);						/* PageTimes */
		write(file,&i,2);						/* DownLimit */
		c=sys_status&SS_SYSPAGE ? 1:0;
		write(file,&c,1);						/* WantChat */
		c=0;
		write(file,&c,1);						/* GosubLevel */

		memset(str,0,255);
		for(i=1;i<20;i++)
			write(file,str,9);					/* GosubData */
		write(file,str,9);						/* Menu */
		c=useron.misc&CLRSCRN ? 1:0;
		write(file,&c,1);						/* ScreenClear */
		c=useron.misc&UPAUSE ? 1:0;
		write(file,&c,1);						/* MorePrompts */
		c=useron.misc&NO_EXASCII ? 0:1;
		write(file,&c,1);						/* GraphicsMode */
		c=useron.xedit ? 1:0;
		write(file,&c,1);						/* ExternEdit */
828
		i=(int16_t)rows;
829
830
831
832
833
834
		write(file,&i,2);						/* ScreenLength */
		c=1;
		write(file,&c,1);						/* MNP_Connect */
		write(file,str,49); 					/* ChatReason */
		c=0;
		write(file,&c,1);						/* ExternLogoff */
835
		c=(char)term_supports(ANSI);
836
837
		write(file,&c,1);						/* ANSI_Capable */
		close(file);
838
	}
839
840

	else if(type==XTRN_WILDCAT) { /* WildCat CALLINFO.BBS File */
841
842
843
844
		strcpy(tmp,"CALLINFO.BBS");
		if(misc&XTRN_LWRCASE)
			strlwr(tmp);
		sprintf(str,"%s%s",dropdir,tmp);
rswindell's avatar
rswindell committed
845
		removecase(str);
846
847
		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT))==-1) {
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT);
848
849
			return; 
		}
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873

		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;
874
875
					break; 
		}
876
		sprintf(str,"%s\n%u\n%s\n%u\n%lu\n%s\n%s\n%u\n"
877
878
879
880
881
			,name								/* User name */
			,i									/* DTE rate */
			,useron.location					/* User location */
			,useron.level						/* Security level */
			,tleft/60							/* Time left in min */
882
			,term_supports(ANSI) ? "COLOR":"MONO"  /* ANSI ??? */
883
884
			,useron.pass						/* Password */
			,useron.number);					/* User number */
885
		lfexpand(str,misc);
886
887
		write(file,str,strlen(str));

888
		localtime_r(&now,&tm);
889
		sprintf(str,"%lu\n%02d:%02d\n%02d:%02d %02d/%02d/%02d\n%s\n"
890
			,tleft								/* Time left in seconds */
891
892
893
894
			,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)
895
			,nulstr);							/* Conferences with access */
896
		lfexpand(str,misc);
897
898
		write(file,str,strlen(str));

899
		localtime32(&useron.laston,&tm);
900
		sprintf(str,"%u\n%u\n%u\n%u\n%s\n%s %02u:%02u\n"
901
902
903
904
905
906
			,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 */
907
908
			,tm.tm_hour						/* MM/DD/YY  HH:MM */
			,tm.tm_min);
909
		lfexpand(str,misc);
910
911
		write(file,str,strlen(str));

912
		localtime_r(&ns_time,&tm);
913
914
		sprintf(str,"%s\n%s\n%02d/%02d/%02d\n%u\n%lu\n%u"
			"\n%u\n%u\n"
915
916
917
			,useron.misc&EXPERT 				/* Expert or Novice mode */
				? "EXPERT":"NOVICE"
			,"All"                              /* Transfer Protocol */
918
919
			,tm.tm_mon+1,tm.tm_mday			/* File new-scan date */
			,TM_YEAR(tm.tm_year)				/* in MM/DD/YY */
920
921
922
923
924
			,useron.logons						/* Total logons */
			,rows								/* Screen length */
			,0									/* Highest message read */
			,useron.uls 						/* Total files uploaded */
			,useron.dls);						/* Total files downloaded */
925
		lfexpand(str,misc);
926
927
		write(file,str,strlen(str));

928
		sprintf(str,"%u\n%s\nCOM%u\n%s\n%lu\n%s\n%s\n"
929
930
931
932
933
934
935
			,8									/* Data bits */
			,online==ON_LOCAL?"LOCAL":"REMOTE"  /* Online local or remote */
			,cfg.com_port						/* COMx port */
			,useron.birth						/* User birthday */
			,dte_rate							/* DTE rate */
			,"FALSE"                            /* Already connected? */
			,"Normal Connection");              /* Normal or ARQ connect */
936
		lfexpand(str,misc);
937
938
		write(file,str,strlen(str));

939
		localtime_r(&now,&tm);
940
		sprintf(str,"%02d/%02d/%02d %02d:%02d\n%u\n%u\n"
941
942
943
			,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 */
944
945
			,cfg.node_num						/* Node number */
			,0);								/* Door number */
946
		lfexpand(str,misc);
947
948
		write(file,str,strlen(str));

949
950
		close(file); 
	}
951
952

	else if(type==XTRN_PCBOARD) { /* PCBoard Files */
953
954
955
956
		strcpy(tmp,"PCBOARD.SYS");
		if(misc&XTRN_LWRCASE)
			strlwr(tmp);
		sprintf(str,"%s%s",dropdir,tmp);
rswindell's avatar
rswindell committed
957
		removecase(str);
958
959
		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
960
961
			return; 
		}
962
963
964
965
966

		sprintf(str,"%2d%2d%2d%2d%c%2d%c%c%5u%-5.5s"
			,-1 								/* Display on/off */
			,0									/* Printer on/off */
			,sys_status&SS_SYSPAGE ? -1:0		/* Page Bell on/off */
967
			,startup->answer_sound[0] ? -1:0	/* Caller Alarm on/off */
968
			,' ' 								/* Sysop next flag */
969
970
971
972
973
974
975
976
977
978
979
980
			,0									/* Error corrected */
			,useron.misc&NO_EXASCII ? '7'       /* Graphics mode */
				: (useron.misc&(COLOR|ANSI))==(COLOR|ANSI) ? 'Y':'N'
			,'A'                                /* Node chat status */
			,(uint)dte_rate 					/* DTE Port Speed */
			,connection 						/* Connection description */
			);
		write(file,str,23);

		write(file,&useron.number,2);			/* User record number */

		strcpy(tmp,name);
981
		p=strchr(tmp,' ');
982
983
984
985
986
987
		if(p) *p=0;
		sprintf(str,"%-15.15s%-12s"
			,tmp								/* User's first name */
			,useron.pass);						/* User's password */
		write(file,str,27);

deuce's avatar
deuce committed
988
		if(localtime_r(&logontime,&tm)==NULL)
989
990
			i=0;
		else
991
			i=(tm.tm_hour*60)+tm.tm_min;
992
993
994
		write(file,&i,2);						/* Logon time in min since mid */

		now=time(NULL);
995
		i=-(int16_t)(((now-starttime)/60)+(time_t)useron.ttoday);/* Negative minutes used */
996
997
		write(file,&i,2);

998
		sprintf(str,"%02d:%02d",tm.tm_hour,tm.tm_min);
999
1000
1001
1002
1003
		write(file,str,5);

		i=cfg.level_timepercall[useron.level];	/* Time allowed on */
		write(file,&i,2);

1004
		c=0;
1005
1006
		i=0;									/* Allowed K-bytes for D/L */
		write(file,&i,2);
1007
		write(file,&c,1);						/* Conference user was in */
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
		write(file,&i,2);						/* Conferences joined */
		write(file,&i,2);						/* "" */
		write(file,&i,2);						/* "" */
		write(file,&i,2);						/* Conferences scanned */
		write(file,&i,2);						/* "" */
		write(file,&i,2);						/* Conference add time */
		write(file,&i,2);						/* Upload/Sysop Chat time min */

		strcpy(str,"    ");
		write(file,str,4);						/* Language extension */

		sprintf(str,"%-25.25s",name);           /* User's full name */
		write(file,str,25);

1022
		i=(int16_t)(tleft/60);
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
		write(file,&i,2);						/* Minutes remaining */

		write(file,&cfg.node_num,1);			/* Node number */

		sprintf(str,"%02d:%02d%2d%2d"           /* Scheduled Event time */
			,0 // sys_eventtime/60
			,0 // sys_eventtime%60
			,0 // sys_timed[0] ? -1:0				 /* Event active ? */
			,0									/* Slide event ? */
			);
		write(file,str,9);

		l=0L;
		write(file,&l,4);						/* Memorized message number */

deuce's avatar
deuce committed
1038
		sprintf(str,"%d%c%c%ld%s%c%c%d%d%d%c%c"
1039
			,cfg.com_port						/* COM Port number */
1040
1041
			,' ' 								/* Reserved */
			,' ' 								/* "" */
1042
			,term_supports(ANSI)				/* 1=ANSI 0=NO ANSI */
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
			,"01-01-80"                         /* last event date */
			,0,0								/* last event minute */
			,0									/* caller exited to dos */
			,sys_status&SS_EVENT ? 1:0			/* event up coming */
			,0									/* stop uploads */
			,0,0								/* conference user was in */
			);
		write(file,str,19);

		close(file);			/* End of PCBOARD.SYS creation */

1054
1055
1056
1057
		strcpy(tmp,"USERS.SYS");
		if(misc&XTRN_LWRCASE)
			strlwr(tmp);
		sprintf(str,"%s%s",dropdir,tmp);
rswindell's avatar
rswindell committed
1058
		removecase(str);
1059
1060
		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
1061
1062
			return; 
		}