addfiles.c 25.1 KB
Newer Older
1
2
3
4
5
6
7
8
/* Program to add files to a Synchronet file database */

/* $Id$ */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
9
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
10
11
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
 *																			*
 * 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"

38
#define ADDFILES_VER "3.03"
39
40
41
42
43
44
45

scfg_t scfg;

int cur_altpath=0;

long files=0,removed=0,mode=0;

46
47
char lib[LEN_GSNAME+1];

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#define DEL_LIST	(1L<<0)
#define NO_EXTEND	(1L<<1)
#define FILE_DATE	(1L<<2)
#define TODAYS_DATE (1L<<3)
#define FILE_ID 	(1L<<4)
#define NO_UPDATE	(1L<<5)
#define NO_NEWDATE	(1L<<6)
#define ASCII_ONLY	(1L<<7)
#define UL_STATS	(1L<<8)
#define ULDATE_ONLY (1L<<9)
#define KEEP_DESC	(1L<<10)
#define AUTO_ADD	(1L<<11)
#define SEARCH_DIR	(1L<<12)
#define SYNC_LIST	(1L<<13)
#define KEEP_SPACE	(1L<<14)

/****************************************************************************/
65
/* This is needed by load_cfg.c												*/
66
/****************************************************************************/
67
int lprintf(int level, const char *fmat, ...)
68
69
{
	va_list argptr;
70
	char sbuf[512];
71
72
73
74
75
	int chcount;

	va_start(argptr,fmat);
	chcount=vsprintf(sbuf,fmat,argptr);
	va_end(argptr);
76
77
	truncsp(sbuf);
	printf("%s\n",sbuf);
78
79
80
	return(chcount);
}

81
void prep_desc(char *str)
82
83
84
85
86
{
	char tmp[1024];
	int i,j;

	for(i=j=0;str[i] && j < sizeof(tmp)-1;i++) {
87
		if(j && str[i]==' ' && tmp[j-1]==' ' && (mode&KEEP_SPACE))
88
			tmp[j++]=str[i];
89
		else if(j && str[i]<=' ' && str[i] > 0&& tmp[j-1]==' ')
90
			continue;
91
		else if(i && !isalnum((uchar)str[i]) && str[i]==str[i-1])
92
			continue;
93
		else if(str[i]>=' ' || str[i]<0)
94
95
			tmp[j++]=str[i];
		else if(str[i]==TAB || (str[i]==CR && str[i+1]==LF))
96
			tmp[j++]=' ';
97
98
99
100
101
	}
	tmp[j]=0;
	strcpy(str,tmp);
}

102
103
104
/*****************************************************************************/
/* Returns command line generated from instr with %c replacments             */
/*****************************************************************************/
105
char *mycmdstr(char *instr, char *fpath, char *fspec, char *outstr)
106
107
108
109
{
    static char cmd[MAX_PATH+1];
    char str[MAX_PATH+1];
    int i,j,len;
rswindell's avatar
rswindell committed
110
111
112
#ifdef _WIN32
	char sfpath[MAX_PATH+1];
#endif
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

	len=strlen(instr);
	for(i=j=0;i<len && j<128;i++) {
		if(instr[i]=='%') {
			i++;
			cmd[j]=0;
			switch(toupper(instr[i])) {
				case 'F':   /* File path */
					strcat(cmd,fpath);
					break;
				case '~':	/* DOS-compatible (8.3) filename */
#ifdef _WIN32
					SAFECOPY(sfpath,fpath);
					GetShortPathName(fpath,sfpath,sizeof(sfpath));
					strcat(cmd,sfpath);
#else
                    strcat(cmd,fpath);
#endif			
					break;
				case 'G':   /* Temp directory */
					strcat(cmd,scfg.temp_dir);
					break;
                case 'J':
                    strcat(cmd,scfg.data_dir);
                    break;
                case 'K':
                    strcat(cmd,scfg.ctrl_dir);
                    break;
				case 'N':   /* Node Directory (same as SBBSNODE environment var) */
					strcat(cmd,scfg.node_dir);
					break;
				case 'S':   /* File Spec */
					strcat(cmd,fspec);
					break;
                case 'Z':
                    strcat(cmd,scfg.text_dir);
                    break;
				case '!':   /* EXEC Directory */
					strcat(cmd,scfg.exec_dir);
					break;
153
154
155
156
157
                case '@':   /* EXEC Directory for DOS/OS2/Win32, blank for Unix */
#ifndef __unix__
                    strcat(cmd,scfg.exec_dir);
#endif
                    break;
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
				case '#':   /* Node number (same as SBBSNNUM environment var) */
					sprintf(str,"%d",scfg.node_num);
					strcat(cmd,str);
					break;
				case '%':   /* %% for percent sign */
					strcat(cmd,"%");
					break;
				default:    /* unknown specification */
					break; 
			}
			j=strlen(cmd); 
		}
		else
			cmd[j++]=instr[i]; 
	}
	cmd[j]=0;

	return(cmd);
}

