home *** CD-ROM | disk | FTP | other *** search
- /*
- * Unshar - extract files from shell archive
- *
- * Written by Warren Toomey [wkt@csadfa.oz.au@munnari.oz@uunet.uu.net] You may
- * freely copy or give away this source as long as this notice remains
- * intact.
- *
- * Definitions used by unshar
- */
-
-
- #include <stdio.h>
- #include <stdlib.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
-
- /* Emulation types available */
-
- #define NUMTOKS 4 /* Must change NUMTOKS to equal the */
- /* Define UNKNOWN 0 *//* number of emulation types */
- #define SED 1
- #define GRES 2
- #define CAT 3
-
- static char *token[NUMTOKS] = /*The list of emulation types ! */
- {"",
- "sed",
- "gres",
- "cat"
- };
-
-
- /* Misc. constants */
- #define BUFSIZE 512 /* Size of line buffer */
-
- /* 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 */
-
-
- #ifdef MSDOS
- /* Unix filename translation for MS-DOS */
-
- void translate_name(char *src)
- {
- char *ptr, *first = NULL, *last = NULL;
- char temp[8];
- extern char *strchr(char *, int);
-
- for ( ptr = strchr(src, 0); ptr >= src; ptr-- )
- if ( *ptr == '.' )
- {
- if ( last == NULL )
- last = ptr;
- }
- else if ( *ptr == '/' )
- {
- first = ptr + 1;
- break;
- }
-
- if ( first == NULL )
- first = src;
- if ( last == NULL )
- last = strchr(src, 0);
-
- for ( ptr = first; ptr < last; ptr++ )
- if ( *ptr == '.' )
- *ptr = '_';
-
- if ( strlen(last) > 4 )
- last[4] = 0;
-
- if ( last - first > 8 )
- {
- strcpy(temp, last);
- strcpy(first + 8, last);
- }
- }
- #endif
-
-
- #define getline(x,y) fgetline(stdin,x,y)
-
- int
- fgetline(zin, how, buf) /* Get a line from a file */
- FILE *zin;
- int how; /* Ignore leading whitespace if */
- char *buf; /* how == NOWHITE */
- {
- 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) /* Get the next string from the buffer */
- char *buf; /* 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 */
- #ifdef DEBUG
- if (verbose)
- printf("*%s*\n", out);
- #endif
- 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) /* Return token value of first word */
- char *buf; /* in the buffer. Assume no leading */
- { /* whitespace 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) /* Return 1 if s1 is in the list of */
- char *s1; /* files to extract. Return 0 if not */
- {
- 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) /* Extract file, up until end word */
- int how; /* If how==YESX, then ignore lead */
- char *file; /* character on every line */
- char *end;
- int lead;
- {
- FILE *zout;
- char line[BUFSIZE];
- char *temp;
- int ch;
-
- #ifdef MSDOS
- translate_name(file);
-
- if ( (zout = fopen(file,"r")) != NULL )
- {
- char buf[128];
-
- fclose(zout);
-
- printf("File %s already exists.\nEnter new name (press ENTER to overwrite): ", file);
-
- zout = fopen("con", "r");
- fgets(buf, sizeof(buf), zout);
- fclose(zout);
- buf[strlen(buf) - 1] = 0;
-
- if ( strlen(buf) != 0 )
- strcpy(file, buf);
- }
- #endif
- 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 ((how == YESX) && (*temp == lead))
- temp++; /* Skip any lead */
-
- if (strcmp(temp, end) == 0) { /* If end word */
- fclose(zout); /* close the file */
- return;
- }
- 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;
- }
- }
- }
-
-
- char *myname;
-
- usage()
- {
- printf("\nUsage: %s [-t] [-b] [-v] [-xfile] [file(s)]\n", myname);
-
- printf(
- "\n -t Do not extract files, just list the files in the archive(s)."
- "\n -b Extract files from the archive(s) brutally, with no regard at all to"
- "\n things such as testing if the file exists, or chmoding the file etc."
- "\n -v Be verbose. Used only for debugging purposes."
- "\n -x Extract the named file from the shell archive."
- "\n -h Show this text.\n");
-
- exit(0);
- }
-
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- extern int optind;
- extern char *optarg;
- int i, c, first;
-
- FILE *zin; /* Dummy file descriptor */
- int method; /* Method of unsharing */
-
- myname = argv[0];
- 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:tbvh")) != 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 */
- if ( isatty(fileno(stdin)) )
- usage();
-
- 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("unshar2");
- exit(1);
- }
- switch (method) {
- case BRUTAL:
- disembowel(); /* Unshar brutally! */
- break;
- default:
- fprintf(stderr, "unshar: Unknown method of unsharing\n");
- exit(1);
- }
- }
- exit(0);
- }
-