home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 9 Archive
/
09-Archive.zip
/
unshar2.zip
/
UNSHAR2.CPP
< prev
next >
Wrap
Text File
|
1997-02-12
|
13KB
|
490 lines
#include <stdlib.h>
#include <io.h>
#include <direct.h>
#include <fstream.h>
#include <iostream.h>
/*═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ U n S h a r / 2 ║
║ ║
║ ported by SolDev Team ║
║ ║
╠════════════════════════════════════════════════════════════════════════════╣
║ Name : UnShar2.CPP ║
║ Purpose : extract files from shell archive ║
║ Developer : Andreas Just(SCORPIO) - based on - see above.. ║
║ Usage : see usage() ║
╠─────────────────┬─────────────────┬─────────────────┬──────────────────────╣
║ Date Begin │ Date End │ Betatest │ Finaltest ║
╠─────────────────┼─────────────────┼─────────────────┼──────────────────────╣
║ │ │ │ ║
╠─────────────────┴─────────────────┴─────────────────┴──────────────────────╣
║ ║
║ 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 subdir. ║
║ 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. ║
║ ║
║ Dez 1996--Andreas Just--ported to OS/2 - changed to CPP-FileStreams ║
║ ANSI sequences added, included modified optlink, some small changes ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════*/
#pragma comment (user,"SolDev Team (SCORPIO) 1997")
// 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
int useAnsi; // use ANSI codes for some color
fstream ifs; // input filestream
//simple ANSI Color
#define GR ((useAnsi)?"\x1B[32m\x1B[1m":"")<<
#define CY ((useAnsi)?"\x1B[36m\x1B[1m":"")<<
#define DC ((useAnsi)?"\x1B[36m\x1B[0m":"")<<
#define RD ((useAnsi)?"\x1B[31m\x1B[1m":"")<<
#define RESET ((useAnsi)?"\x1B[37m\x1B[0m":"")<<
// Methods of unsharing
#define UNKNOWN 0
#define BRUTAL 1
#define APPEND 2
// Whitespace indicators
#define WHITE 0
#define NOWHITE 1
// Leading character indicators
#define NOX 0
#define YESX 1
// Emulation types available
#define SED 1
#define GRES 2
#define CAT 3
#define NUMTOKS 4
#define BUFSIZE 1024
static char *token[NUMTOKS] = // The list of emulation types
{
"",
"sed",
"gres",
"cat"
};
// commandline options
char *optarg;
int opterr = 1;
int optind = 1;
int optopt;
char *index(char* s, char c)
{
do
{
if (*s == c)
return(s);
} while (*s++ != 0);
return(0);
}
int getopt(int argc, char** argv, char* opts)
{
int sp = 1;
int c;
char *cp;
if(sp == 1)
{
if(optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
return(EOF);
else if(strcmp(argv[optind], "--") == NULL)
{
optind++;
return(EOF);
}
}
optopt = c = argv[optind][sp];
if(c == ':' || (cp=index(opts, c)) == NULL)
{
cout <<RD "Commandline: illegal option !" << endl;
if(argv[optind][++sp] == '\0')
{
optind++;
sp = 1;
}
return('?');
}
if(*++cp == ':')
{
if (argv[optind][sp+1] != '\0') optarg = &argv[optind++][sp+1];
else if(++optind >= argc)
{
cout <<RD "Commandline: option requires an argument !" << endl;
sp = 1;
return('?');
}
else optarg = argv[optind++];
sp = 1;
}
else
{
if(argv[optind][++sp] == '\0')
{
sp = 1;
optind++;
}
optarg = NULL;
}
return(c);
}
// UnShar2 functions
int getLine(long how, char* buf)
{
ifs.setf(how); // because ios::skipws is defined as
ifs.getline(buf, 1024); // 0x0000001 we can directly use int how
return ifs.eof();
}
int firstword(char* buf) // Return token value of first word 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);
}
char *getstring(char* buf) // Get the next string from the buffer
{
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);
}
}
void getnames(char* buf, char* file, char* word) // Get the file & end word
{
char *temp = buf;
if (verbose) cout <<CY "Getnames: buf is " << buf << endl;
while (*temp!=NULL) // Scan along buffer
{
switch(*temp) // Get file or end word
{
case '>' : // Get the file name
strcpy(file,getstring(++temp));
break;
case '<' :
if (*(++temp)=='<') ++temp; // Skip 2nd <
strcpy(word,getstring(temp)); // Get next word
break;
default :
temp++;
}
}
}
int mustget(char* s1) // Return 1 if s1 is in the list of
{ // 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 (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(int how, char* file, char* end, int lead, int method) // Extract file, up until end word
{ // If how==YESX, then ignore lead
fstream ofs; // character on every line
char line[BUFSIZE];
char *temp;
long openmode;
int ch;
if (make_subdir(file) != 0) // make subdirs as required for file
{
cout <<RD "Cannot create subdirectory for " << file << endl;
return;
}
if (access(file, 02) == 0 && method == APPEND)
{
openmode = ios::out|ios::app;
cout <<DC " (appending)" << endl;
}
else
{
openmode = ios::out;
cout <<DC " (creating)" << endl;
}
ofs.open(file,openmode);
if (ofs.fail())
{
cout <<RD "Cannot open file "<< file <<". Enter new name or <ENTER> to skip: ";
cin.getline(line, 1024);
if (line[0] != '\0')
{
ofs.open(file,openmode);
if (ofs.fail())
{
cout <<RD "UnShar2: ERROR Opening file " << line << endl;
return;
}
}
}
while(1)
{
ch=getLine(WHITE,line); // Get a line of file
temp=line;
if (ch) // EndOfFile
{
ofs << line << endl;
ofs.close();
return;
}
if (strncmp(line,end,strlen(end))==0) // If end word
{
ofs.close();
return;
}
if ((how==YESX) && (*temp==lead)) temp++; // Skip any lead
ofs << temp << endl;
}
}
void disembowel(int method)
{
char buf[BUFSIZE]; // Line buffer
char file[BUFSIZE]; // File name
char word[BUFSIZE]; // Word buffer
int ch,x;
if (verbose) cout <<CY "Entering disembowel" << endl;
x='X'; // Leading X character
while(1)
{
ch = getLine(NOWHITE, buf); // Get a line from file
if (ch) return;
switch(firstword(buf)) // Extract, depending on first word
{
case CAT :
case GRES :
case SED :
if (verbose) cout <<CY "About to do getnames" << endl;
getnames(buf,file,word);
if (table==0)
{
if ((numext==0) || (mustget(file)))
{
cout <<GR "Extracting : " <<CY file;
if (verbose) cout <<RD "\nstopping at " << word << endl;
extract(YESX,file,word,x,method);
}
}
else cout <<CY file << endl;
break;
default :
break;
}
}
}
void usage()
{
cout <<GR "Usage:\n"
<<CY " UnShar2 [-b] [-t] [-v] [-a] [file(s)]\n\n"
<<GR " -b "<<CY" extract brutally : overwrite existing files - default: append\n"
<<GR " -t "<<CY" table: shows filenames in archive\n"
<<GR " -v "<<CY" verbose: show more info\n"
<<GR " -a "<<CY" turn of ANSI sequences\n"
<<GR " file(s) "<<CY" file(s) to extract\n" <<RESET endl;
exit(0);
}
void main(int argc, char* argv[])
{
int i,c,first;
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
useAnsi = 1;
if (argc==1) usage(); // any argument needed
while ((c=getopt(argc,argv,"x:atbv"))!=EOF)
{
switch(c) // Get the various options
{
case 'a' :
useAnsi = 0;
break;
case 't' :
table=1;
break;
case 'b' :
method= BRUTAL;
break;
case 'v' :
verbose=1;
break;
case 'x' :
exfile[numext] = new char[strlen(optarg)+1];
strcpy(exfile[numext++],optarg);
break;
default :
usage();
}
}
for (first=1;first<argc;first++) if (argv[first][0]!='-') break;
for (i=first; i < argc; i++) // open stdio with every file
{
ifs.close();
ifs.open(argv[i],ios::in);
if (ifs.fail())
{
cout <<RD "UnShar2: ERROR Opening file: " << argv[i] <<RESET endl;
exit(1);
}
switch(method)
{
case BRUTAL: // Unshar brutally!
case APPEND:
disembowel(method); // Unshar somewhat less brutally!
cout <<RESET endl;
break;
default:
cout <<RD "UnShar2: ERROR Unknown method of unsharing" <<RESET endl;
exit(1);
}
}
exit(0);
}