home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 9 / FreshFishVol9-CD2.bin / bbs / util / uucode-36.9.lha / UUCode / uudecode.c < prev    next >
Text File  |  1994-09-28  |  6KB  |  254 lines

  1. /*
  2.  * $Id: uudecode.c,v 36.9 1994/09/28 15:03:59 zodiac Rel zodiac $
  3.  *
  4.  * uudecode 36.9 -- Copyright (c) 1994 Ralph Seichter.
  5.  *
  6.  * Decodes binary files encoded with uuencode. This tool is pure.
  7.  *
  8.  * This tool is FREELY DISTRIBUTABLE. Copying and spreading is encouraged,
  9.  * as long as you don't charge anyone for giving him/her this tool. Please
  10.  * note that the Copyright is mine, this is *NOT* public domain software!
  11.  * Permission is hereby granted to include the complete (!) archive in all
  12.  * non-profit public domain software series like Fred Fish, SaarAG, etc.
  13.  *
  14.  * $Log: uudecode.c,v $
  15.  * Revision 36.9  1994/09/28  15:03:59  zodiac
  16.  * Files with IBM-style EOL sequences (CR/LF pairs) are now
  17.  * processed correctly. This was suggested by Patrick Ohly.
  18.  *
  19.  * Revision 36.8  1994/09/28  14:18:47  zodiac
  20.  * First release with 'pure' executables.
  21.  *
  22.  */
  23.  
  24. #define    VERSION        "\0$VER: uudecode 36.9 (28.9.94)"
  25. #define    TEMPLATE        "FROM/A/M,PATH=TO/K,NC=NOCHECKSUM/S,QUIET/S"
  26.  
  27. #define    NO_DATA_FOUND    -3
  28. #define    BAD_CHECKSUM    -4
  29. #define    LINESIZE        128
  30. #define    SIXBIT        0x40                /* 6 bit = 0x40 */
  31.  
  32. enum { ARG_FROM, ARG_PATH, ARG_NOCHKSUM, ARG_QUIET, ARG_TOTAL };
  33.  
  34. #define    DECODE(c) ((c - 0x20) & 0x3F)        /* decode one single byte */
  35. #define    ISEOL(c) (c == '\n' || c == '\r')    /* check for LF or CR */
  36.  
  37.  
  38.  
  39. /* function prototypes ******************************************************/
  40.  
  41. LONG entryPoint (VOID);
  42. LONG decodeFile (struct DosLibrary *, struct Library *, STRPTR *, BPTR, BOOL);
  43.  
  44.  
  45.  
  46. /* the main program *********************************************************/
  47.  
  48. LONG __saveds entryPoint (VOID)
  49. {
  50.     LONG rc = RETURN_FAIL;
  51.     struct DosLibrary *DOSBase;
  52.  
  53.     /* uudecode will *NOT* run without dos.library V36 or better! */
  54.     if (DOSBase = (struct DosLibrary *)OpenLibrary (DOSNAME, 36))
  55.     {
  56.         struct Library *UtilityBase;
  57.  
  58.         if (UtilityBase = OpenLibrary ("utility.library", 37))
  59.         {
  60.             struct RDArgs *rda;
  61.             STRPTR arg[ARG_TOTAL];
  62.  
  63.             rc = RETURN_ERROR;
  64.             memset (arg, 0, sizeof (arg));
  65.             if (rda = ReadArgs (TEMPLATE, (LONG *)arg, NULL))
  66.             {
  67.                 LONG i, err;
  68.                 BPTR in;
  69.                 STRPTR *name = (STRPTR *)arg[ARG_FROM];
  70.                 static UBYTE ver[] = VERSION;
  71.  
  72.                 if (!arg[ARG_QUIET])
  73.                     Printf ("%s Copyright \xA9 Ralph Seichter\n", &ver[7]);
  74.                 for (err = 0, i = 0; err == 0 && (name[i]); ++i)
  75.                     if (in = Open (name[i], MODE_OLDFILE))
  76.                     {
  77.                         BPTR oldPath, path = NULL;
  78.  
  79.                         if (arg[ARG_PATH] && (path = Lock (arg[ARG_PATH], SHARED_LOCK)))
  80.                             oldPath = CurrentDir (path);
  81.                         if (!arg[ARG_QUIET])
  82.                             Printf ("Processing input file %s\n", name[i]);
  83.                         err = decodeFile (DOSBase, UtilityBase, arg, in, (BOOL)arg[ARG_NOCHKSUM]);
  84.                         if (path)
  85.                         {
  86.                             CurrentDir (oldPath);
  87.                             UnLock (path);
  88.                         }
  89.                         Close (in);
  90.                     }
  91.                     else
  92.                         break;
  93.                 if (err <= NO_DATA_FOUND)
  94.                     rc = RETURN_WARN;
  95.                 else if (err > 0 || (err = IoErr ()) > 0)
  96.                     PrintFault (err, NULL);
  97.                 else
  98.                     rc = RETURN_OK;
  99.                 FreeArgs (rda);
  100.             }
  101.             CloseLibrary (UtilityBase);
  102.         }
  103.         CloseLibrary ((struct Library *)DOSBase);
  104.     }
  105.     return (rc);
  106. }
  107.  
  108.  
  109.  
  110. /* decode a complete file ***************************************************/
  111.  
  112. LONG decodeFile (struct DosLibrary *DOSBase, struct Library *UtilityBase, STRPTR *arg, BPTR in, BOOL ignoreChecksum)
  113. {
  114.     BOOL done, gotBegin = FALSE, badChecksum = FALSE;
  115.     LONG line = 0;
  116.     UBYTE buf[LINESIZE], outbuf[LINESIZE];
  117.     static UBYTE error[] = "\7\23331;42m ERROR \2330m -- ";
  118.     static UBYTE warning[] = "\23331;42m WARNING \2330m -- ";
  119.     STRPTR s, t;
  120.  
  121.     do
  122.     {
  123.         done = TRUE;
  124.  
  125.         /* find the next `begin' line */
  126.         while (s = FGets (in, buf, LINESIZE - 1))
  127.         {
  128.             ++line;
  129.             if (0 == Strnicmp (buf, "begin ", 6))
  130.             {
  131.                 gotBegin = TRUE;
  132.                 /* skip over `begin xyz ' to find the file name. */
  133.                 t = s = FilePart (&buf[10]);
  134.                 while (!ISEOL(*t))
  135.                     ++t;
  136.                 *t = 0;
  137.                 break;
  138.             }
  139.         }
  140.  
  141.         /* is there a file to decode? */
  142.         if (s)
  143.         {
  144.             BPTR out;
  145.  
  146.             if (out = Open (s, MODE_NEWFILE))
  147.             {
  148.                 LONG expected = ~0, size = 0;
  149.  
  150.                 if (!arg[ARG_QUIET])
  151.                     Printf ("Line %ld: decoding file %s\n", line, s);
  152.                 memset (buf, 0, LINESIZE);
  153.                 while (s = FGets (in, buf, LINESIZE - 1))
  154.                 {
  155.                     ++line;
  156.                     if (0 == Strnicmp (buf, "end", 3) && ISEOL(buf[3]))
  157.                     {
  158.                         if (FGets (in, buf, LINESIZE - 1))
  159.                         {
  160.                             ++line;
  161.                             if (0 == Strnicmp (buf, "size ", 5))
  162.                                 StrToLong (&buf[5], &expected);
  163.                         }
  164.                         break;
  165.                     }
  166.                     else
  167.                     {
  168.                         LONG l, c, checksum = 0;
  169.  
  170.                         t = outbuf;
  171.                         c = *s++;
  172.                         l = DECODE(c);
  173.                         if (c != '\n' && l > 0)
  174.                         {
  175.                             /* decode one line. four input bytes will
  176.                                 result in three output bytes. */
  177.                             while (l >= 4)
  178.                             {
  179.                                 c = DECODE(s[0]) << 2 | DECODE(s[1]) >> 4;
  180.                                 checksum += c;
  181.                                 *t++ = c;
  182.  
  183.                                 c = DECODE(s[1]) << 4 | DECODE(s[2]) >> 2;
  184.                                 checksum += c;
  185.                                 *t++ = c;
  186.  
  187.                                 c = DECODE(s[2]) << 6 | DECODE(s[3]);
  188.                                 checksum += c;
  189.                                 *t++ = c;
  190.  
  191.                                 checksum = checksum % SIXBIT;
  192.                                 s += 4;
  193.                                 l -= 3;
  194.                             }
  195.                             c = DECODE(s[0]) << 2 | DECODE(s[1]) >> 4;
  196.                             checksum += c;
  197.                             if (l >= 1)
  198.                                 *t++ = c;
  199.                             c = DECODE(s[1]) << 4 | DECODE(s[2]) >> 2;
  200.                             checksum += c;
  201.                             if (l >= 2)
  202.                                 *t++ = c;
  203.                             c = DECODE(s[2]) << 6 | DECODE(s[3]);
  204.                             checksum += c;
  205.                             if (l >= 3)
  206.                                 *t++ = c;
  207.                             checksum = checksum % SIXBIT;
  208.                             s += 4;
  209.                             if (!ignoreChecksum && *s >= 0x20 && *s <= 0x60 && checksum != DECODE(*s))
  210.                             {
  211.                                 badChecksum = TRUE;
  212.                                 if (!arg[ARG_QUIET])
  213.                                     Printf ("Line %ld: %sbad checksum!\n", line, error);
  214.                                 break;
  215.                             }
  216.                             l = t - outbuf;
  217.                             if (1 == FWrite (out, outbuf, l, 1))
  218.                                 size += l;
  219.                             else
  220.                                 break;
  221.                         }
  222.                     }
  223.                 }
  224.                 if (s)
  225.                 {
  226.                     done = FALSE;
  227.                     if (!arg[ARG_QUIET])
  228.                     {
  229.                         if (expected != ~0 && expected != size)
  230.                             Printf ("Line %ld: %sfile size mismatch!\n%ld bytes expected, ", line, warning, expected);
  231.                         Printf ("%ld bytes written.\n", size);
  232.                     }
  233.                 }
  234.                 else if (!arg[ARG_QUIET])
  235.                     Printf ("Line %ld: %sunexpected end of file!\n", line, error);
  236.                 Close (out);
  237.             }
  238.         }
  239.     }
  240.     while (!done);
  241.     if (badChecksum)
  242.         return (BAD_CHECKSUM);
  243.     else if (gotBegin)
  244.         return (IoErr ());
  245.     else
  246.     {
  247.         if (!arg[ARG_QUIET])
  248.             Printf ("%sno encoded data found.\n", warning);
  249.         return (NO_DATA_FOUND);
  250.     }
  251. }
  252.  
  253. /* EOF */
  254.