home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.os.minix
- Path: sparky!uunet!gatech!paladin.american.edu!news.univie.ac.at!hp4at!mcsun!sun4nl!star.cs.vu.nl!ast
- From: ast@cs.vu.nl (Andy Tanenbaum)
- Subject: Bug in unshar fixed
- Message-ID: <Bxrr32.Dp4@cs.vu.nl>
- Sender: news@cs.vu.nl
- Organization: Fac. Wiskunde & Informatica, VU, Amsterdam
- Date: Sun, 15 Nov 1992 17:54:37 GMT
- Lines: 350
-
-
- I found and fixed a bug in unshar. You must use this version of unshar to
- install the upcoming 1.6.24 distribution.
-
- Andy Tanenbaum (ast@cs.vu.nl)
-
- ------------------------------------------------------------------
- /* unshar - extract files from a shell archive Author: Warren Toomey */
-
- /* Copyright 1989 by Warren Toomey wkt@cs.adfa.oz.au[@uunet.uu.net]
- *
- * You may freely copy or distribute this code as long as this notice
- * remains intact.
- *
- * You may modify this code, as long as this notice remains intact, and
- * you add another notice indicating that the code has been modified.
- *
- * You may NOT sell this code or in any way profit from this code without
- * prior agreement from the author.
- *
- */
-
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
-
- /* Methods of unsharing */
- #define UNKNOWN 0
- #define BRUTAL 1
-
- /* Whitespace indicators */
- #define WHITE 0
- #define NOWHITE 1
-
- /* Leading character indicators */
- #define NOX 0
- #define YESX 1
-
- /* Misc. constants */
- #define BUFSIZE 512 /* Size of line buffer */
-
- /* Macro */
- #define getline(x,y) fgetline(stdin,x,y)
-
- /* Emulation types available */
- #define NUMTOKS 4 /* NUMTOKS must equal # of emulation types */
- #define SED 1
- #define GRES 2
- #define CAT 3
-
- /* The list of emulation types. */
- static char *token[NUMTOKS] =
- {
- "",
- "sed",
- "gres",
- "cat"
- };
-
- /* Global variables */
- int table; /* Generate a table, or extract */
- int verbose; /* Unshar verbosely - debugging */
- int numext; /* Number of files to extract */
- int binfile; /* Binary file - err indicator */
- char *exfile[100]; /* Files to extract */
-
- extern char *optarg;
-
- _PROTOTYPE(int main, (int argc, char **argv));
- _PROTOTYPE(int fgetline, (FILE * zin, int how, char *buf));
- _PROTOTYPE(char *getstring, (char *buf));
- _PROTOTYPE(int firstword, (char *buf));
- _PROTOTYPE(int mustget, (char *s1));
- _PROTOTYPE(void extract, (int how, char *file, char *end, int lead));
- _PROTOTYPE(void getnames, (char *buf, char *file, char *word));
- _PROTOTYPE(void disembowel, (void));
- _PROTOTYPE(void usage, (void));
-
- int main(argc, argv)
- int argc;
- char *argv[];
- {
- int i, c, first;
-
- FILE *zin; /* Dummy file descriptor */
- int method; /* Method of unsharing */
-
- method = BRUTAL; /* Only BRUTAL currently available */
- table = 0; /* Don't generate a table */
- verbose = 0; /* Nor be very verbose */
- numext = 0; /* Initially no files to extract */
-
- while ((c = getopt(argc, argv, "x:tbv")) != EOF) switch (c) {
- case 't':
- table = 1; /* Get the various options */
- break;
- case 'b': method = BRUTAL; break;
- case 'v': verbose = 1; break;
- case 'x':
- exfile[numext] = (char *) malloc(strlen(optarg) + 1);
- strcpy(exfile[numext++], optarg);
- break;
- default: usage();
- }
-
- if (argc == 1) {
- first = argc; /* Find first file argument */
- } else {
- for (first = 1; first < argc; first++)
- if (argv[first][0] != '-') break;
- }
-
- if (first == argc) { /* If no file argument *//* use stdin only */
- switch (method) {
- case BRUTAL:
- disembowel(); /* Unshar brutally! */
- break;
- default:
- fprintf(stderr, "unshar: Unknown method of unsharing\n");
- exit(1);
- }
- } else {
- for (i = first; i < argc; i++) { /* open stdio with every
- * file */
- if (table) printf("%s:\n", argv[i]);
- fclose(stdin);
- if ((zin = fopen(argv[i], "r")) == NULL) {
- perror("unshar");
- exit(1);
- }
- switch (method) {
- case BRUTAL:
- disembowel(); /* Unshar brutally! */
- break;
- default:
- fprintf(stderr,"unshar: Unknown method of unsharing\n");
- exit(1);
- }
- }
- }
- return(0);
- }
-
- int fgetline(zin, how, buf)
- FILE *zin;
- int how; /* Ignore leading whitespace if how=NOWHITE */
- char *buf;
- {
- /* Get a line from a file */
- int ch = 0;
-
- *buf = 0; /* Null the buffer */
- if (how == NOWHITE) { /* If skip any whitespace */
- while (((ch = fgetc(zin)) == ' ') || (ch == '\t')) ;
- if (ch == EOF) return(EOF); /* Returning EOF or 0 */
- if (ch == '\n') return (0);
- *buf++ = ch; /* Put char in buffer */
- }
- while ((ch = fgetc(zin)) != '\n') { /* Now get the line */
- if (ch == EOF) {
- *buf = 0;
- return(EOF);
- }
- if (ch > 127) {
- binfile = 1;
- return(0);
- }
- *buf++ = ch;
- }
-
- *buf = 0; /* Finally null-terminate the buffer */
- return(0); /* and return */
- }
-
- char *getstring(buf)
- char *buf;
- {
- /* Get the next string from the buffer ignoring any quotes. */
- char out[BUFSIZE];
- char *temp = out;
- char inquotes = 0, ok = 1;
- while ((*buf == ' ') || (*buf == '\t')) buf++; /* Skip whitespace */
-
- if (verbose) printf("In getstring...\n");
- *temp = 0;
- while (ok) { /* Parse line */
- switch (*buf) {
- case '\"':
- case '\'':
- buf++;
- inquotes = !inquotes; /* Toggle inquotes */
- break;
- case 0:
- case '\n': /* Stop on <, >, NULL */
- case '>': /* \n, and sometimes */
- case '<': ok = 0; break; /* space & tab */
- case '\t':
- case ' ':
- if (!inquotes) ok = 0;
- case '\\':
- if (!inquotes) {/* Ignore backquotes */
- buf++;
- break;
- }
- default:
- *temp++ = *buf++; /* Copy chars :-) */
- }
- }
- *temp = 0;
- if (verbose) printf("Returning *%s*\n", out);
- return(out);
- }
-
- int firstword(buf)
- char *buf;
- {
- /* Return token value of the first word in the buffer. Assume no leading
- * white space in the buffer.
- */
- int i;
-
- for (i = 1; i < NUMTOKS; i++)
- if (strncmp(buf, token[i], strlen(token[i])) == 0) return(i);
-
- return(UNKNOWN);
- }
-
- int mustget(s1)
- char *s1;
- {
- /* Return 1 if s1 is in he list of files to extract. Else return 0. */
- int i;
-
- if (numext == 0) return(0);
- for (i = 0; i < numext; i++)
- if (!strcmp(s1, exfile[i])) return(1);
- return(0);
- }
-
- void extract(how, file, end, lead)
- int how; /* If how==YESX, ignore 1st char on each line*/
- char *file;
- char *end;
- int lead;
- {
- /* Extract file, up until end word */
- FILE *zout;
- char line[BUFSIZE];
- char *temp;
- int ch;
-
- zout = fopen(file, "w"); /* Open output file */
- if (zout == NULL) {
- perror("unshar1");
- return;
- }
- while (1) {
- binfile = 0;
- ch = getline(WHITE, line); /* Get a line of file */
- temp = line;
- if (binfile || (ch == EOF)) {
- fprintf(zout, "%s\n", line);
- fclose(zout);
- return;
- }
- if (strcmp(temp, end) == 0) { /* If end word */
- fclose(zout); /* close the file */
- return;
- }
- if ((how == YESX) && (*temp == lead)) temp++; /* Skip any lead */
- fprintf(zout, "%s\n", temp);
- }
- }
-
- void getnames(buf, file, word) /* Get the file & end word */
- char *buf, *file, *word; /* from the buffer */
- {
- char *temp;
-
- temp = buf;
- if (verbose) printf("Getnames: buf is %s\n", buf);
-
- while (*temp != 0) { /* Scan along buffer */
- switch (*temp) { /* Get file or end word */
- case '>':
- strcpy(file, getstring(++temp)); /* Get the file name */
- break;
- case '<':
- if (*(++temp) == '<') ++temp; /* Skip 2nd < */
- strcpy(word, getstring(temp)); /* Get next word */
- break;
- default: temp++;
- }
- }
- }
-
- void disembowel()
- { /* Unshar brutally! */
- char buf[BUFSIZE]; /* Line buffer */
- char file[BUFSIZE]; /* File name */
- char word[BUFSIZE]; /* Word buffer */
- int ch, x;
-
- if (verbose) printf("Entering disembowel\n");
- x = 'X'; /* Leading X character */
- while (1) {
- binfile = 0;
- ch = getline(NOWHITE, buf); /* Get a line from file */
- if (ch == EOF) return;
- if (binfile) continue;
-
- switch (firstword(buf)) { /* Extract, depending on first word */
- case CAT:
- if (verbose) printf("About to do getnames\n");
- getnames(buf, file, word);
- if (table == 0) {
- if ((numext == 0) || (mustget(file))) {
- printf("unshar: Extracting %s\n", file);
- if (verbose)
- printf(" stopping at %s\n", word);
- extract(NOX, file, word, x);
- }
- } else
- printf(" %s\n", file);
- break;
- case GRES:
- case SED:
- if (verbose) printf("About to do getnames\n");
- getnames(buf, file, word);
- if (table == 0) {
- if ((numext == 0) || (mustget(file))) {
- printf("unshar: Extracting %s\n", file);
- if (verbose)
- printf(" stopping at %s\n", word);
- extract(YESX, file, word, x);
- }
- } else
- printf(" %s\n", file);
- break;
- default: break;
- }
- }
- }
-
- void usage()
- {
- fprintf(stderr, "Usage: unshar [-t] [-b] [-v] [-xfile] [file(s)]\n");
- exit(0);
- }
-
-