Porting uuencode/uudecode from NetBSD

Lionel: I fixed small mistakes in the mi file, typos, missing keywords,
        and whitespace fixes.

Change-Id: If0c04b923af328838f2d0950e189bf28995bc0f0
This commit is contained in:
Sky Liu 2014-09-07 10:05:15 +08:00 committed by Lionel Sambuc
parent 31b808b8fa
commit 2fde3a4846
17 changed files with 884 additions and 904 deletions

View file

@ -543,9 +543,9 @@
./usr/bin/update minix-sys ./usr/bin/update minix-sys
./usr/bin/uptime minix-sys ./usr/bin/uptime minix-sys
./usr/bin/users 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/uudecode minix-sys
./usr/bin/uue minix-sys ./usr/bin/uue minix-sys obsolete
./usr/bin/uuencode minix-sys ./usr/bin/uuencode minix-sys
./usr/bin/uuidgen minix-sys ./usr/bin/uuidgen minix-sys
./usr/bin/version minix-sys ./usr/bin/version minix-sys
@ -2215,8 +2215,8 @@
./usr/Makefile minix-sys ./usr/Makefile minix-sys
./usr/man minix-sys ./usr/man minix-sys
./usr/man/man1 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
./usr/man/man1/..1 minix-sys obsolete
./usr/man/man1/addr2line.1 minix-sys binutils ./usr/man/man1/addr2line.1 minix-sys binutils
./usr/man/man1/apropos.1 minix-sys ./usr/man/man1/apropos.1 minix-sys
./usr/man/man1/ar.1 minix-sys binutils ./usr/man/man1/ar.1 minix-sys binutils
@ -2537,8 +2537,10 @@
./usr/man/man1/unzip.1 minix-sys ./usr/man/man1/unzip.1 minix-sys
./usr/man/man1/uptime.1 minix-sys ./usr/man/man1/uptime.1 minix-sys
./usr/man/man1/users.1 minix-sys ./usr/man/man1/users.1 minix-sys
./usr/man/man1/uud.1 minix-sys ./usr/man/man1/uud.1 minix-sys obsolete
./usr/man/man1/uue.1 minix-sys ./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/uuidgen.1 minix-sys
./usr/man/man1/vi.1 minix-sys ./usr/man/man1/vi.1 minix-sys
./usr/man/man1/view.1 minix-sys ./usr/man/man1/view.1 minix-sys
@ -5013,6 +5015,7 @@
./usr/man/man5/tzfile.5 minix-sys ./usr/man/man5/tzfile.5 minix-sys
./usr/man/man5/usermgmt.conf.5 minix-sys ./usr/man/man5/usermgmt.conf.5 minix-sys
./usr/man/man5/utmp.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 minix-sys
./usr/man/man6/adventure.6 minix-sys ./usr/man/man6/adventure.6 minix-sys
./usr/man/man6/arithmetic.6 minix-sys ./usr/man/man6/arithmetic.6 minix-sys
@ -5027,7 +5030,7 @@
./usr/man/man6/ppt.6 minix-sys ./usr/man/man6/ppt.6 minix-sys
./usr/man/man6/primes.6 minix-sys ./usr/man/man6/primes.6 minix-sys
./usr/man/man6/random.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/man6/wargames.6 minix-sys
./usr/man/man7 minix-sys ./usr/man/man7 minix-sys
./usr/man/man7/ascii.7 minix-sys ./usr/man/man7/ascii.7 minix-sys

View file

@ -28,7 +28,7 @@ SUBDIR= add_route arp at backup btrace \
syslogd tcpd tcpdp tcpstat telnet \ syslogd tcpd tcpdp tcpstat telnet \
telnetd term termcap tget time \ telnetd term termcap tget time \
truncate udpstat umount \ truncate udpstat umount \
update uud uue version vol \ update version vol \
writeisofs fetch \ writeisofs fetch \
zdump zmodem pkgin_cd pkgin_all pkgin_sets \ zdump zmodem pkgin_cd pkgin_all pkgin_sets \
worldstone updateboot update_bootcfg \ worldstone updateboot update_bootcfg \

View file

@ -1,6 +0,0 @@
PROG= uud
MAN=
LINKS+= ${BINDIR}/uud ${BINDIR}/uudecode
.include <bsd.prog.mk>

View file

@ -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 <sys/types.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
#ifdef GEMDOS
#include <osbind.h>
#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, "<stdin>");
} 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
}

View file

