home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / auucp+-1.02 / fuucp_plus_src.lzh / unix / unshar.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-11-21  |  6.6 KB  |  263 lines

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