aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2017-01-08 08:56:43 +0000
committerRon Yorston <rmy@pobox.com>2017-01-08 08:56:43 +0000
commit3ef86d069577b8a44ebe3aa890c6e97ea31d0d56 (patch)
tree064587c9b2080dba963bf8d93861b8019cb306ed
parentc66975af0b5335b9cdd156206767756237bd814b (diff)
parent86584e134eec1a81298149f8c04c77727f6dccb9 (diff)
downloadbusybox-w32-3ef86d069577b8a44ebe3aa890c6e97ea31d0d56.tar.gz
busybox-w32-3ef86d069577b8a44ebe3aa890c6e97ea31d0d56.tar.bz2
busybox-w32-3ef86d069577b8a44ebe3aa890c6e97ea31d0d56.zip
Merge branch 'busybox' into merge
-rwxr-xr-xapplets/usage_compressed3
-rw-r--r--archival/unzip.c286
-rw-r--r--libbb/appletlib.c26
-rw-r--r--modutils/modprobe-small.c4
-rw-r--r--modutils/modutils.c16
-rw-r--r--networking/ntpd.c73
-rw-r--r--networking/udhcp/Config.src54
-rw-r--r--networking/udhcp/d6_dhcpc.c2
-rw-r--r--shell/Config.src27
-rw-r--r--shell/ash.c18
-rw-r--r--shell/ash_test/ash-redir/redir_leak.right6
-rwxr-xr-xshell/ash_test/ash-redir/redir_leak.tests10
-rw-r--r--shell/hush_test/hush-redir/redir_leak.right6
-rwxr-xr-xshell/hush_test/hush-redir/redir_leak.tests10
-rwxr-xr-xtestsuite/unzip.tests6
15 files changed, 337 insertions, 210 deletions
diff --git a/applets/usage_compressed b/applets/usage_compressed
index 186fcde77..36fc2a007 100755
--- a/applets/usage_compressed
+++ b/applets/usage_compressed
@@ -36,6 +36,9 @@ echo ''
36#0000040 114 105 135 040 133 055 141 040 101 103 124 111 117 116 106 111 36#0000040 114 105 135 040 133 055 141 040 101 103 124 111 117 116 106 111
37# 042514 020135 026533 020141 041501 044524 047117 044506 37# 042514 020135 026533 020141 041501 044524 047117 044506
38 38
39echo "#define UNPACKED_USAGE_LENGTH `$loc/usage | wc -c`"
40echo
41
39echo '#define PACKED_USAGE \' 42echo '#define PACKED_USAGE \'
40## Breaks on big-endian systems! 43## Breaks on big-endian systems!
41## # Extra effort to avoid using "od -t x1": -t is not available 44## # Extra effort to avoid using "od -t x1": -t is not available
diff --git a/archival/unzip.c b/archival/unzip.c
index 27adb3420..7029f66c3 100644
--- a/archival/unzip.c
+++ b/archival/unzip.c
@@ -16,7 +16,6 @@
16 * TODO 16 * TODO
17 * Zip64 + other methods 17 * Zip64 + other methods
18 */ 18 */
19
20//config:config UNZIP 19//config:config UNZIP
21//config: bool "unzip" 20//config: bool "unzip"
22//config: default y 21//config: default y
@@ -24,8 +23,17 @@
24//config: unzip will list or extract files from a ZIP archive, 23//config: unzip will list or extract files from a ZIP archive,
25//config: commonly found on DOS/WIN systems. The default behavior 24//config: commonly found on DOS/WIN systems. The default behavior
26//config: (with no options) is to extract the archive into the 25//config: (with no options) is to extract the archive into the
27//config: current directory. Use the `-d' option to extract to a 26//config: current directory.
28//config: directory of your choice. 27//config:
28//config:config FEATURE_UNZIP_CDF
29//config: bool "Read and use Central Directory data"
30//config: default y
31//config: depends on UNZIP
32//config: help
33//config: If you know that you only need to deal with simple
34//config: ZIP files without deleted/updated files, SFX archives etc,
35//config: you can reduce code size by unselecting this option.
36//config: To support less trivial ZIPs, say Y.
29 37
30//applet:IF_UNZIP(APPLET(unzip, BB_DIR_USR_BIN, BB_SUID_DROP)) 38//applet:IF_UNZIP(APPLET(unzip, BB_DIR_USR_BIN, BB_SUID_DROP))
31//kbuild:lib-$(CONFIG_UNZIP) += unzip.o 39//kbuild:lib-$(CONFIG_UNZIP) += unzip.o
@@ -83,30 +91,20 @@ typedef union {
83 uint32_t ucmpsize PACKED; /* 18-21 */ 91 uint32_t ucmpsize PACKED; /* 18-21 */
84 uint16_t filename_len; /* 22-23 */ 92 uint16_t filename_len; /* 22-23 */
85 uint16_t extra_len; /* 24-25 */ 93 uint16_t extra_len; /* 24-25 */
94 /* filename follows (not NUL terminated) */
95 /* extra field follows */
96 /* data follows */
86 } formatted PACKED; 97 } formatted PACKED;
87} zip_header_t; /* PACKED - gcc 4.2.1 doesn't like it (spews warning) */ 98} zip_header_t; /* PACKED - gcc 4.2.1 doesn't like it (spews warning) */
88 99
89/* Check the offset of the last element, not the length. This leniency 100#define FIX_ENDIANNESS_ZIP(zip_header) \
90 * allows for poor packing, whereby the overall struct may be too long, 101do { if (BB_BIG_ENDIAN) { \
91 * even though the elements are all in the right place.
92 */
93struct BUG_zip_header_must_be_26_bytes {
94 char BUG_zip_header_must_be_26_bytes[
95 offsetof(zip_header_t, formatted.extra_len) + 2
96 == ZIP_HEADER_LEN ? 1 : -1];
97};
98
99#define FIX_ENDIANNESS_ZIP(zip_header) do { \
100 (zip_header).formatted.version = SWAP_LE16((zip_header).formatted.version ); \
101 (zip_header).formatted.method = SWAP_LE16((zip_header).formatted.method ); \
102 (zip_header).formatted.modtime = SWAP_LE16((zip_header).formatted.modtime ); \
103 (zip_header).formatted.moddate = SWAP_LE16((zip_header).formatted.moddate ); \
104 (zip_header).formatted.crc32 = SWAP_LE32((zip_header).formatted.crc32 ); \ 102 (zip_header).formatted.crc32 = SWAP_LE32((zip_header).formatted.crc32 ); \
105 (zip_header).formatted.cmpsize = SWAP_LE32((zip_header).formatted.cmpsize ); \ 103 (zip_header).formatted.cmpsize = SWAP_LE32((zip_header).formatted.cmpsize ); \
106 (zip_header).formatted.ucmpsize = SWAP_LE32((zip_header).formatted.ucmpsize ); \ 104 (zip_header).formatted.ucmpsize = SWAP_LE32((zip_header).formatted.ucmpsize ); \
107 (zip_header).formatted.filename_len = SWAP_LE16((zip_header).formatted.filename_len); \ 105 (zip_header).formatted.filename_len = SWAP_LE16((zip_header).formatted.filename_len); \
108 (zip_header).formatted.extra_len = SWAP_LE16((zip_header).formatted.extra_len ); \ 106 (zip_header).formatted.extra_len = SWAP_LE16((zip_header).formatted.extra_len ); \
109} while (0) 107}} while (0)
110 108
111#define CDF_HEADER_LEN 42 109#define CDF_HEADER_LEN 42
112 110
@@ -118,8 +116,8 @@ typedef union {
118 uint16_t version_needed; /* 2-3 */ 116 uint16_t version_needed; /* 2-3 */
119 uint16_t cdf_flags; /* 4-5 */ 117 uint16_t cdf_flags; /* 4-5 */
120 uint16_t method; /* 6-7 */ 118 uint16_t method; /* 6-7 */
121 uint16_t mtime; /* 8-9 */ 119 uint16_t modtime; /* 8-9 */
122 uint16_t mdate; /* 10-11 */ 120 uint16_t moddate; /* 10-11 */
123 uint32_t crc32; /* 12-15 */ 121 uint32_t crc32; /* 12-15 */
124 uint32_t cmpsize; /* 16-19 */ 122 uint32_t cmpsize; /* 16-19 */
125 uint32_t ucmpsize; /* 20-23 */ 123 uint32_t ucmpsize; /* 20-23 */
@@ -130,27 +128,27 @@ typedef union {
130 uint16_t internal_file_attributes; /* 32-33 */ 128 uint16_t internal_file_attributes; /* 32-33 */
131 uint32_t external_file_attributes PACKED; /* 34-37 */ 129 uint32_t external_file_attributes PACKED; /* 34-37 */
132 uint32_t relative_offset_of_local_header PACKED; /* 38-41 */ 130 uint32_t relative_offset_of_local_header PACKED; /* 38-41 */
131 /* filename follows (not NUL terminated) */
132 /* extra field follows */
133 /* comment follows */
133 } formatted PACKED; 134 } formatted PACKED;
134} cdf_header_t; 135} cdf_header_t;
135 136
136struct BUG_cdf_header_must_be_42_bytes { 137#define FIX_ENDIANNESS_CDF(cdf_header) \
137 char BUG_cdf_header_must_be_42_bytes[ 138do { if (BB_BIG_ENDIAN) { \
138 offsetof(cdf_header_t, formatted.relative_offset_of_local_header) + 4 139 (cdf_header).formatted.version_made_by = SWAP_LE16((cdf_header).formatted.version_made_by); \
139 == CDF_HEADER_LEN ? 1 : -1]; 140 (cdf_header).formatted.version_needed = SWAP_LE16((cdf_header).formatted.version_needed); \
140}; 141 (cdf_header).formatted.method = SWAP_LE16((cdf_header).formatted.method ); \
141 142 (cdf_header).formatted.modtime = SWAP_LE16((cdf_header).formatted.modtime ); \
142#define FIX_ENDIANNESS_CDF(cdf_header) do { \ 143 (cdf_header).formatted.moddate = SWAP_LE16((cdf_header).formatted.moddate ); \
143 (cdf_header).formatted.crc32 = SWAP_LE32((cdf_header).formatted.crc32 ); \ 144 (cdf_header).formatted.crc32 = SWAP_LE32((cdf_header).formatted.crc32 ); \
144 (cdf_header).formatted.cmpsize = SWAP_LE32((cdf_header).formatted.cmpsize ); \ 145 (cdf_header).formatted.cmpsize = SWAP_LE32((cdf_header).formatted.cmpsize ); \
145 (cdf_header).formatted.ucmpsize = SWAP_LE32((cdf_header).formatted.ucmpsize ); \ 146 (cdf_header).formatted.ucmpsize = SWAP_LE32((cdf_header).formatted.ucmpsize ); \
146 (cdf_header).formatted.file_name_length = SWAP_LE16((cdf_header).formatted.file_name_length); \ 147 (cdf_header).formatted.file_name_length = SWAP_LE16((cdf_header).formatted.file_name_length); \
147 (cdf_header).formatted.extra_field_length = SWAP_LE16((cdf_header).formatted.extra_field_length); \ 148 (cdf_header).formatted.extra_field_length = SWAP_LE16((cdf_header).formatted.extra_field_length); \
148 (cdf_header).formatted.file_comment_length = SWAP_LE16((cdf_header).formatted.file_comment_length); \ 149 (cdf_header).formatted.file_comment_length = SWAP_LE16((cdf_header).formatted.file_comment_length); \
149 IF_DESKTOP( \
150 (cdf_header).formatted.version_made_by = SWAP_LE16((cdf_header).formatted.version_made_by); \
151 (cdf_header).formatted.external_file_attributes = SWAP_LE32((cdf_header).formatted.external_file_attributes); \ 150 (cdf_header).formatted.external_file_attributes = SWAP_LE32((cdf_header).formatted.external_file_attributes); \
152 ) \ 151}} while (0)
153} while (0)
154 152
155#define CDE_HEADER_LEN 16 153#define CDE_HEADER_LEN 16
156 154
@@ -169,20 +167,38 @@ typedef union {
169 } formatted PACKED; 167 } formatted PACKED;
170} cde_header_t; 168} cde_header_t;
171 169
172struct BUG_cde_header_must_be_16_bytes { 170#define FIX_ENDIANNESS_CDE(cde_header) \
171do { if (BB_BIG_ENDIAN) { \
172 (cde_header).formatted.cdf_offset = SWAP_LE32((cde_header).formatted.cdf_offset); \
173}} while (0)
174
175struct BUG {
176 /* Check the offset of the last element, not the length. This leniency
177 * allows for poor packing, whereby the overall struct may be too long,
178 * even though the elements are all in the right place.
179 */
180 char BUG_zip_header_must_be_26_bytes[
181 offsetof(zip_header_t, formatted.extra_len) + 2
182 == ZIP_HEADER_LEN ? 1 : -1];
183 char BUG_cdf_header_must_be_42_bytes[
184 offsetof(cdf_header_t, formatted.relative_offset_of_local_header) + 4
185 == CDF_HEADER_LEN ? 1 : -1];
173 char BUG_cde_header_must_be_16_bytes[ 186 char BUG_cde_header_must_be_16_bytes[
174 sizeof(cde_header_t) == CDE_HEADER_LEN ? 1 : -1]; 187 sizeof(cde_header_t) == CDE_HEADER_LEN ? 1 : -1];
175}; 188};
176 189
177#define FIX_ENDIANNESS_CDE(cde_header) do { \
178 (cde_header).formatted.cdf_offset = SWAP_LE32((cde_header).formatted.cdf_offset); \
179} while (0)
180 190
181enum { zip_fd = 3 }; 191enum { zip_fd = 3 };
182 192
183 193
184#if ENABLE_DESKTOP 194/* This value means that we failed to find CDF */
195#define BAD_CDF_OFFSET ((uint32_t)0xffffffff)
196
197#if !ENABLE_FEATURE_UNZIP_CDF
198
199# define find_cdf_offset() BAD_CDF_OFFSET
185 200
201#else
186/* Seen in the wild: 202/* Seen in the wild:
187 * Self-extracting PRO2K3XP_32.exe contains 19078464 byte zip archive, 203 * Self-extracting PRO2K3XP_32.exe contains 19078464 byte zip archive,
188 * where CDE was nearly 48 kbytes before EOF. 204 * where CDE was nearly 48 kbytes before EOF.
@@ -191,25 +207,26 @@ enum { zip_fd = 3 };
191 * To make extraction work, bumped PEEK_FROM_END from 16k to 64k. 207 * To make extraction work, bumped PEEK_FROM_END from 16k to 64k.
192 */ 208 */
193#define PEEK_FROM_END (64*1024) 209#define PEEK_FROM_END (64*1024)
194
195/* This value means that we failed to find CDF */
196#define BAD_CDF_OFFSET ((uint32_t)0xffffffff)
197
198/* NB: does not preserve file position! */ 210/* NB: does not preserve file position! */
199static uint32_t find_cdf_offset(void) 211static uint32_t find_cdf_offset(void)
200{ 212{
201 cde_header_t cde_header; 213 cde_header_t cde_header;
214 unsigned char *buf;
202 unsigned char *p; 215 unsigned char *p;
203 off_t end; 216 off_t end;
204 unsigned char *buf = xzalloc(PEEK_FROM_END);
205 uint32_t found; 217 uint32_t found;
206 218
207 end = xlseek(zip_fd, 0, SEEK_END); 219 end = lseek(zip_fd, 0, SEEK_END);
220 if (end == (off_t) -1)
221 return BAD_CDF_OFFSET;
222
208 end -= PEEK_FROM_END; 223 end -= PEEK_FROM_END;
209 if (end < 0) 224 if (end < 0)
210 end = 0; 225 end = 0;
226
211 dbg("Looking for cdf_offset starting from 0x%"OFF_FMT"x", end); 227 dbg("Looking for cdf_offset starting from 0x%"OFF_FMT"x", end);
212 xlseek(zip_fd, end, SEEK_SET); 228 xlseek(zip_fd, end, SEEK_SET);
229 buf = xzalloc(PEEK_FROM_END);
213 full_read(zip_fd, buf, PEEK_FROM_END); 230 full_read(zip_fd, buf, PEEK_FROM_END);
214 231
215 found = BAD_CDF_OFFSET; 232 found = BAD_CDF_OFFSET;
@@ -254,31 +271,32 @@ static uint32_t find_cdf_offset(void)
254 271
255static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr) 272static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr)
256{ 273{
257 off_t org; 274 uint32_t magic;
258 275
259 org = xlseek(zip_fd, 0, SEEK_CUR); 276 if (cdf_offset == BAD_CDF_OFFSET)
260 277 return cdf_offset;
261 if (!cdf_offset) 278
262 cdf_offset = find_cdf_offset(); 279 dbg("Reading CDF at 0x%x", (unsigned)cdf_offset);
263 280 xlseek(zip_fd, cdf_offset, SEEK_SET);
264 if (cdf_offset != BAD_CDF_OFFSET) { 281 xread(zip_fd, &magic, 4);
265 dbg("Reading CDF at 0x%x", (unsigned)cdf_offset); 282 /* Central Directory End? */
266 xlseek(zip_fd, cdf_offset + 4, SEEK_SET); 283 if (magic == ZIP_CDE_MAGIC) {
267 xread(zip_fd, cdf_ptr->raw, CDF_HEADER_LEN); 284 dbg("got ZIP_CDE_MAGIC");
268 FIX_ENDIANNESS_CDF(*cdf_ptr); 285 return 0; /* EOF */
269 dbg(" file_name_length:%u extra_field_length:%u file_comment_length:%u",
270 (unsigned)cdf_ptr->formatted.file_name_length,
271 (unsigned)cdf_ptr->formatted.extra_field_length,
272 (unsigned)cdf_ptr->formatted.file_comment_length
273 );
274 cdf_offset += 4 + CDF_HEADER_LEN
275 + cdf_ptr->formatted.file_name_length
276 + cdf_ptr->formatted.extra_field_length
277 + cdf_ptr->formatted.file_comment_length;
278 } 286 }
287 xread(zip_fd, cdf_ptr->raw, CDF_HEADER_LEN);
288
289 FIX_ENDIANNESS_CDF(*cdf_ptr);
290 dbg(" file_name_length:%u extra_field_length:%u file_comment_length:%u",
291 (unsigned)cdf_ptr->formatted.file_name_length,
292 (unsigned)cdf_ptr->formatted.extra_field_length,
293 (unsigned)cdf_ptr->formatted.file_comment_length
294 );
295 cdf_offset += 4 + CDF_HEADER_LEN
296 + cdf_ptr->formatted.file_name_length
297 + cdf_ptr->formatted.extra_field_length
298 + cdf_ptr->formatted.file_comment_length;
279 299
280 dbg("Returning file position to 0x%"OFF_FMT"x", org);
281 xlseek(zip_fd, org, SEEK_SET);
282 return cdf_offset; 300 return cdf_offset;
283}; 301};
284#endif 302#endif
@@ -327,6 +345,7 @@ static void unzip_extract(zip_header_t *zip_header, int dst_fd)
327 bb_error_msg("bad length"); 345 bb_error_msg("bad length");
328 } 346 }
329 } 347 }
348 /* TODO? method 12: bzip2, method 14: LZMA */
330} 349}
331 350
332static void my_fgets80(char *buf80) 351static void my_fgets80(char *buf80)
@@ -342,15 +361,12 @@ int unzip_main(int argc, char **argv)
342{ 361{
343 enum { O_PROMPT, O_NEVER, O_ALWAYS }; 362 enum { O_PROMPT, O_NEVER, O_ALWAYS };
344 363
345 zip_header_t zip_header;
346 smallint quiet = 0; 364 smallint quiet = 0;
347 IF_NOT_DESKTOP(const) smallint verbose = 0; 365 IF_NOT_FEATURE_UNZIP_CDF(const) smallint verbose = 0;
348 smallint listing = 0; 366 smallint listing = 0;
349 smallint overwrite = O_PROMPT; 367 smallint overwrite = O_PROMPT;
350 smallint x_opt_seen; 368 smallint x_opt_seen;
351#if ENABLE_DESKTOP
352 uint32_t cdf_offset; 369 uint32_t cdf_offset;
353#endif
354 unsigned long total_usize; 370 unsigned long total_usize;
355 unsigned long total_size; 371 unsigned long total_size;
356 unsigned total_entries; 372 unsigned total_entries;
@@ -433,7 +449,7 @@ int unzip_main(int argc, char **argv)
433 break; 449 break;
434 450
435 case 'v': /* Verbose list */ 451 case 'v': /* Verbose list */
436 IF_DESKTOP(verbose++;) 452 IF_FEATURE_UNZIP_CDF(verbose++;)
437 listing = 1; 453 listing = 1;
438 break; 454 break;
439 455
@@ -548,78 +564,102 @@ int unzip_main(int argc, char **argv)
548 total_usize = 0; 564 total_usize = 0;
549 total_size = 0; 565 total_size = 0;
550 total_entries = 0; 566 total_entries = 0;
551#if ENABLE_DESKTOP 567 cdf_offset = find_cdf_offset(); /* try to seek to the end, find CDE and CDF start */
552 cdf_offset = 0;
553#endif
554 while (1) { 568 while (1) {
555 uint32_t magic; 569 zip_header_t zip_header;
556 mode_t dir_mode = 0777; 570 mode_t dir_mode = 0777;
557#if ENABLE_DESKTOP 571#if ENABLE_FEATURE_UNZIP_CDF
558 mode_t file_mode = 0666; 572 mode_t file_mode = 0666;
559#endif 573#endif
560 574
561 /* Check magic number */ 575 if (!ENABLE_FEATURE_UNZIP_CDF || cdf_offset == BAD_CDF_OFFSET) {
562 xread(zip_fd, &magic, 4); 576 /* Normally happens when input is unseekable.
563 /* Central directory? It's at the end, so exit */ 577 *
564 if (magic == ZIP_CDF_MAGIC) { 578 * Valid ZIP file has Central Directory at the end
565 dbg("got ZIP_CDF_MAGIC"); 579 * with central directory file headers (CDFs).
566 break; 580 * After it, there is a Central Directory End structure.
567 } 581 * CDFs identify what files are in the ZIP and where
568#if ENABLE_DESKTOP 582 * they are located. This allows ZIP readers to load
569 /* Data descriptor? It was a streaming file, go on */ 583 * the list of files without reading the entire ZIP archive.
570 if (magic == ZIP_DD_MAGIC) { 584 * ZIP files may be appended to, only files specified in
571 dbg("got ZIP_DD_MAGIC"); 585 * the CD are valid. Scanning for local file headers is
572 /* skip over duplicate crc32, cmpsize and ucmpsize */ 586 * not a correct algorithm.
573 unzip_skip(3 * 4); 587 *
574 continue; 588 * We try to do the above, and resort to "linear" reading
575 } 589 * of ZIP file only if seek failed or CDE wasn't found.
576#endif 590 */
577 if (magic != ZIP_FILEHEADER_MAGIC) 591 uint32_t magic;
578 bb_error_msg_and_die("invalid zip magic %08X", (int)magic);
579 dbg("got ZIP_FILEHEADER_MAGIC");
580
581 /* Read the file header */
582 xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN);
583 FIX_ENDIANNESS_ZIP(zip_header);
584 if ((zip_header.formatted.method != 0) && (zip_header.formatted.method != 8)) {
585 bb_error_msg_and_die("unsupported method %d", zip_header.formatted.method);
586 }
587#if !ENABLE_DESKTOP
588 if (zip_header.formatted.zip_flags & SWAP_LE16(0x0009)) {
589 bb_error_msg_and_die("zip flags 1 and 8 are not supported");
590 }
591#else
592 if (zip_header.formatted.zip_flags & SWAP_LE16(0x0001)) {
593 /* 0x0001 - encrypted */
594 bb_error_msg_and_die("zip flag 1 (encryption) is not supported");
595 }
596 592
597 if (cdf_offset != BAD_CDF_OFFSET) { 593 /* Check magic number */
594 xread(zip_fd, &magic, 4);
595 /* Central directory? It's at the end, so exit */
596 if (magic == ZIP_CDF_MAGIC) {
597 dbg("got ZIP_CDF_MAGIC");
598 break;
599 }
600 /* Data descriptor? It was a streaming file, go on */
601 if (magic == ZIP_DD_MAGIC) {
602 dbg("got ZIP_DD_MAGIC");
603 /* skip over duplicate crc32, cmpsize and ucmpsize */
604 unzip_skip(3 * 4);
605 continue;
606 }
607 if (magic != ZIP_FILEHEADER_MAGIC)
608 bb_error_msg_and_die("invalid zip magic %08X", (int)magic);
609 dbg("got ZIP_FILEHEADER_MAGIC");
610
611 xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN);
612 FIX_ENDIANNESS_ZIP(zip_header);
613 if ((zip_header.formatted.method != 0)
614 && (zip_header.formatted.method != 8)
615 ) {
616 /* TODO? method 12: bzip2, method 14: LZMA */
617 bb_error_msg_and_die("unsupported method %d", zip_header.formatted.method);
618 }
619 if (zip_header.formatted.zip_flags & SWAP_LE16(0x0009)) {
620 bb_error_msg_and_die("zip flags 1 and 8 are not supported");
621 }
622 }
623#if ENABLE_FEATURE_UNZIP_CDF
624 else {
625 /* cdf_offset is valid (and we know the file is seekable) */
598 cdf_header_t cdf_header; 626 cdf_header_t cdf_header;
599 cdf_offset = read_next_cdf(cdf_offset, &cdf_header); 627 cdf_offset = read_next_cdf(cdf_offset, &cdf_header);
600 /* 628 if (cdf_offset == 0) /* EOF? */
601 * Note: cdf_offset can become BAD_CDF_OFFSET after the above call. 629 break;
602 */ 630# if 0
631 xlseek(zip_fd,
632 SWAP_LE32(cdf_header.formatted.relative_offset_of_local_header) + 4,
633 SEEK_SET);
634 xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN);
635 FIX_ENDIANNESS_ZIP(zip_header);
603 if (zip_header.formatted.zip_flags & SWAP_LE16(0x0008)) { 636 if (zip_header.formatted.zip_flags & SWAP_LE16(0x0008)) {
604 /* 0x0008 - streaming. [u]cmpsize can be reliably gotten 637 /* 0x0008 - streaming. [u]cmpsize can be reliably gotten
605 * only from Central Directory. See unzip_doc.txt 638 * only from Central Directory.
606 */ 639 */
607 zip_header.formatted.crc32 = cdf_header.formatted.crc32; 640 zip_header.formatted.crc32 = cdf_header.formatted.crc32;
608 zip_header.formatted.cmpsize = cdf_header.formatted.cmpsize; 641 zip_header.formatted.cmpsize = cdf_header.formatted.cmpsize;
609 zip_header.formatted.ucmpsize = cdf_header.formatted.ucmpsize; 642 zip_header.formatted.ucmpsize = cdf_header.formatted.ucmpsize;
610 } 643 }
644# else
645 /* CDF has the same data as local header, no need to read the latter */
646 memcpy(&zip_header.formatted.version,
647 &cdf_header.formatted.version_needed, ZIP_HEADER_LEN);
648 xlseek(zip_fd,
649 SWAP_LE32(cdf_header.formatted.relative_offset_of_local_header) + 4 + ZIP_HEADER_LEN,
650 SEEK_SET);
651# endif
611 if ((cdf_header.formatted.version_made_by >> 8) == 3) { 652 if ((cdf_header.formatted.version_made_by >> 8) == 3) {
612 /* This archive is created on Unix */ 653 /* This archive is created on Unix */
613 dir_mode = file_mode = (cdf_header.formatted.external_file_attributes >> 16); 654 dir_mode = file_mode = (cdf_header.formatted.external_file_attributes >> 16);
614 } 655 }
615 } 656 }
616 if (cdf_offset == BAD_CDF_OFFSET
617 && (zip_header.formatted.zip_flags & SWAP_LE16(0x0008))
618 ) {
619 /* If it's a streaming zip, we _require_ CDF */
620 bb_error_msg_and_die("can't find file table");
621 }
622#endif 657#endif
658
659 if (zip_header.formatted.zip_flags & SWAP_LE16(0x0001)) {
660 /* 0x0001 - encrypted */
661 bb_error_msg_and_die("zip flag 1 (encryption) is not supported");
662 }
623 dbg("File cmpsize:0x%x extra_len:0x%x ucmpsize:0x%x", 663 dbg("File cmpsize:0x%x extra_len:0x%x ucmpsize:0x%x",
624 (unsigned)zip_header.formatted.cmpsize, 664 (unsigned)zip_header.formatted.cmpsize,
625 (unsigned)zip_header.formatted.extra_len, 665 (unsigned)zip_header.formatted.extra_len,
@@ -754,7 +794,7 @@ int unzip_main(int argc, char **argv)
754 overwrite = O_ALWAYS; 794 overwrite = O_ALWAYS;
755 case 'y': /* Open file and fall into unzip */ 795 case 'y': /* Open file and fall into unzip */
756 unzip_create_leading_dirs(dst_fn); 796 unzip_create_leading_dirs(dst_fn);
757#if ENABLE_DESKTOP 797#if ENABLE_FEATURE_UNZIP_CDF
758 dst_fd = xopen3(dst_fn, O_WRONLY | O_CREAT | O_TRUNC, file_mode); 798 dst_fd = xopen3(dst_fn, O_WRONLY | O_CREAT | O_TRUNC, file_mode);
759#else 799#else
760 dst_fd = xopen(dst_fn, O_WRONLY | O_CREAT | O_TRUNC); 800 dst_fd = xopen(dst_fn, O_WRONLY | O_CREAT | O_TRUNC);
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index f11384962..6732f89a9 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -52,6 +52,32 @@
52 52
53#include "usage_compressed.h" 53#include "usage_compressed.h"
54 54
55
56/* "Do not compress usage text if uncompressed text is small
57 * and we don't include bunzip2 code for other reasons"
58 *
59 * Useful for mass one-applet rebuild (bunzip2 code is ~2.7k).
60 *
61 * Unlike BUNZIP2, if FEATURE_SEAMLESS_BZ2 is on, bunzip2 code is built but
62 * still may be unused if none of the selected applets calls open_zipped()
63 * or its friends; we test for (FEATURE_SEAMLESS_BZ2 && <APPLET>) instead.
64 * For example, only if TAR and FEATURE_SEAMLESS_BZ2 are both selected,
65 * then bunzip2 code will be linked in anyway, and disabling help compression
66 * would be not optimal:
67 */
68#if UNPACKED_USAGE_LENGTH < 4*1024 \
69 && !(ENABLE_FEATURE_SEAMLESS_BZ2 && ENABLE_TAR) \
70 && !(ENABLE_FEATURE_SEAMLESS_BZ2 && ENABLE_MODPROBE) \
71 && !(ENABLE_FEATURE_SEAMLESS_BZ2 && ENABLE_INSMOD) \
72 && !(ENABLE_FEATURE_SEAMLESS_BZ2 && ENABLE_DEPMOD) \
73 && !(ENABLE_FEATURE_SEAMLESS_BZ2 && ENABLE_MAN) \
74 && !ENABLE_BUNZIP2 \
75 && !ENABLE_BZCAT
76# undef ENABLE_FEATURE_COMPRESS_USAGE
77# define ENABLE_FEATURE_COMPRESS_USAGE 0
78#endif
79
80
55#if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE 81#if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE
56static const char usage_messages[] ALIGN1 = UNPACKED_USAGE; 82static const char usage_messages[] ALIGN1 = UNPACKED_USAGE;
57#else 83#else
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c
index 652ff4dfa..0fc9ea454 100644
--- a/modutils/modprobe-small.c
+++ b/modutils/modprobe-small.c
@@ -39,8 +39,8 @@
39#include <fnmatch.h> 39#include <fnmatch.h>
40#include <sys/syscall.h> 40#include <sys/syscall.h>
41 41
42extern int init_module(void *module, unsigned long len, const char *options); 42#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
43extern int delete_module(const char *module, unsigned flags); 43#define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags)
44#ifdef __NR_finit_module 44#ifdef __NR_finit_module
45# define finit_module(fd, uargs, flags) syscall(__NR_finit_module, fd, uargs, flags) 45# define finit_module(fd, uargs, flags) syscall(__NR_finit_module, fd, uargs, flags)
46#endif 46#endif
diff --git a/modutils/modutils.c b/modutils/modutils.c
index d36caaf68..4204f06fe 100644
--- a/modutils/modutils.c
+++ b/modutils/modutils.c
@@ -7,17 +7,13 @@
7 */ 7 */
8#include "modutils.h" 8#include "modutils.h"
9 9
10#ifdef __UCLIBC__ 10#include <sys/syscall.h>
11extern int init_module(void *module, unsigned long len, const char *options); 11
12extern int delete_module(const char *module, unsigned int flags); 12#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
13#else 13#if defined(__NR_finit_module)
14# include <sys/syscall.h> 14# define finit_module(fd, uargs, flags) syscall(__NR_finit_module, fd, uargs, flags)
15# define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
16# if defined(__NR_finit_module)
17# define finit_module(fd, uargs, flags) syscall(__NR_finit_module, fd, uargs, flags)
18# endif
19# define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags)
20#endif 15#endif
16#define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags)
21 17
22static module_entry *helper_get_module(module_db *db, const char *module, int create) 18static module_entry *helper_get_module(module_db *db, const char *module, int create)
23{ 19{
diff --git a/networking/ntpd.c b/networking/ntpd.c
index b7fa5dce9..bfd5705fc 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -155,6 +155,7 @@
155#define RETRY_INTERVAL 32 /* on send/recv error, retry in N secs (need to be power of 2) */ 155#define RETRY_INTERVAL 32 /* on send/recv error, retry in N secs (need to be power of 2) */
156#define NOREPLY_INTERVAL 512 /* sent, but got no reply: cap next query by this many seconds */ 156#define NOREPLY_INTERVAL 512 /* sent, but got no reply: cap next query by this many seconds */
157#define RESPONSE_INTERVAL 16 /* wait for reply up to N secs */ 157#define RESPONSE_INTERVAL 16 /* wait for reply up to N secs */
158#define HOSTNAME_INTERVAL 5 /* hostname lookup failed. Wait N secs for next try */
158 159
159/* Step threshold (sec). std ntpd uses 0.128. 160/* Step threshold (sec). std ntpd uses 0.128.
160 */ 161 */
@@ -790,28 +791,20 @@ reset_peer_stats(peer_t *p, double offset)
790 VERB6 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time); 791 VERB6 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time);
791} 792}
792 793
793static void 794static len_and_sockaddr*
794resolve_peer_hostname(peer_t *p, int loop_on_fail) 795resolve_peer_hostname(peer_t *p)
795{ 796{
796 len_and_sockaddr *lsa; 797 len_and_sockaddr *lsa = host2sockaddr(p->p_hostname, 123);
797 798 if (lsa) {
798 again: 799 free(p->p_lsa);
799 lsa = host2sockaddr(p->p_hostname, 123); 800 free(p->p_dotted);
800 if (!lsa) { 801 p->p_lsa = lsa;
801 /* error message already emitted by host2sockaddr() */ 802 p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
802 if (!loop_on_fail) 803 } else {
803 return; 804 /* error message is emitted by host2sockaddr() */
804//FIXME: do this to avoid infinite looping on typo in a hostname? 805 set_next(p, HOSTNAME_INTERVAL);
805//well... in which case, what is a good value for loop_on_fail?
806 //if (--loop_on_fail == 0)
807 // xfunc_die();
808 sleep(5);
809 goto again;
810 } 806 }
811 free(p->p_lsa); 807 return lsa;
812 free(p->p_dotted);
813 p->p_lsa = lsa;
814 p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
815} 808}
816 809
817static void 810static void
@@ -822,28 +815,28 @@ add_peers(const char *s)
822 815
823 p = xzalloc(sizeof(*p) + strlen(s)); 816 p = xzalloc(sizeof(*p) + strlen(s));
824 strcpy(p->p_hostname, s); 817 strcpy(p->p_hostname, s);
825 resolve_peer_hostname(p, /*loop_on_fail=*/ 1); 818 p->p_fd = -1;
819 p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3);
820 p->next_action_time = G.cur_time; /* = set_next(p, 0); */
821 reset_peer_stats(p, STEP_THRESHOLD);
826 822
827 /* Names like N.<country2chars>.pool.ntp.org are randomly resolved 823 /* Names like N.<country2chars>.pool.ntp.org are randomly resolved
828 * to a pool of machines. Sometimes different N's resolve to the same IP. 824 * to a pool of machines. Sometimes different N's resolve to the same IP.
829 * It is not useful to have two peers with same IP. We skip duplicates. 825 * It is not useful to have two peers with same IP. We skip duplicates.
830 */ 826 */
831 for (item = G.ntp_peers; item != NULL; item = item->link) { 827 if (resolve_peer_hostname(p)) {
832 peer_t *pp = (peer_t *) item->data; 828 for (item = G.ntp_peers; item != NULL; item = item->link) {
833 if (strcmp(p->p_dotted, pp->p_dotted) == 0) { 829 peer_t *pp = (peer_t *) item->data;
834 bb_error_msg("duplicate peer %s (%s)", s, p->p_dotted); 830 if (pp->p_dotted && strcmp(p->p_dotted, pp->p_dotted) == 0) {
835 free(p->p_lsa); 831 bb_error_msg("duplicate peer %s (%s)", s, p->p_dotted);
836 free(p->p_dotted); 832 free(p->p_lsa);
837 free(p); 833 free(p->p_dotted);
838 return; 834 free(p);
835 return;
836 }
839 } 837 }
840 } 838 }
841 839
842 p->p_fd = -1;
843 p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3);
844 p->next_action_time = G.cur_time; /* = set_next(p, 0); */
845 reset_peer_stats(p, STEP_THRESHOLD);
846
847 llist_add_to(&G.ntp_peers, p); 840 llist_add_to(&G.ntp_peers, p);
848 G.peer_cnt++; 841 G.peer_cnt++;
849} 842}
@@ -871,6 +864,11 @@ do_sendto(int fd,
871static void 864static void
872send_query_to_peer(peer_t *p) 865send_query_to_peer(peer_t *p)
873{ 866{
867 if (!p->p_lsa) {
868 if (!resolve_peer_hostname(p))
869 return;
870 }
871
874 /* Why do we need to bind()? 872 /* Why do we need to bind()?
875 * See what happens when we don't bind: 873 * See what happens when we don't bind:
876 * 874 *
@@ -2238,7 +2236,7 @@ static NOINLINE void ntp_init(char **argv)
2238 IF_FEATURE_NTPD_SERVER("I:") /* compat */ 2236 IF_FEATURE_NTPD_SERVER("I:") /* compat */
2239 "d" /* compat */ 2237 "d" /* compat */
2240 "46aAbgL", /* compat, ignored */ 2238 "46aAbgL", /* compat, ignored */
2241 &peers,&G.script_name, 2239 &peers, &G.script_name,
2242#if ENABLE_FEATURE_NTPD_SERVER 2240#if ENABLE_FEATURE_NTPD_SERVER
2243 &G.if_name, 2241 &G.if_name,
2244#endif 2242#endif
@@ -2263,9 +2261,6 @@ static NOINLINE void ntp_init(char **argv)
2263 if (opts & OPT_N) 2261 if (opts & OPT_N)
2264 setpriority(PRIO_PROCESS, 0, -15); 2262 setpriority(PRIO_PROCESS, 0, -15);
2265 2263
2266 /* add_peers() calls can retry DNS resolution (possibly forever).
2267 * Daemonize before them, or else boot can stall forever.
2268 */
2269 if (!(opts & OPT_n)) { 2264 if (!(opts & OPT_n)) {
2270 bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv); 2265 bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv);
2271 logmode = LOGMODE_NONE; 2266 logmode = LOGMODE_NONE;
@@ -2400,7 +2395,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
2400 2395
2401 /* What if don't see it because it changed its IP? */ 2396 /* What if don't see it because it changed its IP? */
2402 if (p->reachable_bits == 0) 2397 if (p->reachable_bits == 0)
2403 resolve_peer_hostname(p, /*loop_on_fail=*/ 0); 2398 resolve_peer_hostname(p);
2404 2399
2405 set_next(p, timeout); 2400 set_next(p, timeout);
2406 } 2401 }
diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src
index 90fb313b5..7bc13a719 100644
--- a/networking/udhcp/Config.src
+++ b/networking/udhcp/Config.src
@@ -6,29 +6,13 @@
6INSERT 6INSERT
7 7
8config UDHCPD 8config UDHCPD
9 bool "udhcp server (udhcpd)" 9 bool "udhcpd (DHCP server)"
10 default y 10 default y
11 select PLATFORM_LINUX 11 select PLATFORM_LINUX
12 help 12 help
13 udhcpd is a DHCP server geared primarily toward embedded systems, 13 udhcpd is a DHCP server geared primarily toward embedded systems,
14 while striving to be fully functional and RFC compliant. 14 while striving to be fully functional and RFC compliant.
15 15
16config DHCPRELAY
17 bool "dhcprelay"
18 default y
19 help
20 dhcprelay listens for dhcp requests on one or more interfaces
21 and forwards these requests to a different interface or dhcp
22 server.
23
24config DUMPLEASES
25 bool "Lease display utility (dumpleases)"
26 default y
27 help
28 dumpleases displays the leases written out by the udhcpd server.
29 Lease times are stored in the file by time remaining in lease, or
30 by the absolute time that it expires in seconds from epoch.
31
32config FEATURE_UDHCPD_WRITE_LEASES_EARLY 16config FEATURE_UDHCPD_WRITE_LEASES_EARLY
33 bool "Rewrite the lease file at every new acknowledge" 17 bool "Rewrite the lease file at every new acknowledge"
34 default y 18 default y
@@ -61,8 +45,24 @@ config DHCPD_LEASES_FILE
61 udhcpd stores addresses in a lease file. This is the absolute path 45 udhcpd stores addresses in a lease file. This is the absolute path
62 of the file. Normally it is safe to leave it untouched. 46 of the file. Normally it is safe to leave it untouched.
63 47
48config DUMPLEASES
49 bool "dumpleases"
50 default y
51 help
52 dumpleases displays the leases written out by the udhcpd.
53 Lease times are stored in the file by time remaining in lease, or
54 by the absolute time that it expires in seconds from epoch.
55
56config DHCPRELAY
57 bool "dhcprelay"
58 default y
59 help
60 dhcprelay listens for dhcp requests on one or more interfaces
61 and forwards these requests to a different interface or dhcp
62 server.
63
64config UDHCPC 64config UDHCPC
65 bool "udhcp client (udhcpc)" 65 bool "udhcpc (DHCP client)"
66 default y 66 default y
67 select PLATFORM_LINUX 67 select PLATFORM_LINUX
68 help 68 help
@@ -93,6 +93,15 @@ config FEATURE_UDHCPC_SANITIZEOPT
93 they will be replaced with string "bad" when exporting 93 they will be replaced with string "bad" when exporting
94 to the environment. 94 to the environment.
95 95
96config UDHCPC_DEFAULT_SCRIPT
97 string "Absolute path to config script"
98 default "/usr/share/udhcpc/default.script"
99 depends on UDHCPC
100 help
101 This script is called after udhcpc receives an answer. See
102 examples/udhcp for a working example. Normally it is safe
103 to leave this untouched.
104
96config FEATURE_UDHCP_PORT 105config FEATURE_UDHCP_PORT
97 bool "Enable '-P port' option for udhcpd and udhcpc" 106 bool "Enable '-P port' option for udhcpd and udhcpc"
98 default n 107 default n
@@ -130,15 +139,6 @@ config FEATURE_UDHCP_8021Q
130 If selected, both client and server will support passing of VLAN 139 If selected, both client and server will support passing of VLAN
131 ID and priority via options 132 and 133 as per 802.1Q. 140 ID and priority via options 132 and 133 as per 802.1Q.
132 141
133config UDHCPC_DEFAULT_SCRIPT
134 string "Absolute path to config script"
135 default "/usr/share/udhcpc/default.script"
136 depends on UDHCPC
137 help
138 This script is called after udhcpc receives an answer. See
139 examples/udhcp for a working example. Normally it is safe
140 to leave this untouched.
141
142config UDHCPC_SLACK_FOR_BUGGY_SERVERS 142config UDHCPC_SLACK_FOR_BUGGY_SERVERS
143 int "DHCP options slack buffer size" 143 int "DHCP options slack buffer size"
144 default 80 144 default 80
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index ddf3412a0..64339c9b5 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -12,7 +12,7 @@
12 */ 12 */
13 13
14//config:config UDHCPC6 14//config:config UDHCPC6
15//config: bool "udhcp client for DHCPv6 (udhcpc6)" 15//config: bool "udhcpc6 (DHCPv6 client, NOT READY)"
16//config: default n # not yet ready 16//config: default n # not yet ready
17//config: depends on FEATURE_IPV6 17//config: depends on FEATURE_IPV6
18//config: help 18//config: help
diff --git a/shell/Config.src b/shell/Config.src
index 7f5f67050..3545f05dd 100644
--- a/shell/Config.src
+++ b/shell/Config.src
@@ -17,9 +17,19 @@ choice
17config SH_IS_ASH 17config SH_IS_ASH
18 depends on !NOMMU 18 depends on !NOMMU
19 bool "ash" 19 bool "ash"
20 help
21 Choose ash to be the shell executed by 'sh' name.
22 The ash code will be built into busybox. If you don't select
23 "ash" choice (CONFIG_ASH), this shell may only be invoked by
24 the name 'sh' (and not 'ash').
20 25
21config SH_IS_HUSH 26config SH_IS_HUSH
22 bool "hush" 27 bool "hush"
28 help
29 Choose hush to be the shell executed by 'sh' name.
30 The hush code will be built into busybox. If you don't select
31 "hush" choice (CONFIG_HUSH), this shell may only be invoked by
32 the name 'sh' (and not 'hush').
23 33
24config SH_IS_NONE 34config SH_IS_NONE
25 bool "none" 35 bool "none"
@@ -31,7 +41,8 @@ choice
31 default BASH_IS_NONE 41 default BASH_IS_NONE
32 help 42 help
33 Choose which shell you want to be executed by 'bash' alias. 43 Choose which shell you want to be executed by 'bash' alias.
34 The ash shell is the most bash compatible and full featured one. 44 The ash shell is the most bash compatible and full featured one,
45 although compatibility is far from being complete.
35 46
36 Note that selecting this option does not switch on any bash 47 Note that selecting this option does not switch on any bash
37 compatibility code. It merely makes it possible to install 48 compatibility code. It merely makes it possible to install
@@ -46,9 +57,19 @@ choice
46config BASH_IS_ASH 57config BASH_IS_ASH
47 depends on !NOMMU 58 depends on !NOMMU
48 bool "ash" 59 bool "ash"
60 help
61 Choose ash to be the shell executed by 'bash' name.
62 The ash code will be built into busybox. If you don't select
63 "ash" choice (CONFIG_ASH), this shell may only be invoked by
64 the name 'bash' (and not 'ash').
49 65
50config BASH_IS_HUSH 66config BASH_IS_HUSH
51 bool "hush" 67 bool "hush"
68 help
69 Choose hush to be the shell executed by 'bash' name.
70 The hush code will be built into busybox. If you don't select
71 "hush" choice (CONFIG_HUSH), this shell may only be invoked by
72 the name 'bash' (and not 'hush').
52 73
53config BASH_IS_NONE 74config BASH_IS_NONE
54 bool "none" 75 bool "none"
@@ -59,6 +80,9 @@ endchoice
59INSERT 80INSERT
60 81
61 82
83comment "Options common to all shells"
84if ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH
85
62config FEATURE_SH_MATH 86config FEATURE_SH_MATH
63 bool "POSIX math support" 87 bool "POSIX math support"
64 default y 88 default y
@@ -142,5 +166,6 @@ config FEATURE_SH_HISTFILESIZE
142 to set shell history size. Note that its max value is capped 166 to set shell history size. Note that its max value is capped
143 by "History size" setting in library tuning section. 167 by "History size" setting in library tuning section.
144 168
169endif # Options common to all shells
145 170
146endmenu 171endmenu
diff --git a/shell/ash.c b/shell/ash.c
index 35618937a..fe185f5d9 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -41,6 +41,11 @@
41//config: shell (by Herbert Xu), which was created by porting the 'ash' shell 41//config: shell (by Herbert Xu), which was created by porting the 'ash' shell
42//config: (written by Kenneth Almquist) from NetBSD. 42//config: (written by Kenneth Almquist) from NetBSD.
43//config: 43//config:
44//config:# ash options
45//config:# note: Don't remove !NOMMU part in the next line; it would break
46//config:# menuconfig's indenting.
47//config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
48//config:
44//config:config ASH_OPTIMIZE_FOR_SIZE 49//config:config ASH_OPTIMIZE_FOR_SIZE
45//config: bool "Optimize for size instead of speed" 50//config: bool "Optimize for size instead of speed"
46//config: default y 51//config: default y
@@ -155,6 +160,8 @@
155//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH 160//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
156//config: help 161//config: help
157//config: Enable "check for new mail" function in the ash shell. 162//config: Enable "check for new mail" function in the ash shell.
163//config:
164//config:endif # ash options
158 165
159//applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP)) 166//applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
160//applet:IF_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, ash)) 167//applet:IF_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
@@ -5778,11 +5785,11 @@ redirect(union node *redir, int flags)
5778 /* Careful to not accidentally "save" 5785 /* Careful to not accidentally "save"
5779 * to the same fd as right side fd in N>&M */ 5786 * to the same fd as right side fd in N>&M */
5780 int minfd = right_fd < 10 ? 10 : right_fd + 1; 5787 int minfd = right_fd < 10 ? 10 : right_fd + 1;
5788#if defined(F_DUPFD_CLOEXEC)
5789 i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5790#else
5781 i = fcntl(fd, F_DUPFD, minfd); 5791 i = fcntl(fd, F_DUPFD, minfd);
5782/* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds 5792#endif
5783 * are closed in popredir() in the child, preventing them from leaking
5784 * into child. (popredir() also cleans up the mess in case of failures)
5785 */
5786 if (i == -1) { 5793 if (i == -1) {
5787 i = errno; 5794 i = errno;
5788 if (i != EBADF) { 5795 if (i != EBADF) {
@@ -5797,6 +5804,9 @@ redirect(union node *redir, int flags)
5797 remember_to_close: 5804 remember_to_close:
5798 i = CLOSED; 5805 i = CLOSED;
5799 } else { /* fd is open, save its copy */ 5806 } else { /* fd is open, save its copy */
5807#if !defined(F_DUPFD_CLOEXEC)
5808 fcntl(i, F_SETFD, FD_CLOEXEC);
5809#endif
5800 /* "exec fd>&-" should not close fds 5810 /* "exec fd>&-" should not close fds
5801 * which point to script file(s). 5811 * which point to script file(s).
5802 * Force them to be restored afterwards */ 5812 * Force them to be restored afterwards */
diff --git a/shell/ash_test/ash-redir/redir_leak.right b/shell/ash_test/ash-redir/redir_leak.right
new file mode 100644
index 000000000..b1c48292b
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_leak.right
@@ -0,0 +1,6 @@
14
24
34
44
54
64
diff --git a/shell/ash_test/ash-redir/redir_leak.tests b/shell/ash_test/ash-redir/redir_leak.tests
new file mode 100755
index 000000000..c8a9c6343
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_leak.tests
@@ -0,0 +1,10 @@
1# Each of these should show only four lines:
2# fds 0,1,2 are stdio; fd 3 is open by opendir() in ls.
3# This test detects bugs where redirects leave stray open fds.
4
5ls -1 /proc/self/fd | wc -l
6ls -1 /proc/self/fd >/proc/self/fd/1 | wc -l
7ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 | wc -l
8echo "`ls -1 /proc/self/fd `" | wc -l
9echo "`ls -1 /proc/self/fd >/proc/self/fd/1 `" | wc -l
10echo "`ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 `" | wc -l
diff --git a/shell/hush_test/hush-redir/redir_leak.right b/shell/hush_test/hush-redir/redir_leak.right
new file mode 100644
index 000000000..b1c48292b
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_leak.right
@@ -0,0 +1,6 @@
14
24
34
44
54
64
diff --git a/shell/hush_test/hush-redir/redir_leak.tests b/shell/hush_test/hush-redir/redir_leak.tests
new file mode 100755
index 000000000..c8a9c6343
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_leak.tests
@@ -0,0 +1,10 @@
1# Each of these should show only four lines:
2# fds 0,1,2 are stdio; fd 3 is open by opendir() in ls.
3# This test detects bugs where redirects leave stray open fds.
4
5ls -1 /proc/self/fd | wc -l
6ls -1 /proc/self/fd >/proc/self/fd/1 | wc -l
7ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 | wc -l
8echo "`ls -1 /proc/self/fd `" | wc -l
9echo "`ls -1 /proc/self/fd >/proc/self/fd/1 `" | wc -l
10echo "`ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 `" | wc -l
diff --git a/testsuite/unzip.tests b/testsuite/unzip.tests
index d8738a3bd..d9c45242c 100755
--- a/testsuite/unzip.tests
+++ b/testsuite/unzip.tests
@@ -31,11 +31,10 @@ rmdir foo
31rm foo.zip 31rm foo.zip
32 32
33# File containing some damaged encrypted stream 33# File containing some damaged encrypted stream
34optional FEATURE_UNZIP_CDF
34testing "unzip (bad archive)" "uudecode; unzip bad.zip 2>&1; echo \$?" \ 35testing "unzip (bad archive)" "uudecode; unzip bad.zip 2>&1; echo \$?" \
35"Archive: bad.zip 36"Archive: bad.zip
36 inflating: ]3j½r«IK-%Ix 37unzip: short read
37unzip: corrupted data
38unzip: inflate error
391 381
40" \ 39" \
41"" "\ 40"" "\
@@ -49,6 +48,7 @@ BDYAAAAMAAEADQAAADIADQAAAEEAAAASw73Ct1DKokohPXQiNzA+FAI1HCcW
49NzITNFBLBQUKAC4JAA04Cw0EOhZQSwUGAQAABAIAAgCZAAAAeQAAAAIALhM= 48NzITNFBLBQUKAC4JAA04Cw0EOhZQSwUGAQAABAIAAgCZAAAAeQAAAAIALhM=
50==== 49====
51" 50"
51SKIP=
52 52
53rm * 53rm *
54 54