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