Make LCALL like LJMP and avoid segmentation faults parsing segments (!).
[unix-history] / usr / src / contrib / ansi / ansitape.c
index 3f2e850..eac0268 100644 (file)
@@ -9,12 +9,15 @@
 #include <ctype.h>
 
 char *malloc();
 #include <ctype.h>
 
 char *malloc();
+static void rewind();
+long lseek();
 int wflag;
 int xflag;
 int tflag;
 int cflag;
 int vflag;
 int dflag;
 int wflag;
 int xflag;
 int tflag;
 int cflag;
 int vflag;
 int dflag;
+int fflag;
 int totalreadfiles = 0 ;
 int totalreadblocks = 0 ;
 int totalreadlines = 0 ;
 int totalreadfiles = 0 ;
 int totalreadblocks = 0 ;
 int totalreadlines = 0 ;
@@ -29,7 +32,7 @@ main(argc,argv)
        char *argv[];
 {
        struct tm *tm;
        char *argv[];
 {
        struct tm *tm;
-       long timetemp;
+       long timetemp,time();
        int year;
        int day;
        char *tapename;
        int year;
        int day;
        char *tapename;
@@ -48,10 +51,11 @@ main(argc,argv)
        int tmp;
        char blockchar;
        int blocksize=2048;
        int tmp;
        char blockchar;
        int blocksize=2048;
+       int recordsize=1;
 
        char *key;
 
 
        char *key;
 
-       timetemp = time(0);
+       timetemp = time((long *)NULL);
        tm = localtime(&timetemp);
        year = tm->tm_year;
        day = tm->tm_yday;
        tm = localtime(&timetemp);
        year = tm->tm_year;
        day = tm->tm_yday;
@@ -100,6 +104,42 @@ main(argc,argv)
                        argc--;
                        break;
 
                        argc--;
                        break;
 
+               case 'F':
+                       if(*argv == NULL) {
+                               fprintf(stderr, 
+               "ansitape: 'F' options requires recordsize and blocksize specifiers.\n"
+                                               );
+                               usage();
+                       }
+                       tmp = sscanf(*argv++," %d%c ",&recordsize,&blockchar);
+                       argc--;
+                       if(tmp<1) { 
+                               fprintf(stderr,"illegal recordsize: recordsize set to 80\n");
+                               recordsize=80;
+                       } else if(tmp>1) {
+                               if(blockchar == 'b') recordsize *= 512;
+                               if(blockchar == 'k') recordsize *= 1024;
+                       }
+
+                       if (*argv == NULL) {
+                               fprintf(stderr,
+                       "ansitape: 'F' option requires blocksize specifier \n");
+                               usage();
+                       }
+                       tmp = sscanf(*argv++," %d%c ",&blocksize,&blockchar);
+                       argc--;
+                       if(tmp<1) { 
+                               fprintf(stderr,"illegal blocksize: blocksize set to 2048\n");
+                               blocksize=2048;
+                       } else if(tmp>1) {
+                               if(blockchar == 'b') blocksize *= 512;
+                               if(blockchar == 'k') blocksize *= 1024;
+                       }
+                       if(blocksize <18) blocksize=18;
+                       if(blocksize >62*1024) blocksize=62*1024;
+                       fflag++;
+                       break;
+
                case 'b':
                        if (*argv == NULL) {
                                fprintf(stderr,
                case 'b':
                        if (*argv == NULL) {
                                fprintf(stderr,
@@ -155,7 +195,7 @@ main(argc,argv)
        tape = open(device,wflag?O_RDWR:O_RDONLY,NULL);
        if(tape<0) {
                perror(device);
        tape = open(device,wflag?O_RDWR:O_RDONLY,NULL);
        if(tape<0) {
                perror(device);
-               printf(stderr,"tape not accessable - check if drive online and write ring present\n");
+               fprintf(stderr,"tape not accessable - check if drive online and write ring present\n");
                exit(1);
        }
        rewind(tape);
                exit(1);
        }
        rewind(tape);
@@ -192,7 +232,8 @@ main(argc,argv)
                                if(count==1) strcpy(vmsname,unixname);
                                casefix(vmsname);
                                if(filecheck(&file,unixname)) continue;
                                if(count==1) strcpy(vmsname,unixname);
                                casefix(vmsname);
                                if(filecheck(&file,unixname)) continue;
-                               writefile(tape,file,vmsname,tapename,filenum,year,day,blocksize);
+                               writefile(tape,file,vmsname,tapename,filenum,year,day,blocksize,
+                                               recordsize);
                                filenum++;
                                close(file);
                        }
                                filenum++;
                                close(file);
                        }
@@ -201,7 +242,8 @@ main(argc,argv)
                                filename = argv[argnum];
                                if(filecheck(&file,filename)) continue;
                                casefix(filename);
                                filename = argv[argnum];
                                if(filecheck(&file,filename)) continue;
                                casefix(filename);
-                               writefile(tape,file,filename,tapename,filenum,year,day,blocksize);
+                               writefile(tape,file,filename,tapename,filenum,year,day,
+                                               blocksize,recordsize);
                                filenum++;
                                close(file);
                        }
                                filenum++;
                                close(file);
                        }
@@ -221,14 +263,15 @@ main(argc,argv)
                fprintf(stdout," wrote  %d files in %d blocks (%d lines, %d chars)\n",
                        totalwritefiles,totalwriteblocks,totalwritelines,totalwritechars);
        }
                fprintf(stdout," wrote  %d files in %d blocks (%d lines, %d chars)\n",
                        totalwritefiles,totalwriteblocks,totalwritelines,totalwritechars);
        }
