home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / telecom / uucp_442 / src / unix / new / uucodes.lzh / uudecode.c < prev    next >
C/C++ Source or Header  |  1990-12-29  |  7KB  |  294 lines

  1. /* #ifndef lint
  2. static char sccsid[] = "@(#)uudecode.c  5.3-1 (Berkeley) 9/1/87";
  3. #endif */
  4.  
  5. /* Written by Mark Horton */
  6. /* Modified by ajr (Alan J Rosenthatl,flaps@utcsri.UUCP) to use checksums */
  7. /* Modified by fnf (Fred Fish,well!fnf) to use Keith Pyle's suggestion for
  8.    compatibility */
  9. /* Modified by bcn (Bryce Nesbitt,ucbvax!cogsci!bryce) to fix a misleading
  10.    error message on the Amiga port, to fix a bug that prevented decoding
  11.    certain files, to work even if trailing spaces have been removed from a
  12.    file, to check the filesize (if present), to add some error checking, to
  13.    loop for multiple decodes from a single file, and to handle common
  14.    BITNET mangling.  Kludged around a missing string function in Aztec
  15.    C. Changed "r" to "rb" and "w" to "wb" for Messy-dos machines
  16.    (Thanks to Andrew Wylie). */
  17.  
  18. /*
  19.  * uudecode [input]
  20.  *
  21.  * Decode a file encoded with uuencode.  Will extract multiple encoded
  22.  * modules from a single file.    Can deal with most mangled files, including
  23.  * those that have been mangled by common BITNET problems.
  24.  *
  25.  * BUGS:
  26.  *  Will only decode while on ASCII systems.
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include <ctype.h>
  31.  
  32. #ifdef AMIGA
  33. #define AMIGA_LATTICE        /* Set for Amiga Lattice C */
  34. #define MCH_AMIGA
  35. #define MPU68000
  36. #endif
  37.  
  38. #ifdef unix
  39. #include <pwd.h>
  40. #include <sys/types.h>
  41. #include <sys/stat.h>
  42. #endif
  43.  
  44. #define SUMSIZE 64
  45. #define DEC(c)  (((c) - ' ') & 077)    /* single character decode */
  46.  
  47. main(argc, argv)
  48. char **argv;
  49. {
  50. FILE    *in, *out;
  51. int    through_loop=0; /* Dejavu indicator */
  52. int    mode;        /* file's mode (from header) */
  53. long    filesize;    /* theoretical file size (from header) */
  54. char    dest[128];
  55. char    buf[80];
  56.  
  57. #ifdef AMIGA_LATTICE
  58. extern    int Enable_Abort;
  59.     Enable_Abort=1;
  60. #endif
  61.  
  62.     /* A filename can be specified to be uudecoded, or nothing can
  63.     be specified, and the input will come from STDIN */
  64.  
  65.     switch (argc)
  66.     {
  67.     case 1:
  68.     in=stdin;
  69.     break;
  70.  
  71.     case 2:
  72.     if ((in = fopen(argv[1], "r")) == NULL)
  73.         {
  74.         fprintf(stderr, "ERROR: can't find %s\n", argv[1]);
  75.         fprintf(stderr, "USAGE: uudecode [infile]\n");
  76.         exit(10);
  77.         }
  78.     break;
  79.  
  80.     default:
  81.     fprintf(stderr, "USAGE: uudecode [infile]\n");
  82.     exit(11);
  83.     break;
  84.     }
  85.  
  86.     /* Loop through file, searching for headers.  Decode anything with a
  87.        header, complain if there where no headers. */
  88.  
  89. for (;;)
  90. {
  91.     /* search file for header line */
  92.     for (;;)
  93.     {
  94.     if (fgets(buf, sizeof buf, in) == NULL)
  95.         {
  96.         if (!through_loop)
  97.         {
  98.         fprintf(stderr, "ERROR: no `begin' line!\n");
  99.         exit(12);
  100.         }
  101.         else
  102.         {
  103.         exit(0);
  104.         }
  105.         }
  106.     if (strncmp(buf, "begin ", 6) == 0)
  107.         break;
  108.     }
  109.     sscanf(buf, "begin %o %s", &mode, dest);
  110.  
  111. #ifdef unix
  112.     /* handle ~user/file format */
  113.     if (dest[0] == '~')
  114.     {
  115.     char *sl;
  116.     struct passwd *getpwnam();
  117.     char *index();
  118.     struct passwd *user;
  119.     char dnbuf[100];
  120.  
  121.     sl = index(dest, '/');
  122.     if (sl == NULL)
  123.         {
  124.         fprintf(stderr, "Illegal ~user\n");
  125.         exit(13);
  126.         }
  127.     *sl++ = 0;
  128.     user = getpwnam(dest+1);
  129.     if (user == NULL)
  130.         {
  131.         fprintf(stderr, "No such user as %s\n", dest);
  132.         exit(14);
  133.         }
  134.     strcpy(dnbuf, user->pw_dir);
  135.     strcat(dnbuf, "/");
  136.     strcat(dnbuf, sl);
  137.     strcpy(dest, dnbuf);
  138.     }
  139. #endif
  140.  
  141.     /* create output file */
  142.     if ((out = fopen(dest, "w")) == NULL)
  143.     {
  144.     fprintf(stderr, "ERROR: can't open output file %s\n", dest);
  145.     exit(15);
  146.     }
  147. #ifdef unix
  148.     chmod(dest, mode);
  149. #endif
  150.  
  151.     decode(in, out, dest);
  152.  
  153.     if (fgets(buf, sizeof buf, in) == NULL || strncmp(buf,"end",3))
  154.     {           /* don't be overly picky about newline ^ */
  155.     fprintf(stderr, "ERROR: no `end' line\n");
  156.     exit(16);
  157.     }
  158.  
  159.     if (!(fgets(buf,sizeof buf,in) == NULL || strncmp(buf,"size ",3)))
  160.     {
  161.     sscanf(buf, "size %ld", &filesize);
  162.     if (ftell(out) != filesize)
  163.         {
  164.         fprintf(stderr, "ERROR: file should have been %ld bytes long but was %ld.\n", filesize, ftell(out));
  165.         exit(17);
  166.         }
  167.     }
  168.     through_loop = 1;
  169. }   /* forever */
  170. }   /* main */
  171.  
  172. /*
  173.  * Copy from in to out, decoding as you go.
  174.  * If a return or newline is encountered too early in a line, it is
  175.  * assumed that means that some editor has truncated trailing spaces.
  176.  */
  177. decode(in, out, dest)
  178. FILE *in;
  179. FILE *out;
  180. char *dest;
  181. {
  182. char buf[81];
  183. char *bp;
  184. int nosum=0;
  185. #ifndef unix
  186. extern errno;
  187. #endif
  188. register int j;
  189. register int n;
  190. int checksum, line;
  191.  
  192.     for (line = 1; ; line++)    /* for each input line */
  193.     {
  194.     if (fgets(buf, sizeof buf, in) == NULL)
  195.         {
  196.         fprintf(stderr, "ERROR: input ended unexpectedly!\n");
  197.         exit(18);
  198.         }
  199.  
  200.     /* Pad end of lines in case some editor truncated trailing
  201.        spaces */
  202.  
  203.     for (n=0;n<79;n++)  /* search for first \r, \n or \000 */
  204.         {
  205.         if (buf[n]=='\176')     /* If BITNET made a twiddle, */
  206.         buf[n]='\136';     /* we make a caret           */
  207.         if (buf[n]=='\r'||buf[n]=='\n'||buf[n]=='\000')
  208.         break;
  209.         }
  210.     for (;n<79;n++)     /* when found, fill rest of line with space */
  211.         {
  212.         buf[n]=' ';
  213.         }
  214.     buf[79]=0;        /* terminate new string */
  215.  
  216.     checksum = 0;
  217.     n = DEC(buf[0]);
  218.     if (n <= 0)
  219.         break;    /* 0 bytes on a line??    Must be the last line */
  220.  
  221.     bp = &buf[1];
  222.  
  223.     /* FOUR input characters go into each THREE output charcters */
  224.  
  225.     while (n >= 4)
  226.         {
  227.         j = DEC(bp[0]) << 2 | DEC(bp[1]) >> 4; putc(j, out); checksum += j;
  228.         j = DEC(bp[1]) << 4 | DEC(bp[2]) >> 2; putc(j, out); checksum += j;
  229.         j = DEC(bp[2]) << 6 | DEC(bp[3]);      putc(j, out); checksum += j;
  230.         checksum = checksum % SUMSIZE;
  231.         bp += 4;
  232.         n -= 3;
  233.         }
  234.  
  235.         j = DEC(bp[0]) << 2 | DEC(bp[1]) >> 4;
  236.         checksum += j;
  237.         if (n >= 1)
  238.             putc(j, out);
  239.         j = DEC(bp[1]) << 4 | DEC(bp[2]) >> 2;
  240.         checksum += j;
  241.         if (n >= 2)
  242.             putc(j, out);
  243.         j = DEC(bp[2]) << 6 | DEC(bp[3]);
  244.         checksum += j;
  245.         if (n >= 3)
  246.             putc(j, out);
  247.         checksum = checksum % SUMSIZE;
  248.         bp += 4;
  249.         n -= 3;
  250.  
  251. #ifndef unix
  252.      /* Error checking under UNIX??? You must be kidding... */
  253.      /* Check if an error occured while writing to that last line */
  254.     if (errno)
  255.         {
  256.         fprintf(stderr, "ERROR: error writing to %s\n",dest);
  257.         exit(19);
  258.         }
  259. #endif
  260.  
  261.     /* The line has been decoded; now check that sum */
  262.  
  263.     nosum |= !isspace(*bp);
  264.     if (nosum)                      /* Is there a checksum at all?? */
  265.         {
  266.         if (checksum != DEC(*bp))   /* Does that checksum match? */
  267.         {
  268.         fprintf(stderr, "ERROR: checksum mismatch decoding %s, line %d.\n",dest, line);
  269.         }
  270.         }    /* sum */
  271.     }    /* line */
  272. }   /* function */
  273.  
  274. #ifdef unix
  275. /*
  276.  * Return the ptr in sp at which the character c appears;
  277.  * 0 if not found
  278.  */
  279. char *
  280. index(sp, c)
  281. register char *sp, c;
  282. {
  283.     do
  284.     {
  285.     if (*sp == c)
  286.         return(sp);
  287.     }
  288.     while (*sp++);
  289.  
  290.     return(0);
  291. }
  292. #endif unix
  293.  
  294.