xref: /csrg-svn/contrib/ansi/ansitape.c (revision 60586)
130880Sbostic #include <sys/types.h>
230880Sbostic #include <sys/time.h>
330880Sbostic #include <sys/mtio.h>
430880Sbostic #include <sys/ioctl.h>
530880Sbostic #include <sys/file.h>
630880Sbostic #include <sys/stat.h>
7*60586Sbostic 
830880Sbostic #include <a.out.h>
930880Sbostic #include <stdio.h>
1030880Sbostic #include <ctype.h>
11*60586Sbostic #include <unistd.h>
1230880Sbostic 
1330880Sbostic char *malloc();
14*60586Sbostic static void ansi_rewind();
1530880Sbostic int wflag;
1630880Sbostic int xflag;
1730880Sbostic int tflag;
1830880Sbostic int cflag;
1930880Sbostic int vflag;
2030880Sbostic int dflag;
2131972Sbostic int fflag;
2230880Sbostic int totalreadfiles = 0 ;
2330880Sbostic int totalreadblocks = 0 ;
2430880Sbostic int totalreadlines = 0 ;
2530880Sbostic int totalreadchars = 0 ;
2630880Sbostic int totalwritefiles = 0 ;
2730880Sbostic int totalwriteblocks = 0 ;
2830880Sbostic int totalwritelines = 0 ;
2930880Sbostic int totalwritechars = 0 ;
3030880Sbostic 
main(argc,argv)3130880Sbostic main(argc,argv)
3230880Sbostic 	int argc;
3330880Sbostic 	char *argv[];
3430880Sbostic {
3530880Sbostic 	struct tm *tm;
3632599Sbostic 	long timetemp,time();
3730880Sbostic 	int year;
3830880Sbostic 	int day;
3930880Sbostic 	char *tapename;
4030880Sbostic 	char *filename;
4130880Sbostic 	char *namelist=NULL;
4230880Sbostic 	char *device = "/dev/rmt12";
4330880Sbostic 	int tape;
4430880Sbostic 	int file;
4530880Sbostic 	int filenum;
4630880Sbostic 	int argnum;
4730880Sbostic 	char line[1001];
4830880Sbostic 	char vmsname[1000];
4930880Sbostic 	char unixname[1000];
5030880Sbostic 	FILE *names;
5130880Sbostic 	int count;
5230880Sbostic 	int tmp;
5330880Sbostic 	char blockchar;
5430880Sbostic 	int blocksize=2048;
5531972Sbostic 	int recordsize=1;
5630880Sbostic 
5730880Sbostic 	char *key;
5830880Sbostic 
5932599Sbostic 	timetemp = time((long *)NULL);
6030880Sbostic 	tm = localtime(&timetemp);
6130880Sbostic 	year = tm->tm_year;
6230880Sbostic 	day = tm->tm_yday;
6330880Sbostic 	tapename = malloc(10);
6430880Sbostic 	gethostname(tapename,6);
6530880Sbostic 	tapename[7]='\0';
6630880Sbostic 
6730880Sbostic 	/* parse command line */
6830880Sbostic 	if (argc < 2)
6930880Sbostic 		usage();
7030880Sbostic 
7130880Sbostic 	argv++;
7230880Sbostic 	argc--;
7330880Sbostic 	/* loop through first argument (key) */
7430880Sbostic 	argc--;
7530880Sbostic 	for (key = *argv++; *key; key++)
7630880Sbostic 		switch(*key) {
7730880Sbostic 
7830880Sbostic 		case 'f':
7930880Sbostic 			if (*argv == NULL || argc <1) {
8030880Sbostic 				fprintf(stderr,
8130880Sbostic 			"ansitape: 'f' option requires tape name \n");
8230880Sbostic 				usage();
8330880Sbostic 			}
8430880Sbostic 			device = *argv++;
8530880Sbostic 			argc--;
8630880Sbostic 			break;
8730880Sbostic 
8830880Sbostic 		case 'n':
8930880Sbostic 			if (*argv == NULL || argc <1) {
9030880Sbostic 				fprintf(stderr,
9130880Sbostic 			"ansitape: 'n' option requires file name\n");
9230880Sbostic 				usage();
9330880Sbostic 			}
9430880Sbostic 			namelist = *argv++;
9530880Sbostic 			argc--;
9630880Sbostic 			break;
9730880Sbostic 
9830880Sbostic 		case 'l':
9930880Sbostic 			if (*argv == NULL || argc<1) {
10030880Sbostic 				fprintf(stderr,
10130880Sbostic 			"ansitape: 'l' option requires label\n");
10230880Sbostic 				usage();
10330880Sbostic 			}
10430880Sbostic 			tapename = *argv++;
10530880Sbostic 			argc--;
10630880Sbostic 			break;
10730880Sbostic 
10831972Sbostic 		case 'F':
10931972Sbostic 			if(*argv == NULL) {
11031972Sbostic 				fprintf(stderr,
11131972Sbostic 		"ansitape: 'F' options requires recordsize and blocksize specifiers.\n"
11231972Sbostic 						);
11331972Sbostic 				usage();
11431972Sbostic 			}
11531972Sbostic 			tmp = sscanf(*argv++," %d%c ",&recordsize,&blockchar);
11631972Sbostic 			argc--;
11731972Sbostic 			if(tmp<1) {
11831972Sbostic 				fprintf(stderr,"illegal recordsize: recordsize set to 80\n");
11931972Sbostic 				recordsize=80;
12031972Sbostic 			} else if(tmp>1) {
12131972Sbostic 				if(blockchar == 'b') recordsize *= 512;
12231972Sbostic 				if(blockchar == 'k') recordsize *= 1024;
12331972Sbostic 			}
12431972Sbostic 
12531972Sbostic 			if (*argv == NULL) {
12631972Sbostic 				fprintf(stderr,
12731972Sbostic 			"ansitape: 'F' option requires blocksize specifier \n");
12831972Sbostic 				usage();
12931972Sbostic 			}
13031972Sbostic 			tmp = sscanf(*argv++," %d%c ",&blocksize,&blockchar);
13131972Sbostic 			argc--;
13231972Sbostic 			if(tmp<1) {
13331972Sbostic 				fprintf(stderr,"illegal blocksize: blocksize set to 2048\n");
13431972Sbostic 				blocksize=2048;
13531972Sbostic 			} else if(tmp>1) {
13631972Sbostic 				if(blockchar == 'b') blocksize *= 512;
13731972Sbostic 				if(blockchar == 'k') blocksize *= 1024;
13831972Sbostic 			}
13931972Sbostic 			if(blocksize <18) blocksize=18;
14031972Sbostic 			if(blocksize >62*1024) blocksize=62*1024;
14131972Sbostic 			fflag++;
14231972Sbostic 			break;
14331972Sbostic 
14430880Sbostic 		case 'b':
14530880Sbostic 			if (*argv == NULL) {
14630880Sbostic 				fprintf(stderr,
14730880Sbostic 			"ansitape: 'b' option requires blocksize specifier \n");
14830880Sbostic 				usage();
14930880Sbostic 			}
15030880Sbostic 			tmp = sscanf(*argv++," %d%c ",&blocksize,&blockchar);
15130880Sbostic 			argc--;
15230880Sbostic 			if(tmp<1) {
15330880Sbostic 				fprintf(stderr,"illegal blocksize: blocksize set to 2048\n");
15430880Sbostic 				blocksize=2048;
15530880Sbostic 			} else if(tmp>1) {
15630880Sbostic 				if(blockchar == 'b') blocksize *= 512;
15730880Sbostic 				if(blockchar == 'k') blocksize *= 1024;
15830880Sbostic 			}
15930880Sbostic 			if(blocksize <18) blocksize=18;
16030880Sbostic 			if(blocksize >62*1024) blocksize=62*1024;
16130880Sbostic 			break;
16230880Sbostic 
16330880Sbostic 		case 'c':
16430880Sbostic 			cflag++;
16530880Sbostic 			wflag++;
16630880Sbostic 			break;
16730880Sbostic 
16830880Sbostic 		case 'r':
16930880Sbostic 			/*I know, this should be rflag, but I just don't like r for write*/
17030880Sbostic 			wflag++;
17130880Sbostic 			break;
17230880Sbostic 
17330880Sbostic 		case 'v':
17430880Sbostic 			vflag++;
17530880Sbostic 			break;
17630880Sbostic 
17730880Sbostic 		case 'x':
17830880Sbostic 			xflag++;
17930880Sbostic 			break;
18030880Sbostic 
18130880Sbostic 		case 't':
18230880Sbostic 			tflag++;
18330880Sbostic 			break;
18430880Sbostic 
18530880Sbostic 		case '-':
18630880Sbostic 			break;
18730880Sbostic 
18830880Sbostic 		default:
18930880Sbostic 			fprintf(stderr, "ansitape: %c: unknown option\n", *key);
19030880Sbostic 			usage();
19130880Sbostic 		}
19230880Sbostic 
19330880Sbostic 	if (!wflag && !xflag && !tflag)
19430880Sbostic 		usage();
19530880Sbostic 
19630880Sbostic 	tape = open(device,wflag?O_RDWR:O_RDONLY,NULL);
19730880Sbostic 	if(tape<0) {
19830880Sbostic 		perror(device);
19932599Sbostic 		fprintf(stderr,"tape not accessable - check if drive online and write ring present\n");
20030880Sbostic 		exit(1);
20130880Sbostic 	}
202*60586Sbostic 	ansi_rewind(tape);
20330880Sbostic 	filenum=1;
20430880Sbostic 	casefix(tapename);
20530880Sbostic 
20630880Sbostic 	if(cflag) {
20730880Sbostic 		writevol(tapename,tape);
20830880Sbostic 	} else {
20930880Sbostic 		getvol(tapename,tape);
21030880Sbostic 		while(1) {
21130880Sbostic 			/* read files */
21230880Sbostic 			if( readfile(tape,argc,argv) ) break;
21330880Sbostic 			filenum++;
21430880Sbostic 		}
21530880Sbostic 		backspace(tape);
21630880Sbostic 	}
21730880Sbostic 
21830880Sbostic 	if(wflag) {
21930880Sbostic 		if(namelist) {
22030880Sbostic 			if(*namelist == '-') {
22130880Sbostic 				names = stdin;
22230880Sbostic 			} else {
22330880Sbostic 				names=fopen(namelist,"r");
22430880Sbostic 				if(names == NULL) {
22530880Sbostic 					fprintf(stderr,"unable to open namelist file - no files added to tape\n");
22630880Sbostic 				}
22730880Sbostic 			}
22830880Sbostic 			while(1) {
22930880Sbostic 				fgets(line,1000,names);
23030880Sbostic 				if(feof(names)) break;
23130880Sbostic 				count = sscanf(line,"%s %s",unixname,vmsname);
23230880Sbostic 				if(count<1) continue; /* blank line */
23330880Sbostic 				if(count==1) strcpy(vmsname,unixname);
23430880Sbostic 				casefix(vmsname);
23530880Sbostic 				if(filecheck(&file,unixname)) continue;
23631972Sbostic 				writefile(tape,file,vmsname,tapename,filenum,year,day,blocksize,
23731972Sbostic 						recordsize);
23830880Sbostic 				filenum++;
23930880Sbostic 				close(file);
24030880Sbostic 			}
24130880Sbostic 		} else {
24230880Sbostic 			for(argnum=0;argnum<argc;argnum++) {
24330880Sbostic 				filename = argv[argnum];
24430880Sbostic 				if(filecheck(&file,filename)) continue;
24530880Sbostic 				casefix(filename);
24631972Sbostic 				writefile(tape,file,filename,tapename,filenum,year,day,
24731972Sbostic 						blocksize,recordsize);
24830880Sbostic 				filenum++;
24930880Sbostic 				close(file);
25030880Sbostic 			}
25130880Sbostic 		}
25230880Sbostic 		writetm(tape);
25330880Sbostic 		writetm(tape);
25430880Sbostic 		writetm(tape);
25530880Sbostic 		writetm(tape);
25630880Sbostic 	}
257*60586Sbostic 	ansi_rewind(tape);
25830880Sbostic 	close(tape);
25930880Sbostic 	if(vflag && (tflag || xflag)) {
26030880Sbostic 		fprintf(stdout," read  %d files in %d blocks (%d lines, %d chars)\n",
26130880Sbostic 			totalreadfiles,totalreadblocks,totalreadlines,totalreadchars);
26230880Sbostic 	}
26330880Sbostic 	if(vflag && wflag) {
26430880Sbostic 		fprintf(stdout," wrote  %d files in %d blocks (%d lines, %d chars)\n",
26530880Sbostic 			totalwritefiles,totalwriteblocks,totalwritelines,totalwritechars);
26630880Sbostic 	}
26732594Sbostic 	return(0);
26830880Sbostic }
usage()26930880Sbostic usage() {
27030880Sbostic 	fprintf(stderr,
27130880Sbostic 			"ansitape: usage: ansitape -{rxtc}[flnvb] [filename] [label] [filename] [blocksize] [files]\n");
27232594Sbostic 	exit(1);
27330880Sbostic }
27430880Sbostic 
writefile(tape,file,filename,tapename,filenum,year,day,blocksize,recordsize)27531972Sbostic writefile(tape,file,filename,tapename,filenum,year,day,blocksize,recordsize)
27630880Sbostic 	int tape;
27730880Sbostic 	int file;
27830880Sbostic 	char *filename;
27930880Sbostic 	char *tapename;
28030880Sbostic 	int filenum;
28130880Sbostic 	int year;
28230880Sbostic 	int day;
28330880Sbostic 	int blocksize;
28431972Sbostic 	int recordsize;
28530880Sbostic 
28630880Sbostic {
28730880Sbostic 	int blocks;
28830880Sbostic 	writehdr1(tape,filename,tapename,filenum,year,day);
28931972Sbostic 	writehdr2(tape,blocksize,recordsize);
29030880Sbostic 	writehdr3(tape);
29130880Sbostic 	writetm(tape);
29231972Sbostic 	writedata(tape,file,filename,&blocks,blocksize,recordsize);
29330880Sbostic 	writetm(tape);
29430880Sbostic 	writeeof1(tape,filename,tapename,filenum,year,day,blocks);
29531972Sbostic 	writeeof2(tape,blocksize,recordsize);
29630880Sbostic 	writeeof3(tape);
29730880Sbostic 	writetm(tape);
29830880Sbostic 	totalwritefiles++;
29930880Sbostic }
30030880Sbostic 
writedata(tape,file,filename,blocks,blocksize,recsize)30131972Sbostic writedata(tape,file,filename,blocks,blocksize,recsize)
30230880Sbostic 	int tape;
30330880Sbostic 	int file;
30430880Sbostic 	char *filename;
30530880Sbostic 	int *blocks;
30630880Sbostic 	int blocksize;
30731972Sbostic 	int recsize;
30830880Sbostic {
30930880Sbostic char *ibuf;
31030880Sbostic char *ibufstart;
31130880Sbostic char *obuf;
31230880Sbostic char *obufstart;
31330880Sbostic char *endibuf;
31430880Sbostic char *endobuf;
31530880Sbostic int got;
31630880Sbostic int i;
31730880Sbostic char *j;
31830880Sbostic int numchar = 0 ;
31930880Sbostic int numline = 0 ;
32030880Sbostic int numblock = 0;
32130880Sbostic int success;
32230880Sbostic 
32332599Sbostic 	ibufstart = ibuf = malloc((unsigned)(blocksize<4096?8200:(2*blocksize+10)));
32432599Sbostic 	obufstart = obuf = malloc((unsigned)(blocksize+10));
32530880Sbostic 	endobuf = obuf + blocksize;
32630880Sbostic 	endibuf = ibuf;
32730880Sbostic 
32830880Sbostic 
32930880Sbostic 	i=0;
33031972Sbostic 	if (!fflag) {
33131972Sbostic 		while(1) {
33231972Sbostic 			if(ibuf+i>=endibuf) {	/* end of input buffer */
33331972Sbostic 				strncpy(ibufstart,ibuf,endibuf-ibuf); /* copy leftover to start */
33431972Sbostic 				ibuf = ibufstart+(endibuf-ibuf);	/* point to end of valid data */
33531972Sbostic 				got = read(file,ibuf,blocksize<4096?4096:2*blocksize);	/* read in a chunk */
33631972Sbostic 				endibuf = ibuf + got;
33731972Sbostic 				ibuf = ibufstart;	/* point to beginning of data */
33831972Sbostic 				if(got == 0) { /* end of input */
33931972Sbostic 					if(ibuf==ibufstart){ /* no leftovers */
34031972Sbostic 						break; /* done */
34131972Sbostic 					} else {
34231972Sbostic 						ibuf[i]='\n'; /* fake extra newline */
34331972Sbostic 					}
34430880Sbostic 				}
34530880Sbostic 			}
34630880Sbostic 
34731972Sbostic 			if(obuf+i+4 > endobuf) {  /* end of output buffer */
34831972Sbostic 				if(i>blocksize-4) {
34931972Sbostic 					printf("record exceeds blocksize - file truncated\n");
35031972Sbostic 					break;
35131972Sbostic 				}
35231972Sbostic 				/* filled up output record - have to fill,output,restart*/
35331972Sbostic 				for(j=obuf;j<endobuf;j++) {
35431972Sbostic 					*j = '^';
35531972Sbostic 				}
35631972Sbostic 				success = write(tape,obufstart,blocksize);
35731972Sbostic 				if(success != blocksize) {
35831972Sbostic 					perror("tape");
35931972Sbostic 					fprintf(stderr," hard write error:  write aborted\n");
360*60586Sbostic 					ansi_rewind(tape);
36131972Sbostic 					exit(1);
36231972Sbostic 				}
36331972Sbostic 				obuf=obufstart;
36431972Sbostic 				numchar -= i;
36531972Sbostic 				i=0;
36631972Sbostic 				numblock++;
36731972Sbostic 				continue;
36830880Sbostic 			}
36931972Sbostic 
37031972Sbostic 			if(ibuf[i] == '\n') { /* end of line */
37131972Sbostic 				obuf[0] = ((i+4)/1000) + '0';
37231972Sbostic 				obuf[1] = (((i+4)/100)%10) + '0';
37331972Sbostic 				obuf[2] = (((i+4)/10)%10) + '0';
37431972Sbostic 				obuf[3] = (((i+4)/1)%10) + '0';
37531972Sbostic 				obuf += (4+i); /* size + strlen */
37631972Sbostic 				ibuf += (1+i); /* newline + strlen */
37731972Sbostic 				i=0;
37831972Sbostic 				numline++;
37931972Sbostic 				continue; /* back to the top */
38031972Sbostic 			}
38131972Sbostic 
38231972Sbostic 			obuf[i+4]=ibuf[i];
38331972Sbostic 			numchar++;
38431972Sbostic 			i++;
38531972Sbostic 
38631972Sbostic 		}
38731972Sbostic 		/* exited - write last record and go for lunch */
38831972Sbostic 		if(obuf != obufstart) {
38930880Sbostic 			for(j=obuf;j<endobuf;j++) {
39030880Sbostic 				*j = '^';
39130880Sbostic 			}
39230880Sbostic 			success = write(tape,obufstart,blocksize);
39330880Sbostic 			if(success != blocksize) {
39430880Sbostic 				perror("tape");
39530880Sbostic 				fprintf(stderr," hard write error:  write aborted\n");
396*60586Sbostic 				ansi_rewind(tape);
39730880Sbostic 				exit(1);
39830880Sbostic 			}
39930880Sbostic 			numblock++;
40030880Sbostic 		}
40131972Sbostic 	 } else {
40231972Sbostic 		fflush(stdout);
40331972Sbostic 		while(1) {
40431972Sbostic 			/* writing an 'F' format tape */
40531972Sbostic 			got = read(file,ibuf,recsize+1);
40631972Sbostic 			if(got == 0) {
40731972Sbostic 				/* end of input */
40831972Sbostic 				if(obuf<=obufstart) {
40931972Sbostic 					break; /* done */
41031972Sbostic 				} else {
41131972Sbostic 					/* no more data, so force the record out */
41231972Sbostic 					recsize = blocksize+1;
41331972Sbostic 				}
41431972Sbostic 			} else if(got != recsize+1) {
41531972Sbostic 				printf("short read: filled\n");
41631972Sbostic 			} else if( *(ibuf+recsize) != '\n') {
41731972Sbostic 				printf("corrupted record - write aborted\b");
418*60586Sbostic 				ansi_rewind(tape);
41931972Sbostic 				exit(1);
42031972Sbostic 			}
42131972Sbostic 			if(obuf+recsize >endobuf) {
42231972Sbostic 				/*would overflow output buffer, so fill up old buffer */
42331972Sbostic 				for(j=obuf;j<endobuf;j++) {
42431972Sbostic 					*j = '^';
42531972Sbostic 				}
42631972Sbostic 				/* and write it */
42731972Sbostic 				success = write(tape,obufstart,blocksize);
42831972Sbostic 				if(success != blocksize) {
42931972Sbostic 					perror("tape");
43031972Sbostic 					fprintf(stderr," hard write error:   write aborted\n");
431*60586Sbostic 					ansi_rewind(tape);
43231972Sbostic 					exit(1);
43331972Sbostic 				}
43431972Sbostic 				obuf=obufstart;
43531972Sbostic 				numblock++;
43631972Sbostic 			}
43731972Sbostic 			bcopy(ibuf,obuf,recsize);
43831972Sbostic 			obuf+=got-1;
43930880Sbostic 			numline++;
44031972Sbostic 			numchar += recsize;
44130880Sbostic 		}
44231972Sbostic 		numchar -= recsize;
44331972Sbostic 		numline--;
44430880Sbostic 	}
44530880Sbostic 	free(ibufstart);
44630880Sbostic 	free(obufstart);
44730880Sbostic 	if(vflag) {
44830880Sbostic 		fprintf(stdout,"r - %s:  %d lines (%d chars) in %d tape blocks\n",
44930880Sbostic 				filename,numline,numchar,numblock);
45030880Sbostic 	}
45130880Sbostic 	totalwritechars += numchar;
45230880Sbostic 	totalwritelines += numline;
45330880Sbostic 	totalwriteblocks += numblock;
45430880Sbostic 	*blocks = numblock;
45530880Sbostic }
45630880Sbostic 
writetm(tape)45730880Sbostic writetm(tape)
45830880Sbostic 	int tape;
45930880Sbostic {
46030880Sbostic 	struct mtop mtop;
46130880Sbostic 	mtop.mt_op = MTWEOF;
46230880Sbostic 	mtop.mt_count = 1;
46330880Sbostic 	ioctl(tape,MTIOCTOP,&mtop);
46430880Sbostic }
46530880Sbostic 
46631972Sbostic void
ansi_rewind(tape)467*60586Sbostic static ansi_rewind(tape)
46830880Sbostic 	int tape;
46930880Sbostic {
47030880Sbostic 	struct mtop mtop;
47130880Sbostic 	mtop.mt_op = MTREW;
47230880Sbostic 	mtop.mt_count = 1;
47330880Sbostic 	ioctl(tape,MTIOCTOP,&mtop);
47430880Sbostic }
47530880Sbostic 
skipfile(tape)47630880Sbostic skipfile(tape)
47730880Sbostic 	int tape;
47830880Sbostic {
47930880Sbostic 	struct mtop mtop;
48030880Sbostic 	mtop.mt_op = MTFSF;
48130880Sbostic 	mtop.mt_count = 1;
48230880Sbostic 	ioctl(tape,MTIOCTOP,&mtop);
48330880Sbostic }
48430880Sbostic 
backspace(tape)48530880Sbostic backspace(tape)
48630880Sbostic 	int tape;
48730880Sbostic {
48830880Sbostic 	struct mtop mtop;
48930880Sbostic 	mtop.mt_op = MTBSF;
49030880Sbostic 	mtop.mt_count = 1;
49130880Sbostic 	ioctl(tape,MTIOCTOP,&mtop);
49230880Sbostic }
49330880Sbostic 
writehdr1(tape,filename,tapename,filenum,year,day)49430880Sbostic writehdr1(tape,filename,tapename,filenum,year,day)
49530880Sbostic 	int tape;
49630880Sbostic 	char *filename;
49730880Sbostic 	char *tapename;
49830880Sbostic 	int filenum;
49930880Sbostic 	int year;
50030880Sbostic 	int day;
50130880Sbostic {
50230880Sbostic 	char buf[81];
50330880Sbostic 	sprintf(buf,
50430880Sbostic "HDR1%-17.17s%-6.6s0001%4.4d000101 %2.2d%3.3d %2.2d%3.3d 000000DECFILE11A          "
50530880Sbostic 		,filename,tapename,filenum,year,day,year,day);
50630880Sbostic 	write(tape,buf,80);
50730880Sbostic }
50830880Sbostic 
writeeof1(tape,filename,tapename,filenum,year,day,blocks)50930880Sbostic writeeof1(tape,filename,tapename,filenum,year,day,blocks)
51030880Sbostic 	int tape;
51130880Sbostic 	char *filename;
51230880Sbostic 	char *tapename;
51330880Sbostic 	int filenum;
51430880Sbostic 	int year;
51530880Sbostic 	int day;
51630880Sbostic 	int blocks;
51730880Sbostic {
51830880Sbostic 	char buf[81];
51930880Sbostic 	sprintf(buf,
52030880Sbostic "EOF1%-17.17s%-6.6s0001%4.4d000101 %2.2d%3.3d %2.2d%3.3d %6.6dDECFILE11A          "
52130880Sbostic 		,filename,tapename,filenum,year,day,year,day,blocks);
52230880Sbostic 	write(tape,buf,80);
52330880Sbostic }
52430880Sbostic 
writehdr2(tape,blocksize,recordsize)52531972Sbostic writehdr2(tape,blocksize,recordsize)
52630880Sbostic 	int tape;
52730880Sbostic 	int blocksize;
52831972Sbostic 	int recordsize;
52930880Sbostic {
53030880Sbostic 	char buf[81];
53131972Sbostic 	sprintf(buf,"HDR2%c%5.5d%5.5d%35.35s00%28.28s",fflag?'F':'D',
53231972Sbostic 			blocksize,recordsize," "," ");
53330880Sbostic 	write(tape,buf,80);
53430880Sbostic }
53530880Sbostic 
writeeof2(tape,blocksize,recordsize)53631972Sbostic writeeof2(tape,blocksize,recordsize)
53730880Sbostic 	int tape;
53830880Sbostic 	int blocksize;
53931972Sbostic 	int recordsize;
54030880Sbostic {
54130880Sbostic 	char buf[81];
54231972Sbostic 	sprintf(buf,"EOF2%c%5.5d%5.5d%35.35s00%28.28s",fflag?'F':'D',
54331972Sbostic 			blocksize,recordsize," "," ");
54430880Sbostic 	write(tape,buf,80);
54530880Sbostic }
54630880Sbostic 
writehdr3(tape)54730880Sbostic writehdr3(tape)
54830880Sbostic 	int tape;
54930880Sbostic {
55030880Sbostic 	char buf[81];
55130880Sbostic 	sprintf(buf, "HDR3%76.76s"," ");
55230880Sbostic 	write(tape,buf,80);
55330880Sbostic }
55430880Sbostic 
writeeof3(tape)55530880Sbostic writeeof3(tape)
55630880Sbostic 	int tape;
55730880Sbostic {
55830880Sbostic 	char buf[81];
55930880Sbostic 	sprintf(buf, "EOF3%76.76s"," ");
56030880Sbostic 	write(tape,buf,80);
56130880Sbostic }
56230880Sbostic 
writevol(tapename,tape)56330880Sbostic writevol(tapename,tape)
56430880Sbostic 	int tape;
56530880Sbostic 	char *tapename;
56630880Sbostic {
56730880Sbostic 	char buf[81];
56832862Sbostic 	sprintf(buf,"VOL1%-6.6s %26.26sD%cC%10.10s1%28.28s3",tapename," ",'%'," "," ");
56930880Sbostic 	write(tape,buf,80);
57030880Sbostic 	if(vflag) {
57130880Sbostic 		fprintf(stdout," tape labeled %-6.6s\n",tapename);
57230880Sbostic 	}
57330880Sbostic }
57430880Sbostic 
getvol(tapename,tape)57530880Sbostic getvol(tapename,tape)
57630880Sbostic 	int tape;
57730880Sbostic 	char *tapename;
57830880Sbostic {
57930880Sbostic 	char buf[81];
58030880Sbostic 	read(tape,buf,80);
58130880Sbostic 	sscanf(buf,"VOL1%6s",tapename);
58230880Sbostic 	if(vflag) {
58330880Sbostic 		fprintf(stdout," tape was labeled %-6.6s\n",tapename);
58430880Sbostic 	}
58530880Sbostic }
58630880Sbostic 
casefix(string)58730880Sbostic casefix(string)
58830880Sbostic     register char *string;
58930880Sbostic {
59030880Sbostic     while(*string) {
59130880Sbostic         if(islower(*string)) {
59230880Sbostic             *string = toupper(*string);
59330880Sbostic         }
59430880Sbostic         string++;
59530880Sbostic     }
59630880Sbostic }
59730880Sbostic 
59830880Sbostic int
readfile(tape,argc,argv)59930880Sbostic readfile(tape,argc,argv)
60030880Sbostic 	int tape;
60130880Sbostic 	int argc;
60230880Sbostic 	char *argv[];
60330880Sbostic {
60430880Sbostic char buf[80];
60530880Sbostic char mode;
60630880Sbostic char filename[18];
60730880Sbostic FILE *file;
60830880Sbostic int extract;
60930880Sbostic char *ibuf;
61030880Sbostic char *ibufstart;
61130880Sbostic char *endibuf;
61231972Sbostic char *fixpoint;
61330880Sbostic int size;
61430880Sbostic int numblock = 0 ;
61530880Sbostic int numchar = 0 ;
61630880Sbostic int numline = 0 ;
61730880Sbostic int argnum;
61830880Sbostic int ok;
61930880Sbostic int blocksize;
62030880Sbostic int recordsize;
62130880Sbostic 
62230880Sbostic 	if(!(read(tape,buf,80))) return(1); /* no hdr record, so second eof */
62330880Sbostic 	sscanf(buf,"HDR1%17s",filename);
62430880Sbostic 	read(tape,buf,80);
62530880Sbostic 	sscanf(buf,"HDR2%c%5d%5d",&mode,&blocksize,&recordsize);
62630880Sbostic 	blocksize = blocksize>recordsize?blocksize:recordsize;
62730880Sbostic 	skipfile(tape); /* throw away rest of header(s) - not interesting */
62832599Sbostic 	ibufstart=ibuf=malloc((unsigned)(blocksize+10));
62930880Sbostic 	endibuf=ibufstart+blocksize;
63030880Sbostic 	extract=0;
63130880Sbostic 	if(tflag || xflag) {
63230880Sbostic 		ok=0;
63330880Sbostic 		if(!argc) {
63430880Sbostic 			ok=1;
63530880Sbostic 		} else for(argnum=0;argnum<argc;argnum++) {
63630880Sbostic 			casefix(argv[argnum]);
63730880Sbostic 			if(!strcmp(filename,argv[argnum])) {
63830880Sbostic 				ok=1;
63930880Sbostic 				break;
64030880Sbostic 			}
64130880Sbostic 		}
64230880Sbostic 		if(mode == 'D') {
64330880Sbostic 			if(xflag && ok) {
64430880Sbostic 				file = fopen(filename,"w");
64530880Sbostic 				if(file == NULL) {
64630880Sbostic 					perror(filename);
64730880Sbostic 				} else {
64830880Sbostic 					extract = 1;
64930880Sbostic 				}
65030880Sbostic 			}
65131972Sbostic 			while(size=read(tape,ibufstart,blocksize)) {
65231972Sbostic 				if(size != blocksize) {
65331972Sbostic 					/*
65431972Sbostic 					 * somebody's brain damaged program leaves
65531972Sbostic 					 * short blocks on the tape - fill them up to size
65631972Sbostic 					 * (this is work THEY should have done before writing
65731972Sbostic 					 * their undersized blocks)
65831972Sbostic 					 */
65931972Sbostic 					for(fixpoint=ibufstart+size;fixpoint<endibuf;fixpoint++) {
66031972Sbostic 						*fixpoint='^';
66131972Sbostic 					}
66231972Sbostic 				}
66330880Sbostic 				numblock++;
66430880Sbostic 				ibuf = ibufstart;
66530880Sbostic 				while(strncmp("^^^^",ibuf,4)) {
66631972Sbostic #define getsize(a) ((a[0]-'0')*1000)+((a[1]-'0')*100)+((a[2]-'0')*10)+(a[3]-'0')
66731972Sbostic #define bad(a) (!(isdigit(ibuf[a])))
66831972Sbostic 					if(bad(0) || bad(1) || bad(2) || bad(3)) {
66931972Sbostic 						fprintf(stderr, "error:  bad record length field - file may be corrupted, skipping\n");
67030881Sbostic 						break;
67130881Sbostic 					}
67231972Sbostic 					size = getsize(ibuf);
67330880Sbostic 					if(extract) {
67430880Sbostic 						fwrite(ibuf+4,sizeof(char),size-4,file);
67530880Sbostic 						fwrite("\n",1,1,file);
67630880Sbostic 					}
67730880Sbostic 					ibuf += (size);
67830880Sbostic 					numline++;
67930880Sbostic 					numchar += (size-4);
68030880Sbostic 					if(ibuf > endibuf+1) {
68130880Sbostic 						fprintf(stderr,"error:  bad tape records(s) - file may be corrupted\n");
68230880Sbostic 						break;
68330880Sbostic 					}
68430880Sbostic 					if(ibuf>endibuf-4) break;
68530880Sbostic 				}
68630880Sbostic 			}
68730880Sbostic 			if(extract) {
68830880Sbostic 				fclose(file);
68930880Sbostic 			}
69030880Sbostic 		} else if (mode == 'F') {
69130880Sbostic 			if(xflag && ok) {
69230880Sbostic 				file = fopen(filename,"w");
69330880Sbostic 				if(file == NULL) {
69430880Sbostic 					perror(filename);
69530880Sbostic 				} else {
69630880Sbostic 					extract = 1;
69730880Sbostic 				}
69830880Sbostic 			}
69930880Sbostic 			while(read(tape,ibufstart,blocksize)) {
70030880Sbostic 				numblock++;
70130880Sbostic 				ibuf = ibufstart;
70230880Sbostic 				while(ibuf+recordsize <= endibuf) {
70330880Sbostic 					if(extract) {
70430880Sbostic 						fwrite(ibuf,sizeof(char),recordsize,file);
70530880Sbostic 						fwrite("\n",1,1,file);
70630880Sbostic 					}
70730880Sbostic 					ibuf += recordsize;
70830880Sbostic 					numline++;
70930880Sbostic 					numchar += recordsize;
71030880Sbostic 				}
71130880Sbostic 			}
71230880Sbostic 			if(extract) {
71330880Sbostic 				fclose(file);
71430880Sbostic 			}
71530880Sbostic 		} else {
71630880Sbostic 			fprintf(stderr,"unknown record mode (%c) - file %s skipped\n",
71730880Sbostic 					mode,filename);
71830880Sbostic 			skipfile(tape);	/* throw away actual file */
71930880Sbostic 		}
72030880Sbostic 	} else {
72130880Sbostic 		/* not interested in contents of file, so move fast */
72230880Sbostic 		skipfile(tape);
72330880Sbostic 	}
72430880Sbostic 	skipfile(tape); /* throw away eof stuff - not interesting */
72530880Sbostic 	totalreadchars += numchar;
72630880Sbostic 	totalreadlines += numline;
72730880Sbostic 	totalreadblocks += numblock;
72830880Sbostic 	totalreadfiles ++;
72930880Sbostic 	if(xflag && vflag && ok) {
73030880Sbostic 		fprintf(stdout,"x - %s:  %d lines (%d chars) in %d tape blocks\n",
73130880Sbostic 				filename,numline,numchar,numblock);
73230880Sbostic 	} else if(tflag && ok) {
73330880Sbostic 		fprintf(stdout,"t - %s:  %d lines (%d chars) in %d tape blocks\n",
73430880Sbostic 				filename,numline,numchar,numblock);
73530880Sbostic 	}
73630880Sbostic 	free(ibufstart);
73730880Sbostic 	return(0);
73830880Sbostic }
73930880Sbostic 
filecheck(file,name)74030880Sbostic filecheck(file,name)
74130880Sbostic 	int *file;
74230880Sbostic 	char *name;
74330880Sbostic 
74430880Sbostic {
74530880Sbostic 
74630880Sbostic 	struct stat buf;
74730880Sbostic 	struct exec sample;
74830880Sbostic 
74930880Sbostic 	stat(name,&buf);
75030880Sbostic 	if ((buf.st_mode & S_IFDIR)==S_IFDIR) {
75130880Sbostic 		fprintf(stderr,"%s: directory - skipped\n",name);
75230880Sbostic 		return(1);
75330880Sbostic 	}
75430880Sbostic 	if ((buf.st_mode & S_IFCHR)==S_IFCHR) {
75530880Sbostic 		fprintf(stderr,"%s: character device - skipped\n",name);
75630880Sbostic 		return(1);
75730880Sbostic 	}
75830880Sbostic 	if ((buf.st_mode & S_IFBLK)==S_IFBLK) {
75930880Sbostic 		fprintf(stderr,"%s: block device - skipped\n",name);
76030880Sbostic 		return(1);
76130880Sbostic 	}
76230880Sbostic 	if ((buf.st_mode & S_IFLNK)==S_IFLNK) {
76330880Sbostic 		fprintf(stderr,"%s: symbolic link - skipped\n",name);
76430880Sbostic 		return(1);
76530880Sbostic 	}
76630880Sbostic 	if ((buf.st_mode & S_IFSOCK)==S_IFSOCK) {
76730880Sbostic 		fprintf(stderr,"%s: socket - skipped\n",name);
76830880Sbostic 		return(1);
76930880Sbostic 	}
77030880Sbostic 	*file = open(name,O_RDONLY,NULL);
77130880Sbostic 	if(*file <0) {
77230880Sbostic 		perror(name);
77330880Sbostic 		return(1);
77430880Sbostic 	}
77530880Sbostic 	if(read(*file,&sample,sizeof(struct exec))>= sizeof(struct exec)) {
77630880Sbostic 		if(!(N_BADMAG(sample))) {
77730880Sbostic 			/* executable */
77830880Sbostic 			/* the format requires either fixed blocked records,
77930880Sbostic 			 * or variable format records with each record remaining
78030880Sbostic 			 * entirely within a tape block - this limits the
78130880Sbostic 			 * distance between \n's to 2044 bytes, something
78230880Sbostic 			 * which is VERY rarely true of executables, so
78330880Sbostic 			 * we don't even try with them....
78430880Sbostic 			 */
78530880Sbostic 			close(*file);
78630880Sbostic 			fprintf(stderr,"%s: executable - skipped\n",name);
78730880Sbostic 			return(1);
78830880Sbostic 		}
78930880Sbostic 	}
79030880Sbostic 	/* either couldn't read sizeof(struct exec) or wasn't executable */
79130880Sbostic 	/* so we assume it is a reasonable file until proven otherwise */
79230880Sbostic 	lseek(*file,0l,0);
79330880Sbostic 	return(0);
79430880Sbostic }
795