Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/bintrans/uuencode.c
Show First 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#include <err.h> | #include <err.h> | ||||
#include <errno.h> | |||||
#include <libgen.h> | #include <libgen.h> | ||||
#include <resolv.h> | #include <resolv.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
extern int main_encode(int, char *[]); | extern int main_encode(int, char *[]); | ||||
static void encode(void); | static void encode(void); | ||||
static void base64_encode(void); | static void base64_encode(void); | ||||
static int arg_to_col(const char *); | |||||
static void usage(void); | static void usage(void); | ||||
static FILE *output; | static FILE *output; | ||||
static int mode; | static int mode; | ||||
static bool raw; | static bool raw; | ||||
static char **av; | static char **av; | ||||
static int columns = 76; | |||||
int | int | ||||
main_encode(int argc, char *argv[]) | main_encode(int argc, char *argv[]) | ||||
{ | { | ||||
struct stat sb; | struct stat sb; | ||||
bool base64; | bool base64; | ||||
int ch; | int ch; | ||||
const char *outfile; | const char *outfile; | ||||
base64 = false; | base64 = false; | ||||
outfile = NULL; | outfile = NULL; | ||||
if (strcmp(basename(argv[0]), "b64encode") == 0) | if (strcmp(basename(argv[0]), "b64encode") == 0) | ||||
base64 = 1; | base64 = 1; | ||||
while ((ch = getopt(argc, argv, "mo:r")) != -1) { | while ((ch = getopt(argc, argv, "mo:rw:")) != -1) { | ||||
switch (ch) { | switch (ch) { | ||||
case 'm': | case 'm': | ||||
base64 = true; | base64 = true; | ||||
break; | break; | ||||
case 'o': | case 'o': | ||||
outfile = optarg; | outfile = optarg; | ||||
break; | break; | ||||
case 'r': | case 'r': | ||||
raw = true; | raw = true; | ||||
break; | break; | ||||
case 'w': | |||||
columns = arg_to_col(optarg); | |||||
break; | |||||
case '?': | case '?': | ||||
default: | default: | ||||
usage(); | usage(); | ||||
} | } | ||||
} | } | ||||
argv += optind; | argv += optind; | ||||
argc -= optind; | argc -= optind; | ||||
Show All 36 Lines | |||||
/* | /* | ||||
* Copy from in to out, encoding in base64 as you go along. | * Copy from in to out, encoding in base64 as you go along. | ||||
*/ | */ | ||||
static void | static void | ||||
base64_encode(void) | base64_encode(void) | ||||
{ | { | ||||
/* | /* | ||||
* Output must fit into 80 columns, chunks come in 4, leave 1. | * This buffer's length should be a multiple of 24 bits to avoid "=" | ||||
* padding. Once it reached ~1 KB, further expansion didn't improve | |||||
* performance for me. | |||||
*/ | */ | ||||
#define GROUPS ((80 / 4) - 1) | unsigned char buf[1023]; | ||||
unsigned char buf[3]; | |||||
char buf2[sizeof(buf) * 2 + 1]; | char buf2[sizeof(buf) * 2 + 1]; | ||||
size_t n; | size_t n; | ||||
int rv, sequence; | unsigned carry = 0; | ||||
int rv, written; | |||||
sequence = 0; | |||||
if (!raw) | if (!raw) | ||||
fprintf(output, "begin-base64 %o %s\n", mode, *av); | fprintf(output, "begin-base64 %o %s\n", mode, *av); | ||||
while ((n = fread(buf, 1, sizeof(buf), stdin))) { | while ((n = fread(buf, 1, sizeof(buf), stdin))) { | ||||
++sequence; | |||||
rv = b64_ntop(buf, n, buf2, nitems(buf2)); | rv = b64_ntop(buf, n, buf2, nitems(buf2)); | ||||
if (rv == -1) | if (rv == -1) | ||||
errx(1, "b64_ntop: error encoding base64"); | errx(1, "b64_ntop: error encoding base64"); | ||||
fprintf(output, "%s%s", buf2, (sequence % GROUPS) ? "" : "\n"); | if (columns == 0) { | ||||
fputs(buf2, output); | |||||
continue; | |||||
} | } | ||||
if (sequence % GROUPS) | for (int i = 0; i < rv; i += written) { | ||||
fprintf(output, "\n"); | written = fprintf(output, "%.*s", columns - carry, | ||||
&buf2[i]); | |||||
carry = (carry + written) % columns; | |||||
if (carry == 0) | |||||
fputc('\n', output); | |||||
} | |||||
} | |||||
if (columns == 0 || carry != 0) | |||||
fputc('\n', output); | |||||
if (!raw) | if (!raw) | ||||
fprintf(output, "====\n"); | fprintf(output, "====\n"); | ||||
} | } | ||||
/* | /* | ||||
* Copy from in to out, encoding as you go along. | * Copy from in to out, encoding as you go along. | ||||
*/ | */ | ||||
static void | static void | ||||
Show All 35 Lines | while ((n = fread(buf, 1, 45, stdin))) { | ||||
} | } | ||||
if (fputc('\n', output) == EOF) | if (fputc('\n', output) == EOF) | ||||
break; | break; | ||||
} | } | ||||
if (ferror(stdin)) | if (ferror(stdin)) | ||||
errx(1, "read error"); | errx(1, "read error"); | ||||
if (!raw) | if (!raw) | ||||
(void)fprintf(output, "%c\nend\n", ENC('\0')); | (void)fprintf(output, "%c\nend\n", ENC('\0')); | ||||
} | |||||
static int | |||||
arg_to_col(const char *w) | |||||
{ | |||||
char *ep; | |||||
long option; | |||||
errno = 0; | |||||
option = strtol(w, &ep, 10); | |||||
if (option > INT_MAX) | |||||
errno = ERANGE; | |||||
else if (ep[0] != '\0') | |||||
errno = EINVAL; | |||||
if (errno != 0) | |||||
err(2, NULL); | |||||
if (option < 0) { | |||||
errno = EINVAL; | |||||
err(2, "columns argument must be non-negative"); | |||||
} | |||||
return (option); | |||||
} | } | ||||
static void | static void | ||||
usage(void) | usage(void) | ||||
{ | { | ||||
(void)fprintf(stderr, | (void)fprintf(stderr, | ||||
"usage: uuencode [-m] [-o outfile] [infile] remotefile\n" | "usage: uuencode [-m] [-o outfile] [infile] remotefile\n" | ||||
" b64encode [-o outfile] [infile] remotefile\n"); | " b64encode [-o outfile] [infile] remotefile\n"); | ||||
exit(1); | exit(1); | ||||
} | } |