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