addfiles.c 25.5 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
#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)
rswindell's avatar
rswindell committed
63
#define CHECK_DATE	(1L<<15)
64
65

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

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

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

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

103
104
105
/*****************************************************************************/
/* Returns command line generated from instr with %c replacments             */
/*****************************************************************************/
106
char *mycmdstr(char *instr, char *fpath, char *fspec, char *outstr)
107
108
109
110
{
    static char cmd[MAX_PATH+1];
    char str[MAX_PATH+1];
    int i,j,len;
rswindell's avatar
rswindell committed
111
112
113
#ifdef _WIN32
	char sfpath[MAX_PATH+1];
#endif
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
153

	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;
154
155
156
157
158
                case '@':   /* EXEC Directory for DOS/OS2/Win32, blank for Unix */
#ifndef __unix__
                    strcat(cmd,scfg.exec_dir);
#endif
                    break;
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
185
				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
186
	uint32_t	l;
187

188
	sprintf(str,"%sdsts.dab",scfg.ctrl_dir);
189
	if((file=nopen(str,O_RDWR|O_BINARY))==-1) {
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
		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)
{
207
208
209
210
211
212
	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];
213
	char *p;
214
	char ext[1024],tmpext[513];
215
216
	int i,file;
	long l;
217
	BOOL exist;
218
219
220
221
222
	FILE *stream;
	DIR*	dir;
	DIRENT*	dirent;

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

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

			if(mode&FILE_DATE) {		/* get the file date and put into desc */
rswindell's avatar
rswindell committed
260
				unixtodstr(&scfg,(time32_t)file_timestamp,f.desc);
261
262
263
264
				strcat(f.desc,"  "); 
			}

			if(mode&TODAYS_DATE) {		/* put today's date in desc */
265
				unixtodstr(&scfg,time32(NULL),f.desc);
266
267
268
269
270
				strcat(f.desc,"  "); 
			}

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

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


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

	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);
353
	do {
354
355
		f.misc=0;
		f.desc[0]=0;
356
		SAFECOPY(curline,nextline);
357
358
359
		nextline[0]=0;
		fgets(nextline,255,stream);
		truncsp(curline);
360
		if(curline[0]<=' ' || (mode&ASCII_ONLY && (uchar)curline[0]>=0x7e))
361
362
			continue;
		printf("%s\n",curline);
363
		SAFECOPY(fname,curline);
364

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

379
380
381
382
383
384
385
386
387
388
389
		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

390
391
392
393
394
		padfname(fname,f.name);
		if(strcspn(f.name,"\\/|<>+[]:=\";,")!=strlen(f.name))
			continue;

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

		if(i<12)					/* Ctrl chars or EX-ASCII in filename? */
			continue;
rswindell's avatar
rswindell committed
400
		time_t file_timestamp = fdate(filepath);
401
402
		exist=findfile(&scfg,f.dir,f.name);
		if(exist) {
rswindell's avatar
rswindell committed
403
404
			if((mode&CHECK_DATE) && file_timestamp <= f.dateuled)
				continue;
405
406
407
408
			if(mode&NO_UPDATE)
				continue;
			getfileixb(&scfg,&f);
			if(mode&ULDATE_ONLY) {
409
				f.dateuled=time32(NULL);
410
				update_uldate(&scfg, &f);
411
412
413
				continue; 
			} 
		}
414
415

		if(mode&FILE_DATE) {		/* get the file date and put into desc */
rswindell's avatar
rswindell committed
416
			unixtodstr(&scfg,(time32_t)file_timestamp,f.desc);
417
418
			strcat(f.desc,"  "); 
		}
419
420

		if(mode&TODAYS_DATE) {		/* put today's date in desc */
421
			l=time32(NULL);
422
			unixtodstr(&scfg,l,f.desc);
423
424
			strcat(f.desc,"  "); 
		}
425
426
427

		if(dskip && strlen(curline)>=dskip) p=curline+dskip;
		else {
428
429
430
			p = curline;
			FIND_WHITESPACE(p);
			SKIP_WHITESPACE(p); 
431
		}
432
433
434
		SAFECOPY(tmp,p);
		prep_desc(tmp);
		sprintf(f.desc+strlen(f.desc),"%.*s",(int)(LEN_FDESC-strlen(f.desc)),tmp);
435

436
		if(nextline[0]==' ' || strlen(p)>LEN_FDESC) {	/* ext desc */
437
438
439
			if(!(mode&NO_EXTEND)) {
				memset(ext,0,513);
				f.misc|=FM_EXTDESC;
440
441
				sprintf(ext,"%s\r\n",p); 
			}
442

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

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


		if(sskip) l=atol(fname+sskip);
		else {
			l=flength(filepath);
479
			if(l<0L) {
480
				printf("%s not found.\n",filepath);
481
482
				continue; 
			} 
483
484
485
486
			if(l == 0L) {
				printf("%s is a zero-0length file.\n",filepath);
				continue; 
			} 
487
		}
488
489
490

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

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

		if(mode&UL_STATS)
			updatestats(l);
549
		files++; 
550
	} while(!feof(stream) && !ferror(stream));
551
552
553
	fclose(stream);
	if(mode&DEL_LIST && !(mode&SYNC_LIST)) {
		printf("\nDeleting %s\n",listpath);
554
555
		remove(listpath); 
	}
556
557
558
559
560

}

