home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / duucp-1.17 / AU-117b4-src.lha / src / unix / unshar.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-24  |  6.7 KB  |  271 lines

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