1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#include "libbb.h"
35
36#if ENABLE_UUDECODE
37static void FAST_FUNC read_stduu(FILE *src_stream, FILE *dst_stream, int flags UNUSED_PARAM)
38{
39 char *line;
40
41 for (;;) {
42 int encoded_len, str_len;
43 char *line_ptr, *dst;
44 size_t line_len;
45
46 line_len = 64 * 1024;
47 line = xmalloc_fgets_str_len(src_stream, "\n", &line_len);
48 if (!line)
49 break;
50
51
52
53
54 str_len = line_len;
55 while (--str_len >= 0
56 && (line[str_len] == '\n' || line[str_len] == '\r')
57 ) {
58 line[str_len] = '\0';
59 }
60
61 if (strcmp(line, "end") == 0) {
62 return;
63 }
64
65 line_ptr = line;
66 while (*line_ptr) {
67 *line_ptr = (*line_ptr - 0x20) & 0x3f;
68 line_ptr++;
69 }
70 str_len = line_ptr - line;
71
72 encoded_len = line[0] * 4 / 3;
73
74
75
76 if (str_len <= encoded_len) {
77 break;
78 }
79 if (encoded_len <= 0) {
80
81 free(line);
82 continue;
83 }
84 if (encoded_len > 60) {
85 bb_simple_error_msg_and_die("line too long");
86 }
87
88 dst = line;
89 line_ptr = line + 1;
90 do {
91
92 *dst++ = line_ptr[0] << 2 | line_ptr[1] >> 4;
93 encoded_len--;
94 if (encoded_len == 0) {
95 break;
96 }
97
98 *dst++ = line_ptr[1] << 4 | line_ptr[2] >> 2;
99 encoded_len--;
100 if (encoded_len == 0) {
101 break;
102 }
103
104 *dst++ = line_ptr[2] << 6 | line_ptr[3];
105 line_ptr += 4;
106 encoded_len -= 2;
107 } while (encoded_len > 0);
108 fwrite(line, 1, dst - line, dst_stream);
109 free(line);
110 }
111 bb_simple_error_msg_and_die("short file");
112}
113
114int uudecode_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
115int uudecode_main(int argc UNUSED_PARAM, char **argv)
116{
117 FILE *src_stream;
118 char *outname = NULL;
119 char *line;
120
121 getopt32(argv, "^" "o:" "\0" "?1", &outname);
122 argv += optind;
123
124 if (!argv[0])
125 *--argv = (char*)"-";
126 src_stream = xfopen_stdin(argv[0]);
127
128
129 while ((line = xmalloc_fgetline(src_stream)) != NULL) {
130 void FAST_FUNC (*decode_fn_ptr)(FILE *src, FILE *dst, int flags);
131 char *line_ptr;
132 FILE *dst_stream;
133 int mode;
134
135 if (is_prefixed_with(line, "begin-base64 ")) {
136 line_ptr = line + 13;
137 decode_fn_ptr = read_base64;
138 } else if (is_prefixed_with(line, "begin ")) {
139 line_ptr = line + 6;
140 decode_fn_ptr = read_stduu;
141 } else {
142 free(line);
143 continue;
144 }
145
146
147 mode = bb_strtou(line_ptr, NULL, 8);
148 if (outname == NULL) {
149 outname = strchr(line_ptr, ' ');
150 if (!outname)
151 break;
152 outname++;
153 trim(outname);
154 if (!outname[0])
155 break;
156 }
157 dst_stream = stdout;
158 if (NOT_LONE_DASH(outname)) {
159 dst_stream = xfopen_for_write(outname);
160 fchmod(fileno(dst_stream), mode & (S_IRWXU | S_IRWXG | S_IRWXO));
161 }
162 free(line);
163 decode_fn_ptr(src_stream, dst_stream, BASE64_FLAG_UU_STOP + BASE64_FLAG_NO_STOP_CHAR);
164
165 return EXIT_SUCCESS;
166 }
167 bb_simple_error_msg_and_die("no 'begin' line");
168}
169#endif
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208#if ENABLE_BASE32 || ENABLE_BASE64
209
210# if ENABLE_BASE32
211static void bb_b32encode(char *p, const void *src, int length)
212{
213#define tbl bb_uuenc_tbl_base32
214 const unsigned char *s = src;
215
216
217 while (length > 0) {
218 unsigned cur, next;
219
220 length--;
221 cur = *s++;
222 *p++ = tbl[cur >> 3];
223 cur &= 7;
224
225 next = 0;
226 if (--length >= 0)
227 next = *s++;
228 *p++ = tbl[(cur << 2) + (next >> 6)];
229 cur = next & 0x3f;
230
231 *p++ = tbl[cur >> 1];
232 cur &= 1;
233
234 next = 0;
235 if (--length >= 0)
236 next = *s++;
237 *p++ = tbl[(cur << 4) + (next >> 4)];
238 cur = next & 0xf;
239
240 next = 0;
241 if (--length >= 0)
242 next = *s++;
243 *p++ = tbl[(cur << 1) + (next >> 7)];
244 cur = next & 0x7f;
245
246 *p++ = tbl[cur >> 2];
247 cur &= 3;
248
249 next = 0;
250 if (--length >= 0)
251 next = *s++;
252 *p++ = tbl[(cur << 3) + (next >> 5)];
253 cur = next & 0x1f;
254
255 *p++ = tbl[cur];
256 }
257#undef tbl
258
259 *p = '\0';
260
261 length = ((-length) * 3) >> 1;
262 while (length--) {
263 *--p = '=';
264 }
265}
266# else
267void bb_b32encode(char *p, const void *src, int length);
268# endif
269
270int baseNUM_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
271int baseNUM_main(int argc UNUSED_PARAM, char **argv)
272{
273 FILE *src_stream;
274 unsigned opts;
275 unsigned col = 76;
276
277 opts = getopt32(argv, "^" "diw:+" "\0" "?1", &col);
278 argv += optind;
279
280 if (!argv[0])
281 *--argv = (char*)"-";
282 src_stream = xfopen_stdin(argv[0]);
283 if (opts & 1) {
284
285 int flags = (unsigned char)EOF;
286 if (ENABLE_BASE32 && (!ENABLE_BASE64 || applet_name[4] == '3'))
287 flags = ((unsigned char)EOF) | BASE64_32;
288 read_base64(src_stream, stdout, flags);
289 } else {
290 enum {
291 SRC_BUF_SIZE = 3 * 5 * 32,
292 DST_BUF_SIZE = 8 * ((SRC_BUF_SIZE + 4) / 5),
293 };
294
295
296
297
298
299 char dst_buf[((DST_BUF_SIZE + 16) | 0xf) + 1];
300#define src_buf (dst_buf + sizeof(dst_buf) - SRC_BUF_SIZE)
301 int src_fd, rem;
302
303 src_fd = fileno(src_stream);
304 rem = 0;
305 while (1) {
306 size_t size = full_read(src_fd, src_buf, SRC_BUF_SIZE);
307 if ((ssize_t)size < 0)
308 bb_simple_perror_msg_and_die(bb_msg_read_error);
309 if (size == 0) {
310 if (rem != 0) bb_putchar('\n');
311 break;
312 }
313
314
315 if (ENABLE_BASE32 && (!ENABLE_BASE64 || applet_name[4] == '3')) {
316 bb_b32encode(dst_buf, src_buf, size);
317 size = 8 * ((size + 4) / 5);
318 } else {
319 bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64);
320 size = 4 * ((size + 2) / 3);
321 }
322
323 if (col == 0) {
324 fputs_stdout(dst_buf);
325 } else {
326 char *result = dst_buf;
327 if (rem == 0)
328 rem = col;
329 while (1) {
330 int out = size < rem ? size : rem;
331 rem -= out;
332 printf(rem != 0 ? "%.*s" : "%.*s\n", out, result);
333 if (rem != 0)
334 break;
335 size -= out;
336 if (size == 0)
337 break;
338 result += out;
339 rem = col;
340 }
341 }
342 }
343#undef src_buf
344 }
345
346 fflush_stdout_and_exit(EXIT_SUCCESS);
347}
348#endif
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382