| uuencode.c - sbase - suckless unix tools | |
| git clone git://git.suckless.org/sbase | |
| Log | |
| Files | |
| Refs | |
| README | |
| LICENSE | |
| --- | |
| uuencode.c (3015B) | |
| --- | |
| 1 /* See LICENSE file for copyright and license details. */ | |
| 2 #include <sys/stat.h> | |
| 3 | |
| 4 #include <stdio.h> | |
| 5 #include <string.h> | |
| 6 | |
| 7 #include "util.h" | |
| 8 | |
| 9 static unsigned int | |
| 10 b64e(unsigned char *b) | |
| 11 { | |
| 12 unsigned int o, p = b[2] | (b[1] << 8) | (b[0] << 16); | |
| 13 const char b64et[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnop… | |
| 14 | |
| 15 o = b64et[p & 0x3f]; p >>= 6; | |
| 16 o = (o << 8) | b64et[p & 0x3f]; p >>= 6; | |
| 17 o = (o << 8) | b64et[p & 0x3f]; p >>= 6; | |
| 18 o = (o << 8) | b64et[p & 0x3f]; | |
| 19 | |
| 20 return o; | |
| 21 } | |
| 22 | |
| 23 static void | |
| 24 uuencodeb64(FILE *fp, const char *name, const char *s) | |
| 25 { | |
| 26 struct stat st; | |
| 27 ssize_t n, m = 0; | |
| 28 unsigned char buf[45], *pb; | |
| 29 unsigned int out[sizeof(buf)/3 + 1], *po; | |
| 30 | |
| 31 if (fstat(fileno(fp), &st) < 0) | |
| 32 eprintf("fstat %s:", s); | |
| 33 printf("begin-base64 %o %s\n", st.st_mode & 0777, name); | |
| 34 /* write line by line */ | |
| 35 while ((n = fread(buf, 1, sizeof(buf), fp))) { | |
| 36 /* clear old buffer if converting with non-multiple of 3… | |
| 37 if (n != sizeof(buf) && (m = n % 3) != 0) { | |
| 38 buf[n] = '\0'; /* m == 2 */ | |
| 39 if (m == 1) buf[n+1] = '\0'; /* m == 1 */ | |
| 40 } | |
| 41 for (pb = buf, po = out; pb < buf + n; pb += 3) | |
| 42 *po++ = b64e(pb); | |
| 43 if (m != 0) { | |
| 44 unsigned int mask = 0xffffffff, dest = 0x3d3d3d3… | |
| 45 /* m==2 -> 0x00ffffff; m==1 -> 0x0000ffff */ | |
| 46 mask >>= ((3-m) << 3); | |
| 47 po[-1] = (po[-1] & mask) | (dest & ~mask); | |
| 48 } | |
| 49 *po++ = '\n'; | |
| 50 fwrite(out, 1, (po - out) * sizeof(unsigned int) - 3, st… | |
| 51 } | |
| 52 if (ferror(fp)) | |
| 53 eprintf("'%s' read error:", s); | |
| 54 puts("===="); | |
| 55 } | |
| 56 | |
| 57 static void | |
| 58 uuencode(FILE *fp, const char *name, const char *s) | |
| 59 { | |
| 60 struct stat st; | |
| 61 unsigned char buf[45], *p; | |
| 62 ssize_t n; | |
| 63 int ch; | |
| 64 | |
| 65 if (fstat(fileno(fp), &st) < 0) | |
| 66 eprintf("fstat %s:", s); | |
| 67 printf("begin %o %s\n", st.st_mode & 0777, name); | |
| 68 while ((n = fread(buf, 1, sizeof(buf), fp))) { | |
| 69 ch = ' ' + (n & 0x3f); | |
| 70 putchar(ch == ' ' ? '`' : ch); | |
| 71 for (p = buf; n > 0; n -= 3, p += 3) { | |
| 72 if (n < 3) { | |
| 73 p[2] = '\0'; | |
| 74 if (n < 2) | |
| 75 p[1] = '\0'; | |
| 76 } | |
| 77 ch = ' ' + ((p[0] >> 2) & 0x3f); | |
| 78 putchar(ch == ' ' ? '`' : ch); | |
| 79 ch = ' ' + (((p[0] << 4) | ((p[1] >> 4) & 0xf)) … | |
| 80 putchar(ch == ' ' ? '`' : ch); | |
| 81 ch = ' ' + (((p[1] << 2) | ((p[2] >> 6) & 0x3)) … | |
| 82 putchar(ch == ' ' ? '`' : ch); | |
| 83 ch = ' ' + (p[2] & 0x3f); | |
| 84 putchar(ch == ' ' ? '`' : ch); | |
| 85 } | |
| 86 putchar('\n'); | |
| 87 } | |
| 88 if (ferror(fp)) | |
| 89 eprintf("'%s' read error:", s); | |
| 90 printf("%c\nend\n", '`'); | |
| 91 } | |
| 92 | |
| 93 static void | |
| 94 usage(void) | |
| 95 { | |
| 96 eprintf("usage: %s [-m] [file] name\n", argv0); | |
| 97 } | |
| 98 | |
| 99 int | |
| 100 main(int argc, char *argv[]) | |
| 101 { | |
| 102 FILE *fp = NULL; | |
| 103 void (*uuencode_f)(FILE *, const char *, const char *) = uuencod… | |
| 104 int ret = 0; | |
| 105 | |
| 106 ARGBEGIN { | |
| 107 case 'm': | |
| 108 uuencode_f = uuencodeb64; | |
| 109 break; | |
| 110 default: | |
| 111 usage(); | |
| 112 } ARGEND | |
| 113 | |
| 114 if (!argc || argc > 2) | |
| 115 usage(); | |
| 116 | |
| 117 if (argc == 1 || !strcmp(argv[0], "-")) { | |
| 118 uuencode_f(stdin, argv[0], "<stdin>"); | |
| 119 } else { | |
| 120 if (!(fp = fopen(argv[0], "r"))) | |
| 121 eprintf("fopen %s:", argv[0]); | |
| 122 uuencode_f(fp, argv[1], argv[0]); | |
| 123 } | |
| 124 | |
| 125 ret |= fp && fshut(fp, argv[0]); | |
| 126 ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>"); | |
| 127 | |
| 128 return ret; | |
| 129 } |