home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 100-199 / ff174.lzh / Sh / sh.c < prev   
C/C++ Source or Header  |  1989-02-04  |  8KB  |  407 lines

  1. /* sh - JimG's version of sh to unshar files */
  2. char *help = "\
  3. Usage: sh [-v(012)] [-s(01)] [-o(01)] [filename]\n\
  4.   -v = verbosity\n\
  5.     0 = print nothing\n\
  6.     1 = print anything not understood\n\
  7.     2 = echo commands as they are executed\n\
  8.   -s = safety\n\
  9.     1 = exit when something is not understood\n";
  10. char *help2 = "\
  11.   -o = overwrite\n\
  12.     1 = don't overwrite existing files\n\
  13.   filename\n\
  14.     read shar file from here (or stdin if missing)\n";
  15.  
  16. #define NDEBUG
  17.  
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <assert.h>
  22.  
  23. #define ST_CMDLINE    1
  24. #define ST_CAT        2
  25. #define ST_SED        3
  26.  
  27. #define TST_OUT        1
  28. #define TST_QUOTE    2
  29. #define TST_ALPHA    3
  30. #define TST_DIR        4
  31.  
  32. #define BUFSIZE 161
  33. char buf1[BUFSIZE], buf2[BUFSIZE];
  34. char *buff1end = buf1 + BUFSIZE;
  35.  
  36. unsigned short int verbosity = 1;
  37. unsigned short int safety = 0;
  38. unsigned short int overwrite = 1;
  39.  
  40. FILE *fopen(char*,char*);
  41. void sh(FILE*);
  42. int tokenize(char**,int,char*);
  43. void bumpstr(char*);
  44. void ind_error(char**,int);
  45. void fileparse(char**,int,char*,FILE**);
  46. int fillbuffer(char*,int,FILE*);
  47. int match(char*,char*);
  48. void ptokens(char**,int,FILE*);
  49.  
  50. int
  51. fillbuffer(buf,len,fp)        /* This will read up to len-1 characters */
  52. char *buf;
  53. int len;
  54. FILE *fp;
  55. {
  56.     register int i, c;
  57.     
  58.     for (i=1; i<len; i++) {
  59.         c = getc(fp);
  60.         if (c == EOF) break;
  61.         *(buf++) = c;
  62.         if (c == '\n') break;
  63.     }
  64.     *buf = 0;
  65.     return (c);
  66. }
  67.  
  68. main(argc,argv)
  69. int argc;
  70. char *argv[];
  71. {
  72.     register FILE *fp;
  73.     register char *s;
  74.     
  75.     while ((--argc > 0) && ((*++argv)[0] == '-'))
  76.         for (s = argv[0]+1; *s != '\0'; s++)
  77.         switch (*s) {
  78.         case 'v':
  79.             switch (s[1]) {
  80.             case '0':
  81.             case '1':
  82.             case '2':
  83.                 verbosity = (*++s) - '0';
  84.                 break;
  85.             default:
  86.                 verbosity = 1;
  87.                 break;
  88.             }
  89.             break;
  90.         case 's':
  91.             switch(s[1]) {
  92.             case '0':
  93.             case '1':
  94.                 safety = (*++s) - '0';
  95.                 break;
  96.             default:
  97.                 safety = 1;
  98.                 break;
  99.             }
  100.             break;
  101.         case 'o':
  102.             switch(s[1]) {
  103.             case '0':
  104.             case '1':
  105.                 overwrite = (*++s) - '0';
  106.                 break;
  107.             default:
  108.                 overwrite = 1;
  109.                 break;
  110.             }
  111.             break;
  112.         default:
  113.             fputs("sh: illegal option ",stderr);
  114.             putc(*s,stderr);
  115.             putc('\n',stderr);
  116.             exit(10);
  117.             break;
  118.         }
  119.     switch (argc) {
  120.     case 0:    sh(stdin);
  121.         break;
  122.     case 1:    fp = fopen(argv[0],"r");
  123.         if (fp == NULL) {
  124.             fputs("Error - can't open file: ",stderr);
  125.             fputs(argv[0],stderr);
  126.             putc('\n',stderr);
  127.             exit(10);
  128.         }
  129.         sh(fp);
  130.         fclose(fp);
  131.         break;
  132.     default:
  133.         fputs(help,stderr);
  134.         fputs(help2,stderr);
  135.         exit(5);
  136.     }
  137.     return (0);
  138. }
  139.  
  140. int
  141. match(pat,str)
  142. register char *pat, *str;
  143. {
  144.     while (*pat != '\0')
  145.         if (*pat++ != *str++) return (0);
  146.     return(1);
  147. }
  148.  
  149. void
  150. sh(fp)
  151. FILE *fp;
  152. {
  153.     int state = ST_CMDLINE;
  154.     int oldc, c, tcnt;
  155.     FILE *outfp;
  156.     char *tokens[20];
  157.     char schar;
  158.  
  159.     oldc = '\n';
  160.     while ((c = fillbuffer(buf1, BUFSIZE, fp)) != EOF ) {
  161.     switch (state) {
  162.     case ST_CMDLINE:
  163.         if (oldc != '\n') break;
  164.         if (*buf1 == '#') break;
  165.         tcnt = tokenize(tokens, 20, buf1);
  166.         if (tcnt == 0) break;
  167.         if (strcmp(tokens[0],"echo") == 0) {
  168.             ptokens(tokens+1,tcnt-1,stdout);
  169.         } else if (strcmp(tokens[0],"cat") == 0) {
  170.             fileparse(tokens,tcnt,buf2,&outfp);
  171.             if (*buf2) {
  172.                 state = ST_CAT;
  173.                 if (verbosity == 2) {
  174.                     fputs("I am executing:   ",stdout);
  175.                     ptokens(tokens,tcnt,stdout);
  176.                 }
  177.             } else if (outfp != stdout) fclose(outfp);
  178.         } else if (strcmp(tokens[0],"sed") == 0) {
  179.             fileparse(tokens,tcnt,buf2,&outfp);
  180.             if (*buf2) {
  181.                 if (verbosity == 2) {
  182.                 fputs("I am executing:   ",stdout);
  183.                 ptokens(tokens,tcnt,stdout);
  184.                 }
  185.                 if ((tokens[1][0] == 's') &&
  186.                 (tokens[1][1] == tokens[1][4]) &&
  187.                 (tokens[1][2] == '^') &&
  188.                 (tokens[1][5] == tokens[1][1])) {
  189.                     schar = tokens[1][3];
  190.                     state = ST_SED;
  191.                 } else {
  192.                 fputs("Warning -- unknown sed option\n",stderr);
  193.                 fputs(tokens[1],stderr);
  194.                 fputs("\nI am treating it as a 'cat'\n",stderr);
  195.                 fflush(stderr);
  196.                 state = ST_CAT;
  197.                 }
  198.             } else if (outfp != stdout) fclose(outfp);
  199.         } else if (strcmp(tokens[0], "exit") == 0) {
  200.             return;
  201.         } else {
  202.             if (verbosity > 0) {
  203. /*              fputs("I don't understand and am ignoring:\n",stdout);*/
  204.               fputs("Don't understand: ",stdout);
  205.               ptokens(tokens,tcnt,stdout);
  206.             }
  207.             if (safety == 1) exit(5);
  208.         }
  209.         break;
  210.     case ST_CAT:
  211.         if ((oldc == '\n') && (match(buf2,buf1))) {
  212.             state = ST_CMDLINE;
  213.             if (outfp != stdout) fclose(outfp);
  214.         } else fputs(buf1,outfp);
  215.         break;
  216.     case ST_SED:
  217.         if ((oldc == '\n') && (match(buf2,buf1))) {
  218.             state = ST_CMDLINE;
  219.             if (outfp != stdout) fclose(outfp);
  220.         } else if ((oldc == '\n') && (*buf1 == schar))
  221.             fputs(buf1+1,outfp);
  222.         else fputs(buf1,outfp);
  223.         break;
  224.     default:
  225.         fputs("\nInternal Error -- unknown state!\n",stderr);
  226.         exit(20);
  227.     }
  228.     oldc = c;
  229.     }
  230. }
  231.  
  232. void
  233. ptokens(tokens, size, fp)
  234. char *tokens[];
  235. int size;
  236. FILE *fp;
  237. {
  238.     register int i;
  239.     
  240.     for (i = 0; i < (size - 1); i++) {
  241.         fputs(tokens[i],fp);
  242.         putc(' ',fp);
  243.     }
  244.     if (size > 0) fputs(tokens[size - 1],fp);
  245.     putc('\n',fp);
  246.     fflush(fp);
  247. }
  248.  
  249. int
  250. tokenize(tokens, tsize, buf)
  251. char *tokens[];
  252. int tsize;
  253. char *buf;
  254. {
  255.     register char c;
  256.     char quote;
  257.     int tcnt;
  258.     char *tbuf;
  259.     int state;
  260.  
  261.     tcnt = 0;
  262.     state = TST_OUT;
  263.     for (; ((c = *buf) != NULL); buf++) {
  264.         switch (state) {
  265.         case TST_OUT:
  266.         switch (c) {
  267.         case ' ':
  268.         case '\t':
  269.         case '\n':
  270.             break;
  271.         case '\'':
  272.         case '"':
  273.         case '`':
  274.             quote = c;
  275.             state = TST_QUOTE;
  276.             if (tcnt >= tsize) return(tsize);
  277.             tokens[tcnt++] = tbuf = (buf + 1);
  278.             tbuf++;
  279.             break;
  280.         case '<':
  281.         case '>':
  282.             state = TST_DIR;
  283.             if (tcnt >= tsize) return(tsize);
  284.             tokens[tcnt++] = tbuf = buf;
  285.             tbuf++;
  286.             break;
  287.         case '\\':
  288.             buf++;
  289.         default:
  290.             state = TST_ALPHA;
  291.             if (tcnt >= tsize) return(tsize);
  292.             tokens[tcnt++] = tbuf = buf;
  293.             tbuf++;
  294.             break;
  295.         } /* end of switch (c) */
  296.         break;
  297.         case TST_QUOTE:
  298.         if (c == quote) {
  299.             *buf = 0;
  300.             state = TST_OUT;
  301.         } else {
  302. /*            *tbuf++ = c; */        /* Currently no-op */
  303.         }
  304.         break;
  305.         case TST_DIR:
  306.         if ((c != '>') && (c != '<')) {
  307.             if ((c != ' ') &&
  308.                 (c != '\t') &&
  309.                 (c != '\n')) bumpstr(buf);
  310.             *buf = 0;
  311.             state = TST_OUT;
  312.         } else {
  313. /*            *tbuf++ = c; */        /* Currently no-op */
  314.         }
  315.         break;
  316.         case TST_ALPHA:
  317.         if ((c == ' ') ||
  318.             (c == '\t') ||
  319.             (c == '\n')) {
  320.             *tbuf = 0;
  321.             state = TST_OUT;
  322.         } else if (c != '\\') {
  323.             *tbuf++ = c;
  324. /*            *tbuf++ = c; */        /* Currently no-op */
  325.         }
  326.         break;
  327.         } /* end switch (state) */
  328.     }
  329.     return (tcnt);
  330. }
  331.  
  332. void
  333. bumpstr(buff)        /* buff has to be a pointer in buf1 !!!!! */
  334. register char *buff;
  335. {
  336.     register char c1, c2;
  337.     
  338.     assert(((buff >= buf1) && (buff < buff1end)));
  339.  
  340.     c1 = *buff++;
  341.     while (buff != buff1end) {
  342.         c2 = *buff;
  343.         *buff++ = c1;
  344.         if ((buff == buff1end) || (c1 == 0)) break;
  345.         c1 = *buff;
  346.         *buff++ = c2;
  347.         if (c2 == 0) break;
  348.     }
  349. }
  350.  
  351. void
  352. ind_error(tokens, tcnt)
  353. char *tokens[];
  354. int tcnt;
  355. {
  356.     fputs("Error in indirection -- ignored\n",stderr);
  357.     ptokens(tokens,tcnt,stderr);
  358. }
  359.  
  360. void
  361. fileparse(tokens, tcnt, buf, outfp)
  362. char *tokens[];
  363. int tcnt;
  364. char *buf;
  365. FILE **outfp;
  366. {
  367.     int i;
  368.  
  369.     *buf = 0;
  370.     *outfp = NULL;
  371.     
  372.     for (i=0; i < tcnt; i++) {
  373.         if (strcmp(">",tokens[i])==0) {
  374.         if (*outfp) ind_error(tokens,tcnt);
  375.         else if (++i == tcnt) ind_error(tokens,tcnt);
  376.         else {
  377.             if (overwrite == 1) {
  378.                 *outfp = fopen(tokens[i],"r");
  379.                 if (*outfp != NULL) {
  380.                 fputs("Warning: will not overwrite: ",stderr);
  381.                 fputs(tokens[i],stderr);
  382.                 putc('\n',stderr);
  383.                 fflush(stderr);
  384.                 fclose(*outfp);
  385.                 tokens[i]="nil:";
  386.                 }
  387.             }
  388.             *outfp = fopen(tokens[i],"w");
  389.             if (*outfp == NULL) ind_error(tokens,tcnt);
  390.         }
  391.         } else if (strcmp(">>",tokens[i])==0) {
  392.         if (*outfp) ind_error(tokens,tcnt);
  393.         else if (++i == tcnt) ind_error(tokens,tcnt);
  394.         else {
  395.             *outfp = fopen(tokens[i],"a");
  396.             if (*outfp == NULL) ind_error(tokens,tcnt);
  397.         }
  398.         } else if (strcmp("<<",tokens[i])==0) {
  399.         if (*buf) ind_error(tokens,tcnt);
  400.         else if (++i == tcnt) ind_error(tokens,tcnt);
  401.         else strcpy(buf,tokens[i]);
  402.         }
  403.     } /* end for */
  404.     if (*outfp == NULL) *outfp = stdout;
  405. }
  406.  
  407.