1*cf5a6c84SAndroid Build Coastguard Worker /* uudecode.c - uudecode / base64 decode
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2013 Erich Plondke <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker *
5*cf5a6c84SAndroid Build Coastguard Worker * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/uudecode.html
6*cf5a6c84SAndroid Build Coastguard Worker
7*cf5a6c84SAndroid Build Coastguard Worker USE_UUDECODE(NEWTOY(uudecode, ">1o:", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_UMASK))
8*cf5a6c84SAndroid Build Coastguard Worker
9*cf5a6c84SAndroid Build Coastguard Worker config UUDECODE
10*cf5a6c84SAndroid Build Coastguard Worker bool "uudecode"
11*cf5a6c84SAndroid Build Coastguard Worker default y
12*cf5a6c84SAndroid Build Coastguard Worker help
13*cf5a6c84SAndroid Build Coastguard Worker usage: uudecode [-o OUTFILE] [INFILE]
14*cf5a6c84SAndroid Build Coastguard Worker
15*cf5a6c84SAndroid Build Coastguard Worker Decode file from stdin (or INFILE).
16*cf5a6c84SAndroid Build Coastguard Worker
17*cf5a6c84SAndroid Build Coastguard Worker -o Write to OUTFILE instead of filename in header
18*cf5a6c84SAndroid Build Coastguard Worker */
19*cf5a6c84SAndroid Build Coastguard Worker
20*cf5a6c84SAndroid Build Coastguard Worker #define FOR_uudecode
21*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
22*cf5a6c84SAndroid Build Coastguard Worker
GLOBALS(char * o;)23*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
24*cf5a6c84SAndroid Build Coastguard Worker char *o;
25*cf5a6c84SAndroid Build Coastguard Worker )
26*cf5a6c84SAndroid Build Coastguard Worker
27*cf5a6c84SAndroid Build Coastguard Worker void uudecode_main(void)
28*cf5a6c84SAndroid Build Coastguard Worker {
29*cf5a6c84SAndroid Build Coastguard Worker FILE *ifp = stdin;
30*cf5a6c84SAndroid Build Coastguard Worker int ofd, idx = 0, m QUIET, n;
31*cf5a6c84SAndroid Build Coastguard Worker size_t allocated_length;
32*cf5a6c84SAndroid Build Coastguard Worker char *line = 0, mode[16],
33*cf5a6c84SAndroid Build Coastguard Worker *class[] = {"begin%*[ ]%15s%*[ ]%n", "begin-base64%*[ ]%15s%*[ ]%n"};
34*cf5a6c84SAndroid Build Coastguard Worker
35*cf5a6c84SAndroid Build Coastguard Worker if (toys.optc) ifp = xfopen(*toys.optargs, "r");
36*cf5a6c84SAndroid Build Coastguard Worker
37*cf5a6c84SAndroid Build Coastguard Worker while (!idx) {
38*cf5a6c84SAndroid Build Coastguard Worker if ((n = getline(&line, &allocated_length, ifp)) == -1)
39*cf5a6c84SAndroid Build Coastguard Worker error_exit("no begin line");
40*cf5a6c84SAndroid Build Coastguard Worker if (!n) continue;
41*cf5a6c84SAndroid Build Coastguard Worker line[n-1] = 0;
42*cf5a6c84SAndroid Build Coastguard Worker for (m=0; m < 2; m++) {
43*cf5a6c84SAndroid Build Coastguard Worker sscanf(line, class[m], mode, &idx);
44*cf5a6c84SAndroid Build Coastguard Worker if (idx) break;
45*cf5a6c84SAndroid Build Coastguard Worker }
46*cf5a6c84SAndroid Build Coastguard Worker }
47*cf5a6c84SAndroid Build Coastguard Worker
48*cf5a6c84SAndroid Build Coastguard Worker if (TT.o && !strcmp(TT.o, "-")) ofd = 1;
49*cf5a6c84SAndroid Build Coastguard Worker else ofd = xcreate(TT.o ? TT.o : line+idx, O_WRONLY|O_CREAT|O_TRUNC,
50*cf5a6c84SAndroid Build Coastguard Worker string_to_mode(mode, 0777^toys.old_umask));
51*cf5a6c84SAndroid Build Coastguard Worker
52*cf5a6c84SAndroid Build Coastguard Worker for (;;) {
53*cf5a6c84SAndroid Build Coastguard Worker char *in, *out;
54*cf5a6c84SAndroid Build Coastguard Worker int olen;
55*cf5a6c84SAndroid Build Coastguard Worker
56*cf5a6c84SAndroid Build Coastguard Worker if (m == 2 || (n = getline(&line, &allocated_length, ifp)) == -1) break;
57*cf5a6c84SAndroid Build Coastguard Worker if (n) line[n-1] = 0;
58*cf5a6c84SAndroid Build Coastguard Worker if (!strcmp(line, m ? "====" : "end")) {
59*cf5a6c84SAndroid Build Coastguard Worker m = 2;
60*cf5a6c84SAndroid Build Coastguard Worker continue;
61*cf5a6c84SAndroid Build Coastguard Worker }
62*cf5a6c84SAndroid Build Coastguard Worker
63*cf5a6c84SAndroid Build Coastguard Worker olen = 0;
64*cf5a6c84SAndroid Build Coastguard Worker in = out = line;
65*cf5a6c84SAndroid Build Coastguard Worker if (!m) olen = (*(in++) - 32) & 0x3f;
66*cf5a6c84SAndroid Build Coastguard Worker
67*cf5a6c84SAndroid Build Coastguard Worker for (;;) {
68*cf5a6c84SAndroid Build Coastguard Worker int i = 0, x = 0, len = 4;
69*cf5a6c84SAndroid Build Coastguard Worker char c = 0;
70*cf5a6c84SAndroid Build Coastguard Worker
71*cf5a6c84SAndroid Build Coastguard Worker if (!m) {
72*cf5a6c84SAndroid Build Coastguard Worker if (olen < 1) break;
73*cf5a6c84SAndroid Build Coastguard Worker if (olen < 3) len = olen + 1;
74*cf5a6c84SAndroid Build Coastguard Worker }
75*cf5a6c84SAndroid Build Coastguard Worker
76*cf5a6c84SAndroid Build Coastguard Worker while (i < len) {
77*cf5a6c84SAndroid Build Coastguard Worker if (!(c = *(in++))) goto line_done;
78*cf5a6c84SAndroid Build Coastguard Worker
79*cf5a6c84SAndroid Build Coastguard Worker if (m) {
80*cf5a6c84SAndroid Build Coastguard Worker if (c == '=') {
81*cf5a6c84SAndroid Build Coastguard Worker len--;
82*cf5a6c84SAndroid Build Coastguard Worker continue;
83*cf5a6c84SAndroid Build Coastguard Worker } else if (len != 4) break;
84*cf5a6c84SAndroid Build Coastguard Worker
85*cf5a6c84SAndroid Build Coastguard Worker if (c >= 'A' && c <= 'Z') c -= 'A';
86*cf5a6c84SAndroid Build Coastguard Worker else if (c >= 'a' && c <= 'z') c += 26 - 'a';
87*cf5a6c84SAndroid Build Coastguard Worker else if (c >= '0' && c <= '9') c += 52 - '0';
88*cf5a6c84SAndroid Build Coastguard Worker else if (c == '+') c = 62;
89*cf5a6c84SAndroid Build Coastguard Worker else if (c == '/') c = 63;
90*cf5a6c84SAndroid Build Coastguard Worker else continue;
91*cf5a6c84SAndroid Build Coastguard Worker } else c = (c - 32) & 0x3f;
92*cf5a6c84SAndroid Build Coastguard Worker
93*cf5a6c84SAndroid Build Coastguard Worker x |= c << (6*(3-i));
94*cf5a6c84SAndroid Build Coastguard Worker
95*cf5a6c84SAndroid Build Coastguard Worker if (i && i < len) {
96*cf5a6c84SAndroid Build Coastguard Worker *(out++) = (x>>(8*(3-i))) & 0xff;
97*cf5a6c84SAndroid Build Coastguard Worker olen--;
98*cf5a6c84SAndroid Build Coastguard Worker }
99*cf5a6c84SAndroid Build Coastguard Worker i++;
100*cf5a6c84SAndroid Build Coastguard Worker }
101*cf5a6c84SAndroid Build Coastguard Worker
102*cf5a6c84SAndroid Build Coastguard Worker if (i && i!=len) error_exit("bad %s", line);
103*cf5a6c84SAndroid Build Coastguard Worker }
104*cf5a6c84SAndroid Build Coastguard Worker line_done:
105*cf5a6c84SAndroid Build Coastguard Worker xwrite(ofd, line, out-line);
106*cf5a6c84SAndroid Build Coastguard Worker }
107*cf5a6c84SAndroid Build Coastguard Worker
108*cf5a6c84SAndroid Build Coastguard Worker if (CFG_TOYBOX_FREE) {
109*cf5a6c84SAndroid Build Coastguard Worker if (ifp != stdin) fclose(ifp);
110*cf5a6c84SAndroid Build Coastguard Worker close(ofd);
111*cf5a6c84SAndroid Build Coastguard Worker free(line);
112*cf5a6c84SAndroid Build Coastguard Worker }
113*cf5a6c84SAndroid Build Coastguard Worker }
114