home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / ENTERPRS / CPM / UTILS / A / CPMSHAR.LBR / SHAR.CQ / SHAR.C
Text File  |  2000-06-30  |  14KB  |  556 lines

  1. /* 
  2.  *  Shar puts readable text files together in a package
  3.  *
  4.  *  from which they are easy to extract.
  5.  *
  6.  *    v 860716 M. Kersenbrock (tektronix!copper!michaelk) for Z80-CPM
  7.  *    - enhanced usage message
  8.  *
  9.  *    v 860712 D. Wecker for ULTRIX and the AMIGA
  10.  *    - stripped down.. does patterns but no directories
  11.  *    - added a -u (unshar) switch
  12.  */
  13.  
  14. #define CPM
  15.  
  16. #ifdef CPM
  17. #include "c:stdio.h"
  18. #include "c:fcntl.h"
  19. #else
  20. #include <stdio.h>
  21. #endif
  22.  
  23. #ifdef CPM
  24. #define void int
  25. #define fputc putc
  26. extern char *getenv(),*malloc(),*index(),*rindex();
  27. int cpmversion;
  28.  
  29. #endif
  30.  
  31. #ifdef    AMIGA
  32. #include <exec/types.h>
  33. extern char *getenv(),*scdir(),*malloc(),*index();
  34. #endif
  35.  
  36. #ifdef    ULTRIX
  37. #include <sys/types.h>
  38. extern char *getenv(),*scdir(),*malloc(),*index();
  39. #endif
  40.  
  41. #ifdef    VMS
  42. #include <types.h>
  43. extern char *getenv(),*scdir(),*malloc();
  44. #endif
  45.  
  46.  
  47. #define BADCH    ((int)'?')
  48. #define EMSG    ""
  49. #define tell(s)    {fputs(*nargv,stderr);fputs((s),stderr);fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);}
  50. #define rescanopts()    (optind = 1)
  51.  
  52. int    optind = 1,        /* index into parent argv vector */
  53.     optopt;            /* character checked for validity */
  54. long    fsize;            /* length of file */
  55. char    *optarg;        /* argument associated with option */
  56. char    *sav[100];        /* saved file names */
  57. int    savind;            /* save index */
  58.  
  59. /* OPTIONS */
  60. int     Verbose = 0;           /* provide append/extract feedback */
  61. int     Basename = 0;          /* extract into basenames */
  62. int     Count = 0;             /* count characters to check transfer */
  63. char    *Delim = "SHAR_EOF";   /* put after each file */
  64. char    Filter[100] = "cat";   /* used to extract archived files */
  65. char    *Prefix = NULL;        /* line prefix to avoid funny chars */
  66. int    UnShar = 0;           /* do we unshar an input file? */
  67.  
  68. char Usage1[] = 
  69. "\nSHAR: Create/extract file archive for extraction by /bin/sh (normally).\n\
  70. \n\
  71. usage: shar [-u archive] [[-a] [-p prefix]\
  72.  [-d delim] [-bcv] files > archive]\n\
  73. \n\
  74.     where:    -a  all the options (v,c,b,-pXX)\n";
  75.  
  76. char Usage2[] = 
  77. "        -b  extract absolute paths into current directory\n\
  78.         -c  check filesizes on extraction\n\
  79.         -d  use this EOF delimiter instead of SHAR_EOF\n";
  80.  
  81. char Usage3[] =
  82. "        -p  use this as prefix to each line in archived files\n\
  83.         -u  unshar <archive>\n\
  84.         -v  verbose on extraction, incl. echoing filesizes\n";
  85.  
  86.  
  87. #define    SED "sed 's/^%s//'"    /* used to remove prefix from lines */
  88.  
  89. #ifdef CPM
  90. #define    OPTSTRING "U:AP:D:BCV"
  91. #else
  92. #define    OPTSTRING "u:ap:d:bcv"
  93. #endif
  94.  
  95. #ifdef    VMS
  96. char *index(s,c)
  97. char    *s;
  98. char    c;
  99. {
  100.     while (*s != 0 && *s != c) s++;
  101.     if (*s == 0 && *s != c) s = 0;
  102.     return(s);    
  103. }
  104. #endif
  105.  
  106. int header(ppchFiles)
  107. char *ppchFiles[];
  108. {
  109.     extern char *ctime();
  110.     register int i;
  111.     auto long clock;
  112.     register char **ppchList;
  113.     char *pchOrg;
  114.     char *pchName;
  115.     register int  problems = 0;
  116.  
  117.     pchOrg = getenv("ORGANIZATION");
  118.     pchName = getenv("NAME");
  119.  
  120.     puts("#\tThis is a shell archive.");
  121.     puts("#\tRemove everything above and including the cut line.");
  122.     puts("#\tThen run the rest of the file through sh.");
  123.     puts("#----cut here-----cut here-----cut here-----cut here----#");
  124.     puts("#!/bin/sh");
  125.     puts("# shar:    Shell Archiver");
  126.     puts("#\tRun the following text with /bin/sh to create:");
  127.     for (ppchList = ppchFiles; *ppchList; ++ppchList)
  128.         printf("#\t%s\n", *ppchList);
  129. #ifdef CPM
  130.   if (cpmversion >= 0x30) {
  131. #endif
  132.     (void) time(& clock);
  133.     printf("# This archive created: %s", ctime(&clock));
  134. #ifdef CPM
  135.   }
  136. #endif
  137.     if (pchName)
  138.         printf("# By:\t%s (%s)\n", pchName, 
  139.         pchOrg ? pchOrg : "Dave Wecker Midnight Hacks");
  140.     return(0);
  141. }
  142.  
  143. int archive(input, output)
  144. char *input, *output;
  145. {
  146.     auto char line[BUFSIZ];
  147.     register FILE *ioptr;
  148.  
  149.     if (ioptr = fopen(input, "r")) {
  150.         printf("%s << \\%s > %s\n", Filter, Delim, output);
  151.         while(fgets(line, BUFSIZ, ioptr)) {
  152.             if (Prefix) fputs(Prefix, stdout);
  153.             fputs(line, stdout);
  154.             if (Count) fsize += strlen(line);
  155.         }
  156.         puts(Delim);
  157.         (void) fclose(ioptr);
  158.         return(0);
  159.     } 
  160.     else {
  161.         fprintf(stderr, "shar: Can't open '%s'\n", input);
  162.         return(1);
  163.     }
  164. }
  165.  
  166.  
  167. void shar(file)
  168. char *file;
  169. {
  170.     register char *basefile;
  171.     basefile = file;
  172.     if (!strcmp(file, "."))
  173.         return;
  174.     fsize = 0;
  175.     if (Basename) {
  176.         while(*basefile)
  177.             basefile++;        /* go to end of name */
  178.         while(basefile > file && *(basefile-1) != '/')
  179.             basefile--;
  180.     }
  181.     if (Verbose) printf("echo shar: extracting %s\n", basefile);
  182.     if (archive(file, basefile)) exit(66);
  183.     if (Count) {
  184.         printf("if test %ld -ne \"`wc -c %s`\"\n",fsize,basefile);
  185.         printf("then\necho shar: error transmitting %s ",basefile);
  186.         printf("'(should have been %ld characters)'\nfi\n",fsize);
  187.     }
  188. }
  189.  
  190. int main(argc, argv)
  191. int argc;
  192. char **argv;    
  193. {
  194.     auto char *ppchFiles[256];
  195.     register int  C;
  196.     register char **ppchList = ppchFiles;
  197.     register int errflg = 0;
  198.  
  199. #ifdef CPM
  200.     cpmversion = (bdoshl(0x0c,0) & 0xff);
  201. #endif
  202.  
  203.     while(EOF != (C = getopt(argc, argv, OPTSTRING))) {
  204. #ifdef CPM
  205.         switch(isupper(C) ? tolower(C) : C ) {
  206. #else
  207.         switch(C) {
  208. #endif
  209.         case 'v': 
  210.             Verbose++; 
  211.             break;
  212.         case 'c': 
  213.             Count++; 
  214.             break;
  215.         case 'b': 
  216.             Basename++; 
  217.             break;
  218.         case 'd': 
  219.             Delim = optarg; 
  220.             break;
  221.         case 'a': /* all the options */
  222.             optarg = "XX";
  223.             Verbose++;
  224.             Count++;
  225.             Basename++;
  226.             /* fall through to set prefix */
  227.         case 'p': 
  228.             (void) sprintf(Filter, SED, Prefix = optarg); 
  229.             break;
  230.         case 'u':
  231.             UnShar++;
  232.             dounshar(optarg);
  233.             break;
  234.         default: 
  235.             errflg++;
  236.         }
  237.     }
  238.     if (UnShar) exit(0);
  239.  
  240.     C = getarg(argc, argv);
  241.     if (errflg || EOF == C) {
  242.         if (EOF == C)
  243.             fprintf(stderr, "shar: No input files\n");
  244.         fprintf(stderr, "%s%s%s", Usage1, Usage2, Usage3);
  245.         exit(1);
  246.     }
  247.  
  248.     savind = 0;
  249.     do {
  250.         if (getpat(optarg)) exit(2);
  251.     } 
  252.     while (EOF != (C = getarg(argc, argv)));
  253.  
  254.     sav[savind] = 0;
  255.     header(sav);
  256.     for (ppchList = sav; *ppchList; ++ppchList) {
  257.  
  258. #ifdef CPM
  259.      strlower(*ppchList);
  260. #endif
  261.  
  262.      shar(*ppchList);
  263.     }
  264.     puts("#\tEnd of shell archive");
  265.     puts("exit 0");
  266.     exit(0);
  267. }
  268.  
  269. getpat(pattern)
  270. char *pattern;
  271. {
  272.     register char *ptr;
  273.     int temp;
  274.  
  275. #ifdef AMIGA
  276.     while (ptr = scdir(pattern)) {
  277. #else
  278.     ptr = pattern;
  279.     {
  280. #endif
  281.     sav[savind] = malloc(strlen(ptr)+1);
  282.     strcpy(sav[savind++],ptr);
  283. #ifdef CPM
  284.     temp = open(ptr,O_RDONLY);
  285.     if (temp == -1) {
  286. #else
  287.     if (access(ptr,4)) {
  288. #endif
  289.         printf("No read access for file: %s\n",ptr);
  290.         return(-1);
  291.     }
  292.  
  293. #ifdef CPM
  294.     close(temp);
  295. #endif
  296.     }
  297.     return(0);
  298. }
  299.  
  300.  
  301. /*
  302.  * get option letter from argument vector
  303.  */
  304. int
  305. getopt(nargc, nargv, ostr)
  306. int nargc;
  307. char **nargv, *ostr;
  308. {
  309.     register char    *oli;        /* option letter list index */
  310.     static char    *place = EMSG;    /* option letter processing */
  311.     if(!*place) {            /* update scanning pointer */
  312.         if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place)
  313.          return(EOF);
  314.         if (*place == '-') {    /* found "--" */
  315.             ++optind;
  316.             return EOF;
  317.         }
  318.     }                /* option letter okay? */
  319.     if ((optopt = (int)*place++) == (int)':' || !(oli = index(ostr,optopt))) {
  320.         if(!*place) ++optind;
  321.         tell(": illegal option -- ");
  322.     }
  323.     if (*++oli != ':') {        /* don't need argument */
  324.         optarg = NULL;
  325.         if (!*place)
  326.             ++optind;
  327.     } 
  328.     else {                /* need an argument */
  329.         if (*place) {            /* no white space */
  330.             optarg = place;
  331.         } 
  332.         else {
  333.         if (nargc <= ++optind) {    /* no arg */
  334.                     place = EMSG;
  335.                     tell(": option requires an argument -- ");
  336.                 }
  337.             else {
  338.                 optarg = nargv[optind];    /* white space */
  339.         }
  340.         }
  341.         place = EMSG;
  342.         ++optind;
  343.     }
  344.     return(optopt);            /* dump back option letter */
  345. }
  346.  
  347.  
  348. int
  349. getarg(nargc, nargv)
  350. int nargc;
  351. char **nargv;
  352. {
  353.     if (nargc <= optind) {
  354.         optarg = (char *) 0;
  355.         return EOF;
  356.     } 
  357.     else {
  358.         optarg = nargv[optind++];
  359.         return 0;
  360.     }
  361. }
  362.  
  363. dounshar(ArcNam)
  364. char *ArcNam;
  365. {
  366.     register int i,j;
  367.     register FILE *inptr,*outptr;
  368.     auto char line[BUFSIZ];
  369.     int DirNum = -1;
  370.     int Prefix = 0;
  371.     char Dirs[5][40],FilNam[128],Delim[40],ScrStr[128];
  372.     char *ptr;
  373.  
  374.     if (!(inptr = fopen(ArcNam,"r"))) {
  375.         fprintf(stderr,"shar: Can't open archive '%s'\n", ArcNam);
  376.         return;
  377.     }
  378.     while (fgets(line,BUFSIZ,inptr)) {
  379.         if (strncmp(line,"sed ",4) == 0) {
  380.             Prefix = 0;
  381.             if (!(ptr = index(line,'/'))) goto getfil;
  382.             if (*++ptr == '^') ++ptr;
  383.             while (*ptr++ != '/') Prefix++;
  384.             goto getfil;
  385.         }
  386.         else if (strncmp(line,"cat ",4) == 0) {
  387.             Prefix = 0;
  388.             ;
  389. getfil:
  390.  
  391. #ifdef    VMS
  392.             strcpy(FilNam,"[");
  393. #else
  394.             FilNam[0] = 0;
  395. #endif
  396.  
  397.             for (i = 0; i <= DirNum; i++) {
  398.  
  399. #ifdef    VMS
  400.                 strcat(FilNam,".");
  401.                 strcat(FilNam,Dirs[i]);
  402. #else
  403.                 strcat(FilNam,Dirs[i]);
  404.                 strcat(FilNam,"/");
  405. #endif
  406.  
  407.             }
  408.  
  409.  
  410. #ifdef    VMS
  411.             strcat(FilNam,"]");
  412. #endif
  413.  
  414.             getshpar(line,">",ScrStr);
  415.             strcat(FilNam,ScrStr);
  416.  
  417. #ifdef CPM
  418.         tocpmformat(FilNam);    /* tweek format as needed */
  419. #endif
  420.             getshpar(line,"<<",Delim);
  421.             fprintf(stderr,"Creating %s ...",FilNam);
  422.             outptr = fopen(FilNam,"w");
  423.             while (fgets(line,BUFSIZ,inptr)) {
  424.                 if (strncmp(line,Delim,strlen(Delim)) == 0) break;
  425.                 if (outptr) fputs(&line[Prefix],outptr);
  426.             }
  427.             if (outptr) {
  428.                 fclose(outptr);
  429.                 fprintf(stderr,"...done\n");
  430.             }
  431.             else fprintf(stderr,"...error in creating file\n");
  432.         }
  433.         else if (strncmp(line,"mkdir ",6) == 0) {
  434.             sprintf(stderr,"Need to make directory: %s\n",&line[6]);
  435.         }
  436.         else if (strncmp(line,"chdir ",6) == 0) {
  437.             if (line[6] == '.' && line[7] == '.') DirNum--;
  438.             else strcpy(Dirs[++DirNum],&line[6]);
  439.             if (DirNum < -1) DirNum = -1;
  440.         }
  441.         else if (strncmp(line,"cd ",3) == 0) {
  442.             if (line[3] == '.' && line[4] == '.') DirNum--;
  443.             else strcpy(Dirs[++DirNum],&line[3]);
  444.             if (DirNum < -1) DirNum = -1;
  445.         }
  446.     }
  447.     fclose(inptr);
  448. }
  449.  
  450. getshpar(line,sea,par)
  451. char *line,*sea,*par;
  452. {
  453.     register int i,j,k;
  454.     register char *scr1,*scr2;
  455.  
  456.     while (*line) {
  457.         scr1 = line;
  458.         scr2 = sea;
  459.         while (*scr1 && *scr2 && *scr1 == *scr2) { 
  460.             scr1++; 
  461.             scr2++; 
  462.         }
  463.         if (*scr2 == 0) {
  464.             if (*scr1 == 0) { 
  465.                 *par = 0; 
  466.                 return; 
  467.             }
  468.             while ( *scr1 == ' ' || *scr1 == '\t' ||
  469.                 *scr1 == '\\' || *scr1 == '\'' || *scr1 == '"') scr1++;
  470.             while ( *scr1 != 0 && *scr1 != ' ' && *scr1 != '\t' &&
  471.                 *scr1 != '\\' && *scr1 != '\'' && *scr1 != '"' &&
  472.                 *scr1 != '\n' && *scr1 != '\r') *par++ = *scr1++;
  473.             *par = 0;
  474.             return;
  475.         }
  476.         line++;
  477.     }
  478.     *par = 0;
  479. }
  480.  
  481.  
  482. #ifdef CPM
  483.  
  484. tocpmformat(filename)
  485. char *filename;
  486. {
  487.     char buffer[100];
  488.     char extension[100];
  489.     register char *temp;
  490.     int mod = 0;
  491.  
  492.     strcpy(buffer,filename);
  493.  
  494.     /* 
  495.       * Make sure we get rid of any pathnames
  496.      */
  497.     if ((temp=rindex(buffer,'/')) != 0) {
  498.         strcpy(buffer,(char *)((temp-buffer)+filename+1));
  499.         mod = 1;
  500.     }
  501.  
  502.     if (strlen(filename) <= 8) {
  503.         if (mod != 0) {
  504.             strcpy(filename,buffer);
  505.         }
  506.         return(0);
  507.     }
  508.  
  509.     /*
  510.      * If it already is in "CPM" format we'll check if we need
  511.      * to truncate the front filename part.
  512.      */
  513.     if ((temp=index(buffer,'.')) != 0 ) {
  514.         if ((temp-buffer) < 8) {
  515.             if (mod != 0) {
  516.                 strcpy(filename,buffer);
  517.             }
  518.             return(0);
  519.         }
  520.         else {
  521.             strcpy(extension,temp);
  522.             strcpy(&buffer[8],extension);
  523.             buffer[12] = '\0';
  524.             strcpy(filename,buffer);
  525.             return(1);
  526.         }
  527.     }
  528.             
  529.     /*
  530.      * OK, filename is longer than can be handled, and it doesnt have
  531.      * a filetype "." marker already.  We will put one in to minimize
  532.      * truncation.
  533.      */
  534.     strcpy(extension,&buffer[8]);
  535.     buffer[8] = '.';
  536.     strcpy(&buffer[9],extension);
  537.     buffer[12] = '\0';
  538.     strcpy(filename,buffer);
  539.     return(2);
  540. }
  541.  
  542.  
  543.     
  544. strlower(string)
  545. char *string;
  546. {
  547.     register char *pointer;
  548.     char c;
  549.     for (pointer = string ; (c=*pointer) != '\0' ; pointer++ ) {
  550.         if (isupper(c))
  551.             *pointer = tolower(c);
  552.     }
  553. }
  554.  
  555. #endif
  556.