source: MondoRescue/branches/3.3/mindi-busybox/coreutils/uudecode.c@ 3865

Last change on this file since 3865 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

File size: 6.3 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright 2003, Glenn McGrath
4 *
5 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
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//usage:#define uudecode_trivial_usage
15//usage: "[-o OUTFILE] [INFILE]"
16//usage:#define uudecode_full_usage "\n\n"
17//usage: "Uudecode a file\n"
18//usage: "Finds OUTFILE in uuencoded source unless -o is given"
19//usage:
20//usage:#define uudecode_example_usage
21//usage: "$ uudecode -o busybox busybox.uu\n"
22//usage: "$ ls -l busybox\n"
23//usage: "-rwxr-xr-x 1 ams ams 245264 Jun 7 21:35 busybox\n"
24
25#include "libbb.h"
26
27#if ENABLE_UUDECODE
28static void FAST_FUNC read_stduu(FILE *src_stream, FILE *dst_stream, int flags UNUSED_PARAM)
29{
30 char *line;
31
32 for (;;) {
33 int encoded_len, str_len;
34 char *line_ptr, *dst;
35 size_t line_len;
36
37 line_len = 64 * 1024;
38 line = xmalloc_fgets_str_len(src_stream, "\n", &line_len);
39 if (!line)
40 break;
41 /* Handle both Unix and MSDOS text, and stray trailing spaces */
42 str_len = line_len;
43 while (--str_len >= 0 && isspace(line[str_len]))
44 line[str_len] = '\0';
45
46 if (strcmp(line, "end") == 0) {
47 return; /* the only non-error exit */
48 }
49
50 line_ptr = line;
51 while (*line_ptr) {
52 *line_ptr = (*line_ptr - 0x20) & 0x3f;
53 line_ptr++;
54 }
55 str_len = line_ptr - line;
56
57 encoded_len = line[0] * 4 / 3;
58 /* Check that line is not too short. (we tolerate
59 * overly _long_ line to accommodate possible extra '`').
60 * Empty line case is also caught here. */
61 if (str_len <= encoded_len) {
62 break; /* go to bb_error_msg_and_die("short file"); */
63 }
64 if (encoded_len <= 0) {
65 /* Ignore the "`\n" line, why is it even in the encode file ? */
66 free(line);
67 continue;
68 }
69 if (encoded_len > 60) {
70 bb_error_msg_and_die("line too long");
71 }
72
73 dst = line;
74 line_ptr = line + 1;
75 do {
76 /* Merge four 6 bit chars to three 8 bit chars */
77 *dst++ = line_ptr[0] << 2 | line_ptr[1] >> 4;
78 encoded_len--;
79 if (encoded_len == 0) {
80 break;
81 }
82
83 *dst++ = line_ptr[1] << 4 | line_ptr[2] >> 2;
84 encoded_len--;
85 if (encoded_len == 0) {
86 break;
87 }
88
89 *dst++ = line_ptr[2] << 6 | line_ptr[3];
90 line_ptr += 4;
91 encoded_len -= 2;
92 } while (encoded_len > 0);
93 fwrite(line, 1, dst - line, dst_stream);
94 free(line);
95 }
96 bb_error_msg_and_die("short file");
97}
98#endif
99
100#if ENABLE_UUDECODE
101int uudecode_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
102int uudecode_main(int argc UNUSED_PARAM, char **argv)
103{
104 FILE *src_stream;
105 char *outname = NULL;
106 char *line;
107
108 opt_complementary = "?1"; /* 1 argument max */
109 getopt32(argv, "o:", &outname);
110 argv += optind;
111
112 if (!argv[0])
113 *--argv = (char*)"-";
114 src_stream = xfopen_stdin(argv[0]);
115
116 /* Search for the start of the encoding */
117 while ((line = xmalloc_fgetline(src_stream)) != NULL) {
118 void FAST_FUNC (*decode_fn_ptr)(FILE *src, FILE *dst, int flags);
119 char *line_ptr;
120 FILE *dst_stream;
121 int mode;
122
123 if (is_prefixed_with(line, "begin-base64 ")) {
124 line_ptr = line + 13;
125 decode_fn_ptr = read_base64;
126 } else if (is_prefixed_with(line, "begin ")) {
127 line_ptr = line + 6;
128 decode_fn_ptr = read_stduu;
129 } else {
130 free(line);
131 continue;
132 }
133
134 /* begin line found. decode and exit */
135 mode = bb_strtou(line_ptr, NULL, 8);
136 if (outname == NULL) {
137 outname = strchr(line_ptr, ' ');
138 if (!outname)
139 break;
140 outname++;
141 trim(outname); /* remove trailing space (and '\r' for DOS text) */
142 if (!outname[0])
143 break;
144 }
145 dst_stream = stdout;
146 if (NOT_LONE_DASH(outname)) {
147 dst_stream = xfopen_for_write(outname);
148 fchmod(fileno(dst_stream), mode & (S_IRWXU | S_IRWXG | S_IRWXO));
149 }
150 free(line);
151 decode_fn_ptr(src_stream, dst_stream, /*flags:*/ BASE64_FLAG_UU_STOP + BASE64_FLAG_NO_STOP_CHAR);
152 /* fclose_if_not_stdin(src_stream); - redundant */
153 return EXIT_SUCCESS;
154 }
155 bb_error_msg_and_die("no 'begin' line");
156}
157#endif
158
159//applet:IF_BASE64(APPLET(base64, BB_DIR_BIN, BB_SUID_DROP))
160
161//kbuild:lib-$(CONFIG_BASE64) += uudecode.o
162
163//config:config BASE64
164//config: bool "base64"
165//config: default y
166//config: help
167//config: Base64 encode and decode
168
169//usage:#define base64_trivial_usage
170//usage: "[-d] [FILE]"
171//usage:#define base64_full_usage "\n\n"
172//usage: "Base64 encode or decode FILE to standard output"
173//usage: "\n -d Decode data"
174////usage: "\n -w COL Wrap lines at COL (default 76, 0 disables)"
175////usage: "\n -i When decoding, ignore non-alphabet characters"
176
177#if ENABLE_BASE64
178int base64_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
179int base64_main(int argc UNUSED_PARAM, char **argv)
180{
181 FILE *src_stream;
182 unsigned opts;
183
184 opt_complementary = "?1"; /* 1 argument max */
185 opts = getopt32(argv, "d");
186 argv += optind;
187
188 if (!argv[0])
189 *--argv = (char*)"-";
190 src_stream = xfopen_stdin(argv[0]);
191 if (opts) {
192 read_base64(src_stream, stdout, /*flags:*/ (char)EOF);
193 } else {
194 enum {
195 SRC_BUF_SIZE = 76/4*3, /* This *MUST* be a multiple of 3 */
196 DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3),
197 };
198 char src_buf[SRC_BUF_SIZE];
199 char dst_buf[DST_BUF_SIZE + 1];
200 int src_fd = fileno(src_stream);
201 while (1) {
202 size_t size = full_read(src_fd, src_buf, SRC_BUF_SIZE);
203 if (!size)
204 break;
205 if ((ssize_t)size < 0)
206 bb_perror_msg_and_die(bb_msg_read_error);
207 /* Encode the buffer we just read in */
208 bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64);
209 xwrite(STDOUT_FILENO, dst_buf, 4 * ((size + 2) / 3));
210 bb_putchar('\n');
211 fflush(stdout);
212 }
213 }
214
215 fflush_stdout_and_exit(EXIT_SUCCESS);
216}
217#endif
218
219/* Test script.
220Put this into an empty dir with busybox binary, an run.
221
222#!/bin/sh
223test -x busybox || { echo "No ./busybox?"; exit; }
224ln -sf busybox uudecode
225ln -sf busybox uuencode
226>A_null
227echo -n A >A
228echo -n AB >AB
229echo -n ABC >ABC
230echo -n ABCD >ABCD
231echo -n ABCDE >ABCDE
232echo -n ABCDEF >ABCDEF
233cat busybox >A_bbox
234for f in A*; do
235 echo uuencode $f
236 ./uuencode $f <$f >u_$f
237 ./uuencode -m $f <$f >m_$f
238done
239mkdir unpk_u unpk_m 2>/dev/null
240for f in u_*; do
241 ./uudecode <$f -o unpk_u/${f:2}
242 diff -a ${f:2} unpk_u/${f:2} >/dev/null 2>&1
243 echo uudecode $f: $?
244done
245for f in m_*; do
246 ./uudecode <$f -o unpk_m/${f:2}
247 diff -a ${f:2} unpk_m/${f:2} >/dev/null 2>&1
248 echo uudecode $f: $?
249done
250*/
Note: See TracBrowser for help on using the repository browser.