home *** CD-ROM | disk | FTP | other *** search
- /*
- * UNSHAR.C
- *
- * unshar -- undo a shell archive file
- * (C) Copyright June 4 1987 by Craig Norborg
- *
- * Permission given to use this code in any form as long as it is
- * not sold or marketed in any form without the written permission
- * of its author. Removal of this copyright notice is expressly
- * forbidden as well as any alteration of it.
- */
-
- /*
- * Here is a small unshar program written to be as portable as possible.
- * It was written under Aztec C on an Amiga and tested on a VAX 11/780,
- * pdp11/70 and a Sequent Balance 21000. Any bug reports or enhancements
- * should be reported to the author. Some further enhancements may
- * include the correct handling of sub-directories and the handling of
- * btoa/atob type shars. If you find a type of shar that this code
- * does not work on, please send it to me, doc@j.cc.purdue.edu.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <string.h>
- #include "version.h"
-
- IDENT (".02");
-
- #include <fcntl.h>
-
- #if !defined (F_OK)
- /* for access() */
- #define F_OK 0
- #endif
-
- #define BUFSIZE 512 /* Max length of an input line */
- #define STRLEN 25 /* Max length of a file name or delimiter */
- #define CAT "cat" /* The name of the 'cat' program */
- #define SED "sed" /* The name of the 'sed' program */
- #define TEST "if test" /* Leader for test types */
-
- /*
- * This is a small routine that given the beginning of a quoted, backslashed
- * or just plain string, will return it in a given buffer.
- */
- void
- copystring(char *source, char *dest)
- {
- register int i = 0;
- char c;
-
- if ('\'' == *source || '\"' == *source) {/* Is it a quoted string? */
- c = *source;
- while (c != *++source)
- dest[i++] = *source;
- source++;
- } else if ('\\' == *source) { /* Is it a backslashed string? */
- while (!isspace(*++source))
- dest[i++] = *source;
- } else { /* Just a string */
- while (!isspace(*source)) {
- dest[i++] = *source;
- source++;
- }
- }
- dest[i] = '\0';
- }
-
- void
- wordcount(char *buf, char *filename, int wc)
- {
- if (wc != atoi(buf)) {
- (void) printf("Error unsharing %s (wc should have been %d, but was %d)\n", filename, atoi(buf), wc);
- }
- }
-
- int
- checkfile(char *string)
- {
- char filename[BUFSIZE];
-
- while (0 != isspace(*string))
- string++;
-
- copystring(string, filename);
- if (0 == access(filename, F_OK))
- return 1;
-
- return 0;
- }
-
- /*
- * This is a small routine that given a 'cat' or 'sed' string, will pull out
- * the end of file string and the file name
- */
- void
- getendfile(char *line, char *end, char *file)
- /*
- ** getendfile
- **
- ** line: the 'sed' or 'cat' string
- ** end: place to store EOF marker
- ** file: place to store filename
- */
- {
- char *tmp;
-
- /*
- * This section of code finds the end of file string. It assumes
- * that the eof string is the string of characters immediately
- * following the last '<' and that it has either a '\' preceding it
- * or is surrounded by single quotes.
- */
- tmp = (char *) strrchr(line, '<'); /* Find the last '<' on the
- * line */
- while (isspace(*++tmp))
- ; /* Do nothing */
- copystring(tmp, end);
-
- /*
- * This section of code finds the name of the file. It assumes that
- * the name of the file is the string immediately following the last
- * '>' in the line
- */
- tmp = (char *) strrchr(line, '>');
- while (isspace(*++tmp))
- ; /* Do Nothing */
- copystring(tmp, file);
-
- #ifdef DEBUG
- (void) printf("EOF = %s, FILE = %s\n", end, file);
- #endif
- }
-
- int
- main(int argc, char **argv)
- {
- FILE *fp, *dfp; /* input file pointer and dest file
- * pointer */
- char *bp, /* temp line buffer ptr */
- buf[BUFSIZE], /* line buffer */
- prefix[STRLEN], /* SED leader if any */
- endstring[STRLEN], /* EOF marker */
- filename[STRLEN]; /* file name */
- int infile = 0, /* var to tell if we're in the middle of a
- * file or not */
- wc = 0, /* variable to keep a word count */
- fileexists = 0; /* does the file exist? */
-
- if (argc == 1) { /* check usage */
- (void) printf("usage: unshar <file>\n");
- exit(1);
- }
- if ((fp = fopen(argv[1], "r")) == NULL) {
- (void) printf("Error opening input file\n");
- exit(1);
- }
- while (fgets(buf, BUFSIZE, fp)) {
- #ifdef DEBUG
- puts(buf);
- #endif
- #ifdef NOTDEF
- /* XXX removed, screws up some archives */
- for (bp = buf; *bp == ' '; ++bp); /* MRR FIX, SKIP LEADING BLANKS */
- #endif
- bp = buf;
-
- if (0 == infile) { /* if we are not in the middle of a
- * file */
- if ('#' == buf[0]) /* comment? */
- continue;
-
- /* Is this a CAT type shar? */
- if (0 == strncmp(bp, CAT, strlen(CAT))) {
- prefix[0] = '\0';
- getendfile(bp, endstring, filename);
- if (fileexists != 0) {
- fprintf(stderr, "File exists (%s), skipping\n", filename);
- fileexists = 0;
- continue;
- }
- if (NULL == (dfp = fopen(filename, "w"))) {
- (void) printf("Error opening output file %s\n", filename);
- exit(1);
- }
- (void) printf("Extracting %s ... ", filename);
- (void) fflush(stdout);
- infile = 1;
- wc = 0;
- continue;
- }
- /* Is it a SED type shar? */
- if (0 == strncmp(bp, SED, strlen(SED))) {
- register int i = 0, j = 0;
-
- while ('^' != bp[i++])
- ;
- while ('/' != bp[i]) {
- prefix[j++] = bp[i++];
- }
- prefix[j] = '\0';
- getendfile(&bp[i], endstring, filename);
- if (fileexists != 0) {
- fprintf(stderr, "File exists (%s), skipping\n", filename);
- fileexists = 0;
- continue;
- }
- if (NULL == (dfp = fopen(filename, "w"))) {
- (void) printf("Error opening output file %s\n", filename);
- exit(1);
- }
- (void) printf("Extracting %s ... ", filename);
- (void) fflush(stdout);
- infile = 1;
- wc = 0;
- continue;
- }
- /* Do we want to do a test of sorts on a file? */
- if (0 == strncmp(bp, TEST, strlen(TEST))) {
- register int i = 0;
-
- while(!isdigit(bp[i]) && bp[i] != '-' && bp[i])
- i++;
-
- if (0 != isdigit(bp[i])) {
- wordcount(&bp[i], filename, wc);
- }
-
- if ('f' == bp[++i]) {
- fileexists = checkfile(&bp[++i]);
- }
- continue;
- }
- } else { /* We are in the middle of a file */
-
- /* Are we at the end of this one? */
- if (0 == strncmp(bp, endstring, strlen(endstring))) {
- (void) printf("Done\n");
- (void) fclose(dfp);
- infile = 0;
- continue;
- }
- /* No, then does it have a prefix? */
- if ('\0' == prefix[0]) {
- fputs(bp, dfp);
- wc = wc + strlen(bp);
- } else {
-
- /*
- * If it does have a prefix, is there one on
- * this line?
- */
- #ifdef SKIPBLANKS
- for (bp = buf; *bp == ' '; ++bp);
- #endif
- if (0 != strncmp(bp, prefix, strlen(prefix))) {
- fputs(buf, dfp);
- wc = wc + strlen(buf);
- } else {
- fputs(&bp[strlen(prefix)], dfp);
- wc = wc + strlen(bp) - strlen(prefix);
- }
- }
- }
- }
- (void) printf("All Done!\n");
- (void) fclose(fp);
- }
-