home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
dostools
/
unshar
/
unshar.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-01
|
9KB
|
371 lines
#include <stdio.h>
#include "unshar.h"
/*
* Unshar - extract files from shell archive
*
* Written by Warren Toomey. Nov, 1989.
* You may freely copy or give away this source as
* long as this notice remains intact.
*
* Feb 1990--Fred C. Smith--Added make_subdir() which
* handles shar files which require extracted files to
* be inserted into a non-existent sub directory.
*
* Feb 1990--Fred C. Smith--Added APPEND mode in which unshar
* checks for existence of a file before unsharing, and if
* already exists it appends to it. Also outputs a message
* for each file indicating whether it is creating or
* appending (message is output in all modes).
*/
/* Global variables */
int table; /* Generate a table, or extract */
int verbose; /* Unshar verbosely - debugging */
int numext; /* Number of files to extract */
char *exfile[100]; /* Files to extract */
#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=NULL;
*buf=NULL; /* Null the buffer */
if (how==NOWHITE) /* If skip any whitespace */
{
while (((ch=fgetc(zin))==' ') || (ch=='\t'));
if (ch==EOF) return(EOF); /* Returning EOF or NULL */
if (ch=='\n') return(NULL);
*buf++ =ch; /* Put char in buffer */
}
while ((ch=fgetc(zin))!='\n') /* Now get the line */
{
if (ch==EOF) { *buf=NULL; return(EOF); }
*buf++ = ch;
}
*buf=NULL; /* Finally null-terminate the buffer */
return(NULL); /* and return */
}
char *getstring(buf) /* Get the next string from the buffer */
char *buf; /* ignoring any quotes */
{
char out[BUFSIZE];
char *temp=out;
while ((*buf==' ') || (*buf=='\t')) buf++; /* Skip whitespace */
switch(*buf) /* Now check first char */
{
case '\'' : buf++;
while (*buf!='\'') *temp++ = *buf++;
*temp=NULL;
return(out);
case '\"' : buf++;
while (*buf!='\"') *temp++ = *buf++;
*temp=NULL;
return(out);
case NULL : return(NULL);
default : while ((*buf!=' ') && (*buf!='\t'))
if (*buf!='\\') *temp++ = *buf++;
else buf++;
*temp=NULL;
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);
}
int make_subdir (fullpath)
char *fullpath;
{
char localpath [256];
int index;
index = 0;
if (fullpath[1] == ':')
{
localpath[0] = fullpath[0];
localpath[1] = fullpath[1];
if (fullpath[2] == '\\' || fullpath[2] == '/')
localpath[2] = fullpath[2];
localpath[3] = (char) 0;
index = 3;
}
else if (fullpath[0]== '\\' || fullpath[0] == '/')
{
localpath[0] = fullpath[0];
localpath[1] = (char) 0;
index = 2;
}
for ( ; index < strlen (fullpath) ; index++)
{
if (fullpath[index] == '\\' || fullpath[index] == '/')
{
/* the stuff in localpath should be a full pathname of
a subdirectory which might need to be made. check
it, and if so, make it.
*/
localpath[index] = (char) 0;
if (access (localpath, 0) == -1) /* i.e., does not exist */
{
if (mkdir (localpath) == -1)
return (-1); /* mkdir failed */
}
}
localpath[index] = fullpath[index];
}
return (0);
}
void extract(how,file,end,lead, method) /* Extract file, up until end word */
int how; /* If how==YESX, then ignore lead */
char *file; /* character on every line */
char *end;
int lead;
int method;
{
FILE *zout;
char line[BUFSIZE];
char *temp, *openmode;
int ch;
if (make_subdir(file) != 0) /* make subdirs as required for file */
{
fprintf (stderr, "Cannot create subdirectory for %s\n", file);
return;
}
if (method == APPEND)
{
if (access (file, 02) == 0)
{
openmode = "a";
printf (" (appending)\n");
}
else
{
openmode = "w";
printf (" (creating)\n");
}
}
else
{
openmode = "w";
printf (" (creating)\n");
}
zout=fopen(file,openmode); /* Open output file */
if (zout == NULL)
{
fprintf (stderr, "Cannot open file %s: Enter new name or <ENTER> to skip: ",
file);
gets (line);
if (line[0] != '\0')
{
zout = fopen (line, openmode);
if (zout==NULL)
{ perror("unshar");
return;
}
}
}
while(1)
{
ch=getline(WHITE,line); /* Get a line of file */
temp=line;
if (ch==EOF)
{ fprintf(zout,"%s\n",line);
fclose(zout);
return;
}
if (strncmp(line,end,strlen(end))==0) /* If end word */
{ fclose(zout); /* close the file */
return;
}
if ((how==YESX) && (*temp==lead)) temp++; /* Skip any lead */
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!=NULL) /* 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(method) /* Unshar brutally! */
int method;
{
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)
{
ch=getline(NOWHITE,buf); /* Get a line from file */
if (ch==EOF)
return;
switch(firstword(buf)) /* Extract, depending on first word */
{
case CAT:
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",file);
if (verbose)
printf(" stopping at %s\n",word);
extract(YESX,file,word,x,method);
}
}
else printf("%s\n",file);
break;
default: break;
}
}
}
usage()
{
fprintf(stderr,"Usage: unshar [-t] [-b] [-v] [-xfile] [file(s)]\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 */
method= APPEND; /* default used to be BRUTAL */
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:tbav"))!=EOF)
switch(c)
{
case 't' : table=1; /* Get the various options */
break;
case 'a' : method= APPEND;
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 */
switch(method)
{
case APPEND: disembowel(method ); /* Unshar somewhat less brutally! */
break;
case BRUTAL: disembowel(method); /* 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 */
{
fclose(stdin);
if ((zin=fopen(argv[i],"r"))==NULL)
{ perror("unshar");
exit(1);
}
switch(method)
{
case BRUTAL: disembowel(); /* Unshar brutally! */
break;
case APPEND: disembowel(method ); /* Unshar somewhat less brutally! */
break;
default: fprintf(stderr,"unshar: Unknown method of unsharing\n");
exit(1);
}
}
exit(0);
}