home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 9 Archive
/
09-Archive.zip
/
SHAROS2.ZIP
/
SHAR.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-25
|
12KB
|
544 lines
/*------------------------------------------------------------------------------
The UNIX program 'shar' (from "shell archive") puts readable text files
together in a package from which they are easy to extract by feeding the
package to 'sh'.
Like its predecessors, this OS/2 implementation of shar builds shell
archives but is also capable of decomposing them in the absence of the
Bourne shell. It is thus a useful tool for dealing with shell archives
created on UNIX systems.
v 911225 J. Saxton
- Corrected a problem in mkdir when directory name was NOT quoted.
- Tidied up reporting of directory operations.
v 911205 J. Saxton
- This version strictly for OS/2 HPFS. No longer is any attempt made
to rectify file names for FAT or CP/M file systems. Code for VMS
has been deleted. Code for ULTRIX and the Amiga has been retained
without verification.
- Detect directories and don't try to add them to archives.
(Maybe next version will allow recursion into directories?)
- Added dequote() function to normalize directory names.
- Generated a Makefile and a definitions file.
- made -pX the default pattern instead of -pXX.
- fixed 'unshar' operation to ignore leading blanks.
- tidied up source so it now compiles with MSC 6.0A at -W3 without
complaint.
v 910525 J. Saxton for OS/2 2.0 and HPFS
v 891212 J. Saxton for MSDOS and OS/2
- index() function changed to strchr() to comply with more modern C
compilers.
- eliminated several warning messages generated by the Microsoft C
compiler (version 5.1)
- compiled as a non-PM application for OS/2 and bound as a family mode
program for MSDOS. Does wildcard expansion on input file names.
cl /Ox /Fb shar.c c:\os2\lib\setargv.obj
v 860716 M. Kersenbrock (tektronix!copper!michaelk) for Z80-CPM
- enhanced usage message
v 860712 D. Wecker for ULTRIX and the AMIGA
- stripped down..does patterns but no directories
- added a -u (unshar) switch
------------------------------------------------------------------------------*/
#ifdef MSDOS
#define OS2
#endif
#ifdef OS2
#include <string.h>
#include <ctype.h>
#include <malloc.h>
#include <stdlib.h>
#include <direct.h>
#include <sys/types.h>
#include <sys/stat.h>
#endif
#include <stdio.h>
#include <io.h>
#include <time.h>
#include <errno.h>
#ifdef AMIGA
#include <exec/types.h>
extern char *getenv(), *scdir(), *malloc(), *strchr();
#endif
#ifdef ULTRIX
#include <sys/types.h>
#include <sys/stat.h>
extern char *getenv(), *scdir(), *malloc(), *strchr();
#endif
int
getopt(int, char **, char *),
getpat(char *),
getarg(int, char **);
void
dounshar(char *),
getshpar(char *, char *, char *),
dequote(char *);
#define BADCH ((int)'?')
#define EMSG ""
#define tell(s) {fputs(*nargv,stderr);fputs((s),stderr);fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);}
#define rescanopts() (optind = 1)
int optind = 1, /* index into parent argv vector */
optopt; /* character checked for validity */
long fsize; /* length of file */
char *optarg; /* argument associated with option */
char *sav[100]; /* saved file names */
int savind; /* save index */
/* OPTIONS */
int Verbose = 0; /* provide append/extract feedback */
int Basename = 0; /* extract into basenames */
int Count = 0; /* count characters to check transfer */
char *Delim = "SHAR_EOF"; /* put after each file */
char Filter[100] = "cat"; /* used to extract archived files */
char *Prefix = NULL; /* line prefix to avoid funny chars */
int UnShar = 0; /* do we unshar an input file? */
char Usage1[] =
"\nSHAR: Create/extract file archive for extraction by /bin/sh (normally).\n\
\n\
usage: shar [-u archive] [[-a] [-p prefix]\
[-d delim] [-bcv] files > archive]\n\
\n\
where: -a all the options (v,c,b,-pX)\n";
char Usage2[] =
" -b extract absolute paths into current directory\n\
-c check filesizes on extraction\n\
-d use this EOF delimiter instead of SHAR_EOF\n";
char Usage3[] =
" -p use this as prefix to each line in archived files\n\
-u unshar <archive>\n\
-v verbose on extraction, incl. echoing filesizes\n";
struct stat
FileInfo;
#define SED "sed 's/^%s//'"
#define OPTSTRING "u:ap:d:bcv"
int header(char **ppchFiles)
{
auto long clock;
char **ppchList;
char *pchOrg;
char *pchName;
register int problems = 0;
pchOrg = getenv("ORGANIZATION");
pchName = getenv("NAME");
puts("#\tThis is a shell archive.");
puts("#\tRemove everything above and including the cut line.");
puts("#\tThen run the rest of the file through sh.");
puts("#----cut here-----cut here-----cut here-----cut here----#");
puts("#!/bin/sh");
puts("# shar: Shell Archiver");
puts("#\tRun the following text with /bin/sh to create:");
for (ppchList = ppchFiles; *ppchList; ++ppchList)
printf("#\t%s\n", *ppchList);
(void) time(&clock);
printf("# This archive created: %s", ctime(&clock));
if (pchName != NULL)
printf("# By:\t%s (%s)\n", pchName,
pchOrg == NULL ? "Dave Wecker Midnight Hacks" : pchOrg);
return (0);
}
int archive(char *input, char *output)
{
auto char line[BUFSIZ];
register FILE *ioptr;
if (ioptr = fopen(input, "r"))
{
printf("%s << \\%s > %s\n", Filter, Delim, output);
while (fgets(line, BUFSIZ, ioptr))
{
if (Prefix)
fputs(Prefix, stdout);
fputs(line, stdout);
if (Count)
fsize += strlen(line);
}
puts(Delim);
(void) fclose(ioptr);
return (0);
}
else
{
fprintf(stderr, "shar: Can't open '%s'\n", input);
return (1);
}
}
void shar(char *file)
{
char *basefile;
if (!strcmp(file, "."))
return;
fsize = 0;
if (stat(file, &FileInfo))
{
fprintf(stderr,"Unable to do a stat() on '%s'\n", file);
return;
}
if (FileInfo.st_mode & S_IFMT != S_IFREG)
{
basefile = "strange file";
if (FileInfo.st_mode & S_IFCHR)
basefile = "character special file";
if (FileInfo.st_mode & S_IFDIR)
basefile = "directory";
fprintf(stderr,"Cannot archive %s '%s'\n", basefile, file);
return;
}
basefile = file;
if (Basename)
{
while (*basefile)
basefile++; /* go to end of name */
while (basefile > file && *(basefile - 1) != '/')
basefile--;
}
if (Verbose)
printf("echo shar: extracting %s\n", basefile);
if (archive(file, basefile))
exit(66);
if (Count)
{
printf("if test %ld -ne \"`wc -c %s`\"\n", fsize, basefile);
printf("then\necho shar: error transmitting %s ", basefile);
printf("'(should have been %ld characters)'\nfi\n", fsize);
}
}
void main(int argc, char *argv[])
{
auto char *ppchFiles[256];
register int C;
register char **ppchList = ppchFiles;
register int errflg = 0;
while (EOF != (C = getopt(argc, argv, OPTSTRING)))
{
switch (C)
{
case 'v':
Verbose++;
break;
case 'c':
Count++;
break;
case 'b':
Basename++;
break;
case 'd':
Delim = optarg;
break;
case 'a': /* all the options */
optarg = "X";
Verbose++;
Count++;
Basename++;
/* fall through to set prefix */
case 'p':
(void) sprintf(Filter, SED, Prefix = optarg);
break;
case 'u':
UnShar++;
dounshar(optarg);
break;
default:
errflg++;
}
}
if (UnShar)
exit(0);
C = getarg(argc, argv);
if (errflg || EOF == C)
{
if (EOF == C)
fprintf(stderr, "shar: No input files\n");
fprintf(stderr, "%s%s%s", Usage1, Usage2, Usage3);
exit(1);
}
savind = 0;
do
{
if (getpat(optarg))
exit(2);
}
while (EOF != (C = getarg(argc, argv)));
sav[savind] = NULL;
header(sav);
for (ppchList = sav; *ppchList; ++ppchList)
{
shar(*ppchList);
}
puts("#\tEnd of shell archive");
puts("exit 0");
exit(0);
}
int getpat(char *pattern)
{
register char *ptr;
#ifdef AMIGA
while (ptr = scdir(pattern))
#else
ptr = pattern;
#endif
{
sav[savind] = malloc(strlen(ptr) + 1);
strcpy(sav[savind++], ptr);
if (access(ptr, 4))
{
printf("No read access for file: %s\n", ptr);
return (-1);
}
}
return (0);
}
/*
get option letter from argument vector
*/
int getopt(int nargc, char **nargv, char *ostr)
{
register char *oli; /* option letter list index */
static char *place = EMSG; /* option letter processing */
if (!*place)
{ /* update scanning pointer */
if (optind >= nargc || *(place = nargv[optind]) != '-' || !*++place)
return (EOF);
if (*place == '-')
{ /* found "--" */
++optind;
return EOF;
}
} /* option letter okay? */
if ((optopt = (int) *place++) == (int) ':' || !(oli = strchr(ostr, optopt)))
{
if (!*place)
++optind;
tell(": illegal option -- ");
}
if (*++oli != ':')
{ /* don't need argument */
optarg = NULL;
if (!*place)
++optind;
}
else
{ /* need an argument */
if (*place)
{ /* no white space */
optarg = place;
}
else
{
if (nargc <= ++optind)
{ /* no arg */
place = EMSG;
tell(": option requires an argument -- ");
}
else
{
optarg = nargv[optind]; /* white space */
}
}
place = EMSG;
++optind;
}
return (optopt); /* dump back option letter */
}
int getarg(int nargc, char **nargv)
{
if (nargc <= optind)
{
optarg = (char *) 0;
return EOF;
}
else
{
optarg = nargv[optind++];
return 0;
}
}
void dounshar(char *ArcNam)
{
int
Prefix = 0,
i;
FILE
*inptr, *outptr;
char
*ptr,
*nlf,
line[BUFSIZ],
FilNam[256],
Delim[40];
if (!(inptr = fopen(ArcNam, "r")))
{
fprintf(stderr, "shar: Can't open archive '%s'\n", ArcNam);
return;
}
while (fgets(line, BUFSIZ, inptr))
{
ptr = line + strspn(line, " \t");
if (strncmp(ptr, "sed ", 4) == 0)
{
Prefix = 0;
if (!(ptr = strchr(ptr, '/')))
goto getfil;
if (*++ptr == '^')
++ptr;
while (*ptr++ != '/')
Prefix++;
goto getfil;
}
else
if (strncmp(ptr, "cat ", 4) == 0)
{
Prefix = 0;
getfil:
getshpar(ptr, ">", FilNam);
getshpar(ptr, "<<", Delim);
fprintf(stderr, "Creating %s ...", FilNam);
outptr = fopen(FilNam, "w");
while (fgets(line, BUFSIZ, inptr))
{
if (strncmp(line, Delim, strlen(Delim)) == 0)
break;
if (outptr)
fputs(&line[Prefix], outptr);
}
if (outptr)
{
fclose(outptr);
fprintf(stderr, "...done\n");
}
else
fprintf(stderr, "...error in creating file\n");
}
else
if (strncmp(ptr, "mkdir ", 6) == 0)
{
for (nlf=ptr+6; *nlf; ++nlf)
if (*nlf == '\n')
*nlf = '\0';
fprintf(stderr, "Creating directory %s ...", ptr+6);
dequote(ptr+6);
i = mkdir(ptr+6);
if (i) /* then it failed */
fprintf(stderr, "failed, errno=%u\n", errno);
else
fprintf(stderr, "done\n");
}
else
if (strncmp(ptr, "chdir ", 6) == 0)
{
dequote(ptr+6);
chdir(ptr+6);
}
else
if (strncmp(line, "cd ", 3) == 0)
{
dequote(ptr+3);
chdir(ptr+3);
}
}
fclose(inptr);
}
void getshpar(char *line, char *sea, char *par)
{
register char *scr1, *scr2;
while (*line)
{
scr1 = line;
scr2 = sea;
while (*scr1 && *scr2 && *scr1 == *scr2)
{
scr1++;
scr2++;
}
if (*scr2 == 0)
{
if (*scr1 == 0)
{
*par = 0;
return;
}
while (*scr1 == ' ' || *scr1 == '\t' ||
*scr1 == '/' ||
*scr1 == '\\' || *scr1 == '\'' || *scr1 == '"')
scr1++;
while (*scr1 != 0 && *scr1 != ' ' && *scr1 != '\t' &&
// *scr1 != '/' &&
*scr1 != '\\' && *scr1 != '\'' && *scr1 != '"' &&
*scr1 != '\n' && *scr1 != '\r')
*par++ = *scr1++;
*par = 0;
return;
}
line++;
}
*par = 0;
}
void dequote(char *p)
{
char
*d = p,
q;
while (isspace(*d))
++d;
switch (*d)
{
case '\'':
case '"':
q = *d++;
break;
default:
q = ' ';
}
while (*d && !isspace(*d) && *d != q)
*p++ = *d++;
*p = '\0';
}