The branch main has been updated by pstef:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=2ad786c63ae2f8018f67414076c9aa023e062028

commit 2ad786c63ae2f8018f67414076c9aa023e062028
Author:     Piotr Pawel Stefaniak <ps...@freebsd.org>
AuthorDate: 2022-04-06 18:03:02 +0000
Commit:     Piotr Pawel Stefaniak <ps...@freebsd.org>
CommitDate: 2022-04-18 11:53:58 +0000

    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
---
 usr.bin/bintrans/bintrans.1 | 10 ++++++++
 usr.bin/bintrans/uuencode.c | 60 ++++++++++++++++++++++++++++++++++++---------
 2 files changed, 59 insertions(+), 11 deletions(-)

diff --git a/usr.bin/bintrans/bintrans.1 b/usr.bin/bintrans/bintrans.1
index e3ad5813f4cd..cdc819aa7a18 100644
--- a/usr.bin/bintrans/bintrans.1
+++ b/usr.bin/bintrans/bintrans.1
@@ -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.
diff --git a/usr.bin/bintrans/uuencode.c b/usr.bin/bintrans/uuencode.c
index f2d4b5b2b498..4837d3310578 100644
--- a/usr.bin/bintrans/uuencode.c
+++ b/usr.bin/bintrans/uuencode.c
@@ -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)
 {

Reply via email to