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 } |