home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / os / minix / 4770 next >
Encoding:
Text File  |  1992-11-15  |  8.4 KB  |  361 lines

  1. Newsgroups: comp.os.minix
  2. Path: sparky!uunet!gatech!paladin.american.edu!news.univie.ac.at!hp4at!mcsun!sun4nl!star.cs.vu.nl!ast
  3. From: ast@cs.vu.nl (Andy Tanenbaum)
  4. Subject: Bug in unshar fixed
  5. Message-ID: <Bxrr32.Dp4@cs.vu.nl>
  6. Sender: news@cs.vu.nl
  7. Organization: Fac. Wiskunde & Informatica, VU, Amsterdam
  8. Date: Sun, 15 Nov 1992 17:54:37 GMT
  9. Lines: 350
  10.  
  11.  
  12. I found and fixed a bug in unshar.  You must use this version of unshar to
  13. install the upcoming 1.6.24 distribution.
  14.  
  15. Andy Tanenbaum (ast@cs.vu.nl)
  16.  
  17. ------------------------------------------------------------------
  18. /* unshar - extract files from a shell archive    Author: Warren Toomey */
  19.  
  20. /* Copyright 1989 by Warren Toomey    wkt@cs.adfa.oz.au[@uunet.uu.net]
  21.  *
  22.  * You may freely copy or distribute this code as long as this notice
  23.  * remains intact.
  24.  *
  25.  * You may modify this code, as long as this notice remains intact, and
  26.  * you add another notice indicating that the code has been modified.
  27.  *
  28.  * You may NOT sell this code or in any way profit from this code without
  29.  * prior agreement from the author.
  30.  *
  31.  */
  32.  
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <stdio.h>
  36.  
  37. /* Methods of unsharing */
  38. #define UNKNOWN    0
  39. #define BRUTAL    1
  40.  
  41. /* Whitespace indicators */
  42. #define WHITE    0
  43. #define NOWHITE 1
  44.  
  45. /* Leading character indicators */
  46. #define NOX    0
  47. #define YESX    1
  48.  
  49. /* Misc. constants */
  50. #define BUFSIZE    512        /* Size of line buffer */
  51.  
  52. /* Macro */
  53. #define getline(x,y)    fgetline(stdin,x,y)
  54.  
  55. /* Emulation types available */
  56. #define NUMTOKS    4        /* NUMTOKS must equal # of emulation types */
  57. #define SED       1
  58. #define GRES        2
  59. #define CAT       3
  60.  
  61. /* The list of emulation types. */
  62. static char *token[NUMTOKS] =
  63. {
  64.  "",
  65.  "sed",
  66.  "gres",
  67.  "cat"
  68. };
  69.  
  70. /* Global variables */
  71. int table;            /* Generate a table, or extract */
  72. int verbose;            /* Unshar verbosely - debugging */
  73. int numext;            /* Number of files to extract */
  74. int binfile;            /* Binary file - err indicator */
  75. char *exfile[100];        /* Files to extract */
  76.  
  77. extern char *optarg;
  78.  
  79. _PROTOTYPE(int main, (int argc, char **argv));
  80. _PROTOTYPE(int fgetline, (FILE * zin, int how, char *buf));
  81. _PROTOTYPE(char *getstring, (char *buf));
  82. _PROTOTYPE(int firstword, (char *buf));
  83. _PROTOTYPE(int mustget, (char *s1));
  84. _PROTOTYPE(void extract, (int how, char *file, char *end, int lead));
  85. _PROTOTYPE(void getnames, (char *buf, char *file, char *word));
  86. _PROTOTYPE(void disembowel, (void));
  87. _PROTOTYPE(void usage, (void));
  88.  
  89. int main(argc, argv)
  90. int argc;
  91. char *argv[];
  92. {
  93.   int i, c, first;
  94.  
  95.   FILE *zin;            /* Dummy file descriptor */
  96.   int method;            /* Method of unsharing */
  97.  
  98.   method = BRUTAL;        /* Only BRUTAL currently available */
  99.   table = 0;            /* Don't generate a table */
  100.   verbose = 0;            /* Nor be very verbose */
  101.   numext = 0;            /* Initially no files to extract */
  102.  
  103.   while ((c = getopt(argc, argv, "x:tbv")) != EOF) switch (c) {
  104.         case 't':
  105.         table = 1;    /* Get the various options */
  106.         break;
  107.         case 'b':    method = BRUTAL;    break;
  108.         case 'v':    verbose = 1;    break;
  109.         case 'x':
  110.         exfile[numext] = (char *) malloc(strlen(optarg) + 1);
  111.         strcpy(exfile[numext++], optarg);
  112.         break;
  113.         default:    usage();
  114.     }
  115.  
  116.   if (argc == 1) {
  117.     first = argc;        /* Find first file argument */
  118.   } else {
  119.     for (first = 1; first < argc; first++)
  120.         if (argv[first][0] != '-') break;
  121.   }
  122.  
  123.   if (first == argc) {        /* If no file argument *//* use stdin only */
  124.     switch (method) {
  125.         case BRUTAL:
  126.         disembowel();    /* Unshar brutally! */
  127.         break;
  128.         default:
  129.         fprintf(stderr, "unshar: Unknown method of unsharing\n");
  130.         exit(1);
  131.     }
  132.   } else {
  133.     for (i = first; i < argc; i++) {    /* open stdio with every
  134.                          * file */
  135.         if (table) printf("%s:\n", argv[i]);
  136.         fclose(stdin);
  137.         if ((zin = fopen(argv[i], "r")) == NULL) {
  138.             perror("unshar");
  139.             exit(1);
  140.         }
  141.         switch (method) {
  142.             case BRUTAL:
  143.             disembowel();    /* Unshar brutally! */
  144.             break;
  145.             default:
  146.             fprintf(stderr,"unshar: Unknown method of unsharing\n");
  147.             exit(1);
  148.         }
  149.     }
  150.   }
  151.   return(0);
  152. }
  153.  
  154. int fgetline(zin, how, buf)
  155. FILE *zin;
  156. int how;            /* Ignore leading whitespace if how=NOWHITE */
  157. char *buf;
  158. {
  159. /* Get a line from a file */
  160.   int ch = 0;
  161.  
  162.   *buf = 0;            /* Null the buffer */
  163.   if (how == NOWHITE) {        /* If skip any whitespace */
  164.     while (((ch = fgetc(zin)) == ' ') || (ch == '\t'))    ;
  165.     if (ch == EOF) return(EOF);    /* Returning EOF or 0 */
  166.     if (ch == '\n') return (0);
  167.     *buf++ = ch;        /* Put char in buffer */
  168.   }
  169.   while ((ch = fgetc(zin)) != '\n') {    /* Now get the line */
  170.     if (ch == EOF) {
  171.         *buf = 0;
  172.         return(EOF);
  173.     }
  174.     if (ch > 127) {
  175.         binfile = 1;
  176.         return(0);
  177.     }
  178.     *buf++ = ch;
  179.   }
  180.  
  181.   *buf = 0;            /* Finally null-terminate the buffer */
  182.   return(0);            /* and return */
  183. }
  184.  
  185. char *getstring(buf)
  186. char *buf;
  187. {
  188. /* Get the next string from the buffer ignoring any quotes. */
  189.   char out[BUFSIZE];
  190.   char *temp = out;
  191.   char inquotes = 0, ok = 1;
  192.   while ((*buf == ' ') || (*buf == '\t')) buf++;    /* Skip whitespace */
  193.  
  194.   if (verbose) printf("In getstring...\n");
  195.   *temp = 0;
  196.   while (ok) {            /* Parse line */
  197.     switch (*buf) {
  198.         case '\"':
  199.         case '\'':
  200.         buf++;
  201.         inquotes = !inquotes;    /* Toggle inquotes */
  202.         break;
  203.         case 0:
  204.         case '\n':        /* Stop on <, >, NULL */
  205.         case '>':        /* \n, and sometimes */
  206.         case '<':    ok = 0;    break;    /* space & tab */
  207.         case '\t':
  208.         case ' ':
  209.         if (!inquotes) ok = 0;
  210.         case '\\':
  211.         if (!inquotes) {/* Ignore backquotes */
  212.             buf++;
  213.             break;
  214.         }
  215.         default:
  216.         *temp++ = *buf++;    /* Copy chars :-) */
  217.     }
  218.   }
  219.   *temp = 0;
  220.   if (verbose) printf("Returning *%s*\n", out);
  221.   return(out);
  222. }
  223.  
  224. int firstword(buf)
  225. char *buf;
  226. {
  227. /* Return token value of the first word in the buffer.  Assume no leading
  228.  * white space in the buffer.
  229.  */
  230.   int i;
  231.  
  232.   for (i = 1; i < NUMTOKS; i++)
  233.     if (strncmp(buf, token[i], strlen(token[i])) == 0) return(i);
  234.  
  235.   return(UNKNOWN);
  236. }
  237.  
  238. int mustget(s1)
  239. char *s1;
  240. {
  241. /* Return 1 if s1 is in he list of files to extract.  Else return 0. */
  242.   int i;
  243.  
  244.   if (numext == 0) return(0);
  245.   for (i = 0; i < numext; i++)
  246.     if (!strcmp(s1, exfile[i])) return(1);
  247.   return(0);
  248. }
  249.  
  250. void extract(how, file, end, lead)
  251. int how;            /* If how==YESX, ignore 1st char on each line*/
  252. char *file;
  253. char *end;
  254. int lead;
  255. {
  256. /* Extract file, up until end word */
  257.   FILE *zout;
  258.   char line[BUFSIZE];
  259.   char *temp;
  260.   int ch;
  261.  
  262.   zout = fopen(file, "w");    /* Open output file */
  263.   if (zout == NULL) {
  264.     perror("unshar1");
  265.     return;
  266.   }
  267.   while (1) {
  268.     binfile = 0;
  269.     ch = getline(WHITE, line);    /* Get a line of file */
  270.     temp = line;
  271.     if (binfile || (ch == EOF)) {
  272.         fprintf(zout, "%s\n", line);
  273.         fclose(zout);
  274.         return;
  275.     }
  276.     if (strcmp(temp, end) == 0) {    /* If end word */
  277.         fclose(zout);    /* close the file */
  278.         return;
  279.     }
  280.     if ((how == YESX) && (*temp == lead)) temp++;    /* Skip any lead */
  281.     fprintf(zout, "%s\n", temp);
  282.   }
  283. }
  284.  
  285. void getnames(buf, file, word)    /* Get the file & end word */
  286. char *buf, *file, *word;    /* from the buffer */
  287. {
  288.   char *temp;
  289.  
  290.   temp = buf;
  291.   if (verbose) printf("Getnames: buf is %s\n", buf);
  292.  
  293.   while (*temp != 0) {        /* Scan along buffer */
  294.     switch (*temp) {    /* Get file or end word */
  295.         case '>':
  296.         strcpy(file, getstring(++temp));    /* Get the file name */
  297.         break;
  298.         case '<':
  299.         if (*(++temp) == '<') ++temp;    /* Skip 2nd < */
  300.         strcpy(word, getstring(temp));    /* Get next word */
  301.         break;
  302.         default:    temp++;
  303.     }
  304.   }
  305. }
  306.  
  307. void disembowel()
  308. {                /* Unshar brutally! */
  309.   char buf[BUFSIZE];        /* Line buffer */
  310.   char file[BUFSIZE];        /* File name */
  311.   char word[BUFSIZE];        /* Word buffer */
  312.   int ch, x;
  313.  
  314.   if (verbose) printf("Entering disembowel\n");
  315.   x = 'X';            /* Leading X character */
  316.   while (1) {
  317.     binfile = 0;
  318.     ch = getline(NOWHITE, buf);    /* Get a line from file */
  319.     if (ch == EOF) return;
  320.     if (binfile) continue;
  321.  
  322.     switch (firstword(buf)) {    /* Extract, depending on first word */
  323.         case CAT:
  324.         if (verbose) printf("About to do getnames\n");
  325.         getnames(buf, file, word);
  326.         if (table == 0) {
  327.             if ((numext == 0) || (mustget(file))) {
  328.                 printf("unshar: Extracting  %s\n", file);
  329.                 if (verbose)
  330.                     printf("      stopping at %s\n", word);
  331.                 extract(NOX, file, word, x);
  332.             }
  333.         } else
  334.             printf("  %s\n", file);
  335.         break;
  336.         case GRES:
  337.         case SED:
  338.         if (verbose) printf("About to do getnames\n");
  339.         getnames(buf, file, word);
  340.         if (table == 0) {
  341.             if ((numext == 0) || (mustget(file))) {
  342.                 printf("unshar: Extracting  %s\n", file);
  343.                 if (verbose)
  344.                     printf("      stopping at %s\n", word);
  345.                 extract(YESX, file, word, x);
  346.             }
  347.         } else
  348.             printf("  %s\n", file);
  349.         break;
  350.         default:    break;
  351.     }
  352.   }
  353. }
  354.  
  355. void usage()
  356. {
  357.   fprintf(stderr, "Usage: unshar [-t] [-b] [-v] [-xfile] [file(s)]\n");
  358.   exit(0);
  359. }
  360.  
  361.