+       return(0);
 }
 usage() {
        fprintf(stderr,
                        "ansitape: usage: ansitape -{rxtc}[flnvb] [filename] [label] [filename] [blocksize] [files]\n");
 }
 usage() {
        fprintf(stderr,
                        "ansitape: usage: ansitape -{rxtc}[flnvb] [filename] [label] [filename] [blocksize] [files]\n");
-       exit();
+       exit(1);
 }
 
 }
 
-writefile(tape,file,filename,tapename,filenum,year,day,blocksize)
+writefile(tape,file,filename,tapename,filenum,year,day,blocksize,recordsize)
        int tape;
        int file;
        char *filename;
        int tape;
        int file;
        char *filename;
@@ -237,34 +280,35 @@ writefile(tape,file,filename,tapename,filenum,year,day,blocksize)
        int year;
        int day;
        int blocksize;
        int year;
        int day;
        int blocksize;
+       int recordsize;
 
 {
        int blocks;
        writehdr1(tape,filename,tapename,filenum,year,day);
 
 {
        int blocks;
        writehdr1(tape,filename,tapename,filenum,year,day);
-       writehdr2(tape,blocksize);
+       writehdr2(tape,blocksize,recordsize);
        writehdr3(tape);
        writetm(tape);
        writehdr3(tape);
        writetm(tape);
-       writedata(tape,file,filename,&blocks,blocksize);
+       writedata(tape,file,filename,&blocks,blocksize,recordsize);
        writetm(tape);
        writeeof1(tape,filename,tapename,filenum,year,day,blocks);
        writetm(tape);
        writeeof1(tape,filename,tapename,filenum,year,day,blocks);
-       writeeof2(tape);
+       writeeof2(tape,blocksize,recordsize);
        writeeof3(tape);
        writetm(tape);
        totalwritefiles++;
 }
 
        writeeof3(tape);
        writetm(tape);
        totalwritefiles++;
 }
 
-writedata(tape,file,filename,blocks,blocksize)
+writedata(tape,file,filename,blocks,blocksize,recsize)
        int tape;
        int file;
        char *filename;
        int *blocks;
        int blocksize;
        int tape;
        int file;
        char *filename;
        int *blocks;
        int blocksize;
