scott@max.u.washington.edu (02/21/90)
This is the C source code and comments for UUENCODER. Sincerely, Scott K. Stephen ============================================================================== Modified to compile with Microsoft C v3.00 and CI86 only. Much easier to use than uue [remote-f-n] <local-f-n >output-f-n. Both are inverse of the other. Gregory Hicks ============================================================================== Modified once more to compile with Microsoft C V3.00. The CI86 code is still there, surrounded with #ifdef CI86...#endif Usage is: uuencode [input [output] ] if output not specified, write to stdout if input not specified, get input from stdin uudecode [input] if input not specified, get input from stdin WARNING: Current restriction on VAX/VMS: ASCII text files get all CR/LF combinations converted to LF only during UUENCODE. This should not be a major problem, as ASCII text files should not need to be "encoded". Also note that the return status is not consistent with VAX/VMS usage, although the error messages should be OK. Gary Stebbins, DEC, 8/31/86 ============================================================================== The files described in the following paragraphs have been modified for and compiled under Computer Innovations C86. Note that when uuencoding a binary file, you must not feed the file to uuencode through stdin--for some reason, this causes the file to only be partially encoded (I suspect that this happens when uuencode runs into a ^Z in the input--I have played around with putting stdin into 'raw' mode, which failed to successfully correct the problem). So when uuencoding binary files, use the full two-argument form. Note that uudecode is unaffected. Brant Cheikes Department of Computer and Information Science University of Pennsylvania ARPA: brant@linc.cis.upenn.edu CSNET: brant%upenn-linc@upenn.csnet ============================================================================== uudecode and uuencode are easily implemented under MSDOS as well. Here are the sources for Microsoft C v3.0, but if you have another kind of C compiler, there should be perhaps only 1 change -- the output file of uudecode and the input file of uuencode must be in binary format. (ie. binary files, like .EXE files may have byte patterns that are the same as ^Z, which signals end-of-file in non-binary (text) mode). If you need more info, write back. Note that the included files are *not* in "shar" format -- you will have to use an editor to cut the files out. Don Kneller UUCP: ...ucbvax!ucsfcgl!kneller ARPA: kneller@ucsf-cgl.ARPA BITNET: kneller@ucsfcgl.BITNET /* * uudecode [input] * * if input not specified, get input from stdin * * Create the specified file, decoding as you go. * Used with uuencode. * * Modified for use with Microsoft C and VAX/VMS. * Define CI86 symbol to use with CI86. */ #include <stdio.h> #ifndef CI86 #include <sys/types.h> #include <sys/stat.h> #endif /* single character decode */ #define DEC(c) (((c) - ' ') & 077) main(argc, argv) char **argv; { FILE *in, *out; #ifndef CI86 struct stat sbuf; #endif int mode; char dest[128]; char buf[80]; /* optional input arg */ if (argc > 1) { if ((in = fopen(argv[1], "r")) == NULL) { perror(argv[1]); exit(1); } argv++; argc--; } else in = stdin; if (argc != 1) { fprintf(stderr, "Usage: uudecode [infile]\n"); exit(2); } /* search for header line */ for (;;) { if (fgets(buf, sizeof buf, in) == NULL) { fprintf(stderr, "No begin line\n"); exit(3); } if (strncmp(buf, "begin ", 6) == 0) break; } sscanf(buf, "begin %o %s", &mode, dest); /* create output file */ /* binary output file */ out = fopen(dest, "wb"); if (out == NULL) { perror(dest); exit(4); } #ifndef CI86 chmod(dest, mode); #endif decode(in, out); if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) { fprintf(stderr, "No end line\n"); exit(5); } exit(0); } /* * copy from in to out, decoding as you go along. */ decode(in, out) FILE *in; FILE *out; { char buf[80]; char *bp; int n; for (;;) { /* for each input line */ if (fgets(buf, sizeof buf, in) == NULL) { fprintf(stderr, "Short file\n"); exit(10); } n = DEC(buf[0]); if (n <= 0) break; bp = &buf[1]; while (n > 0) { outdec(bp, out, n); bp += 4; n -= 3; } } } /* * 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. */ outdec(p, f, n) char *p; FILE *f; { int c1, c2, c3; c1 = DEC(*p) << 2 | DEC(p[1]) >> 4; c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2; c3 = DEC(p[2]) << 6 | DEC(p[3]); if (n >= 1) putc(c1, f); if (n >= 2) putc(c2, f); if (n >= 3) putc(c3, f); } /* fr: like read but stdio */ int fr(fd, buf, cnt) FILE *fd; char *buf; int cnt; { int c, i; for (i=0; i<cnt; i++) { c = getc(fd); if (c == EOF) return(i); buf[i] = c; } return (cnt); } /* * Return the ptr in sp at which the character c appears; * NULL if not found */ #define NULL 0 char * index(sp, c) register char *sp, c; { do { if (*sp == c) return(sp); } while (*sp++); return(NULL); } ----------------------------------------------- /* * uuencode [input [output] ] * * if output not specified, output to stdout * if input not specified, input from stdin * * Encode a file so it can be mailed to a remote system. * * Modified for use with Microsoft C and VAX/VMS. * Define CI86 symbol to use with CI86. */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> /* ENC is the basic 1 character encoding function to make a char printing */ #define ENC(c) (((c) & 077) + ' ') main(argc, argv) char **argv; { FILE *in, *out; struct stat sbuf; int mode; /* if 3 arguments, then output file specified */ if (argc > 2) { if ((out = fopen(argv[2], "w")) == NULL) { perror(argv[2]); exit(3); } argc--; } else out = stdout; if (argc > 1) { /* Use binary mode */ if ((in = fopen(argv[1], "rb")) == NULL) { perror(argv[1]); exit(1); } argc--; } else in = stdin; if (argc != 1) { fprintf(stderr,"Usage: uuencode [infile [outfile] ]\n"); exit(2); } /* figure out the input file mode */ fstat(fileno(in), &sbuf); mode = sbuf.st_mode & 0777; fprintf(out,"begin %o %s\n", mode, argv[1]); encode(in, out); fprintf(out,"end\n"); exit(0); } /* * copy from in to out, encoding as you go along. */ encode(in, out) FILE *in; FILE *out; { char buf[80]; int i, n; for (;;) { /* 1 (up to) 45 character line */ n = fr(in, buf, 45); putc(ENC(n), out); for (i=0; i<n; i += 3) outdec(&buf[i], out); putc('\n', out); if (n <= 0) break; } } /* * output one group of 3 bytes, pointed at by p, on file f. */ outdec(p, f) char *p; FILE *f; { int c1, c2, c3, c4; c1 = *p >> 2; c2 = (*p << 4) & 060 | (p[1] >> 4) & 017; c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03; c4 = p[2] & 077; putc(ENC(c1), f); putc(ENC(c2), f); putc(ENC(c3), f); putc(ENC(c4), f); } /* fr: like read but stdio */ int fr(fd, buf, cnt) FILE *fd; char *buf; int cnt; { int c, i; for (i=0; i<cnt; i++) { c = getc(fd); if (c == EOF) return(i); buf[i] = c; } return (cnt); }