1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include "libbb.h"
16
17static void read_stduu(FILE *src_stream, FILE *dst_stream)
18{
19 char *line;
20
21 while ((line = xmalloc_fgetline(src_stream)) != NULL) {
22 int encoded_len, str_len;
23 char *line_ptr, *dst;
24
25 if (strcmp(line, "end") == 0) {
26 return;
27 }
28
29 line_ptr = line;
30 while (*line_ptr) {
31 *line_ptr = (*line_ptr - 0x20) & 0x3f;
32 line_ptr++;
33 }
34 str_len = line_ptr - line;
35
36 encoded_len = line[0] * 4 / 3;
37
38
39
40 if (str_len <= encoded_len) {
41 break;
42 }
43 if (encoded_len <= 0) {
44
45 free(line);
46 continue;
47 }
48 if (encoded_len > 60) {
49 bb_error_msg_and_die("line too long");
50 }
51
52 dst = line;
53 line_ptr = line + 1;
54 do {
55
56 *dst++ = line_ptr[0] << 2 | line_ptr[1] >> 4;
57 encoded_len--;
58 if (encoded_len == 0) {
59 break;
60 }
61
62 *dst++ = line_ptr[1] << 4 | line_ptr[2] >> 2;
63 encoded_len--;
64 if (encoded_len == 0) {
65 break;
66 }
67
68 *dst++ = line_ptr[2] << 6 | line_ptr[3];
69 line_ptr += 4;
70 encoded_len -= 2;
71 } while (encoded_len > 0);
72 fwrite(line, 1, dst - line, dst_stream);
73 free(line);
74 }
75 bb_error_msg_and_die("short file");
76}
77
78static void read_base64(FILE *src_stream, FILE *dst_stream)
79{
80 int term_count = 1;
81
82 while (1) {
83 char translated[4];
84 int count = 0;
85
86 while (count < 4) {
87 char *table_ptr;
88 int ch;
89
90
91
92
93
94 do {
95 ch = fgetc(src_stream);
96 if (ch == EOF) {
97 bb_error_msg_and_die("short file");
98 }
99 table_ptr = strchr(bb_uuenc_tbl_base64, ch);
100 } while (table_ptr == NULL);
101
102
103 ch = table_ptr - bb_uuenc_tbl_base64;
104
105 if (*table_ptr == '=') {
106 if (term_count == 0) {
107 translated[count] = '\0';
108 break;
109 }
110 term_count++;
111 } else if (*table_ptr == '\n') {
112
113 if (term_count == 5) {
114 return;
115 }
116 term_count = 1;
117 continue;
118 } else {
119 translated[count] = ch;
120 count++;
121 term_count = 0;
122 }
123 }
124
125
126 if (count > 1) {
127 fputc(translated[0] << 2 | translated[1] >> 4, dst_stream);
128 }
129 if (count > 2) {
130 fputc(translated[1] << 4 | translated[2] >> 2, dst_stream);
131 }
132 if (count > 3) {
133 fputc(translated[2] << 6 | translated[3], dst_stream);
134 }
135 }
136}
137
138int uudecode_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
139int uudecode_main(int argc UNUSED_PARAM, char **argv)
140{
141 FILE *src_stream;
142 char *outname = NULL;
143 char *line;
144
145 opt_complementary = "?1";
146 getopt32(argv, "o:", &outname);
147 argv += optind;
148
149 if (!*argv)
150 *--argv = (char*)"-";
151 src_stream = xfopen_stdin(*argv);
152
153
154 while ((line = xmalloc_fgetline(src_stream)) != NULL) {
155 void (*decode_fn_ptr)(FILE *src, FILE *dst);
156 char *line_ptr;
157 FILE *dst_stream;
158 int mode;
159
160 if (strncmp(line, "begin-base64 ", 13) == 0) {
161 line_ptr = line + 13;
162 decode_fn_ptr = read_base64;
163 } else if (strncmp(line, "begin ", 6) == 0) {
164 line_ptr = line + 6;
165 decode_fn_ptr = read_stduu;
166 } else {
167 free(line);
168 continue;
169 }
170
171
172 mode = bb_strtou(line_ptr, NULL, 8);
173 if (outname == NULL) {
174 outname = strchr(line_ptr, ' ');
175 if ((outname == NULL) || (*outname == '\0')) {
176 break;
177 }
178 outname++;
179 }
180 dst_stream = stdout;
181 if (NOT_LONE_DASH(outname)) {
182 dst_stream = xfopen_for_write(outname);
183 fchmod(fileno(dst_stream), mode & (S_IRWXU | S_IRWXG | S_IRWXO));
184 }
185 free(line);
186 decode_fn_ptr(src_stream, dst_stream);
187
188 return EXIT_SUCCESS;
189 }
190 bb_error_msg_and_die("no 'begin' line");
191}
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225