summaryrefslogtreecommitdiff
path: root/util/sbase/uuencode.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/sbase/uuencode.c')
-rw-r--r--util/sbase/uuencode.c129
1 files changed, 129 insertions, 0 deletions
diff --git a/util/sbase/uuencode.c b/util/sbase/uuencode.c
new file mode 100644
index 00000000..b5317205
--- /dev/null
+++ b/util/sbase/uuencode.c
@@ -0,0 +1,129 @@
+/* See LICENSE file for copyright and license details. */
+#include <sys/stat.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "util.h"
+
+static unsigned int
+b64e(unsigned char *b)
+{
+ unsigned int o, p = b[2] | (b[1] << 8) | (b[0] << 16);
+ const char b64et[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+ o = b64et[p & 0x3f]; p >>= 6;
+ o = (o << 8) | b64et[p & 0x3f]; p >>= 6;
+ o = (o << 8) | b64et[p & 0x3f]; p >>= 6;
+ o = (o << 8) | b64et[p & 0x3f];
+
+ return o;
+}
+
+static void
+uuencodeb64(FILE *fp, const char *name, const char *s)
+{
+ struct stat st;
+ ssize_t n, m = 0;
+ unsigned char buf[45], *pb;
+ unsigned int out[sizeof(buf)/3 + 1], *po;
+
+ if (fstat(fileno(fp), &st) < 0)
+ eprintf("fstat %s:", s);
+ printf("begin-base64 %o %s\n", st.st_mode & 0777, name);
+ /* write line by line */
+ while ((n = fread(buf, 1, sizeof(buf), fp))) {
+ /* clear old buffer if converting with non-multiple of 3 */
+ if (n != sizeof(buf) && (m = n % 3) != 0) {
+ buf[n] = '\0'; /* m == 2 */
+ if (m == 1) buf[n+1] = '\0'; /* m == 1 */
+ }
+ for (pb = buf, po = out; pb < buf + n; pb += 3)
+ *po++ = b64e(pb);
+ if (m != 0) {
+ unsigned int mask = 0xffffffff, dest = 0x3d3d3d3d;
+ /* m==2 -> 0x00ffffff; m==1 -> 0x0000ffff */
+ mask >>= ((3-m) << 3);
+ po[-1] = (po[-1] & mask) | (dest & ~mask);
+ }
+ *po++ = '\n';
+ fwrite(out, 1, (po - out) * sizeof(unsigned int) - 3, stdout);
+ }
+ if (ferror(fp))
+ eprintf("'%s' read error:", s);
+ puts("====");
+}
+
+static void
+uuencode(FILE *fp, const char *name, const char *s)
+{
+ struct stat st;
+ unsigned char buf[45], *p;
+ ssize_t n;
+ int ch;
+
+ if (fstat(fileno(fp), &st) < 0)
+ eprintf("fstat %s:", s);
+ printf("begin %o %s\n", st.st_mode & 0777, name);
+ while ((n = fread(buf, 1, sizeof(buf), fp))) {
+ ch = ' ' + (n & 0x3f);
+ putchar(ch == ' ' ? '`' : ch);
+ for (p = buf; n > 0; n -= 3, p += 3) {
+ if (n < 3) {
+ p[2] = '\0';
+ if (n < 2)
+ p[1] = '\0';
+ }
+ ch = ' ' + ((p[0] >> 2) & 0x3f);
+ putchar(ch == ' ' ? '`' : ch);
+ ch = ' ' + (((p[0] << 4) | ((p[1] >> 4) & 0xf)) & 0x3f);
+ putchar(ch == ' ' ? '`' : ch);
+ ch = ' ' + (((p[1] << 2) | ((p[2] >> 6) & 0x3)) & 0x3f);
+ putchar(ch == ' ' ? '`' : ch);
+ ch = ' ' + (p[2] & 0x3f);
+ putchar(ch == ' ' ? '`' : ch);
+ }
+ putchar('\n');
+ }
+ if (ferror(fp))
+ eprintf("'%s' read error:", s);
+ printf("%c\nend\n", '`');
+}
+
+static void
+usage(void)
+{
+ eprintf("usage: %s [-m] [file] name\n", argv0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ FILE *fp = NULL;
+ void (*uuencode_f)(FILE *, const char *, const char *) = uuencode;
+ int ret = 0;
+
+ ARGBEGIN {
+ case 'm':
+ uuencode_f = uuencodeb64;
+ break;
+ default:
+ usage();
+ } ARGEND
+
+ if (!argc || argc > 2)
+ usage();
+
+ if (argc == 1 || !strcmp(argv[0], "-")) {
+ uuencode_f(stdin, argv[0], "<stdin>");
+ } else {
+ if (!(fp = fopen(argv[0], "r")))
+ eprintf("fopen %s:", argv[0]);
+ uuencode_f(fp, argv[1], argv[0]);
+ }
+
+ ret |= fp && fshut(fp, argv[0]);
+ ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>");
+
+ return ret;
+}