home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / tapeutils.zip / tuubad.c < prev    next >
C/C++ Source or Header  |  1988-08-16  |  34KB  |  1,646 lines

  1. /*
  2. >From zehntel!ihnp4!ixn5c!inuxc!pur-ee!uiucdcs!uiucuxc!root Sat Jul  2 04:31:32 1983
  3. Subject: Ansitar.c - (nf)
  4. Newsgroups: net.sources
  5.  
  6. #N:uiucuxc:12500005:000:19678
  7. uiucuxc!root    Jul  1 23:55:00 1983
  8. *
  9. * 10/28/83 DRB: new option 'D': read variable length records (D format)
  10. * 10/29/83 FGH: 1. wildcard ability added to filenames.
  11. *         2. when output filename isn't valid for Unix (as it's perhaps
  12. *           taken from a foreign tape), this program now just skips
  13. *           that file rather than exiting the whole job.
  14. * 10/30/83 FGH: 1. some problems with varunblock's handling of end of record.
  15. *           still must use 'D' option with 'b' such that b's argument
  16. *           exceeds the tape's physical record size (2048 in my case)
  17. *        2. changed varunblock/doxtract to correct the byte count.
  18. *
  19. * 10/31/83 DRB:
  20. *    new option P - create/read files in "pip" (FILES-11) counted format.
  21. *    handle tape read error
  22. * From zehntel!tektronix!ucbcad!ucbvax!decvax!microsoft!uw-beaver!cornell!vax135!floyd!harpo!utah-cs!utah-gr!thomas Tue Aug  2 21:27:08 1983
  23. *    (=Spencer)   (#ifdef PIP)
  24. # MACKAY@WASHINGTON.ARPA
  25. * 04/24/84 PAM:
  26. *        1. Upgrade to ANSI X3.27 System level 3.
  27. *           Program now reads and writes HDR2 label 
  28. *           for deblocking info.
  29. *        2. When reading, sets blocksize only if D-type, blocksize
  30. *           and linesize (aka record-length) if F-type.
  31. *           Neither D nor b/B need be specified on the
  32. *           command line if tape has valid HDR2 labels.
  33. *        3. Full HDR2 info provided in "verbose mode."
  34. *           (Ought to check matching EOF2 and print string
  35. *           for HDR3-9/EOF3-9 labels)
  36. *        4. If D is used as an option in writing, a default
  37. *           blocksize of 2048 is chosen, based on the ISO
  38. *           recommendation for maximum blocksize.  Line length
  39. *           is limited to 255 bytes, which seems a reasonable
  40. *           maximum.
  41. *
  42. * 8/30/84    eac (cucca) Set default blocksize to 8192.  Ignore ISO
  43. *        recommendation for 'D' tapes.
  44. */
  45.  
  46. #define CUCCA
  47. #define VARIAN
  48. #define PIP 
  49.  
  50. #ifdef VARIAN
  51. #define DEBUG      0    /* set to nonzero to debug new Varian code */
  52. #define DBG       if(DEBUG) fprintf(stderr,
  53. #define WILDCARD '*'
  54. #endif VARIAN
  55.  
  56. #include <stdio.h>
  57. #include <ctype.h>
  58. #include <sys/time.h>
  59. #include <pwd.h>
  60. #include <sys/types.h>
  61. #include <sys/ioctl.h>
  62. #include <sys/mtio.h>
  63.  
  64. /* ansitar -- archiver for ansi-format labelled tapes
  65.  *
  66.  * ansitar [crxtvbl] [blocksize] [labelsize] file ...
  67.  *
  68.  * The options are similar to tar:
  69.  *    c - create a tape
  70.  *    r - replace (update) a tape
  71.  *    x - extract files
  72.  *    t - print table of contents
  73.  *    v - set verbose mode: for crx, print names; for t print labels
  74.  *    0-9 - select drive 0-9
  75.  *    b - use next argument as a block size
  76.  *    B - use next argument as tape block size, and
  77.  *        following argument as line size (for blocking/unblocking)
  78.  *    l - use next arg as a label size
  79.  *    U - select upper(out)/lower(in) case translation of names
  80.  *    V - use next argument as a VSN
  81.  *    R - use RT11 label and name conventions (UGH!)
  82.  *    S - use RSTS conventions (==RT11 except 80-byte labels)
  83.  *    P - create/read files in "pip" (FILES-11) counted format.
  84.  *    D - create/read files with variable length records (D format)
  85.  *
  86.  * When extracting from tape to UNIX, the filename may contain * to 
  87.  * indicate a wild card; however, the asterisk should be enclosed 
  88.  * in quotes, however, to prevent the shell from interpreting it.  
  89.  *
  90.  * Examples of usage:
  91.  *    ansitar tv            Verbose table of contents
  92.  *    ansitar xvDUb 2000 file1 file2  Extract file1 and file2 from
  93.  *                    tape with 2000 bytes/block
  94.  *                    and variable length records
  95.  *
  96.  * BUGS:
  97.  *
  98.  * Warning: The routines skipfile and backspace use nonstandard
  99.  * (4.1BSD) ioctl calls!
  100.  */
  101.  
  102. #define    Skiparg()    argc--; argv++
  103. #define    MAXLINE    256
  104. #define    TRUE    1
  105. #define    FALSE    0
  106. #define    READ    0
  107. #define    READWRITE    2
  108. #define ISOBLOCK    2048
  109.  
  110. /* field sizes */
  111. #define    LABID    3
  112. #define    SERIAL    6
  113. #define    OWNER    14
  114. #define    FILEID    17
  115. #define    SETID    6
  116. #define    SECNO    4
  117. #define    SEQNO    4
  118. #define    GENNO    4
  119. #define    GENVSNO    2
  120. #define    CRDATE    6
  121. #define    EXDATE    6
  122. #define    BLOCKS    6
  123. #define    SYSTEM    13
  124. #define    BLKMAX    5
  125. #define    RECMAX    5
  126. #define    BYTOFFS    2
  127. #define DBYTES    4
  128.  
  129. /* pad fields (reserved for future use) */
  130. #define    VRES1    20
  131. #define    VRES2    6
  132. #define    VRES3    28
  133. #define    HRES1    7
  134. #define    H2RES1    35
  135. #define    H2RES2    28
  136.  
  137. /* Volume header label */
  138. struct vol {
  139.     char    v_labid[LABID];        /* label identifier "VOL" */
  140.     char    v_labno;        /* label number */
  141.     char    v_serial[SERIAL];    /* volume serial number */
  142.     char    v_access;        /* accessibility */
  143.     char    v_res1[VRES1];        /* reserved for future use */
  144.     char    v_res2[VRES2];        /* reserved for future use */
  145.     char    v_owner[OWNER];        /* owner identifier */
  146.     char    v_res3[VRES3];        /* reserved for future use */
  147.     char    v_stdlabel;        /* standard label flag */
  148.     };
  149.  
  150.  
  151.  
  152.  
  153. /* file header/eof label */
  154. struct hdr {
  155.     char    h_labid[LABID];        /* label identifier: "HDR" or "EOF" */
  156.     char    h_labno;        /* label number */
  157.     char    h_fileid[FILEID];    /* file identifier */
  158.     char    h_setid[SETID];        /* file set identifier */
  159.     char    h_secno[SECNO];        /* file section number */
  160.     char    h_seqno[SEQNO];        /* file sequence number */
  161.     char    h_genno[GENNO];        /* generation number */
  162.     char    h_genvsno[GENVSNO];    /* generation vsn number */
  163.     char    h_crdate[CRDATE];    /* creation date */
  164.     char    h_exdate[EXDATE];    /* expiration date */
  165.     char    h_access;        /* accessibility */
  166.     char    h_blocks[BLOCKS];    /* block count */
  167.     char    h_system[SYSTEM];    /* system code */
  168.     char    h_x1[7];        /* reserved */
  169.     };
  170.  
  171. /* deblocking hdr2/eof2 label */
  172. struct hd2 {
  173.     char    h2_labid[LABID];    /* label identifier: "HDR" or "EOF" */
  174.     char    h2_labno;        /* label number "2" */
  175.     char    h2_datatype;        /* type identifier "D" or "F" */
  176.     char    h2_blkmax[BLKMAX];    /* maximum block size in bytes */
  177.     char    h2_recmax[RECMAX];    /* maximum record size in bytes */
  178.     char    h2_x1[H2RES1];        /* reserved */
  179.     char    h2_bytoffs[BYTOFFS];    /* extra stuff at start of block */
  180.     char    h2_x2[H2RES2];        /* reserved */
  181.     };
  182.  
  183.  
  184.  
  185. struct vol vol1;
  186. struct hdr hdr1, eof1;
  187. struct hd2 hdr2, eof2;
  188.  
  189. char *tapefile = "/dev/rmt8";
  190. char *buffer, *linebuffer, *malloc(), *realloc(), *index();
  191. char **filetab;
  192. #ifdef CUCCA
  193. unsigned blocksize = 8192;
  194. #else
  195. unsigned blocksize = 512;
  196. #endif CUCCA
  197. unsigned linesize = 0;
  198. int bfactor = 0;
  199. int labelsize = sizeof(struct vol);
  200.  
  201. int tapeunit = 0;
  202. int tf;
  203.  
  204. char    *defvsn = "";
  205.  
  206. char curdate[CRDATE+1];
  207. char *alongtime = " 99364";
  208.  
  209. #ifdef PIP
  210. int create, replace, xtract, table, verbose, confirm, pipfile;
  211. #else
  212. int create, replace, xtract, table, verbose, confirm;
  213. #endif
  214.  
  215. int blocking;
  216. int RT11, Upper;
  217. #ifdef VARIAN
  218. int Varlen;
  219. #endif VARIAN
  220. int Fixlen;
  221.  
  222. main(argc, argv)
  223.     int argc;
  224.     char **argv;
  225. {
  226.     char *ap;
  227.     int bufsize, openmode;
  228.  
  229.     if (argc < 2)
  230.         usage();
  231.     Skiparg();
  232.  
  233.     openmode = READ;
  234.     ap = argv[0];
  235.     Skiparg();
  236.     while (*ap) {
  237.         switch (*ap) {
  238.             case 'c':
  239.                 create++;
  240.                 openmode = READWRITE;
  241.                 break;
  242.             case 'r':
  243.                 replace++;
  244.                 openmode = READWRITE;
  245.                 break;
  246.             case 'x':
  247.                 xtract++;
  248.                 break;
  249.             case 't':
  250.                 table++;
  251.                 break;
  252.             case 'v':
  253.                 verbose++;
  254.                 break;
  255.             case 'w':
  256.                 confirm++;
  257.                 break;
  258.             case 'b':
  259.             case 'B':
  260.             case 'F':
  261.                 blocking++;
  262.                 blocksize = atoi(argv[0]);
  263.                 if (blocksize <= 0)
  264.                     fatal("bad block size %s\n", argv[0]);
  265.                 Skiparg();
  266.                 if ((*ap == 'B') || (*ap == 'F')) {
  267.                     linesize = atoi(argv[0]);
  268.                     if (linesize <= 0 ||
  269.                         blocksize % linesize != 0)
  270.                         fatal("bad line size %s\n", argv[0]);
  271.                     bfactor = blocksize / linesize;
  272.                     Skiparg();
  273.                     }
  274.                 if (*ap == 'F') Fixlen++;
  275.                 break;
  276.             case 'l':
  277.                 labelsize = atoi(argv[0]);
  278.                 if (labelsize < sizeof(struct hdr))
  279.                     fatal("label size must be >= %d\n",
  280.                         sizeof(struct hdr));
  281.                 Skiparg();
  282.                 break;
  283.             case 'U':
  284.                 Upper++;
  285.                 break;
  286.             case 'V':
  287.                 defvsn = argv[0];
  288.                 if (strlen(defvsn) > SERIAL)
  289.                     defvsn[SERIAL] = '\0';
  290.                 Skiparg();
  291.                 break;
  292.             case 'S':
  293.             case 'R':
  294.                 RT11++;
  295.                 Upper++;
  296.                 if (*ap == 'R')
  297.                     labelsize = 512;
  298.                 break;
  299. #ifdef VARIAN
  300.             case 'D':
  301.                 Varlen++;
  302.                 break;
  303. #endif VARIAN
  304. #ifdef PIP
  305.              case 'P':
  306.                  pipfile++;
  307.                  break;
  308. #endif PIP 
  309.             default:
  310.                 if (isdigit(*ap)) {
  311.                     tapeunit = *ap;
  312.                     break;
  313.                     }
  314.                 fatal("bad flag: %c\n", *ap);
  315.             }
  316.         ap++;
  317.         }
  318.  
  319.     filetab = argv;
  320.     filetab[argc] = NULL;
  321.  
  322.     if (tapeunit)
  323.         tapefile[strlen(tapefile)-1] = tapeunit;
  324.     tf = open(tapefile, openmode);
  325.     if (tf < 0)
  326.         fatal("can't open %s%s\n", tapefile,
  327.             (openmode != READ) ? " for writing" : "");
  328.     bufsize = max(blocksize, labelsize);
  329.     buffer = malloc(bufsize + 10);
  330.     if (buffer == NULL)
  331.         fatal("can't allocate buffer of %d bytes\n", blocksize);
  332.     if (linesize) {
  333.         linebuffer = malloc(linesize + 10);
  334.         if (linebuffer == NULL)
  335.             fatal("can't allocate line buffer of %d bytes\n",
  336.                 linesize);
  337.         }
  338.     getansidate(curdate);
  339.  
  340.     if (verbose && blocking) {
  341.         printf("Blocksize: %d", blocksize);
  342.         if (linesize)
  343.             printf(" Linesize: %d", linesize);
  344.         putc('\n', stdout);
  345.         }
  346.  
  347.     if (create || replace)
  348.         doupdate(tf);
  349.     else if (xtract)
  350.         doxtract(tf);
  351.     else if (table)
  352.         dotable(tf);
  353.     else
  354.         usage();
  355.     exit(0);
  356. }
  357.  
  358.  
  359.  
  360.  
  361. usage()
  362. {
  363.     fatal("usage: ansitar crxtvbl [blocksize] [labelsize] file ...\n");
  364. }
  365.  
  366.  
  367.  
  368.  
  369. dotable(tf)
  370.     int tf;
  371. {
  372.     char fileid[FILEID+1];
  373.     int files, n;
  374.     int blocks;
  375.     int lbseq;
  376.     long bytes;
  377.  
  378.     getvol(tf, &vol1);
  379.     prtvol(&vol1);
  380.     putc('\n', stdout);
  381.     files = 0;
  382.     lbseq = '1';
  383.     while (gethdr(tf, &hdr1)) {
  384.         files++;
  385.         if (verbose)
  386.             prthdr(&hdr1);
  387.         getmark(tf, &hdr2, lbseq);
  388.         sncpy(fileid, hdr1.h_fileid, FILEID);
  389.         blocks = 0;
  390.         bytes = 0L;
  391.         while ((n = getrec(tf, buffer, blocksize)) > 0) {
  392.             blocks++;
  393.             bytes += n;
  394.             }
  395.         lbseq = '1';
  396.         geteof(tf, &eof1);
  397.         if (verbose)
  398.             prthdr(&eof1);
  399.         getmark(tf, &hdr2, lbseq);
  400.         cmphdreof(&hdr1, &eof1);
  401.         if (verbose)
  402.             putc('\n', stdout);
  403.         printf("t %s %d blocks %D bytes\n", fileid, blocks, bytes);
  404.         if (linesize) 
  405.             printf("\t F-type: blocksize: %d linesize %d\n", blocksize, linesize);
  406.         else
  407.             printf("\t D-type: blocksize: %d\n", blocksize);
  408.         if (verbose)
  409.             putc('\n', stdout);
  410.         }
  411.     printf("\n%d files\n", files);
  412. }
  413.  
  414.  
  415.  
  416.  
  417. doxtract(tf)
  418.     int tf;
  419. {
  420.     char fileid[FILEID+1];
  421.     FILE *fp;
  422.     long bytes;
  423.     int blocks;
  424.     int n, xall;
  425.     int lbseq;
  426. #ifdef VARIAN
  427.     int newn;
  428. #endif VARIAN
  429.  
  430.     lbseq = '1';
  431.     xall = (filetab[0] == NULL);
  432.     getvol(tf, &vol1);
  433.     if (verbose)
  434.         prtvol(&vol1);
  435.     while (gethdr(tf, &hdr1)) {
  436.         getmark(tf, &hdr2, lbseq);
  437.         sncpy(fileid, hdr1.h_fileid, FILEID);
  438.         trimsp(fileid);
  439.         if (RT11)
  440.             fromRT11(fileid);
  441.  
  442.         /* if 1.you're doing all the files or 2. this file matches */
  443.         /* one of the the names in the arglist, then copy it, else */
  444.         /* skip this file. filetab is really 'argv' list.       */
  445.         if ( (xall || lookup(filetab, fileid, Upper)) &&
  446.              checkw('x', fileid) ) {
  447.             if (Upper)  makelower(fileid);    /* name to lower case*/
  448.             fp = fopen(fileid, "w");
  449. #ifdef VARIAN
  450.             if (fp == NULL) 
  451.                 {
  452.                 printf("can't create %s - will skip\n", fileid);
  453.                 skipfile(tf);
  454.                 }
  455. #else
  456.             if (fp == NULL) fatal("can't create %s\n", fileid);
  457. #endif VARIAN
  458.             else{    /* file OK, do the copy */
  459.                 blocks = 0;
  460.                 bytes = 0L;
  461.                 while ((n = getrec(tf, buffer, blocksize)) > 0) {
  462.                 if (linesize)
  463.                     lunblock(fp, buffer, n, linesize);
  464.                 else
  465. #ifdef VARIAN
  466.                     if (Varlen)
  467.                     {
  468.                     newn = varunblock(fp,buffer,n);
  469.                     n = newn;  /* now it's # written */
  470.                     }
  471.                     else
  472. #endif VARIAN
  473. #ifdef PIP
  474.                        if (pipfile)
  475.                      pipunblock(fp, buffer, n);
  476.                       else
  477. #endif PIP
  478.                     fwrite(buffer, n, 1, fp);
  479.                 blocks++;
  480.                 bytes += n;
  481.                 }
  482.                 fclose(fp);
  483.                 if (verbose)
  484.                 printf("x %s %d blocks %D bytes\n",
  485.                     fileid, blocks, bytes);
  486.                 }   /* end 'if file open was OK' */
  487.             }    /* end 'if filename OK or copying all' */
  488.         else    /* if this file is not be copied */
  489.             skipfile(tf);
  490.  
  491.         lbseq = '1';
  492.         geteof(tf, &eof1);
  493.         cmphdreof(&hdr1, &eof1);
  494.         getmark(tf, &hdr2, lbseq);
  495.         }
  496. }
  497.  
  498.  
  499.  
  500.  
  501. doupdate(tf)
  502.     int tf;
  503. {
  504.     int i, n;
  505.     int blocks;
  506.     long bytes;
  507.     char line[MAXLINE];
  508.     char fileid[FILEID+1];
  509.     char recmax[RECMAX+1];
  510.     FILE *fp;
  511.     int sequence;
  512.      int lbseq;
  513.  
  514.  
  515.     lbseq = '1';
  516.     sequence = 0;
  517.     if (create) {
  518.         initvol(&vol1);
  519.         putvol(tf, &vol1);
  520.         }
  521.     else {    /* replace */
  522.         getvol(tf, &vol1);
  523.         while (gethdr(tf, &hdr1)) {
  524.             sncpy(line, hdr1.h_seqno, SEQNO);
  525.             sequence = atoi(line);
  526.             getmark(tf, &hdr2, lbseq);
  527.             skipfile(tf);
  528.             lbseq = '1';
  529.             geteof(tf, &eof1);
  530.             getmark(tf, &hdr2, lbseq);
  531.             }
  532.         backspace(tf);
  533.         }
  534.     for (i=0; filetab[i] != NULL; i++) {
  535.         if (!checkw('a', filetab[i]))
  536.             continue;
  537.         strncpy(fileid, filetab[i], FILEID);
  538.         fileid[FILEID] = '\0';
  539.         fp = fopen(fileid, "r");
  540.         if (fp == NULL)
  541.             fatal("can't open %s\n", fileid);
  542.         sequence++;
  543.         if (RT11)
  544.             toRT11(fileid);
  545.         if (Upper)
  546.             makeupper(fileid);
  547.         inithdr(&hdr1, fileid, sequence);
  548.         puthdr(tf, &hdr1);
  549.         if (Varlen) {
  550. #ifdef CUCCA
  551.             blocksize = ISOBLOCK;
  552. #endif CUCCA
  553.             realloc(buffer,blocksize+10);
  554.             linesize = 0;
  555.             inithdr2(&hdr2, 'D', blocksize, 0);
  556.             n = dblock(fp, buffer, blocksize);
  557.             utoaz(n, recmax, RECMAX);
  558.             blcopy(hdr2.h2_recmax, recmax, RECMAX);
  559.             puthdr(tf, &hdr2);
  560.             fclose(fp);
  561.             fp = fopen("#tmp.tmp", "r");
  562.             if (fp == NULL) fatal("can't re-read #tmp.tmp\n");
  563.             }
  564.         if (Fixlen) {
  565.             inithdr2(&hdr2, 'F', blocksize, linesize);
  566.             puthdr(tf, &hdr2);
  567.             }
  568.         tapemark(tf);
  569.         blocks = 0;
  570.         bytes = 0L;
  571.         if (linesize)
  572.             while ((n = lblock(fp, buffer, linesize, bfactor)) > 0) {
  573.                 if (n % 2) {
  574.                     buffer[n] = '\0';
  575.                     n++;
  576.                     }
  577.                 n = write(tf, buffer, n);
  578.                 blocks++;
  579.                 bytes += n;
  580.                 }
  581. #ifdef PIP
  582.          else if (pipfile)
  583.              while ((n = pipblock(fp, buffer, blocksize)) > 0)
  584.              {
  585.                  n = write(tf, buffer, n);
  586.                  blocks++;
  587.                  bytes += n;
  588.              }
  589.                else
  590. #else
  591.         else
  592. #endif PIP
  593.             while ((n = fread(buffer, sizeof(char), blocksize, fp)) > 0) {
  594.                 if (n % 2) {
  595.                     buffer[n] = '\0';
  596.                     n++;
  597.                     }
  598.                 n = write(tf, buffer, n);
  599.                 blocks++;
  600.                 bytes += n;
  601.                 }
  602.         fclose(fp);
  603.         tapemark(tf);
  604.         blcopy(hdr1.h_labid, "EOF", LABID);
  605.         utoaz(blocks, line, BLOCKS);
  606.         blcopy(hdr1.h_blocks, line, BLOCKS);
  607.         puthdr(tf, &hdr1);
  608.         if ((Varlen) || (Fixlen)) {
  609.             blcopy(hdr2.h2_labid, "EOF", LABID);
  610.             puthdr(tf, &hdr2);
  611.             }
  612.         tapemark(tf);
  613.         if (verbose)
  614.             printf("a %s %d blocks %D bytes\n",
  615.                 fileid, blocks, bytes);
  616.         }
  617.     tapemark(tf);
  618. }
  619.  
  620.  
  621.  
  622.  
  623. getvol(tf, volp)
  624.     int tf;
  625.     struct vol *volp;
  626. {
  627.     int n;
  628.  
  629.     if (labelsize == sizeof(struct vol))
  630.         n = read(tf, (char *)volp, sizeof(struct vol));
  631.     else {
  632.         n = read(tf, buffer, labelsize);
  633.         bcopy((char *)volp, buffer, sizeof(struct vol));
  634.         }
  635. #ifdef PIP
  636.      if (n<0)
  637.      {
  638.          perror("Tape read error");
  639.          exit(1);
  640.      }
  641. #endif PIP
  642.     if (n != labelsize ||
  643.         strncmp(volp->v_labid, "VOL", LABID) != 0 ||
  644.         volp->v_labno != '1') {
  645.         printf("Warning: Volume label (VOL1) missing\n");
  646.         backspace(tf);
  647.         return;
  648.         }
  649.  
  650.     /* check for RT11 boot block between VOL1 and first HDR1 */
  651.     if (RT11) {
  652.         /* must have labelsize = 512 */
  653.         n = read(tf, buffer, labelsize);
  654.         bcopy((char *)&hdr1, buffer, sizeof(struct hdr));
  655.         if (n == labelsize && strncmp(hdr1.h_labid, "HDR", LABID) == 0)
  656.             backspace(tf);
  657.         else
  658.             printf("Possible RT11 bootstrap block.\n");
  659.         }
  660. }
  661.  
  662.  
  663.  
  664.  
  665. int
  666. gethdr(tf, hdrp)
  667.     int tf;
  668.     struct hdr *hdrp;
  669. {
  670.     int n;
  671.  
  672.     if (labelsize == sizeof(struct hdr))
  673.         n = read(tf, (char *)hdrp, sizeof(struct hdr));
  674.     else {
  675.         n = read(tf, buffer, labelsize);
  676.         bcopy((char *)hdrp, buffer, sizeof(struct hdr));
  677.         }
  678.     if (n == 0)
  679.         return(FALSE);
  680.     if (n != labelsize ||
  681.         strncmp(hdrp->h_labid, "HDR", LABID) != 0 ||
  682.         hdrp->h_labno != '1')
  683.         hdrerr(tf, hdrp);
  684.     return(TRUE);
  685. }
  686.  
  687.  
  688.  
  689.  
  690. hdrerr(tf, hdrp)
  691.     int tf;
  692.     struct hdr *hdrp;
  693. {
  694.     int found, n;
  695.  
  696.     printf("Warning: File label (HDR1) error - skipping\n");
  697.     found = FALSE;
  698.     while (!found) {
  699.         skipfile(tf);
  700.         if (labelsize == sizeof(struct hdr))
  701.             n = read(tf, (char *)hdrp, sizeof(struct hdr));
  702.         else {
  703.             n = read(tf, buffer, labelsize);
  704.             bcopy((char *)hdrp, buffer, sizeof(struct hdr));
  705.             }
  706.         if ((n == labelsize) &&
  707.             (strncmp(hdrp->h_labid, "HDR", LABID) == 0))
  708.             found = TRUE;
  709.         }
  710. }
  711.  
  712.  
  713.  
  714.  
  715. geteof(tf, eofp)
  716.     int tf;
  717.     struct hdr *eofp;
  718. {
  719.     int n;
  720.  
  721.     if (labelsize == sizeof(struct hdr))
  722.         n = read(tf, eofp, sizeof(struct hdr));
  723.     else {
  724.         n = read(tf, buffer, labelsize);
  725.         bcopy((char *)eofp, buffer, sizeof(struct hdr));
  726.         }
  727.     if (n != labelsize ||
  728.         strncmp(eofp->h_labid, "EOF", LABID) != 0 ||
  729.         eofp->h_labno != '1')
  730.         printf("Warning: File label (EOF1) error\n");
  731. }
  732.  
  733.  
  734.  
  735.  
  736. int
  737. getrec(f, buf, size)
  738.     int f;
  739.     char *buf;
  740.     int size;
  741. {
  742.     int n;
  743.  
  744.     n = read(f, buf, size);
  745.     if (n < 0)
  746.         fatal("Read error (record may be larger than %db)\n",
  747.             size);
  748.     return(n);
  749. }
  750.  
  751.  
  752.  
  753.  
  754. getmark(tf, hdr2p, labseq)
  755.     int tf;
  756.     int labseq;
  757.     struct hd2 *hdr2p;
  758. {
  759.     char rec[sizeof(struct hdr)];
  760.     char blkmax[BLKMAX+1], recmax[RECMAX+1];
  761.     char lstring[sizeof(struct hdr) + 1];
  762.     int n;
  763.     int s;
  764.  
  765.     s = labseq;
  766.         s++;
  767.     n = read(tf, rec, sizeof(rec));
  768.     if (n == 0)
  769.         return;
  770.     if (n == sizeof(struct hdr) && (strncmp("HDR", rec, 3)==0)) {
  771.         bcopy((char *)hdr2p, rec, sizeof(struct hdr));
  772.         if (hdr2p->h2_labno == s) {
  773.             sncpy(blkmax, hdr2p->h2_blkmax, BLKMAX);
  774.             sncpy(recmax, hdr2p->h2_recmax, RECMAX);
  775.             if ((verbose) && (table)) 
  776.                 prthdr2(&hdr2);
  777.             blocksize = max(blocksize, atoi(blkmax));
  778.             if (hdr2p->h2_datatype == 'D') {
  779.                 linesize = 0;
  780.                 Varlen = TRUE; }
  781.             else  { linesize = max(linesize, atoi(recmax));
  782.                 Varlen = FALSE; }
  783.             realloc(buffer,blocksize+10);
  784.             }
  785.         }
  786.     else if ((verbose) && (table)) {
  787.         sncpy(lstring, rec, sizeof(struct hdr));
  788.         printf("%s\n", lstring);
  789.         }
  790.     /* skip HDR3-9 */
  791.     while (n == sizeof(struct hdr) &&
  792.           (strncmp("HDR", rec, 3)==0 || strncmp("EOF", rec, 3)==0)) {
  793.         n = read(tf, rec, sizeof(rec));
  794.         if (n == 0)
  795.             return;
  796.         else if ((verbose) && (table)) {
  797.             sncpy(lstring, rec, sizeof(struct hdr));
  798.             printf("%s\n", lstring);
  799.             }
  800.         }
  801.     printf("Warning: tape mark missing\n");
  802. }
  803.  
  804.  
  805.  
  806.  
  807. cmphdreof(hdrp, eofp)
  808.     struct hdr *hdrp, *eofp;
  809. {
  810.     char line[MAXLINE];
  811.  
  812.     static int len = FILEID+SETID+SECNO+SEQNO+GENNO+GENVSNO+
  813.             CRDATE+EXDATE+1;
  814.  
  815.     if (strncmp(hdrp->h_fileid, eofp->h_fileid, len) != 0 ||
  816.         strncmp(hdrp->h_system, eofp->h_system, SYSTEM) != 0) {
  817.         sncpy(line, hdrp->h_fileid, FILEID);
  818.         fprintf(stderr, "Warning: HDR and EOF labels for %s disagree\n",
  819.             line);
  820.         }
  821. }
  822.  
  823.  
  824.  
  825.  
  826. putvol(tf, volp)
  827.     int tf;
  828.     struct vol *volp;
  829. {
  830.     int len;
  831.  
  832.     if (labelsize == sizeof(struct vol)) {
  833.         write(tf, volp, sizeof(struct vol));
  834.         return;
  835.         }
  836.     bcopy(buffer, (char *)volp, sizeof(struct vol));
  837.     len = labelsize - sizeof(struct vol);
  838.     blcopy(&buffer[sizeof(struct vol)], "", len);
  839.     write(tf, buffer, labelsize);
  840. }
  841.  
  842.  
  843.  
  844.  
  845. puthdr(tf, hdrp)
  846.     int tf;
  847.     struct hdr *hdrp;
  848. {
  849.     int len;
  850.  
  851.     if (labelsize == sizeof(struct hdr)) {
  852.         write(tf, hdrp, sizeof(struct hdr));
  853.         return;
  854.         }
  855.     bcopy(buffer, (char *)hdrp, sizeof(struct hdr));
  856.     len = labelsize - sizeof(struct hdr);
  857.     blcopy(&buffer[sizeof(struct hdr)], "", len);
  858.     write(tf, buffer, labelsize);
  859. }
  860.  
  861.  
  862.  
  863.  
  864. prtvol(volp)
  865.     struct vol *volp;
  866. {
  867.     char labid[LABID+1], serial[SERIAL+1], owner[OWNER+1];
  868.  
  869.     sncpy(labid, volp->v_labid, LABID);
  870.     sncpy(serial, volp->v_serial, SERIAL);
  871.     sncpy(owner, volp->v_owner, OWNER);
  872.     printf("Volume label:\n");
  873.     printf("\tLabel: %s%c Serial: %s  Access: %c\n",
  874.         labid, volp->v_labno, serial, volp->v_access);
  875.     printf("\tOwner: %s  Standard: %c\n",
  876.         owner, volp->v_stdlabel);
  877. }
  878.  
  879.  
  880.  
  881.  
  882. prthdr(hdrp)
  883.     struct hdr *hdrp;
  884. {
  885.     char labid[LABID+1], fileid[FILEID+1], setid[SETID+1];
  886.     char secno[SECNO+1], seqno[SEQNO+1];
  887.     char genno[GENNO+1], genvsno[GENVSNO+1];
  888.     char crdate[CRDATE+1], exdate[EXDATE+1];
  889.     char blocks[BLOCKS+1], system[SYSTEM+1];
  890.  
  891.     sncpy(labid, hdrp->h_labid, LABID);
  892.     sncpy(fileid, hdrp->h_fileid, FILEID);
  893.     sncpy(setid, hdrp->h_setid, SETID);
  894.     sncpy(secno, hdrp->h_secno, SECNO);
  895.     sncpy(seqno, hdrp->h_seqno, SEQNO);
  896.     sncpy(genno, hdrp->h_genno, GENNO);
  897.     sncpy(genvsno, hdrp->h_genvsno, GENVSNO);
  898.     sncpy(crdate, hdrp->h_crdate, CRDATE);
  899.     sncpy(exdate, hdrp->h_exdate, EXDATE);
  900.     sncpy(blocks, hdrp->h_blocks, BLOCKS);
  901.     sncpy(system, hdrp->h_system, SYSTEM);
  902.  
  903.     printf("File Label:\n");
  904.     printf("\tLabel: %s%c  File: %s\n",
  905.         labid, hdrp->h_labno, fileid);
  906.     printf("\tSet: %s  Section: %s  Sequence: %s\n",
  907.         setid, secno, seqno);
  908.     printf("\tGeneration: %s  Generation Version: %s\n",
  909.         genno, genvsno);
  910.     printf("\tCreated: %s  Expires: %s  Access: %c\n",
  911.         crdate, exdate, hdrp->h_access);
  912.     printf("\tBlocks: %s  System: %s\n",
  913.         blocks, system);
  914. }
  915.  
  916. prthdr2(hdrp)
  917.     struct hd2 *hdrp;
  918. {
  919.     char labid[LABID+1]; 
  920.     char blkmax[BLKMAX+1], recmax[RECMAX+1];
  921.     char bytoffs[BYTOFFS+1];
  922.  
  923.     sncpy(labid, hdrp->h2_labid, LABID);
  924.     sncpy(blkmax, hdrp->h2_blkmax, BLKMAX);
  925.     sncpy(recmax, hdrp->h2_recmax, RECMAX);
  926.     sncpy(bytoffs, hdrp->h2_bytoffs, BYTOFFS);
  927.  
  928.     printf("File Label:\n");
  929.     printf("\tLabel: %s%c  Datatype: %c\n",
  930.         labid, hdrp->h2_labno, hdrp->h2_datatype);
  931.     printf("\tMaximum block size: %s  Maximum record size: %s\n",
  932.         blkmax, recmax);
  933.     printf("\tByte offset at head of block: %s\n",
  934.         bytoffs);
  935. }
  936.  
  937.  
  938.  
  939.  
  940. initvol(volp)
  941.     struct vol *volp;
  942. {
  943.     struct passwd *passwp, *getpwuid();
  944.  
  945.     blcopy(volp, "", sizeof(struct vol));
  946.  
  947.     blcopy(volp->v_labid, "VOL", LABID);
  948.     volp->v_labno = '1';
  949.     blcopy(volp->v_serial, defvsn, SERIAL);
  950.     volp->v_access = ' ';
  951.     passwp = getpwuid(getuid());
  952.     blcopy(volp->v_owner, passwp->pw_name, OWNER);
  953.     if ((Varlen) || (Fixlen))
  954.         volp->v_stdlabel = '3'; 
  955.     else 
  956.         volp->v_stdlabel = '1';
  957. }
  958.  
  959.  
  960.  
  961.  
  962. inithdr(hdrp, filename, seq)
  963.     struct hdr *hdrp;
  964.     char *filename;
  965.     int seq;
  966. {
  967.     char seqno[SEQNO+1];
  968.  
  969.     blcopy(hdrp, "", sizeof(struct hdr));
  970.  
  971.     blcopy(hdrp->h_labid, "HDR", LABID);
  972.     hdrp->h_labno = '1';
  973.     blcopy(hdrp->h_fileid, filename, FILEID);
  974.     blcopy(hdrp->h_secno, "0001", SECNO);
  975.     utoaz(seq, seqno, SEQNO);
  976.     blcopy(hdrp->h_seqno, seqno, SEQNO);
  977.     blcopy(hdrp->h_genno, "0001", GENNO);
  978.     blcopy(hdrp->h_genvsno, "00", GENVSNO);
  979.     blcopy(hdrp->h_crdate, curdate, CRDATE);
  980.     blcopy(hdrp->h_exdate, alongtime, EXDATE);
  981.     blcopy(hdrp->h_blocks, "000000", BLOCKS);
  982.     blcopy(hdrp->h_system, "Unix V7", SYSTEM);
  983. }
  984.  
  985. inithdr2(hdr2p, rectype, b, r)
  986.     struct hd2 *hdr2p;
  987.     int rectype;
  988.     int b, r;
  989. {
  990.     char blkmax[BLKMAX+1];
  991.     char recmax[RECMAX+1];
  992.  
  993.     blcopy(hdr2p, "", sizeof(struct hdr));
  994.  
  995.     blcopy(hdr2p->h2_labid, "HDR", LABID);
  996.     hdr2p->h2_labno = '2';
  997.     hdr2p->h2_datatype = rectype;
  998.     utoaz(b, blkmax, BLKMAX);
  999.     blcopy(hdr2p->h2_blkmax, blkmax, BLKMAX);
  1000.     utoaz(r, recmax, RECMAX);
  1001.     blcopy(hdr2p->h2_recmax, recmax, RECMAX);
  1002.     blcopy(hdr2p->h2_bytoffs, "00", BYTOFFS);
  1003. }
  1004.  
  1005.  
  1006. int
  1007. dblock(fp,buffer,blocksize)
  1008.     FILE *fp;
  1009.     char *buffer;
  1010.     int blocksize;
  1011. {
  1012.     FILE *fs;
  1013.     char dbuffer[MAXLINE+5];
  1014. #if DEBUG
  1015.     char tbuffer[ISOBLOCK + 1];
  1016. #endif
  1017.     char *bb, *db;
  1018.     int n, nl, nlm;
  1019.     int brem;
  1020.     int nf;
  1021.  
  1022.     fs = fopen("#tmp.tmp", "w");
  1023.     if (fs == NULL) fatal("can't create #tmp.tmp\n");
  1024.     bb = buffer; brem = blocksize + 1; n = 1; nlm = 0;
  1025.     while (n) {
  1026.         n = drecord(fp, dbuffer); 
  1027.         nlm = max(nlm, n);
  1028. #if DEBUG
  1029.         printf(" %s\n in dbuffer  %d brem\n", dbuffer, brem);
  1030. #endif
  1031.         if ((n) && ((brem -= n) > 0)) { 
  1032.             for(nl = 0; nl < n; ++nl) *bb++ = dbuffer[nl];  
  1033. #if DEBUG
  1034.         *bb = 0; printf("first try %s\n", buffer);
  1035. #endif
  1036.             } 
  1037.         else {     
  1038.         brem += n;
  1039. #if DEBUG
  1040.             printf(" %d fill bytes needed\n", brem);
  1041. #endif
  1042.             while (brem-- > 0) *bb++ = '^'; 
  1043.             bb = buffer; nl = n; 
  1044. #if DEBUG
  1045.         strncpy(tbuffer, buffer, blocksize);printf("%s\n", tbuffer);
  1046. #endif
  1047.             nf = fwrite(buffer, blocksize, 1, fs); 
  1048.             if (n) { 
  1049.                 for(nl = 0; nl < n; ++nl) *bb++ = dbuffer[nl];  
  1050. #if DEBUG
  1051.         strncpy(tbuffer, buffer, blocksize);printf("%s\n", tbuffer);
  1052. #endif
  1053.                 brem = blocksize - n;
  1054.                 } 
  1055.             }
  1056.         } 
  1057.     fclose(fs); 
  1058.     return(nlm); 
  1059. }
  1060.  
  1061.  
  1062.  
  1063. int
  1064. drecord(fp, lbuffer)
  1065.     FILE *fp;
  1066.     char *lbuffer;
  1067.  
  1068. {
  1069.     char count[DBYTES+1];
  1070.     int n;
  1071.     
  1072.     n = filldln(fp, lbuffer);
  1073.     utoaz(n, count, DBYTES);
  1074.     bcopy(lbuffer, count, DBYTES);
  1075.     return(n);
  1076. }
  1077.  
  1078.  
  1079.  
  1080.  
  1081. int
  1082. filldln(fp, lbuf)
  1083.     FILE *fp;
  1084.     char *lbuf;
  1085.  
  1086. {
  1087.     int i, linelim;
  1088.     register int c;
  1089.     register char *lb;
  1090.  
  1091.     lb = lbuf;
  1092.     linelim = MAXLINE+DBYTES;
  1093.     i = DBYTES;
  1094.     lb += DBYTES;
  1095.     while ((c = getc(fp)) && (c != EOF) && (c != '\n')) {
  1096.         *lb++ = c;
  1097.         if (i++ > linelim-1) break;
  1098.         }
  1099.     *lb = '\0';
  1100.     if (c == '\n') return(i);
  1101.     if (c == EOF) return(0);
  1102.     printf("%d byte line too long; Broken into parts.\n", i);
  1103.         return(i);
  1104. }
  1105.  
  1106.  
  1107. int
  1108. lblock(fp, buffer, lsize, bfactor)
  1109.     FILE *fp;
  1110.     char *buffer;
  1111.     int lsize, bfactor;
  1112. {
  1113.     register char *lp, *linelim;
  1114.     register int c;
  1115.     int i;
  1116.     char *bp;
  1117.  
  1118.     bp = buffer;
  1119.     for (i=0; i<bfactor; i++) {
  1120.         lp = bp;
  1121.         linelim = &lp[lsize];
  1122.         while (lp < linelim) {
  1123.             c = getc(fp);
  1124.             if (c == '\n' || c == EOF)
  1125.                 break;
  1126.             *lp++ = c;
  1127.             }
  1128.         if (c == EOF && lp == bp)
  1129.             break;
  1130.         while (c != '\n' && c != EOF)
  1131.             c = getc(fp);
  1132.         while (lp < linelim)
  1133.             *lp++ = ' ';
  1134.         bp += lsize;
  1135.         }
  1136.     return(bp - buffer);
  1137. }
  1138.  
  1139.  
  1140.  
  1141.  
  1142. lunblock(fp, buffer, blen, lsize)
  1143.     FILE *fp;
  1144.     char *buffer;
  1145.     int blen, lsize;
  1146. {
  1147.     register char *lastp, *bp1;
  1148.     char *bp, *buflim;
  1149.  
  1150.     buflim = &buffer[blen];
  1151.     bp = buffer;
  1152.     while (bp < buflim) {
  1153.         lastp = &bp[lsize-1];
  1154.         while (lastp >= bp && isspace(*lastp))
  1155.             lastp--;
  1156.         for (bp1=bp; bp1<=lastp; bp1++)
  1157.             putc(*bp1, fp);
  1158.         putc('\n', fp);
  1159.         bp += lsize;
  1160.         }
  1161. }
  1162.  
  1163.  
  1164.  
  1165.  
  1166. blcopy(dest, src, n)
  1167.     char *dest, *src;
  1168.     int n;
  1169. {
  1170.     int i;
  1171.  
  1172.     i=0;
  1173.     while (i < n && *src) {
  1174.         *dest++ = *src++;
  1175.         i++;
  1176.         }
  1177.     while (i++ < n)
  1178.         *dest++ = ' ';
  1179. }
  1180.  
  1181.  
  1182.  
  1183.  
  1184. sncpy(dest, src, n)
  1185.     char *dest, *src;
  1186.     int n;
  1187. {
  1188.     int i;
  1189.  
  1190.     i = 0;
  1191.     while (*src && i<n) {
  1192.         *dest++ = *src++;
  1193.         i++;
  1194.         }
  1195.     *dest = '\0';
  1196. }
  1197.  
  1198.  
  1199.  
  1200. utoaz(n, buf, size)
  1201.     int n;
  1202.     char *buf;
  1203.     int size;
  1204. {
  1205.     char *p;
  1206.  
  1207.     p = &buf[size-1];
  1208.     while (p >= buf && n != 0) {
  1209.         *p = '0' + (n % 10);
  1210.         n /= 10;
  1211.         p--;
  1212.         }
  1213.     while (p >= buf) {
  1214.         *p = '0';
  1215.         p--;
  1216.         }
  1217. }
  1218.  
  1219.  
  1220.  
  1221.  
  1222. tapemark(tf)
  1223.     int tf;
  1224. {
  1225.     struct mtop mtop;
  1226.  
  1227.     mtop.mt_count = 1;
  1228.     mtop.mt_op = MTWEOF;
  1229.     ioctl(tf, MTIOCTOP, &mtop);
  1230. }
  1231.  
  1232.  
  1233.  
  1234.  
  1235. skipfile(tf)
  1236.     int tf;
  1237. {
  1238.     struct mtop mtop;
  1239.  
  1240.     mtop.mt_count = 1;
  1241.     mtop.mt_op = MTFSF;
  1242.     ioctl(tf, MTIOCTOP, &mtop);
  1243. }
  1244.  
  1245.  
  1246.  
  1247.  
  1248. backspace(tf)
  1249.     int tf;
  1250. {
  1251.     struct mtop mtop;
  1252.  
  1253.     mtop.mt_count = 1;
  1254.     mtop.mt_op = MTBSR;
  1255.     ioctl(tf, MTIOCTOP, &mtop);
  1256. }
  1257.  
  1258.  
  1259.  
  1260.  
  1261. /* getansidate -- return the current date in ansi format
  1262.  *
  1263.  * Ansi dates are strings of the form " yyddd" where
  1264.  * yy = the year and ddd = the day in the year.  There must
  1265.  * be an initial blank.
  1266.  */
  1267.  
  1268. getansidate(curdate)
  1269.     char *curdate;
  1270. {
  1271.     time_t now, time();
  1272.     struct tm *timep, *localtime();
  1273.  
  1274.     now = time(NULL);
  1275.     timep = localtime(&now);
  1276.     curdate[0] = ' ';
  1277.     utoaz(timep->tm_year, &curdate[1], 2);
  1278.     utoaz(timep->tm_yday, &curdate[3], 3);
  1279.     curdate[6] = '\0';
  1280. }
  1281.  
  1282.  
  1283.  
  1284.  
  1285. int
  1286. lookup(tab, name, Upper)
  1287.     char *tab[];
  1288.     char *name;
  1289.     int Upper;
  1290. {
  1291.     int i;
  1292.     char lower[MAXLINE];
  1293.  
  1294.     if (Upper) {
  1295.         strcpy(lower, name);
  1296.         makelower(lower);
  1297.         }
  1298.     for (i=0; tab[i] != NULL; i++)
  1299. #ifdef VARIAN
  1300.         if (wildcmp(tab[i], name, WILDCARD) == 0 ||
  1301.             (Upper && wildcmp(tab[i], lower, WILDCARD)==0))
  1302. #else
  1303.         if (strcmp(tab[i], name) == 0 ||
  1304.             (Upper && strcmp(tab[i], lower)==0))
  1305.  
  1306. #endif VARIAN
  1307.             return(TRUE);
  1308.     return(FALSE);
  1309. }
  1310.  
  1311.  
  1312.  
  1313.  
  1314. makelower(s)
  1315.     char *s;
  1316. {
  1317.     register char *p;
  1318.  
  1319.     p = s;
  1320.     while (*p) {
  1321.         if (isupper(*p))
  1322.             *p = tolower(*p);
  1323.         p++;
  1324.         }
  1325. }
  1326.  
  1327.  
  1328.  
  1329.  
  1330. makeupper(s)
  1331.     char *s;
  1332. {
  1333.     register char *p;
  1334.  
  1335.     p = s;
  1336.     while (*p) {
  1337.         if (islower(*p))
  1338.             *p = toupper(*p);
  1339.         p++;
  1340.         }
  1341. }
  1342.  
  1343.  
  1344.  
  1345.  
  1346. int
  1347. haslower(p)
  1348. register char *p;
  1349. {
  1350.  
  1351.     while (*p) {
  1352.         if (islower(*p))
  1353.             return(TRUE);
  1354.         p++;
  1355.         }
  1356.     return(FALSE);
  1357. }
  1358.  
  1359.  
  1360.  
  1361.  
  1362. toRT11(name)
  1363.     char *name;
  1364. {
  1365.     char buf[32], *extp;
  1366.  
  1367.     extp = index(name, '.');
  1368.     if (extp != NULL) {
  1369.         *extp = '\0';
  1370.         extp++;
  1371.         }
  1372.     blcopy(buf, name, 6);
  1373.     buf[6] = '.';
  1374.     if (extp != NULL)
  1375.         blcopy(&buf[7], extp, 3);
  1376.     else
  1377.         strcpy(&buf[7], "ext");
  1378.     buf[10] = '\0';
  1379.     strcpy(name, buf);
  1380. }
  1381.  
  1382.  
  1383.  
  1384.  
  1385. fromRT11(name)
  1386.     char *name;
  1387. {
  1388.     char *op, *np;
  1389.  
  1390.     op = np = name;
  1391.     while (*op) {
  1392.         if (!isspace(*op))
  1393.             *np++ = *op;
  1394.         op++;
  1395.         }
  1396.     *np = '\0';
  1397. }
  1398.  
  1399.  
  1400.  
  1401.  
  1402.  
  1403. trimsp(s)
  1404.     char *s;
  1405. {
  1406.     register char *p;
  1407.  
  1408.     p = &s[strlen(s)-1];
  1409.     while (p >= s && isspace(*p))
  1410.         p--;
  1411.     *++p = '\0';
  1412. }
  1413.  
  1414.  
  1415.  
  1416.  
  1417. bcopy(dest, src, size)
  1418.     char *dest, *src;
  1419.     int size;
  1420. {
  1421.     while (size-- > 0)
  1422.         *dest++ = *src++;
  1423. }
  1424.  
  1425.  
  1426.  
  1427.  
  1428. int
  1429. max(a, b)
  1430.     int a, b;
  1431. {
  1432.     if (a > b)
  1433.         return(a);
  1434.     return(b);
  1435. }
  1436.  
  1437.  
  1438.  
  1439.  
  1440. int
  1441. checkw(c, name)
  1442.     char c, *name;
  1443. {
  1444.     if (!confirm)
  1445.         return(TRUE);
  1446.     printf("%c %s:", c, name);
  1447.     c = getchar();
  1448.     if (c != '\n')
  1449.         while ((c = getchar()) != '\n')
  1450.             ;
  1451.     return(c == 'y' || c == 'Y');
  1452. }
  1453.  
  1454.  
  1455.  
  1456. /* VARARGS */
  1457. fatal(s, a1, a2, a3, a4)
  1458.     char *s;
  1459. {
  1460.     fprintf(stderr, "ansitar: ");
  1461.     fprintf(stderr, s, a1, a2, a3, a4);
  1462.     exit(1);
  1463. }
  1464.  
  1465. #ifdef VARIAN
  1466. /* varunblock - unblock variable length records ("D" format)    
  1467.  * Beginning of each record contains a 4 digit number which is the
  1468.  *   length of the record (including the count).
  1469.  * There are no line terminators (CR or LF).
  1470.  */
  1471. varunblock(fp, buffer, blen)
  1472.     FILE *fp;
  1473.     char *buffer;
  1474.     int blen;
  1475. {    /* the function now returns the # of bytes it decided to write */
  1476.     register char *lastp, *bp1;
  1477.     char *bp, *buflim;
  1478.     int count;
  1479.     int newblen;    /* this will count the actual bytes written out */
  1480.  
  1481.     buflim = &buffer[blen];
  1482.     bp = buffer;
  1483.     newblen = 0;
  1484. #if DEBUG    
  1485.     DBG" varunblock called. length %d\n",blen);
  1486.     if(DEBUG)hexdmp(" buffer passed to varunblock",buffer,blen);
  1487.     DBG"  ");
  1488. #endif DEBUG
  1489.  
  1490.     while (bp < buflim) {
  1491. #if DEBUG
  1492.         DBG"  count being made from %2x %2x %2x %2x %2x\n",
  1493.             *bp,*(bp+1),*(bp+2),*(bp+3),*(bp+4));
  1494. #endif
  1495.         sscanf(bp,"%4d",&count);
  1496.         count = count - 4;    /* count includes the count itself */
  1497. #if DEBUG
  1498.         DBG"  count %3d\n     ",count);
  1499. #endif
  1500.         if (*bp == 0x5e)     /* if fill encountered for length */
  1501.             {        /* then abandon this record */
  1502. #if DEBUG
  1503.             DBG" hit filler. assume eor. break\n");
  1504. #endif
  1505.             break;
  1506.             }
  1507.         bp = bp+4;        /* point to the end of line        */
  1508.         lastp = bp + count;
  1509.         while (bp<lastp)
  1510.             {
  1511. #if DEBUG
  1512.             if(DEBUG) putc(*bp, stderr);
  1513. #endif
  1514.             putc(*bp++, fp);
  1515.             newblen++;
  1516.             }
  1517. #if DEBUG
  1518.         if(DEBUG) putc('\n', stderr);
  1519. #endif
  1520.         putc('\n', fp);
  1521.         newblen++;
  1522.         }
  1523.  
  1524.     return(newblen);
  1525. }
  1526.  
  1527.  
  1528.  
  1529. wildcmp(wilds,str,wc)    /* compare 2 strings. 1st can have a wildcard '*' */
  1530. char   *wilds;        /* input string possibly containing a wildcard chr*/
  1531. char   *str;        /* 2nd input string.  wild chrs in it aren't 'wild'*/
  1532. char    wc;        /* the 'wild card' character, often a '*'      */
  1533. {    /* function return is 0 if equal (like strcmp). < > not supported */
  1534.     char  *l,*s;
  1535.     int    flag;        /* will watch for multiple *'s in 'wild'*/
  1536.     char   wcrd;
  1537.  
  1538.     if (strlen(str) == 0) return(-1);    /* don't match phantom */
  1539.     wcrd = wc & 127;
  1540.  
  1541.     flag = 0;    /* wildcard not encountered yet */
  1542.     for (l=wilds,s=str ; *l != '\0' ;     )
  1543.         {
  1544.         if (*l == wcrd)    /* if wildcard emcountered, adjust pointers*/
  1545.         {
  1546.         if (flag)  return(0);
  1547.         flag = 1;
  1548.         l++;    /* skip the wildcard */
  1549.         s = str + strlen(str) - (strlen(wilds) - (l - wilds) );
  1550.         }
  1551.         else{    /* no wildcard, increment pointers normally */
  1552.             if (*l != *s) return(*l - *s);
  1553.         l++;
  1554.         s++;
  1555.         }
  1556.         }
  1557.  
  1558.     if (*s != '\0') return(*l - *s);
  1559.     return(0);    /* returning "success" indicator. they were equal */
  1560. }
  1561. #endif VARIAN
  1562.  
  1563. #ifdef PIP
  1564.  
  1565.  /*****************************************************************
  1566.   * TAG( pipunblock )
  1567.   * 
  1568.   * Unblock pip records.  These are in a counted format with a 4 byte
  1569.   * count, followed by the record.  (Count includes the length of the
  1570.   * count).  Blank space at the end of a block is filled with '^'
  1571.   * characters.
  1572.   */
  1573.  
  1574.  pipunblock(fp, buffer, n)
  1575.  FILE *fp;
  1576.  char *buffer;
  1577.  {
  1578.      register char *cp;
  1579.      int len, i;
  1580.  
  1581.      for (cp=buffer; cp<buffer+n; )
  1582.      {
  1583.      for (i=0, len=0; i<4; i++)
  1584.          len = len*10 + *cp++ - '0';
  1585.      for (len -= 4; len > 0; len--)
  1586.          putc(*cp++, fp);
  1587.      putc('\n', fp);
  1588.      while (*cp == '^' && cp<buffer+n)
  1589.          cp++;
  1590.      }
  1591.  }
  1592.  
  1593.  /*****************************************************************
  1594.   * TAG( pipblock )
  1595.   * 
  1596.   * Read lines from the input file and block them pip-style into the
  1597.   * buffer.  Make logical blocks of 512 bytes and fill space at the end
  1598.   * of the logical blocks with '^' characters.
  1599.   */
  1600.  
  1601.  pipblock(fp, buffer, blocksize)
  1602.  FILE *fp;
  1603.  char *buffer;
  1604.  {
  1605.      register char *cp;
  1606.      static char linebuf[512];         /* lines not allowed longer than this? */
  1607.      static int nline = 0;
  1608.      int n;
  1609.  
  1610.      if (blocksize%512)
  1611.      {
  1612.      fprintf(stderr, "Blocksize must be a multiple of 512 for pip tapes\n");
  1613.      exit(1);
  1614.      }
  1615.      for (cp=buffer; cp<(buffer+blocksize); )
  1616.      {
  1617.      if (nline <= 0)
  1618.          if (fgets(linebuf, 508, fp) == NULL)
  1619.          nline = -1;
  1620.          else
  1621.          {
  1622.          linebuf[508] = '\0';
  1623.          nline = strlen(linebuf);
  1624.          if (linebuf[nline-1] == '\n')
  1625.              linebuf[--nline] = '\0';
  1626.          }
  1627.  
  1628.      if (nline > (508 - (cp-buffer)%512) ||
  1629.          (nline < 0 && (cp-buffer)%512 != 0))
  1630.          while ( (cp-buffer)%512 != 0 )
  1631.          *cp++ = '^';
  1632.  
  1633.      if (cp-buffer >= blocksize || nline < 0)
  1634.          return cp-buffer;
  1635.  
  1636.      sprintf(cp, "%04d", nline+4);
  1637.      cp += 4;
  1638.      strncpy(cp, linebuf, 508);
  1639.      cp += nline;
  1640.      nline = 0;
  1641.      }
  1642.  
  1643.      return cp-buffer;           /* should never get here, but you never know */
  1644. }
  1645. #endif PIP
  1646.