diff options
Diffstat (limited to 'coreutils/uudecode.c')
-rw-r--r-- | coreutils/uudecode.c | 70 |
1 files changed, 40 insertions, 30 deletions
diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c index 34a22398c..4c619dec5 100644 --- a/coreutils/uudecode.c +++ b/coreutils/uudecode.c | |||
@@ -19,48 +19,57 @@ static void read_stduu(FILE *src_stream, FILE *dst_stream) | |||
19 | char *line; | 19 | char *line; |
20 | 20 | ||
21 | while ((line = xmalloc_getline(src_stream)) != NULL) { | 21 | while ((line = xmalloc_getline(src_stream)) != NULL) { |
22 | int length; | 22 | int encoded_len, str_len; |
23 | char *line_ptr = line; | 23 | char *line_ptr, *dst; |
24 | 24 | ||
25 | if (strcmp(line, "end") == 0) { | 25 | if (strcmp(line, "end") == 0) { |
26 | return; | 26 | return; /* the only non-error exit */ |
27 | } | 27 | } |
28 | length = ((*line_ptr - 0x20) & 0x3f)* 4 / 3; | ||
29 | 28 | ||
30 | if (length <= 0) { | 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 | /* Check that line is not too short. (we tolerate | ||
38 | * overly _long_ line to accomodate possible extra '`'). | ||
39 | * Empty line case is also caught here. */ | ||
40 | if (str_len <= encoded_len) { | ||
41 | break; /* go to bb_error_msg_and_die("short file"); */ | ||
42 | } | ||
43 | if (encoded_len <= 0) { | ||
31 | /* Ignore the "`\n" line, why is it even in the encode file ? */ | 44 | /* Ignore the "`\n" line, why is it even in the encode file ? */ |
45 | free(line); | ||
32 | continue; | 46 | continue; |
33 | } | 47 | } |
34 | if (length > 60) { | 48 | if (encoded_len > 60) { |
35 | bb_error_msg_and_die("line too long"); | 49 | bb_error_msg_and_die("line too long"); |
36 | } | 50 | } |
37 | 51 | ||
38 | line_ptr++; | 52 | dst = line; |
39 | /* Tolerate an overly long line to accomodate a possible exta '`' */ | 53 | line_ptr = line + 1; |
40 | if (strlen(line_ptr) < (size_t)length) { | 54 | do { |
41 | bb_error_msg_and_die("short file"); | ||
42 | } | ||
43 | |||
44 | while (length > 0) { | ||
45 | /* Merge four 6 bit chars to three 8 bit chars */ | 55 | /* Merge four 6 bit chars to three 8 bit chars */ |
46 | fputc(((line_ptr[0] - 0x20) & 077) << 2 | ((line_ptr[1] - 0x20) & 077) >> 4, dst_stream); | 56 | *dst++ = line_ptr[0] << 2 | line_ptr[1] >> 4; |
47 | line_ptr++; | 57 | encoded_len--; |
48 | length--; | 58 | if (encoded_len == 0) { |
49 | if (length == 0) { | ||
50 | break; | 59 | break; |
51 | } | 60 | } |
52 | 61 | ||
53 | fputc(((line_ptr[0] - 0x20) & 077) << 4 | ((line_ptr[1] - 0x20) & 077) >> 2, dst_stream); | 62 | *dst++ = line_ptr[1] << 4 | line_ptr[2] >> 2; |
54 | line_ptr++; | 63 | encoded_len--; |
55 | length--; | 64 | if (encoded_len == 0) { |
56 | if (length == 0) { | ||
57 | break; | 65 | break; |
58 | } | 66 | } |
59 | 67 | ||
60 | fputc(((line_ptr[0] - 0x20) & 077) << 6 | ((line_ptr[1] - 0x20) & 077), dst_stream); | 68 | *dst++ = line_ptr[2] << 6 | line_ptr[3]; |
61 | line_ptr += 2; | 69 | line_ptr += 4; |
62 | length -= 2; | 70 | encoded_len -= 2; |
63 | } | 71 | } while (encoded_len > 0); |
72 | fwrite(line, 1, dst - line, dst_stream); | ||
64 | free(line); | 73 | free(line); |
65 | } | 74 | } |
66 | bb_error_msg_and_die("short file"); | 75 | bb_error_msg_and_die("short file"); |
@@ -129,7 +138,7 @@ static void read_base64(FILE *src_stream, FILE *dst_stream) | |||
129 | int uudecode_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 138 | int uudecode_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
130 | int uudecode_main(int argc ATTRIBUTE_UNUSED, char **argv) | 139 | int uudecode_main(int argc ATTRIBUTE_UNUSED, char **argv) |
131 | { | 140 | { |
132 | FILE *src_stream = stdin; | 141 | FILE *src_stream; |
133 | char *outname = NULL; | 142 | char *outname = NULL; |
134 | char *line; | 143 | char *line; |
135 | 144 | ||
@@ -137,8 +146,9 @@ int uudecode_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
137 | getopt32(argv, "o:", &outname); | 146 | getopt32(argv, "o:", &outname); |
138 | argv += optind; | 147 | argv += optind; |
139 | 148 | ||
140 | if (argv[0]) | 149 | if (!*argv) |
141 | src_stream = xfopen(argv[0], "r"); | 150 | *--argv = (char*)"-"; |
151 | src_stream = xfopen_stdin(*argv); | ||
142 | 152 | ||
143 | /* Search for the start of the encoding */ | 153 | /* Search for the start of the encoding */ |
144 | while ((line = xmalloc_getline(src_stream)) != NULL) { | 154 | while ((line = xmalloc_getline(src_stream)) != NULL) { |
@@ -159,7 +169,7 @@ int uudecode_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
159 | } | 169 | } |
160 | 170 | ||
161 | /* begin line found. decode and exit */ | 171 | /* begin line found. decode and exit */ |
162 | mode = strtoul(line_ptr, NULL, 8); | 172 | mode = bb_strtou(line_ptr, NULL, 8); |
163 | if (outname == NULL) { | 173 | if (outname == NULL) { |
164 | outname = strchr(line_ptr, ' '); | 174 | outname = strchr(line_ptr, ' '); |
165 | if ((outname == NULL) || (*outname == '\0')) { | 175 | if ((outname == NULL) || (*outname == '\0')) { |
@@ -170,7 +180,7 @@ int uudecode_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
170 | dst_stream = stdout; | 180 | dst_stream = stdout; |
171 | if (NOT_LONE_DASH(outname)) { | 181 | if (NOT_LONE_DASH(outname)) { |
172 | dst_stream = xfopen(outname, "w"); | 182 | dst_stream = xfopen(outname, "w"); |
173 | chmod(outname, mode & (S_IRWXU | S_IRWXG | S_IRWXO)); | 183 | fchmod(fileno(dst_stream), mode & (S_IRWXU | S_IRWXG | S_IRWXO)); |
174 | } | 184 | } |
175 | free(line); | 185 | free(line); |
176 | decode_fn_ptr(src_stream, dst_stream); | 186 | decode_fn_ptr(src_stream, dst_stream); |