home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / bbs_mail / fdsnd_20.arj / UUD.C < prev   
Text File  |  1991-11-06  |  6KB  |  281 lines

  1. /*
  2.  * Uudecode -- decode a uuencoded file back to binary form.
  3.  *
  4.  * modified for Lattice C on the ST - 11.05.86 by MSD
  5.  * modified for Alcyon on the ST -    10-24-86 by RDR
  6.  * modified (a lot) for MWC on the ST 02/07/87 by JPHD 
  7.  * (Some more to be done on the I/O speed...)
  8.  *
  9.  */
  10.  
  11. #include <stdio.h>
  12. #ifdef ATARI_ST
  13. #include <osbind.h>
  14. #endif
  15. extern FILE *fopen();
  16. extern char *strcpy();
  17.  
  18. char *getnword();
  19.  
  20. #define MAXCHAR 127
  21. #define LINELEN 80
  22. #define FILELEN 64
  23. #define CODEDLN 61
  24. #define NORMLEN 45
  25.  
  26. char *mism = "Part suffix mismatch: <%> instead of <%>.\r\n";
  27. #define SUBS1     23
  28. #define SUBS2    38
  29.  
  30. FILE  *in, *out;
  31. char ifname[FILELEN];
  32. char chtbl[MAXCHAR];
  33. char *pos;
  34. char blank, part = '\0';
  35. int partn = 'a';
  36. int lens;
  37.  
  38. main(argc, argv) int argc; char *argv[];
  39. {
  40.     register int i, j;
  41.     char dest[FILELEN], buf[LINELEN];
  42.  
  43.     if (argc < 2) {
  44.         Console("Almost foolproof uudecode v1.0 15-Feb-1987 JPHD\r\n");
  45.         Console("Usage: uudecode inputfile\r\n");
  46.         exit(1);
  47.     }
  48.         if((in = fopen(argv[1], "r")) == NULL) {
  49.         Console("Cant open input file.\r\n");
  50.         exit(2);
  51.     }
  52.  
  53. /*
  54.  * Set up the default translation table. 
  55.  */
  56.     for (i = 0; i < ' '; i++) chtbl[i] = '\0';
  57.     for (i = ' ', j = 0; i < ' ' + 64; i++, j++) chtbl[i] = j;
  58.     for (i = ' ' + 64; i < MAXCHAR; i++) chtbl[i] = '\0';
  59.     chtbl['`'] = chtbl[' '];    /* common mutation */
  60.     chtbl['~'] = chtbl['^'];    /* an other common mutation */
  61.     blank = ' ';
  62. /*
  63.  * search for header or translation table line.
  64.  */
  65.     for (;;) {
  66.         if (fgets(buf, sizeof buf, in) == NULL) {
  67.             Console("No begin line\r\n");
  68.             exit(3);
  69.         }
  70.         if (strncmp(buf, "table", 5) == 0) {
  71.             gettable();
  72.             continue;
  73.         }
  74.         if (strncmp(buf, "begin", 5) == 0) {
  75.             break;
  76.         }
  77.     }
  78.     lens = strlen(buf);
  79.     if (lens) buf[--lens] = '\0';
  80.     if ((pos = getnword(buf, 3)) == NULL) {
  81.         Console("Missing filename in begin line.\r\n");
  82.         exit(10);
  83.     } else
  84.         strcpy(dest, pos);
  85.  
  86.     if((out = fopen(dest, "wb")) == NULL) {
  87.         Console("Cannot open output file\r\n");
  88.         exit(4);
  89.     }
  90.     decode();
  91.     fclose(out);
  92.     exit(0);
  93. }
  94. /*
  95.  * Bring back a pointer to the start of the nth word.
  96.  */
  97. char *getnword(str, n) register char *str; register int n;
  98. {
  99.     while((*str == '\t') || (*str == ' ')) str++;
  100.     if (! *str) return NULL;
  101.     while(--n) {
  102.         while ((*str != '\t') && (*str != ' ') && (*str)) str++;
  103.         if (! *str) return NULL;
  104.         while((*str == '\t') || (*str == ' ')) str++;
  105.         if (! *str) return NULL;
  106.     }
  107.     return str;
  108. }
  109.  
  110. /*
  111.  * Install the table in memory for later use.
  112.  */
  113. gettable()
  114. {
  115.     char buf[LINELEN];
  116.     register int c, n = 0;
  117.     register char *cpt;
  118.  
  119.     for (c = 0; c <= MAXCHAR; c++) chtbl[c] = '\0';
  120.  
  121. again:    if (fgets(buf, sizeof buf, in) == NULL) {
  122.         Console("EOF while in translation table.\r\n");
  123.         exit(5);
  124.     }
  125.     if (strncmp(buf, "begin", 5) == 0) {
  126.         Console("Incomplete translation table.\r\n");
  127.         exit(6);
  128.     }
  129.     cpt = buf + strlen(buf) - 1;
  130.     *cpt = ' ';
  131.     while (*(cpt) == ' ') {
  132.         *cpt = '\0'; 
  133.         cpt--;
  134.     }
  135.     cpt = buf;
  136.     while (c = *cpt) {
  137.         if (chtbl[c] != '\0') {
  138.             Console("Duplicate char in translation table.\n");
  139.             exit(6);
  140.         }
  141.         if (n == 0) blank = c;
  142.         chtbl[c] = n++;
  143.         if (n >= 64) return;
  144.         cpt++;
  145.     }
  146.     goto again;
  147. }
  148.  
  149. /*
  150.  * copy from in to out, decoding as you go along.
  151.  */
  152.  
  153. decode()
  154. {
  155.     char buf[LINELEN], outl[LINELEN];
  156.     register char *bp, *ut, *trtbl = chtbl;
  157.     register unsigned int n, c, len;
  158.  
  159.     for (;;) {
  160.         if (fgets(buf, sizeof buf, in) == NULL) {
  161.             Console("Short file.\r\n");
  162.             return;
  163.         }
  164.         len = strlen(buf);
  165.         if (len) buf[--len] = '\0';
  166. /*
  167.  * Get the binary line length.
  168.  */
  169.         n = trtbl[*buf];
  170.         if (n == NORMLEN) goto decod;
  171. /*
  172.  * end of uuencoded file ?
  173.  */
  174.         if (strncmp(buf, "end", 3) == 0) return;
  175. /*
  176.  * end of current file ? : get next one.
  177.  */
  178.         if (strncmp(buf, "include", 7) == 0) {
  179.             getfile(buf);
  180.             continue;
  181.         }
  182. /*
  183.  * Is it the empty line before the end line ?
  184.  */
  185.         if (n <= 0) continue;
  186. /*
  187.  * Pad with blanks.
  188.  */
  189. decod:        for (bp = &buf[c = len];
  190.              c < CODEDLN; c++, bp++) *bp = blank;
  191.  
  192. /*
  193.  * output a group of 3 bytes (4 input characters).
  194.  * the input chars are pointed to by p, they are to
  195.  * be output to file f.  n is used to tell us not to
  196.  * output all of them at the end of the file.
  197.  */
  198.         ut = outl;
  199.         len = n;
  200.         bp = &buf[1];
  201.         while (n > 0) {
  202.             *(ut++) = trtbl[*bp] << 2 | trtbl[bp[1]] >> 4;
  203.             n--;
  204.             if (n) {
  205.                 *(ut++) = trtbl[bp[1]] << 4 | trtbl[bp[2]] >> 2;
  206.                 n--;
  207.             }
  208.             if (n) {
  209.                 *(ut++) = trtbl[bp[2]] << 6 | trtbl[bp[3]];
  210.                 n--;
  211.             }
  212.             bp += 4;
  213.         }
  214.         n = fwrite(outl, 1, len, out);
  215.     }
  216. }
  217.  
  218. /* you may need to rename the filenames at the ends of each part
  219. * if the encoder encoded them on directories and specified drives.
  220. */
  221. getfile(buf) register char *buf;
  222. {
  223.     if ((pos = getnword(buf, 2)) == NULL) {
  224.         Console("Missing include file name.\r\n");
  225.         exit(11);
  226.     } else
  227.         strcpy(ifname, pos);
  228.  
  229.     if (freopen(ifname, "r", in) != in) {
  230.         Console("Cannot reassign input file to included file.\r\n");
  231.         exit(7);
  232.     }
  233.     for (;;) {
  234.         if (fgets(buf, LINELEN, in) == NULL) {
  235.             Console("No begin line in included file: ");
  236.             Console(ifname);
  237.             Console(".\r\n");
  238.             exit(3);
  239.         }
  240.  
  241.         if (strncmp(buf, "table", 5) == 0) {
  242.             gettable();
  243.             continue;
  244.         }
  245.         if (strncmp(buf, "begin", 5) == 0) {
  246.             break;
  247.         }
  248.     }
  249.     lens = strlen(buf);
  250.     if (lens) buf[--lens] = '\0';
  251.     if ((pos = getnword(buf, 3)) == NULL ) {
  252.         Console("Missing part name, in included begin line.\r\n");
  253.         part = '?';
  254.     } else {
  255.         part = *pos;
  256. /*
  257.  * Check the part suffix.
  258.  */
  259.         partn++;
  260.         if (part != partn) {
  261.             mism[SUBS1] = part;
  262.             mism[SUBS2] = partn;
  263.             Console(mism);
  264.         }
  265.     }
  266. }
  267.  
  268. /*
  269.  * Output to console, immune against redirection of stdout.
  270.  */
  271. Console(s) register char *s;
  272. {
  273. #ifdef ATARI_ST
  274.     while (*s) Bconout(2,*s++);
  275. #else
  276.     while (*s) fputc(*s++,stderr);
  277. #endif
  278. }
  279.  
  280.  
  281.