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