home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / c-kermit / ckdecod.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  6KB  |  312 lines

  1. #ifndef lint
  2. static char sccsid[] = "@(#)uudecode.c    5.3-1 (Berkeley) 4/10/85";
  3. #endif
  4. /* modified by ajr to use checksums */
  5. /* modified by fnf to use Keith Pyle's suggestion for compatibility */
  6.  
  7. /* Adapted by Phil Julian, SAS Institute, Inc., for use on the Data General
  8.  * minicomputers.  #ifdefs surround host-dependent code.
  9.  * 27 May 1987
  10.  */
  11.  
  12. /*
  13.  * uudecode [input]
  14.  *
  15.  * create the specified file, decoding as you go.
  16.  * used with uuencode.
  17.  */
  18. #include <stdio.h>
  19.  
  20. #ifdef unix
  21. #include <pwd.h>
  22. #include <sys/types.h>
  23. #include <sys/stat.h>
  24. #endif
  25.  
  26. #ifdef datageneral
  27. #include <sys_calls.h>
  28. #include <packets/filestatus.h>         /* Used for ?GNFN */
  29. #include <packets:normal_io.h>
  30. #include <paru.h>
  31. int rec_format, file_type;
  32. struct p_nio_ex w_io_parms;             /* ?write system call structure */
  33. int chanout;                            /* Output channel */
  34. #ifdef putc
  35. #undef putc
  36. #endif
  37. #define putc(c,file) { char ch = (char) (c); dg_binw(fchannel(file),&ch,1); }
  38. #endif
  39.  
  40. #define SUMSIZE 64
  41.  
  42. /* single character decode */
  43. #define DEC(c)    (((c) - ' ') & 077)
  44.  
  45. main(argc, argv)
  46. char **argv;
  47. {
  48.     FILE *in, *out;
  49.     int mode;
  50. #ifdef datageneral
  51.     char dest[256];     /* Filenames can be larger */
  52.     char buf[512];
  53. #else
  54.     char dest[128];
  55.     char buf[80];
  56. #endif
  57.  
  58.     /* optional input arg */
  59.     if (argc > 1) {
  60.         if ((in = fopen(argv[1], "r")) == NULL) {
  61.             perror(argv[1]);
  62.             exit(1);
  63.         }
  64.         argv++; argc--;
  65.     } else
  66.         in = stdin;
  67.  
  68.     if (argc != 1) {
  69.         printf("Usage: uudecode [infile]\n");
  70.         exit(2);
  71.     }
  72.  
  73.     /* search for header line */
  74.     for (;;) {
  75.         if (fgets(buf, sizeof buf, in) == NULL) {
  76.             fprintf(stderr, "No begin line\n");
  77.             exit(3);
  78.         }
  79.         if (strncmp(buf, "begin ", 6) == 0)
  80.             break;
  81.     }
  82. #ifdef datageneral
  83.         /* DG format has extra information, and the record format field must
  84.          * be a legal value.  Other systems only store two items: the file 
  85.          * mode and the file name.  We store the record format, the file
  86.          * name and the file type.
  87.          * Legal record formats are current betwee $RTDY and $RTVB (which 
  88.          * is IBM tape only).
  89.          */
  90.     if ((sscanf(buf, "begin %o %s %o", &rec_format, dest, &file_type) < 3) 
  91.     || ((rec_format < $RTDY) && (rec_format > $RTVB))) {
  92.             /* Not a DG generated file -- use defaults of Dynamic data and
  93.              * a user data file (UDF).
  94.              */
  95.         rec_format = $RTDY;
  96.         file_type  = $FUDF;
  97.     }
  98. #else
  99.     sscanf(buf, "begin %o %s", &mode, dest);
  100. #endif
  101.  
  102. #ifdef unix
  103.     /* handle ~user/file format */
  104.     if (dest[0] == '~') {
  105.         char *sl;
  106.         struct passwd *getpwnam();
  107.         char *index();
  108.         struct passwd *user;
  109.         char dnbuf[100];
  110.  
  111.         sl = index(dest, '/');
  112.         if (sl == NULL) {
  113.             fprintf(stderr, "Illegal ~user\n");
  114.             exit(3);
  115.         }
  116.         *sl++ = 0;
  117.         user = getpwnam(dest+1);
  118.         if (user == NULL) {
  119.             fprintf(stderr, "No such user as %s\n", dest);
  120.             exit(4);
  121.         }
  122.         strcpy(dnbuf, user->pw_dir);
  123.         strcat(dnbuf, "/");
  124.         strcat(dnbuf, sl);
  125.         strcpy(dest, dnbuf);
  126.     }
  127. #endif
  128.  
  129.     /* create output file */
  130. #ifdef datageneral
  131.         zero((char *) &w_io_parms, sizeof(w_io_parms));
  132.         w_io_parms.isti = $IBIN|$RTDY|$ICRF|$OFOT;
  133.         w_io_parms.isti &= ~$IPST;
  134.         w_io_parms.imrs = 2048;
  135.         w_io_parms.ibad = -1;
  136.         w_io_parms.ircl = -1;
  137.  
  138.         if (rec_format == 0) rec_format = $RTUN; 
  139.         out = dg_open(dest, $OFOT|$IBIN|$OFCR|$OFCE|rec_format,file_type);
  140.         if (out == NULL) {
  141.         perror(dest);
  142.         exit(4);
  143.     }
  144.     chanout = fchannel(out);
  145. #else
  146.     out = fopen(dest, "w");
  147.     if (out == NULL) {
  148.         perror(dest);
  149.         exit(4);
  150.     }
  151. #if (unix || !MANX)
  152.     chmod(dest, mode);
  153. #endif
  154. #endif datageneral
  155.  
  156.     decode(in, out);
  157.  
  158.     if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) {
  159.         fprintf(stderr, "No end line\n");
  160.         exit(5);
  161.     }
  162.     exit(0);
  163. }
  164.  
  165. /*
  166.  * copy from in to out, decoding as you go along.
  167.  */
  168. decode(in, out)
  169. FILE *in;
  170. FILE *out;
  171. {
  172.     char buf[80];
  173.     char *bp;
  174.     int n, checksum, line;
  175.     int warnings = 5;
  176.  
  177.     for (line = 1; ; line++) {
  178.         /* for each input line */
  179.         if (fgets(buf, sizeof buf, in) == NULL) {
  180.             printf("Short file\n");
  181.             exit(10);
  182.         }
  183.  
  184.         checksum = 0;
  185.         n = DEC(buf[0]);
  186.         if (n <= 0)
  187.             break;
  188.  
  189.         bp = &buf[1];
  190.         while (n > 0) {
  191.             checksum = (checksum+outdec(bp, out, n)) % SUMSIZE;
  192.             bp += 4;
  193.             n -= 3;
  194.         }
  195.  
  196.         if (*bp != '\n' && checksum != DEC(*bp))
  197.             if (warnings > 0) {
  198.                 printf("Checksum error, line %d.\n",line);
  199.                 warnings--;
  200.             } else if (warnings == 0) {
  201.                 printf("more...\n");
  202.                 warnings--;
  203.             }
  204.     }
  205. }
  206.  
  207. /*
  208.  * output a group of 3 bytes (4 input characters).
  209.  * the input chars are pointed to by p, they are to
  210.  * be output to file f.  n is used to tell us not to
  211.  * output all of them at the end of the file.
  212.  * we return a checksum increment.
  213.  */
  214. int outdec(p, f, n)
  215. char *p;
  216. FILE *f;
  217. {
  218.     int c1, c2, c3;
  219.  
  220.     c1 = DEC(*p) << 2 | DEC(p[1]) >> 4;
  221.     c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
  222.     c3 = DEC(p[2]) << 6 | DEC(p[3]);
  223.  
  224.     if (n >= 1)
  225.         putc(c1, f);
  226.     if (n >= 2)
  227.         putc(c2, f);
  228.     if (n >= 3)
  229.         putc(c3, f);
  230.  
  231.     return((c1+c2+c3) % SUMSIZE);
  232. }
  233.  
  234.  
  235. /* fr: like read but stdio */
  236. int
  237. fr(fd, buf, cnt)
  238. FILE *fd;
  239. char *buf;
  240. int cnt;
  241. {
  242.     int c, i;
  243.  
  244.     for (i=0; i<cnt; i++) {
  245.         c = getc(fd);
  246.         if (c == EOF)
  247.             return(i);
  248.         buf[i] = c;
  249.     }
  250.     return (cnt);
  251. }
  252.  
  253. /*
  254.  * Return the ptr in sp at which the character c appears;
  255.  * NULL if not found
  256.  */
  257.  
  258. #ifndef NULL        /* MANX has bogus "#define NULL 0L" somewhere */
  259. #define    NULL    0
  260. #endif
  261.  
  262. char *
  263. index(sp, c)
  264. register char *sp, c;
  265. {
  266.     do {
  267.         if (*sp == c)
  268.             return(sp);
  269.     } while (*sp++);
  270.     return(NULL);
  271. }
  272.  
  273. #if (!unix && MANX)
  274.  
  275. perror (sp)
  276. char *sp;
  277. {
  278.     if (sp && *sp) {
  279.         fprintf (stderr, "%s: ");
  280.     }
  281.     fprintf (stderr, "<unknown error>\n");
  282. }
  283.  
  284. #endif    /* Unix */
  285.  
  286. #ifdef datageneral
  287. /* D G _ B I N W -- Output len characters to the file number filenum 
  288.  * 
  289.  *  The syntax is like the Unix write command.
  290.  *  This code was borrowed from my Kermit source -- ckdtio.c
  291.  */
  292.  
  293. dg_binw(channel,chs,len) int channel, len; char *chs; 
  294. {
  295.      int ac2,err;
  296.  
  297.      if (len == 0) return(0);
  298.  
  299.      w_io_parms.ich = channel;
  300.      w_io_parms.ibad = chs;
  301.      w_io_parms.ircl = len;
  302.      ac2 = &w_io_parms;
  303.      
  304.      if ((err = sys_write(ac2)) == 0) return(0);
  305.  
  306.      if ( err != ERLTL && err != EREOF ) {
  307.           perror("dg_binw: sys_write ");
  308.           exit(err);
  309.      }
  310. }
  311. #endif
  312.