b64encode: implement -w to wrap lines
This functionality is present in GNU base64 and I find it useful when I want to generate random, ASCII-clean data of specific width. Reviewed by: delphij Differential Revision: https://reviews.freebsd.org/D32944
This commit is contained in:
parent
f331cf9b04
commit
2ad786c63a
@ -56,6 +56,7 @@
|
||||
.Fl o Ar output_file
|
||||
.Nm b64encode
|
||||
.Op Fl r
|
||||
.Op Fl w Ar column
|
||||
.Op Fl o Ar output_file
|
||||
.Op Ar file
|
||||
.Ar name
|
||||
@ -181,6 +182,15 @@ deletes any prefix ending with the last slash '/' for security
|
||||
reasons.
|
||||
.El
|
||||
.Pp
|
||||
Additionally,
|
||||
.Nm b64encode
|
||||
accepts the following option:
|
||||
.Bl -tag -width ident
|
||||
.It Fl w Ar column
|
||||
Wrap encoded output after
|
||||
.Ar column .
|
||||
.El
|
||||
.Pp
|
||||
.Nm
|
||||
is a generic utility that can run
|
||||
any of the aforementioned encoders and decoders.
|
||||
|
@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <libgen.h>
|
||||
#include <resolv.h>
|
||||
#include <stdio.h>
|
||||
@ -67,12 +68,14 @@ extern int main_encode(int, char *[]);
|
||||
|
||||
static void encode(void);
|
||||
static void base64_encode(void);
|
||||
static int arg_to_col(const char *);
|
||||
static void usage(void);
|
||||
|
||||
static FILE *output;
|
||||
static int mode;
|
||||
static bool raw;
|
||||
static char **av;
|
||||
static int columns = 76;
|
||||
|
||||
int
|
||||
main_encode(int argc, char *argv[])
|
||||
@ -88,7 +91,7 @@ main_encode(int argc, char *argv[])
|
||||
if (strcmp(basename(argv[0]), "b64encode") == 0)
|
||||
base64 = 1;
|
||||
|
||||
while ((ch = getopt(argc, argv, "mo:r")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "mo:rw:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'm':
|
||||
base64 = true;
|
||||
@ -99,6 +102,9 @@ main_encode(int argc, char *argv[])
|
||||
case 'r':
|
||||
raw = true;
|
||||
break;
|
||||
case 'w':
|
||||
columns = arg_to_col(optarg);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
@ -151,27 +157,37 @@ static 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[3];
|
||||
unsigned char buf[1023];
|
||||
char buf2[sizeof(buf) * 2 + 1];
|
||||
size_t n;
|
||||
int rv, sequence;
|
||||
|
||||
sequence = 0;
|
||||
unsigned carry = 0;
|
||||
int rv, written;
|
||||
|
||||
if (!raw)
|
||||
fprintf(output, "begin-base64 %o %s\n", mode, *av);
|
||||
while ((n = fread(buf, 1, sizeof(buf), stdin))) {
|
||||
++sequence;
|
||||
rv = b64_ntop(buf, n, buf2, nitems(buf2));
|
||||
if (rv == -1)
|
||||
errx(1, "b64_ntop: error encoding base64");
|
||||
fprintf(output, "%s%s", buf2, (sequence % GROUPS) ? "" : "\n");
|
||||
if (columns == 0) {
|
||||
fputs(buf2, output);
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < rv; i += written) {
|
||||
written = fprintf(output, "%.*s", columns - carry,
|
||||
&buf2[i]);
|
||||
|
||||
carry = (carry + written) % columns;
|
||||
if (carry == 0)
|
||||
fputc('\n', output);
|
||||
}
|
||||
}
|
||||
if (sequence % GROUPS)
|
||||
fprintf(output, "\n");
|
||||
if (columns == 0 || carry != 0)
|
||||
fputc('\n', output);
|
||||
if (!raw)
|
||||
fprintf(output, "====\n");
|
||||
}
|
||||
@ -225,6 +241,28 @@ encode(void)
|
||||
(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
|
||||
usage(void)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user