home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / UNSHAR.ZIP / UNSHAR.C < prev    next >
C/C++ Source or Header  |  1990-07-17  |  10KB  |  449 lines

  1. /*
  2.  * Unshar - extract files from shell archive
  3.  *
  4.  * Written by Warren Toomey [wkt@csadfa.oz.au@munnari.oz@uunet.uu.net] You may
  5.  * freely copy or give away this source as long as this notice remains
  6.  * intact.
  7.  *
  8.  * Definitions used by unshar
  9.  */
  10.  
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14.  
  15. /* Methods of unsharing */
  16. #define UNKNOWN    0
  17. #define BRUTAL    1
  18.  
  19. /* Whitespace indicators */
  20. #define WHITE    0
  21. #define NOWHITE 1
  22.  
  23. /* Leading character indicators */
  24. #define NOX    0
  25. #define YESX    1
  26.  
  27. /* Emulation types available */
  28.  
  29. #define NUMTOKS    4        /* Must change NUMTOKS to equal the */
  30. /* Define UNKNOWN  0 *//* number of emulation types */
  31. #define SED       1
  32. #define GRES        2
  33. #define CAT       3
  34.  
  35. static char    *token[NUMTOKS] = /*The list of emulation types ! */
  36. {"",
  37.  "sed",
  38.  "gres",
  39.  "cat"
  40. };
  41.  
  42.  
  43. /* Misc. constants */
  44. #define BUFSIZE    512        /* Size of line buffer */
  45.  
  46. /* Global variables */
  47. int             table;        /* Generate a table, or extract */
  48. int             verbose;    /* Unshar verbosely - debugging */
  49. int             numext;        /* Number of files to extract */
  50. int             binfile;    /* Binary file - err indicator */
  51. char           *exfile[100];    /* Files to extract */
  52.  
  53.  
  54. #ifdef MSDOS
  55. /* Unix filename translation for MS-DOS */
  56.  
  57. void translate_name(char *src)
  58. {
  59.   char *ptr, *first = NULL, *last = NULL;
  60.   char temp[8];
  61.   extern char *strchr(char *, int);
  62.  
  63.   for ( ptr = strchr(src, 0); ptr >= src; ptr-- )
  64.     if ( *ptr == '.' )
  65.     {
  66.       if ( last == NULL )
  67.         last = ptr;
  68.     }
  69.     else if ( *ptr == '/' )
  70.     {
  71.       first = ptr + 1;
  72.       break;
  73.     }
  74.  
  75.   if ( first == NULL )
  76.     first = src;
  77.   if ( last == NULL )
  78.     last = strchr(src, 0);
  79.  
  80.   for ( ptr = first; ptr < last; ptr++ )
  81.     if ( *ptr == '.' )
  82.       *ptr = '_';
  83.  
  84.   if ( strlen(last) > 4 )
  85.     last[4] = 0;
  86.  
  87.   if ( last - first > 8 )
  88.   {
  89.     strcpy(temp, last);
  90.     strcpy(first + 8, last);
  91.   }
  92. }
  93. #endif
  94.  
  95.  
  96. #define getline(x,y)    fgetline(stdin,x,y)
  97.  
  98. int
  99. fgetline(zin, how, buf)        /* Get a line from a file */
  100.     FILE           *zin;
  101.     int             how;    /* Ignore leading whitespace if */
  102.     char           *buf;    /* how == NOWHITE */
  103. {
  104.     int             ch = 0;
  105.  
  106.     *buf = 0;        /* Null the buffer */
  107.     if (how == NOWHITE) {    /* If skip any whitespace */
  108.         while (((ch = fgetc(zin)) == ' ') || (ch == '\t'));
  109.         if (ch == EOF)
  110.             return (EOF);    /* Returning EOF or 0 */
  111.         if (ch == '\n')
  112.             return (0);
  113.         *buf++ = ch;    /* Put char in buffer */
  114.     }
  115.     while ((ch = fgetc(zin)) != '\n') {    /* Now get the line */
  116.         if (ch == EOF) {
  117.             *buf = 0;
  118.             return (EOF);
  119.         }
  120.         if (ch > 127) {
  121.             binfile = 1;
  122.             return (0);
  123.         }
  124.         *buf++ = ch;
  125.     }
  126.  
  127.     *buf = 0;        /* Finally null-terminate the buffer */
  128.     return (0);        /* and return */
  129. }
  130.  
  131.  
  132.  
  133. char           *
  134. getstring(buf)            /* Get the next string from the buffer */
  135.     char           *buf;    /* ignoring any quotes */
  136. {
  137.     char            out[BUFSIZE];
  138.     char           *temp = out;
  139.     char            inquotes = 0, ok = 1;
  140.     while ((*buf == ' ') || (*buf == '\t'))
  141.         buf++;        /* Skip whitespace */
  142.  
  143.     if (verbose)
  144.         printf("In getstring...\n");
  145.     *temp = 0;
  146.     while (ok) {        /* Parse line */
  147. #ifdef DEBUG
  148.         if (verbose)
  149.             printf("*%s*\n", out);
  150. #endif
  151.         switch (*buf) {
  152.         case '\"':
  153.         case '\'':
  154.             buf++;
  155.             inquotes = !inquotes;    /* Toggle inquotes */
  156.             break;
  157.         case 0:
  158.         case '\n':    /* Stop on <, >, NULL */
  159.         case '>':    /* \n, and sometimes */
  160.         case '<':
  161.             ok = 0;
  162.             break;    /* space & tab */
  163.         case '\t':
  164.         case ' ':
  165.             if (!inquotes)
  166.                 ok = 0;
  167.         case '\\':
  168.             if (!inquotes) {    /* Ignore backquotes */
  169.                 buf++;
  170.                 break;
  171.             }
  172.         default:
  173.             *temp++ = *buf++;    /* Copy chars :-) */
  174.         }
  175.     }
  176.     *temp = 0;
  177.     if (verbose)
  178.         printf("Returning *%s*\n", out);
  179.     return (out);
  180. }
  181.  
  182.  
  183. int
  184. firstword(buf)            /* Return token value of first word */
  185.     char           *buf;    /* in the buffer. Assume no leading */
  186. {                /* whitespace in the buffer */
  187.     int             i;
  188.  
  189.     for (i = 1; i < NUMTOKS; i++)
  190.         if (strncmp(buf, token[i], strlen(token[i])) == 0)
  191.             return (i);
  192.  
  193.     return (UNKNOWN);
  194. }
  195.  
  196.  
  197. int
  198. mustget(s1)            /* Return 1 if s1 is in the list of  */
  199.     char           *s1;    /* files to extract. Return 0 if not */
  200. {
  201.     int             i;
  202.  
  203.     if (numext == 0)
  204.         return (0);
  205.     for (i = 0; i < numext; i++)
  206.         if (!strcmp(s1, exfile[i]))
  207.             return (1);
  208.     return (0);
  209. }
  210.  
  211.  
  212. void
  213. extract(how, file, end, lead)    /* Extract file, up until end word */
  214.     int             how;    /* If how==YESX, then ignore lead   */
  215.     char           *file;    /* character on every line */
  216.     char           *end;
  217.     int             lead;
  218. {
  219.     FILE           *zout;
  220.     char            line[BUFSIZE];
  221.     char           *temp;
  222.     int             ch;
  223.  
  224. #ifdef MSDOS
  225.   translate_name(file);
  226.  
  227.   if ( (zout = fopen(file,"r")) != NULL )
  228.   {
  229.     char buf[128];
  230.  
  231.     fclose(zout);
  232.  
  233.     printf("File %s already exists.\nEnter new name (press ENTER to overwrite): ", file);
  234.  
  235.     zout = fopen("con", "r");
  236.     fgets(buf, sizeof(buf), zout);
  237.     fclose(zout);
  238.     buf[strlen(buf) - 1] = 0;
  239.  
  240.     if ( strlen(buf) != 0 )
  241.       strcpy(file, buf);
  242.   }
  243. #endif
  244.     zout = fopen(file, "w");/* Open output file */
  245.     if (zout == NULL) {
  246.         perror("unshar1");
  247.         return;
  248.     }
  249.     while (1) {
  250.         binfile = 0;
  251.         ch = getline(WHITE, line);    /* Get a line of file */
  252.         temp = line;
  253.         if (binfile || (ch == EOF)) {
  254.             fprintf(zout, "%s\n", line);
  255.             fclose(zout);
  256.             return;
  257.         }
  258.         if ((how == YESX) && (*temp == lead))
  259.             temp++;    /* Skip any lead */
  260.  
  261.         if (strcmp(temp, end) == 0) {    /* If end word */
  262.             fclose(zout);    /* close the file */
  263.             return;
  264.         }
  265.         fprintf(zout, "%s\n", temp);
  266.     }
  267. }
  268.  
  269.  
  270. void
  271. getnames(buf, file, word)    /* Get the file & end word */
  272.     char           *buf, *file, *word;    /* from the buffer */
  273. {
  274.     char           *temp;
  275.  
  276.     temp = buf;
  277.     if (verbose)
  278.         printf("Getnames: buf is %s\n", buf);
  279.  
  280.     while (*temp != 0) {    /* Scan along buffer */
  281.         switch (*temp) {/* Get file or end word */
  282.         case '>':
  283.             strcpy(file, getstring(++temp));    /* Get the file name */
  284.             break;
  285.         case '<':
  286.             if (*(++temp) == '<')
  287.                 ++temp;    /* Skip 2nd < */
  288.             strcpy(word, getstring(temp));    /* Get next word */
  289.             break;
  290.         default:
  291.             temp++;
  292.         }
  293.     }
  294. }
  295.  
  296.  
  297.  
  298. void
  299. disembowel()
  300. {                /* Unshar brutally! */
  301.     char            buf[BUFSIZE];    /* Line buffer */
  302.     char            file[BUFSIZE];    /* File name */
  303.     char            word[BUFSIZE];    /* Word buffer */
  304.     int             ch, x;
  305.  
  306.     if (verbose)
  307.         printf("Entering disembowel\n");
  308.     x = 'X';        /* Leading X character */
  309.     while (1) {
  310.         binfile = 0;
  311.         ch = getline(NOWHITE, buf);    /* Get a line from file */
  312.         if (ch == EOF)
  313.             return;
  314.         if (binfile)
  315.             continue;
  316.  
  317.         switch (firstword(buf)) {    /* Extract, depending on
  318.                          * first word */
  319.         case CAT:
  320.             if (verbose)
  321.                 printf("About to do getnames\n");
  322.             getnames(buf, file, word);
  323.             if (table == 0) {
  324.                 if ((numext == 0) || (mustget(file))) {
  325.                     printf("unshar: Extracting  %s\n", file);
  326.                     if (verbose)
  327.                         printf("        stopping at %s\n", word);
  328.                     extract(NOX, file, word, x);
  329.                 }
  330.             } else
  331.                 printf("  %s\n", file);
  332.             break;
  333.         case GRES:
  334.         case SED:
  335.             if (verbose)
  336.                 printf("About to do getnames\n");
  337.             getnames(buf, file, word);
  338.             if (table == 0) {
  339.                 if ((numext == 0) || (mustget(file))) {
  340.                     printf("unshar: Extracting  %s\n", file);
  341.                     if (verbose)
  342.                         printf("        stopping at %s\n", word);
  343.                     extract(YESX, file, word, x);
  344.                 }
  345.             } else
  346.                 printf("  %s\n", file);
  347.             break;
  348.         default:
  349.             break;
  350.         }
  351.     }
  352. }
  353.  
  354.  
  355. char *myname;
  356.  
  357. usage()
  358. {
  359.   printf("\nUsage: %s [-t] [-b] [-v] [-xfile] [file(s)]\n", myname);
  360.  
  361.   printf(
  362.   "\n  -t  Do not extract files, just list the files in the archive(s)."
  363.   "\n  -b  Extract files from the archive(s) brutally, with no regard at all to"
  364.   "\n      things such as testing if the file exists, or chmoding the file etc."
  365.   "\n  -v  Be verbose. Used only for debugging purposes."
  366.   "\n  -x  Extract the named file from the shell archive."
  367.   "\n  -h  Show this text.\n");
  368.  
  369.   exit(0);
  370. }
  371.  
  372.  
  373. main(argc, argv)
  374.     int             argc;
  375.     char           *argv[];
  376. {
  377.     extern int      optind;
  378.     extern char    *optarg;
  379.     int             i, c, first;
  380.  
  381.     FILE           *zin;    /* Dummy file descriptor */
  382.     int             method;    /* Method of unsharing */
  383.  
  384.         myname = argv[0];
  385.     method = BRUTAL;    /* Only BRUTAL currently available */
  386.     table = 0;        /* Don't generate a table */
  387.     verbose = 0;        /* Nor be very verbose */
  388.     numext = 0;        /* Initially no files to extract */
  389.  
  390.         while ((c = getopt(argc, argv, "x:tbvh")) != EOF)
  391.         switch (c) {
  392.         case 't':
  393.             table = 1;    /* Get the various options */
  394.             break;
  395.         case 'b':
  396.             method = BRUTAL;
  397.             break;
  398.         case 'v':
  399.             verbose = 1;
  400.             break;
  401.         case 'x':
  402.             exfile[numext] = (char *) malloc(strlen(optarg) + 1);
  403.             strcpy(exfile[numext++], optarg);
  404.             break;
  405.         default:
  406.             usage();
  407.         }
  408.  
  409.     if (argc == 1)
  410.         first = argc;    /* Find first file argument */
  411.     else
  412.         for (first = 1; first < argc; first++)
  413.             if (argv[first][0] != '-')
  414.                 break;
  415.  
  416.         if (first == argc) {    /* If no file argument *//* use stdin only */
  417.                 if ( isatty(fileno(stdin)) )
  418.                   usage();
  419.  
  420.         switch (method) {
  421.         case BRUTAL:
  422.             disembowel();    /* Unshar brutally! */
  423.             break;
  424.         default:
  425.             fprintf(stderr, "unshar: Unknown method of unsharing\n");
  426.             exit(1);
  427.         }
  428.     } else
  429.         for (i = first; i < argc; i++) {    /* open stdio with every
  430.                              * file */
  431.             if (table)
  432.                 printf("%s:\n", argv[i]);
  433.             fclose(stdin);
  434.             if ((zin = fopen(argv[i], "r")) == NULL) {
  435.                 perror("unshar2");
  436.                 exit(1);
  437.             }
  438.             switch (method) {
  439.             case BRUTAL:
  440.                 disembowel();    /* Unshar brutally! */
  441.                 break;
  442.             default:
  443.                 fprintf(stderr, "unshar: Unknown method of unsharing\n");
  444.                 exit(1);
  445.             }
  446.         }
  447.     exit(0);
  448. }
  449.