home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 9 Archive
/
09-Archive.zip
/
UNSHAR.ZIP
/
UNSHAR.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-17
|
10KB
|
449 lines
/*
* Unshar - extract files from shell archive
*
* Written by Warren Toomey [wkt@csadfa.oz.au@munnari.oz@uunet.uu.net] You may
* freely copy or give away this source as long as this notice remains
* intact.
*
* Definitions used by unshar
*/
#include <stdio.h>
#include <stdlib.h>
/* Methods of unsharing */
#define UNKNOWN 0
#define BRUTAL 1
/* Whitespace indicators */
#define WHITE 0
#define NOWHITE 1
/* Leading character indicators */
#define NOX 0
#define YESX 1
/* Emulation types available */
#define NUMTOKS 4 /* Must change NUMTOKS to equal the */
/* Define UNKNOWN 0 *//* number of emulation types */
#define SED 1
#define GRES 2
#define CAT 3
static char *token[NUMTOKS] = /*The list of emulation types ! */
{"",
"sed",
"gres",
"cat"
};
/* Misc. constants */
#define BUFSIZE 512 /* Size of line buffer */
/* Global variables */
int table; /* Generate a table, or extract */
int verbose; /* Unshar verbosely - debugging */
int numext; /* Number of files to extract */
int binfile; /* Binary file - err indicator */
char *exfile[100]; /* Files to extract */
#ifdef MSDOS
/* Unix filename translation for MS-DOS */
void translate_name(char *src)
{
char *ptr, *first = NULL, *last = NULL;
char temp[8];
extern char *strchr(char *, int);
for ( ptr = strchr(src, 0); ptr >= src; ptr-- )
if ( *ptr == '.' )
{
if ( last == NULL )
last = ptr;
}
else if ( *ptr == '/' )
{
first = ptr + 1;
break;
}
if ( first == NULL )
first = src;
if ( last == NULL )
last = strchr(src, 0);
for ( ptr = first; ptr < last; ptr++ )
if ( *ptr == '.' )
*ptr = '_';
if ( strlen(last) > 4 )
last[4] = 0;
if ( last - first > 8 )
{
strcpy(temp, last);
strcpy(first + 8, last);
}
}
#endif
#define getline(x,y) fgetline(stdin,x,y)
int
fgetline(zin, how, buf) /* Get a line from a file */
FILE *zin;
int how; /* Ignore leading whitespace if */
char *buf; /* how == NOWHITE */
{
int ch = 0;
*buf = 0; /* Null the buffer */
if (how == NOWHITE) { /* If skip any whitespace */
while (((ch = fgetc(zin)) == ' ') || (ch == '\t'));
if (ch == EOF)
return (EOF); /* Returning EOF or 0 */
if (ch == '\n')
return (0);
*buf++ = ch; /* Put char in buffer */
}
while ((ch = fgetc(zin)) != '\n') { /* Now get the line */
if (ch == EOF) {
*buf = 0;
return (EOF);
}
if (ch > 127) {
binfile = 1;
return (0);
}
*buf++ = ch;
}
*buf = 0; /* Finally null-terminate the buffer */
return (0); /* and return */
}
char *
getstring(buf) /* Get the next string from the buffer */
char *buf; /* ignoring any quotes */
{
char out[BUFSIZE];
char *temp = out;
char inquotes = 0, ok = 1;
while ((*buf == ' ') || (*buf == '\t'))
buf++; /* Skip whitespace */
if (verbose)
printf("In getstring...\n");
*temp = 0;
while (ok) { /* Parse line */
#ifdef DEBUG
if (verbose)
printf("*%s*\n", out);
#endif
switch (*buf) {
case '\"':
case '\'':
buf++;
inquotes = !inquotes; /* Toggle inquotes */
break;
case 0:
case '\n': /* Stop on <, >, NULL */
case '>': /* \n, and sometimes */
case '<':
ok = 0;
break; /* space & tab */
case '\t':
case ' ':
if (!inquotes)
ok = 0;
case '\\':
if (!inquotes) { /* Ignore backquotes */
buf++;
break;
}
default:
*temp++ = *buf++; /* Copy chars :-) */
}
}
*temp = 0;
if (verbose)
printf("Returning *%s*\n", out);
return (out);
}
int
firstword(buf) /* Return token value of first word */
char *buf; /* in the buffer. Assume no leading */
{ /* whitespace in the buffer */
int i;
for (i = 1; i < NUMTOKS; i++)
if (strncmp(buf, token[i], strlen(token[i])) == 0)
return (i);
return (UNKNOWN);
}
int
mustget(s1) /* Return 1 if s1 is in the list of */
char *s1; /* files to extract. Return 0 if not */
{
int i;
if (numext == 0)
return (0);
for (i = 0; i < numext; i++)
if (!strcmp(s1, exfile[i]))
return (1);
return (0);
}
void
extract(how, file, end, lead) /* Extract file, up until end word */
int how; /* If how==YESX, then ignore lead */
char *file; /* character on every line */
char *end;
int lead;
{
FILE *zout;
char line[BUFSIZE];
char *temp;
int ch;
#ifdef MSDOS
translate_name(file);
if ( (zout = fopen(file,"r")) != NULL )
{
char buf[128];
fclose(zout);
printf("File %s already exists.\nEnter new name (press ENTER to overwrite): ", file);
zout = fopen("con", "r");
fgets(buf, sizeof(buf), zout);
fclose(zout);
buf[strlen(buf) - 1] = 0;
if ( strlen(buf) != 0 )
strcpy(file, buf);
}
#endif
zout = fopen(file, "w");/* Open output file */
if (zout == NULL) {
perror("unshar1");
return;
}
while (1) {
binfile = 0;
ch = getline(WHITE, line); /* Get a line of file */
temp = line;
if (binfile || (ch == EOF)) {
fprintf(zout, "%s\n", line);
fclose(zout);
return;
}
if ((how == YESX) && (*temp == lead))
temp++; /* Skip any lead */
if (strcmp(temp, end) == 0) { /* If end word */
fclose(zout); /* close the file */
return;
}
fprintf(zout, "%s\n", temp);
}
}
void
getnames(buf, file, word) /* Get the file & end word */
char *buf, *file, *word; /* from the buffer */
{
char *temp;
temp = buf;
if (verbose)
printf("Getnames: buf is %s\n", buf);
while (*temp != 0) { /* Scan along buffer */
switch (*temp) {/* Get file or end word */
case '>':
strcpy(file, getstring(++temp)); /* Get the file name */
break;
case '<':
if (*(++temp) == '<')
++temp; /* Skip 2nd < */
strcpy(word, getstring(temp)); /* Get next word */
break;
default:
temp++;
}
}
}
void
disembowel()
{ /* Unshar brutally! */
char buf[BUFSIZE]; /* Line buffer */
char file[BUFSIZE]; /* File name */
char word[BUFSIZE]; /* Word buffer */
int ch, x;
if (verbose)
printf("Entering disembowel\n");
x = 'X'; /* Leading X character */
while (1) {
binfile = 0;
ch = getline(NOWHITE, buf); /* Get a line from file */
if (ch == EOF)
return;
if (binfile)
continue;
switch (firstword(buf)) { /* Extract, depending on
* first word */
case CAT:
if (verbose)
printf("About to do getnames\n");
getnames(buf, file, word);
if (table == 0) {
if ((numext == 0) || (mustget(file))) {
printf("unshar: Extracting %s\n", file);
if (verbose)
printf(" stopping at %s\n", word);
extract(NOX, file, word, x);
}
} else
printf(" %s\n", file);
break;
case GRES:
case SED:
if (verbose)
printf("About to do getnames\n");
getnames(buf, file, word);
if (table == 0) {
if ((numext == 0) || (mustget(file))) {
printf("unshar: Extracting %s\n", file);
if (verbose)
printf(" stopping at %s\n", word);
extract(YESX, file, word, x);
}
} else
printf(" %s\n", file);
break;
default:
break;
}
}
}
char *myname;
usage()
{
printf("\nUsage: %s [-t] [-b] [-v] [-xfile] [file(s)]\n", myname);
printf(
"\n -t Do not extract files, just list the files in the archive(s)."
"\n -b Extract files from the archive(s) brutally, with no regard at all to"
"\n things such as testing if the file exists, or chmoding the file etc."
"\n -v Be verbose. Used only for debugging purposes."
"\n -x Extract the named file from the shell archive."
"\n -h Show this text.\n");
exit(0);
}
main(argc, argv)
int argc;
char *argv[];
{
extern int optind;
extern char *optarg;
int i, c, first;
FILE *zin; /* Dummy file descriptor */
int method; /* Method of unsharing */
myname = argv[0];
method = BRUTAL; /* Only BRUTAL currently available */
table = 0; /* Don't generate a table */
verbose = 0; /* Nor be very verbose */
numext = 0; /* Initially no files to extract */
while ((c = getopt(argc, argv, "x:tbvh")) != EOF)
switch (c) {
case 't':
table = 1; /* Get the various options */
break;
case 'b':
method = BRUTAL;
break;
case 'v':
verbose = 1;
break;
case 'x':
exfile[numext] = (char *) malloc(strlen(optarg) + 1);
strcpy(exfile[numext++], optarg);
break;
default:
usage();
}
if (argc == 1)
first = argc; /* Find first file argument */
else
for (first = 1; first < argc; first++)
if (argv[first][0] != '-')
break;
if (first == argc) { /* If no file argument *//* use stdin only */
if ( isatty(fileno(stdin)) )
usage();
switch (method) {
case BRUTAL:
disembowel(); /* Unshar brutally! */
break;
default:
fprintf(stderr, "unshar: Unknown method of unsharing\n");
exit(1);
}
} else
for (i = first; i < argc; i++) { /* open stdio with every
* file */
if (table)
printf("%s:\n", argv[i]);
fclose(stdin);
if ((zin = fopen(argv[i], "r")) == NULL) {
perror("unshar2");
exit(1);
}
switch (method) {
case BRUTAL:
disembowel(); /* Unshar brutally! */
break;
default:
fprintf(stderr, "unshar: Unknown method of unsharing\n");
exit(1);
}
}
exit(0);
}