home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / xloadimg.zip / xloadimage.4.1 / uufilter.c < prev    next >
C/C++ Source or Header  |  1993-10-28  |  5KB  |  215 lines

  1. /* uufilter.c:
  2.  *
  3.  * "smart" uudecode function that skips junk lines and outputs data to
  4.  * stdout rather than a filename.
  5.  *
  6.  * jim frost 10.21.93
  7.  *
  8.  * 10.27.93 fixed a bug where short uuencoded lines were stripped out
  9.  *          due to a bad "short length" calculation.  added -v flag at
  10.  *          the same time.
  11.  */
  12.  
  13. #include <stdio.h>
  14.  
  15. main(argc, argv)
  16.      int argc;
  17.      char **argv;
  18. {
  19.   FILE *inf, *outf;
  20.   char *infilename = NULL;
  21.   char *outfilename = NULL;
  22.   int dump_to_file = 1; /* true if we're outputting to a file */
  23.   int stringent = 1; /* true if we're really stringent about data lines */
  24.   int verbose = 0; /* true if we're babbling about what we're skipping */
  25.   char buf[1024];
  26.   int i, len;
  27.   int phase = 0;
  28.   unsigned char outchar;
  29.  
  30.   for (i = 1; i < argc; i++) {
  31.     if (!strcmp(argv[i], "-s")) /* output to stdout */
  32.       dump_to_file = 0;
  33.     else if (!strcmp(argv[i], "-l")) /* lenient mode */
  34.       stringent = 0;
  35.     else if (!strcmp(argv[i], "-f")) { /* output to named file */
  36.       dump_to_file = 1;
  37.       outfilename = argv[++i];
  38.     }
  39.     else if (!strcmp(argv[i], "-v")) /* verbose output */
  40.       verbose = 1;
  41.     else {
  42.       infilename = argv[i];
  43.       break;
  44.     }
  45.   }
  46.   if (infilename == NULL) {
  47.     inf = stdin;
  48.     infilename = "stdin";
  49.   }
  50.   else {
  51.     inf = fopen(infilename, "r");
  52.     if (inf == NULL) {
  53.       perror(infilename);
  54.       exit(1);
  55.     }
  56.   }
  57.  
  58.   /* scan for "begin" line
  59.    */
  60.   while (fgets(buf, 1024, inf) != NULL) {
  61.     if (!strncmp(buf, "begin ", 6))
  62.       break;
  63.     if (verbose)
  64.       fprintf(stderr, "Ignoring header line: %s\n", buf);
  65.   }
  66.   if (feof(inf)) {
  67.     fprintf(stderr, "No 'begin' line, sorry.\n", infilename);
  68.     exit(1);
  69.   }
  70.  
  71.   if (dump_to_file) {
  72.     int mode; /* ignored */
  73.     char tmp[1024];
  74.  
  75.     if (!outfilename) {
  76.       if (sscanf(buf, "begin %o %s", &mode, tmp) != 2) {
  77.     fprintf(stderr, "%s: Bad format for 'begin' line (can't dump to file)\n", infilename);
  78.     exit(1);
  79.       }
  80.       outfilename = tmp;
  81.     }
  82.     fprintf(stderr, "Decoding into file %s\n", outfilename);
  83.     outf = fopen(outfilename, "w");
  84.     if (outf == NULL) {
  85.       perror(outfilename);
  86.       exit(1);
  87.     }
  88.   }
  89.   else
  90.     outf = stdout;
  91.  
  92.   for (;;) {
  93.     char *bp;
  94.  
  95.     if (fgets(buf, 1024, inf) == NULL) {
  96.       fprintf(stderr, "%s: Missing 'end' line.\n", infilename);
  97.       break;
  98.     }
  99.     
  100.     if (!strncmp(buf, "end", 3))
  101.       break; /* end of data */
  102.  
  103.     /* strip off trailing characters
  104.      */
  105.     len = strlen(buf) - 1;
  106.     while ((buf[len] == '\n') || (buf[len] == '\r'))
  107.       buf[len--] = '\0';
  108.  
  109.     /* character conversion and "obvious" filtering
  110.      */
  111.     for (; len >= 0; len--) {
  112.       if ((buf[len] >= 'a') || (buf[len] < ' '))
  113.     break; /* garbage character seen */
  114.  
  115.       if (buf[len] == '`')
  116.     buf[len] = ' ';
  117.     }
  118.     if (len >= 0) {
  119.       if (verbose)
  120.     fprintf(stderr, "Ignoring garbage line: %s\n", buf);
  121.       continue; /* line had garbage, ignore it */
  122.     }
  123.  
  124.     if (buf[0] == '\0')
  125.       continue; /* line is blank, ignore it */
  126.  
  127.     len = buf[0] - ' ';
  128.  
  129.     /* ok, see if the line length looks sane.
  130.      */
  131.     {
  132.       int line_len = strlen(buf) - 1;
  133.       int allow_len;
  134.  
  135.       /* if the line is shorter than the absolute minimum
  136.        * allowable then we're sure this is not a valid line.
  137.        */
  138.       allow_len = ((len * 4) / 3) + ((len * 4) % 3);
  139.       if (line_len < allow_len) {
  140.     if (verbose)
  141.       fprintf(stderr, "Ignoring short line: %s\n", buf);
  142.     continue;
  143.       }
  144.  
  145.       /* if we're being really stringent about the lines we allow
  146.        * this filters out any lines that are too long, too.  note
  147.        * that this is still fairly lenient; it allows uuencode
  148.        * programs to pad the line length out to a multiple of
  149.        * 3 bytes.
  150.        */
  151.       if (stringent) {
  152.     allow_len = ((len + 2) * 4) / 3;
  153.     if (line_len > allow_len) {
  154.       if (verbose)
  155.         fprintf(stderr, "Ignoring long line: %s\n", buf);
  156.       continue;
  157.     }
  158.       }
  159.     }
  160.  
  161.     /* ok, we have some characters -- process them!
  162.      */
  163.     bp = &buf[1];
  164.     phase = 0;
  165.     while (len > 0) {
  166.       unsigned char c;
  167.  
  168.       c = (unsigned char)*(bp++) - ' ';
  169.       switch (phase) {
  170.       case 0: /* 1st 6 bits */
  171.     outchar = (c << 2);
  172.     break;
  173.       case 1: /* last 2 bits, 1st 4 bits */
  174.     outchar |= (c >> 4);
  175.     fputc(outchar, outf);
  176.     len--;
  177.     outchar = (c & 0xf) << 4;
  178.     break;
  179.       case 2: /* last 4 bits, 1st 2 bits */
  180.     outchar |= (c >> 2);
  181.     fputc(outchar, outf);
  182.     len--;
  183.     outchar = (c & 0x3) << 6;
  184.     break;
  185.       case 3: /* last 6 bits */
  186.     outchar |= c;
  187.     fputc(outchar, outf);
  188.     len--;
  189.     phase = 0;
  190.     continue;
  191.       }
  192.       phase++;
  193.     }
  194.   }
  195.   /* flush output
  196.    */
  197.   if (outf == stdout)
  198.     fflush(outf);
  199.   else
  200.     fclose(outf);
  201.  
  202.   /* suck up the rest of the input file.  this avoids "broken pipe"
  203.    * errors if reading from stdin.
  204.    */
  205.   if (inf == stdin) {
  206.     while (fgets(buf, 1024, inf) != NULL)
  207.       if (verbose)
  208.     fprintf(stderr, "Ignoring trailing line: %s\n", buf);
  209.   }
  210.   else
  211.     fclose(inf);
  212.  
  213.   exit(0);
  214. }
  215.