bryce@hoser.berkeley.edu (Bryce Nesbitt) (09/09/87)
#! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: uuencode.1 uuencode.c uudecode.c # Wrapped by bryce@hoser.berkeley.edu on Mon Sep 7 22:27:18 1987 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f uuencode.1 -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"uuencode.1\" else echo shar: Extracting \"uuencode.1\" \(2661 characters\) sed "s/^X//" >uuencode.1 <<'END_OF_uuencode.1' X.TH UUENCODE 1 "1 Sep 1987" X.UC 4 X.SH NAME Xuuencode,uudecode \- encode/decode a binary file for transmission via X(plain text) mail X.SH SYNOPSIS X.B uuencode X[source] remotedest | X.B mail Xsys1!sys2!..!decode X.br X.B uuencode X>outfile.uue source remotedest X.br X.B uuencode X>outfile.uue <source remotedest X.br X.B uudecode X[file] X.SH DESCRIPTION X.I Uuencode Xand X.I uudecode Xare used to send a binary file via uucp (or other) mail. This combination can Xbe used over indirect mail links even when X.IR uusend (1C) Xor other direct binary transmission methods are not available. X.PP X.I Uuencode Xtakes the named source file (default standard input) and produces an encoded Xversion on the standard output. The encoding uses only printing ASCII Xcharacters, and includes the mode of the file and the X.I remotedest Xfor recreation on the remote system. X.PP X.I Uudecode Xreads an encoded file, strips off any leading lines added by mailers, Xand recreates the original file with the specified mode and name. If Xthere are other uuencoded files in the same input, they will be decoded Xas well. X.PP XThe intent is that all mail to the user ``decode'' should be filtered Xthrough the uudecode program. This way the file is created automatically Xwithout human intervention. This is possible on the uucp network by either Xusing X.I sendmail Xor by making X.I rmail Xbe a link to X.I Mail Xinstead of X.I mail. XIn each case, an alias must be created in a master file to get Xthe automatic invocation of uudecode. X.PP XIf these facilities are not available, the file can be uudecoded manually. X.PP XThe encode file has an ordinary text form and can be edited by any text editor Xto change the mode or remote name. X.PP XThis version of uuencode automatically adds checksums to each line, and Xan overall file size to the end. Old versions of uudecode will ignore this Xextra information, new versions will check it and complain if it is in Xerror. X.PP XCare has been taken with these versions to compensate for most of the nasty Xthings editors and networks can do to files. In particular, lines that Xhave had trailing spaces truncated are handled, as are files that have Xpassed through X.I BITNET Xhosts. X.SH SEE\ ALSO Xuuencode(5), uusend(1C), uucp(1C), uux(1C), mail(1) X.SH AUTHOR XMark Horton X.br XChecksums and Amiga port by Alan J. Rosenthal X.br XFile compatability added back in by Fred Fish X.br XFile size check and various refinements by Bryce Nesbitt X.SH BUGS XThe file is expanded by 35% (3 bytes become 4, plus control information) Xcausing it to take longer to transmit. X.PP XThe user on the remote system who is invoking X.I uudecode X(often X.I uucp) Xmust have write permission on the specified file END_OF_uuencode.1 if test 2661 -ne `wc -c <uuencode.1`; then echo shar: \"uuencode.1\" unpacked with wrong size! fi # end of overwriting check fi if test -f uuencode.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"uuencode.c\" else echo shar: Extracting \"uuencode.c\" \(3245 characters\) sed "s/^X//" >uuencode.c <<'END_OF_uuencode.c' X/* #ifndef lint Xstatic char sccsid[] = "@(#)uuencode.c 5.3-1 (Berkeley) 9/1/87"; X#endif */ X X/* Written by Mark Horton */ X/* Modified by ajr (Alan J Rosenthatl,flaps@utcsri.UUCP) to use checksums */ X/* Modified by fnf (Fred Fish,well!fnf) to use Keith Pyle's suggestion for X compatibility */ X/* Modified by bcn (Bryce Nesbitt,ucbvax!cogsci!bryce) to enable CTRL-C for X Amiga Lattice C and add a transparant file size trailer for later check. */ X X/* X * uuencode >outfile [infile] name X * X * Encode a file so it can be mailed to a remote system. This version X * transparantly adds line checksums and a file size for sanity checks. X * X */ X X#include <stdio.h> X X#ifdef AMIGA /* Amiga Lattice C */ X#define AMIGA_LATTICE X#define MCH_AMIGA X#define MPU68000 X#endif X X#ifdef unix X#include <sys/types.h> X#include <sys/stat.h> X#endif X X#define SUMSIZE 64 /* 6 bits */ X/* ENC is the basic 1 character encode function to make a char printing */ X/* Each output character represents 6 bits of input */ X#define ENC(c) ((c) ? ((c) & 077) + ' ': '`') Xlong totalsize=0; /* Used to count the file size because ftell() does X not return sane results for pipes */ X Xmain(argc, argv) Xchar **argv; X{ X FILE *in; X int mode; X#ifdef unix X struct stat sbuf; X#endif X#ifdef AMIGA_LATTICE X extern int Enable_Abort; /* Enable CTRL-C for Lattice */ X Enable_Abort=1; X#endif X X /* optional 1st argument */ X if (argc > 2) { X if ((in = fopen(argv[1], "r")) == NULL) { X fprintf(stderr, "ERROR: can't find %s\n", argv[1]); X fprintf(stderr, "USAGE: uuencode >outfile [infile] name\n"); X exit(10); X } X argv++; argc--; X } else X in = stdin; X X if (argc != 2) { X fprintf(stderr, "USAGE: uuencode >outfile [infile] name\n"); X exit(11); X } X X#ifdef unix X /* figure out the input file mode */ X fstat(fileno(in), &sbuf); X mode = sbuf.st_mode & 0777; X#else X mode = 0644; /* Default permissions */ X#endif X X printf("\nbegin %o %s\n", mode, argv[1]); X X encode(in, stdout); X X printf("end\n"); X printf("size %ld\n",totalsize); X exit(0); X} X X/* X * copy from in to out, encoding as you go along. X */ Xencode(in, out) XFILE *in; XFILE *out; X{ X#ifndef unix Xextern errno; X#endif X char buf[80]; X int i, n, checksum; X X for (;;) { X /* 1 (up to) 45 character line */ X n = fr(in, buf, 45); X putc(ENC(n), out); X X checksum = 0; X for (i=0; i<n; i += 3) X checksum = (checksum+outdec(&buf[i], out)) % SUMSIZE; X X putc(ENC(checksum), out); X putc('\n', out); X X#ifndef unix X /* Error checking under UNIX?? You must be kidding! */ X if (errno) { X fprintf(stderr, "ERROR: error writing to output\n"); X exit(12); X } X#endif X if (n <= 0) X break; X } X} X X/* X * output one group of 3 bytes, pointed at by p, on file f. X * return the checksum increment. X */ Xint outdec(p, f) Xchar *p; XFILE *f; X{ X int c1, c2, c3, c4; X X c1 = *p >> 2; X c2 = (*p << 4) & 060 | (p[1] >> 4) & 017; X c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03; X c4 = p[2] & 077; X putc(ENC(c1), f); X putc(ENC(c2), f); X putc(ENC(c3), f); X putc(ENC(c4), f); X X return((p[0]+p[1]+p[2]) % SUMSIZE); X} X X/* fr: like read but stdio */ Xint Xfr(fd, buf, cnt) XFILE *fd; Xchar *buf; Xint cnt; X{ X int c, i; X X for (i=0; i<cnt; i++) { X c = getc(fd); X if (c == EOF) X return(i); X totalsize++; X buf[i] = c; X } X return (cnt); X} END_OF_uuencode.c if test 3245 -ne `wc -c <uuencode.c`; then echo shar: \"uuencode.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f uudecode.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"uudecode.c\" else echo shar: Extracting \"uudecode.c\" \(6418 characters\) sed "s/^X//" >uudecode.c <<'END_OF_uudecode.c' X/* #ifndef lint Xstatic char sccsid[] = "@(#)uudecode.c 5.3-1 (Berkeley) 9/1/87"; X#endif */ X X/* Written by Mark Horton */ X/* Modified by ajr (Alan J Rosenthatl,flaps@utcsri.UUCP) to use checksums */ X/* Modified by fnf (Fred Fish,well!fnf) to use Keith Pyle's suggestion for X compatibility */ X/* Modified by bcn (Bryce Nesbitt,ucbvax!cogsci!bryce) to fix a misleading X error message on the Amiga port, to fix a bug that prevented decoding X certain files, to work even if trailing spaces have been removed from a X file, to check the filesize (if present), to add some error checking, to X loop for multiple decodes from a single file, and to handle common X BITNET mangling. Also kludged around a missing string function in Aztec X C */ X X/* X * uudecode [input] X * X * Decode a file encoded with uuencode. WIll extract multiple encoded X * modules from a single file. Can deal with most mangled files, including X * BITNET. X */ X X#include <stdio.h> X#include <ctype.h> X X#ifdef AMIGA X#define AMIGA_LATTICE /* Set for Amiga Lattice C */ X#define MCH_AMIGA X#define MPU68000 X#endif X X#ifdef unix X#include <pwd.h> X#include <sys/types.h> X#include <sys/stat.h> X#endif X X#define SUMSIZE 64 X#define DEC(c) (((c) - ' ') & 077) /* single character decode */ X Xmain(argc, argv) Xchar **argv; X{ XFILE *in, *out; Xint through_loop=0; /* Dejavu indicator */ Xint mode; /* file's mode (from header) */ Xlong filesize; /* theoretical file size (from header) */ Xchar dest[128]; Xchar buf[80]; X X#ifdef AMIGA_LATTICE Xextern int Enable_Abort; X Enable_Abort=1; X#endif X X /* A filename can be specified to be uudecoded, or nothing can X be specified, and the input will come from STDIN */ X X switch (argc) X { X case 1: X in=stdin; X break; X X case 2: X if ((in = fopen(argv[1], "r")) == NULL) X { X fprintf(stderr, "ERROR: can't find %s\n", argv[1]); X fprintf(stderr, "USAGE: uudecode [infile]\n"); X exit(10); X } X break; X X default: X fprintf(stderr, "USAGE: uudecode [infile]\n"); X exit(11); X break; X } X X /* Loop through file, searching for headers. Decode anything with a X header, complain if there where no headers. */ X Xfor (;;) X{ X /* search file for header line */ X for (;;) X { X if (fgets(buf, sizeof buf, in) == NULL) X { X if (!through_loop) X { X fprintf(stderr, "ERROR: no `begin' line!\n"); X exit(12); X } X else X { X exit(0); X } X } X if (strncmp(buf, "begin ", 6) == 0) X break; X } X sscanf(buf, "begin %o %s", &mode, dest); X X#ifdef unix X /* handle ~user/file format */ X if (dest[0] == '~') X { X char *sl; X struct passwd *getpwnam(); X char *index(); X struct passwd *user; X char dnbuf[100]; X X sl = index(dest, '/'); X if (sl == NULL) X { X fprintf(stderr, "Illegal ~user\n"); X exit(13); X } X *sl++ = 0; X user = getpwnam(dest+1); X if (user == NULL) X { X fprintf(stderr, "No such user as %s\n", dest); X exit(14); X } X strcpy(dnbuf, user->pw_dir); X strcat(dnbuf, "/"); X strcat(dnbuf, sl); X strcpy(dest, dnbuf); X } X#endif X X /* create output file */ X if ((out = fopen(dest, "w")) == NULL) X { X fprintf(stderr, "ERROR: can't open output file %s\n", dest); X exit(15); X } X#ifdef unix X chmod(dest, mode); X#endif X X decode(in, out, dest); X X if (fgets(buf, sizeof buf, in) == NULL || strncmp(buf,"end",3)) X { /* don't be overly picky about newline ^ */ X fprintf(stderr, "ERROR: no `end' line\n"); X exit(16); X } X X if (!(fgets(buf,sizeof buf,in) == NULL || strncmp(buf,"size ",3))) X { X sscanf(buf, "size %ld", &filesize); X if (ftell(out) != filesize) X { X fprintf(stderr, "ERROR: file should have been %ld bytes long but was %ld.\n", filesize, ftell(out)); X exit(17); X } X } X through_loop = 1; X} /* forever */ X} /* main */ X X/* X * Copy from in to out, decoding as you go. X * If a return or newline is encountered too early in a line, it is X * assumed that means that some editor has truncated trailing spaces. X */ Xdecode(in, out, dest) XFILE *in; XFILE *out; Xchar *dest; X{ Xchar buf[81]; Xchar *bp; Xint nosum=0; X#ifndef unix Xextern errno; X#endif Xregister int j; Xregister int n; Xint checksum, line; X X for (line = 1; ; line++) /* for each input line */ X { X if (fgets(buf, sizeof buf, in) == NULL) X { X fprintf(stderr, "ERROR: input ended unexpectedly!\n"); X exit(18); X } X X /* Pad end of lines in case some editor truncated trailing X spaces */ X X for (n=0;n<79;n++) /* search for first \r, \n or \000 */ X { X if (buf[n]=='\176') /* If BITNET made a twiddle, */ X buf[n]='\136'; /* we make a caret */ X if (buf[n]=='\r'||buf[n]=='\n'||buf[n]=='\000') X break; X } X for (;n<79;n++) /* when found, fill rest of line with space */ X { X buf[n]=' '; X } X buf[79]=0; /* terminate new string */ X X checksum = 0; X n = DEC(buf[0]); X if (n <= 0) X break; /* 0 bytes on a line?? Must be the last line */ X X bp = &buf[1]; X X /* FOUR input characters go into each THREE output charcters */ X X while (n >= 4) X { X j = DEC(bp[0]) << 2 | DEC(bp[1]) >> 4; putc(j, out); checksum += j; X j = DEC(bp[1]) << 4 | DEC(bp[2]) >> 2; putc(j, out); checksum += j; X j = DEC(bp[2]) << 6 | DEC(bp[3]); putc(j, out); checksum += j; X checksum = checksum % SUMSIZE; X bp += 4; X n -= 3; X } X X j = DEC(bp[0]) << 2 | DEC(bp[1]) >> 4; X checksum += j; X if (n >= 1) X putc(j, out); X j = DEC(bp[1]) << 4 | DEC(bp[2]) >> 2; X checksum += j; X if (n >= 2) X putc(j, out); X j = DEC(bp[2]) << 6 | DEC(bp[3]); X checksum += j; X if (n >= 3) X putc(j, out); X checksum = checksum % SUMSIZE; X bp += 4; X n -= 3; X X#ifndef unix X /* Error checking under UNIX??? You must be kidding... */ X /* Check if an error occured while writing to that last line */ X if (errno) X { X fprintf(stderr, "ERROR: error writing to %s\n",dest); X exit(19); X } X#endif X X /* The line has been decoded; now check that sum */ X X nosum |= !isspace(*bp); X if (nosum) /* Is there a checksum at all?? */ X { X if (checksum != DEC(*bp)) /* Does that checksum match? */ X { X fprintf(stderr, "ERROR: checksum mismatch decoding %s, line %d.\n",dest, line); X } X } /* sum */ X } /* line */ X} /* function */ X X#ifdef unix X/* X * Return the ptr in sp at which the character c appears; X * 0 if not found X */ Xchar * Xindex(sp, c) Xregister char *sp, c; X{ X do X { X if (*sp == c) X return(sp); X } X while (*sp++); X X return(0); X} X#endif unix X END_OF_uudecode.c if test 6418 -ne `wc -c <uudecode.c`; then echo shar: \"uudecode.c\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of shell archive. exit 0