PR/33319: Seebs: base64 is annoying

Thanks to Matt Fleming for implementing a -m switch (base64 mode) for
both uuencode(1) and uudecode(1)! Man-pages updated as well.
This commit is contained in:
elad 2006-09-24 15:32:48 +00:00
parent b6ce42d579
commit 3b4778f8b2
3 changed files with 168 additions and 55 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: uudecode.c,v 1.20 2005/06/29 20:35:32 wiz Exp $ */
/* $NetBSD: uudecode.c,v 1.21 2006/09/24 15:32:48 elad Exp $ */
/*-
* Copyright (c) 1983, 1993
@ -40,7 +40,7 @@ __COPYRIGHT("@(#) Copyright (c) 1983, 1993\n\
#if 0
static char sccsid[] = "@(#)uudecode.c 8.2 (Berkeley) 4/2/94";
#endif
__RCSID("$NetBSD: uudecode.c,v 1.20 2005/06/29 20:35:32 wiz Exp $");
__RCSID("$NetBSD: uudecode.c,v 1.21 2006/09/24 15:32:48 elad Exp $");
#endif /* not lint */
/*
@ -51,11 +51,13 @@ __RCSID("$NetBSD: uudecode.c,v 1.20 2005/06/29 20:35:32 wiz Exp $");
*/
#include <sys/param.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <locale.h>
#include <resolv.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
@ -64,9 +66,11 @@ __RCSID("$NetBSD: uudecode.c,v 1.20 2005/06/29 20:35:32 wiz Exp $");
static int decode(void);
static void usage(void);
static int checkend(const char *, const char *, const char *);
static int base64_decode(void);
int main(int, char *[]);
int pflag;
int base64, pflag;
char *filename;
int
@ -78,8 +82,11 @@ main(int argc, char *argv[])
setprogname(argv[0]);
pflag = 0;
while ((ch = getopt(argc, argv, "p")) != -1)
while ((ch = getopt(argc, argv, "mp")) != -1)
switch (ch) {
case 'm':
base64 = 1;
break;
case 'p':
pflag = 1;
break;
@ -118,23 +125,37 @@ decode(void)
char buf[MAXPATHLEN];
/* search for header line */
do {
for (;;) {
if (!fgets(buf, sizeof(buf), stdin)) {
warnx("%s: no \"begin\" line", filename);
warnx("%s: no \"%s\" line", filename, base64 ?
"begin-base64" : "begin");
return(1);
}
} while (strncmp(buf, "begin ", 6));
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(buf + 6, &fn, 8);
if (fn == (buf+6) || !isspace((unsigned char)*fn) || mode==LONG_MIN || mode==LONG_MAX)
mode = strtol(p, &fn, 8);
if (fn == (p) || !isspace((unsigned char)*fn) || mode==LONG_MIN || mode==LONG_MAX)
{
warnx("%s: invalid mode on \"begin\" line", filename);
warnx("%s: invalid mode on \"%s\" line", filename,
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 \"begin\" line", filename);
warnx("%s: no filename on \"%s\" line", filename,
base64 ? "begin-base64" : "begin");
return(1);
}
/* zap newline */
@ -173,54 +194,93 @@ decode(void)
return(1);
}
/* for each input line */
for (;;) {
if (!fgets(p = buf, sizeof(buf), stdin)) {
warnx("%s: short file.", filename);
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);
if (base64)
return base64_decode();
else {
/* for each input line */
for (;;) {
if (!fgets(p = buf, sizeof(buf), stdin)) {
warnx("%s: short file.", filename);
return(1);
}
else {
if (n >= 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);
}
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);
}
}
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.", filename);
return(1);
}
return(0);
}
if (!fgets(buf, sizeof(buf), stdin) || strcmp(buf, "end\n")) {
warnx("%s: no \"end\" line.", filename);
return(1);
}
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);
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.", filename);
return (1);
}
n = b64_pton(inbuf, outbuf, sizeof(outbuf));
if (n < 0)
break;
fwrite(outbuf, 1, n, stdout);
}
return (checkend(inbuf, "====",
"error decoding base64 input stream"));
}
static void
usage()
{
(void)fprintf(stderr, "usage: %s [-p] [file ...]\n",
(void)fprintf(stderr, "usage: %s [-m | -p] [file ...]\n",
getprogname());
exit(1);
}

View File

@ -1,4 +1,4 @@
.\" $NetBSD: uuencode.1,v 1.14 2003/08/07 11:16:58 agc Exp $
.\" $NetBSD: uuencode.1,v 1.15 2006/09/24 15:32:48 elad Exp $
.\"
.\" Copyright (c) 1980, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -29,7 +29,7 @@
.\"
.\" @(#)uuencode.1 8.1 (Berkeley) 6/6/93
.\"
.Dd March 19, 1999
.Dd September 24, 2006
.Dt UUENCODE 1
.Os
.Sh NAME
@ -38,6 +38,7 @@
.Nd encode/decode a binary file
.Sh SYNOPSIS
.Nm
.Op Fl m
.Op Ar file
.Ar name
.Nm uudecode
@ -52,6 +53,12 @@ that do not support other than simple
.Tn ASCII
data.
.Pp
The following options are available:
.Bl -tag
.It Fl m
Use base64 encoding.
.El
.Pp
.Nm
reads
.Ar file

View File

@ -1,4 +1,4 @@
/* $NetBSD: uuencode.c,v 1.11 2005/06/29 20:35:48 wiz Exp $ */
/* $NetBSD: uuencode.c,v 1.12 2006/09/24 15:32:48 elad Exp $ */
/*-
* Copyright (c) 1983, 1993
@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1983, 1993\n\
#if 0
static char sccsid[] = "@(#)uuencode.c 8.2 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: uuencode.c,v 1.11 2005/06/29 20:35:48 wiz Exp $");
__RCSID("$NetBSD: uuencode.c,v 1.12 2006/09/24 15:32:48 elad Exp $");
#endif
#endif /* not lint */
@ -50,9 +50,11 @@ __RCSID("$NetBSD: uuencode.c,v 1.11 2005/06/29 20:35:48 wiz Exp $");
*/
#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>
@ -60,20 +62,29 @@ __RCSID("$NetBSD: uuencode.c,v 1.11 2005/06/29 20:35:48 wiz Exp $");
int main(int, char *[]);
static void encode(void);
static void base64_encode(void);
static void usage(void);
int
main(int argc, char *argv[])
{
struct stat sb;
int mode;
int base64, ch, mode;
mode = 0;
base64 = 0;
setlocale(LC_ALL, "");
setprogname(argv[0]);
while (getopt(argc, argv, "") != -1)
usage();
while ((ch = getopt(argc, argv, "m")) != -1) {
switch(ch) {
case 'm':
base64 = 1;
break;
default:
usage();
}
}
argv += optind;
argc -= optind;
@ -94,9 +105,16 @@ main(int argc, char *argv[])
usage();
}
(void)printf("begin %o %s\n", mode, *argv);
encode();
(void)printf("end\n");
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);
@ -105,6 +123,34 @@ main(int argc, char *argv[])
/* 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.
*/
@ -150,7 +196,7 @@ encode(void)
static void
usage(void)
{
(void)fprintf(stderr, "usage: %s [infile] remotefile\n",
(void)fprintf(stderr, "usage: %s [-m] [infile] remotefile\n",
getprogname());
exit(1);
}