xref: /csrg-svn/contrib/ansi/ansitape.c (revision 30880)
1*30880Sbostic #include <sys/types.h>
2*30880Sbostic #include <sys/time.h>
3*30880Sbostic #include <sys/mtio.h>
4*30880Sbostic #include <sys/ioctl.h>
5*30880Sbostic #include <sys/file.h>
6*30880Sbostic #include <sys/stat.h>
7*30880Sbostic #include <a.out.h>
8*30880Sbostic #include <stdio.h>
9*30880Sbostic #include <ctype.h>
10*30880Sbostic 
11*30880Sbostic char *malloc();
12*30880Sbostic int wflag;
13*30880Sbostic int xflag;
14*30880Sbostic int tflag;
15*30880Sbostic int cflag;
16*30880Sbostic int vflag;
17*30880Sbostic int dflag;
18*30880Sbostic int totalreadfiles = 0 ;
19*30880Sbostic int totalreadblocks = 0 ;
20*30880Sbostic int totalreadlines = 0 ;
21*30880Sbostic int totalreadchars = 0 ;
22*30880Sbostic int totalwritefiles = 0 ;
23*30880Sbostic int totalwriteblocks = 0 ;
24*30880Sbostic int totalwritelines = 0 ;
25*30880Sbostic int totalwritechars = 0 ;
26*30880Sbostic 
27*30880Sbostic main(argc,argv)
28*30880Sbostic 	int argc;
29*30880Sbostic 	char *argv[];
30*30880Sbostic {
31*30880Sbostic 	struct tm *tm;
32*30880Sbostic 	long timetemp;
33*30880Sbostic 	int year;
34*30880Sbostic 	int day;
35*30880Sbostic 	char *tapename;
36*30880Sbostic 	char *filename;
37*30880Sbostic 	char *namelist=NULL;
38*30880Sbostic 	char *device = "/dev/rmt12";
39*30880Sbostic 	int tape;
40*30880Sbostic 	int file;
41*30880Sbostic 	int filenum;
42*30880Sbostic 	int argnum;
43*30880Sbostic 	char line[1001];
44*30880Sbostic 	char vmsname[1000];
45*30880Sbostic 	char unixname[1000];
46*30880Sbostic 	FILE *names;
47*30880Sbostic 	int count;
48*30880Sbostic 	int tmp;
49*30880Sbostic 	char blockchar;
50*30880Sbostic 	int blocksize=2048;
51*30880Sbostic 
52*30880Sbostic 	char *key;
53*30880Sbostic 
54*30880Sbostic 	timetemp = time(0);
55*30880Sbostic 	tm = localtime(&timetemp);
56*30880Sbostic 	year = tm->tm_year;
57*30880Sbostic 	day = tm->tm_yday;
58*30880Sbostic 	tapename = malloc(10);
59*30880Sbostic 	gethostname(tapename,6);
60*30880Sbostic 	tapename[7]='\0';
61*30880Sbostic 
62*30880Sbostic 	/* parse command line */
63*30880Sbostic 	if (argc < 2)
64*30880Sbostic 		usage();
65*30880Sbostic 
66*30880Sbostic 	argv++;
67*30880Sbostic 	argc--;
68*30880Sbostic 	/* loop through first argument (key) */
69*30880Sbostic 	argc--;
70*30880Sbostic 	for (key = *argv++; *key; key++)
71*30880Sbostic 		switch(*key) {
72*30880Sbostic 
73*30880Sbostic 		case 'f':
74*30880Sbostic 			if (*argv == NULL || argc <1) {
75*30880Sbostic 				fprintf(stderr,
76*30880Sbostic 			"ansitape: 'f' option requires tape name \n");
77*30880Sbostic 				usage();
78*30880Sbostic 			}
79*30880Sbostic 			device = *argv++;
80*30880Sbostic 			argc--;
81*30880Sbostic 			break;
82*30880Sbostic 
83*30880Sbostic 		case 'n':
84*30880Sbostic 			if (*argv == NULL || argc <1) {
85*30880Sbostic 				fprintf(stderr,
86*30880Sbostic 			"ansitape: 'n' option requires file name\n");
87*30880Sbostic 				usage();
88*30880Sbostic 			}
89*30880Sbostic 			namelist = *argv++;
90*30880Sbostic 			argc--;
91*30880Sbostic 			break;
92*30880Sbostic 
93*30880Sbostic 		case 'l':
94*30880Sbostic 			if (*argv == NULL || argc<1) {
95*30880Sbostic 				fprintf(stderr,
96*30880Sbostic 			"ansitape: 'l' option requires label\n");
97*30880Sbostic 				usage();
98*30880Sbostic 			}
99*30880Sbostic 			tapename = *argv++;
100*30880Sbostic 			argc--;
101*30880Sbostic 			break;
102*30880Sbostic 
103*30880Sbostic 		case 'b':
104*30880Sbostic 			if (*argv == NULL) {
105*30880Sbostic 				fprintf(stderr,
106*30880Sbostic 			"ansitape: 'b' option requires blocksize specifier \n");
107*30880Sbostic 				usage();
108*30880Sbostic 			}
109*30880Sbostic 			tmp = sscanf(*argv++," %d%c ",&blocksize,&blockchar);
110*30880Sbostic 			argc--;
111*30880Sbostic 			if(tmp<1) {
112*30880Sbostic 				fprintf(stderr,"illegal blocksize: blocksize set to 2048\n");
113*30880Sbostic 				blocksize=2048;
114*30880Sbostic 			} else if(tmp>1) {
115*30880Sbostic 				if(blockchar == 'b') blocksize *= 512;
116*30880Sbostic 				if(blockchar == 'k') blocksize *= 1024;
117*30880Sbostic 			}
118*30880Sbostic 			if(blocksize <18) blocksize=18;
119*30880Sbostic 			if(blocksize >62*1024) blocksize=62*1024;
120*30880Sbostic 			break;
121*30880Sbostic 
122*30880Sbostic 		case 'c':
123*30880Sbostic 			cflag++;
124*30880Sbostic 			wflag++;
125*30880Sbostic 			break;
126*30880Sbostic 
127*30880Sbostic 		case 'r':
128*30880Sbostic 			/*I know, this should be rflag, but I just don't like r for write*/
129*30880Sbostic 			wflag++;
130*30880Sbostic 			break;
131*30880Sbostic 
132*30880Sbostic 		case 'v':
133*30880Sbostic 			vflag++;
134*30880Sbostic 			break;
135*30880Sbostic 
136*30880Sbostic 		case 'x':
137*30880Sbostic 			xflag++;
138*30880Sbostic 			break;
139*30880Sbostic 
140*30880Sbostic 		case 't':
141*30880Sbostic 			tflag++;
142*30880Sbostic 			break;
143*30880Sbostic 
144*30880Sbostic 		case '-':
145*30880Sbostic 			break;
146*30880Sbostic 
147*30880Sbostic 		default:
148*30880Sbostic 			fprintf(stderr, "ansitape: %c: unknown option\n", *key);
149*30880Sbostic 			usage();
150*30880Sbostic 		}
151*30880Sbostic 
152*30880Sbostic 	if (!wflag && !xflag && !tflag)
153*30880Sbostic 		usage();
154*30880Sbostic 
155*30880Sbostic 	tape = open(device,wflag?O_RDWR:O_RDONLY,NULL);
156*30880Sbostic 	if(tape<0) {
157*30880Sbostic 		perror(device);
158*30880Sbostic 		printf(stderr,"tape not accessable - check if drive online and write ring present\n");
159*30880Sbostic 		exit(1);
160*30880Sbostic 	}
161*30880Sbostic 	rewind(tape);
162*30880Sbostic 	filenum=1;
163*30880Sbostic 	casefix(tapename);
164*30880Sbostic 
165*30880Sbostic 	if(cflag) {
166*30880Sbostic 		writevol(tapename,tape);
167*30880Sbostic 	} else {
168*30880Sbostic 		getvol(tapename,tape);
169*30880Sbostic 		while(1) {
170*30880Sbostic 			/* read files */
171*30880Sbostic 			if( readfile(tape,argc,argv) ) break;
172*30880Sbostic 			filenum++;
173*30880Sbostic 		}
174*30880Sbostic 		backspace(tape);
175*30880Sbostic 	}
176*30880Sbostic 
177*30880Sbostic 	if(wflag) {
178*30880Sbostic 		if(namelist) {
179*30880Sbostic 			if(*namelist == '-') {
180*30880Sbostic 				names = stdin;
181*30880Sbostic 			} else {
182*30880Sbostic 				names=fopen(namelist,"r");
183*30880Sbostic 				if(names == NULL) {
184*30880Sbostic 					fprintf(stderr,"unable to open namelist file - no files added to tape\n");
185*30880Sbostic 				}
186*30880Sbostic 			}
187*30880Sbostic 			while(1) {
188*30880Sbostic 				fgets(line,1000,names);
189*30880Sbostic 				if(feof(names)) break;
190*30880Sbostic 				count = sscanf(line,"%s %s",unixname,vmsname);
191*30880Sbostic 				if(count<1) continue; /* blank line */
192*30880Sbostic 				if(count==1) strcpy(vmsname,unixname);
193*30880Sbostic 				casefix(vmsname);
194*30880Sbostic 				if(filecheck(&file,unixname)) continue;
195*30880Sbostic 				writefile(tape,file,vmsname,tapename,filenum,year,day,blocksize);
196*30880Sbostic 				filenum++;
197*30880Sbostic 				close(file);
198*30880Sbostic 			}
199*30880Sbostic 		} else {
200*30880Sbostic 			for(argnum=0;argnum<argc;argnum++) {
201*30880Sbostic 				filename = argv[argnum];
202*30880Sbostic 				if(filecheck(&file,filename)) continue;
203*30880Sbostic 				casefix(filename);
204*30880Sbostic 				writefile(tape,file,filename,tapename,filenum,year,day,blocksize);
205*30880Sbostic 				filenum++;
206*30880Sbostic 				close(file);
207*30880Sbostic 			}
208*30880Sbostic 		}
209*30880Sbostic 		writetm(tape);
210*30880Sbostic 		writetm(tape);
211*30880Sbostic 		writetm(tape);
212*30880Sbostic 		writetm(tape);
213*30880Sbostic 	}
214*30880Sbostic 	rewind(tape);
215*30880Sbostic 	close(tape);
216*30880Sbostic 	if(vflag && (tflag || xflag)) {
217*30880Sbostic 		fprintf(stdout," read  %d files in %d blocks (%d lines, %d chars)\n",
218*30880Sbostic 			totalreadfiles,totalreadblocks,totalreadlines,totalreadchars);
219*30880Sbostic 	}
220*30880Sbostic 	if(vflag && wflag) {
221*30880Sbostic 		fprintf(stdout," wrote  %d files in %d blocks (%d lines, %d chars)\n",
222*30880Sbostic 			totalwritefiles,totalwriteblocks,totalwritelines,totalwritechars);
223*30880Sbostic 	}
224*30880Sbostic }
225*30880Sbostic usage() {
226*30880Sbostic 	fprintf(stderr,
227*30880Sbostic 			"ansitape: usage: ansitape -{rxtc}[flnvb] [filename] [label] [filename] [blocksize] [files]\n");
228*30880Sbostic 	exit();
229*30880Sbostic }
230*30880Sbostic 
231*30880Sbostic writefile(tape,file,filename,tapename,filenum,year,day,blocksize)
232*30880Sbostic 	int tape;
233*30880Sbostic 	int file;
234*30880Sbostic 	char *filename;
235*30880Sbostic 	char *tapename;
236*30880Sbostic 	int filenum;
237*30880Sbostic 	int year;
238*30880Sbostic 	int day;
239*30880Sbostic 	int blocksize;
240*30880Sbostic 
241*30880Sbostic {
242*30880Sbostic 	int blocks;
243*30880Sbostic 	writehdr1(tape,filename,tapename,filenum,year,day);
244*30880Sbostic 	writehdr2(tape,blocksize);
245*30880Sbostic 	writehdr3(tape);
246*30880Sbostic 	writetm(tape);
247*30880Sbostic 	writedata(tape,file,filename,&blocks,blocksize);
248*30880Sbostic 	writetm(tape);
249*30880Sbostic 	writeeof1(tape,filename,tapename,filenum,year,day,blocks);
250*30880Sbostic 	writeeof2(tape);
251*30880Sbostic 	writeeof3(tape);
252*30880Sbostic 	writetm(tape);
253*30880Sbostic 	totalwritefiles++;
254*30880Sbostic }
255*30880Sbostic 
256*30880Sbostic writedata(tape,file,filename,blocks,blocksize)
257*30880Sbostic 	int tape;
258*30880Sbostic 	int file;
259*30880Sbostic 	char *filename;
260*30880Sbostic 	int *blocks;
261*30880Sbostic 	int blocksize;
262*30880Sbostic {
263*30880Sbostic char *ibuf;
264*30880Sbostic char *ibufstart;
265*30880Sbostic char *obuf;
266*30880Sbostic char *obufstart;
267*30880Sbostic char sizebuf[5];
268*30880Sbostic char *endibuf;
269*30880Sbostic char *endobuf;
270*30880Sbostic int got;
271*30880Sbostic int i;
272*30880Sbostic char *j;
273*30880Sbostic int numchar = 0 ;
274*30880Sbostic int numline = 0 ;
275*30880Sbostic int numblock = 0;
276*30880Sbostic int success;
277*30880Sbostic 
278*30880Sbostic 	ibufstart = ibuf = malloc(blocksize<4096?8200:(2*blocksize+10));
279*30880Sbostic 	obufstart = obuf = malloc(blocksize+10);
280*30880Sbostic 	endobuf = obuf + blocksize;
281*30880Sbostic 	endibuf = ibuf;
282*30880Sbostic 
283*30880Sbostic 
284*30880Sbostic 	i=0;
285*30880Sbostic 	while(1) {
286*30880Sbostic 		if(ibuf+i>=endibuf) {	/* end of input buffer */
287*30880Sbostic 			strncpy(ibufstart,ibuf,endibuf-ibuf); /* copy leftover to start */
288*30880Sbostic 			ibuf = ibufstart+(endibuf-ibuf);	/* point to end of valid data */
289*30880Sbostic 			got = read(file,ibuf,blocksize<4096?4096:2*blocksize);	/* read in a chunk */
290*30880Sbostic 			endibuf = ibuf + got;
291*30880Sbostic 			ibuf = ibufstart;	/* point to beginning of data */
292*30880Sbostic 			if(got == 0) { /* end of input */
293*30880Sbostic 				if(ibuf==ibufstart){ /* no leftovers */
294*30880Sbostic 					break; /* done */
295*30880Sbostic 				} else {
296*30880Sbostic 					ibuf[i]='\n'; /* fake extra newline */
297*30880Sbostic 				}
298*30880Sbostic 			}
299*30880Sbostic 		}
300*30880Sbostic 
301*30880Sbostic 		if(obuf+i+4 > endobuf) {  /* end of output buffer */
302*30880Sbostic 			if(i>blocksize-4) {
303*30880Sbostic 				printf("record exceeds blocksize - file truncated\n");
304*30880Sbostic 				break;
305*30880Sbostic 			}
306*30880Sbostic 			/* filled up output record - have to fill,output,restart*/
307*30880Sbostic 			for(j=obuf;j<endobuf;j++) {
308*30880Sbostic 				*j = '^';
309*30880Sbostic 			}
310*30880Sbostic 			success = write(tape,obufstart,blocksize);
311*30880Sbostic 			if(success != blocksize) {
312*30880Sbostic 				perror("tape");
313*30880Sbostic 				fprintf(stderr," hard write error:  write aborted\n");
314*30880Sbostic 				rewind(tape);
315*30880Sbostic 				exit(1);
316*30880Sbostic 			}
317*30880Sbostic 			obuf=obufstart;
318*30880Sbostic 			numchar -= i;
319*30880Sbostic 			i=0;
320*30880Sbostic 			numblock++;
321*30880Sbostic 			continue;
322*30880Sbostic 		}
323*30880Sbostic 
324*30880Sbostic 		if(ibuf[i] == '\n') { /* end of line */
325*30880Sbostic 			/*sprintf(sizebuf,"%4.4d",i+4); /* make length string */
326*30880Sbostic 			/*strncpy(obuf,sizebuf,4); /* put in length field */
327*30880Sbostic 			obuf[0] = ((i+4)/1000) + '0';
328*30880Sbostic 			obuf[1] = (((i+4)/100)%10) + '0';
329*30880Sbostic 			obuf[2] = (((i+4)/10)%10) + '0';
330*30880Sbostic 			obuf[3] = (((i+4)/1)%10) + '0';
331*30880Sbostic 			obuf += (4+i); /* size + strlen */
332*30880Sbostic 			ibuf += (1+i); /* newline + strlen */
333*30880Sbostic 			i=0;
334*30880Sbostic 			numline++;
335*30880Sbostic 			continue; /* back to the top */
336*30880Sbostic 		}
337*30880Sbostic 
338*30880Sbostic 		obuf[i+4]=ibuf[i];
339*30880Sbostic 		numchar++;
340*30880Sbostic 		i++;
341*30880Sbostic 
342*30880Sbostic 	}
343*30880Sbostic 	/* exited - write last record and go for lunch */
344*30880Sbostic 	if(obuf != obufstart) {
345*30880Sbostic 		for(j=obuf;j<endobuf;j++) {
346*30880Sbostic 			*j = '^';
347*30880Sbostic 		}
348*30880Sbostic 		success = write(tape,obufstart,blocksize);
349*30880Sbostic 		if(success != blocksize) {
350*30880Sbostic 			perror("tape");
351*30880Sbostic 			fprintf(stderr," hard write error:  write aborted\n");
352*30880Sbostic 			rewind(tape);
353*30880Sbostic 			exit(1);
354*30880Sbostic 		}
355*30880Sbostic 		numblock++;
356*30880Sbostic 	}
357*30880Sbostic 	free(ibufstart);
358*30880Sbostic 	free(obufstart);
359*30880Sbostic 	if(vflag) {
360*30880Sbostic 		fprintf(stdout,"r - %s:  %d lines (%d chars) in %d tape blocks\n",
361*30880Sbostic 				filename,numline,numchar,numblock);
362*30880Sbostic 	}
363*30880Sbostic 	totalwritechars += numchar;
364*30880Sbostic 	totalwritelines += numline;
365*30880Sbostic 	totalwriteblocks += numblock;
366*30880Sbostic 	*blocks = numblock;
367*30880Sbostic }
368*30880Sbostic 
369*30880Sbostic writetm(tape)
370*30880Sbostic 	int tape;
371*30880Sbostic {
372*30880Sbostic 	struct mtop mtop;
373*30880Sbostic 	mtop.mt_op = MTWEOF;
374*30880Sbostic 	mtop.mt_count = 1;
375*30880Sbostic 	ioctl(tape,MTIOCTOP,&mtop);
376*30880Sbostic }
377*30880Sbostic 
378*30880Sbostic rewind(tape)
379*30880Sbostic 	int tape;
380*30880Sbostic {
381*30880Sbostic 	struct mtop mtop;
382*30880Sbostic 	mtop.mt_op = MTREW;
383*30880Sbostic 	mtop.mt_count = 1;
384*30880Sbostic 	ioctl(tape,MTIOCTOP,&mtop);
385*30880Sbostic }
386*30880Sbostic 
387*30880Sbostic skipfile(tape)
388*30880Sbostic 	int tape;
389*30880Sbostic {
390*30880Sbostic 	struct mtop mtop;
391*30880Sbostic 	mtop.mt_op = MTFSF;
392*30880Sbostic 	mtop.mt_count = 1;
393*30880Sbostic 	ioctl(tape,MTIOCTOP,&mtop);
394*30880Sbostic }
395*30880Sbostic 
396*30880Sbostic backspace(tape)
397*30880Sbostic 	int tape;
398*30880Sbostic {
399*30880Sbostic 	struct mtop mtop;
400*30880Sbostic 	mtop.mt_op = MTBSF;
401*30880Sbostic 	mtop.mt_count = 1;
402*30880Sbostic 	ioctl(tape,MTIOCTOP,&mtop);
403*30880Sbostic }
404*30880Sbostic 
405*30880Sbostic writehdr1(tape,filename,tapename,filenum,year,day)
406*30880Sbostic 	int tape;
407*30880Sbostic 	char *filename;
408*30880Sbostic 	char *tapename;
409*30880Sbostic 	int filenum;
410*30880Sbostic 	int year;
411*30880Sbostic 	int day;
412*30880Sbostic {
413*30880Sbostic 	char buf[81];
414*30880Sbostic 	sprintf(buf,
415*30880Sbostic "HDR1%-17.17s%-6.6s0001%4.4d000101 %2.2d%3.3d %2.2d%3.3d 000000DECFILE11A          "
416*30880Sbostic 		,filename,tapename,filenum,year,day,year,day);
417*30880Sbostic 	write(tape,buf,80);
418*30880Sbostic }
419*30880Sbostic 
420*30880Sbostic writeeof1(tape,filename,tapename,filenum,year,day,blocks)
421*30880Sbostic 	int tape;
422*30880Sbostic 	char *filename;
423*30880Sbostic 	char *tapename;
424*30880Sbostic 	int filenum;
425*30880Sbostic 	int year;
426*30880Sbostic 	int day;
427*30880Sbostic 	int blocks;
428*30880Sbostic {
429*30880Sbostic 	char buf[81];
430*30880Sbostic 	sprintf(buf,
431*30880Sbostic "EOF1%-17.17s%-6.6s0001%4.4d000101 %2.2d%3.3d %2.2d%3.3d %6.6dDECFILE11A          "
432*30880Sbostic 		,filename,tapename,filenum,year,day,year,day,blocks);
433*30880Sbostic 	write(tape,buf,80);
434*30880Sbostic }
435*30880Sbostic 
436*30880Sbostic writehdr2(tape,blocksize)
437*30880Sbostic 	int tape;
438*30880Sbostic 	int blocksize;
439*30880Sbostic {
440*30880Sbostic 	char buf[81];
441*30880Sbostic 	sprintf(buf, "HDR2D%5.5d%5.5d%35.35s00%28.28s",blocksize,blocksize," "," ");
442*30880Sbostic 	write(tape,buf,80);
443*30880Sbostic }
444*30880Sbostic 
445*30880Sbostic writeeof2(tape,blocksize)
446*30880Sbostic 	int tape;
447*30880Sbostic 	int blocksize;
448*30880Sbostic {
449*30880Sbostic 	char buf[81];
450*30880Sbostic 	sprintf(buf, "EOF2D%5.5d%5.5d%35.35s00%28.28s",blocksize,blocksize," "," ");
451*30880Sbostic 	write(tape,buf,80);
452*30880Sbostic }
453*30880Sbostic 
454*30880Sbostic writehdr3(tape)
455*30880Sbostic 	int tape;
456*30880Sbostic {
457*30880Sbostic 	char buf[81];
458*30880Sbostic 	sprintf(buf, "HDR3%76.76s"," ");
459*30880Sbostic 	write(tape,buf,80);
460*30880Sbostic }
461*30880Sbostic 
462*30880Sbostic writeeof3(tape)
463*30880Sbostic 	int tape;
464*30880Sbostic {
465*30880Sbostic 	char buf[81];
466*30880Sbostic 	sprintf(buf, "EOF3%76.76s"," ");
467*30880Sbostic 	write(tape,buf,80);
468*30880Sbostic }
469*30880Sbostic 
470*30880Sbostic writevol(tapename,tape)
471*30880Sbostic 	int tape;
472*30880Sbostic 	char *tapename;
473*30880Sbostic {
474*30880Sbostic 	char buf[81];
475*30880Sbostic 	sprintf(buf,"VOL1%-6.6s %26.26sD%47510.10s1%28.28s3",tapename," "," "," ");
476*30880Sbostic 	write(tape,buf,80);
477*30880Sbostic 	if(vflag) {
478*30880Sbostic 		fprintf(stdout," tape labeled %-6.6s\n",tapename);
479*30880Sbostic 	}
480*30880Sbostic }
481*30880Sbostic 
482*30880Sbostic getvol(tapename,tape)
483*30880Sbostic 	int tape;
484*30880Sbostic 	char *tapename;
485*30880Sbostic {
486*30880Sbostic 	char buf[81];
487*30880Sbostic 	read(tape,buf,80);
488*30880Sbostic 	sscanf(buf,"VOL1%6s",tapename);
489*30880Sbostic 	if(vflag) {
490*30880Sbostic 		fprintf(stdout," tape was labeled %-6.6s\n",tapename);
491*30880Sbostic 	}
492*30880Sbostic }
493*30880Sbostic 
494*30880Sbostic casefix(string)
495*30880Sbostic     register char *string;
496*30880Sbostic {
497*30880Sbostic     while(*string) {
498*30880Sbostic         if(islower(*string)) {
499*30880Sbostic             *string = toupper(*string);
500*30880Sbostic         }
501*30880Sbostic         string++;
502*30880Sbostic     }
503*30880Sbostic }
504*30880Sbostic 
505*30880Sbostic #define getsize(a) ((a[0]-'0')*1000)+((a[1]-'0')*100)+((a[2]-'0')*10)+(a[3]-'0')
506*30880Sbostic int
507*30880Sbostic readfile(tape,argc,argv)
508*30880Sbostic 	int tape;
509*30880Sbostic 	int argc;
510*30880Sbostic 	char *argv[];
511*30880Sbostic {
512*30880Sbostic char buf[80];
513*30880Sbostic char mode;
514*30880Sbostic char filename[18];
515*30880Sbostic FILE *file;
516*30880Sbostic int extract;
517*30880Sbostic char *ibuf;
518*30880Sbostic char *ibufstart;
519*30880Sbostic char *endibuf;
520*30880Sbostic int i;
521*30880Sbostic int size;
522*30880Sbostic int numblock = 0 ;
523*30880Sbostic int numchar = 0 ;
524*30880Sbostic int numline = 0 ;
525*30880Sbostic int argnum;
526*30880Sbostic int ok;
527*30880Sbostic int blocksize;
528*30880Sbostic int recordsize;
529*30880Sbostic int writeblock;
530*30880Sbostic 
531*30880Sbostic 	if(!(read(tape,buf,80))) return(1); /* no hdr record, so second eof */
532*30880Sbostic 	sscanf(buf,"HDR1%17s",filename);
533*30880Sbostic 	read(tape,buf,80);
534*30880Sbostic 	sscanf(buf,"HDR2%c%5d%5d",&mode,&blocksize,&recordsize);
535*30880Sbostic 	blocksize = blocksize>recordsize?blocksize:recordsize;
536*30880Sbostic 	skipfile(tape); /* throw away rest of header(s) - not interesting */
537*30880Sbostic 	ibufstart=ibuf=malloc(blocksize+10);
538*30880Sbostic 	endibuf=ibufstart+blocksize;
539*30880Sbostic 	extract=0;
540*30880Sbostic 	if(tflag || xflag) {
541*30880Sbostic 		ok=0;
542*30880Sbostic 		if(!argc) {
543*30880Sbostic 			ok=1;
544*30880Sbostic 		} else for(argnum=0;argnum<argc;argnum++) {
545*30880Sbostic 			casefix(argv[argnum]);
546*30880Sbostic 			if(!strcmp(filename,argv[argnum])) {
547*30880Sbostic 				ok=1;
548*30880Sbostic 				break;
549*30880Sbostic 			}
550*30880Sbostic 		}
551*30880Sbostic 		if(mode == 'D') {
552*30880Sbostic 			if(xflag && ok) {
553*30880Sbostic 				file = fopen(filename,"w");
554*30880Sbostic 				if(file == NULL) {
555*30880Sbostic 					perror(filename);
556*30880Sbostic 				} else {
557*30880Sbostic 					extract = 1;
558*30880Sbostic 				}
559*30880Sbostic 			}
560*30880Sbostic 			while(read(tape,ibufstart,blocksize)) {
561*30880Sbostic 				numblock++;
562*30880Sbostic 				ibuf = ibufstart;
563*30880Sbostic 				while(strncmp("^^^^",ibuf,4)) {
564*30880Sbostic 					size = getsize(ibuf);
565*30880Sbostic 					if(extract) {
566*30880Sbostic 						fwrite(ibuf+4,sizeof(char),size-4,file);
567*30880Sbostic 						fwrite("\n",1,1,file);
568*30880Sbostic 					}
569*30880Sbostic 					ibuf += (size);
570*30880Sbostic 					numline++;
571*30880Sbostic 					numchar += (size-4);
572*30880Sbostic 					if(ibuf > endibuf+1) {
573*30880Sbostic 						fprintf(stderr,"error:  bad tape records(s) - file may be corrupted\n");
574*30880Sbostic 						break;
575*30880Sbostic 					}
576*30880Sbostic 					if(ibuf>endibuf-4) break;
577*30880Sbostic 				}
578*30880Sbostic 			}
579*30880Sbostic 			if(extract) {
580*30880Sbostic 				fclose(file);
581*30880Sbostic 			}
582*30880Sbostic 		} else if (mode == 'F') {
583*30880Sbostic 			if(xflag && ok) {
584*30880Sbostic 				file = fopen(filename,"w");
585*30880Sbostic 				if(file == NULL) {
586*30880Sbostic 					perror(filename);
587*30880Sbostic 				} else {
588*30880Sbostic 					extract = 1;
589*30880Sbostic 				}
590*30880Sbostic 			}
591*30880Sbostic 			while(read(tape,ibufstart,blocksize)) {
592*30880Sbostic 				numblock++;
593*30880Sbostic 				ibuf = ibufstart;
594*30880Sbostic 				while(ibuf+recordsize <= endibuf) {
595*30880Sbostic 					if(extract) {
596*30880Sbostic 						fwrite(ibuf,sizeof(char),recordsize,file);
597*30880Sbostic 						fwrite("\n",1,1,file);
598*30880Sbostic 					}
599*30880Sbostic 					ibuf += recordsize;
600*30880Sbostic 					numline++;
601*30880Sbostic 					numchar += recordsize;
602*30880Sbostic 				}
603*30880Sbostic 			}
604*30880Sbostic 			if(extract) {
605*30880Sbostic 				fclose(file);
606*30880Sbostic 			}
607*30880Sbostic 		} else {
608*30880Sbostic 			fprintf(stderr,"unknown record mode (%c) - file %s skipped\n",
609*30880Sbostic 					mode,filename);
610*30880Sbostic 			skipfile(tape);	/* throw away actual file */
611*30880Sbostic 		}
612*30880Sbostic 	} else {
613*30880Sbostic 		/* not interested in contents of file, so move fast */
614*30880Sbostic 		skipfile(tape);
615*30880Sbostic 	}
616*30880Sbostic 	skipfile(tape); /* throw away eof stuff - not interesting */
617*30880Sbostic 	totalreadchars += numchar;
618*30880Sbostic 	totalreadlines += numline;
619*30880Sbostic 	totalreadblocks += numblock;
620*30880Sbostic 	totalreadfiles ++;
621*30880Sbostic 	if(xflag && vflag && ok) {
622*30880Sbostic 		fprintf(stdout,"x - %s:  %d lines (%d chars) in %d tape blocks\n",
623*30880Sbostic 				filename,numline,numchar,numblock);
624*30880Sbostic 	} else if(tflag && ok) {
625*30880Sbostic 		fprintf(stdout,"t - %s:  %d lines (%d chars) in %d tape blocks\n",
626*30880Sbostic 				filename,numline,numchar,numblock);
627*30880Sbostic 	}
628*30880Sbostic 	free(ibufstart);
629*30880Sbostic 	return(0);
630*30880Sbostic }
631*30880Sbostic 
632*30880Sbostic filecheck(file,name)
633*30880Sbostic 	int *file;
634*30880Sbostic 	char *name;
635*30880Sbostic 
636*30880Sbostic {
637*30880Sbostic 
638*30880Sbostic 	struct stat buf;
639*30880Sbostic 	struct exec sample;
640*30880Sbostic 
641*30880Sbostic 	stat(name,&buf);
642*30880Sbostic 	if ((buf.st_mode & S_IFDIR)==S_IFDIR) {
643*30880Sbostic 		fprintf(stderr,"%s: directory - skipped\n",name);
644*30880Sbostic 		return(1);
645*30880Sbostic 	}
646*30880Sbostic 	if ((buf.st_mode & S_IFCHR)==S_IFCHR) {
647*30880Sbostic 		fprintf(stderr,"%s: character device - skipped\n",name);
648*30880Sbostic 		return(1);
649*30880Sbostic 	}
650*30880Sbostic 	if ((buf.st_mode & S_IFBLK)==S_IFBLK) {
651*30880Sbostic 		fprintf(stderr,"%s: block device - skipped\n",name);
652*30880Sbostic 		return(1);
653*30880Sbostic 	}
654*30880Sbostic 	if ((buf.st_mode & S_IFLNK)==S_IFLNK) {
655*30880Sbostic 		fprintf(stderr,"%s: symbolic link - skipped\n",name);
656*30880Sbostic 		return(1);
657*30880Sbostic 	}
658*30880Sbostic 	if ((buf.st_mode & S_IFSOCK)==S_IFSOCK) {
659*30880Sbostic 		fprintf(stderr,"%s: socket - skipped\n",name);
660*30880Sbostic 		return(1);
661*30880Sbostic 	}
662*30880Sbostic 	*file = open(name,O_RDONLY,NULL);
663*30880Sbostic 	if(*file <0) {
664*30880Sbostic 		perror(name);
665*30880Sbostic 		return(1);
666*30880Sbostic 	}
667*30880Sbostic 	if(read(*file,&sample,sizeof(struct exec))>= sizeof(struct exec)) {
668*30880Sbostic 		if(!(N_BADMAG(sample))) {
669*30880Sbostic 			/* executable */
670*30880Sbostic 			/* the format requires either fixed blocked records,
671*30880Sbostic 			 * or variable format records with each record remaining
672*30880Sbostic 			 * entirely within a tape block - this limits the
673*30880Sbostic 			 * distance between \n's to 2044 bytes, something
674*30880Sbostic 			 * which is VERY rarely true of executables, so
675*30880Sbostic 			 * we don't even try with them....
676*30880Sbostic 			 */
677*30880Sbostic 			close(*file);
678*30880Sbostic 			fprintf(stderr,"%s: executable - skipped\n",name);
679*30880Sbostic 			return(1);
680*30880Sbostic 		}
681*30880Sbostic 	}
682*30880Sbostic 	/* either couldn't read sizeof(struct exec) or wasn't executable */
683*30880Sbostic 	/* so we assume it is a reasonable file until proven otherwise */
684*30880Sbostic 	lseek(*file,0l,0);
685*30880Sbostic 	return(0);
686*30880Sbostic }
687