Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/coreutils/uudecode.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 816 - (hide annotations) (download)
Fri Apr 24 18:33:46 2009 UTC (15 years, 2 months ago) by niro
File MIME type: text/plain
File size: 5184 byte(s)
-updated to busybox-1.13.4
1 niro 532 /* vi: set sw=4 ts=4: */
2     /*
3 niro 816 * Copyright 2003, Glenn McGrath
4 niro 532 *
5     * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
6     *
7     * Based on specification from
8     * http://www.opengroup.org/onlinepubs/007904975/utilities/uuencode.html
9     *
10     * Bugs: the spec doesn't mention anything about "`\n`\n" prior to the
11     * "end" line
12     */
13    
14    
15 niro 816 #include "libbb.h"
16 niro 532
17 niro 816 static void read_stduu(FILE *src_stream, FILE *dst_stream)
18 niro 532 {
19     char *line;
20    
21 niro 816 while ((line = xmalloc_fgetline(src_stream)) != NULL) {
22     int encoded_len, str_len;
23     char *line_ptr, *dst;
24 niro 532
25     if (strcmp(line, "end") == 0) {
26 niro 816 return; /* the only non-error exit */
27 niro 532 }
28    
29 niro 816 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) {
44 niro 532 /* Ignore the "`\n" line, why is it even in the encode file ? */
45 niro 816 free(line);
46 niro 532 continue;
47     }
48 niro 816 if (encoded_len > 60) {
49 niro 532 bb_error_msg_and_die("line too long");
50     }
51    
52 niro 816 dst = line;
53     line_ptr = line + 1;
54     do {
55 niro 532 /* Merge four 6 bit chars to three 8 bit chars */
56 niro 816 *dst++ = line_ptr[0] << 2 | line_ptr[1] >> 4;
57     encoded_len--;
58     if (encoded_len == 0) {
59 niro 532 break;
60     }
61    
62 niro 816 *dst++ = line_ptr[1] << 4 | line_ptr[2] >> 2;
63     encoded_len--;
64     if (encoded_len == 0) {
65 niro 532 break;
66     }
67    
68 niro 816 *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 niro 532 free(line);
74     }
75     bb_error_msg_and_die("short file");
76     }
77    
78 niro 816 static void read_base64(FILE *src_stream, FILE *dst_stream)
79 niro 532 {
80 niro 816 int term_count = 1;
81 niro 532
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 niro 816 /* Get next _valid_ character.
91     * global vector bb_uuenc_tbl_base64[] contains this string:
92     * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n"
93     */
94 niro 532 do {
95     ch = fgetc(src_stream);
96     if (ch == EOF) {
97     bb_error_msg_and_die("short file");
98     }
99 niro 816 table_ptr = strchr(bb_uuenc_tbl_base64, ch);
100     } while (table_ptr == NULL);
101 niro 532
102 niro 816 /* Convert encoded character to decimal */
103     ch = table_ptr - bb_uuenc_tbl_base64;
104 niro 532
105     if (*table_ptr == '=') {
106     if (term_count == 0) {
107 niro 816 translated[count] = '\0';
108 niro 532 break;
109     }
110     term_count++;
111 niro 816 } else if (*table_ptr == '\n') {
112 niro 532 /* Check for terminating line */
113     if (term_count == 5) {
114 niro 816 return;
115 niro 532 }
116     term_count = 1;
117     continue;
118     } else {
119     translated[count] = ch;
120     count++;
121     term_count = 0;
122     }
123     }
124    
125     /* Merge 6 bit chars to 8 bit */
126 niro 816 if (count > 1) {
127     fputc(translated[0] << 2 | translated[1] >> 4, dst_stream);
128     }
129 niro 532 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    
138 niro 816 int uudecode_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
139     int uudecode_main(int argc UNUSED_PARAM, char **argv)
140 niro 532 {
141     FILE *src_stream;
142     char *outname = NULL;
143     char *line;
144    
145 niro 816 opt_complementary = "?1"; /* 1 argument max */
146     getopt32(argv, "o:", &outname);
147     argv += optind;
148 niro 532
149 niro 816 if (!*argv)
150     *--argv = (char*)"-";
151     src_stream = xfopen_stdin(*argv);
152 niro 532
153     /* Search for the start of the encoding */
154 niro 816 while ((line = xmalloc_fgetline(src_stream)) != NULL) {
155     void (*decode_fn_ptr)(FILE *src, FILE *dst);
156 niro 532 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 niro 816 /* begin line found. decode and exit */
172     mode = bb_strtou(line_ptr, NULL, 8);
173 niro 532 if (outname == NULL) {
174     outname = strchr(line_ptr, ' ');
175     if ((outname == NULL) || (*outname == '\0')) {
176     break;
177     }
178     outname++;
179     }
180 niro 816 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 niro 532 }
185     free(line);
186 niro 816 decode_fn_ptr(src_stream, dst_stream);
187     /* fclose_if_not_stdin(src_stream); - redundant */
188     return EXIT_SUCCESS;
189 niro 532 }
190     bb_error_msg_and_die("no 'begin' line");
191     }
192 niro 816
193     /* Test script.
194     Put this into an empty dir with busybox binary, an run.
195    
196     #!/bin/sh
197     test -x busybox || { echo "No ./busybox?"; exit; }
198     ln -sf busybox uudecode
199     ln -sf busybox uuencode
200     >A_null
201     echo -n A >A
202     echo -n AB >AB
203     echo -n ABC >ABC
204     echo -n ABCD >ABCD
205     echo -n ABCDE >ABCDE
206     echo -n ABCDEF >ABCDEF
207     cat busybox >A_bbox
208     for f in A*; do
209     echo uuencode $f
210     ./uuencode $f <$f >u_$f
211     ./uuencode -m $f <$f >m_$f
212     done
213     mkdir unpk_u unpk_m 2>/dev/null
214     for f in u_*; do
215     ./uudecode <$f -o unpk_u/${f:2}
216     diff -a ${f:2} unpk_u/${f:2} >/dev/null 2>&1
217     echo uudecode $f: $?
218     done
219     for f in m_*; do
220     ./uudecode <$f -o unpk_m/${f:2}
221     diff -a ${f:2} unpk_m/${f:2} >/dev/null 2>&1
222     echo uudecode $f: $?
223     done
224     */