home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 mARCH / PCWK3A99.iso / Archiwiz / Tar320 / SOURCES.ZIP / READOPT.C < prev    next >
Text File  |  1994-12-31  |  15KB  |  513 lines

  1. #include "modern.h"
  2. #ifdef MODERN
  3. #    include <stdlib.h>
  4. #    include <string.h>
  5. #    ifdef ZMEM
  6. #        define MEMCPY(d,s,n) strcpy(d,s)
  7. #    endif
  8. #    ifdef NOMEMCPY
  9. #        define MEMCPY(d,s,n) strcpy(d,s)
  10. #    endif
  11. #    ifndef MEMCPY
  12. #        define MEMCPY(d,s,n) memcpy(d,s,n)
  13. #    endif
  14. #    ifdef __TURBOC__
  15. #        include <io.h>
  16. #    endif
  17. #else
  18. #    define MEMCPY(d,s,n) strcpy(d,s)
  19.     char *strcpy(), *getenv(), *malloc(), *realloc();
  20.         int strlen();
  21. #endif
  22. #include <stdio.h>
  23. #include "define.h"
  24. #include "lzwbits.h"
  25.  
  26. #ifdef MSDOS
  27. #    define switchar(c) ((c)=='-' || (c)=='/')
  28. #else
  29. #    define switchar(c) ((c)=='/')
  30. #endif
  31.  
  32. void revector(argc, argv, n)
  33. char ***argv;
  34. {
  35.    register i;
  36.  
  37.    /* create new argument vector */
  38.    i = (int)((argc + n) * sizeof(char *));
  39.    if (argvector) {
  40.       free(argvector);
  41.       if ((argvector=(char**)realloc(argvector, i)) == NULL) outmem(stderr);
  42.    } else {
  43.       argvector = (char **)salloc(i);
  44.       /* copy origin arguments */
  45.       for (i=0; i<argc; i++) argvector[i] = (*argv)[i];
  46.    }
  47.    *argv = argvector;
  48. }
  49.  
  50. int buildarg(argc, argv, buf)
  51. char ***argv, *buf;
  52. {
  53.    register c;
  54.    register i, n;
  55.  
  56.    i = 0; n = 0;
  57.    while (buf[i]) { /* count number of words in responce file */
  58.       while ((c=buf[i])!='\0' && space(c)) ++i;
  59.       if (buf[i]) ++n; /* next word found */
  60.       while ((c=buf[i])!='\0' && !space(c)) ++i;
  61.    }
  62.    revector(argc, argv, n);
  63.    i = argc; n = 0;
  64.    while (buf[n]) {/* append new arguments */
  65.       while ((c=buf[n])!='\0' && space(c)) buf[n++] = '\0';
  66.       if (buf[n]) argvector[i++] = buf+n; /* next word found */
  67.       while ((c=buf[n])!='\0' && !space(c)) ++n;
  68.    }
  69.    return i;
  70. }
  71.  
  72. #define INDMAX 32760
  73. #define INDMIN 1024
  74. #define INDLOW 1023
  75.  
  76. int argfile(argc, argv, fname, buf)
  77. char ***argv, *fname, **buf;
  78. {
  79.    register i;
  80.    register l = 0;
  81.    register char *p;
  82.  
  83.    if (fname[0] == '-' && fname[1] == '\0') {
  84.       /* standard input */ i = 0;
  85.    } else if ((i = open(fname, O_RDONLY)) < 0 || fstat(i, &st) < 0) {
  86.       (void)fprintf(stderr, "Tar: can\'t process \'%s\'\n", fname);
  87.       done(ERRARG);
  88.    }
  89.    if ((st.st_mode & S_IFMT) == S_IFREG) {
  90.       if (st.st_size >= INDMAX) {
  91.          (void)fprintf(stderr, "Tar: \'%s\' exceeds limit in size\n", fname);
  92.          done(ERRARG);
  93.       }
  94.       p = salloc((l = (int)st.st_size) + 1);
  95. /* Note: effective text file size differs from the real one under MS-DOS */
  96.       if ((l = read(i, p, l)) < 1) {
  97.          (void)fprintf(stderr, "Tar: can\'t read \'%s\'\n", fname);
  98.          done(ERRARG);
  99.       }
  100.       (void)close(i);
  101.    } else if ((st.st_mode & S_IFMT) == S_IFCHR || /* character device */
  102.               (st.st_mode & S_IFMT) == S_IFIFO) { /* pipe */
  103.       int j, m; long s;
  104.  
  105.       for (s=0, m=INDMAX+1; m>=INDMIN; ) {
  106.          if ((p = malloc(m)) != NULL) goto ok;
  107.          m = ((m+INDLOW) & ~INDLOW) / 2;
  108.       }
  109.       outmem(stderr);
  110. ok:
  111.       s = 0;
  112.       do {
  113.          l = (int)s;
  114.          j = read(i, p+l, m-l);
  115.          s += j;
  116.       } while (j>0 && s<m);
  117.       if (j < 0) {
  118.          (void)fprintf(stderr, "Tar: error reading \'%s\'\n", fname);
  119.          done(ERRARG);
  120.       }
  121.       if (s >= m) {
  122.          if (m < INDMAX) {
  123.             outmem(stderr);
  124.          } else {
  125.             (void)fprintf(stderr,"Tar: \'%s\' exceeds limit in size\n",fname);
  126.             done(ERRARG);
  127.          }
  128.       }
  129.       if (l+1 < m) {
  130.          free(p);
  131.          if ((p = realloc(p, l+1)) == NULL) {
  132.             (void)fprintf(stderr, "Tar: error shrinking memory block\n");
  133.             done(ERRARG);
  134.          }
  135.       }
  136.    } else {
  137.       (void)fprintf(stderr, "Tar: \'%s\' not a file\n", fname);
  138.       done(ERRARG);
  139.    }
  140.    p[l] = '\0';
  141.    return buildarg(argc, argv, (*buf=p));
  142. }
  143.  
  144. int envbuild(argc, argv)
  145. char ***argv;
  146. {
  147.    register i;
  148.    register char *p;
  149.  
  150.    if ((p = getenv("TARCMD")) == NULL) return 0;
  151.    i = strlen(p); if (!i) return 0;
  152. #ifdef UNIX
  153. #  define ARGFILE
  154.    if (p[0] == '/')
  155. #endif
  156. #ifdef MSDOS
  157. #  define ARGFILE
  158.    if (((p[0] <= 'A' && p[0] >= 'Z') || (p[0] <= 'a' && p[0] >= 'z')) &&
  159.        p[1] == ':' && p[2] == '\\' || p[0]=='\\')
  160. #endif
  161. #ifdef ARGFILE
  162.    return argfile(argc, argv, p, &tarcmd);
  163. #endif
  164. #if 0 /*ndef MSDOS*/
  165.    /* Make a copy of environment variable to avoid protection problems */
  166.    tarcmd = salloc(i+1); (void)MEMCPY(tarcmd, p, i+1); p = tarcmd;
  167. #endif
  168.    return buildarg(argc, argv, p);
  169. }
  170.  
  171. /* ARGSUSED */ static void readblk(p, argv, i)
  172. char **p, **argv; int *i;
  173. {
  174.    register char *s;
  175.    register n;
  176.  
  177.    if (cblock) {
  178.       (void)fprintf(stderr, "Tar: blocksize multiply defined\n");
  179.       done(ERRARG);
  180.    }
  181.    s = argv[++*i];
  182.    for (cblock=0,n=0; digit(*s) && n<3; ++n,s++) cblock = *s-'0' + 10*cblock;
  183.    if (n>0 && n<=2) {
  184.       if      (*s == 'k' || *s == 'K') { cblock *= 2; s++; }
  185.       else if (*s == 'b' || *s == 'B') s++;
  186.       if (*s=='\0' && cblock>0 && cblock<=MAXBLOCK) /* blocksize ok */ return;
  187.    }
  188.    (void)fprintf(stderr, "Tar: bad blocksize (max is %d)\n", MAXBLOCK);
  189.    done(ERRARG);
  190. #ifdef __TURBOC__
  191.    (void)p;
  192. #endif
  193. }
  194.  
  195. #ifdef MSDOS
  196. static void readvol(p, argv, i)
  197. char **p, **argv; int *i;
  198. {
  199.    register char *s;
  200.    register n;
  201.  
  202.    if (k_flag || tapename) {
  203.       (void)fprintf(stderr, "Tar: tape device multiply defined\n");
  204.       done(ERRARG);
  205.    }
  206.    k_flag = TRUE;
  207.    s = argv[++*i];
  208.    for (volume=0, n=0; digit(*s) && n<7; ++n,s++) volume = *s-'0' + 10*volume;
  209.    if (n>0 && n<=6) {
  210.       if      (*s == 'm' || *s == 'M') { volume <<= 11; ++s; }
  211.       else if (*s == 'k' || *s == 'K') { volume += volume; ++s; }
  212.       else if (*s == 'b' || *s == 'B') ++s;
  213.       else volume += volume;
  214.       if ((volume & ~0x7FFE) == 0)
  215.          if (*s=='\0' && argdisk((int)volume >> 1) == 0)
  216.             /* diskette size ok */ return;
  217.    }
  218.    (void)fprintf(stderr, "Tar: Invalid diskette size\n");
  219.    done(ERRARG);
  220. #ifdef __TURBOC__
  221.    (void)p;
  222. #endif
  223. }
  224. #endif
  225.  
  226. /* ARGSUSED */ static void readpk(p, argv, i)
  227. char **p, **argv; int *i;
  228. {
  229.    register c;
  230.    c = (*p)[0]; if (c>='A' && c<='Z') c += 'z'-'Z';
  231.  
  232.    if (pktype != PKNONE) {
  233.       (void)fprintf(stderr,"Tar: compression method multiply defined\n");
  234.       done(ERRARG);
  235.    }
  236.    if (c == 'z' || c == ',') {
  237.       pktype = c==',' ? PKpLZW : PKfLZW;
  238.       lzwbits = BITS;
  239.       if ((*p)[1] == '9') {
  240.          *p += 1; lzwbits = 9;
  241.       } else if ((*p)[1] == '1') {
  242.          *p += 2; lzwbits = 10 + **p - '0';
  243.          if (lzwbits < 10 || lzwbits > BITS) {
  244.             (void)fprintf(stderr, "Tar: Invalid bits factor\n");
  245.             done(ERRARG);
  246.          }
  247.       }
  248.    } else {
  249.       pktype = c=='.' ? PKZIP : PKDEF;
  250.       ziplevel = 6; /* default */
  251.       if (digit((*p)[1])) {
  252.          *p += 1; ziplevel = **p - '0';
  253.       }
  254.    }
  255. #ifdef __TURBOC__
  256.    (void)argv; (void)i;
  257. #endif
  258. }
  259.  
  260. #ifdef MSDOS
  261. /* ARGSUSED */ static void devno(p, argv, i)
  262. char **p, **argv; int *i;
  263. {
  264.    ndrive = **p & 7; setdrive = TRUE;
  265. #ifdef __TURBOC__
  266.    (void)argv; (void)i;
  267. #endif
  268. }
  269. #endif
  270.  
  271. static void readxcl(p, argv, i)
  272. char **p, **argv; int *i;
  273. {
  274.    if (xcnt >= XMAX) {
  275.       (void)fprintf(stderr,"Tar: too many \'%s\'s\n", **p ? "#" : argv[*i]);
  276.       done(ERRARG);
  277.    }
  278.    xarg[xcnt++] = argv[++*i];
  279. }
  280.  
  281. #define TO_APP  '\377'
  282. #define TO_INC  '\376'
  283. #define TO_REM  '\375'
  284. #define TO_CALL '\374'
  285. #define MAXOPT  8
  286.  
  287. #ifdef MODERN
  288. #    ifdef __MEDIUM__
  289. #        define NF void far *
  290. #    else
  291. #        define NF void *
  292. #    endif
  293. #endif
  294.  
  295. static struct {
  296.    union {
  297. #ifdef NF
  298.       NF __dummy__;
  299. #endif
  300.       char *flag; char **str;
  301.       void (*fun) __ARGS__((char**, char**, int*));
  302.    } p;
  303.    char longop[MAXOPT], shortop;
  304.    char optype, xflag;
  305. } oplist[] = {
  306.    { &a_flag,  "append",  'a', TRUE,    0},
  307.    { &a_flag,  "append",  'r', TRUE,    0},
  308.    { &c_flag,  "create",  'c', TRUE,    0},
  309.    { &x_flag,  "extract", 'x', TRUE,    0},
  310.    { &t_flag,  "list",    't', TO_INC,  0},
  311.    { &y_flag,  "move",    'y', TRUE,    0},
  312.    { &u_flag,  "update",  'u', TRUE,    0},
  313.    { &d_flag,  "delete",  'd', TRUE,    0},
  314.    { &v_flag,  "verbose", 'v', TO_INC,  0},
  315.    { &w_flag,  "interact",'w', TRUE,    0},
  316.    { &i_flag,  "inhibit", 'i', TRUE,    0},
  317.    { &s_flag,  "strict",  's', TRUE,    0},
  318.    { &m_flag,  "modifica",'m', TRUE,    0},
  319.    { &j_flag,  "comment", 'j', TRUE,    0},
  320.    { &nonest,  "nonest",  'n', TRUE,    0},
  321.    { &o_flag,  "",        'o', TRUE,    0},
  322. #ifdef UNIX
  323.    { &dslash,  "",        '/', TRUE,    0},
  324.    { &l_flag,  "link-war",'l', TRUE,    0},
  325.    { &p_flag,  "permissi",'p', TRUE,    0},
  326.    { &ndrive,  "",        '0', 0,       0},
  327.    { &ndrive,  "",        '1', 1,       0},
  328.    { &ndrive,  "",        '2', 2,       0},
  329.    { &ndrive,  "",        '3', 3,       0},
  330.    { &ndrive,  "",        '4', 4,       0},
  331.    { &ndrive,  "",        '5', 5,       0},
  332.    { &ndrive,  "",        '6', 6,       0},
  333.    { &ndrive,  "",        '7', 7,       0},
  334. #endif
  335. #ifdef MSDOS
  336.    { &dslash,  "",        '\\',TRUE,    0},
  337.    { &l_flag,  "link-cop",'l', TRUE,    0},
  338.    { readvol,  "",        'k', TO_CALL, 0},
  339.    { &deldrv,  "",        ':', TRUE,    0},
  340.    { devno,    "",        '0', TO_CALL, 0},
  341.    { devno,    "",        '1', TO_CALL, 0},
  342.    { devno,    "",        '2', TO_CALL, 0},
  343.    { devno,    "",        '3', TO_CALL, 0},
  344. #endif
  345.    { &tapename,"file",    'f', TO_REM,  0},
  346.    { readblk,  "block-si",'b', TO_CALL, 0},
  347.    { NULL,     "",        '@', TO_APP,  0},
  348.    { readxcl,  "exclude", '#', TO_CALL, 0},
  349.    { readpk,   "",        ',', TO_CALL, 0},
  350.    { readpk,   "",        '.', TO_CALL, 0},
  351.    { readpk,   "",        'e', TO_CALL, 0},
  352.    { readpk,   "",        'z', TO_CALL, 0},
  353.    { &pktype,  "compress", 0,  PKpLZW,  0},
  354.    { &pktype,  "zip-arch", 0,  PKZIP,   0},
  355.    { &pktype,  "zip-file", 0,  PKDEF,   0},
  356.    { &gnuzip,  "gzip",     0,  TRUE,    0},
  357.    { &gnuzip,  "gnu",      0,  TRUE,    0},
  358. };
  359.  
  360. void cleanopt()
  361. {
  362.    register i;
  363.    for (i=0; i<dimof(oplist); i++) {
  364.       switch (oplist[i].optype) {
  365.          case TO_REM:  *(oplist[i].p.str) = NULL;
  366.          case TO_CALL: break;
  367.          default:      *(oplist[i].p.flag) = 0;
  368.       }
  369.       oplist[i].xflag = 0;
  370.    }
  371. }
  372.  
  373. static void cmpflags __ARGS__((char**, int, int));
  374.  
  375. static void cmpflags(fl, n, to_break)
  376. char *fl[];
  377. {
  378.    register i;
  379.    register x0, x1;
  380.  
  381.    for (x0=x1=0, i=0; i<n; i++) {
  382.       if (*(fl[i])) { if (*(fl[i]) & OPTFLAG) ++x1; else ++x0; }
  383.    }
  384.    if (x0 == 1) {
  385.       for (i=0; i<n; i++) if (*(fl[i]) & OPTFLAG) *(fl[i]) = 0;
  386.    } else if (x0>1 || x1>1) {
  387.       (void)fprintf(stderr, "Tar: ambiguous options\n");
  388.       if (to_break) done(ERRARG);
  389.    }
  390. }
  391.  
  392. int readopt(argc, argv, aux)
  393. int *argc; char ***argv;
  394. {
  395.    register c;
  396.    register j, k;
  397.    char lex[MAXOPT];
  398.    char *p;
  399.    int i;
  400.    char *fl[5];
  401.  
  402.    if (*argc < 1) {
  403.       (void)fprintf(stderr, "Tar: no options to read\n");
  404.       done(ERRARG);
  405.    }
  406.    for (i=0; i<*argc; i++) {
  407.       p = (*argv)[i];
  408.       if (switchar(*p)) {
  409.          if (p[1] == '\0') goto end;
  410.          if (p[1] != '-' || p[0] != '-') ++p;
  411.       } else if (*p != '+' && i) goto end;
  412.  
  413.       if (p[0]!='+' && (p[0]!='-' || p[1]!='-')) {
  414.          for (;*p; p++) {
  415.             c = *p; if (switchar(c)) goto end;
  416.             if (c>='A' && c<='Z') c += 'z'-'Z';
  417.             for (k=0; k<dimof(oplist); k++) {
  418.                if (c == oplist[k].shortop) goto sfound;
  419.             }
  420.             (void)fprintf(stderr, "Tar: bad option \'%c\'\n", *p);
  421.             done(ERRARG);
  422. sfound:     switch (oplist[k].optype) {
  423.                case TO_APP:
  424.                   if (aux) {
  425.                      appname = (*argv)[++i];
  426.                   } else {
  427.                      *argc = argfile(*argc, argv, (*argv)[++i], &responce);
  428.                   }
  429.                   break;
  430.                case TO_REM:
  431.                   if (*(oplist[k].p.str) && oplist[k].xflag == aux) {
  432.                      (void)fprintf(stderr, "Tar: duplicate \'%c\'\n", *p);
  433.                      done(ERRARG);
  434.                   }
  435.                   *(oplist[k].p.str) = (*argv)[++i];
  436.                   break;
  437.                case TO_CALL:
  438.                   (*(oplist[k].p.fun))(&p, (*argv), &i);
  439.                   break;
  440.                case TO_INC:
  441.                   if (oplist[k].xflag != aux) *(oplist[k].p.flag) = 0;
  442.                   *(oplist[k].p.flag) = aux | (1 + *(oplist[k].p.flag));
  443.                   break;
  444.                default:
  445.                   if (*(oplist[i].p.flag) && oplist[k].xflag == aux) {
  446.                      (void)fprintf(stderr, "Tar: duplicate \'%c\'\n", *p);
  447.                      done(ERRARG);
  448.                   }
  449.                   *(oplist[k].p.flag) = aux | oplist[k].optype;
  450.             }
  451.             oplist[k].xflag = aux;
  452.          }
  453.       } else {
  454.          if (p[0] == '+') p += 1; else p += 2;
  455.          for (j=0; *p; p++) {
  456.             if (j < MAXOPT) {
  457.                c = *p; if (c>='A' && c<='Z') c += 'z'-'Z';
  458.                lex[j++] = c;
  459.             }
  460.          }
  461.          if (!j) goto end;
  462.          for (k=0; k<dimof(oplist); k++) {
  463.             if (oplist[k].longop[0] &&
  464.                 0 == strncmp(oplist[k].longop, lex, j)) goto lfound;
  465.          }
  466.          (void)fprintf(stderr, "Tar: bad option \'%s\'\n", (*argv)[i]);
  467.          done(ERRARG);
  468. lfound:  switch (oplist[k].optype) {
  469.             case TO_APP:
  470.                if (aux) {
  471.                   appname = (*argv)[++i];
  472.                } else {
  473.                   *argc = argfile(*argc, argv, (*argv)[++i], &responce);
  474.                }
  475.                break;
  476.             case TO_REM:
  477.                if (*(oplist[k].p.str) && oplist[k].xflag == aux) {
  478.                   (void)fprintf(stderr, "Tar: duplicate \'%s\'\n", (*argv)[i]);
  479.                   done(ERRARG);
  480.                }
  481.                *(oplist[k].p.str) = (*argv)[++i];
  482.                break;
  483.             case TO_CALL:
  484.                (*(oplist[k].p.fun))(&p, (*argv), &i);
  485.                break;
  486.             case TO_INC:
  487.                if (oplist[k].xflag != aux) *(oplist[k].p.flag) = 0;
  488.                *(oplist[k].p.flag) = aux | (1 + *(oplist[k].p.flag));
  489.                break;
  490.             default:
  491.                if (*(oplist[k].p.flag) && oplist[k].xflag == aux) {
  492.                   (void)fprintf(stderr, "Tar: duplicate \'%s\'\n", argv[i]);
  493.                   done(ERRARG);
  494.                }
  495.                *(oplist[k].p.flag) = oplist[k].optype;
  496.          }
  497.          oplist[k].xflag = aux;
  498.       }
  499.    }
  500. end:
  501.    fl[0] = &c_flag; fl[1] = &u_flag;                  cmpflags(fl, 2, TRUE);
  502.    fl[0] = &a_flag; fl[1] = &x_flag; fl[2] = &t_flag; cmpflags(fl, 3, TRUE);
  503.    fl[0] = &d_flag; fl[3] = &c_flag;                  cmpflags(fl, 4, TRUE);
  504.    fl[0] = &d_flag; fl[1] = &i_flag;                  cmpflags(fl, 2, TRUE);
  505.    if (c_flag && !a_flag)            a_flag = c_flag;
  506.    if (u_flag && !a_flag && !x_flag) a_flag = u_flag;
  507.    if (a_flag && !c_flag) {
  508.       fl[0] = &a_flag; fl[1] = &i_flag;               cmpflags(fl, 2, TRUE);
  509.    }
  510.    fl[0] = &u_flag; fl[1] = &m_flag;                  cmpflags(fl, 2, FALSE);
  511.    return i;
  512. }
  513.