@ -1,6 +0,0 @@
PROG= uue
MAN=
LINKS+= ${BINDIR}/uue ${BINDIR}/uuencode
.include <bsd.prog.mk>

View file

@ -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 <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#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);
}

View file

@ -18,7 +18,7 @@ MAN= at.1 \
synctree.1 sysenv.1 sz.1 telnet.1 template.1 \ synctree.1 sysenv.1 sz.1 telnet.1 template.1 \
term.1 termcap.1 tget.1 time.1 \ term.1 termcap.1 tget.1 time.1 \
truncate.1 umount.1 \ truncate.1 umount.1 \
uud.1 uue.1 vol.1 \ vol.1 \
yap.1 linkfarm.1 pkg_view.1 yap.1 linkfarm.1 pkg_view.1
MLINKS += compress.1 uncompress.1 MLINKS += compress.1 uncompress.1

View file

@ -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 \- <file.uue
# The \- means use \fIstdin\fR
.SH DESCRIPTION
.PP
\fIUud\fR decodes a file encoded with \fIuue\fR or
\s-2UNIX\s+2
\fIuuencode\fR.
The decoded file is given the name that the original file had.
The name information is part of the encoded file.
Mail headers and other junk before the encoded file are skipped.
.SH "SEE ALSO"
.BR uue (1).

View file

@ -1,51 +0,0 @@
.TH UUE 1
.SH NAME
uue, uuencode \- encode a binary file to ASCII (e.g., for mailing)
.SH SYNOPSIS
\fBuue\fR [\fB\-\fIn\fR] \fIfile\fR [\fB\-\fR]\fR
.br
.de FL
.TP
\\fB\\$1\\fR
\\$2
..
.de EX
.TP 20
\\fB\\$1\\fR
# \\$2
..
.SH OPTIONS
.TP 5
.B \-\fIn\fR
# How many lines to put in each file
.SH EXAMPLES
.TP 20
.B uue file
# Encode \fIfile\fR to \fIfile.uue\fR
.TP 20
.B uue file \- >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).

View file

@ -282,20 +282,20 @@ END
tsort <x >y tsort <x >y
if cmp -s y answer; then : ; else bomb "Error on tsort test 1"; fi if cmp -s y answer; then : ; else bomb "Error on tsort test 1"; fi
#Test uue/uud #Test uuencode/uudecode
cp $f x cp $f x
uue x uuencode x x > x.uue
if test -s x.uue; then : ; else bomb "Error on uue/uud test 1"; fi if test -s x.uue; then : ; else bomb "Error on uuencode/uudecode test 1"; fi
rm x rm x
uud x.uue uudecode x.uue
if cmp -s x $f; then : ; else bomb "Error on uue/uud test 2"; fi if cmp -s x $f; then : ; else bomb "Error on uuencode/uudecode test 2"; fi
compress -fc x >x.Z 2>/dev/null compress -fc x >x.Z 2>/dev/null
uue x.Z uuencode x.Z x.Z > x.Z.uue
rm x x.Z rm x x.Z
uud x.uue uudecode x.Z.uue
compress -cd x.Z >x 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 .. cd ..
rm -rf $TESTDIR rm -rf $TESTDIR

View file

@ -28,7 +28,7 @@ SUBDIR= asa \
tail tee tic touch tput \ tail tee tic touch tput \
tr true tsort tty ul uname unexpand unifdef \ tr true tsort tty ul uname unexpand unifdef \
uniq units unvis unzip users \ uniq units unvis unzip users \
uuidgen vis \ uudecode uuencode uuidgen vis \
w \ w \
wall wc what whereis who whois \ wall wc what whereis who whois \
write xargs xinstall xstr yes write xargs xinstall xstr yes

View file

@ -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 <bsd.prog.mk>

323
usr.bin/uudecode/uudecode.c Normal file
View file

@ -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 <sys/cdefs.h>
#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 <sys/param.h>
#include <sys/stat.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <locale.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifndef NO_BASE64
#include <netinet/in.h>
#include <resolv.h>
#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);
}

View file

@ -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 <bsd.prog.mk>

175
usr.bin/uuencode/uuencode.1 Normal file
View file

@ -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.

146
usr.bin/uuencode/uuencode.5 Normal file
View file

@ -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.

202
usr.bin/uuencode/uuencode.c Normal file
View file

@ -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 <sys/cdefs.h>
#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 <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <err.h>
#include <errno.h>
#include <locale.h>
#include <resolv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
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);
}