RDROYA01@ULKYVX.BITNET.UUCP (01/29/87)
# This is a shell archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# readme.shr
# shar.c
# shar.lnk
# This archive created: 29-January-1987 15:12:56 EST
# By: Robert_Royar (University_of_Louisville)
cat << \SHAR_EOF > README.SHR
The next two files make up a shar/unshare program for the ST and vax VMS. I
have tested both versions and they work the same on each system. I've had
this source for quite a while and have been using it on VMS, but hadn't
bothered to port it to the ST until recently. The first file is the shar
archive for source and the link68 linkfile. The second file is the uuencoded
binary shar.prg. I haven't prefixed the lines so that you can easily
extract the files without the progrm itself. The original was posted to
net.sources last year. This one has had some bugs removed and most of the
amiga/cpm stuff deleted (it made it difficult to decipher the code). But I
left the VMS conditionals in place to make it easy to get versions running
on the two machines. Hope you can find a use for this. I sure have.
SHAR_EOF
if test 817 -ne "`wc -c README.SHR`"
then
echo shar: error transmitting README.SHR '(should have been 817 characters)'
fi
cat << \SHAR_EOF > SHAR.C
/*
* Shar puts readable text files together in a package
*
* from which they are easy to extract.
*
* 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
*
* v 870128 R. Royar for ST
* - removed #ifdefs that left stray }s in file
* - reformatted text for consistant style
* - modified main to abort when no files are given
* - fixed call to fputc in tell macro, which omitted the stream
* causing address errors on the ST.
* - fixed STUPID coding in getopt that tried to write to
* address 0++.
* - known bug:
* still no directory support. Extracting
* files with directory names will get
* only the directory name on an open call.
*/
#define ST
#include <stdio.h>
#ifdef ST
#include <osbind.h>
long _STKSIZ = 16 * 1024; /* for new gemstart.s */
char *Defenv = "ENOENV"; /* if no cc.ini file */
extern char *getenv(),*malloc(),*index(),*fopen();
void shar();
#endif
#ifdef ULTRIX
#include <sys/types.h>
extern char *getenv(),*scdir(),*malloc(),*index();
#endif
#ifdef VMS
#include <stdio.h>
#include <types.h>
extern char *getenv(),*scdir(),*malloc();
#endif
#define BADCH ((int)'?')
#define EMSG ""
#define tell(s) {fputs(*nargv,stderr);fputs((s),stderr);fputc('\n',stderr);}
#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,-pXX)\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";
#define SED "sed 's/^%s//'" /* used to remove prefix from lines */
#define OPTSTRING "u:ap:d:bcv"
#ifdef VMS
char *index(s,c)
char *s;
char c;
{
while (*s != 0 && *s != c) s++;
if (*s == 0 && *s != c) s = 0;
return(s);
}
#endif
void main(argc, argv)
int argc;
char **argv;
{
char *ppchFiles[256];
register int C;
char **ppchList = ppchFiles;
register int errflg;
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 = "XX";
Verbose++;
Count++;
Basename++;
/* fall through to set prefix */
case 'p':
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] = 0;
header(sav);
for (ppchList = sav; *ppchList; ++ppchList)
shar(*ppchList);
puts("#\tEnd of shell archive");
puts("exit 0");
exit(0);
}
int header(ppchFiles)
char *ppchFiles[];
{
register int i;
#ifdef ST
char clock[40];
#else
extern char *ctime();
auto long clock;
#endif
register char **ppchList;
char *pchOrg;
char *pchName;
register int problems;
problems = 0;
#ifdef ST /* see cc.ini for this */
pchOrg = getenv("organization");
pchName = getenv("name");
#else
pchOrg = getenv("ORGANIZATION");
pchName = getenv("NAME");
#endif
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);
time(&clock);
#ifdef ST
printf("# This archive created: %s",clock);
#else
printf("# This archive created: %s", ctime(&clock));
#endif
if (pchName)
printf("# By:\t%s (%s)\n", pchName,pchOrg);
return(0);
}
#ifdef ST
/* create an ASCII time string and copy it into timeline. Caller
* should make sure timeline has ~35 characters space.
*/
time(timeline)
char timeline[];
{
register int mytime;
register int date;
register int hours, minutes, seconds;
int day, month, year;
static char *months[] = {"January","February","March","April",
"May","June","July","August","September",
"October","November","December"};
char *tzone;
tzone = getenv("timezone");
mytime = Tgettime();
date = Tgetdate();
seconds = (mytime&31)*2;
minutes = (mytime>>5)&63;
hours = (mytime>>11)&31;
day = (date&31);
month = (date>>5)-113;
year = ((date>>9)&31)+1980;
sprintf(timeline,"%02d-%s-%d %d:%02d:%02d %s\n",
day,months[month],year,hours,minutes,seconds,tzone);
return(TRUE);
}
#endif
int
archive(input, output)
char *input, *output;
{
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);
fclose(ioptr);
return(0);
}
else
{
fprintf(stderr, "shar: Can't open '%s'\n", input);
return(1);
}
}
void shar(file)
char *file;
{
register char *basefile;
basefile = file;
if (!strcmp(file, "."))
return;
fsize = 0;
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);
}
}
getpat(pattern)
char *pattern;
{
register char *ptr;
int temp;
ptr = pattern;
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(nargc, nargv, ostr)
int nargc;
char **nargv, *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 = index(ostr,optopt)))
{
if(!*place)
++optind;
tell(": illegal option");
}
if (oli) /* %$^& what if oli = NULL!!! */
{
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(nargc, nargv)
int nargc;
char **nargv;
{
if (nargc <= optind)
{
optarg = (char *) 0;
return(EOF);
}
else
{
optarg = nargv[optind++];
return 0;
}
}
dounshar(ArcNam)
char *ArcNam;
{
register int i,j;
register FILE *inptr,*outptr;
char line[BUFSIZ];
int DirNum = -1;
int Prefix = 0;
char Dirs[5][40],FilNam[128],Delim[40],ScrStr[128];
char *ptr;
if (!(inptr = fopen(ArcNam,"r")))
{
fprintf(stderr,"shar: Can't open archive '%s'\n", ArcNam);
return;
}
while (fgets(line,BUFSIZ,inptr))
{
if (strncmp(line,"sed ",4) == 0)
{
Prefix = 0;
if (!(ptr = index(line,'/')))
goto getfil;
if (*++ptr == '^')
++ptr;
while (*ptr++ != '/')
Prefix++;
goto getfil;
}
else if (strncmp(line,"cat ",4) == 0)
{
Prefix = 0;
getfil:
#ifdef VMS
strcpy(FilNam,"[");
#else
FilNam[0] = 0;
#endif
for (i = 0; i <= DirNum; i++)
{
#ifdef VMS
strcat(FilNam,".");
strcat(FilNam,Dirs[i]);
#else
strcat(FilNam,Dirs[i]);
strcat(FilNam,"/");
#endif
}
#ifdef VMS
strcat(FilNam,"]");
#endif
getshpar(line,">",ScrStr);
strcat(FilNam,ScrStr);
getshpar(line,"<<",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(line,"mkdir ",6) == 0)
sprintf(stderr,"Need to make directory: %s\n",&line[6]);
else if (strncmp(line,"chdir ",6) == 0)
{
if (line[6] == '.' && line[7] == '.')
DirNum--;
else
strcpy(Dirs[++DirNum],&line[6]);
if (DirNum < -1)
DirNum = -1;
}
else if (strncmp(line,"cd ",3) == 0)
{
if (line[3] == '.' && line[4] == '.')
DirNum--;
else
strcpy(Dirs[++DirNum],&line[3]);
if (DirNum < -1)
DirNum = -1;
}
}
fclose(inptr);
}
getshpar(line,sea,par)
char *line,*sea,*par;
{
register int i,j,k;
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++;
while ( *scr1 != 0 && *scr1 != ' ' && *scr1 != '\t' &&
*scr1 != '\\' && *scr1 != '\'' && *scr1 != '"' &
&
*scr1 != '\n' && *scr1 != '\r')
*par++ = *scr1++;
*par = 0;
return;
}
line++;
}
*par = 0;
}
#ifdef ST
/* since nothing ever initializes the environment table on the ST
* I'll just use my home brew cc.ini environment file.
*/
char *getenv(var)
register char *var;
{
FILE *fp;
register char *ptr;
static char line[81];
register char *safestore;
if ((fp=fopen("cc.ini","r")) == NULL)
return(Defenv);
while (fgets(line,80,fp))
{
if ((ptr=index(line,' '))!=(char *)NULL)
*ptr = '\0';
if ((ptr=index(line,'\n'))!=(char *)NULL)
*ptr = '\0';
if ((ptr=index(line,'\t'))!=(char *)NULL)
*ptr = '\0';
if ((ptr=index(line,'='))!=(char *)NULL)
*ptr = '\0';
else
continue;
++ptr;
if (strcmp(line,var)==NULL)
{
safestore = malloc(strlen(ptr)+1);
strcpy(safestore,ptr);
return(safestore);
}
else if (feof(fp))
break;
}
return(Defenv);
}
#endif
SHAR_EOF
if test 11755 -ne "`wc -c SHAR.C`"
then
echo shar: error transmitting SHAR.C '(should have been 11755 characters)'
fi
cat << \SHAR_EOF > SHAR.LNK
[tem[m:]]m:unshare.68k=gemsnew,m:unshare,gemlib[in[_nofloats],in[_nottyin],
in[_nofilesz],in[_nobinary]]
SHAR_EOF
if test 105 -ne "`wc -c SHAR.LNK`"
then
echo shar: error transmitting SHAR.LNK '(should have been 105 characters)'
fi
# End of shell archive
exit 0