+       int recsize;
 {
 char *ibuf;
 char *ibufstart;
 char *obuf;
 char *obufstart;
 {
 char *ibuf;
 char *ibufstart;
 char *obuf;
 char *obufstart;
-char sizebuf[5];
 char *endibuf;
 char *endobuf;
 int got;
 char *endibuf;
 char *endobuf;
 int got;
@@ -275,35 +319,72 @@ int numline = 0 ;
 int numblock = 0;
 int success;
 
 int numblock = 0;
 int success;
 
-       ibufstart = ibuf = malloc(blocksize<4096?8200:(2*blocksize+10));
-       obufstart = obuf = malloc(blocksize+10);
+       ibufstart = ibuf = malloc((unsigned)(blocksize<4096?8200:(2*blocksize+10)));
+       obufstart = obuf = malloc((unsigned)(blocksize+10));
        endobuf = obuf + blocksize;
        endibuf = ibuf;
 
 
        i=0;
        endobuf = obuf + blocksize;
        endibuf = ibuf;
 
 
        i=0;
-       while(1) {
-               if(ibuf+i>=endibuf) {   /* end of input buffer */
-                       strncpy(ibufstart,ibuf,endibuf-ibuf); /* copy leftover to start */
-                       ibuf = ibufstart+(endibuf-ibuf);        /* point to end of valid data */
-                       got = read(file,ibuf,blocksize<4096?4096:2*blocksize);  /* read in a chunk */
-                       endibuf = ibuf + got;
-                       ibuf = ibufstart;       /* point to beginning of data */
-                       if(got == 0) { /* end of input */
-                               if(ibuf==ibufstart){ /* no leftovers */
-                                       break; /* done */
-                               } else {
-                                       ibuf[i]='\n'; /* fake extra newline */
+       if (!fflag) {
+               while(1) {
+                       if(ibuf+i>=endibuf) {   /* end of input buffer */
+                               strncpy(ibufstart,ibuf,endibuf-ibuf); /* copy leftover to start */
+                               ibuf = ibufstart+(endibuf-ibuf);        /* point to end of valid data */
+                               got = read(file,ibuf,blocksize<4096?4096:2*blocksize);  /* read in a chunk */
+                               endibuf = ibuf + got;
+                               ibuf = ibufstart;       /* point to beginning of data */
+                               if(got == 0) { /* end of input */
+                                       if(ibuf==ibufstart){ /* no leftovers */
+                                               break; /* done */
+                                       } else {
+                                               ibuf[i]='\n'; /* fake extra newline */
+                                       }
                                }
                        }
                                }
                        }
-               }
 
 
-               if(obuf+i+4 > endobuf) {  /* end of output buffer */
-                       if(i>blocksize-4) { 
-                               printf("record exceeds blocksize - file truncated\n");
-                               break;
+                       if(obuf+i+4 > endobuf) {  /* end of output buffer */
+                               if(i>blocksize-4) { 
+                                       printf("record exceeds blocksize - file truncated\n");
+                                       break;
+                               }
+                               /* filled up output record - have to fill,output,restart*/
+                               for(j=obuf;j<endobuf;j++) {
+                                       *j = '^';
+                               }
+                               success = write(tape,obufstart,blocksize);
+                               if(success != blocksize) {
+                                       perror("tape");
+                                       fprintf(stderr," hard write error:  write aborted\n");
+                                       rewind(tape);
+                                       exit(1);
+                               }
+                               obuf=obufstart;
+                               numchar -= i;
+                               i=0;
+                               numblock++;
+                               continue;
+                       }
+
+                       if(ibuf[i] == '\n') { /* end of line */
+                               obuf[0] = ((i+4)/1000) + '0';
+                               obuf[1] = (((i+4)/100)%10) + '0';
+                               obuf[2] = (((i+4)/10)%10) + '0';
+                               obuf[3] = (((i+4)/1)%10) + '0';
+                               obuf += (4+i); /* size + strlen */
+                               ibuf += (1+i); /* newline + strlen */
+                               i=0;
+                               numline++;
+                               continue; /* back to the top */
                        }
                        }
-                       /* filled up output record - have to fill,output,restart*/
+
+                       obuf[i+4]=ibuf[i];
+                       numchar++;
+                       i++;
+
+               }
+               /* exited - write last record and go for lunch */
+               if(obuf != obufstart) {
                        for(j=obuf;j<endobuf;j++) {
                                *j = '^';
                        }
                        for(j=obuf;j<endobuf;j++) {
                                *j = '^';
                        }
@@ -314,45 +395,51 @@ int success;
                                rewind(tape);
                                exit(1);
                        }
                                rewind(tape);
                                exit(1);
                        }
-                       obuf=obufstart;
-                       numchar -= i;
-                       i=0;
                        numblock++;
                        numblock++;
-                       continue;
                }
                }
-
-               if(ibuf[i] == '\n') { /* end of line */
-                       /*sprintf(sizebuf,"%4.4d",i+4); /* make length string */
-                       /*strncpy(obuf,sizebuf,4); /* put in length field */
-                       obuf[0] = ((i+4)/1000) + '0';
-                       obuf[1] = (((i+4)/100)%10) + '0';
-                       obuf[2] = (((i+4)/10)%10) + '0';
-                       obuf[3] = (((i+4)/1)%10) + '0';
-                       obuf += (4+i); /* size + strlen */
-                       ibuf += (1+i); /* newline + strlen */
-                       i=0;
+        } else {
+               fflush(stdout);
+               while(1) {
+                       /* writing an 'F' format tape */
+                       got = read(file,ibuf,recsize+1);
+                       if(got == 0) {
+                               /* end of input */
+                               if(obuf<=obufstart) {
+                                       break; /* done */
+                               } else {
+                                       /* no more data, so force the record out */
+                                       recsize = blocksize+1;
+                               }
+                       } else if(got != recsize+1) {
+                               printf("short read: filled\n");
+                       } else if( *(ibuf+recsize) != '\n') {
+                               printf("corrupted record - write aborted\b");
+                               rewind(tape);
+                               exit(1);
+                       }
+                       if(obuf+recsize >endobuf) {
+                               /*would overflow output buffer, so fill up old buffer */
+                               for(j=obuf;j<endobuf;j++) {
+                                       *j = '^';
+                               }
+                               /* and write it */
+                               success = write(tape,obufstart,blocksize);
+                               if(success != blocksize) {
+                                       perror("tape");
+                                       fprintf(stderr," hard write error:   write aborted\n");
+                                       rewind(tape);
+                                       exit(1);
+                               }
+                               obuf=obufstart;
+                               numblock++;
+                       }
+                       bcopy(ibuf,obuf,recsize);
+                       obuf+=got-1;
                        numline++;
                        numline++;
-                       continue; /* back to the top */
+                       numchar += recsize;
                }
                }
-
-               obuf[i+4]=ibuf[i];
-               numchar++;
-               i++;
-
-       }
-       /* exited - write last record and go for lunch */
-       if(obuf != obufstart) {
-               for(j=obuf;j<endobuf;j++) {
-                       *j = '^';
-               }
-               success = write(tape,obufstart,blocksize);
-               if(success != blocksize) {
-                       perror("tape");
-                       fprintf(stderr," hard write error:  write aborted\n");
-                       rewind(tape);
-                       exit(1);
-               }
-               numblock++;
+               numchar -= recsize;
+               numline--;
        }
        free(ibufstart);
        free(obufstart);
        }
        free(ibufstart);
        free(obufstart);
