home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 9
/
FreshFishVol9-CD2.bin
/
bbs
/
util
/
uucode-36.9.lha
/
UUCode
/
uudecode.c
< prev
next >
Wrap
Text File
|
1994-09-28
|
6KB
|
254 lines
/*
* $Id: uudecode.c,v 36.9 1994/09/28 15:03:59 zodiac Rel zodiac $
*
* uudecode 36.9 -- Copyright (c) 1994 Ralph Seichter.
*
* Decodes binary files encoded with uuencode. This tool is pure.
*
* This tool is FREELY DISTRIBUTABLE. Copying and spreading is encouraged,
* as long as you don't charge anyone for giving him/her this tool. Please
* note that the Copyright is mine, this is *NOT* public domain software!
* Permission is hereby granted to include the complete (!) archive in all
* non-profit public domain software series like Fred Fish, SaarAG, etc.
*
* $Log: uudecode.c,v $
* Revision 36.9 1994/09/28 15:03:59 zodiac
* Files with IBM-style EOL sequences (CR/LF pairs) are now
* processed correctly. This was suggested by Patrick Ohly.
*
* Revision 36.8 1994/09/28 14:18:47 zodiac
* First release with 'pure' executables.
*
*/
#define VERSION "\0$VER: uudecode 36.9 (28.9.94)"
#define TEMPLATE "FROM/A/M,PATH=TO/K,NC=NOCHECKSUM/S,QUIET/S"
#define NO_DATA_FOUND -3
#define BAD_CHECKSUM -4
#define LINESIZE 128
#define SIXBIT 0x40 /* 6 bit = 0x40 */
enum { ARG_FROM, ARG_PATH, ARG_NOCHKSUM, ARG_QUIET, ARG_TOTAL };
#define DECODE(c) ((c - 0x20) & 0x3F) /* decode one single byte */
#define ISEOL(c) (c == '\n' || c == '\r') /* check for LF or CR */
/* function prototypes ******************************************************/
LONG entryPoint (VOID);
LONG decodeFile (struct DosLibrary *, struct Library *, STRPTR *, BPTR, BOOL);
/* the main program *********************************************************/
LONG __saveds entryPoint (VOID)
{
LONG rc = RETURN_FAIL;
struct DosLibrary *DOSBase;
/* uudecode will *NOT* run without dos.library V36 or better! */
if (DOSBase = (struct DosLibrary *)OpenLibrary (DOSNAME, 36))
{
struct Library *UtilityBase;
if (UtilityBase = OpenLibrary ("utility.library", 37))
{
struct RDArgs *rda;
STRPTR arg[ARG_TOTAL];
rc = RETURN_ERROR;
memset (arg, 0, sizeof (arg));
if (rda = ReadArgs (TEMPLATE, (LONG *)arg, NULL))
{
LONG i, err;
BPTR in;
STRPTR *name = (STRPTR *)arg[ARG_FROM];
static UBYTE ver[] = VERSION;
if (!arg[ARG_QUIET])
Printf ("%s Copyright \xA9 Ralph Seichter\n", &ver[7]);
for (err = 0, i = 0; err == 0 && (name[i]); ++i)
if (in = Open (name[i], MODE_OLDFILE))
{
BPTR oldPath, path = NULL;
if (arg[ARG_PATH] && (path = Lock (arg[ARG_PATH], SHARED_LOCK)))
oldPath = CurrentDir (path);
if (!arg[ARG_QUIET])
Printf ("Processing input file %s\n", name[i]);
err = decodeFile (DOSBase, UtilityBase, arg, in, (BOOL)arg[ARG_NOCHKSUM]);
if (path)
{
CurrentDir (oldPath);
UnLock (path);
}
Close (in);
}
else
break;
if (err <= NO_DATA_FOUND)
rc = RETURN_WARN;
else if (err > 0 || (err = IoErr ()) > 0)
PrintFault (err, NULL);
else
rc = RETURN_OK;
FreeArgs (rda);
}
CloseLibrary (UtilityBase);
}
CloseLibrary ((struct Library *)DOSBase);
}
return (rc);
}
/* decode a complete file ***************************************************/
LONG decodeFile (struct DosLibrary *DOSBase, struct Library *UtilityBase, STRPTR *arg, BPTR in, BOOL ignoreChecksum)
{
BOOL done, gotBegin = FALSE, badChecksum = FALSE;
LONG line = 0;
UBYTE buf[LINESIZE], outbuf[LINESIZE];
static UBYTE error[] = "\7\23331;42m ERROR \2330m -- ";
static UBYTE warning[] = "\23331;42m WARNING \2330m -- ";
STRPTR s, t;
do
{
done = TRUE;
/* find the next `begin' line */
while (s = FGets (in, buf, LINESIZE - 1))
{
++line;
if (0 == Strnicmp (buf, "begin ", 6))
{
gotBegin = TRUE;
/* skip over `begin xyz ' to find the file name. */
t = s = FilePart (&buf[10]);
while (!ISEOL(*t))
++t;
*t = 0;
break;
}
}
/* is there a file to decode? */
if (s)
{
BPTR out;
if (out = Open (s, MODE_NEWFILE))
{
LONG expected = ~0, size = 0;
if (!arg[ARG_QUIET])
Printf ("Line %ld: decoding file %s\n", line, s);
memset (buf, 0, LINESIZE);
while (s = FGets (in, buf, LINESIZE - 1))
{
++line;
if (0 == Strnicmp (buf, "end", 3) && ISEOL(buf[3]))
{
if (FGets (in, buf, LINESIZE - 1))
{
++line;
if (0 == Strnicmp (buf, "size ", 5))
StrToLong (&buf[5], &expected);
}
break;
}
else
{
LONG l, c, checksum = 0;
t = outbuf;
c = *s++;
l = DECODE(c);
if (c != '\n' && l > 0)
{
/* decode one line. four input bytes will
result in three output bytes. */
while (l >= 4)
{
c = DECODE(s[0]) << 2 | DECODE(s[1]) >> 4;
checksum += c;
*t++ = c;
c = DECODE(s[1]) << 4 | DECODE(s[2]) >> 2;
checksum += c;
*t++ = c;
c = DECODE(s[2]) << 6 | DECODE(s[3]);
checksum += c;
*t++ = c;
checksum = checksum % SIXBIT;
s += 4;
l -= 3;
}
c = DECODE(s[0]) << 2 | DECODE(s[1]) >> 4;
checksum += c;
if (l >= 1)
*t++ = c;
c = DECODE(s[1]) << 4 | DECODE(s[2]) >> 2;
checksum += c;
if (l >= 2)
*t++ = c;
c = DECODE(s[2]) << 6 | DECODE(s[3]);
checksum += c;
if (l >= 3)
*t++ = c;
checksum = checksum % SIXBIT;
s += 4;
if (!ignoreChecksum && *s >= 0x20 && *s <= 0x60 && checksum != DECODE(*s))
{
badChecksum = TRUE;
if (!arg[ARG_QUIET])
Printf ("Line %ld: %sbad checksum!\n", line, error);
break;
}
l = t - outbuf;
if (1 == FWrite (out, outbuf, l, 1))
size += l;
else
break;
}
}
}
if (s)
{
done = FALSE;
if (!arg[ARG_QUIET])
{
if (expected != ~0 && expected != size)
Printf ("Line %ld: %sfile size mismatch!\n%ld bytes expected, ", line, warning, expected);
Printf ("%ld bytes written.\n", size);
}
}
else if (!arg[ARG_QUIET])
Printf ("Line %ld: %sunexpected end of file!\n", line, error);
Close (out);
}
}
}
while (!done);
if (badChecksum)
return (BAD_CHECKSUM);
else if (gotBegin)
return (IoErr ());
else
{
if (!arg[ARG_QUIET])
Printf ("%sno encoded data found.\n", warning);
return (NO_DATA_FOUND);
}
}
/* EOF */