home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / programs / compress / misc / uucode / source.lha / uudecode.c < prev    next >
C/C++ Source or Header  |  1995-01-10  |  6KB  |  276 lines

  1. /*
  2.     uudecode 36.6 -- Copyright (c) 1993 Ralph Seichter.
  3.  
  4.     Decodes binary files encoded with uuencode.
  5.  
  6.     This tool is FREELY DISTRIBUTABLE. Copying and spreading is encouraged,
  7.     as long as you don't charge anyone for giving him/her this tool. Please
  8.     note that the Copyright is mine, this is *NOT* public domain software!
  9.     Permission is hereby granted to include the complete (!) archive in all
  10.     non-profit public domain software series like Fred Fish, SaarAG, etc.
  11.  
  12.     This version of uuencode was especially optimized for AmigaDOS 2.04 or
  13.     better and the SAS/C 6.3 development system.
  14. */
  15.  
  16. #include <proto/dos.h>
  17. #include <proto/exec.h>
  18. #include <proto/utility.h>
  19. #include <exec/memory.h>
  20.  
  21. #define    ARG_FROM        0
  22. #define    ARG_PATH        1
  23. #define    ARG_NOCHKSUM    2
  24. #define    ARG_TOTAL        3
  25. #define    LINESIZE        128
  26. #define    SIXBIT        0x40        /* 6 bit = 0x40 */
  27.  
  28. /* decode one single byte */
  29.  
  30. #define DECODE(c) ((c - 0x20) & 0x3F)
  31.  
  32.  
  33.  
  34. /* function prototypes and globals ******************************************/
  35.  
  36. LONG atol (STRPTR);
  37. LONG decodeFile (struct Library *, BPTR, BOOL);
  38. BOOL putFile (BPTR, STRPTR, ...);
  39. BOOL putStr (STRPTR, ...);
  40. LONG uudecode (VOID);
  41.  
  42. UBYTE ver[] = "$VER: uudecode 36.6 (24.8.93) Copyright \xA9 1993 Ralph Seichter";
  43. struct DosLibrary *DOSBase;
  44.  
  45.  
  46.  
  47. /* the main program *********************************************************/
  48.  
  49. LONG __saveds uudecode (VOID)
  50. {
  51.     LONG rc = RETURN_FAIL;
  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.         LONG err = 0;
  58.  
  59.         if (UtilityBase = OpenLibrary ("utility.library", 37))
  60.         {
  61.             STRPTR arg[ARG_TOTAL] = {0, 0, 0};
  62.             struct RDArgs *rda;
  63.  
  64.             if (rda = ReadArgs ("FROM/A/M,PATH/K,NOCHECKSUM/S", (LONG *)arg, NULL))
  65.             {
  66.                 LONG i;
  67.                 BPTR in;
  68.                 STRPTR *name = (STRPTR *)arg[ARG_FROM];
  69.  
  70.                 for (err = 0, i = 0; err == 0 && (name[i]); ++i)
  71.                 {
  72.                     if (in = Open (name[i], MODE_OLDFILE))
  73.                     {
  74.                         BPTR oldPath, path = NULL;
  75.  
  76.                         if ((arg[ARG_PATH]) && (path = Lock (arg[ARG_PATH], SHARED_LOCK)))
  77.                             oldPath = CurrentDir (path);
  78.  
  79.                         putStr ("\nProcessing input file `%s'\n", name[i]);
  80.                         err = decodeFile (UtilityBase, in, (BOOL)arg[ARG_NOCHKSUM]);
  81.  
  82.                         if (path)
  83.                         {
  84.                             CurrentDir (oldPath);
  85.                             UnLock (path);
  86.                         }
  87.                         Close (in);
  88.                     }
  89.                 }
  90.                 rc = (err == 0 ? RETURN_OK : RETURN_ERROR);
  91.                 FreeArgs (rda);
  92.             }
  93.             CloseLibrary (UtilityBase);
  94.         }
  95.         if (err > 0 || (err = IoErr ()) > 0)
  96.             PrintFault (err, NULL);
  97.         CloseLibrary ((struct Library *)DOSBase);
  98.     }
  99.     return (rc);
  100. }
  101.  
  102.  
  103.  
  104. /* ASCII to LONG ************************************************************/
  105.  
  106. LONG atol (STRPTR s)
  107. {
  108.     LONG x = 0;
  109.  
  110.     while (*s >= '0' && *s <= '9')
  111.         x = 10 * x + (LONG)(*s++ - '0');
  112.     return (x);
  113. }
  114.  
  115.  
  116.  
  117. /* sort of a private fprintf() function *************************************/
  118.  
  119. BOOL putFile (BPTR file, STRPTR format, ...)
  120. {
  121.     UBYTE buf[256];
  122.  
  123.     RawDoFmt (format, &format + 1, (void (*))"\x16\xC0\x4E\x75", buf);
  124.     return ((BOOL)(0 == FPuts (file, buf)));
  125. }
  126.  
  127.  
  128.  
  129. /* sort of a private printf() function *************************************/
  130.  
  131. BOOL putStr (STRPTR format, ...)
  132. {
  133.     UBYTE buf[256];
  134.  
  135.     RawDoFmt (format, &format + 1, (void (*))"\x16\xC0\x4E\x75", buf);
  136.     return ((BOOL)(0 == PutStr (buf)));
  137. }
  138.  
  139.  
  140.  
  141. /* decode a complete file ***************************************************/
  142.  
  143. LONG decodeFile (struct Library *UtilityBase, BPTR in, BOOL ignoreChecksum)
  144. {
  145.     BOOL done, gotBegin = FALSE;
  146.     LONG line = 0;
  147.     UBYTE __aligned buf[LINESIZE];
  148.     UBYTE __aligned outbuf[LINESIZE];
  149.     UBYTE error[] = "\7\23331;42m ERROR \2330m -- ";
  150.     UBYTE warning[] = "\23331;42m WARNING \2330m -- ";
  151.     STRPTR s, t, empty;
  152.  
  153.     if (empty = AllocVec (LINESIZE, MEMF_CLEAR))
  154.     {
  155.         do
  156.         {
  157.             done = TRUE;
  158.  
  159.             /* find the next `begin' line */
  160.             while (s = FGets (in, buf, LINESIZE - 1))
  161.             {
  162.                 ++line;
  163.                 if (0 == Strnicmp (buf, "begin ", 6))
  164.                 {
  165.                     gotBegin = TRUE;
  166.  
  167.                     /* skip over `begin xyz ' to find the file name. */
  168.                     t = s = FilePart (&buf[10]);
  169.                     while (*t != '\n')
  170.                         ++t;
  171.                     *t = 0;
  172.                     break;
  173.                 }
  174.             }
  175.  
  176.             /* is there a file to decode? */
  177.             if (s)
  178.             {
  179.                 BPTR out;
  180.  
  181.                 if (out = Open (s, MODE_NEWFILE))
  182.                 {
  183.                     LONG expected = ~0, size = 0;
  184.  
  185.                     putStr ("\nLine %ld: decoding file `%s'\n", line, s);
  186.                     CopyMemQuick (empty, buf, LINESIZE);
  187.                     while (s = FGets (in, buf, LINESIZE - 1))
  188.                     {
  189.                         ++line;
  190.                         if (0 == Stricmp (buf, "end\n"))
  191.                         {
  192.                             if (FGets (in, buf, LINESIZE - 1))
  193.                             {
  194.                                 ++line;
  195.                                 if (0 == Strnicmp (buf, "size ", 5))
  196.                                     expected = atol (&buf[5]);
  197.                             }
  198.                             break;
  199.                         }
  200.                         else
  201.                         {
  202.                             LONG l, c, checksum = 0;
  203.  
  204.                             t = outbuf;
  205.                             c = *s++;
  206.                             l = DECODE(c);
  207.                             if (c != '\n' && l > 0)
  208.                             {
  209.                                 /* decode one line. four input bytes will
  210.                                     result in three output bytes. */
  211.                                 while (l >= 4)
  212.                                 {
  213.                                     c = DECODE(s[0]) << 2 | DECODE(s[1]) >> 4;
  214.                                     checksum += c;
  215.                                     *t++ = c;
  216.  
  217.                                     c = DECODE(s[1]) << 4 | DECODE(s[2]) >> 2;
  218.                                     checksum += c;
  219.                                     *t++ = c;
  220.  
  221.                                     c = DECODE(s[2]) << 6 | DECODE(s[3]);
  222.                                     checksum += c;
  223.                                     *t++ = c;
  224.  
  225.                                     checksum = checksum % SIXBIT;
  226.                                     s += 4;
  227.                                     l -= 3;
  228.                                 }
  229.                                 c = DECODE(s[0]) << 2 | DECODE(s[1]) >> 4;
  230.                                 checksum += c;
  231.                                 if (l >= 1)
  232.                                     *t++ = c;
  233.                                 c = DECODE(s[1]) << 4 | DECODE(s[2]) >> 2;
  234.                                 checksum += c;
  235.                                 if (l >= 2)
  236.                                     *t++ = c;
  237.                                 c = DECODE(s[2]) << 6 | DECODE(s[3]);
  238.                                 checksum += c;
  239.                                 if (l >= 3)
  240.                                     *t++ = c;
  241.                                 checksum = checksum % SIXBIT;
  242.                                 s += 4;
  243.                                 if (!ignoreChecksum && *s >= 0x20 && *s <= 0x60 && checksum != DECODE(*s))
  244.                                 {
  245.                                     putStr ("Line %ld: %sbad checksum!\n", line, error);
  246.                                     break;
  247.                                 }
  248.                                 l = t - outbuf;
  249.                                 if (1 == FWrite (out, outbuf, l, 1))
  250.                                     size += l;
  251.                                 else
  252.                                     break;
  253.                             }
  254.                         }
  255.                     }
  256.                     if (s)
  257.                     {
  258.                         if (expected != ~0 && expected != size)
  259.                             putStr ("Line %ld: %sfile size mismatch!\n%ld bytes expected, ", line, warning, expected);
  260.                         putStr ("%ld bytes written.\n", size);
  261.                         done = FALSE;
  262.                     }
  263.                     else
  264.                         putStr ("Line %ld: %sunexpected end of file!\n", line, error);
  265.                     Close (out);
  266.                 }
  267.             }
  268.         }
  269.         while (!done);
  270.         if (!gotBegin)
  271.             putStr ("%sno `begin' line found.\n", warning);
  272.         FreeVec (empty);
  273.     }
  274.     return (IoErr ());
  275. }
  276.