@@ -375,7 +462,8 @@ writetm(tape)
        ioctl(tape,MTIOCTOP,&mtop);
 }
 
        ioctl(tape,MTIOCTOP,&mtop);
 }
 
-rewind(tape)
+void
+static rewind(tape)
        int tape;
 {
        struct mtop mtop;
        int tape;
 {
        struct mtop mtop;
@@ -433,21 +521,25 @@ writeeof1(tape,filename,tapename,filenum,year,day,blocks)
        write(tape,buf,80);
 }
 
        write(tape,buf,80);
 }
 
-writehdr2(tape,blocksize)
+writehdr2(tape,blocksize,recordsize)
        int tape;
        int blocksize;
        int tape;
        int blocksize;
+       int recordsize;
 {
        char buf[81];
 {
        char buf[81];
-       sprintf(buf, "HDR2D%5.5d%5.5d%35.35s00%28.28s",blocksize,blocksize," "," ");
+       sprintf(buf,"HDR2%c%5.5d%5.5d%35.35s00%28.28s",fflag?'F':'D',
+                       blocksize,recordsize," "," ");
        write(tape,buf,80);
 }
 
        write(tape,buf,80);
 }
 
-writeeof2(tape,blocksize)
+writeeof2(tape,blocksize,recordsize)
        int tape;
        int blocksize;
        int tape;
        int blocksize;
+       int recordsize;
 {
        char buf[81];
 {
        char buf[81];
-       sprintf(buf, "EOF2D%5.5d%5.5d%35.35s00%28.28s",blocksize,blocksize," "," ");
+       sprintf(buf,"EOF2%c%5.5d%5.5d%35.35s00%28.28s",fflag?'F':'D',
+                       blocksize,recordsize," "," ");
        write(tape,buf,80);
 }
 
        write(tape,buf,80);
 }
 
@@ -472,7 +564,7 @@ writevol(tapename,tape)
        char *tapename;
 {
        char buf[81];
        char *tapename;
 {
        char buf[81];
-       sprintf(buf,"VOL1%-6.6s %26.26sD%%C%10.10s1%28.28s3",tapename," "," "," ");
+       sprintf(buf,"VOL1%-6.6s %26.26sD%cC%10.10s1%28.28s3",tapename," ",'%'," "," ");
        write(tape,buf,80);
        if(vflag) {
                fprintf(stdout," tape labeled %-6.6s\n",tapename);
        write(tape,buf,80);
        if(vflag) {
                fprintf(stdout," tape labeled %-6.6s\n",tapename);
@@ -502,33 +594,6 @@ casefix(string)
     }
 }
 
     }
 }
 
