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