home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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
- *
- * 081991 Fred C. Smith (uunet!samsung!wizvax!fcshome!fredex)
- * - update/modify for MSC 5.1.
- */
-
- #ifndef MSDOS
- #define MSDOS
- #endif
-
- #ifdef CPM
- #include "c:stdio.h"
- #include "c:fcntl.h"
- #else
- #include <stdio.h>
- #endif
-
- #ifdef CPM
- #define void int
- #define fputc putc
- extern char *getenv(),*malloc(),*index(),*rindex();
- int cpmversion;
-
- #endif
-
- #ifdef AMIGA
- #include <exec/types.h>
- extern char *getenv(),*scdir(),*malloc(),*index();
- #endif
-
- #ifdef ULTRIX
- #include <sys/types.h>
- extern char *getenv(),*scdir(),*malloc(),*index();
- #endif
-
- #ifdef VMS
- #define VMSdef 1
- #include <types.h>
- extern char *getenv(),*scdir(),*malloc();
- #endif
-
- #ifdef MSDOS
- #define MSDOSdef 1
- #include <stdlib.h>
- /*
- extern char *getenv(),*scdir(),*malloc();
- */
- #endif
-
- #ifndef VMSdef
- #define VMSdef 0
- #endif
-
- #ifndef MSDOSdef
- #define MSDOSdef 0
- #endif
-
- #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,-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 */
-
- #ifdef CPM
- #define OPTSTRING "U:AP:D:BCV"
- #else
- #define OPTSTRING "u:ap:d:bcv"
- #endif
-
- #if VMSdef | MSDOSdef
- char *index(s,c)
- char *s;
- char c;
- {
- while (*s != 0 && *s != c) s++;
- if (*s == 0 && *s != c) s = 0;
- return(s);
- }
- #endif
-
- int header(ppchFiles)
- char *ppchFiles[];
- {
- extern char *ctime();
- register int i;
- auto long clock;
- register 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);
- #ifdef CPM
- if (cpmversion >= 0x30) {
- #endif
- (void) time(& clock);
- printf("# This archive created: %s", ctime(&clock));
- #ifdef CPM
- }
- #endif
- if (pchName)
- printf("# By:\t%s (%s)\n", pchName,
- pchOrg ? pchOrg : "Dave Wecker Midnight Hacks");
- return(0);
- }
-
- int archive(input, output)
- char *input, *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(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);
- }
- }
-
- int main(argc, argv)
- int argc;
- char **argv;
- {
- auto char *ppchFiles[256];
- register int C;
- register char **ppchList = ppchFiles;
- register int errflg = 0;
-
- #ifdef CPM
- cpmversion = (bdoshl(0x0c,0) & 0xff);
- #endif
-
- /*
- if (in the unlikely case that) you use Allen Holub's Unix-Like shell,
- you will want to enable this call to reargv. (For those of you who don't
- know what this is, Allen's shell provides a 2048 byte command-line, which
- is passed from the shell to the application in an environment variable.
- This call to reargv retrieves the text, vectorizes it and stuffs it into
- argv.)
- reargv (&argc, &argv);
- */
-
- while(EOF != (C = getopt(argc, argv, OPTSTRING))) {
- #ifdef CPM
- switch(isupper(C) ? tolower(C) : C ) {
- #else
- switch(C) {
- #endif
- 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':
- (void) sprintf(Filter, SED, Prefix = optarg);
- break;
- case 'u':
- UnShar++;
- dounshar(optarg);
- break;
- default:
- errflg++;
- }
- }
- #ifdef VMS
- if (UnShar) exit(1);
- #else
- if (UnShar) exit(0);
- #endif
- 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) {
-
- #ifdef CPM
- strlower(*ppchList);
- #endif
-
- shar(*ppchList);
- }
- puts("#\tEnd of shell archive");
- puts("exit 0");
- #ifdef VMS
- exit(1);
- #else
- exit(0);
- #endif
- }
-
- getpat(pattern)
- char *pattern;
- {
- register char *ptr;
- int temp;
-
- #ifdef AMIGA
- while (ptr = scdir(pattern)) {
- #else
- ptr = pattern;
- {
- #endif
- sav[savind] = malloc(strlen(ptr)+1);
- strcpy(sav[savind++],ptr);
- #ifdef CPM
- temp = open(ptr,O_RDONLY);
- if (temp == -1) {
- #else
- if (access(ptr,4)) {
- #endif
- printf("No read access for file: %s\n",ptr);
- return(-1);
- }
-
- #ifdef CPM
- close(temp);
- #endif
- }
- 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 != ':') { /* 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;
- auto 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);
-
- #ifdef CPM
- tocpmformat(FilNam); /* tweek format as needed */
- #endif
- 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) {
- fprintf(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 CPM
-
- tocpmformat(filename)
- char *filename;
- {
- char buffer[100];
- char extension[100];
- register char *temp;
- int mod = 0;
-
- strcpy(buffer,filename);
-
- /*
- * Make sure we get rid of any pathnames
- */
- if ((temp=rindex(buffer,'/')) != 0) {
- strcpy(buffer,(char *)((temp-buffer)+filename+1));
- mod = 1;
- }
-
- if (strlen(filename) <= 8) {
- if (mod != 0) {
- strcpy(filename,buffer);
- }
- return(0);
- }
-
- /*
- * If it already is in "CPM" format we'll check if we need
- * to truncate the front filename part.
- */
- if ((temp=index(buffer,'.')) != 0 ) {
- if ((temp-buffer) < 8) {
- if (mod != 0) {
- strcpy(filename,buffer);
- }
- return(0);
- }
- else {
- strcpy(extension,temp);
- strcpy(&buffer[8],extension);
- buffer[12] = '\0';
- strcpy(filename,buffer);
- return(1);
- }
- }
-
- /*
- * OK, filename is longer than can be handled, and it doesnt have
- * a filetype "." marker already. We will put one in to minimize
- * truncation.
- */
- strcpy(extension,&buffer[8]);
- buffer[8] = '.';
- strcpy(&buffer[9],extension);
- buffer[12] = '\0';
- strcpy(filename,buffer);
- return(2);
- }
-
-
-
- strlower(string)
- char *string;
- {
- register char *pointer;
- char c;
- for (pointer = string ; (c=*pointer) != '\0' ; pointer++ ) {
- if (isupper(c))
- *pointer = tolower(c);
- }
- }
-
- #endif
-