diff options
author | jmallett <jmallett@FreeBSD.org> | 2002-03-05 03:27:47 +0000 |
---|---|---|
committer | jmallett <jmallett@FreeBSD.org> | 2002-03-05 03:27:47 +0000 |
commit | ce51fff754f20521ce32eaf888c654ec967b9781 (patch) | |
tree | 650de0ad3b3660ee3fa7b3cd64021350aebe479b | |
parent | 66d03d29ff7c7e5018ff773f7ce2a36c67ee067d (diff) | |
download | FreeBSD-src-ce51fff754f20521ce32eaf888c654ec967b9781.zip FreeBSD-src-ce51fff754f20521ce32eaf888c654ec967b9781.tar.gz |
Add base64 support to uuencode(1) and uudecode(1), as specified by SUSv3.
Add `-o' option to uuencode(1) to pipe the uuencoded output to an
arbitrary file, instead of just stdout.
Reviewed by: -standards, mike
Approved by: mike
-rw-r--r-- | usr.bin/uudecode/uudecode.c | 49 | ||||
-rw-r--r-- | usr.bin/uuencode/uuencode.1 | 21 | ||||
-rw-r--r-- | usr.bin/uuencode/uuencode.c | 98 |
3 files changed, 139 insertions, 29 deletions
diff --git a/usr.bin/uudecode/uudecode.c b/usr.bin/uudecode/uudecode.c index 3630427..b0cc073 100644 --- a/usr.bin/uudecode/uudecode.c +++ b/usr.bin/uudecode/uudecode.c @@ -52,11 +52,14 @@ static const char rcsid[] = * used with uuencode. */ #include <sys/param.h> +#include <sys/socket.h> #include <sys/stat.h> +#include <netinet/in.h> + #include <err.h> -#include <fnmatch.h> #include <pwd.h> +#include <resolv.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -69,6 +72,7 @@ int cflag, iflag, oflag, pflag, sflag; static void usage __P((void)); int decode __P((void)); int decode2 __P((int)); +void base64_decode __P((const char *)); int main(argc, argv) @@ -155,11 +159,11 @@ decode2(flag) struct passwd *pw; register int n; register char ch, *p; - int ignore, mode, n1; + int base64, ignore, mode, n1; char buf[MAXPATHLEN]; char buffn[MAXPATHLEN]; /* file name buffer */ - ignore = 0; + base64 = ignore = 0; /* search for header line */ do { if (!fgets(buf, sizeof(buf), stdin)) { @@ -169,17 +173,26 @@ decode2(flag) warnx("%s: no \"begin\" line", filename); return(1); } - } while (strncmp(buf, "begin ", 6) || - fnmatch("begin [0-7]* *", buf, 0)); + } while (strncmp(buf, "begin", 5) != 0); + + if (strncmp(buf, "begin-base64", 12) == 0) + base64 = 1; if (oflag) { - (void)sscanf(buf, "begin %o ", &mode); + if (base64) + (void)sscanf(buf, "begin-base64 %o ", &mode); + else + (void)sscanf(buf, "begin %o ", &mode); if (strlcpy(buf, outfile, sizeof(buf)) >= sizeof(buf)) { warnx("%s: filename too long", outfile); return (1); } - } else - (void)sscanf(buf, "begin %o %[^\n\r]", &mode, buf); + } else { + if (base64) + (void)sscanf(buf, "begin-base64 %o %[^\n\r]", &mode, buf); + else + (void)sscanf(buf, "begin %o %[^\n\r]", &mode, buf); + } if (!sflag && !pflag) { strncpy(buffn, buf, sizeof(buffn)); @@ -230,11 +243,18 @@ decode2(flag) strcpy(buffn, buf); /* store file name from header line */ /* for each input line */ +next: for (;;) { if (!fgets(p = buf, sizeof(buf), stdin)) { warnx("%s: short file", filename); return(1); } + if (base64) { + if (strncmp(buf, "====", 4) == 0) + return (0); + base64_decode(buf); + goto next; + } #define DEC(c) (((c) - ' ') & 077) /* single character decode */ #define IS_DEC(c) ( (((c) - ' ') >= 0) && (((c) - ' ') <= 077 + 1) ) /* #define IS_DEC(c) (1) */ @@ -304,6 +324,19 @@ if (!ignore) \ return(0); } +void +base64_decode(stream) + const char *stream; +{ + unsigned char out[MAXPATHLEN * 4]; + int rv; + + rv = b64_pton(stream, out, (sizeof(out) / sizeof(out[0]))); + if (rv == -1) + errx(1, "b64_pton: error decoding base64 input stream"); + printf("%s", out); +} + static void usage() { diff --git a/usr.bin/uuencode/uuencode.1 b/usr.bin/uuencode/uuencode.1 index b348143..0d4cfe4 100644 --- a/usr.bin/uuencode/uuencode.1 +++ b/usr.bin/uuencode/uuencode.1 @@ -41,6 +41,8 @@ .Nd encode/decode a binary file .Sh SYNOPSIS .Nm +.Op Fl m +.Op Fl o Ar output_file .Op Ar file .Ar name .Nm uudecode @@ -63,7 +65,9 @@ data. reads .Ar file (or by default the standard input) and writes an encoded version -to the standard output. +to the standard output, or +.Ar output_file +if one has been specified. The encoding uses only printing .Tn ASCII characters and includes the @@ -86,7 +90,20 @@ and execute bits are not retained. .Nm Uudecode ignores any leading and trailing lines. .Pp -The following options are available for +The following options are available: +.Pp +.Nm uuencode : +.Bl -tag -width ident +.It Fl m +Use the Base64 method of encoding, rather than the traditional +.Nm +algorithm. +.It Fl o Ar output_file +Output to +.Ar output_file +instead of standard output. +.El +.Pp .Nm uudecode : .Bl -tag -width ident .It Fl c diff --git a/usr.bin/uuencode/uuencode.c b/usr.bin/uuencode/uuencode.c index d85c7f1..64a279c 100644 --- a/usr.bin/uuencode/uuencode.c +++ b/usr.bin/uuencode/uuencode.c @@ -50,27 +50,53 @@ static const char rcsid[] = * * Encode a file so it can be mailed to a remote system. */ -#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> #include <sys/stat.h> +#include <netinet/in.h> + #include <err.h> +#include <resolv.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> void encode __P((void)); +void base64_encode __P((void)); static void usage __P((void)); +FILE *output = stdout; +int mode; +char **av; + int main(argc, argv) int argc; char *argv[]; { struct stat sb; - int mode; + int base64; + char ch; + char *outfile; - while (getopt(argc, argv, "") != -1) - usage(); + base64 = 0; + outfile = NULL; + + while ((ch = getopt(argc, argv, "mo:")) != -1) { + switch (ch) { + case 'm': + base64 = 1; + break; + case 'o': + outfile = optarg; + break; + case '?': + default: + usage(); + } + } argv += optind; argc -= optind; @@ -91,10 +117,18 @@ main(argc, argv) usage(); } - (void)printf("begin %o %s\n", mode, *argv); - encode(); - (void)printf("end\n"); - if (ferror(stdout)) + av = argv; + + if (outfile != NULL) { + output = fopen(outfile, "w+"); + if (output == NULL) + err(1, "unable to open %s for output", outfile); + } + if (base64) + base64_encode(); + else + encode(); + if (ferror(output)) errx(1, "write error"); exit(0); } @@ -103,7 +137,34 @@ main(argc, argv) #define ENC(c) ((c) ? ((c) & 077) + ' ': '`') /* - * copy from in to out, encoding as you go along. + * Copy from in to out, encoding in base64 as you go along. + */ +void +base64_encode() +{ +#define GROUPS 8 /* Group output chunks */ + unsigned char buf[6]; + char buf2[16]; + size_t n; + int rv, sequence; + + sequence = 0; + + fprintf(output, "begin-base64 %o %s\n", mode, *av); + 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"); + fprintf(output, "%s%s", buf2, (sequence % GROUPS) ? "" : "\n"); + } + if (sequence % GROUPS) + fprintf(output, "\n"); + fprintf(output, "====\n"); +} + +/* + * Copy from in to out, encoding as you go along. */ void encode() @@ -112,9 +173,10 @@ encode() register char *p; char buf[80]; + (void)fprintf(output, "begin %o %s\n", mode, *av); while ((n = fread(buf, 1, 45, stdin))) { ch = ENC(n); - if (putchar(ch) == EOF) + if (fputc(ch, output) == EOF) break; for (p = buf; n > 0; n -= 3, p += 3) { /* Pad with nulls if not a multiple of 3. */ @@ -125,34 +187,32 @@ encode() } ch = *p >> 2; ch = ENC(ch); - if (putchar(ch) == EOF) + if (fputc(ch, output) == EOF) break; ch = ((*p << 4) & 060) | ((p[1] >> 4) & 017); ch = ENC(ch); - if (putchar(ch) == EOF) + if (fputc(ch, output) == EOF) break; ch = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03); ch = ENC(ch); - if (putchar(ch) == EOF) + if (fputc(ch, output) == EOF) break; ch = p[2] & 077; ch = ENC(ch); - if (putchar(ch) == EOF) + if (fputc(ch, output) == EOF) break; } - if (putchar('\n') == EOF) + if (fputc('\n', output) == EOF) break; } if (ferror(stdin)) errx(1, "read error"); - ch = ENC('\0'); - (void)putchar(ch); - (void)putchar('\n'); + (void)fprintf(output, "%c\nend\n", ENC('\0')); } static void usage() { - (void)fprintf(stderr,"usage: uuencode [infile] remotefile\n"); + (void)fprintf(stderr,"usage: uuencode [-m] [-o outfile] [infile] remotefile\n"); exit(1); } |