home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 341b.lha / uucp1_v1.03d / src / compress / unshar.c < prev    next >
C/C++ Source or Header  |  1990-01-28  |  7KB  |  257 lines

  1. /*
  2.  *    unshar    -- undo a shell archive file
  3.  *    (C) Copyright June 4 1987 by Craig Norborg
  4.  *    Permission given to use this code in any form as long as it is
  5.  *    not sold or marketed in any form without the written permission
  6.  *    of its author.    Removal of this copyright notice is expressly
  7.  *    forbidden as well as any alteration of it.
  8.  */
  9. /*
  10.  *    Here is a small unshar program written to be as portable as possible.
  11.  *    It was written under Aztec C on an Amiga and tested on a VAX 11/780,
  12.  *    pdp11/70 and a Sequent Balance 21000.  Any bug reports or enhancements
  13.  *    should be reported to the author.  Some further enhancements may
  14.  *    include the correct handling of sub-directories and the handling of
  15.  *    btoa/atob type shars.  If you find a type of shar that this code
  16.  *    does not work on, please send it to me, doc@j.cc.purdue.edu.
  17.  */
  18.  
  19. #include <stdio.h>
  20. #include <ctype.h>
  21. #include "/version.h"
  22.  
  23. IDENT(".00");
  24.  
  25. #ifdef unix
  26. #include <sys/file.h>
  27. #endif unix
  28. #ifdef AMIGA
  29. #define F_OK    0
  30. #endif AMIGA
  31.  
  32. #define BUFSIZE 512        /* Max length of an input line */
  33. #define STRLEN    25        /* Max length of a file name or delimiter */
  34. #define CAT    "cat"           /* The name of the 'cat' program */
  35. #define SED    "sed"           /* The name of the 'sed' program */
  36. #define TEST    "if test"       /* Leader for test types */
  37.  
  38. /*
  39.  * This is a small routine that given the beginning of a quoted, backslashed
  40.  * or just plain string, will return it in a given buffer.
  41.  */
  42. void
  43. copystring(source, dest)
  44. char *source, *dest;
  45. {
  46.     register int i = 0;
  47.     char c;
  48.  
  49.     if ('\'' == *source || '\"' == *source) {/* Is it a quoted string? */
  50.         c = *source;
  51.         while (c != *++source)
  52.             dest[i++] = *source;
  53.         source++;
  54.     } else if ('\\' == *source) {                   /* Is it a backslashed string? */
  55.         while (!isspace(*++source))
  56.             dest[i++] = *source;
  57.     } else {                                /* Just a string */
  58.         while (!isspace(*source)) {
  59.             dest[i++] = *source;
  60.             source++;
  61.         }
  62.     }
  63.     dest[i] = '\0';
  64. }
  65.  
  66. void
  67. wordcount(buf, filename, wc)
  68. char *buf, *filename;
  69. int wc;
  70. {
  71.     if (wc != atoi(buf)) {
  72.         (void) printf("Error unsharing %s (wc should have been %d, but was %d)\n", filename, atoi(buf), wc);
  73.     }
  74. }
  75.  
  76. int
  77. checkfile(string)
  78. char *string;
  79. {
  80.     char filename[BUFSIZE];
  81.  
  82.     while (0 != isspace(*string))
  83.         string++;
  84.  
  85.     copystring(string, filename);
  86.     if (0 == access(filename, F_OK))
  87.         return 1;
  88.  
  89.     return 0;
  90. }
  91.  
  92. /*
  93.  * This is a small routine that given a 'cat' or 'sed' string, will pull out
  94.  * the end of file string and the file name
  95.  */
  96. void
  97. getendfile(line, end, file)
  98. char   *line,            /* The 'sed' or 'cat' string */
  99.        *end,            /* Place to store the end of file marker */
  100.        *file;            /* Place for the filename */
  101. {
  102.     char   *tmp, *strrchr();
  103.  
  104.     /*
  105.      * This section of code finds the end of file string.  It assumes
  106.      * that the eof string is the string of characters immediately
  107.      * following the last '<' and that it has either a '\' preceding it
  108.      * or is surrounded by single quotes.
  109.      */
  110.     tmp = (char *) strrchr(line, '<');       /* Find the last '<' on the
  111.                                              * line */
  112.     while (isspace(*++tmp))
  113.         ;    /* Do nothing */
  114.     copystring(tmp, end);
  115.  
  116.     /*
  117.      * This section of code finds the name of the file.  It assumes that
  118.      * the name of the file is the string immediately following the last
  119.      * '>' in the line
  120.      */
  121.     tmp = (char *) strrchr(line, '>');
  122.     while (isspace(*++tmp))
  123.         ;    /* Do Nothing */
  124.     copystring(tmp, file);
  125.  
  126. #ifdef DEBUG
  127.     (void) printf("EOF = %s, FILE = %s\n", end, file);
  128. #endif DEBUG
  129. }
  130.  
  131. int
  132. main(argc, argv)
  133. int    argc;
  134. char  **argv;
  135. {
  136.     FILE   *fp, *dfp, *fopen();     /* input file pointer and dest file
  137.                      * pointer */
  138.     char    buf[BUFSIZE],        /* line buffer */
  139.         prefix[STRLEN],     /* SED leader if any */
  140.         endstring[STRLEN],    /* EOF marker */
  141.         filename[STRLEN];    /* file name */
  142.     int    infile = 0,            /* var to tell if we're in the middle of a
  143.                                  * file or not */
  144.         wc = 0,             /* variable to keep a word count */
  145.             fileexists = 0;     /* does the file exist? */
  146.  
  147.     if (1 == argc) {        /* check usage */
  148.         (void) printf("usage: unshar <file>");
  149.     }
  150.     if (NULL == (fp = fopen(argv[1], "r"))) {
  151.         (void) printf("Error opening input file\n");
  152.         exit(1);
  153.     }
  154.     while (NULL != fgets(buf, BUFSIZE, fp)) {       /* while there are lines
  155.                              * to get */
  156. #ifdef DEBUG
  157.         puts(buf);
  158. #endif DEBUG
  159.  
  160.         if (0 == infile) {      /* if we are not in the middle of a
  161.                      * file */
  162.             if ('#' == buf[0])      /* comment? */
  163.                 continue;
  164.  
  165.             /* Is this a CAT type shar? */
  166.             if (0 == strncmp(buf, CAT, strlen(CAT))) {
  167.                 prefix[0] = '\0';
  168.                 getendfile(buf, endstring, filename);
  169.                 if (fileexists != 0) {
  170.                     fprintf(stderr, "File exists (%s), skipping\n", filename);
  171.                     fileexists = 0;
  172.                     continue;
  173.                 }
  174.                 if (NULL == (dfp = fopen(filename, "w"))) {
  175.                     (void) printf("Error opening output file %s\n", filename);
  176.                     exit(1);
  177.                 }
  178.                 (void) printf("Extracting %s ... ", filename);
  179.                 (void) fflush(stdout);
  180.                 infile = 1;
  181.                 wc = 0;
  182.                 continue;
  183.             }
  184.             /* Is it a SED type shar? */
  185.             if (0 == strncmp(buf, SED, strlen(SED))) {
  186.                 register int i = 0, j = 0;
  187.  
  188.                 while ('^' != buf[i++])
  189.                     ;
  190.                 while ('/' != buf[i]) {
  191.                     prefix[j++] = buf[i++];
  192.                 }
  193.                 prefix[j] = '\0';
  194.                 getendfile(&buf[i], endstring, filename);
  195.                 if (fileexists != 0) {
  196.                     fprintf(stderr, "File exists (%s), skipping\n", filename);
  197.                     fileexists = 0;
  198.                     continue;
  199.                 }
  200.                 if (NULL == (dfp = fopen(filename, "w"))) {
  201.                     (void) printf("Error opening output file %s\n", filename);
  202.                     exit(1);
  203.                 }
  204.                 (void) printf("Extracting %s ... ", filename);
  205.                 (void) fflush(stdout);
  206.                 infile = 1;
  207.                 wc = 0;
  208.                 continue;
  209.             }
  210.             /* Do we want to do a test of sorts on a file? */
  211.             if (0 == strncmp(buf, TEST, strlen(TEST))) {
  212.                 register int i = 0;
  213.  
  214.                 while(!isdigit(buf[i]) && '-' != buf[i] && NULL != buf[i])
  215.                     i++;
  216.  
  217.                 if (0 != isdigit(buf[i])) {
  218.                     wordcount(&buf[i], filename, wc);
  219.                 }
  220.  
  221.                 if ('f' == buf[++i]) {
  222.                     fileexists = checkfile(&buf[++i]);
  223.                 }
  224.                 continue;
  225.             }
  226.         } else {    /* We are in the middle of a file */
  227.  
  228.             /* Are we at the end of this one? */
  229.             if (0 == strncmp(buf, endstring, strlen(endstring))) {
  230.                 (void) printf("Done\n");
  231.                 (void) fclose(dfp);
  232.                 infile = 0;
  233.                 continue;
  234.             }
  235.             /* No, then does it have a prefix? */
  236.             if ('\0' == prefix[0]) {
  237.                 fputs(buf, dfp);
  238.                 wc = wc + strlen(buf);
  239.             } else {
  240.  
  241.                 /*
  242.                  * If it does have a prefix, is there one on
  243.                  * this line?
  244.                  */
  245.                 if (0 != strncmp(buf, prefix, strlen(prefix))) {
  246.                     fputs(buf, dfp);
  247.                 } else {
  248.                     fputs(&buf[strlen(prefix)], dfp);
  249.                     wc = wc + strlen(buf) - strlen(prefix);
  250.                 }
  251.             }
  252.         }
  253.     }
  254.     (void) printf("All Done!\n");
  255.     (void) fclose(fp);
  256. }
  257.