void synclist(char *inpath, int dirnum)
{
561
	char	str[1024];
562
563
564
	char	fname[MAX_PATH+1];
	char	listpath[MAX_PATH+1];
	uchar*	ixbbuf;
565
	char*	p;
566
567
568
569
	int		i,file,found;
	long	l,m,length;
	FILE*	stream;
	file_t	f;
570

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

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

	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)
613
				str[i]=ixbbuf[m]>' ' ? '.' : ' ';
614
615
616
617
618
619
620
621
622
623
			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);
624
			p=strchr(str,' ');
625
626
			if(p) *p=0;
			if(!stricmp(str,fname))
627
628
				found=1; 
		}
629
630
631
632
633
634
635
636
637
		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);
638
639
			continue; 
		}
640
		removefiledat(&scfg,&f);
641
		if(remove(getfilepath(&scfg,&f,str)))
642
643
			printf("Error removing %s\n",str);
		removed++;
644
645
		printf("Removed from database\n"); 
	}
646
647
648

	if(mode&DEL_LIST) {
		printf("\nDeleting %s\n",listpath);
649
650
		remove(listpath); 
	}
651
652
}

653
char *usage="\nusage: addfiles code [.alt_path] [-opts] +list "
654
			 "[desc_off] [size_off]"
655
	"\n   or: addfiles code [.alt_path] [-opts] file "
656
657
		"\"description\"\n"
	"\navailable opts:"
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"
rswindell's avatar
rswindell committed
668
	"\n      -p         compare file date with upload date for existing files"
669
670
671
672
673
674
	"\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)"
675
	"\n"
676
677
	"\nAuto-ADD:   use - in place of code for Auto-ADD of FILES.BBS"
	"\n            use -filename to Auto-ADD a different filename"
678
	"\n            use -l \"libname\" to only Auto-ADD files to a specific library"
679
680
681
682
683
684
685
686
	;

/*********************/
/* Entry point (duh) */
/*********************/
int main(int argc, char **argv)
{
	char error[512];
687
	char revision[16];
688
689
	char str[MAX_PATH+1];
	char tmp[MAX_PATH+1];
690
691
	char *p;
	char exist,listgiven=0,namegiven=0,ext[513]
692
		,auto_name[MAX_PATH+1]="FILES.BBS";
693
	int i,j,file;
694
	uint desc_offset=0, size_offset=0;
695
696
697
	long l;
	file_t	f;

698
	sscanf("$Revision$", "%*s %s", revision);
699

700
	fprintf(stderr,"\nADDFILES v%s-%s (rev %s) - Adds Files to Synchronet "
701
702
703
		"Filebase\n"
		,ADDFILES_VER
		,PLATFORM_DESC
704
		,revision
705
706
707
		);

	if(argc<2) {
708
		puts(usage);
709
710
		return(1); 
	}
711
712
713
714
715
716
717
718

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

719
720
	memset(&scfg,0,sizeof(scfg));
	scfg.size=sizeof(scfg);
721
	SAFECOPY(scfg.ctrl_dir,p);
722
723
724
725
726

	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);