/****************************************************************************/
/* Updates dstst.dab file													*/
/****************************************************************************/
void updatestats(ulong size)
{
    char	str[MAX_PATH+1];
    int		file;
deuce's avatar
64-bit    
deuce committed
185
	uint32_t	l;
186

187
	sprintf(str,"%sdsts.dab",scfg.ctrl_dir);
188
	if((file=nopen(str,O_RDWR|O_BINARY))==-1) {
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
		printf("ERR_OPEN %s\n",str);
		return; 
	}
	lseek(file,20L,SEEK_SET);	/* Skip timestamp, logons and logons today */
	read(file,&l,4);			/* Uploads today		 */
	l++;
	lseek(file,-4L,SEEK_CUR);
	write(file,&l,4);
	read(file,&l,4);			/* Upload bytes today	 */
	l+=size;
	lseek(file,-4L,SEEK_CUR);
	write(file,&l,4);
	close(file);
}

void addlist(char *inpath, file_t f, uint dskip, uint sskip)
{
206
207
208
209
210
211
	char str[MAX_PATH+1];
	char tmp[MAX_PATH+1];
	char fname[MAX_PATH+1];
	char listpath[MAX_PATH+1];
	char filepath[MAX_PATH+1];
	char curline[256],nextline[256];
212
	char *p;
213
	char ext[1024],tmpext[513];
214
215
	int i,file;
	long l;
216
	BOOL exist;
217
218
219
220
221
	FILE *stream;
	DIR*	dir;
	DIRENT*	dirent;

	if(mode&SEARCH_DIR) {
222
		SAFECOPY(str,cur_altpath ? scfg.altpath[cur_altpath-1] : scfg.dir[f.dir]->path);
223
224
225
226
		printf("Searching %s\n\n",str);
		dir=opendir(str);

		while(dir!=NULL && (dirent=readdir(dir))!=NULL) {
rswindell's avatar
rswindell committed
227
228
229
			sprintf(tmp,"%s%s"
				,cur_altpath ? scfg.altpath[cur_altpath-1] : scfg.dir[f.dir]->path
				,dirent->d_name);
230
231
232
233
234
			if(isdir(tmp))
				continue;
#ifdef _WIN32
			GetShortPathName(tmp, filepath, sizeof(filepath));
#else
235
			SAFECOPY(filepath,tmp);
236
#endif
237
238
239
			f.misc=0;
			f.desc[0]=0;
			f.cdt=flength(filepath);
240
			padfname(getfname(filepath),f.name);
deuce's avatar
deuce committed
241
			printf("%s  %10"PRIu32"  %s\n"
242
				,f.name,f.cdt,unixtodstr(&scfg,(time32_t)fdate(filepath),str));
243
244
245
246
247
248
			exist=findfile(&scfg,f.dir,f.name);
			if(exist) {
				if(mode&NO_UPDATE)
					continue;
				getfileixb(&scfg,&f);
				if(mode&ULDATE_ONLY) {
249
					f.dateuled=time32(NULL);
250
251
252
253
254
255
					update_uldate(&scfg, &f);
					continue; 
				} 
			}

			if(mode&FILE_DATE) {		/* get the file date and put into desc */
256
				unixtodstr(&scfg,(time32_t)fdate(filepath),f.desc);
257
258
259
260
				strcat(f.desc,"  "); 
			}

			if(mode&TODAYS_DATE) {		/* put today's date in desc */
261
				unixtodstr(&scfg,time32(NULL),f.desc);
262
263
264
265
266
				strcat(f.desc,"  "); 
			}

			if(mode&FILE_ID) {
				for(i=0;i<scfg.total_fextrs;i++)
rswindell's avatar
rswindell committed
267
					if(!stricmp(scfg.fextr[i]->ext,f.name+9) && chk_ar(&scfg,scfg.fextr[i]->ar,/* user: */NULL, /* client: */NULL))
268
269
270
						break;
				if(i<scfg.total_fextrs) {
					sprintf(tmp,"%sFILE_ID.DIZ",scfg.temp_dir);
271
					removecase(tmp);
272
					system(mycmdstr(scfg.fextr[i]->cmd,filepath,"FILE_ID.DIZ",NULL));
273
274
					if(!fexistcase(tmp)) {
						sprintf(tmp,"%sDESC.SDI",scfg.temp_dir);
275
						removecase(tmp);
276
						system(mycmdstr(scfg.fextr[i]->cmd,filepath,"DESC.SDI",NULL)); 
277
278
						fexistcase(tmp);
					}
279
					if((file=nopen(tmp,O_RDONLY|O_BINARY))!=-1) {
280
281
282
						memset(ext,0,513);
						read(file,ext,512);
						for(i=512;i;i--)
283
							if(ext[i-1]>' ' || ext[i-1]<0)
284
285
286
								break;
						ext[i]=0;
						if(mode&ASCII_ONLY)
287
							strip_exascii(ext, ext);
288
289
						if(!(mode&KEEP_DESC)) {
							sprintf(tmpext,"%.256s",ext);
290
							prep_desc(tmpext);
291
							for(i=0;tmpext[i];i++)
292
								if(isalpha((uchar)tmpext[i]))
293
294
									break;
							sprintf(f.desc,"%.*s",LEN_FDESC,tmpext+i);
295
							for(i=0;(f.desc[i]>=' ' || f.desc[i]<0) && i<LEN_FDESC;i++)
296
297
298
299
300
301
302
303
								;
							f.desc[i]=0; }
						close(file);
						f.misc|=FM_EXTDESC; 
					} 
				} 
			}

304
			f.dateuled=time32(NULL);
305
			f.altpath=cur_altpath;
306
			prep_desc(f.desc);
307
			if(mode&ASCII_ONLY)
308
				strip_exascii(f.desc, f.desc);
309
310
311
			if(exist) {
				putfiledat(&scfg,&f);
				if(!(mode&NO_NEWDATE))
312
313
					update_uldate(&scfg, &f); 
			}
314
315
316
317
			else
				addfiledat(&scfg,&f);
			if(f.misc&FM_EXTDESC) {
				truncsp(ext);
318
319
				putextdesc(&scfg,f.dir,f.datoffset,ext); 
			}
320
321
322
323
324
325
326
327
328
329
			if(mode&UL_STATS)
				updatestats(f.cdt);
			files++; 
		}
		if(dir!=NULL)
			closedir(dir);
		return; 
	}


330
	SAFECOPY(listpath,inpath);
331
	fexistcase(listpath);
332
	if((stream=fopen(listpath,"r"))==NULL) {
333
334
		fprintf(stderr,"Error %d (%s) opening %s\n"
			,errno,strerror(errno),listpath);
335
336
		sprintf(listpath,"%s%s",cur_altpath ? scfg.altpath[cur_altpath-1]
				: scfg.dir[f.dir]->path,inpath);
337
		fexistcase(listpath);
338
		if((stream=fopen(listpath,"r"))==NULL) {
339
340
			printf("Can't open: %s\n"
				   "        or: %s\n",inpath,listpath);
341
342
343
			return; 
		} 
	}
344
345
346
347
348

	printf("Adding %s to %s %s\n\n"
		,listpath,scfg.lib[scfg.dir[f.dir]->lib]->sname,scfg.dir[f.dir]->sname);

	fgets(nextline,255,stream);
349
	do {
350
351
		f.misc=0;
		f.desc[0]=0;
352
		SAFECOPY(curline,nextline);
353
354
355
		nextline[0]=0;
		fgets(nextline,255,stream);
		truncsp(curline);
356
		if(curline[0]<=' ' || (mode&ASCII_ONLY && (uchar)curline[0]>=0x7e))
357
358
			continue;
		printf("%s\n",curline);
359
		SAFECOPY(fname,curline);
360

361
#if 0	/* Files without dots are valid on modern systems */
362
363
364
		p=strchr(fname,'.');
		if(!p || p==fname || p>fname+8)    /* no dot or invalid dot location */
			continue;
365
366
#endif
		p=strchr(fname,' ');
367
368
369
		if(p) *p=0;
		else				   /* no space after filename? */
			continue;
370
#if 0
371
		strupr(fname);
372
#endif
373
		SAFECOPY(fname,unpadfname(fname,tmp));
374

375
376
377
378
379
380
381
382
383
384
385
		sprintf(filepath,"%s%s",cur_altpath ? scfg.altpath[cur_altpath-1]
			: scfg.dir[f.dir]->path,fname);

#ifdef _WIN32
		{
			char shortpath[MAX_PATH+1];
			GetShortPathName(filepath, shortpath, sizeof(shortpath));
			SAFECOPY(fname, getfname(shortpath));
		}
#endif

386
387
388
389
390
		padfname(fname,f.name);
		if(strcspn(f.name,"\\/|<>+[]:=\";,")!=strlen(f.name))
			continue;

		for(i=0;i<12;i++)
391
			if(f.name[i]<' ' || (mode&ASCII_ONLY && (uchar)f.name[i]>0x7e))
392
393
394
395
396
397
398
399
400
401
				break;

		if(i<12)					/* Ctrl chars or EX-ASCII in filename? */
			continue;
		exist=findfile(&scfg,f.dir,f.name);
		if(exist) {
			if(mode&NO_UPDATE)
				continue;
			getfileixb(&scfg,&f);
			if(mode&ULDATE_ONLY) {
402
				f.dateuled=time32(NULL);
403
				update_uldate(&scfg, &f);
404
405
406
				continue; 
			} 
		}
407
408

		if(mode&FILE_DATE) {		/* get the file date and put into desc */
409
			l=(time32_t)fdate(filepath);
410
			unixtodstr(&scfg,l,f.desc);
411
412
			strcat(f.desc,"  "); 
		}
413
414

		if(mode&TODAYS_DATE) {		/* put today's date in desc */
415
			l=time32(NULL);
416
			unixtodstr(&scfg,l,f.desc);
417
418
			strcat(f.desc,"  "); 
		}
419
420
421

		if(dskip && strlen(curline)>=dskip) p=curline+dskip;
		else {
422
423
424
			p = curline;
			FIND_WHITESPACE(p);
			SKIP_WHITESPACE(p); 
425
		}
426
427
428
		SAFECOPY(tmp,p);
		prep_desc(tmp);
		sprintf(f.desc+strlen(f.desc),"%.*s",(int)(LEN_FDESC-strlen(f.desc)),tmp);
429

430
		if(nextline[0]==' ' || strlen(p)>LEN_FDESC) {	/* ext desc */
431
432
433
			if(!(mode&NO_EXTEND)) {
				memset(ext,0,513);
				f.misc|=FM_EXTDESC;
434
435
				sprintf(ext,"%s\r\n",p); 
			}
436

437
			if(nextline[0]==' ') {
438
				SAFECOPY(str,nextline);				   /* tack on to end of desc */
439
				p=str+dskip;
440
				while(*p>0 && *p<=' ') p++;
441
442
443
444
445
446
				i=LEN_FDESC-strlen(f.desc);
				if(i>1) {
					p[i-1]=0;
					truncsp(p);
					if(p[0]) {
						strcat(f.desc," ");
447
448
449
450
						strcat(f.desc,p); 
					} 
				} 
			}
451
452

			while(!feof(stream) && !ferror(stream) && strlen(ext)<512) {
453
				if(nextline[0]!=' ')
454
455
456
457
458
459
					break;
				truncsp(nextline);
				printf("%s\n",nextline);
				if(!(mode&NO_EXTEND)) {
					f.misc|=FM_EXTDESC;
					p=nextline+dskip;
460
					while(*p==' ') p++;
461
					strcat(ext,p);
462
463
					strcat(ext,"\r\n"); 
				}
464
				nextline[0]=0;
465
466
467
				fgets(nextline,255,stream); 
			} 
		}
468
469
470
471
472


		if(sskip) l=atol(fname+sskip);
		else {
			l=flength(filepath);
473
			if(l<0L) {
474
				printf("%s not found.\n",filepath);
475
476
				continue; 
			} 
477
478
479
480
			if(l == 0L) {
				printf("%s is a zero-0length file.\n",filepath);
				continue; 
			} 
481
		}
482
483
484

		if(mode&FILE_ID) {
			for(i=0;i<scfg.total_fextrs;i++)
rswindell's avatar
rswindell committed
485
				if(!stricmp(scfg.fextr[i]->ext,f.name+9) && chk_ar(&scfg,scfg.fextr[i]->ar,/* user: */NULL, /* client: */NULL))
486
487
488
					break;
			if(i<scfg.total_fextrs) {
				sprintf(tmp,"%sFILE_ID.DIZ",scfg.temp_dir);
489
				removecase(tmp);
490
				system(mycmdstr(scfg.fextr[i]->cmd,filepath,"FILE_ID.DIZ",NULL));
491
492
				if(!fexistcase(tmp)) {
					sprintf(tmp,"%sDESC.SDI",scfg.temp_dir);
493
					removecase(tmp);
494
					system(mycmdstr(scfg.fextr[i]->cmd,filepath,"DESC.SDI",NULL)); 
495
496
					fexistcase(tmp);
				}
497
				if((file=nopen(tmp,O_RDONLY|O_BINARY))!=-1) {
498
499
500
					memset(ext,0,513);
					read(file,ext,512);
					for(i=512;i;i--)
501
						if(ext[i-1]>' ' || ext[i-1]<0)
502
503
504
							break;
					ext[i]=0;
					if(mode&ASCII_ONLY)
505
						strip_exascii(ext, ext);
506
507
					if(!(mode&KEEP_DESC)) {
						sprintf(tmpext,"%.256s",ext);
508
						prep_desc(tmpext);
509
						for(i=0;tmpext[i];i++)
510
							if(isalpha((uchar)tmpext[i]))
511
512
								break;
						sprintf(f.desc,"%.*s",LEN_FDESC,tmpext+i);
513
						for(i=0;(f.desc[i]>=' ' || f.desc[i]<0) && i<LEN_FDESC;i++)
514
							;
515
516
						f.desc[i]=0; 
					}
517
518
519
520
521
522
523
					close(file);
					f.misc|=FM_EXTDESC; 
				} 
			} 
		}

		f.cdt=l;
524
		f.dateuled=time32(NULL);
525
		f.altpath=cur_altpath;
526
		prep_desc(f.desc);
527
		if(mode&ASCII_ONLY)
528
			strip_exascii(f.desc, f.desc);
529
530
531
		if(exist) {
			putfiledat(&scfg,&f);
			if(!(mode&NO_NEWDATE))
532
533
				update_uldate(&scfg, &f); 
		}
534
535
536
537
		else
			addfiledat(&scfg,&f);
		if(f.misc&FM_EXTDESC) {
			truncsp(ext);
538
539
			putextdesc(&scfg,f.dir,f.datoffset,ext); 
		}
540
541
542

		if(mode&UL_STATS)
			updatestats(l);
543
		files++; 
544
	} while(!feof(stream) && !ferror(stream));
545
546
547
	fclose(stream);
	if(mode&DEL_LIST && !(mode&SYNC_LIST)) {
		printf("\nDeleting %s\n",listpath);
548
549
		remove(listpath); 
	}
550
551
552
553
554

}

