source: MondoRescue/branches/2.2.2/mindi-busybox/coreutils/uudecode.c@ 1247

Last change on this file since 1247 was 821, checked in by Bruno Cornec, 18 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

File size: 4.2 KB
Line 
1/*
2 * Copyright 2003, Glenn McGrath <bug1@iinet.net.au>
3 *
4 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
5 *
6 * Based on specification from
7 * http://www.opengroup.org/onlinepubs/007904975/utilities/uuencode.html
8 *
9 * Bugs: the spec doesn't mention anything about "`\n`\n" prior to the
10 * "end" line
11 */
12
13
14#include <stdio.h>
15#include <errno.h>
16#include <getopt.h> /* optind */
17#include <string.h>
18#include <stdlib.h>
19#include "busybox.h"
20
21static int read_stduu(FILE *src_stream, FILE *dst_stream)
22{
23 char *line;
24
25 while ((line = bb_get_chomped_line_from_file(src_stream)) != NULL) {
26 int length;
27 char *line_ptr = line;
28
29 if (strcmp(line, "end") == 0) {
30 return(EXIT_SUCCESS);
31 }
32 length = ((*line_ptr - 0x20) & 0x3f)* 4 / 3;
33
34 if (length <= 0) {
35 /* Ignore the "`\n" line, why is it even in the encode file ? */
36 continue;
37 }
38 if (length > 60) {
39 bb_error_msg_and_die("Line too long");
40 }
41
42 line_ptr++;
43 /* Tolerate an overly long line to acomadate a possible exta '`' */
44 if (strlen(line_ptr) < (size_t)length) {
45 bb_error_msg_and_die("Short file");
46 }
47
48 while (length > 0) {
49 /* Merge four 6 bit chars to three 8 bit chars */
50 fputc(((line_ptr[0] - 0x20) & 077) << 2 | ((line_ptr[1] - 0x20) & 077) >> 4, dst_stream);
51 line_ptr++;
52 length--;
53 if (length == 0) {
54 break;
55 }
56
57 fputc(((line_ptr[0] - 0x20) & 077) << 4 | ((line_ptr[1] - 0x20) & 077) >> 2, dst_stream);
58 line_ptr++;
59 length--;
60 if (length == 0) {
61 break;
62 }
63
64 fputc(((line_ptr[0] - 0x20) & 077) << 6 | ((line_ptr[1] - 0x20) & 077), dst_stream);
65 line_ptr += 2;
66 length -= 2;
67 }
68 free(line);
69 }
70 bb_error_msg_and_die("Short file");
71}
72
73static int read_base64(FILE *src_stream, FILE *dst_stream)
74{
75 static const char base64_table[] =
76 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n";
77 char term_count = 0;
78
79 while (1) {
80 char translated[4];
81 int count = 0;
82
83 while (count < 4) {
84 char *table_ptr;
85 int ch;
86
87 /* Get next _valid_ character */
88 do {
89 ch = fgetc(src_stream);
90 if (ch == EOF) {
91 bb_error_msg_and_die("Short file");
92 }
93 } while ((table_ptr = strchr(base64_table, ch)) == NULL);
94
95 /* Convert encoded charcter to decimal */
96 ch = table_ptr - base64_table;
97
98 if (*table_ptr == '=') {
99 if (term_count == 0) {
100 translated[count] = 0;
101 break;
102 }
103 term_count++;
104 }
105 else if (*table_ptr == '\n') {
106 /* Check for terminating line */
107 if (term_count == 5) {
108 return(EXIT_SUCCESS);
109 }
110 term_count = 1;
111 continue;
112 } else {
113 translated[count] = ch;
114 count++;
115 term_count = 0;
116 }
117 }
118
119 /* Merge 6 bit chars to 8 bit */
120 fputc(translated[0] << 2 | translated[1] >> 4, dst_stream);
121 if (count > 2) {
122 fputc(translated[1] << 4 | translated[2] >> 2, dst_stream);
123 }
124 if (count > 3) {
125 fputc(translated[2] << 6 | translated[3], dst_stream);
126 }
127 }
128}
129
130int uudecode_main(int argc, char **argv)
131{
132 int (*decode_fn_ptr) (FILE * src, FILE * dst);
133 FILE *src_stream;
134 char *outname = NULL;
135 char *line;
136 int opt;
137
138 opt = bb_getopt_ulflags(argc, argv, "o:", &outname);
139
140 if (optind == argc) {
141 src_stream = stdin;
142 } else if (optind + 1 == argc) {
143 src_stream = bb_xfopen(argv[optind], "r");
144 } else {
145 bb_show_usage();
146 }
147
148 /* Search for the start of the encoding */
149 while ((line = bb_get_chomped_line_from_file(src_stream)) != NULL) {
150 char *line_ptr = NULL;
151
152 if (line == NULL) {
153 break;
154 } else if (strncmp(line, "begin-base64 ", 13) == 0) {
155 line_ptr = line + 13;
156 decode_fn_ptr = read_base64;
157 } else if (strncmp(line, "begin ", 6) == 0) {
158 line_ptr = line + 6;
159 decode_fn_ptr = read_stduu;
160 }
161
162 if (line_ptr) {
163 FILE *dst_stream;
164 int mode;
165 int ret;
166
167 mode = strtoul(line_ptr, NULL, 8);
168 if (outname == NULL) {
169 outname = strchr(line_ptr, ' ');
170 if ((outname == NULL) || (*outname == '\0')) {
171 break;
172 }
173 outname++;
174 }
175 if (strcmp(outname, "-") == 0) {
176 dst_stream = stdout;
177 } else {
178 dst_stream = bb_xfopen(outname, "w");
179 chmod(outname, mode & (S_IRWXU | S_IRWXG | S_IRWXO));
180 }
181 free(line);
182 ret = decode_fn_ptr(src_stream, dst_stream);
183 bb_fclose_nonstdin(src_stream);
184 return(ret);
185 }
186 free(line);
187 }
188 bb_error_msg_and_die("No `begin' line");
189}
Note: See TracBrowser for help on using the repository browser.