/* * Uudecode -- decode a uuencoded file back to binary form. * * modified for Lattice C on the ST - 11.05.86 by MSD * modified for Alcyon on the ST -    10-24-86 by RDR * modified (a lot) for MWC on the ST 02/07/87 by JPHD * (Some more to be done on the I/O speed...) * modified more for Atari 8-bit -- jrd * */#include <stdio.h>extern FILE * fopen();extern char * strcpy();#ifdef M6502#define exit(x) careful_exit(x)#else#include <osbind.h>#define fix_pathname(foo) foo#endif#define MAXCHAR 127#define LINELEN 80#define FILELEN 64#define CODEDLN 61#define NORMLEN 45char * mism = "Part suffix mismatch: <%> instead of <%>.\n";#define SUBS1 23#define SUBS238FILE * in, * out;char ifname[FILELEN];char chtbl[MAXCHAR];char * pos;char blank, part = '\0';int partn = 'a';int lens;#ifdef M6502char argbuf[80];#endif/* * Bring back a pointer to the start of the nth word. */char * getnword(str, n)register char * str;register int n;{  while ((*str == '\t') || (*str == ' '))    str++;  if (!*str)    return NULL;  while (--n)    {      while ((*str != '\t') && (*str != ' ') && (*str))str++;      if (!*str)return NULL;      while ((*str == '\t') || (*str == ' '))str++;      if (!*str)return NULL;    }  return str;}main(argc, argv)int argc;char * argv[];{  register int i, j;  char dest[FILELEN], buf[LINELEN];#ifdef M6502  if (argc < 2)    argc = 1 + readargs("UUD>", argbuf, argv + 1);#endif  if (argc < 2)    {      Console("Almost foolproof uudecode v1.0 15-Feb-1987 JPHD\n");      Console("Usage: uudecode inputfile\n");      exit(1);    }  if ((in = fopen(fix_pathname(argv[1]), "r")) == NULL)    {      Console("Cant open input file.\n");      exit(2);    }  /*   * Set up the default translation table.   */  for (i = 0; i < ' '; i++)    chtbl[i] = '\0';  for (i = ' ', j = 0; i < ' ' + 64; i++, j++)    chtbl[i] = j;  for (i = ' ' + 64; i < MAXCHAR; i++)    chtbl[i] = '\0';  chtbl['`'] = chtbl[' '];/* common mutation */  chtbl['~'] = chtbl['^'];/* an other common mutation */  blank = ' ';  /*   * search for header or translation table line.   */  for (;;)    {      if (fgets(buf, sizeof buf, in) == NULL){  Console("No begin line\n");  exit(3);}      if (strncmp(buf, "table", 5) == 0){  gettable();  continue;}      if (strncmp(buf, "begin", 5) == 0){  break;}    }  lens = strlen(buf);  if (lens)    buf[--lens] = '\0';  if ((pos = getnword(buf, 3)) == NULL)    {      Console("Missing filename in begin line.\n");      exit(10);    }  else    strcpy(dest, pos);  if ((out = fopen(fix_pathname(dest), "wb")) == NULL)    {      Console("Cannot open output file\n");      exit(4);    }  decode();  fclose(out);  exit(0);}/* * Install the table in memory for later use. */gettable(){  char buf[LINELEN];  register int c, n;  register char * cpt;  n = 0;  for (c = 0; c <= MAXCHAR; c++)    chtbl[c] = '\0'; again:if (fgets(buf, sizeof buf, in) == NULL)   {     Console("EOF while in translation table.\n");     exit(5);   }  if (strncmp(buf, "begin", 5) == 0)    {      Console("Incomplete translation table.\n");      exit(6);    }  cpt = buf + strlen(buf) - 1;  *cpt = ' ';  while (*(cpt) == ' ')    {      *cpt = '\0';      cpt--;    }  cpt = buf;  while (c = *cpt)    {      if (chtbl[c] != '\0'){  Console("Duplicate char in translation table.\n");  exit(6);}      if (n == 0)blank = c;      chtbl[c] = n++;      if (n >= 64)return;      cpt++;    }  goto again;}/* * copy from in to out, decoding as you go along. */decode(){  char buf[LINELEN], outl[LINELEN];  register char * bp, * ut, * trtbl;  register unsigned int n, c, len;  trtbl = chtbl;  for (;;)    {      if (fgets(buf, sizeof buf, in) == NULL){  Console("Short file.\n");  return;}      len = strlen(buf);      if (len)buf[--len] = '\0';      /*       * Get the binary line length.       */      n = trtbl[*buf];      if (n == NORMLEN)goto decod;      /*       * end of uuencoded file ?       */      if (strncmp(buf, "end", 3) == 0)return;      /*       * end of current file ? : get next one.       */      if (strncmp(buf, "include", 7) == 0){  getfile(buf);  continue;}      /*       * Is it the empty line before the end line ?       */      if (n <= 0)continue;      /*       * Pad with blanks.       */    decod:for (bp = &buf[c = len];       c < CODEDLN; c++, bp++)      *bp = blank;      /*       * output a group of 3 bytes (4 input characters).       * the input chars are pointed to by p, they are to       * be output to file f.  n is used to tell us not to       * output all of them at the end of the file.       */      ut = outl;      len = n;      bp = &buf[1];      while (n > 0){  *(ut++) = trtbl[*bp] << 2 | trtbl[bp[1]] >> 4;  n--;  if (n)    {      *(ut++) = trtbl[bp[1]] << 4 | trtbl[bp[2]] >> 2;      n--;    }  if (n)    {      *(ut++) = trtbl[bp[2]] << 6 | trtbl[bp[3]];      n--;    }  bp += 4;}      n = fwrite(outl, 1, len, out);    }}/* you may need to rename the filenames at the ends of each part* if the encoder encoded them on directories and specified drives.*/getfile(buf)register char * buf;{  if ((pos = getnword(buf, 2)) == NULL)    {      Console("Missing include file name.\n");      exit(11);    }  else    strcpy(ifname, pos);#ifdef M6502  fclose(in);  if ((in = fopen(fix_pathname(ifname), "r")) == NULL)#else  if (freopen(ifname, "r", in) !=in)#endif    {      Console("Cannot reassign input file to included file.\n");      exit(7);    }  for (;;)    {      if (fgets(buf, LINELEN, in) == NULL){  Console("No begin line in included file: ");  Console(ifname);  Console(".\n");  exit(3);}      if (strncmp(buf, "table", 5) == 0){  gettable();  continue;}      if (strncmp(buf, "begin", 5) == 0){  break;}    }  lens = strlen(buf);  if (lens)    buf[--lens] = '\0';  if ((pos = getnword(buf, 3)) == NULL)    {      Console("Missing part name, in included begin line.\n");      part = '?';    }  else    {      part = *pos;/* * Check the part suffix. */      partn++;      if (part != partn){  mism[SUBS1] = part;  mism[SUBS2] = partn;  Console(mism);}    }}/* * Output to console, immune against redirection of stdout. */Console(s)register char * s;{  while (*s)    Bconout(2, *s++);}