727
728
729
730
	if(!load_cfg(&scfg,NULL,TRUE,error)) {
		fprintf(stderr,"!ERROR loading configuration files: %s\n",error);
		exit(1);
	}
rswindell's avatar
rswindell committed
731
732
	SAFECOPY(scfg.temp_dir,"../temp");
	prep_dir(scfg.ctrl_dir, scfg.temp_dir, sizeof(scfg.temp_dir));
733

734
735
	if(argv[1][0]=='*' || argv[1][0]=='-') {
		if(argv[1][1]=='?') {
736
			puts(usage);
737
738
			exit(0);
		}
739
		if(argv[1][1])
740
			SAFECOPY(auto_name,argv[1]+1);
741
		mode|=AUTO_ADD;
742
743
		i=0; 
	} else {
744
		if(!isalnum((uchar)argv[1][0]) && argc==2) {
745
			puts(usage);
746
747
748
			return(1); 
		}

749
		for(i=0;i<scfg.total_dirs;i++)
750
			if(!stricmp(scfg.dir[i]->code,argv[1])) /* use matchmatchi() instead? */
751
752
753
754
				break;

		if(i>=scfg.total_dirs) {
			printf("Directory code '%s' not found.\n",argv[1]);
755
756
757
			exit(1); 
		} 
	}
758
759
760

	memset(&f,0,sizeof(file_t));
	f.dir=i;
761
	SAFECOPY(f.uler,"-> ADDFILES <-");
762
763

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

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

			if(mode&UL_STATS)
				updatestats(l);
956
957
958
			files++; 
		} 
	}
959
960
961

	if(mode&AUTO_ADD) {
		for(i=0;i<scfg.total_dirs;i++) {
962
963
			if(lib[0] && stricmp(scfg.lib[scfg.dir[i]->lib]->sname,lib))
				continue;
964
965
966
967
			if(scfg.dir[i]->misc&DIR_NOAUTO)
				continue;
			f.dir=i;
			if(mode&SEARCH_DIR) {
968
				addlist("",f,desc_offset,size_offset);
969
970
				continue; 
			}
971
			sprintf(str,"%s%s.lst",scfg.dir[f.dir]->path,scfg.dir[f.dir]->code);
972
			if(fexistcase(str) && flength(str)>0L) {
973
				printf("Auto-adding %s\n",str);
974
				addlist(str,f,desc_offset,size_offset);
975
976
				if(mode&SYNC_LIST)
					synclist(str,i);
977
978
				continue; 
			}
979
			sprintf(str,"%s%s",scfg.dir[f.dir]->path,auto_name);
980
			if(fexistcase(str) && flength(str)>0L) {
981
				printf("Auto-adding %s\n",str);
982
				addlist(str,f,desc_offset,size_offset);
983
984
				if(mode&SYNC_LIST)
					synclist(str,i);
985
986
987
988
				continue; 
			} 
		} 
	}
989
990
991

	else {
		if(!listgiven && !namegiven) {
992
			sprintf(str,"%s%s.lst",scfg.dir[f.dir]->path, scfg.dir[f.dir]->code);
993
			if(!fexistcase(str) || flength(str)<=0L)
994
				sprintf(str,"%s%s",scfg.dir[f.dir]->path, auto_name);
995
			addlist(str,f,desc_offset,size_offset);
996
			if(mode&SYNC_LIST)
997
998
999
				synclist(str,f.dir); 
		} 
	}
1000
1001
1002
1003
1004
1005
1006
1007

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