From: Sky Liu Date: Sun, 7 Sep 2014 02:05:15 +0000 (+0800) Subject: Porting uuencode/uudecode from NetBSD X-Git-Tag: v3.3.0~12 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zlib_tech.html?a=commitdiff_plain;h=refs%2Fchanges%2F20%2F2820%2F2;p=minix.git Porting uuencode/uudecode from NetBSD Lionel: I fixed small mistakes in the mi file, typos, missing keywords, and whitespace fixes. Change-Id: If0c04b923af328838f2d0950e189bf28995bc0f0 --- diff --git a/distrib/sets/lists/minix/mi b/distrib/sets/lists/minix/mi index 0becfe402..6d10cd780 100644 --- a/distrib/sets/lists/minix/mi +++ b/distrib/sets/lists/minix/mi @@ -543,9 +543,9 @@ ./usr/bin/update minix-sys ./usr/bin/uptime minix-sys ./usr/bin/users minix-sys -./usr/bin/uud minix-sys +./usr/bin/uud minix-sys obsolete ./usr/bin/uudecode minix-sys -./usr/bin/uue minix-sys +./usr/bin/uue minix-sys obsolete ./usr/bin/uuencode minix-sys ./usr/bin/uuidgen minix-sys ./usr/bin/version minix-sys @@ -1890,7 +1890,7 @@ ./usr/lib/bc/libminc.a minix-sys bitcode ./usr/lib/bc/libminixfs.a minix-sys bitcode ./usr/lib/bc/libminlib.a minix-sys bitcode obsolete -./usr/lib/bc/libmthread.a minix-sys bitcode +./usr/lib/bc/libmthread.a minix-sys bitcode ./usr/lib/bc/libnetdriver.a minix-sys bitcode ./usr/lib/bc/libnetsock.a minix-sys bitcode ./usr/lib/bc/libopcodes.a minix-sys bitcode,binutils @@ -2215,8 +2215,8 @@ ./usr/Makefile minix-sys ./usr/man minix-sys ./usr/man/man1 minix-sys -./usr/man/man1/..1 minix-sys obsolete ./usr/man/man1/[.1 minix-sys +./usr/man/man1/..1 minix-sys obsolete ./usr/man/man1/addr2line.1 minix-sys binutils ./usr/man/man1/apropos.1 minix-sys ./usr/man/man1/ar.1 minix-sys binutils @@ -2537,8 +2537,10 @@ ./usr/man/man1/unzip.1 minix-sys ./usr/man/man1/uptime.1 minix-sys ./usr/man/man1/users.1 minix-sys -./usr/man/man1/uud.1 minix-sys -./usr/man/man1/uue.1 minix-sys +./usr/man/man1/uud.1 minix-sys obsolete +./usr/man/man1/uudecode.1 minix-sys +./usr/man/man1/uue.1 minix-sys obsolete +./usr/man/man1/uuencode.1 minix-sys ./usr/man/man1/uuidgen.1 minix-sys ./usr/man/man1/vi.1 minix-sys ./usr/man/man1/view.1 minix-sys @@ -5013,6 +5015,7 @@ ./usr/man/man5/tzfile.5 minix-sys ./usr/man/man5/usermgmt.conf.5 minix-sys ./usr/man/man5/utmp.5 minix-sys +./usr/man/man5/uuencode.5 minix-sys ./usr/man/man6 minix-sys ./usr/man/man6/adventure.6 minix-sys ./usr/man/man6/arithmetic.6 minix-sys @@ -5027,7 +5030,7 @@ ./usr/man/man6/ppt.6 minix-sys ./usr/man/man6/primes.6 minix-sys ./usr/man/man6/random.6 minix-sys -./usr/man/man6/tetris.6 +./usr/man/man6/tetris.6 minix-sys ./usr/man/man6/wargames.6 minix-sys ./usr/man/man7 minix-sys ./usr/man/man7/ascii.7 minix-sys @@ -5098,7 +5101,7 @@ ./usr/man/man8/ossdevlinks.8 minix-sys ./usr/man/man8/part.8 minix-sys ./usr/man/man8/partition.8 minix-sys -./usr/man/man8/ping.8 minix-sys +./usr/man/man8/ping.8 minix-sys ./usr/man/man8/postinstall.8 minix-sys ./usr/man/man8/poweroff.8 minix-sys ./usr/man/man8/printroot.8 minix-sys diff --git a/minix/commands/Makefile b/minix/commands/Makefile index 94fe739a3..9882d297c 100644 --- a/minix/commands/Makefile +++ b/minix/commands/Makefile @@ -28,7 +28,7 @@ SUBDIR= add_route arp at backup btrace \ syslogd tcpd tcpdp tcpstat telnet \ telnetd term termcap tget time \ truncate udpstat umount \ - update uud uue version vol \ + update version vol \ writeisofs fetch \ zdump zmodem pkgin_cd pkgin_all pkgin_sets \ worldstone updateboot update_bootcfg \ diff --git a/minix/commands/uud/Makefile b/minix/commands/uud/Makefile deleted file mode 100644 index 793da4233..000000000 --- a/minix/commands/uud/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -PROG= uud -MAN= - -LINKS+= ${BINDIR}/uud ${BINDIR}/uudecode - -.include diff --git a/minix/commands/uud/uud.c b/minix/commands/uud/uud.c deleted file mode 100644 index 3e4a970ff..000000000 --- a/minix/commands/uud/uud.c +++ /dev/null @@ -1,562 +0,0 @@ -/* uud - bulletproof version of uudecode */ - -/* - * Uud -- decode a uuencoded file back to binary form. - * - * From the Berkeley original, modified by MSD, RDR, JPHD & WLS. - * The Atari GEMDOS version compiled with MWC 2.x. - * The MSDOS version with TurboC. - * The Unix version with cc. - * this version is made: 25 Nov 1988. - * Jan 2 1990: Change system definition and change MSDOS to open the output - * file for write binary do cr/lf replacement. - */ - -#define UNIX 1 /* define one of: UNIX (Minix too!), MSDOS, or GEMDOS */ - -#ifdef GEMDOS -#define SYSNAME "gemdos" -#define SMALL 1 -#endif -#ifdef MSDOS -#define SYSNAME "msdos" -#define SMALL 1 -#endif -#ifdef UNIX -#define SYSNAME "unix" -#endif - -#include -#include -#include -#include -#include -#include -#include - -#ifdef GEMDOS -#include -#define Error(n) { Bconin(2); exit(n); } -#else -#define Error(n) exit(n) -#endif -#ifdef UNIX -#define WRITE "w" -#else -#define WRITE "wb" /* for both MSDOS and GEMDOS! */ -#endif - -#define loop while (1) - -#define NCHARS 256 -#define LINELEN 256 -#define FILELEN 64 -#define NORMLEN 60 /* allows for 80 encoded chars per line */ - -#define SEQMAX 'z' -#define SEQMIN 'a' -char seqc; -int first, secnd, check, numl; - -FILE *in, *out; -char *pos; -char ifname[FILELEN], ofname[FILELEN]; -char *source = NULL, *target = NULL; -char blank, part = '\0'; -int partn, lens; -int debug = 0, nochk = 0, onedone = 0; -int chtbl[NCHARS], cdlen[NORMLEN + 3]; - -int main(int argc, char **argv); -char *getnword(char *str, int n); -void gettable(void); -void decode(void); -void getfile(char *buf); -void format(char *fp, ...); -void doprnt(char *fp, char *ap); -void puti(unsigned int i, unsigned int r); -void outc(int c); - -int main(argc, argv) int argc; char *argv[]; -{ - int mode; - register int i, j; - char *curarg; - char dest[FILELEN], buf[LINELEN]; - - while ((curarg = argv[1]) != NULL && curarg[0] == '-') { - if (((curarg[1] == 'd') || (curarg[1] == 'D')) && - (curarg[2] == '\0')) { - debug = 1; - } else if (((curarg[1] == 'n') || (curarg[1] == 'N')) && - (curarg[2] == '\0')) { - nochk = 1; - } else if (((curarg[1] == 't') || (curarg[1] == 'T')) && - (curarg[2] == '\0')) { - argv++; - argc--; - if (argc < 2) { - format("uud: Missing target directory.\n"); - Error(15); - } - target = argv[1]; - if (debug) - format("Target dir = %s\n",target); - } else if (((curarg[1] == 's') || (curarg[1] == 'S')) && - (curarg[2] == '\0')) { - argv++; - argc--; - if (argc < 2) { - format("uud: Missing source directory.\n"); - Error(15); - } - source = argv[1]; - if (debug) - format("Source dir = %s\n",source); - } else if (curarg[1] != '\0') { - format("Usage: uud [-n] [-d] [-s dir] [-t dir] [input-file]\n"); - Error(1); - } else - break; - argv++; - argc--; - } - - if (curarg == NULL || ((curarg[0] == '-') && (curarg[1] == '\0'))) { - in = stdin; - strcpy(ifname, ""); - } else { - if (source != NULL) { - strcpy(ifname, source); - strcat(ifname, curarg); - } else - strcpy(ifname, curarg); - if ((in = fopen(ifname, "r")) == NULL) { - format("uud: Can't open %s\n", ifname); - Error(2); - } - numl = 0; - } - -/* - * Set up the default translation table. - */ - for (i = 0; i < ' '; i++) chtbl[i] = -1; - for (i = ' ', j = 0; i < ' ' + 64; i++, j++) chtbl[i] = j; - for (i = ' ' + 64; i < NCHARS; i++) chtbl[i] = -1; - chtbl['`'] = chtbl[' ']; /* common mutation */ - chtbl['~'] = chtbl['^']; /* an other common mutation */ - blank = ' '; -/* - * set up the line length table, to avoid computing lotsa * and / ... - */ - cdlen[0] = 1; - for (i = 1, j = 5; i <= NORMLEN; i += 3, j += 4) - cdlen[i] = (cdlen[i + 1] = (cdlen[i + 2] = j)); -/* - * search for header or translation table line. - */ - loop { /* master loop for multiple decodes in one file */ - partn = 'a'; - loop { - if (fgets(buf, sizeof buf, in) == NULL) { - if (onedone) { - if (debug) format("End of file.\n"); - exit(0); - } else { - format("uud: No begin line.\n"); - Error(3); - } - } - numl++; - if (strncmp(buf, "table", (size_t)5) == 0) { - gettable(); - continue; - } - if (strncmp(buf, "begin", (size_t)5) == 0) { - break; - } - } - lens = strlen(buf); - if (lens) buf[--lens] = '\0'; -#ifdef SMALL - if ((pos = getnword(buf, 3))) { - strcpy(dest, pos); - } else -#else - if(sscanf(buf,"begin%o%s", &mode, dest) != 2) -#endif - { - format("uud: Missing filename in begin line.\n"); - Error(10); - } - - if (target != NULL) { - strcpy(ofname, target); - strcat(ofname, dest); - } else - strcpy(ofname, dest); - - if((out = fopen(ofname, WRITE)) == NULL) { - format("uud: Cannot open output file: %s\n", ofname); - Error(4); - } - if (debug) format("Begin uudecoding: %s\n", ofname); - seqc = SEQMAX; - check = nochk ? 0 : 1; - first = 1; - secnd = 0; - decode(); - fclose(out); -#ifdef UNIX - chmod(ofname, mode); -#endif - onedone = 1; - if (debug) format("End uudecoding: %s\n", ofname); - } /* master loop for multiple decodes in one file */ -} - -/* - * Bring back a pointer to the start of the nth word. - */ -char *getnword(str, n) register char *str; register int n; -{ - while((*str == '\t') || (*str == ' ')) str++; - if (! *str) return NULL; - while(--n) { - while ((*str != '\t') && (*str != ' ') && (*str)) str++; - if (! *str) return NULL; - while((*str == '\t') || (*str == ' ')) str++; - if (! *str) return NULL; - } - return str; -} - -/* - * Install the table in memory for later use. - */ -void gettable() -{ - char buf[LINELEN]; - register int c, n = 0; - register char *cpt; - - for (c = 0; c < NCHARS; c++) chtbl[c] = -1; - -again: if (fgets(buf, sizeof buf, in) == NULL) { - format("uud: EOF while in translation table.\n"); - Error(5); - } - numl++; - if (strncmp(buf, "begin", (size_t)5) == 0) { - format("uud: Incomplete translation table.\n"); - Error(6); - } - cpt = buf + strlen(buf) - 1; - *cpt = ' '; - while (*(cpt) == ' ') { - *cpt = 0; - cpt--; - } - cpt = buf; - while ((c = *cpt)) { - if (chtbl[c] != -1) { - format("uud: Duplicate char in translation table.\n"); - Error(7); - } - if (n == 0) blank = c; - chtbl[c] = n++; - if (n >= 64) return; - cpt++; - } - goto again; -} - -/* - * copy from in to out, decoding as you go along. - */ - -void decode() -{ - char buf[LINELEN], outl[LINELEN]; - register char *bp, *ut; - register int *trtbl = chtbl; - register int n, c, rlen; - register unsigned int len; - - loop { - if (fgets(buf, sizeof buf, in) == NULL) { - format("uud: EOF before end.\n"); - fclose(out); - Error(8); - } - numl++; - len = strlen(buf); - if (len) buf[--len] = '\0'; -/* - * Is it an unprotected empty line before the end line ? - */ - if (len == 0) continue; -/* - * Get the binary line length. - */ - n = trtbl[(unsigned char)*buf]; - if (n >= 0) goto decod; -/* - * end of uuencoded file ? - */ - if (strncmp(buf, "end", (size_t)3) == 0) return; -/* - * end of current file ? : get next one. - */ - if (strncmp(buf, "include", (size_t)7) == 0) { - getfile(buf); - continue; - } - format("uud: Bad prefix line %d in file: %s\n",numl, ifname); - if (debug) format("Bad line =%s\n",buf); - Error(11); -/* - * Sequence checking ? - */ -decod: rlen = cdlen[n]; -/* - * Is it the empty line before the end line ? - */ - if (n == 0) continue; -/* - * Pad with blanks. - */ - for (bp = &buf[c = len]; - c < rlen; c++, bp++) *bp = blank; -/* - * Verify if asked for. - */ - if (debug) { - for (len = 0, bp = buf; len < rlen; len++) { - if (trtbl[(unsigned char)*bp] < 0) { - format( - "Non uuencoded char <%c>, line %d in file: %s\n", *bp, numl, ifname); - format("Bad line =%s\n",buf); - Error(16); - } - bp++; - } - } -/* - * All this just to check for uuencodes that append a 'z' to each line.... - */ - if (secnd && check) { - secnd = 0; - if (buf[rlen] == SEQMAX) { - check = 0; - if (debug) format("Sequence check turned off (2).\n"); - } else - if (debug) format("Sequence check on (2).\n"); - } else if (first && check) { - first = 0; - secnd = 1; - if (buf[rlen] != SEQMAX) { - check = 0; - if (debug) format("No sequence check (1).\n"); - } else - if (debug) format("Sequence check on (1).\n"); - } -/* - * There we check. - */ - if (check) { - if (buf[rlen] != seqc) { - format("uud: Wrong sequence line %d in %s\n", - numl, ifname); - if (debug) - format( - "Sequence char is <%c> instead of <%c>.\n", buf[rlen], seqc); - Error(18); - } - seqc--; - if (seqc < SEQMIN) seqc = SEQMAX; - } -/* - * 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. - */ - ut = outl; - len = n; - bp = &buf[1]; - while (n > 0) { - *(ut++) = trtbl[(unsigned char)*bp] << 2 | trtbl[(unsigned char)bp[1]] >> 4; - n--; - if (n) { - *(ut++) = (trtbl[(unsigned char)bp[1]] << 4) | - (trtbl[(unsigned char)bp[2]] >> 2); - n--; - } - if (n) { - *(ut++) = trtbl[(unsigned char)bp[2]] << 6 | trtbl[(unsigned char)bp[3]]; - n--; - } - bp += 4; - } - if ((n = fwrite(outl, (size_t)1, (size_t)len, out)) <= 0) { - format("uud: Error on writing decoded file.\n"); - Error(18); - } - } -} - -/* - * Find the next needed file, if existing, otherwise try further - * on next file. - */ -void getfile(buf) register char *buf; -{ - if ((pos = getnword(buf, 2)) == NULL) { - format("uud: Missing include file name.\n"); - Error(17); - } else - if (source != NULL) { - strcpy(ifname, source); - strcat(ifname, pos); - } else - strcpy(ifname, pos); -#ifdef GEMDOS - if (Fattrib(ifname, 0, 0) < 0) -#else - if (access(ifname, 04)) -#endif - { - if (debug) { - format("Cant find: %s\n", ifname); - format("Continuing to read same file.\n"); - } - } - else { - if (freopen(ifname, "r", in) == in) { - numl = 0; - if (debug) - format("Reading next section from: %s\n", ifname); - } else { - format("uud: Freopen abort: %s\n", ifname); - Error(9); - } - } - loop { - if (fgets(buf, LINELEN, in) == NULL) { - format("uud: No begin line after include: %s\n", ifname); - Error(12); - } - numl++; - if (strncmp(buf, "table", (size_t)5) == 0) { - gettable(); - continue; - } - if (strncmp(buf, "begin", (size_t)5) == 0) break; - } - lens = strlen(buf); - if (lens) buf[--lens] = '\0'; -/* - * Check the part suffix. - */ - if ((pos = getnword(buf, 3)) == NULL ) { - format("uud: Missing part name, in included file: %s\n", ifname); - Error(13); - } else { - part = *pos; - partn++; - if (partn > 'z') partn = 'a'; - if (part != partn) { - format("uud: Part suffix mismatch: <%c> instead of <%c>.\n", - part, partn); - Error(14); - } - if (debug) format("Reading part %c\n", *pos); - } -} - -/* - * Printf style formatting. (Borrowed from MicroEmacs by Dave Conroy.) - * A lot smaller than the full fledged printf. - */ -#ifdef __STDC__ -void format(char *fp, ...) -{ - va_list args; - - va_start (args, fp); - doprnt(fp, (char *)&args); - va_end(args); -} -#else -/* VARARGS1 */ -void format(fp, args) char *fp; -{ - doprnt(fp, (char *)&args); -} -#endif - -void doprnt(fp, ap) -register char *fp; -register char *ap; -{ - register int c, k; - register char *s; - - while ((c = *fp++) != '\0') { - if (c != '%') - outc(c); - else { - c = *fp++; - switch (c) { - case 'd': - puti(*(int *)ap, 10); - ap += sizeof(int); - break; - - case 's': - s = *(char **)ap; - while ((k = *s++) != '\0') - outc(k); - ap += sizeof(char *); - break; - - case 'c': - outc(*(int *)ap); - ap += sizeof(int); - break; - - default: - outc(c); - } - } - } -} - -/* - * Put integer, in radix "r". - */ -void puti(i, r) -register unsigned int i; -register unsigned int r; -{ - register unsigned int q, s; - - if ((q = i / r) != 0) - puti(q, r); - s = i % r; - if (s <= 9) - outc(s + '0'); - else - outc(s - 10 + 'A'); -} -void outc(c) register char c; -{ -#ifdef GEMDOS - if (c == '\n') Bconout(2, '\r'); - Bconout(2, c); -#else - putchar(c); -#endif -} diff --git a/minix/commands/uue/Makefile b/minix/commands/uue/Makefile deleted file mode 100644 index 0a08f937c..000000000 --- a/minix/commands/uue/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -PROG= uue -MAN= - -LINKS+= ${BINDIR}/uue ${BINDIR}/uuencode - -.include diff --git a/minix/commands/uue/uue.c b/minix/commands/uue/uue.c deleted file mode 100644 index e98a8dc1d..000000000 --- a/minix/commands/uue/uue.c +++ /dev/null @@ -1,217 +0,0 @@ -/* uue - bulletproof version of uuencode */ - -/* Uue -- encode a file so that it's printable ascii, short lines - * - * Slightly modified from a version posted to net.sources a while back, - * and suitable for compilation on the IBM PC - * - * modified for Lattice C on the ST - 11.05.85 by MSD - * modified for ALCYON on the ST - 10-24-86 by RDR - * modified a little more for MWC... 02/09/87 by JPHD - * (An optional first argument of the form: -nnumber (e.g. -500), will - * produce a serie of files that long, linked by the include statement, - * such files are automatically uudecoded by the companion program.) - * More mods, - ... 05/06/87 by jphd - * Mods for TOPS 20, and more. 08/06/87 by jphd - * (remove freopen and rindex...change filename generation...) - * (A lot more to do about I/O speed, avoiding completely the stdio.h...) - * May be called as uuencode. Oct 2 1993 by Kees J. Bot - * - */ - - -#include -#include -#include -#include - -#define USAGE -#define FILE_NAME 10 /* affects how long names are truncated */ - -/* ENC is the basic 1 character encoding function to make a char printing */ -#define ENC(c) (((c) & 077) + ' ') - -FILE *fp, *outp; -char ofname[80]; -int lenofname; -int stdo = 0; - -#ifdef ST -#define READ "rb" -#else -#define READ "r" -#endif - -int part = 'a', chap = 'a'; -#define SEQMAX 'z' -#define SEQMIN 'a' -char seqc = SEQMAX; - -int split = 0; -int fileln = 32000; - -int main(int argc, char **argv); -void maketable(void); -void makename(void); -void encode(void); -void outdec(char *p); -int fr(char *buf, int cnt); - -int main(argc, argv) -int argc; -char *argv[]; -{ - char *prog_name; - char *fname; - int filter; - - prog_name = argv[0] + strlen(argv[0]); - while (prog_name > argv[0] && prog_name[-1] != '/') prog_name--; - filter = strcmp(prog_name, "uuencode") == 0; - - if (argc < 2) { - fprintf(stderr, "Usage: %s [-n] inputfile [-]\n", prog_name); - exit(2); - } - if (argv[1][0] == '-') { - fileln = -atoi(argv[1]); - if (fileln <= 0) { - fprintf(stderr, "Wrong file length arg.\n"); - exit(3); - } - split = 1; - argv++; - argc--; - } - if (filter) { /* old uuencode reads from standard input */ - fp = stdin; - } else { - if ((fp = fopen(argv[1], READ)) == NULL) { /* binary input !!! */ - fprintf(stderr, "Cannot open %s\n", argv[1]); - exit(1); - } - } - fname = argv[1] + strlen(argv[1]); - while (fname > argv[1] && fname[-1] != '/') fname--; - strcpy(ofname, fname); - fname = ofname; - do { - if (*fname == '.') *fname = '\0'; - } while (*fname++); - /* 10 char prefix + .uue -> 14 chars MAX */ - lenofname = strlen(ofname); - if (lenofname > FILE_NAME) ofname[FILE_NAME] = '\0'; - strcat(ofname, ".uue"); - lenofname = strlen(ofname); - if (!split && (filter || ((argc > 2) && (argv[2][0] == '-')))) { - stdo = 1; - outp = stdout; - } else { - makename(); - if ((outp = fopen(ofname, "w")) == NULL) { - fprintf(stderr, "Cannot open %s\n", ofname); - exit(1); - } - } - maketable(); - fprintf(outp, "begin %o %s\n", 0644, argv[1]); - encode(); - fprintf(outp, "end\n"); - fclose(outp); - return(0); -} - -/* Create ASCII table so a mailer can screw it up and the decode - * program can restore the error. - */ -void maketable() -{ - register int i, j; - - fputs("table\n", outp); - for (i = ' ', j = 0; i < '`'; j++) { - if (j == 32) putc('\n', outp); - fputc(i++, outp); - } - putc('\n', outp); -} - -/* Generate the names needed for single and multiple part encoding. */ -void makename() -{ - if (split) { - ofname[lenofname - 1] = part; - ofname[lenofname - 2] = chap; - } -} - -/* Copy from in to out, encoding as you go along. */ -void encode() -{ - char buf[80]; - register int i, n; - register int lines; - lines = 6; - - for (;;) { - n = fr(buf, 45); - putc(ENC(n), outp); - for (i = 0; i < n; i += 3) outdec(&buf[i]); - putc(seqc, outp); - seqc--; - if (seqc < SEQMIN) seqc = SEQMAX; - putc('\n', outp); - ++lines; - if (split && (lines > fileln)) { - part++; - if (part > 'z') { - part = 'a'; - if (chap == 'z') - chap = 'a'; /* loop ... */ - else - chap++; - } - makename(); - fprintf(outp, "include %s\n", ofname); - fclose(outp); - if ((outp = fopen(ofname, "w")) == NULL) { - fprintf(stderr, "Cannot open %s\n", ofname); - exit(1); - } - maketable(); - fprintf(outp, "begin part %c %s\n", part, ofname); - lines = 6; - } - if (n <= 0) break; - } -} - -/* Output one group of 3 bytes, pointed at by p, on file f. */ -void outdec(p) -register char *p; -{ - register 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), outp); - putc(ENC(c2), outp); - putc(ENC(c3), outp); - putc(ENC(c4), outp); -} - -/* Fr: like read but stdio */ -int fr(buf, cnt) -register char *buf; -register int cnt; -{ - register int c, i; - for (i = 0; i < cnt; i++) { - c = fgetc(fp); - if (feof(fp)) return(i); - buf[i] = c; - } - return(cnt); -} diff --git a/minix/man/man1/Makefile b/minix/man/man1/Makefile index d2fb8f240..4a4d52dbc 100644 --- a/minix/man/man1/Makefile +++ b/minix/man/man1/Makefile @@ -18,7 +18,7 @@ MAN= at.1 \ synctree.1 sysenv.1 sz.1 telnet.1 template.1 \ term.1 termcap.1 tget.1 time.1 \ truncate.1 umount.1 \ - uud.1 uue.1 vol.1 \ + vol.1 \ yap.1 linkfarm.1 pkg_view.1 MLINKS += compress.1 uncompress.1 diff --git a/minix/man/man1/uud.1 b/minix/man/man1/uud.1 deleted file mode 100644 index e74b30bf7..000000000 --- a/minix/man/man1/uud.1 +++ /dev/null @@ -1,43 +0,0 @@ -.TH UUD 1 -.SH NAME -uud, uudecode \- decode a binary file encoded with uue -.SH SYNOPSIS -\fBuud\fR [\fB\-n\fR]\fR [\fB\-s \fIsrcdir\fR] [\fB\-t \fIdstdir/\fR] \fIfile\fR -.br -.de FL -.TP -\\fB\\$1\\fR -\\$2 -.. -.de EX -.TP 20 -\\fB\\$1\\fR -# \\$2 -.. -.SH OPTIONS -.TP 5 -.B \-n -# Do not verify checksums -.TP 5 -.B \-s -# Name of directory where \fI.uue\fR file is -.TP 5 -.B \-t -# Name of directory where output goes -.SH EXAMPLES -.TP 20 -.B uud file.uue -# Re-create the original file -.TP 20 -.B uud \- x -# Encode \fIfile\fR and write on \fIstdout\fR -.TP 20 -.B uue \-800 file -# Output on \fIfile.uaa\fR, \fIfile.uab\fR etc. -.SH DESCRIPTION -.PP -\fIUuencode\fR is a famous program that converts an arbitrary (usually binary) -file to an encoding using only 64 ASCII characters. -\fIUudecode\fR converts it back to the original file. -The \fIuue\fR and \fIuud\fR programs are the -\s-1MINIX 3\s-1 -versions of these programs, and are compatible with the \s-2UNIX\s0 ones. -The files produced can even be sent successfully over BITNET, which is -notorious for mangling files. -It is possible to have \fIuue\fR automatically split the encoded file up -into small chunks. -The output files then get the suffixes \fI.uaa\fR, \fI.uab\fR, etc., instead -of \fI.uue\fR. -When \fIuud\fR is given \fIfile.uaa\fR to decode, it automatically includes -the subsequent pieces. -The encoding takes 3 bytes (24 bits) from the input file and renders it -as 4 bytes in the output file. -.SH "SEE ALSO" -.BR btoa (1), -.BR uud (1). diff --git a/minix/tests/testsh1.sh b/minix/tests/testsh1.sh index c094d8434..4a2c88cc2 100755 --- a/minix/tests/testsh1.sh +++ b/minix/tests/testsh1.sh @@ -282,20 +282,20 @@ END tsort y if cmp -s y answer; then : ; else bomb "Error on tsort test 1"; fi -#Test uue/uud +#Test uuencode/uudecode cp $f x -uue x -if test -s x.uue; then : ; else bomb "Error on uue/uud test 1"; fi +uuencode x x > x.uue +if test -s x.uue; then : ; else bomb "Error on uuencode/uudecode test 1"; fi rm x -uud x.uue -if cmp -s x $f; then : ; else bomb "Error on uue/uud test 2"; fi +uudecode x.uue +if cmp -s x $f; then : ; else bomb "Error on uuencode/uudecode test 2"; fi compress -fc x >x.Z 2>/dev/null -uue x.Z +uuencode x.Z x.Z > x.Z.uue rm x x.Z -uud x.uue +uudecode x.Z.uue compress -cd x.Z >x -if cmp -s x $f; then : ; else bomb "Error on uue/uud test 3"; fi +if cmp -s x $f; then : ; else bomb "Error on uuencode/uudecode test 3"; fi cd .. rm -rf $TESTDIR diff --git a/usr.bin/Makefile b/usr.bin/Makefile index 910735f8f..792ba7e78 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -28,7 +28,7 @@ SUBDIR= asa \ tail tee tic touch tput \ tr true tsort tty ul uname unexpand unifdef \ uniq units unvis unzip users \ - uuidgen vis \ + uudecode uuencode uuidgen vis \ w \ wall wc what whereis who whois \ write xargs xinstall xstr yes diff --git a/usr.bin/uudecode/Makefile b/usr.bin/uudecode/Makefile new file mode 100644 index 000000000..0df4b4f6b --- /dev/null +++ b/usr.bin/uudecode/Makefile @@ -0,0 +1,8 @@ +# $NetBSD: Makefile,v 1.8 2003/05/18 07:57:37 lukem Exp $ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +NOMAN= # defined + +PROG= uudecode + +.include diff --git a/usr.bin/uudecode/uudecode.c b/usr.bin/uudecode/uudecode.c new file mode 100644 index 000000000..977ace222 --- /dev/null +++ b/usr.bin/uudecode/uudecode.c @@ -0,0 +1,323 @@ +/* $NetBSD: uudecode.c,v 1.28 2013/01/28 19:50:30 apb Exp $ */ + +/*- + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +#if !defined(lint) +__COPYRIGHT("@(#) Copyright (c) 1983, 1993\ + The Regents of the University of California. All rights reserved."); +#if 0 +static char sccsid[] = "@(#)uudecode.c 8.2 (Berkeley) 4/2/94"; +#endif +__RCSID("$NetBSD: uudecode.c,v 1.28 2013/01/28 19:50:30 apb Exp $"); +#endif /* not lint */ + +/* + * uudecode [file ...] + * + * create the specified file, decoding as you go. + * used with uuencode. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef NO_BASE64 +#include +#include +#endif + +static int decode(char *); +__dead static void usage(void); +static int checkend(const char *, const char *, const char *); +static int base64_decode(void); + +static int base64; +static const char *inputname; + +int +main(int argc, char *argv[]) +{ + int ch, rval; + char *outputname = NULL; + + setlocale(LC_ALL, ""); + setprogname(argv[0]); + + while ((ch = getopt(argc, argv, "mo:p")) != -1) + switch (ch) { + case 'm': + base64 = 1; + break; + case 'o': + outputname = optarg; + break; + case 'p': + outputname = __UNCONST("/dev/stdout"); + break; + default: + usage(); + } + argc -= optind; + argv += optind; + + if (*argv) { + rval = 0; + do { + if (!freopen(inputname = *argv, "r", stdin)) { + warn("%s", *argv); + rval = 1; + continue; + } + rval |= decode(outputname); + } while (*++argv); + } else { + inputname = "stdin"; + rval = decode(outputname); + } + exit(rval); +} + +/* + * Decode one file from stdin. If outputname is not NULL + * then it overrides the file name embedded in the input data. + */ +static int +decode(char *outputname) +{ + struct passwd *pw; + int n; + char ch, *p; + int n1; + long mode; + char *fn; + char buf[MAXPATHLEN]; + + /* search for header line */ + for (;;) { + if (!fgets(buf, sizeof(buf), stdin)) { + warnx("%s: no \"%s\" line", inputname, base64 ? + "begin-base64" : "begin"); + return(1); + } + p = buf; + if (strncmp(p, "begin-base64", 12) == 0) { + base64 = 1; + p += 13; + break; + } else if (strncmp(p, "begin", 5) == 0) { + p += 6; + break; + } else + continue; + } + + /* must be followed by an octal mode and a space */ + mode = strtol(p, &fn, 8); + if (fn == (p) || !isspace((unsigned char)*fn) || mode==LONG_MIN || mode==LONG_MAX) + { + warnx("%s: invalid mode on \"%s\" line", inputname, + base64 ? "begin-base64" : "begin"); + return(1); + } + /* skip whitespace for file name */ + while (*fn && isspace((unsigned char)*fn)) fn++; + if (*fn == 0) { + warnx("%s: no filename on \"%s\" line", inputname, + base64 ? "begin-base64" : "begin"); + return(1); + } + /* zap newline */ + for (p = fn; *p && *p != '\n'; p++) + ; + if (*p) *p = 0; + + /* outputname overrides fn */ + if (outputname) + fn = outputname; + + /* handle ~user/file format */ + if (*fn == '~') { + if (!(p = strchr(fn, '/'))) { + warnx("%s: illegal ~user.", inputname); + return(1); + } + *p++ = '\0'; + if (!(pw = getpwnam(fn + 1))) { + warnx("%s: no user %s.", inputname, buf); + return(1); + } + n = strlen(pw->pw_dir); + n1 = strlen(p); + if (n + n1 + 2 > MAXPATHLEN) { + warnx("%s: path too long.", inputname); + return(1); + } + /* make space at beginning of buf by moving end of pathname */ + memmove(buf + n + 1, p, n1 + 1); + memmove(buf, pw->pw_dir, n); + buf[n] = '/'; + fn = buf; + } + + if (strcmp(fn, "/dev/stdout") == 0 || strcmp(fn, "-") == 0) { + /* + * POSIX.1-2008 says that both "-" and "/dev/stdout" + * refer to standard output when they appear in the file + * header, but only "/dev/stdout" refers to standard + * output when it appears as the argument to the "-o" + * command line option. + * + * We handle both special names, regardless of whether + * they came from the "-o" option or from the header of + * the input stream. + */ + } else { + /* + * Create output file, and set its mode. POSIX.1-2008 + * requires the mode to be used exactly, ignoring the + * umask and anything else, but we mask it with 0666. + */ + if (freopen(fn, "w", stdout) == NULL || + fchmod(fileno(stdout), mode & 0666) != 0) { + warn("%s: %s", fn, inputname); + return(1); + } + } + + if (base64) + return base64_decode(); + else { + /* for each input line */ + for (;;) { + if (!fgets(p = buf, sizeof(buf), stdin)) { + warnx("%s: short file.", inputname); + return(1); + } +#define DEC(c) (((c) - ' ') & 077) /* single character decode */ + /* + * `n' is used to avoid writing out all the characters + * at the end of the file. + */ + if ((n = DEC(*p)) <= 0) + break; + for (++p; n > 0; p += 4, n -= 3) + if (n >= 3) { + ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; + putchar(ch); + ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; + putchar(ch); + ch = DEC(p[2]) << 6 | DEC(p[3]); + putchar(ch); + } + else { + if (n >= 1) { + ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; + putchar(ch); + } + if (n >= 2) { + ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; + putchar(ch); + } + if (n >= 3) { + ch = DEC(p[2]) << 6 | DEC(p[3]); + putchar(ch); + } + } + } + if (!fgets(buf, sizeof(buf), stdin) || strcmp(buf, "end\n")) { + warnx("%s: no \"end\" line.", inputname); + return(1); + } + return(0); + } +} + +static int +checkend(const char *ptr, const char *end, const char *msg) +{ + size_t n; + + n = strlen(end); + if (strncmp(ptr, end, n) != 0 || + strspn(ptr + n, "\t\r\n") != strlen(ptr + n)) { + warnx("%s", msg); + return (1); + } + return (0); +} + +static int +base64_decode(void) +{ + int n; + char inbuf[MAXPATHLEN]; + unsigned char outbuf[MAXPATHLEN * 4]; + + for (;;) { + if (!fgets(inbuf, sizeof(inbuf), stdin)) { + warnx("%s: short file.", inputname); + return (1); + } +#ifdef NO_BASE64 + warnx("%s: base64 decoding is not supported", inputname); + return (1); +#else + n = b64_pton(inbuf, outbuf, sizeof(outbuf)); +#endif + if (n < 0) + break; + fwrite(outbuf, 1, n, stdout); + } + return (checkend(inbuf, "====", + "error decoding base64 input stream")); +} + +static void +usage(void) +{ + (void)fprintf(stderr, + "usage: %s [-m] [-p | -o outfile] [encoded-file ...]\n", + getprogname()); + exit(1); +} diff --git a/usr.bin/uuencode/Makefile b/usr.bin/uuencode/Makefile new file mode 100644 index 000000000..ddceae4a1 --- /dev/null +++ b/usr.bin/uuencode/Makefile @@ -0,0 +1,8 @@ +# $NetBSD: Makefile,v 1.5 1995/12/05 03:02:31 jtc Exp $ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= uuencode +MAN= uuencode.1 uuencode.5 +MLINKS= uuencode.1 uudecode.1 + +.include diff --git a/usr.bin/uuencode/uuencode.1 b/usr.bin/uuencode/uuencode.1 new file mode 100644 index 000000000..2ce995f3b --- /dev/null +++ b/usr.bin/uuencode/uuencode.1 @@ -0,0 +1,175 @@ +.\" $NetBSD: uuencode.1,v 1.26 2014/09/06 21:21:36 wiz Exp $ +.\" +.\" Copyright (c) 1980, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)uuencode.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd September 6, 2014 +.Dt UUENCODE 1 +.Os +.Sh NAME +.Nm uuencode , +.Nm uudecode +.Nd encode/decode a binary file +.Sh SYNOPSIS +.Nm +.Op Fl m +.Op Ar inputfile +.Ar headername +.Nm uudecode +.Op Fl m +.Op Fl p | Fl o Ar outputfile +.Op Ar encoded-file ... +.Sh DESCRIPTION +.Nm +and +.Nm uudecode +are used to transmit binary files over transmission mediums +that do not support other than simple +.Tn ASCII +data. +.Pp +The following options are available: +.Bl -tag -width ".Fl m" +.It Fl m +Use base64 encoding. +For +.Nm , +the historical uuencode algorithm is the default. +For +.Nm uudecode , +by default the encoding is automatically detected. +.It Fl o Ar outputfile +.Po Nm uudecode No only . Pc +Send the decoded output data to +.Ar outputfile . +By default, +.Nm uudecode +uses the +.Ar headername +recorded in the header of the encoded data stream. +.It Fl p +.Po Nm uudecode No only . Pc +Write the decoded file to standard output instead of to a file. +.El +.Pp +.Nm +reads +.Ar inputfile +(or by default the standard input) and writes an encoded version +to (always) the standard output. +The encoding uses only printing +.Tn ASCII +characters suitable for text-only transport media. +The string +.Ar headername +is inserted into the output header as the +.Ar outputfile +to use at +.Nm uudecode +time. +The header also includes the mode (permissions) of the file. +.Pp +.Nm uudecode +transforms +.Em uuencoded +files (or by default, the standard input) into the original form. +The resulting file is named +.Ar headername +as recorded in the encoded file, +or as specified by the +.Fl o +option, +and will have the mode of the original file except that setuid +and execute bits are not retained. +If the +.Fl p +option is specified, or if the output file name is given as +.Pa /dev/stdout , +then the data will be written to the standard output +instead of to a named file. +.Nm uudecode +ignores any leading and trailing lines. +.Pp +The encoded form of the file is expanded by 35%. +Every 3 bytes become 4 plus control information. +.Sh EXIT STATUS +The +.Nm uudecode +and +.Nm +utilities exits 0 on success, and \*[Gt]0 if an error occurs. +.Sh EXAMPLES +The following example packages up a source tree, compresses it, +uuencodes it and mails it to a user on another system. +.Pp +.Bd -literal -offset indent -compact +tar czf \- src_tree \&| uuencode src_tree.tgz \&| mail user@example.com +.Ed +.Pp +On the other system, if the user saves the mail to the file +.Pa temp , +the following example creates the file +.Pa src_tree.tgz +and extracts it to make a copy of the original tree. +.Pp +.Bd -literal -offset indent -compact +uudecode temp +tar xzf src_tree.tgz +.Ed +.Sh SEE ALSO +.Xr gzip 1 , +.Xr mail 1 , +.Xr tar 1 , +.\".Xr uucp 1 , +.Xr uuencode 5 +.Sh STANDARDS +The +.Nm uudecode +and +.Nm +utilities conform to +.St -p1003.1-2008 . +.Sh HISTORY +The +.Nm uudecode +and +.Nm +utilities appeared in +.Bx 4.0 . +.Sh SECURITY CONSIDERATIONS +When using +.Nm uudecode +with files coming from dubious sources, +always either explicitly pass the +.Fl o +option or check the header (the first line) of the encoded file for +safety. +Blindly using a +.Ar headername +from a hostile source can overwrite important files. diff --git a/usr.bin/uuencode/uuencode.5 b/usr.bin/uuencode/uuencode.5 new file mode 100644 index 000000000..2eda6d9ed --- /dev/null +++ b/usr.bin/uuencode/uuencode.5 @@ -0,0 +1,146 @@ +.\" $NetBSD: uuencode.5,v 1.11 2008/08/25 09:36:24 wiz Exp $ +.\" +.\" Copyright (c) 1989, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)uuencode.format.5 8.2 (Berkeley) 1/12/94 +.\" +.Dd April 9, 1997 +.Dt UUENCODE 5 +.Os +.Sh NAME +.Nm uuencode +.Nd format of an encoded uuencode file +.Sh DESCRIPTION +Files output by +.Xr uuencode 1 +consist of a header line, +followed by a number of body lines, +and a trailer line. +The +.Xr uudecode 1 +command +will ignore any lines preceding the header or +following the trailer. +Lines preceding a header must not, of course, +look like a header. +.Pp +The header line starts with the word +.Dq begin , +a space, +a file mode (in octal), +a space, +and finally a string which names the file being encoded. +.Pp +The central engine of +.Xr uuencode 1 +is a six-bit encoding function which outputs an +.Tn ASCII +character. +The six bits to be encoded are treated as a small integer and added +with the +.Tn ASCII +value for the space character (octal 40). +The result is a printable +.Tn ASCII +character. +In the case where all six bits to be encoded are zero, +the +.Tn ASCII +backquote character \` (octal 140) is emitted instead of what +would normally be a space. +.Pp +The body of an encoded file consists of one or more lines, +each of which may be a maximum of 86 characters long (including the trailing +newline). +Each line represents an encoded chunk of data from the input file and begins +with a byte count, +followed by encoded bytes, +followed by a newline. +.Pp +The byte count is a six-bit integer encoded with the above function, +representing the number of bytes encoded in the rest of the line. +The method used to encode the data expands its size by +133% (described below). +Therefore it is important to note that the byte count describes the size of +the chunk of data before it is encoded, not afterwards. +The six bit size of this number effectively limits the number of bytes +that can be encoded in each line to a maximum of 63. +While +.Xr uuencode 1 +will not encode more than 45 bytes per line, +.Xr uudecode 1 +will tolerate the maximum line size. +.Pp +The remaining characters in the line represent the data of the input +file encoded as follows. +Input data are broken into groups of three eight-bit bytes, +which are then interpreted together as a 24-bit block. +The first bit of the block is the highest order bit of the first character, +and the last is the lowest order bit of the third character. +This block is then broken into four six-bit integers which are encoded one by +one starting from the first bit of the block. +The result is a four character +.Tn ASCII +string for every three bytes of input data. +.Pp +Encoded lines of data continue in this manner until the input file is +exhausted. +The end of the body is signaled by an encoded line with a byte count +of zero (the +.Tn ASCII +backquote character \`). +.Pp +Obviously, not every input file will be a multiple of three bytes in size. +In these cases, +.Xr uuencode 1 +will pad the remaining one or two bytes of data with garbage bytes until +a three byte group is created. +The byte count in a line containing +garbage padding will reflect the actual number of bytes encoded, making +it possible to convey how many bytes are garbage. +.Pp +The trailer line consists of +.Dq end +on a line by itself. +.Sh SEE ALSO +.Xr mail 1 , +.Xr uucp 1 , +.Xr uudecode 1 , +.Xr uuencode 1 , +.Xr ascii 7 +.Sh HISTORY +The +.Nm +file format appeared in +.Bx 4.0 . +.Sh BUGS +The interpretation of the +.Nm +format relies on properties of the +.Tn ASCII +character set and may not work correctly on non-ASCII systems. diff --git a/usr.bin/uuencode/uuencode.c b/usr.bin/uuencode/uuencode.c new file mode 100644 index 000000000..50b705134 --- /dev/null +++ b/usr.bin/uuencode/uuencode.c @@ -0,0 +1,202 @@ +/* $NetBSD: uuencode.c,v 1.16 2014/09/06 18:58:35 dholland Exp $ */ + +/*- + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef lint +__COPYRIGHT("@(#) Copyright (c) 1983, 1993\ + The Regents of the University of California. All rights reserved."); +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)uuencode.c 8.2 (Berkeley) 4/2/94"; +#else +__RCSID("$NetBSD: uuencode.c,v 1.16 2014/09/06 18:58:35 dholland Exp $"); +#endif +#endif /* not lint */ + +/* + * uuencode [input] output + * + * Encode a file so it can be mailed to a remote system. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void encode(void); +static void base64_encode(void); +__dead static void usage(void); + +int +main(int argc, char *argv[]) +{ + struct stat sb; + int base64, ch, mode; + + mode = 0; + base64 = 0; + setlocale(LC_ALL, ""); + setprogname(argv[0]); + + while ((ch = getopt(argc, argv, "m")) != -1) { + switch(ch) { + case 'm': + base64 = 1; + break; + default: + usage(); + } + } + argv += optind; + argc -= optind; + + switch(argc) { + case 2: /* optional first argument is input file */ + if (!freopen(*argv, "r", stdin) || fstat(fileno(stdin), &sb)) + err(1, "%s", *argv); +#define RWX (S_IRWXU|S_IRWXG|S_IRWXO) + mode = sb.st_mode & RWX; + ++argv; + break; + case 1: +#define RW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) + mode = RW & ~umask(RW); + break; + case 0: + default: + usage(); + } + + if (base64) { + (void)printf("begin-base64 %o %s\n", mode, *argv); + base64_encode(); + (void)printf("====\n"); + } else { + (void)printf("begin %o %s\n", mode, *argv); + encode(); + (void)printf("end\n"); + } + + if (ferror(stdout)) + err(1, "write error"); + exit(0); +} + +/* ENC is the basic 1 character encoding function to make a char printing */ +#define ENC(c) ((c) ? ((c) & 077) + ' ': '`') + +/* + * copy from in to out, encoding in base64 as you go along. + */ +static void +base64_encode(void) +{ + /* + * Output must fit into 80 columns, chunks come in 4, leave 1. + */ +#define GROUPS ((70 / 4) - 1) + unsigned char buf[3]; + char buf2[sizeof(buf) * 2 + 1]; + size_t n; + int rv, sequence; + + sequence = 0; + + while ((n = fread(buf, 1, sizeof(buf), stdin))) { + ++sequence; + rv = b64_ntop(buf, n, buf2, (sizeof(buf2) / sizeof(buf2[0]))); + if (rv == -1) + errx(1, "b64_ntop: error encoding base64"); + printf("%s%s", buf2, (sequence % GROUPS) ? "" : "\n"); + } + if (sequence % GROUPS) + printf("\n"); +} + +/* + * copy from in to out, encoding as you go along. + */ +static void +encode(void) +{ + int ch, n; + char *p; + char buf[80]; + + while ((n = fread(buf, 1, 45, stdin)) > 0) { + ch = ENC(n); + if (putchar(ch) == EOF) + break; + for (p = buf; n > 0; n -= 3, p += 3) { + ch = *p >> 2; + ch = ENC(ch); + if (putchar(ch) == EOF) + break; + ch = ((*p << 4) & 060) | ((p[1] >> 4) & 017); + ch = ENC(ch); + if (putchar(ch) == EOF) + break; + ch = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03); + ch = ENC(ch); + if (putchar(ch) == EOF) + break; + ch = p[2] & 077; + ch = ENC(ch); + if (putchar(ch) == EOF) + break; + } + if (putchar('\n') == EOF) + break; + } + if (ferror(stdin)) + err(1, "read error."); + ch = ENC('\0'); + (void)putchar(ch); + (void)putchar('\n'); +} + +static void +usage(void) +{ + (void)fprintf(stderr, + "usage: %s [-m] [inputfile] headername > encodedfile\n", + getprogname()); + exit(1); +}