void synclist(char *inpath, int dirnum)
{
555
	char	str[1024];
556
557
558
	char	fname[MAX_PATH+1];
	char	listpath[MAX_PATH+1];
	uchar*	ixbbuf;
559
	char*	p;
560
561
562
563
	int		i,file,found;
	long	l,m,length;
	FILE*	stream;
	file_t	f;
564

565
	sprintf(str,"%s%s.ixb",scfg.dir[dirnum]->data_dir,scfg.dir[dirnum]->code);
566
	if((file=nopen(str,O_RDONLY|O_BINARY))==-1) {
567
		printf("ERR_OPEN %s\n",str);
568
569
		return; 
	}
570
571
572
	length=filelength(file);
	if(length%F_IXBSIZE) {
		close(file);
rswindell's avatar
rswindell committed
573
		printf("ERR_LEN (%ld) of %s\n",length,str);
574
575
		return; 
	}
deuce's avatar
deuce committed
576
	if((ixbbuf=(uchar *)malloc(length))==NULL) {
577
578
		close(file);
		printf("ERR_ALLOC %s\n",str);
579
580
		return; 
	}
581
582
	if(lread(file,ixbbuf,length)!=length) {
		close(file);
deuce's avatar
deuce committed
583
		free((char *)ixbbuf);
584
		printf("ERR_READ %s\n",str);
585
586
		return; 
	}
587
588
	close(file);

589
	SAFECOPY(listpath,inpath);
590
	if((stream=fopen(listpath,"r"))==NULL) {
591
592
		sprintf(listpath,"%s%s",cur_altpath ? scfg.altpath[cur_altpath-1]
				: scfg.dir[dirnum]->path,inpath);
593
		if((stream=fopen(listpath,"r"))==NULL) {
594
595
			printf("Can't open: %s\n"
				   "        or: %s\n",inpath,listpath);
596
597
598
			return; 
		} 
	}
599
600
601
602
603
604
605
606

	printf("\nSynchronizing %s with %s %s\n\n"
		,listpath,scfg.lib[scfg.dir[dirnum]->lib]->sname,scfg.dir[dirnum]->sname);

	for(l=0;l<length;l+=F_IXBSIZE) {
		m=l;
		for(i=0;i<12 && l<length;i++)
			if(i==8)
607
				str[i]=ixbbuf[m]>' ' ? '.' : ' ';
608
609
610
611
612
613
614
615
616
617
			else
				str[i]=ixbbuf[m++]; 	/* Turns FILENAMEEXT into FILENAME.EXT */
		str[i]=0;
		unpadfname(str,fname);
		rewind(stream);
		found=0;
		while(!found) {
			if(!fgets(str,1000,stream))
				break;
			truncsp(str);
618
			p=strchr(str,' ');
619
620
			if(p) *p=0;
			if(!stricmp(str,fname))
621
622
				found=1; 
		}
623
624
625
626
627
628
629
630
631
		if(found)
			continue;
		padfname(fname,f.name);
		printf("%s not found in list - ",f.name);
		f.dir=dirnum;
		f.datoffset=ixbbuf[m]|((long)ixbbuf[m+1]<<8)|((long)ixbbuf[m+2]<<16);
		getfiledat(&scfg,&f);
		if(f.opencount) {
			printf("currently OPEN by %u users\n",f.opencount);
632
633
			continue; 
		}
634
		removefiledat(&scfg,&f);
635
		if(remove(getfilepath(&scfg,&f,str)))
636
637
			printf("Error removing %s\n",str);
		removed++;
638
639
		printf("Removed from database\n"); 
	}
640
641
642

	if(mode&DEL_LIST) {
		printf("\nDeleting %s\n",listpath);
643
644
		remove(listpath); 
	}
645
646
}