-static
-getsize(a)
-       register char *a;
-{
-       register int    i;
-       int             answer;
-
-       answer = 0;
-       for (i = 0; i < 4; ++i) {
-               answer *= 10;
-               switch (a[i]) {
-                       default:        return -1;
-                       case '0':       break;
-                       case '1':       answer += 1; break;
-                       case '2':       answer += 2; break;
-                       case '3':       answer += 3; break;
-                       case '4':       answer += 4; break;
-                       case '5':       answer += 5; break;
-                       case '6':       answer += 6; break;
-                       case '7':       answer += 7; break;
-                       case '8':       answer += 8; break;
-                       case '9':       answer += 9; break;
-               }
-       }
-       return(answer);
-}
-
 int
 readfile(tape,argc,argv)
        int tape;
 int
 readfile(tape,argc,argv)
        int tape;
@@ -543,7 +608,7 @@ int extract;
 char *ibuf;
 char *ibufstart;
 char *endibuf;
 char *ibuf;
 char *ibufstart;
 char *endibuf;
-int i;
+char *fixpoint;
 int size;
 int numblock = 0 ;
 int numchar = 0 ;
 int size;
 int numblock = 0 ;
 int numchar = 0 ;
@@ -552,7 +617,6 @@ int argnum;
 int ok;
 int blocksize;
 int recordsize;
 int ok;
 int blocksize;
 int recordsize;
-int writeblock;
 
        if(!(read(tape,buf,80))) return(1); /* no hdr record, so second eof */
        sscanf(buf,"HDR1%17s",filename);
 
        if(!(read(tape,buf,80))) return(1); /* no hdr record, so second eof */
        sscanf(buf,"HDR1%17s",filename);
@@ -560,7 +624,7 @@ int writeblock;
        sscanf(buf,"HDR2%c%5d%5d",&mode,&blocksize,&recordsize);
        blocksize = blocksize>recordsize?blocksize:recordsize;
        skipfile(tape); /* throw away rest of header(s) - not interesting */
        sscanf(buf,"HDR2%c%5d%5d",&mode,&blocksize,&recordsize);
        blocksize = blocksize>recordsize?blocksize:recordsize;
        skipfile(tape); /* throw away rest of header(s) - not interesting */
-       ibufstart=ibuf=malloc(blocksize+10);
+       ibufstart=ibuf=malloc((unsigned)(blocksize+10));
        endibuf=ibufstart+blocksize;
        extract=0;
        if(tflag || xflag) {
        endibuf=ibufstart+blocksize;
        extract=0;
        if(tflag || xflag) {
@@ -583,16 +647,28 @@ int writeblock;
                                        extract = 1;
                                }
                        }
                                        extract = 1;
                                }
                        }
-                       while(read(tape,ibufstart,blocksize)) {
+                       while(size=read(tape,ibufstart,blocksize)) {
+                               if(size != blocksize) {
+                                       /*
+                                        * somebody's brain damaged program leaves
+                                        * short blocks on the tape - fill them up to size
+                                        * (this is work THEY should have done before writing
+                                        * their undersized blocks)
+                                        */
+                                       for(fixpoint=ibufstart+size;fixpoint<endibuf;fixpoint++) {
+                                               *fixpoint='^';
+                                       }
+                               }
                                numblock++;
                                ibuf = ibufstart;
                                while(strncmp("^^^^",ibuf,4)) {
                                numblock++;
                                ibuf = ibufstart;
                                while(strncmp("^^^^",ibuf,4)) {
-                                       size = getsize(ibuf);
-                                       if(size <= 0) {
-                                               (void)fflush(stdout);
-                                               (void)fprintf(stderr,"error: bad tape record(s) in file %s - file may be truncated/corrupted.\n", filename);
+#define getsize(a) ((a[0]-'0')*1000)+((a[1]-'0')*100)+((a[2]-'0')*10)+(a[3]-'0')
+#define bad(a) (!(isdigit(ibuf[a])))
+                                       if(bad(0) || bad(1) || bad(2) || bad(3)) {
+                                               fprintf(stderr, "error:  bad record length field - file may be corrupted, skipping\n");
                                                break;
                                        }
                                                break;
                                        }
+                                       size = getsize(ibuf);
                                        if(extract) {
                                                fwrite(ibuf+4,sizeof(char),size-4,file);
                                                fwrite("\n",1,1,file);
                                        if(extract) {
                                                fwrite(ibuf+4,sizeof(char),size-4,file);
                                                fwrite("\n",1,1,file);