home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / telecom / uucp_442 / src / unix / unshar.c < prev    next >
C/C++ Source or Header  |  1990-12-27  |  7KB  |  265 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(".01");
  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    *bp,            /* temp line buffer ptr */
  145.         buf[BUFSIZE],        /* line buffer        */
  146.         prefix[STRLEN],     /* SED leader if any    */
  147.         endstring[STRLEN],    /* EOF marker        */
  148.         filename[STRLEN];    /* file name        */
  149.     int    infile = 0,        /* var to tell if we're in the middle of a
  150.                      * file or not        */
  151.         wc = 0,         /* variable to keep a word count */
  152.         fileexists = 0;     /* does the file exist? */
  153.  
  154.     if (argc == 1) {        /* check usage */
  155.         (void) printf("usage: unshar <file>\n");
  156.         exit(1);
  157.     }
  158.     if ((fp = fopen(argv[1], "r")) == NULL) {
  159.         (void) printf("Error opening input file\n");
  160.         exit(1);
  161.     }
  162.     while (fgets(buf, BUFSIZE, fp)) {
  163. #ifdef DEBUG
  164.         puts(buf);
  165. #endif DEBUG
  166.         for (bp = buf; *bp == ' '; ++bp);       /* MRR FIX, SKIP LEADING BLANKS */
  167.  
  168.         if (0 == infile) {      /* if we are not in the middle of a
  169.                      * file */
  170.             if ('#' == buf[0])      /* comment? */
  171.                 continue;
  172.  
  173.             /* Is this a CAT type shar? */
  174.             if (0 == strncmp(bp, CAT, strlen(CAT))) {
  175.                 prefix[0] = '\0';
  176.                 getendfile(bp, endstring, filename);
  177.                 if (fileexists != 0) {
  178.                     fprintf(stderr, "File exists (%s), skipping\n", filename);
  179.                     fileexists = 0;
  180.                     continue;
  181.                 }
  182.                 if (NULL == (dfp = fopen(filename, "w"))) {
  183.                     (void) printf("Error opening output file %s\n", filename);
  184.                     exit(1);
  185.                 }
  186.                 (void) printf("Extracting %s ... ", filename);
  187.                 (void) fflush(stdout);
  188.                 infile = 1;
  189.                 wc = 0;
  190.                 continue;
  191.             }
  192.             /* Is it a SED type shar? */
  193.             if (0 == strncmp(bp, SED, strlen(SED))) {
  194.                 register int i = 0, j = 0;
  195.  
  196.                 while ('^' != bp[i++])
  197.                     ;
  198.                 while ('/' != bp[i]) {
  199.                     prefix[j++] = bp[i++];
  200.                 }
  201.                 prefix[j] = '\0';
  202.                 getendfile(&bp[i], endstring, filename);
  203.                 if (fileexists != 0) {
  204.                     fprintf(stderr, "File exists (%s), skipping\n", filename);
  205.                     fileexists = 0;
  206.                     continue;
  207.                 }
  208.                 if (NULL == (dfp = fopen(filename, "w"))) {
  209.                     (void) printf("Error opening output file %s\n", filename);
  210.                     exit(1);
  211.                 }
  212.                 (void) printf("Extracting %s ... ", filename);
  213.                 (void) fflush(stdout);
  214.                 infile = 1;
  215.                 wc = 0;
  216.                 continue;
  217.             }
  218.             /* Do we want to do a test of sorts on a file? */
  219.             if (0 == strncmp(bp, TEST, strlen(TEST))) {
  220.                 register int i = 0;
  221.  
  222.                 while(!isdigit(bp[i]) && bp[i] != '-' && bp[i])
  223.                     i++;
  224.  
  225.                 if (0 != isdigit(bp[i])) {
  226.                     wordcount(&bp[i], filename, wc);
  227.                 }
  228.  
  229.                 if ('f' == bp[++i]) {
  230.                     fileexists = checkfile(&bp[++i]);
  231.                 }
  232.                 continue;
  233.             }
  234.         } else {    /* We are in the middle of a file */
  235.  
  236.             /* Are we at the end of this one? */
  237.             if (0 == strncmp(bp, endstring, strlen(endstring))) {
  238.                 (void) printf("Done\n");
  239.                 (void) fclose(dfp);
  240.                 infile = 0;
  241.                 continue;
  242.             }
  243.             /* No, then does it have a prefix? */
  244.             if ('\0' == prefix[0]) {
  245.                 fputs(bp, dfp);
  246.                 wc = wc + strlen(bp);
  247.             } else {
  248.  
  249.                 /*
  250.                  * If it does have a prefix, is there one on
  251.                  * this line?
  252.                  */
  253.                 if (0 != strncmp(bp, prefix, strlen(prefix))) {
  254.                     fputs(bp, dfp);
  255.                 } else {
  256.                     fputs(&bp[strlen(prefix)], dfp);
  257.                     wc = wc + strlen(bp) - strlen(prefix);
  258.                 }
  259.             }
  260.         }
  261.     }
  262.     (void) printf("All Done!\n");
  263.     (void) fclose(fp);
  264. }
  265.