647
char *usage="\nusage: addfiles code [.alt_path] [-opts] +list "
648
			 "[desc_off] [size_off]"
649
	"\n   or: addfiles code [.alt_path] [-opts] file "
650
651
		"\"description\"\n"
	"\navailable opts:"
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
	"\n      -a         import ASCII only (no extended ASCII)"
	"\n      -b         synchronize database with file list (use with caution)"
	"\n      -c         do not remove extra spaces from file description"
	"\n      -d         delete list after import"
	"\n      -e         do not import extended descriptions"
	"\n      -f         include file date in descriptions"
	"\n      -t         include today's date in descriptions"
	"\n      -i         include added files in upload statistics"
	"\n      -n         do not update information for existing files"
	"\n      -o         update upload date only for existing files"
	"\n      -u         do not update upload date for existing files"
	"\n      -z         check for and import FILE_ID.DIZ and DESC.SDI"
	"\n      -k         keep original short description (not DIZ)"
	"\n      -s         search directory for files (no file list)"
	"\n      -l <lib>   specify library (short name) to Auto-ADD"
	"\n      -x <name>  specify uploader's user name (may require quotes)"
668
	"\n"
669
670
	"\nAuto-ADD:   use - in place of code for Auto-ADD of FILES.BBS"
	"\n            use -filename to Auto-ADD a different filename"
