/* Shar puts readable text files together in a package from which they are easy to extract. v 860712 D. Wecker for ULTRIX and the AMIGA - stripped down.. does patterns but no directories - added a -u (unshar) switch */ #include #ifdef AMIGA #include extern char *getenv(),*scdir(),*malloc(),*index(); #endif #ifdef ULTRIX #include extern char *getenv(),*scdir(),*malloc(),*index(); #endif #ifdef VMS #include extern char *getenv(),*scdir(),*malloc(); #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? */ #define SED "sed 's/^%s//'" /* used to remove prefix from lines */ #define USAGE "[-u archive] [[-a] [-p prefix] [-d delim] [-bcv] files > archive]" #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 int header(ppchFiles) char *ppchFiles[]; { extern char *ctime(); register int i; auto long clock; register int problems = 0; register char **ppchList; register char *pchOrg = getenv("ORGANIZATION"); register char *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) 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 = 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; 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': (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, "usage: shar %s\n", USAGE); 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); } getpat(pattern) 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(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: #if VMS strcpy(FilNam,"["); #else FilNam[0] = 0; #endif for (i = 0; i <= DirNum; i++) { #if VMS strcat(FilNam,"."); strcat(FilNam,Dirs[i]); #else strcat(FilNam,Dirs[i]); strcat(FilNam,"/"); #endif } #if 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; }