home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / starter / uudecode.c < prev    next >
C/C++ Source or Header  |  1994-03-05  |  5KB  |  227 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. /*
  19.  * Modified 12 April 1990 by Mark Adler for use on MSDOS systems with
  20.  * Microsoft C and Turbo C.
  21.  *
  22.  * Modifed 13 February 1991 by Greg Roelofs for use on VMS systems.  As
  23.  * with the MS-DOS version, the setting of the file mode has been disabled.
  24.  * Compile and link normally (but note that the shared-image link option
  25.  * produces a binary only 6 blocks long, as opposed to the 137-block one
  26.  * produced by an ordinary link).  To set up the VMS symbol to run the
  27.  * program ("run uudecode filename" won't work), do:
  28.  *        uudecode :== "$disk:[directory]uudecode.exe"
  29.  * and don't forget the leading "$" or it still won't work.  The binaries
  30.  * produced by this program are in VMS "stream-LF" format; this makes no
  31.  * difference to VMS when running decoded executables, nor to VMS unzip,
  32.  * but other programs such as zoo or arc may or may not require the file
  33.  * to be "BILFed" (or "unBILFed" or whatever).  Also, unlike the other
  34.  * flavors, VMS files don't get overwritten (a higher version is created).
  35.  * 
  36.  * Modified 13 April 1991 by Gary Mussar to be forgiving of systems that
  37.  * appear to be stripping trailing blanks.
  38.  */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)uudecode.c    5.5 (Berkeley) 7/6/88";
  42. #endif /* not lint */
  43.  
  44. #ifdef __MSDOS__        /* For Turbo C */
  45. #define MSDOS 1
  46. #endif
  47.  
  48. /*
  49.  * uudecode [input]
  50.  *
  51.  * create the specified file, decoding as you go.
  52.  * used with uuencode.
  53.  */
  54. #include <stdio.h>
  55.  
  56. #ifdef VMS
  57. #  include <types.h>
  58. #  include <stat.h>
  59. #else
  60. #  ifndef MSDOS            /* i.e., UNIX */
  61. #    include <pwd.h>
  62. #  endif
  63. #  include <sys/types.h>   /* MSDOS or UNIX */
  64. #  include <sys/stat.h>
  65. #endif
  66.  
  67. /* single-character decode */
  68. #define DEC(c)    (((c) - ' ') & 077)
  69.  
  70. main(argc, argv)
  71. char **argv;
  72. {
  73.     FILE *in, *out;
  74.     int mode;
  75.     char dest[128];
  76.     char buf[80];
  77.  
  78.     /* optional input arg */
  79.     if (argc > 1) {
  80.         if ((in = fopen(argv[1], "r")) == NULL) {
  81.             perror(argv[1]);
  82.             exit(1);
  83.         }
  84.         argv++; argc--;
  85.     } else
  86.         in = stdin;
  87.  
  88.     if (argc != 1) {
  89.         printf("Usage: uudecode [infile]\n");
  90.         exit(2);
  91.     }
  92.  
  93.     /* search for header line */
  94.     for (;;) {
  95.         if (fgets(buf, sizeof buf, in) == NULL) {
  96.             fprintf(stderr, "No begin line\n");
  97.             exit(3);
  98.         }
  99.         if (strncmp(buf, "begin ", 6) == 0)
  100.             break;
  101.     }
  102.     (void)sscanf(buf, "begin %o %s", &mode, dest);
  103.  
  104. #if !defined(MSDOS) && !defined(VMS)    /* i.e., UNIX */
  105.     /* handle ~user/file format */
  106.     if (dest[0] == '~') {
  107.         char *sl;
  108.         struct passwd *getpwnam();
  109.         struct passwd *user;
  110.         char dnbuf[100], *index(), *strcat(), *strcpy();
  111.  
  112.         sl = index(dest, '/');
  113.         if (sl == NULL) {
  114.             fprintf(stderr, "Illegal ~user\n");
  115.             exit(3);
  116.         }
  117.         *sl++ = 0;
  118.         user = getpwnam(dest+1);
  119.         if (user == NULL) {
  120.             fprintf(stderr, "No such user as %s\n", dest);
  121.             exit(4);
  122.         }
  123.         strcpy(dnbuf, user->pw_dir);
  124.         strcat(dnbuf, "/");
  125.         strcat(dnbuf, sl);
  126.         strcpy(dest, dnbuf);
  127.     }
  128. #endif    /* !defined(MSDOS) && !defined(VMS) */
  129.  
  130.     /* create output file */
  131. #ifdef MSDOS
  132.     out = fopen(dest, "wb");    /* Binary file */
  133. #else
  134.     out = fopen(dest, "w");
  135. #endif
  136.     if (out == NULL) {
  137.         perror(dest);
  138.         exit(4);
  139.     }
  140. #if !defined(MSDOS) && !defined(VMS)    /* i.e., UNIX */
  141.     chmod(dest, mode);
  142. #endif
  143.  
  144.     decode(in, out);
  145.  
  146.     if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) {
  147.         fprintf(stderr, "No end line\n");
  148.         exit(5);
  149.     }
  150.     exit(0);
  151. }
  152.  
  153. /*
  154.  * copy from in to out, decoding as you go along.
  155.  */
  156. decode(in, out)
  157. FILE *in;
  158. FILE *out;
  159. {
  160.     char buf[80];
  161.     char *bp;
  162.     int n, i, expected;
  163.  
  164.     for (;;) {
  165.         /* for each input line */
  166.         if (fgets(buf, sizeof buf, in) == NULL) {
  167.             printf("Short file\n");
  168.             exit(10);
  169.         }
  170.         n = DEC(buf[0]);
  171.         if ((n <= 0) || (buf[0] == '\n'))
  172.             break;
  173.  
  174.         /* Calculate expected # of chars and pad if necessary */
  175.         expected = ((n+2)/3)<<2;
  176.         for (i = strlen(buf)-1; i <= expected; i++) buf[i] = ' ';
  177.  
  178.         bp = &buf[1];
  179.         while (n > 0) {
  180.             outdec(bp, out, n);
  181.             bp += 4;
  182.             n -= 3;
  183.         }
  184.     }
  185. }
  186.  
  187. /*
  188.  * output a group of 3 bytes (4 input characters).
  189.  * the input chars are pointed to by p, they are to
  190.  * be output to file f.  n is used to tell us not to
  191.  * output all of them at the end of the file.
  192.  */
  193. outdec(p, f, n)
  194. char *p;
  195. FILE *f;
  196. {
  197.     int c1, c2, c3;
  198.  
  199.     c1 = DEC(*p) << 2 | DEC(p[1]) >> 4;
  200.     c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
  201.     c3 = DEC(p[2]) << 6 | DEC(p[3]);
  202.     if (n >= 1)
  203.         putc(c1, f);
  204.     if (n >= 2)
  205.         putc(c2, f);
  206.     if (n >= 3)
  207.         putc(c3, f);
  208. }
  209.  
  210. /*
  211.  * Return the ptr in sp at which the character c appears;
  212.  * NULL if not found
  213.  */
  214.  
  215. #define    NULL    0
  216.  
  217. char *
  218. index(sp, c)
  219. register char *sp, c;
  220. {
  221.     do {
  222.         if (*sp == c)
  223.             return(sp);
  224.     } while (*sp++);
  225.     return(NULL);
  226. }
  227.