671
	"\n            use -l \"libname\" to only Auto-ADD files to a specific library"
672
673
674
675
676
677
678
679
	;

/*********************/
/* Entry point (duh) */
/*********************/
int main(int argc, char **argv)
{
	char error[512];
680
	char revision[16];
681
682
	char str[MAX_PATH+1];
	char tmp[MAX_PATH+1];
683
684
	char *p;
	char exist,listgiven=0,namegiven=0,ext[513]
685
		,auto_name[MAX_PATH+1]="FILES.BBS";
686
	int i,j,file;
687
	uint desc_offset=0, size_offset=0;
688
689
690
	long l;
	file_t	f;

691
	sscanf("$Revision$", "%*s %s", revision);
692

693
	fprintf(stderr,"\nADDFILES v%s-%s (rev %s) - Adds Files to Synchronet "
694
695
696
		"Filebase\n"
		,ADDFILES_VER
		,PLATFORM_DESC
697
		,revision
698
699
700
		);

	if(argc<2) {
701
		puts(usage);
702
703
		return(1); 
	}
704
705
706
707
708
709
710
711

	p=getenv("SBBSCTRL");
	if(p==NULL) {
		printf("\nSBBSCTRL environment variable not set.\n");
		printf("\nExample: SET SBBSCTRL=/sbbs/ctrl\n");
		exit(1); 
	}

712
713
	memset(&scfg,0,sizeof(scfg));
	scfg.size=sizeof(scfg);
714
	SAFECOPY(scfg.ctrl_dir,p);
715
716
717
718
719

	if(chdir(scfg.ctrl_dir)!=0)
		fprintf(stderr,"!ERROR changing directory to: %s", scfg.ctrl_dir);

	printf("\nLoading configuration files from %s\n",scfg.ctrl_dir);
720
721
722
723
	if(!load_cfg(&scfg,NULL,TRUE,error)) {
		fprintf(stderr,"!ERROR loading configuration files: %s\n",error);
		exit(1);
	}
rswindell's avatar
rswindell committed
724
725
	SAFECOPY(scfg.temp_dir,"../temp");
	prep_dir(scfg.ctrl_dir, scfg.temp_dir, sizeof(scfg.temp_dir));
726

727
728
	if(argv[1][0]=='*' || argv[1][0]=='-') {
		if(argv[1][1]=='?') {
729
			puts(usage);
730
731
			exit(0);
		}
732
		if(argv[1][1])
733
			SAFECOPY(auto_name,argv[1]+1);
734
		mode|=AUTO_ADD;
735
736
		i=0; 
	} else {
737
		if(!isalnum((uchar)argv[1][0]) && argc==2) {
738
			puts(usage);
739
740
741
			return(1); 
		}

742
		for(i=0;i<scfg.total_dirs;i++)
743
			if(!stricmp(scfg.dir[i]->code,argv[1])) /* use matchmatchi() instead? */
744
745
746
747
				break;

		if(i>=scfg.total_dirs) {
			printf("Directory code '%s' not found.\n",argv[1]);
748
749
750
			exit(1); 
		} 
	}
751
752
753

	memset(&f,0,sizeof(file_t));
	f.dir=i;
754
	SAFECOPY(f.uler,"-> ADDFILES <-");
755
756

	for(j=2;j<argc;j++) {
757
758
		if(argv[j][0]=='*')     /* set the uploader name (legacy) */
			SAFECOPY(f.uler,argv[j]+1);
759
760
761
762
		else 
			if(argv[j][0]=='-'
			|| argv[j][0]=='/'
			) {      /* options */
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
			for(i=1;argv[j][i];i++)
				switch(toupper(argv[j][i])) {
					case 'A':
						mode|=ASCII_ONLY;
						break;
					case 'B':
						mode|=(SYNC_LIST|NO_UPDATE);
						break;
					case 'C':
						mode|=KEEP_SPACE;
						break;
					case 'D':
						mode|=DEL_LIST;
						break;
					case 'E':
						mode|=NO_EXTEND;
						break;
					case 'I':
						mode|=UL_STATS;
						break;
783
784
785
					case 'L':
						j++;
						if(argv[j]==NULL) {
786
							puts(usage);
787
788
789
790
791
							return(-1);
						}
						SAFECOPY(lib,argv[j]);
						i=strlen(argv[j])-1;
						break;
792
793
794
					case 'X':
						j++;
						if(argv[j]==NULL) {
795
							puts(usage);
796
797
798
799
800
							return(-1);
						}
						SAFECOPY(f.uler,argv[j]);
						i=strlen(argv[j])-1;
						break;
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
					case 'Z':
						mode|=FILE_ID;
						break;
					case 'K':
						mode|=KEEP_DESC;	 /* Don't use DIZ for short desc */
						break;
					case 'N':
						mode|=NO_UPDATE;
						break;
					case 'O':
						mode|=ULDATE_ONLY;
						break;
					case 'U':
						mode|=NO_NEWDATE;
						break;
					case 'F':
						mode|=FILE_DATE;
						break;
					case 'T':
						mode|=TODAYS_DATE;
						break;
					case 'S':
						mode|=SEARCH_DIR;
						break;
					default:
826
						puts(usage);
827
828
829
						return(1); 
			} 
		}
830
		else if(isdigit((uchar)argv[j][0])) {
831
832
833
834
835
836
			if(desc_offset==0)
				desc_offset=atoi(argv[j]);
			else
				size_offset=atoi(argv[j]);
			continue;
		}
837
838
		else if(argv[j][0]=='+') {      /* filelist - FILES.BBS */
			listgiven=1;
rswindell's avatar
rswindell committed
839
			if(argc > j+1
840
				&& isdigit((uchar)argv[j+1][0])) { /* skip x characters before description */
rswindell's avatar
rswindell committed
841
				if(argc > j+2
842
					&& isdigit((uchar)argv[j+2][0])) { /* skip x characters before size */
843
					addlist(argv[j]+1,f,atoi(argv[j+1]),atoi(argv[j+2]));
844
845
					j+=2; 
				}
846
847
				else {
					addlist(argv[j]+1,f,atoi(argv[j+1]),0);
848
849
850
					j++; 
				} 
			}
851
852
853
			else
				addlist(argv[j]+1,f,0,0);
			if(mode&SYNC_LIST)
854
855
				synclist(argv[j]+1,f.dir); 
		}
856
857
858
859
		else if(argv[j][0]=='.') {      /* alternate file path */
			cur_altpath=atoi(argv[j]+1);
			if(cur_altpath>scfg.altpaths) {
				printf("Invalid alternate path.\n");
860
861
862
				exit(1); 
			} 
		}
863
864
865
866
		else {
			namegiven=1;
			padfname(argv[j],f.name);
			f.desc[0]=0;
867
#if 0
868
			strupr(f.name);
869
#endif
870
871
			if(j+1==argc) {
				printf("%s no description given.\n",f.name);
872
873
				continue; 
			}
874
875
876
			sprintf(str,"%s%s",cur_altpath ? scfg.altpath[cur_altpath-1]
				: scfg.dir[f.dir]->path,argv[j]);
			if(mode&FILE_DATE)
877
				sprintf(f.desc,"%s  ",unixtodstr(&scfg,(time32_t)fdate(str),tmp));
878
			if(mode&TODAYS_DATE)
879
				sprintf(f.desc,"%s  ",unixtodstr(&scfg,time32(NULL),tmp));
rswindell's avatar
rswindell committed
880
			sprintf(tmp,"%.*s",(int)(LEN_FDESC-strlen(f.desc)),argv[++j]);
881
			SAFECOPY(f.desc,tmp);
882
883
884
			l=flength(str);
			if(l==-1) {
				printf("%s not found.\n",str);
885
886
				continue; 
			}
887
888
889
890
891
892
			exist=findfile(&scfg,f.dir,f.name);
			if(exist) {
				if(mode&NO_UPDATE)
					continue;
				getfileixb(&scfg,&f);
				if(mode&ULDATE_ONLY) {
893
					f.dateuled=time32(NULL);
894
					update_uldate(&scfg, &f);
895
896
897
					continue; 
				} 
			}
898
			f.cdt=l;
899
			f.dateuled=time32(NULL);
900
			f.altpath=cur_altpath;
901
			prep_desc(f.desc);
902
			if(mode&ASCII_ONLY)
903
				strip_exascii(f.desc, f.desc);
deuce's avatar
deuce committed
904
			printf("%s %7"PRIu32" %s\n",f.name,f.cdt,f.desc);
905
906
			if(mode&FILE_ID) {
				for(i=0;i<scfg.total_fextrs;i++)
rswindell's avatar
rswindell committed
907
					if(!stricmp(scfg.fextr[i]->ext,f.name+9) && chk_ar(&scfg,scfg.fextr[i]->ar,/* user: */NULL, /* client: */NULL))
908
909
910
						break;
				if(i<scfg.total_fextrs) {
					sprintf(tmp,"%sFILE_ID.DIZ",scfg.temp_dir);
911
					removecase(tmp);
912
					system(mycmdstr(scfg.fextr[i]->cmd,str,"FILE_ID.DIZ",NULL));
913
					if(!fexistcase(tmp)) {
914
						sprintf(tmp,"%sDESC.SDI",scfg.temp_dir);
915
						removecase(tmp);
916
						system(mycmdstr(scfg.fextr[i]->cmd,str,"DESC.SDI",NULL)); 
917
918
						fexistcase(tmp);
					}
919
					if((file=nopen(tmp,O_RDONLY|O_BINARY))!=-1) {
920
921
922
923
						memset(ext,0,513);
						read(file,ext,512);
						if(!(mode&KEEP_DESC)) {
							sprintf(f.desc,"%.*s",LEN_FDESC,ext);
924
							for(i=0;(f.desc[i]>=' ' || f.desc[i]<0) && i<LEN_FDESC;i++)
925
								;
926
927
							f.desc[i]=0; 
						}
928
						close(file);
929
930
931
932
						f.misc|=FM_EXTDESC; 
					} 
				} 
			}
933
934
935
			if(exist) {
				putfiledat(&scfg,&f);
				if(!(mode&NO_NEWDATE))
936
937
					update_uldate(&scfg, &f); 
			}
938
939
940
941
942
943
944
945
			else
				addfiledat(&scfg,&f);

			if(f.misc&FM_EXTDESC)
				putextdesc(&scfg,f.dir,f.datoffset,ext);

			if(mode&UL_STATS)
				updatestats(l);
946
947
948
			files++; 
		} 
	}
949
950
951

	if(mode&AUTO_ADD) {
		for(i=0;i<scfg.total_dirs;i++) {
952
953
			if(lib[0] && stricmp(scfg.lib[scfg.dir[i]->lib]->sname,lib))
				continue;
954
955
956
957
			if(scfg.dir[i]->misc&DIR_NOAUTO)
				continue;
			f.dir=i;
			if(mode&SEARCH_DIR) {
958
				addlist("",f,desc_offset,size_offset);
959
960
				continue; 
			}
961
			sprintf(str,"%s%s.lst",scfg.dir[f.dir]->path,scfg.dir[f.dir]->code);
962
			if(fexistcase(str) && flength(str)>0L) {
963
				printf("Auto-adding %s\n",str);
964
				addlist(str,f,desc_offset,size_offset);
965
966
				if(mode&SYNC_LIST)
					synclist(str,i);
967
968
				continue; 
			}
969
			sprintf(str,"%s%s",scfg.dir[f.dir]->path,auto_name);
970
			if(fexistcase(str) && flength(str)>0L) {
971
				printf("Auto-adding %s\n",str);
972
				addlist(str,f,desc_offset,size_offset);
973
974
				if(mode&SYNC_LIST)
					synclist(str,i);
975
976
977
978
				continue; 
			} 
		} 
	}
979
980
981

	else {
		if(!listgiven && !namegiven) {
982
			sprintf(str,"%s%s.lst",scfg.dir[f.dir]->path, scfg.dir[f.dir]->code);
983
			if(!fexistcase(str) || flength(str)<=0L)
984
				sprintf(str,"%s%s",scfg.dir[f.dir]->path, auto_name);
985
			addlist(str,f,desc_offset,size_offset);
986
			if(mode&SYNC_LIST)
987
988
989
				synclist(str,f.dir); 
		} 
	}
990
991
992
993
994
995
996
997

	printf("\n%lu file(s) added.",files);
	if(removed)
		printf("\n%lu files(s) removed.",removed);
	printf("\n");
	return(0);
}