diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2011-01-04 19:56:15 +0700 |
---|---|---|
committer | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2011-01-04 19:56:15 +0700 |
commit | 5f6f2162512106adf120d4b528bb125e93e34429 (patch) | |
tree | 7d7449f755633c263be7125ad58d21cc3ca5b8a7 | |
parent | 9db69882bee2d528d706d61d34ef7741122330be (diff) | |
parent | a116552869db5e7793ae10968eb3c962c69b3d8c (diff) | |
download | busybox-w32-5f6f2162512106adf120d4b528bb125e93e34429.tar.gz busybox-w32-5f6f2162512106adf120d4b528bb125e93e34429.tar.bz2 busybox-w32-5f6f2162512106adf120d4b528bb125e93e34429.zip |
Merge remote-tracking branch 'upstream/master'
250 files changed, 3469 insertions, 2479 deletions
@@ -151,8 +151,9 @@ config INSTALL_NO_USR | |||
151 | default n | 151 | default n |
152 | depends on FEATURE_INSTALLER | 152 | depends on FEATURE_INSTALLER |
153 | help | 153 | help |
154 | Disable use of /usr. busybox --install will install applets | 154 | Disable use of /usr. busybox --install and "make install" |
155 | only to /bin and /sbin, never to /usr/bin or /usr/sbin. | 155 | will install applets only to /bin and /sbin, |
156 | never to /usr/bin or /usr/sbin. | ||
156 | 157 | ||
157 | config LOCALE_SUPPORT | 158 | config LOCALE_SUPPORT |
158 | bool "Enable locale support (system needs locale for this to work)" | 159 | bool "Enable locale support (system needs locale for this to work)" |
@@ -1,5 +1,5 @@ | |||
1 | VERSION = 1 | 1 | VERSION = 1 |
2 | PATCHLEVEL = 18 | 2 | PATCHLEVEL = 19 |
3 | SUBLEVEL = 0 | 3 | SUBLEVEL = 0 |
4 | EXTRAVERSION = .git | 4 | EXTRAVERSION = .git |
5 | NAME = Unnamed | 5 | NAME = Unnamed |
@@ -465,7 +465,7 @@ core-y := \ | |||
465 | 465 | ||
466 | libs-y := \ | 466 | libs-y := \ |
467 | archival/ \ | 467 | archival/ \ |
468 | archival/libunarchive/ \ | 468 | archival/libarchive/ \ |
469 | console-tools/ \ | 469 | console-tools/ \ |
470 | coreutils/ \ | 470 | coreutils/ \ |
471 | coreutils/libcoreutils/ \ | 471 | coreutils/libcoreutils/ \ |
@@ -1010,8 +1010,8 @@ $(mrproper-dirs): | |||
1010 | mrproper: clean archmrproper $(mrproper-dirs) | 1010 | mrproper: clean archmrproper $(mrproper-dirs) |
1011 | $(call cmd,rmdirs) | 1011 | $(call cmd,rmdirs) |
1012 | $(call cmd,rmfiles) | 1012 | $(call cmd,rmfiles) |
1013 | @find -name Config.src | sed 's/.src$$/.in/' | xargs -r rm -f | 1013 | @find . -name Config.src | sed 's/.src$$/.in/' | xargs -r rm -f |
1014 | @find -name Kbuild.src | sed 's/.src$$//' | xargs -r rm -f | 1014 | @find . -name Kbuild.src | sed 's/.src$$//' | xargs -r rm -f |
1015 | 1015 | ||
1016 | # distclean | 1016 | # distclean |
1017 | # | 1017 | # |
diff --git a/Makefile.flags b/Makefile.flags index 7122d9bd6..c7a805877 100644 --- a/Makefile.flags +++ b/Makefile.flags | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | BB_VER = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) | 5 | BB_VER = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) |
6 | export BB_VER | 6 | export BB_VER |
7 | SKIP_STRIP = n | 7 | SKIP_STRIP ?= n |
8 | 8 | ||
9 | # -std=gnu99 needed for [U]LLONG_MAX on some systems | 9 | # -std=gnu99 needed for [U]LLONG_MAX on some systems |
10 | CPPFLAGS += $(call cc-option,-std=gnu99,) | 10 | CPPFLAGS += $(call cc-option,-std=gnu99,) |
diff --git a/archival/Kbuild.src b/archival/Kbuild.src index a0edb123d..3466452f7 100644 --- a/archival/Kbuild.src +++ b/archival/Kbuild.src | |||
@@ -4,7 +4,7 @@ | |||
4 | # | 4 | # |
5 | # Licensed under GPLv2, see file LICENSE in this source tree. | 5 | # Licensed under GPLv2, see file LICENSE in this source tree. |
6 | 6 | ||
7 | libs-y += libunarchive/ | 7 | libs-y += libarchive/ |
8 | 8 | ||
9 | lib-y:= | 9 | lib-y:= |
10 | 10 | ||
@@ -19,8 +19,7 @@ lib-$(CONFIG_RPM) += rpm.o | |||
19 | lib-$(CONFIG_TAR) += tar.o | 19 | lib-$(CONFIG_TAR) += tar.o |
20 | lib-$(CONFIG_UNZIP) += unzip.o | 20 | lib-$(CONFIG_UNZIP) += unzip.o |
21 | 21 | ||
22 | lib-$(CONFIG_LZOP) += lzop.o lzo1x_1.o lzo1x_1o.o lzo1x_d.o bbunzip.o | 22 | lib-$(CONFIG_LZOP) += lzop.o bbunzip.o |
23 | lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o | ||
24 | lib-$(CONFIG_GZIP) += gzip.o bbunzip.o | 23 | lib-$(CONFIG_GZIP) += gzip.o bbunzip.o |
25 | lib-$(CONFIG_BZIP2) += bzip2.o bbunzip.o | 24 | lib-$(CONFIG_BZIP2) += bzip2.o bbunzip.o |
26 | 25 | ||
diff --git a/archival/ar.c b/archival/ar.c index 05556c6cb..a2e3306ac 100644 --- a/archival/ar.c +++ b/archival/ar.c | |||
@@ -18,7 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include "libbb.h" | 20 | #include "libbb.h" |
21 | #include "unarchive.h" | 21 | #include "archive.h" |
22 | #include "ar.h" | 22 | #include "ar.h" |
23 | 23 | ||
24 | #if ENABLE_FEATURE_AR_CREATE | 24 | #if ENABLE_FEATURE_AR_CREATE |
@@ -179,17 +179,17 @@ static void FAST_FUNC header_verbose_list_ar(const file_header_t *file_header) | |||
179 | ); | 179 | ); |
180 | } | 180 | } |
181 | 181 | ||
182 | #define AR_OPT_VERBOSE (1 << 0) | 182 | #define AR_OPT_VERBOSE (1 << 0) |
183 | #define AR_OPT_PRESERVE_DATE (1 << 1) | 183 | #define AR_OPT_PRESERVE_DATE (1 << 1) |
184 | /* "ar r" implies create, but warns about it. c suppresses warning. | 184 | /* "ar r" implies create, but warns about it. c suppresses warning. |
185 | * bbox accepts but ignores it: */ | 185 | * bbox accepts but ignores it: */ |
186 | #define AR_OPT_CREATE (1 << 2) | 186 | #define AR_OPT_CREATE (1 << 2) |
187 | 187 | ||
188 | #define AR_CMD_PRINT (1 << 3) | 188 | #define AR_CMD_PRINT (1 << 3) |
189 | #define FIRST_CMD AR_CMD_PRINT | 189 | #define FIRST_CMD AR_CMD_PRINT |
190 | #define AR_CMD_LIST (1 << 4) | 190 | #define AR_CMD_LIST (1 << 4) |
191 | #define AR_CMD_EXTRACT (1 << 5) | 191 | #define AR_CMD_EXTRACT (1 << 5) |
192 | #define AR_CMD_INSERT (1 << 6) | 192 | #define AR_CMD_INSERT (1 << 6) |
193 | 193 | ||
194 | int ar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 194 | int ar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
195 | int ar_main(int argc UNUSED_PARAM, char **argv) | 195 | int ar_main(int argc UNUSED_PARAM, char **argv) |
diff --git a/archival/bbunzip.c b/archival/bbunzip.c index a195434e4..0f89443e0 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
6 | */ | 6 | */ |
7 | #include "libbb.h" | 7 | #include "libbb.h" |
8 | #include "unarchive.h" | 8 | #include "archive.h" |
9 | 9 | ||
10 | enum { | 10 | enum { |
11 | OPT_STDOUT = 1 << 0, | 11 | OPT_STDOUT = 1 << 0, |
diff --git a/archival/bzip2.c b/archival/bzip2.c index fdb8b9306..ab08ffc1a 100644 --- a/archival/bzip2.c +++ b/archival/bzip2.c | |||
@@ -8,7 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include "libbb.h" | 10 | #include "libbb.h" |
11 | #include "unarchive.h" | 11 | #include "archive.h" |
12 | 12 | ||
13 | #define CONFIG_BZIP2_FEATURE_SPEED 1 | 13 | #define CONFIG_BZIP2_FEATURE_SPEED 1 |
14 | 14 | ||
@@ -33,14 +33,14 @@ | |||
33 | /* Takes ~300 bytes, detects corruption caused by bad RAM etc */ | 33 | /* Takes ~300 bytes, detects corruption caused by bad RAM etc */ |
34 | #define BZ_LIGHT_DEBUG 0 | 34 | #define BZ_LIGHT_DEBUG 0 |
35 | 35 | ||
36 | #include "bz/bzlib.h" | 36 | #include "libarchive/bz/bzlib.h" |
37 | 37 | ||
38 | #include "bz/bzlib_private.h" | 38 | #include "libarchive/bz/bzlib_private.h" |
39 | 39 | ||
40 | #include "bz/blocksort.c" | 40 | #include "libarchive/bz/blocksort.c" |
41 | #include "bz/bzlib.c" | 41 | #include "libarchive/bz/bzlib.c" |
42 | #include "bz/compress.c" | 42 | #include "libarchive/bz/compress.c" |
43 | #include "bz/huffman.c" | 43 | #include "libarchive/bz/huffman.c" |
44 | 44 | ||
45 | /* No point in being shy and having very small buffer here. | 45 | /* No point in being shy and having very small buffer here. |
46 | * bzip2 internal buffers are much bigger anyway, hundreds of kbytes. | 46 | * bzip2 internal buffers are much bigger anyway, hundreds of kbytes. |
@@ -128,10 +128,12 @@ IF_DESKTOP(long long) int FAST_FUNC compressStream(unpack_info_t *info UNUSED_PA | |||
128 | break; | 128 | break; |
129 | } | 129 | } |
130 | 130 | ||
131 | #if ENABLE_FEATURE_CLEAN_UP | 131 | /* Can't be conditional on ENABLE_FEATURE_CLEAN_UP - |
132 | * we are called repeatedly | ||
133 | */ | ||
132 | BZ2_bzCompressEnd(strm); | 134 | BZ2_bzCompressEnd(strm); |
133 | free(iobuf); | 135 | free(iobuf); |
134 | #endif | 136 | |
135 | return total; | 137 | return total; |
136 | } | 138 | } |
137 | 139 | ||
diff --git a/archival/cpio.c b/archival/cpio.c index a2d74dc79..c746a71fa 100644 --- a/archival/cpio.c +++ b/archival/cpio.c | |||
@@ -12,7 +12,37 @@ | |||
12 | * | 12 | * |
13 | */ | 13 | */ |
14 | #include "libbb.h" | 14 | #include "libbb.h" |
15 | #include "unarchive.h" | 15 | #include "archive.h" |
16 | |||
17 | //usage:#define cpio_trivial_usage | ||
18 | //usage: "[-dmvu] [-F FILE]" IF_FEATURE_CPIO_O(" [-H newc]") | ||
19 | //usage: " [-ti"IF_FEATURE_CPIO_O("o")"]" IF_FEATURE_CPIO_P(" [-p DIR]") | ||
20 | //usage: " [EXTR_FILE]..." | ||
21 | //usage:#define cpio_full_usage "\n\n" | ||
22 | //usage: "Extract or list files from a cpio archive" | ||
23 | //usage: IF_FEATURE_CPIO_O(", or" | ||
24 | //usage: "\ncreate an archive" IF_FEATURE_CPIO_P(" (-o) or copy files (-p)") | ||
25 | //usage: " using file list on stdin" | ||
26 | //usage: ) | ||
27 | //usage: "\n" | ||
28 | //usage: "\nMain operation mode:" | ||
29 | //usage: "\n -t List" | ||
30 | //usage: "\n -i Extract EXTR_FILEs (or all)" | ||
31 | //usage: IF_FEATURE_CPIO_O( | ||
32 | //usage: "\n -o Create (requires -H newc)" | ||
33 | //usage: ) | ||
34 | //usage: IF_FEATURE_CPIO_P( | ||
35 | //usage: "\n -p DIR Copy files to DIR" | ||
36 | //usage: ) | ||
37 | //usage: "\nOptions:" | ||
38 | //usage: "\n -d Make leading directories" | ||
39 | //usage: "\n -m Preserve mtime" | ||
40 | //usage: "\n -v Verbose" | ||
41 | //usage: "\n -u Overwrite" | ||
42 | //usage: "\n -F FILE Input (-t,-i,-p) or output (-o) file" | ||
43 | //usage: IF_FEATURE_CPIO_O( | ||
44 | //usage: "\n -H newc Archive format" | ||
45 | //usage: ) | ||
16 | 46 | ||
17 | /* GNU cpio 2.9 --help (abridged): | 47 | /* GNU cpio 2.9 --help (abridged): |
18 | 48 | ||
@@ -20,7 +50,7 @@ | |||
20 | -t, --list List the archive | 50 | -t, --list List the archive |
21 | -i, --extract Extract files from an archive | 51 | -i, --extract Extract files from an archive |
22 | -o, --create Create the archive | 52 | -o, --create Create the archive |
23 | -p, --pass-through Copy-pass mode [was ist das?!] | 53 | -p, --pass-through Copy-pass mode |
24 | 54 | ||
25 | Options valid in any mode: | 55 | Options valid in any mode: |
26 | --block-size=SIZE I/O block size = SIZE * 512 bytes | 56 | --block-size=SIZE I/O block size = SIZE * 512 bytes |
@@ -78,27 +108,28 @@ | |||
78 | --sparse Write files with blocks of zeros as sparse files | 108 | --sparse Write files with blocks of zeros as sparse files |
79 | -u, --unconditional Replace all files unconditionally | 109 | -u, --unconditional Replace all files unconditionally |
80 | */ | 110 | */ |
111 | |||
81 | enum { | 112 | enum { |
82 | CPIO_OPT_EXTRACT = (1 << 0), | 113 | OPT_EXTRACT = (1 << 0), |
83 | CPIO_OPT_TEST = (1 << 1), | 114 | OPT_TEST = (1 << 1), |
84 | CPIO_OPT_NUL_TERMINATED = (1 << 2), | 115 | OPT_NUL_TERMINATED = (1 << 2), |
85 | CPIO_OPT_UNCONDITIONAL = (1 << 3), | 116 | OPT_UNCONDITIONAL = (1 << 3), |
86 | CPIO_OPT_VERBOSE = (1 << 4), | 117 | OPT_VERBOSE = (1 << 4), |
87 | CPIO_OPT_CREATE_LEADING_DIR = (1 << 5), | 118 | OPT_CREATE_LEADING_DIR = (1 << 5), |
88 | CPIO_OPT_PRESERVE_MTIME = (1 << 6), | 119 | OPT_PRESERVE_MTIME = (1 << 6), |
89 | CPIO_OPT_DEREF = (1 << 7), | 120 | OPT_DEREF = (1 << 7), |
90 | CPIO_OPT_FILE = (1 << 8), | 121 | OPT_FILE = (1 << 8), |
91 | OPTBIT_FILE = 8, | 122 | OPTBIT_FILE = 8, |
92 | IF_FEATURE_CPIO_O(OPTBIT_CREATE ,) | 123 | IF_FEATURE_CPIO_O(OPTBIT_CREATE ,) |
93 | IF_FEATURE_CPIO_O(OPTBIT_FORMAT ,) | 124 | IF_FEATURE_CPIO_O(OPTBIT_FORMAT ,) |
94 | IF_FEATURE_CPIO_P(OPTBIT_PASSTHROUGH,) | 125 | IF_FEATURE_CPIO_P(OPTBIT_PASSTHROUGH,) |
95 | IF_LONG_OPTS( OPTBIT_QUIET ,) | 126 | IF_LONG_OPTS( OPTBIT_QUIET ,) |
96 | IF_LONG_OPTS( OPTBIT_2STDOUT ,) | 127 | IF_LONG_OPTS( OPTBIT_2STDOUT ,) |
97 | CPIO_OPT_CREATE = IF_FEATURE_CPIO_O((1 << OPTBIT_CREATE )) + 0, | 128 | OPT_CREATE = IF_FEATURE_CPIO_O((1 << OPTBIT_CREATE )) + 0, |
98 | CPIO_OPT_FORMAT = IF_FEATURE_CPIO_O((1 << OPTBIT_FORMAT )) + 0, | 129 | OPT_FORMAT = IF_FEATURE_CPIO_O((1 << OPTBIT_FORMAT )) + 0, |
99 | CPIO_OPT_PASSTHROUGH = IF_FEATURE_CPIO_P((1 << OPTBIT_PASSTHROUGH)) + 0, | 130 | OPT_PASSTHROUGH = IF_FEATURE_CPIO_P((1 << OPTBIT_PASSTHROUGH)) + 0, |
100 | CPIO_OPT_QUIET = IF_LONG_OPTS( (1 << OPTBIT_QUIET )) + 0, | 131 | OPT_QUIET = IF_LONG_OPTS( (1 << OPTBIT_QUIET )) + 0, |
101 | CPIO_OPT_2STDOUT = IF_LONG_OPTS( (1 << OPTBIT_2STDOUT )) + 0, | 132 | OPT_2STDOUT = IF_LONG_OPTS( (1 << OPTBIT_2STDOUT )) + 0, |
102 | }; | 133 | }; |
103 | 134 | ||
104 | #define OPTION_STR "it0uvdmLF:" | 135 | #define OPTION_STR "it0uvdmLF:" |
@@ -138,7 +169,7 @@ static NOINLINE int cpio_o(void) | |||
138 | char *line; | 169 | char *line; |
139 | struct stat st; | 170 | struct stat st; |
140 | 171 | ||
141 | line = (option_mask32 & CPIO_OPT_NUL_TERMINATED) | 172 | line = (option_mask32 & OPT_NUL_TERMINATED) |
142 | ? bb_get_chunk_from_file(stdin, NULL) | 173 | ? bb_get_chunk_from_file(stdin, NULL) |
143 | : xmalloc_fgetline(stdin); | 174 | : xmalloc_fgetline(stdin); |
144 | 175 | ||
@@ -153,7 +184,7 @@ static NOINLINE int cpio_o(void) | |||
153 | free(line); | 184 | free(line); |
154 | continue; | 185 | continue; |
155 | } | 186 | } |
156 | if ((option_mask32 & CPIO_OPT_DEREF) | 187 | if ((option_mask32 & OPT_DEREF) |
157 | ? stat(name, &st) | 188 | ? stat(name, &st) |
158 | : lstat(name, &st) | 189 | : lstat(name, &st) |
159 | ) { | 190 | ) { |
@@ -308,28 +339,24 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) | |||
308 | /* -L makes sense only with -o or -p */ | 339 | /* -L makes sense only with -o or -p */ |
309 | 340 | ||
310 | #if !ENABLE_FEATURE_CPIO_O | 341 | #if !ENABLE_FEATURE_CPIO_O |
311 | /* no parameters */ | ||
312 | opt_complementary = "=0"; | ||
313 | opt = getopt32(argv, OPTION_STR, &cpio_filename); | 342 | opt = getopt32(argv, OPTION_STR, &cpio_filename); |
314 | argv += optind; | 343 | argv += optind; |
315 | if (opt & CPIO_OPT_FILE) { /* -F */ | 344 | if (opt & OPT_FILE) { /* -F */ |
316 | xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO); | 345 | xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO); |
317 | } | 346 | } |
318 | #else | 347 | #else |
319 | /* _exactly_ one parameter for -p, thus <= 1 param if -p is allowed */ | ||
320 | opt_complementary = ENABLE_FEATURE_CPIO_P ? "?1" : "=0"; | ||
321 | opt = getopt32(argv, OPTION_STR "oH:" IF_FEATURE_CPIO_P("p"), &cpio_filename, &cpio_fmt); | 348 | opt = getopt32(argv, OPTION_STR "oH:" IF_FEATURE_CPIO_P("p"), &cpio_filename, &cpio_fmt); |
322 | argv += optind; | 349 | argv += optind; |
323 | if ((opt & (CPIO_OPT_FILE|CPIO_OPT_CREATE)) == CPIO_OPT_FILE) { /* -F without -o */ | 350 | if ((opt & (OPT_FILE|OPT_CREATE)) == OPT_FILE) { /* -F without -o */ |
324 | xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO); | 351 | xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO); |
325 | } | 352 | } |
326 | if (opt & CPIO_OPT_PASSTHROUGH) { | 353 | if (opt & OPT_PASSTHROUGH) { |
327 | pid_t pid; | 354 | pid_t pid; |
328 | struct fd_pair pp; | 355 | struct fd_pair pp; |
329 | 356 | ||
330 | if (argv[0] == NULL) | 357 | if (argv[0] == NULL) |
331 | bb_show_usage(); | 358 | bb_show_usage(); |
332 | if (opt & CPIO_OPT_CREATE_LEADING_DIR) | 359 | if (opt & OPT_CREATE_LEADING_DIR) |
333 | mkdir(argv[0], 0777); | 360 | mkdir(argv[0], 0777); |
334 | /* Crude existence check: | 361 | /* Crude existence check: |
335 | * close(xopen(argv[0], O_RDONLY | O_DIRECTORY)); | 362 | * close(xopen(argv[0], O_RDONLY | O_DIRECTORY)); |
@@ -361,15 +388,15 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) | |||
361 | xchdir(*argv++); | 388 | xchdir(*argv++); |
362 | close(pp.wr); | 389 | close(pp.wr); |
363 | xmove_fd(pp.rd, STDIN_FILENO); | 390 | xmove_fd(pp.rd, STDIN_FILENO); |
364 | //opt &= ~CPIO_OPT_PASSTHROUGH; | 391 | //opt &= ~OPT_PASSTHROUGH; |
365 | opt |= CPIO_OPT_EXTRACT; | 392 | opt |= OPT_EXTRACT; |
366 | goto skip; | 393 | goto skip; |
367 | } | 394 | } |
368 | /* -o */ | 395 | /* -o */ |
369 | if (opt & CPIO_OPT_CREATE) { | 396 | if (opt & OPT_CREATE) { |
370 | if (cpio_fmt[0] != 'n') /* we _require_ "-H newc" */ | 397 | if (cpio_fmt[0] != 'n') /* we _require_ "-H newc" */ |
371 | bb_show_usage(); | 398 | bb_show_usage(); |
372 | if (opt & CPIO_OPT_FILE) { | 399 | if (opt & OPT_FILE) { |
373 | xmove_fd(xopen(cpio_filename, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO); | 400 | xmove_fd(xopen(cpio_filename, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO); |
374 | } | 401 | } |
375 | dump: | 402 | dump: |
@@ -379,35 +406,35 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) | |||
379 | #endif | 406 | #endif |
380 | 407 | ||
381 | /* One of either extract or test options must be given */ | 408 | /* One of either extract or test options must be given */ |
382 | if ((opt & (CPIO_OPT_TEST | CPIO_OPT_EXTRACT)) == 0) { | 409 | if ((opt & (OPT_TEST | OPT_EXTRACT)) == 0) { |
383 | bb_show_usage(); | 410 | bb_show_usage(); |
384 | } | 411 | } |
385 | 412 | ||
386 | if (opt & CPIO_OPT_TEST) { | 413 | if (opt & OPT_TEST) { |
387 | /* if both extract and test options are given, ignore extract option */ | 414 | /* if both extract and test options are given, ignore extract option */ |
388 | opt &= ~CPIO_OPT_EXTRACT; | 415 | opt &= ~OPT_EXTRACT; |
389 | archive_handle->action_header = header_list; | 416 | archive_handle->action_header = header_list; |
390 | } | 417 | } |
391 | if (opt & CPIO_OPT_EXTRACT) { | 418 | if (opt & OPT_EXTRACT) { |
392 | archive_handle->action_data = data_extract_all; | 419 | archive_handle->action_data = data_extract_all; |
393 | if (opt & CPIO_OPT_2STDOUT) | 420 | if (opt & OPT_2STDOUT) |
394 | archive_handle->action_data = data_extract_to_stdout; | 421 | archive_handle->action_data = data_extract_to_stdout; |
395 | } | 422 | } |
396 | if (opt & CPIO_OPT_UNCONDITIONAL) { | 423 | if (opt & OPT_UNCONDITIONAL) { |
397 | archive_handle->ah_flags |= ARCHIVE_UNLINK_OLD; | 424 | archive_handle->ah_flags |= ARCHIVE_UNLINK_OLD; |
398 | archive_handle->ah_flags &= ~ARCHIVE_EXTRACT_NEWER; | 425 | archive_handle->ah_flags &= ~ARCHIVE_EXTRACT_NEWER; |
399 | } | 426 | } |
400 | if (opt & CPIO_OPT_VERBOSE) { | 427 | if (opt & OPT_VERBOSE) { |
401 | if (archive_handle->action_header == header_list) { | 428 | if (archive_handle->action_header == header_list) { |
402 | archive_handle->action_header = header_verbose_list; | 429 | archive_handle->action_header = header_verbose_list; |
403 | } else { | 430 | } else { |
404 | archive_handle->action_header = header_list; | 431 | archive_handle->action_header = header_list; |
405 | } | 432 | } |
406 | } | 433 | } |
407 | if (opt & CPIO_OPT_CREATE_LEADING_DIR) { | 434 | if (opt & OPT_CREATE_LEADING_DIR) { |
408 | archive_handle->ah_flags |= ARCHIVE_CREATE_LEADING_DIRS; | 435 | archive_handle->ah_flags |= ARCHIVE_CREATE_LEADING_DIRS; |
409 | } | 436 | } |
410 | if (opt & CPIO_OPT_PRESERVE_MTIME) { | 437 | if (opt & OPT_PRESERVE_MTIME) { |
411 | archive_handle->ah_flags |= ARCHIVE_RESTORE_DATE; | 438 | archive_handle->ah_flags |= ARCHIVE_RESTORE_DATE; |
412 | } | 439 | } |
413 | 440 | ||
@@ -423,7 +450,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) | |||
423 | continue; | 450 | continue; |
424 | 451 | ||
425 | if (archive_handle->cpio__blocks != (off_t)-1 | 452 | if (archive_handle->cpio__blocks != (off_t)-1 |
426 | && !(opt & CPIO_OPT_QUIET) | 453 | && !(opt & OPT_QUIET) |
427 | ) { | 454 | ) { |
428 | fprintf(stderr, "%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks); | 455 | fprintf(stderr, "%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks); |
429 | } | 456 | } |
diff --git a/archival/dpkg.c b/archival/dpkg.c index 508b4297b..c37ae3349 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c | |||
@@ -30,7 +30,7 @@ | |||
30 | 30 | ||
31 | #include "libbb.h" | 31 | #include "libbb.h" |
32 | #include <fnmatch.h> | 32 | #include <fnmatch.h> |
33 | #include "unarchive.h" | 33 | #include "archive.h" |
34 | 34 | ||
35 | /* note: if you vary hash_prime sizes be aware, | 35 | /* note: if you vary hash_prime sizes be aware, |
36 | * 1) tweaking these will have a big effect on how much memory this program uses. | 36 | * 1) tweaking these will have a big effect on how much memory this program uses. |
@@ -939,8 +939,8 @@ static int package_satisfies_dependency(int package, int depend_type) | |||
939 | return 0; | 939 | return 0; |
940 | 940 | ||
941 | switch (depend_type) { | 941 | switch (depend_type) { |
942 | case EDGE_PRE_DEPENDS: return get_status(status_num, 3) == search_name_hashtable("installed"); | 942 | case EDGE_PRE_DEPENDS: return get_status(status_num, 3) == search_name_hashtable("installed"); |
943 | case EDGE_DEPENDS: return get_status(status_num, 1) == search_name_hashtable("install"); | 943 | case EDGE_DEPENDS: return get_status(status_num, 1) == search_name_hashtable("install"); |
944 | } | 944 | } |
945 | return 0; | 945 | return 0; |
946 | } | 946 | } |
@@ -967,7 +967,7 @@ static int check_deps(deb_file_t **deb_file, int deb_start /*, int dep_max_count | |||
967 | conflicts[conflicts_num] = package_num; | 967 | conflicts[conflicts_num] = package_num; |
968 | conflicts_num++; | 968 | conflicts_num++; |
969 | /* add provides to conflicts list */ | 969 | /* add provides to conflicts list */ |
970 | for (j = 0; j < package_hashtable[package_num]->num_of_edges; j++) { | 970 | for (j = 0; j < package_hashtable[package_num]->num_of_edges; j++) { |
971 | if (package_hashtable[package_num]->edge[j]->type == EDGE_PROVIDES) { | 971 | if (package_hashtable[package_num]->edge[j]->type == EDGE_PROVIDES) { |
972 | const int conflicts_package_num = search_package_hashtable( | 972 | const int conflicts_package_num = search_package_hashtable( |
973 | package_hashtable[package_num]->edge[j]->name, | 973 | package_hashtable[package_num]->edge[j]->name, |
@@ -1067,12 +1067,13 @@ static int check_deps(deb_file_t **deb_file, int deb_start /*, int dep_max_count | |||
1067 | 1067 | ||
1068 | if (package_edge->type == EDGE_OR_PRE_DEPENDS | 1068 | if (package_edge->type == EDGE_OR_PRE_DEPENDS |
1069 | || package_edge->type == EDGE_OR_DEPENDS | 1069 | || package_edge->type == EDGE_OR_DEPENDS |
1070 | ) { /* start an EDGE_OR_ list */ | 1070 | ) { |
1071 | /* start an EDGE_OR_ list */ | ||
1071 | number_of_alternatives = package_edge->version; | 1072 | number_of_alternatives = package_edge->version; |
1072 | root_of_alternatives = package_edge; | 1073 | root_of_alternatives = package_edge; |
1073 | continue; | 1074 | continue; |
1074 | } | 1075 | } |
1075 | if (number_of_alternatives == 0) { /* not in the middle of an EDGE_OR_ list */ | 1076 | if (number_of_alternatives == 0) { /* not in the middle of an EDGE_OR_ list */ |
1076 | number_of_alternatives = 1; | 1077 | number_of_alternatives = 1; |
1077 | root_of_alternatives = NULL; | 1078 | root_of_alternatives = NULL; |
1078 | } | 1079 | } |
diff --git a/archival/dpkg_deb.c b/archival/dpkg_deb.c index 4c627e890..aee7b4cf5 100644 --- a/archival/dpkg_deb.c +++ b/archival/dpkg_deb.c | |||
@@ -5,13 +5,13 @@ | |||
5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
6 | */ | 6 | */ |
7 | #include "libbb.h" | 7 | #include "libbb.h" |
8 | #include "unarchive.h" | 8 | #include "archive.h" |
9 | 9 | ||
10 | #define DPKG_DEB_OPT_CONTENTS 1 | 10 | #define DPKG_DEB_OPT_CONTENTS 1 |
11 | #define DPKG_DEB_OPT_CONTROL 2 | 11 | #define DPKG_DEB_OPT_CONTROL 2 |
12 | #define DPKG_DEB_OPT_FIELD 4 | 12 | #define DPKG_DEB_OPT_FIELD 4 |
13 | #define DPKG_DEB_OPT_EXTRACT 8 | 13 | #define DPKG_DEB_OPT_EXTRACT 8 |
14 | #define DPKG_DEB_OPT_EXTRACT_VERBOSE 16 | 14 | #define DPKG_DEB_OPT_EXTRACT_VERBOSE 16 |
15 | 15 | ||
16 | int dpkg_deb_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 16 | int dpkg_deb_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
17 | int dpkg_deb_main(int argc, char **argv) | 17 | int dpkg_deb_main(int argc, char **argv) |
diff --git a/archival/gzip.c b/archival/gzip.c index b573ed6ab..feeddf58f 100644 --- a/archival/gzip.c +++ b/archival/gzip.c | |||
@@ -40,7 +40,7 @@ aa: 85.1% -- replaced with aa.gz | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | #include "libbb.h" | 42 | #include "libbb.h" |
43 | #include "unarchive.h" | 43 | #include "archive.h" |
44 | 44 | ||
45 | 45 | ||
46 | /* =========================================================================== | 46 | /* =========================================================================== |
diff --git a/archival/libunarchive/Kbuild.src b/archival/libarchive/Kbuild.src index e92b4aad2..b0bc4e5aa 100644 --- a/archival/libunarchive/Kbuild.src +++ b/archival/libarchive/Kbuild.src | |||
@@ -48,6 +48,8 @@ lib-$(CONFIG_RPM) += open_transformer.o decompress_unzip.o | |||
48 | lib-$(CONFIG_TAR) += get_header_tar.o | 48 | lib-$(CONFIG_TAR) += get_header_tar.o |
49 | lib-$(CONFIG_UNCOMPRESS) += decompress_uncompress.o | 49 | lib-$(CONFIG_UNCOMPRESS) += decompress_uncompress.o |
50 | lib-$(CONFIG_UNZIP) += decompress_unzip.o | 50 | lib-$(CONFIG_UNZIP) += decompress_unzip.o |
51 | lib-$(CONFIG_LZOP) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o | ||
52 | lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o | ||
51 | lib-$(CONFIG_FEATURE_SEAMLESS_Z) += open_transformer.o decompress_uncompress.o | 53 | lib-$(CONFIG_FEATURE_SEAMLESS_Z) += open_transformer.o decompress_uncompress.o |
52 | lib-$(CONFIG_FEATURE_SEAMLESS_GZ) += open_transformer.o decompress_unzip.o get_header_tar_gz.o | 54 | lib-$(CONFIG_FEATURE_SEAMLESS_GZ) += open_transformer.o decompress_unzip.o get_header_tar_gz.o |
53 | lib-$(CONFIG_FEATURE_SEAMLESS_BZ2) += open_transformer.o decompress_bunzip2.o get_header_tar_bz2.o | 55 | lib-$(CONFIG_FEATURE_SEAMLESS_BZ2) += open_transformer.o decompress_bunzip2.o get_header_tar_bz2.o |
diff --git a/archival/bz/LICENSE b/archival/libarchive/bz/LICENSE index da4346520..da4346520 100644 --- a/archival/bz/LICENSE +++ b/archival/libarchive/bz/LICENSE | |||
diff --git a/archival/bz/README b/archival/libarchive/bz/README index fffd47b8a..fffd47b8a 100644 --- a/archival/bz/README +++ b/archival/libarchive/bz/README | |||
diff --git a/archival/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index f70c3701d..f70c3701d 100644 --- a/archival/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c | |||
diff --git a/archival/bz/bzlib.c b/archival/libarchive/bz/bzlib.c index 834179403..5f7db747a 100644 --- a/archival/bz/bzlib.c +++ b/archival/libarchive/bz/bzlib.c | |||
@@ -28,7 +28,7 @@ in the file LICENSE. | |||
28 | * 0.9.0a/b -- no changes in this file. | 28 | * 0.9.0a/b -- no changes in this file. |
29 | * 0.9.0c -- made zero-length BZ_FLUSH work correctly in bzCompress(). | 29 | * 0.9.0c -- made zero-length BZ_FLUSH work correctly in bzCompress(). |
30 | * fixed bzWrite/bzRead to ignore zero-length requests. | 30 | * fixed bzWrite/bzRead to ignore zero-length requests. |
31 | * fixed bzread to correctly handle read requests after EOF. | 31 | * fixed bzread to correctly handle read requests after EOF. |
32 | * wrong parameter order in call to bzDecompressInit in | 32 | * wrong parameter order in call to bzDecompressInit in |
33 | * bzBuffToBuffDecompress. Fixed. | 33 | * bzBuffToBuffDecompress. Fixed. |
34 | */ | 34 | */ |
@@ -361,7 +361,6 @@ int BZ2_bzCompress(bz_stream *strm, int action) | |||
361 | 361 | ||
362 | 362 | ||
363 | /*---------------------------------------------------*/ | 363 | /*---------------------------------------------------*/ |
364 | #if ENABLE_FEATURE_CLEAN_UP | ||
365 | static | 364 | static |
366 | void BZ2_bzCompressEnd(bz_stream *strm) | 365 | void BZ2_bzCompressEnd(bz_stream *strm) |
367 | { | 366 | { |
@@ -372,9 +371,8 @@ void BZ2_bzCompressEnd(bz_stream *strm) | |||
372 | free(s->arr2); | 371 | free(s->arr2); |
373 | free(s->ftab); | 372 | free(s->ftab); |
374 | free(s->crc32table); | 373 | free(s->crc32table); |
375 | free(strm->state); | 374 | free(s); |
376 | } | 375 | } |
377 | #endif | ||
378 | 376 | ||
379 | 377 | ||
380 | /*---------------------------------------------------*/ | 378 | /*---------------------------------------------------*/ |
diff --git a/archival/bz/bzlib.h b/archival/libarchive/bz/bzlib.h index 1bb811c4a..1bb811c4a 100644 --- a/archival/bz/bzlib.h +++ b/archival/libarchive/bz/bzlib.h | |||
diff --git a/archival/bz/bzlib_private.h b/archival/libarchive/bz/bzlib_private.h index 6430ce407..6430ce407 100644 --- a/archival/bz/bzlib_private.h +++ b/archival/libarchive/bz/bzlib_private.h | |||
diff --git a/archival/bz/compress.c b/archival/libarchive/bz/compress.c index b9b0949a9..6f1c70a08 100644 --- a/archival/bz/compress.c +++ b/archival/libarchive/bz/compress.c | |||
@@ -134,15 +134,14 @@ void generateMTFValues(EState* s) | |||
134 | * holds the original block data. | 134 | * holds the original block data. |
135 | * | 135 | * |
136 | * The first thing to do is generate the MTF values, | 136 | * The first thing to do is generate the MTF values, |
137 | * and put them in | 137 | * and put them in ((uint16_t*)s->arr1)[0 .. s->nblock-1]. |
138 | * ((uint16_t*)s->arr1)[0 .. s->nblock-1]. | 138 | * |
139 | * Because there are strictly fewer or equal MTF values | 139 | * Because there are strictly fewer or equal MTF values |
140 | * than block values, ptr values in this area are overwritten | 140 | * than block values, ptr values in this area are overwritten |
141 | * with MTF values only when they are no longer needed. | 141 | * with MTF values only when they are no longer needed. |
142 | * | 142 | * |
143 | * The final compressed bitstream is generated into the | 143 | * The final compressed bitstream is generated into the |
144 | * area starting at | 144 | * area starting at &((uint8_t*)s->arr2)[s->nblock] |
145 | * &((uint8_t*)s->arr2)[s->nblock] | ||
146 | * | 145 | * |
147 | * These storage aliases are set up in bzCompressInit(), | 146 | * These storage aliases are set up in bzCompressInit(), |
148 | * except for the last one, which is arranged in | 147 | * except for the last one, which is arranged in |
@@ -459,7 +458,7 @@ void sendMTFValues(EState* s) | |||
459 | } | 458 | } |
460 | 459 | ||
461 | AssertH(nGroups < 8, 3002); | 460 | AssertH(nGroups < 8, 3002); |
462 | AssertH(nSelectors < 32768 && nSelectors <= (2 + (900000 / BZ_G_SIZE)), 3003); | 461 | AssertH(nSelectors < 32768 && nSelectors <= (2 + (900000 / BZ_G_SIZE)), 3003); |
463 | 462 | ||
464 | /*--- Compute MTF values for the selectors. ---*/ | 463 | /*--- Compute MTF values for the selectors. ---*/ |
465 | { | 464 | { |
diff --git a/archival/bz/huffman.c b/archival/libarchive/bz/huffman.c index 676b1af66..676b1af66 100644 --- a/archival/bz/huffman.c +++ b/archival/libarchive/bz/huffman.c | |||
diff --git a/archival/libunarchive/data_align.c b/archival/libarchive/data_align.c index 4e21a36b3..2e56fa8ff 100644 --- a/archival/libunarchive/data_align.c +++ b/archival/libarchive/data_align.c | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "libbb.h" | 6 | #include "libbb.h" |
7 | #include "unarchive.h" | 7 | #include "archive.h" |
8 | 8 | ||
9 | void FAST_FUNC data_align(archive_handle_t *archive_handle, unsigned boundary) | 9 | void FAST_FUNC data_align(archive_handle_t *archive_handle, unsigned boundary) |
10 | { | 10 | { |
diff --git a/archival/libunarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c index 5fb1ab2ae..1b25c8bd6 100644 --- a/archival/libunarchive/data_extract_all.c +++ b/archival/libarchive/data_extract_all.c | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "libbb.h" | 6 | #include "libbb.h" |
7 | #include "unarchive.h" | 7 | #include "archive.h" |
8 | 8 | ||
9 | void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | 9 | void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) |
10 | { | 10 | { |
diff --git a/archival/libunarchive/data_extract_to_command.c b/archival/libarchive/data_extract_to_command.c index b54f7f215..2bbab7641 100644 --- a/archival/libunarchive/data_extract_to_command.c +++ b/archival/libarchive/data_extract_to_command.c | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "libbb.h" | 6 | #include "libbb.h" |
7 | #include "unarchive.h" | 7 | #include "archive.h" |
8 | 8 | ||
9 | enum { | 9 | enum { |
10 | //TAR_FILETYPE, | 10 | //TAR_FILETYPE, |
diff --git a/archival/libunarchive/data_extract_to_stdout.c b/archival/libarchive/data_extract_to_stdout.c index ce0713ac4..91f3f3539 100644 --- a/archival/libunarchive/data_extract_to_stdout.c +++ b/archival/libarchive/data_extract_to_stdout.c | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "libbb.h" | 6 | #include "libbb.h" |
7 | #include "unarchive.h" | 7 | #include "archive.h" |
8 | 8 | ||
9 | void FAST_FUNC data_extract_to_stdout(archive_handle_t *archive_handle) | 9 | void FAST_FUNC data_extract_to_stdout(archive_handle_t *archive_handle) |
10 | { | 10 | { |
diff --git a/archival/libunarchive/data_skip.c b/archival/libarchive/data_skip.c index 06b74399d..a055424e2 100644 --- a/archival/libunarchive/data_skip.c +++ b/archival/libarchive/data_skip.c | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "libbb.h" | 6 | #include "libbb.h" |
7 | #include "unarchive.h" | 7 | #include "archive.h" |
8 | 8 | ||
9 | void FAST_FUNC data_skip(archive_handle_t *archive_handle) | 9 | void FAST_FUNC data_skip(archive_handle_t *archive_handle) |
10 | { | 10 | { |
diff --git a/archival/libunarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c index 22015683c..4e46e6849 100644 --- a/archival/libunarchive/decompress_bunzip2.c +++ b/archival/libarchive/decompress_bunzip2.c | |||
@@ -16,10 +16,21 @@ | |||
16 | function, and various other tweaks. In (limited) tests, approximately | 16 | function, and various other tweaks. In (limited) tests, approximately |
17 | 20% faster than bzcat on x86 and about 10% faster on arm. | 17 | 20% faster than bzcat on x86 and about 10% faster on arm. |
18 | 18 | ||
19 | Note that about 2/3 of the time is spent in read_unzip() reversing | 19 | Note that about 2/3 of the time is spent in read_bunzip() reversing |
20 | the Burrows-Wheeler transformation. Much of that time is delay | 20 | the Burrows-Wheeler transformation. Much of that time is delay |
21 | resulting from cache misses. | 21 | resulting from cache misses. |
22 | 22 | ||
23 | (2010 update by vda: profiled "bzcat <84mbyte.bz2 >/dev/null" | ||
24 | on x86-64 CPU with L2 > 1M: get_next_block is hotter than read_bunzip: | ||
25 | %time seconds calls function | ||
26 | 71.01 12.69 444 get_next_block | ||
27 | 28.65 5.12 93065 read_bunzip | ||
28 | 00.22 0.04 7736490 get_bits | ||
29 | 00.11 0.02 47 dealloc_bunzip | ||
30 | 00.00 0.00 93018 full_write | ||
31 | ...) | ||
32 | |||
33 | |||
23 | I would ask that anyone benefiting from this work, especially those | 34 | I would ask that anyone benefiting from this work, especially those |
24 | using it in commercial products, consider making a donation to my local | 35 | using it in commercial products, consider making a donation to my local |
25 | non-profit hospice organization (www.hospiceacadiana.com) in the name of | 36 | non-profit hospice organization (www.hospiceacadiana.com) in the name of |
@@ -29,7 +40,7 @@ | |||
29 | */ | 40 | */ |
30 | 41 | ||
31 | #include "libbb.h" | 42 | #include "libbb.h" |
32 | #include "unarchive.h" | 43 | #include "archive.h" |
33 | 44 | ||
34 | /* Constants for Huffman coding */ | 45 | /* Constants for Huffman coding */ |
35 | #define MAX_GROUPS 6 | 46 | #define MAX_GROUPS 6 |
@@ -70,38 +81,41 @@ struct bunzip_data { | |||
70 | /* I/O tracking data (file handles, buffers, positions, etc.) */ | 81 | /* I/O tracking data (file handles, buffers, positions, etc.) */ |
71 | unsigned inbufBitCount, inbufBits; | 82 | unsigned inbufBitCount, inbufBits; |
72 | int in_fd, out_fd, inbufCount, inbufPos /*, outbufPos*/; | 83 | int in_fd, out_fd, inbufCount, inbufPos /*, outbufPos*/; |
73 | unsigned char *inbuf /*,*outbuf*/; | 84 | uint8_t *inbuf /*,*outbuf*/; |
74 | 85 | ||
75 | /* State for interrupting output loop */ | 86 | /* State for interrupting output loop */ |
76 | int writeCopies, writePos, writeRunCountdown, writeCount, writeCurrent; | 87 | int writeCopies, writePos, writeRunCountdown, writeCount; |
88 | int writeCurrent; /* actually a uint8_t */ | ||
77 | 89 | ||
78 | /* The CRC values stored in the block header and calculated from the data */ | 90 | /* The CRC values stored in the block header and calculated from the data */ |
79 | uint32_t headerCRC, totalCRC, writeCRC; | 91 | uint32_t headerCRC, totalCRC, writeCRC; |
80 | 92 | ||
81 | /* Intermediate buffer and its size (in bytes) */ | 93 | /* Intermediate buffer and its size (in bytes) */ |
82 | unsigned *dbuf, dbufSize; | 94 | uint32_t *dbuf; |
95 | unsigned dbufSize; | ||
83 | 96 | ||
84 | /* For I/O error handling */ | 97 | /* For I/O error handling */ |
85 | jmp_buf jmpbuf; | 98 | jmp_buf jmpbuf; |
86 | 99 | ||
87 | /* Big things go last (register-relative addressing can be larger for big offsets) */ | 100 | /* Big things go last (register-relative addressing can be larger for big offsets) */ |
88 | uint32_t crc32Table[256]; | 101 | uint32_t crc32Table[256]; |
89 | unsigned char selectors[32768]; /* nSelectors=15 bits */ | 102 | uint8_t selectors[32768]; /* nSelectors=15 bits */ |
90 | struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */ | 103 | struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */ |
91 | }; | 104 | }; |
92 | /* typedef struct bunzip_data bunzip_data; -- done in .h file */ | 105 | /* typedef struct bunzip_data bunzip_data; -- done in .h file */ |
93 | 106 | ||
94 | 107 | ||
95 | /* Return the next nnn bits of input. All reads from the compressed input | 108 | /* Return the next nnn bits of input. All reads from the compressed input |
96 | are done through this function. All reads are big endian */ | 109 | are done through this function. All reads are big endian */ |
97 | |||
98 | static unsigned get_bits(bunzip_data *bd, int bits_wanted) | 110 | static unsigned get_bits(bunzip_data *bd, int bits_wanted) |
99 | { | 111 | { |
100 | unsigned bits = 0; | 112 | unsigned bits = 0; |
113 | /* Cache bd->inbufBitCount in a CPU register (hopefully): */ | ||
114 | int bit_count = bd->inbufBitCount; | ||
101 | 115 | ||
102 | /* If we need to get more data from the byte buffer, do so. (Loop getting | 116 | /* If we need to get more data from the byte buffer, do so. (Loop getting |
103 | one byte at a time to enforce endianness and avoid unaligned access.) */ | 117 | one byte at a time to enforce endianness and avoid unaligned access.) */ |
104 | while ((int)(bd->inbufBitCount) < bits_wanted) { | 118 | while (bit_count < bits_wanted) { |
105 | 119 | ||
106 | /* If we need to read more data from file into byte buffer, do so */ | 120 | /* If we need to read more data from file into byte buffer, do so */ |
107 | if (bd->inbufPos == bd->inbufCount) { | 121 | if (bd->inbufPos == bd->inbufCount) { |
@@ -113,41 +127,47 @@ static unsigned get_bits(bunzip_data *bd, int bits_wanted) | |||
113 | } | 127 | } |
114 | 128 | ||
115 | /* Avoid 32-bit overflow (dump bit buffer to top of output) */ | 129 | /* Avoid 32-bit overflow (dump bit buffer to top of output) */ |
116 | if (bd->inbufBitCount >= 24) { | 130 | if (bit_count >= 24) { |
117 | bits = bd->inbufBits & ((1 << bd->inbufBitCount) - 1); | 131 | bits = bd->inbufBits & ((1 << bit_count) - 1); |
118 | bits_wanted -= bd->inbufBitCount; | 132 | bits_wanted -= bit_count; |
119 | bits <<= bits_wanted; | 133 | bits <<= bits_wanted; |
120 | bd->inbufBitCount = 0; | 134 | bit_count = 0; |
121 | } | 135 | } |
122 | 136 | ||
123 | /* Grab next 8 bits of input from buffer. */ | 137 | /* Grab next 8 bits of input from buffer. */ |
124 | bd->inbufBits = (bd->inbufBits << 8) | bd->inbuf[bd->inbufPos++]; | 138 | bd->inbufBits = (bd->inbufBits << 8) | bd->inbuf[bd->inbufPos++]; |
125 | bd->inbufBitCount += 8; | 139 | bit_count += 8; |
126 | } | 140 | } |
127 | 141 | ||
128 | /* Calculate result */ | 142 | /* Calculate result */ |
129 | bd->inbufBitCount -= bits_wanted; | 143 | bit_count -= bits_wanted; |
130 | bits |= (bd->inbufBits >> bd->inbufBitCount) & ((1 << bits_wanted) - 1); | 144 | bd->inbufBitCount = bit_count; |
145 | bits |= (bd->inbufBits >> bit_count) & ((1 << bits_wanted) - 1); | ||
131 | 146 | ||
132 | return bits; | 147 | return bits; |
133 | } | 148 | } |
134 | 149 | ||
135 | /* Unpacks the next block and sets up for the inverse burrows-wheeler step. */ | 150 | /* Unpacks the next block and sets up for the inverse Burrows-Wheeler step. */ |
136 | static int get_next_block(bunzip_data *bd) | 151 | static int get_next_block(bunzip_data *bd) |
137 | { | 152 | { |
138 | struct group_data *hufGroup; | 153 | struct group_data *hufGroup; |
139 | int dbufCount, nextSym, dbufSize, groupCount, *base, *limit, selector, | 154 | int dbufCount, dbufSize, groupCount, *base, *limit, selector, |
140 | i, j, k, t, runPos, symCount, symTotal, nSelectors, byteCount[256]; | 155 | i, j, t, runPos, symCount, symTotal, nSelectors, byteCount[256]; |
141 | unsigned char uc, symToByte[256], mtfSymbol[256], *selectors; | 156 | int runCnt = runCnt; /* for compiler */ |
142 | unsigned *dbuf, origPtr; | 157 | uint8_t uc, symToByte[256], mtfSymbol[256], *selectors; |
158 | uint32_t *dbuf; | ||
159 | unsigned origPtr; | ||
143 | 160 | ||
144 | dbuf = bd->dbuf; | 161 | dbuf = bd->dbuf; |
145 | dbufSize = bd->dbufSize; | 162 | dbufSize = bd->dbufSize; |
146 | selectors = bd->selectors; | 163 | selectors = bd->selectors; |
147 | 164 | ||
165 | /* In bbox, we are ok with aborting through setjmp which is set up in start_bunzip */ | ||
166 | #if 0 | ||
148 | /* Reset longjmp I/O error handling */ | 167 | /* Reset longjmp I/O error handling */ |
149 | i = setjmp(bd->jmpbuf); | 168 | i = setjmp(bd->jmpbuf); |
150 | if (i) return i; | 169 | if (i) return i; |
170 | #endif | ||
151 | 171 | ||
152 | /* Read in header signature and CRC, then validate signature. | 172 | /* Read in header signature and CRC, then validate signature. |
153 | (last block signature means CRC is for whole file, return now) */ | 173 | (last block signature means CRC is for whole file, return now) */ |
@@ -169,16 +189,23 @@ static int get_next_block(bunzip_data *bd) | |||
169 | symbols to deal with, and writes a sparse bitfield indicating which | 189 | symbols to deal with, and writes a sparse bitfield indicating which |
170 | values were present. We make a translation table to convert the symbols | 190 | values were present. We make a translation table to convert the symbols |
171 | back to the corresponding bytes. */ | 191 | back to the corresponding bytes. */ |
172 | t = get_bits(bd, 16); | ||
173 | symTotal = 0; | 192 | symTotal = 0; |
174 | for (i = 0; i < 16; i++) { | 193 | i = 0; |
175 | if (t & (1 << (15-i))) { | 194 | t = get_bits(bd, 16); |
176 | k = get_bits(bd, 16); | 195 | do { |
177 | for (j = 0; j < 16; j++) | 196 | if (t & (1 << 15)) { |
178 | if (k & (1 << (15-j))) | 197 | unsigned inner_map = get_bits(bd, 16); |
179 | symToByte[symTotal++] = (16*i) + j; | 198 | do { |
199 | if (inner_map & (1 << 15)) | ||
200 | symToByte[symTotal++] = i; | ||
201 | inner_map <<= 1; | ||
202 | i++; | ||
203 | } while (i & 15); | ||
204 | i -= 16; | ||
180 | } | 205 | } |
181 | } | 206 | t <<= 1; |
207 | i += 16; | ||
208 | } while (i < 256); | ||
182 | 209 | ||
183 | /* How many different Huffman coding groups does this block use? */ | 210 | /* How many different Huffman coding groups does this block use? */ |
184 | groupCount = get_bits(bd, 3); | 211 | groupCount = get_bits(bd, 3); |
@@ -189,57 +216,63 @@ static int get_next_block(bunzip_data *bd) | |||
189 | group. Read in the group selector list, which is stored as MTF encoded | 216 | group. Read in the group selector list, which is stored as MTF encoded |
190 | bit runs. (MTF=Move To Front, as each value is used it's moved to the | 217 | bit runs. (MTF=Move To Front, as each value is used it's moved to the |
191 | start of the list.) */ | 218 | start of the list.) */ |
219 | for (i = 0; i < groupCount; i++) | ||
220 | mtfSymbol[i] = i; | ||
192 | nSelectors = get_bits(bd, 15); | 221 | nSelectors = get_bits(bd, 15); |
193 | if (!nSelectors) return RETVAL_DATA_ERROR; | 222 | if (!nSelectors) |
194 | for (i = 0; i < groupCount; i++) mtfSymbol[i] = i; | 223 | return RETVAL_DATA_ERROR; |
195 | for (i = 0; i < nSelectors; i++) { | 224 | for (i = 0; i < nSelectors; i++) { |
196 | 225 | uint8_t tmp_byte; | |
197 | /* Get next value */ | 226 | /* Get next value */ |
198 | for (j = 0; get_bits(bd, 1); j++) | 227 | int n = 0; |
199 | if (j >= groupCount) return RETVAL_DATA_ERROR; | 228 | while (get_bits(bd, 1)) { |
200 | 229 | if (n >= groupCount) return RETVAL_DATA_ERROR; | |
230 | n++; | ||
231 | } | ||
201 | /* Decode MTF to get the next selector */ | 232 | /* Decode MTF to get the next selector */ |
202 | uc = mtfSymbol[j]; | 233 | tmp_byte = mtfSymbol[n]; |
203 | for (;j;j--) mtfSymbol[j] = mtfSymbol[j-1]; | 234 | while (--n >= 0) |
204 | mtfSymbol[0] = selectors[i] = uc; | 235 | mtfSymbol[n + 1] = mtfSymbol[n]; |
236 | mtfSymbol[0] = selectors[i] = tmp_byte; | ||
205 | } | 237 | } |
206 | 238 | ||
207 | /* Read the Huffman coding tables for each group, which code for symTotal | 239 | /* Read the Huffman coding tables for each group, which code for symTotal |
208 | literal symbols, plus two run symbols (RUNA, RUNB) */ | 240 | literal symbols, plus two run symbols (RUNA, RUNB) */ |
209 | symCount = symTotal + 2; | 241 | symCount = symTotal + 2; |
210 | for (j = 0; j < groupCount; j++) { | 242 | for (j = 0; j < groupCount; j++) { |
211 | unsigned char length[MAX_SYMBOLS]; | 243 | uint8_t length[MAX_SYMBOLS]; |
212 | /* 8 bits is ALMOST enough for temp[], see below */ | 244 | /* 8 bits is ALMOST enough for temp[], see below */ |
213 | unsigned temp[MAX_HUFCODE_BITS+1]; | 245 | unsigned temp[MAX_HUFCODE_BITS+1]; |
214 | int minLen, maxLen, pp; | 246 | int minLen, maxLen, pp, len_m1; |
215 | 247 | ||
216 | /* Read Huffman code lengths for each symbol. They're stored in | 248 | /* Read Huffman code lengths for each symbol. They're stored in |
217 | a way similar to mtf; record a starting value for the first symbol, | 249 | a way similar to mtf; record a starting value for the first symbol, |
218 | and an offset from the previous value for everys symbol after that. | 250 | and an offset from the previous value for every symbol after that. |
219 | (Subtracting 1 before the loop and then adding it back at the end is | 251 | (Subtracting 1 before the loop and then adding it back at the end is |
220 | an optimization that makes the test inside the loop simpler: symbol | 252 | an optimization that makes the test inside the loop simpler: symbol |
221 | length 0 becomes negative, so an unsigned inequality catches it.) */ | 253 | length 0 becomes negative, so an unsigned inequality catches it.) */ |
222 | t = get_bits(bd, 5) - 1; | 254 | len_m1 = get_bits(bd, 5) - 1; |
223 | for (i = 0; i < symCount; i++) { | 255 | for (i = 0; i < symCount; i++) { |
224 | for (;;) { | 256 | for (;;) { |
225 | if ((unsigned)t > (MAX_HUFCODE_BITS-1)) | 257 | int two_bits; |
258 | if ((unsigned)len_m1 > (MAX_HUFCODE_BITS-1)) | ||
226 | return RETVAL_DATA_ERROR; | 259 | return RETVAL_DATA_ERROR; |
227 | 260 | ||
228 | /* If first bit is 0, stop. Else second bit indicates whether | 261 | /* If first bit is 0, stop. Else second bit indicates whether |
229 | to increment or decrement the value. Optimization: grab 2 | 262 | to increment or decrement the value. Optimization: grab 2 |
230 | bits and unget the second if the first was 0. */ | 263 | bits and unget the second if the first was 0. */ |
231 | k = get_bits(bd, 2); | 264 | two_bits = get_bits(bd, 2); |
232 | if (k < 2) { | 265 | if (two_bits < 2) { |
233 | bd->inbufBitCount++; | 266 | bd->inbufBitCount++; |
234 | break; | 267 | break; |
235 | } | 268 | } |
236 | 269 | ||
237 | /* Add one if second bit 1, else subtract 1. Avoids if/else */ | 270 | /* Add one if second bit 1, else subtract 1. Avoids if/else */ |
238 | t += (((k+1) & 2) - 1); | 271 | len_m1 += (((two_bits+1) & 2) - 1); |
239 | } | 272 | } |
240 | 273 | ||
241 | /* Correct for the initial -1, to get the final symbol length */ | 274 | /* Correct for the initial -1, to get the final symbol length */ |
242 | length[i] = t + 1; | 275 | length[i] = len_m1 + 1; |
243 | } | 276 | } |
244 | 277 | ||
245 | /* Find largest and smallest lengths in this group */ | 278 | /* Find largest and smallest lengths in this group */ |
@@ -265,17 +298,18 @@ static int get_next_block(bunzip_data *bd) | |||
265 | 298 | ||
266 | /* Note that minLen can't be smaller than 1, so we adjust the base | 299 | /* Note that minLen can't be smaller than 1, so we adjust the base |
267 | and limit array pointers so we're not always wasting the first | 300 | and limit array pointers so we're not always wasting the first |
268 | entry. We do this again when using them (during symbol decoding).*/ | 301 | entry. We do this again when using them (during symbol decoding). */ |
269 | base = hufGroup->base - 1; | 302 | base = hufGroup->base - 1; |
270 | limit = hufGroup->limit - 1; | 303 | limit = hufGroup->limit - 1; |
271 | 304 | ||
272 | /* Calculate permute[]. Concurently, initialize temp[] and limit[]. */ | 305 | /* Calculate permute[]. Concurently, initialize temp[] and limit[]. */ |
273 | pp = 0; | 306 | pp = 0; |
274 | for (i = minLen; i <= maxLen; i++) { | 307 | for (i = minLen; i <= maxLen; i++) { |
308 | int k; | ||
275 | temp[i] = limit[i] = 0; | 309 | temp[i] = limit[i] = 0; |
276 | for (t = 0; t < symCount; t++) | 310 | for (k = 0; k < symCount; k++) |
277 | if (length[t] == i) | 311 | if (length[k] == i) |
278 | hufGroup->permute[pp++] = t; | 312 | hufGroup->permute[pp++] = k; |
279 | } | 313 | } |
280 | 314 | ||
281 | /* Count symbols coded for at each bit length */ | 315 | /* Count symbols coded for at each bit length */ |
@@ -288,8 +322,10 @@ static int get_next_block(bunzip_data *bd) | |||
288 | * base[] (number of symbols to ignore at each bit length, which is | 322 | * base[] (number of symbols to ignore at each bit length, which is |
289 | * limit minus the cumulative count of symbols coded for already). */ | 323 | * limit minus the cumulative count of symbols coded for already). */ |
290 | pp = t = 0; | 324 | pp = t = 0; |
291 | for (i = minLen; i < maxLen; i++) { | 325 | for (i = minLen; i < maxLen;) { |
292 | pp += temp[i]; | 326 | unsigned temp_i = temp[i]; |
327 | |||
328 | pp += temp_i; | ||
293 | 329 | ||
294 | /* We read the largest possible symbol size and then unget bits | 330 | /* We read the largest possible symbol size and then unget bits |
295 | after determining how many we need, and those extra bits could | 331 | after determining how many we need, and those extra bits could |
@@ -299,11 +335,11 @@ static int get_next_block(bunzip_data *bd) | |||
299 | don't affect the value>limit[length] comparison. */ | 335 | don't affect the value>limit[length] comparison. */ |
300 | limit[i] = (pp << (maxLen - i)) - 1; | 336 | limit[i] = (pp << (maxLen - i)) - 1; |
301 | pp <<= 1; | 337 | pp <<= 1; |
302 | t += temp[i]; | 338 | t += temp_i; |
303 | base[i+1] = pp - t; | 339 | base[++i] = pp - t; |
304 | } | 340 | } |
305 | limit[maxLen+1] = INT_MAX; /* Sentinel value for reading next sym. */ | ||
306 | limit[maxLen] = pp + temp[maxLen] - 1; | 341 | limit[maxLen] = pp + temp[maxLen] - 1; |
342 | limit[maxLen+1] = INT_MAX; /* Sentinel value for reading next sym. */ | ||
307 | base[minLen] = 0; | 343 | base[minLen] = 0; |
308 | } | 344 | } |
309 | 345 | ||
@@ -312,16 +348,17 @@ static int get_next_block(bunzip_data *bd) | |||
312 | and run length encoding, saving the result into dbuf[dbufCount++] = uc */ | 348 | and run length encoding, saving the result into dbuf[dbufCount++] = uc */ |
313 | 349 | ||
314 | /* Initialize symbol occurrence counters and symbol Move To Front table */ | 350 | /* Initialize symbol occurrence counters and symbol Move To Front table */ |
315 | memset(byteCount, 0, sizeof(byteCount)); /* smaller, maybe slower? */ | 351 | /*memset(byteCount, 0, sizeof(byteCount)); - smaller, but slower */ |
316 | for (i = 0; i < 256; i++) { | 352 | for (i = 0; i < 256; i++) { |
317 | //byteCount[i] = 0; | 353 | byteCount[i] = 0; |
318 | mtfSymbol[i] = (unsigned char)i; | 354 | mtfSymbol[i] = (uint8_t)i; |
319 | } | 355 | } |
320 | 356 | ||
321 | /* Loop through compressed symbols. */ | 357 | /* Loop through compressed symbols. */ |
322 | 358 | ||
323 | runPos = dbufCount = selector = 0; | 359 | runPos = dbufCount = selector = 0; |
324 | for (;;) { | 360 | for (;;) { |
361 | int nextSym; | ||
325 | 362 | ||
326 | /* Fetch next Huffman coding group from list. */ | 363 | /* Fetch next Huffman coding group from list. */ |
327 | symCount = GROUP_SIZE - 1; | 364 | symCount = GROUP_SIZE - 1; |
@@ -329,44 +366,49 @@ static int get_next_block(bunzip_data *bd) | |||
329 | hufGroup = bd->groups + selectors[selector++]; | 366 | hufGroup = bd->groups + selectors[selector++]; |
330 | base = hufGroup->base - 1; | 367 | base = hufGroup->base - 1; |
331 | limit = hufGroup->limit - 1; | 368 | limit = hufGroup->limit - 1; |
332 | continue_this_group: | ||
333 | 369 | ||
370 | continue_this_group: | ||
334 | /* Read next Huffman-coded symbol. */ | 371 | /* Read next Huffman-coded symbol. */ |
335 | 372 | ||
336 | /* Note: It is far cheaper to read maxLen bits and back up than it is | 373 | /* Note: It is far cheaper to read maxLen bits and back up than it is |
337 | to read minLen bits and then an additional bit at a time, testing | 374 | to read minLen bits and then add additional bit at a time, testing |
338 | as we go. Because there is a trailing last block (with file CRC), | 375 | as we go. Because there is a trailing last block (with file CRC), |
339 | there is no danger of the overread causing an unexpected EOF for a | 376 | there is no danger of the overread causing an unexpected EOF for a |
340 | valid compressed file. As a further optimization, we do the read | 377 | valid compressed file. |
341 | inline (falling back to a call to get_bits if the buffer runs | ||
342 | dry). The following (up to got_huff_bits:) is equivalent to | ||
343 | j = get_bits(bd, hufGroup->maxLen); | ||
344 | */ | 378 | */ |
345 | while ((int)(bd->inbufBitCount) < hufGroup->maxLen) { | 379 | if (1) { |
346 | if (bd->inbufPos == bd->inbufCount) { | 380 | /* As a further optimization, we do the read inline |
347 | j = get_bits(bd, hufGroup->maxLen); | 381 | (falling back to a call to get_bits if the buffer runs dry). |
348 | goto got_huff_bits; | 382 | */ |
349 | } | 383 | int new_cnt; |
350 | bd->inbufBits = (bd->inbufBits << 8) | bd->inbuf[bd->inbufPos++]; | 384 | while ((new_cnt = bd->inbufBitCount - hufGroup->maxLen) < 0) { |
351 | bd->inbufBitCount += 8; | 385 | /* bd->inbufBitCount < hufGroup->maxLen */ |
352 | }; | 386 | if (bd->inbufPos == bd->inbufCount) { |
353 | bd->inbufBitCount -= hufGroup->maxLen; | 387 | nextSym = get_bits(bd, hufGroup->maxLen); |
354 | j = (bd->inbufBits >> bd->inbufBitCount) & ((1 << hufGroup->maxLen) - 1); | 388 | goto got_huff_bits; |
355 | 389 | } | |
356 | got_huff_bits: | 390 | bd->inbufBits = (bd->inbufBits << 8) | bd->inbuf[bd->inbufPos++]; |
357 | 391 | bd->inbufBitCount += 8; | |
358 | /* Figure how how many bits are in next symbol and unget extras */ | 392 | }; |
393 | bd->inbufBitCount = new_cnt; /* "bd->inbufBitCount -= hufGroup->maxLen;" */ | ||
394 | nextSym = (bd->inbufBits >> new_cnt) & ((1 << hufGroup->maxLen) - 1); | ||
395 | got_huff_bits: ; | ||
396 | } else { /* unoptimized equivalent */ | ||
397 | nextSym = get_bits(bd, hufGroup->maxLen); | ||
398 | } | ||
399 | /* Figure how many bits are in next symbol and unget extras */ | ||
359 | i = hufGroup->minLen; | 400 | i = hufGroup->minLen; |
360 | while (j > limit[i]) ++i; | 401 | while (nextSym > limit[i]) ++i; |
361 | bd->inbufBitCount += (hufGroup->maxLen - i); | 402 | j = hufGroup->maxLen - i; |
403 | if (j < 0) | ||
404 | return RETVAL_DATA_ERROR; | ||
405 | bd->inbufBitCount += j; | ||
362 | 406 | ||
363 | /* Huffman decode value to get nextSym (with bounds checking) */ | 407 | /* Huffman decode value to get nextSym (with bounds checking) */ |
364 | if (i > hufGroup->maxLen) | 408 | nextSym = (nextSym >> j) - base[i]; |
409 | if ((unsigned)nextSym >= MAX_SYMBOLS) | ||
365 | return RETVAL_DATA_ERROR; | 410 | return RETVAL_DATA_ERROR; |
366 | j = (j >> (hufGroup->maxLen - i)) - base[i]; | 411 | nextSym = hufGroup->permute[nextSym]; |
367 | if ((unsigned)j >= MAX_SYMBOLS) | ||
368 | return RETVAL_DATA_ERROR; | ||
369 | nextSym = hufGroup->permute[j]; | ||
370 | 412 | ||
371 | /* We have now decoded the symbol, which indicates either a new literal | 413 | /* We have now decoded the symbol, which indicates either a new literal |
372 | byte, or a repeated run of the most recent literal byte. First, | 414 | byte, or a repeated run of the most recent literal byte. First, |
@@ -375,9 +417,9 @@ static int get_next_block(bunzip_data *bd) | |||
375 | if ((unsigned)nextSym <= SYMBOL_RUNB) { /* RUNA or RUNB */ | 417 | if ((unsigned)nextSym <= SYMBOL_RUNB) { /* RUNA or RUNB */ |
376 | 418 | ||
377 | /* If this is the start of a new run, zero out counter */ | 419 | /* If this is the start of a new run, zero out counter */ |
378 | if (!runPos) { | 420 | if (runPos == 0) { |
379 | runPos = 1; | 421 | runPos = 1; |
380 | t = 0; | 422 | runCnt = 0; |
381 | } | 423 | } |
382 | 424 | ||
383 | /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at | 425 | /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at |
@@ -387,7 +429,7 @@ static int get_next_block(bunzip_data *bd) | |||
387 | the basic or 0/1 method (except all bits 0, which would use no | 429 | the basic or 0/1 method (except all bits 0, which would use no |
388 | symbols, but a run of length 0 doesn't mean anything in this | 430 | symbols, but a run of length 0 doesn't mean anything in this |
389 | context). Thus space is saved. */ | 431 | context). Thus space is saved. */ |
390 | t += (runPos << nextSym); /* +runPos if RUNA; +2*runPos if RUNB */ | 432 | runCnt += (runPos << nextSym); /* +runPos if RUNA; +2*runPos if RUNB */ |
391 | if (runPos < dbufSize) runPos <<= 1; | 433 | if (runPos < dbufSize) runPos <<= 1; |
392 | goto end_of_huffman_loop; | 434 | goto end_of_huffman_loop; |
393 | } | 435 | } |
@@ -396,13 +438,13 @@ static int get_next_block(bunzip_data *bd) | |||
396 | how many times to repeat the last literal, so append that many | 438 | how many times to repeat the last literal, so append that many |
397 | copies to our buffer of decoded symbols (dbuf) now. (The last | 439 | copies to our buffer of decoded symbols (dbuf) now. (The last |
398 | literal used is the one at the head of the mtfSymbol array.) */ | 440 | literal used is the one at the head of the mtfSymbol array.) */ |
399 | if (runPos) { | 441 | if (runPos != 0) { |
442 | uint8_t tmp_byte; | ||
443 | if (dbufCount + runCnt >= dbufSize) return RETVAL_DATA_ERROR; | ||
444 | tmp_byte = symToByte[mtfSymbol[0]]; | ||
445 | byteCount[tmp_byte] += runCnt; | ||
446 | while (--runCnt >= 0) dbuf[dbufCount++] = (uint32_t)tmp_byte; | ||
400 | runPos = 0; | 447 | runPos = 0; |
401 | if (dbufCount + t >= dbufSize) return RETVAL_DATA_ERROR; | ||
402 | |||
403 | uc = symToByte[mtfSymbol[0]]; | ||
404 | byteCount[uc] += t; | ||
405 | while (t--) dbuf[dbufCount++] = uc; | ||
406 | } | 448 | } |
407 | 449 | ||
408 | /* Is this the terminating symbol? */ | 450 | /* Is this the terminating symbol? */ |
@@ -431,12 +473,12 @@ static int get_next_block(bunzip_data *bd) | |||
431 | 473 | ||
432 | /* We have our literal byte. Save it into dbuf. */ | 474 | /* We have our literal byte. Save it into dbuf. */ |
433 | byteCount[uc]++; | 475 | byteCount[uc]++; |
434 | dbuf[dbufCount++] = (unsigned)uc; | 476 | dbuf[dbufCount++] = (uint32_t)uc; |
435 | 477 | ||
436 | /* Skip group initialization if we're not done with this group. Done | 478 | /* Skip group initialization if we're not done with this group. Done |
437 | * this way to avoid compiler warning. */ | 479 | * this way to avoid compiler warning. */ |
438 | end_of_huffman_loop: | 480 | end_of_huffman_loop: |
439 | if (symCount--) goto continue_this_group; | 481 | if (--symCount >= 0) goto continue_this_group; |
440 | } | 482 | } |
441 | 483 | ||
442 | /* At this point, we've read all the Huffman-coded symbols (and repeated | 484 | /* At this point, we've read all the Huffman-coded symbols (and repeated |
@@ -449,26 +491,28 @@ static int get_next_block(bunzip_data *bd) | |||
449 | /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */ | 491 | /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */ |
450 | j = 0; | 492 | j = 0; |
451 | for (i = 0; i < 256; i++) { | 493 | for (i = 0; i < 256; i++) { |
452 | k = j + byteCount[i]; | 494 | int tmp_count = j + byteCount[i]; |
453 | byteCount[i] = j; | 495 | byteCount[i] = j; |
454 | j = k; | 496 | j = tmp_count; |
455 | } | 497 | } |
456 | 498 | ||
457 | /* Figure out what order dbuf would be in if we sorted it. */ | 499 | /* Figure out what order dbuf would be in if we sorted it. */ |
458 | for (i = 0; i < dbufCount; i++) { | 500 | for (i = 0; i < dbufCount; i++) { |
459 | uc = (unsigned char)(dbuf[i] & 0xff); | 501 | uint8_t tmp_byte = (uint8_t)dbuf[i]; |
460 | dbuf[byteCount[uc]] |= (i << 8); | 502 | int tmp_count = byteCount[tmp_byte]; |
461 | byteCount[uc]++; | 503 | dbuf[tmp_count] |= (i << 8); |
504 | byteCount[tmp_byte] = tmp_count + 1; | ||
462 | } | 505 | } |
463 | 506 | ||
464 | /* Decode first byte by hand to initialize "previous" byte. Note that it | 507 | /* Decode first byte by hand to initialize "previous" byte. Note that it |
465 | doesn't get output, and if the first three characters are identical | 508 | doesn't get output, and if the first three characters are identical |
466 | it doesn't qualify as a run (hence writeRunCountdown=5). */ | 509 | it doesn't qualify as a run (hence writeRunCountdown=5). */ |
467 | if (dbufCount) { | 510 | if (dbufCount) { |
511 | uint32_t tmp; | ||
468 | if ((int)origPtr >= dbufCount) return RETVAL_DATA_ERROR; | 512 | if ((int)origPtr >= dbufCount) return RETVAL_DATA_ERROR; |
469 | bd->writePos = dbuf[origPtr]; | 513 | tmp = dbuf[origPtr]; |
470 | bd->writeCurrent = (unsigned char)(bd->writePos & 0xff); | 514 | bd->writeCurrent = (uint8_t)tmp; |
471 | bd->writePos >>= 8; | 515 | bd->writePos = (tmp >> 8); |
472 | bd->writeRunCountdown = 5; | 516 | bd->writeRunCountdown = 5; |
473 | } | 517 | } |
474 | bd->writeCount = dbufCount; | 518 | bd->writeCount = dbufCount; |
@@ -476,70 +520,84 @@ static int get_next_block(bunzip_data *bd) | |||
476 | return RETVAL_OK; | 520 | return RETVAL_OK; |
477 | } | 521 | } |
478 | 522 | ||
479 | /* Undo burrows-wheeler transform on intermediate buffer to produce output. | 523 | /* Undo Burrows-Wheeler transform on intermediate buffer to produce output. |
480 | If start_bunzip was initialized with out_fd=-1, then up to len bytes of | 524 | If start_bunzip was initialized with out_fd=-1, then up to len bytes of |
481 | data are written to outbuf. Return value is number of bytes written or | 525 | data are written to outbuf. Return value is number of bytes written or |
482 | error (all errors are negative numbers). If out_fd!=-1, outbuf and len | 526 | error (all errors are negative numbers). If out_fd!=-1, outbuf and len |
483 | are ignored, data is written to out_fd and return is RETVAL_OK or error. | 527 | are ignored, data is written to out_fd and return is RETVAL_OK or error. |
528 | |||
529 | NB: read_bunzip returns < 0 on error, or the number of *unfilled* bytes | ||
530 | in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0. | ||
531 | (Why? This allows to get rid of one local variable) | ||
484 | */ | 532 | */ |
485 | int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) | 533 | int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) |
486 | { | 534 | { |
487 | const unsigned *dbuf; | 535 | const uint32_t *dbuf; |
488 | int pos, current, previous, gotcount; | 536 | int pos, current, previous; |
537 | uint32_t CRC; | ||
489 | 538 | ||
490 | /* If last read was short due to end of file, return last block now */ | 539 | /* If we already have error/end indicator, return it */ |
491 | if (bd->writeCount < 0) return bd->writeCount; | 540 | if (bd->writeCount < 0) |
541 | return bd->writeCount; | ||
492 | 542 | ||
493 | gotcount = 0; | ||
494 | dbuf = bd->dbuf; | 543 | dbuf = bd->dbuf; |
544 | |||
545 | /* Register-cached state (hopefully): */ | ||
495 | pos = bd->writePos; | 546 | pos = bd->writePos; |
496 | current = bd->writeCurrent; | 547 | current = bd->writeCurrent; |
548 | CRC = bd->writeCRC; /* small loss on x86-32 (not enough regs), win on x86-64 */ | ||
497 | 549 | ||
498 | /* We will always have pending decoded data to write into the output | 550 | /* We will always have pending decoded data to write into the output |
499 | buffer unless this is the very first call (in which case we haven't | 551 | buffer unless this is the very first call (in which case we haven't |
500 | Huffman-decoded a block into the intermediate buffer yet). */ | 552 | Huffman-decoded a block into the intermediate buffer yet). */ |
501 | if (bd->writeCopies) { | 553 | if (bd->writeCopies) { |
502 | 554 | ||
555 | dec_writeCopies: | ||
503 | /* Inside the loop, writeCopies means extra copies (beyond 1) */ | 556 | /* Inside the loop, writeCopies means extra copies (beyond 1) */ |
504 | --bd->writeCopies; | 557 | --bd->writeCopies; |
505 | 558 | ||
506 | /* Loop outputting bytes */ | 559 | /* Loop outputting bytes */ |
507 | for (;;) { | 560 | for (;;) { |
508 | 561 | ||
509 | /* If the output buffer is full, snapshot state and return */ | 562 | /* If the output buffer is full, save cached state and return */ |
510 | if (gotcount >= len) { | 563 | if (--len < 0) { |
511 | bd->writePos = pos; | 564 | /* Unlikely branch. |
512 | bd->writeCurrent = current; | 565 | * Use of "goto" instead of keeping code here |
513 | bd->writeCopies++; | 566 | * helps compiler to realize this. */ |
514 | return len; | 567 | goto outbuf_full; |
515 | } | 568 | } |
516 | 569 | ||
517 | /* Write next byte into output buffer, updating CRC */ | 570 | /* Write next byte into output buffer, updating CRC */ |
518 | outbuf[gotcount++] = current; | 571 | *outbuf++ = current; |
519 | bd->writeCRC = (bd->writeCRC << 8) | 572 | CRC = (CRC << 8) ^ bd->crc32Table[(CRC >> 24) ^ current]; |
520 | ^ bd->crc32Table[(bd->writeCRC >> 24) ^ current]; | ||
521 | 573 | ||
522 | /* Loop now if we're outputting multiple copies of this byte */ | 574 | /* Loop now if we're outputting multiple copies of this byte */ |
523 | if (bd->writeCopies) { | 575 | if (bd->writeCopies) { |
524 | --bd->writeCopies; | 576 | /* Unlikely branch */ |
525 | continue; | 577 | /*--bd->writeCopies;*/ |
578 | /*continue;*/ | ||
579 | /* Same, but (ab)using other existing --writeCopies operation | ||
580 | * (and this if() compiles into just test+branch pair): */ | ||
581 | goto dec_writeCopies; | ||
526 | } | 582 | } |
527 | decode_next_byte: | 583 | decode_next_byte: |
528 | if (!bd->writeCount--) break; | 584 | if (--bd->writeCount < 0) |
585 | break; /* input block is fully consumed, need next one */ | ||
586 | |||
529 | /* Follow sequence vector to undo Burrows-Wheeler transform */ | 587 | /* Follow sequence vector to undo Burrows-Wheeler transform */ |
530 | previous = current; | 588 | previous = current; |
531 | pos = dbuf[pos]; | 589 | pos = dbuf[pos]; |
532 | current = pos & 0xff; | 590 | current = (uint8_t)pos; |
533 | pos >>= 8; | 591 | pos >>= 8; |
534 | 592 | ||
535 | /* After 3 consecutive copies of the same byte, the 4th | 593 | /* After 3 consecutive copies of the same byte, the 4th |
536 | * is a repeat count. We count down from 4 instead | 594 | * is a repeat count. We count down from 4 instead |
537 | * of counting up because testing for non-zero is faster */ | 595 | * of counting up because testing for non-zero is faster */ |
538 | if (--bd->writeRunCountdown) { | 596 | if (--bd->writeRunCountdown != 0) { |
539 | if (current != previous) | 597 | if (current != previous) |
540 | bd->writeRunCountdown = 4; | 598 | bd->writeRunCountdown = 4; |
541 | } else { | 599 | } else { |
542 | 600 | /* Unlikely branch */ | |
543 | /* We have a repeated run, this byte indicates the count */ | 601 | /* We have a repeated run, this byte indicates the count */ |
544 | bd->writeCopies = current; | 602 | bd->writeCopies = current; |
545 | current = previous; | 603 | current = previous; |
@@ -551,30 +609,42 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) | |||
551 | /* Subtract the 1 copy we'd output anyway to get extras */ | 609 | /* Subtract the 1 copy we'd output anyway to get extras */ |
552 | --bd->writeCopies; | 610 | --bd->writeCopies; |
553 | } | 611 | } |
554 | } | 612 | } /* for(;;) */ |
555 | 613 | ||
556 | /* Decompression of this block completed successfully */ | 614 | /* Decompression of this input block completed successfully */ |
557 | bd->writeCRC = ~bd->writeCRC; | 615 | bd->writeCRC = CRC = ~CRC; |
558 | bd->totalCRC = ((bd->totalCRC << 1) | (bd->totalCRC >> 31)) ^ bd->writeCRC; | 616 | bd->totalCRC = ((bd->totalCRC << 1) | (bd->totalCRC >> 31)) ^ CRC; |
559 | 617 | ||
560 | /* If this block had a CRC error, force file level CRC error. */ | 618 | /* If this block had a CRC error, force file level CRC error */ |
561 | if (bd->writeCRC != bd->headerCRC) { | 619 | if (CRC != bd->headerCRC) { |
562 | bd->totalCRC = bd->headerCRC + 1; | 620 | bd->totalCRC = bd->headerCRC + 1; |
563 | return RETVAL_LAST_BLOCK; | 621 | return RETVAL_LAST_BLOCK; |
564 | } | 622 | } |
565 | } | 623 | } |
566 | 624 | ||
567 | /* Refill the intermediate buffer by Huffman-decoding next block of input */ | 625 | /* Refill the intermediate buffer by Huffman-decoding next block of input */ |
568 | /* (previous is just a convenient unused temp variable here) */ | 626 | { |
569 | previous = get_next_block(bd); | 627 | int r = get_next_block(bd); |
570 | if (previous) { | 628 | if (r) { /* error/end */ |
571 | bd->writeCount = previous; | 629 | bd->writeCount = r; |
572 | return (previous != RETVAL_LAST_BLOCK) ? previous : gotcount; | 630 | return (r != RETVAL_LAST_BLOCK) ? r : len; |
631 | } | ||
573 | } | 632 | } |
574 | bd->writeCRC = ~0; | 633 | |
634 | CRC = ~0; | ||
575 | pos = bd->writePos; | 635 | pos = bd->writePos; |
576 | current = bd->writeCurrent; | 636 | current = bd->writeCurrent; |
577 | goto decode_next_byte; | 637 | goto decode_next_byte; |
638 | |||
639 | outbuf_full: | ||
640 | /* Output buffer is full, save cached state and return */ | ||
641 | bd->writePos = pos; | ||
642 | bd->writeCurrent = current; | ||
643 | bd->writeCRC = CRC; | ||
644 | |||
645 | bd->writeCopies++; | ||
646 | |||
647 | return 0; | ||
578 | } | 648 | } |
579 | 649 | ||
580 | /* Allocate the structure, read file header. If in_fd==-1, inbuf must contain | 650 | /* Allocate the structure, read file header. If in_fd==-1, inbuf must contain |
@@ -584,8 +654,8 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) | |||
584 | /* Because bunzip2 is used for help text unpacking, and because bb_show_usage() | 654 | /* Because bunzip2 is used for help text unpacking, and because bb_show_usage() |
585 | should work for NOFORK applets too, we must be extremely careful to not leak | 655 | should work for NOFORK applets too, we must be extremely careful to not leak |
586 | any allocations! */ | 656 | any allocations! */ |
587 | int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd, const unsigned char *inbuf, | 657 | int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd, |
588 | int len) | 658 | const void *inbuf, int len) |
589 | { | 659 | { |
590 | bunzip_data *bd; | 660 | bunzip_data *bd; |
591 | unsigned i; | 661 | unsigned i; |
@@ -606,9 +676,11 @@ int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd, const unsigned char *in | |||
606 | if (-1 == in_fd) { | 676 | if (-1 == in_fd) { |
607 | /* in this case, bd->inbuf is read-only */ | 677 | /* in this case, bd->inbuf is read-only */ |
608 | bd->inbuf = (void*)inbuf; /* cast away const-ness */ | 678 | bd->inbuf = (void*)inbuf; /* cast away const-ness */ |
609 | bd->inbufCount = len; | 679 | } else { |
610 | } else | 680 | bd->inbuf = (uint8_t*)(bd + 1); |
611 | bd->inbuf = (unsigned char *)(bd + 1); | 681 | memcpy(bd->inbuf, inbuf, len); |
682 | } | ||
683 | bd->inbufCount = len; | ||
612 | 684 | ||
613 | /* Init the CRC32 table (big endian) */ | 685 | /* Init the CRC32 table (big endian) */ |
614 | crc32_filltable(bd->crc32Table, 1); | 686 | crc32_filltable(bd->crc32Table, 1); |
@@ -632,7 +704,7 @@ int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd, const unsigned char *in | |||
632 | bd->dbufSize = 100000 * (i - h0); | 704 | bd->dbufSize = 100000 * (i - h0); |
633 | 705 | ||
634 | /* Cannot use xmalloc - may leak bd in NOFORK case! */ | 706 | /* Cannot use xmalloc - may leak bd in NOFORK case! */ |
635 | bd->dbuf = malloc_or_warn(bd->dbufSize * sizeof(int)); | 707 | bd->dbuf = malloc_or_warn(bd->dbufSize * sizeof(bd->dbuf[0])); |
636 | if (!bd->dbuf) { | 708 | if (!bd->dbuf) { |
637 | free(bd); | 709 | free(bd); |
638 | xfunc_die(); | 710 | xfunc_die(); |
@@ -652,37 +724,63 @@ IF_DESKTOP(long long) int FAST_FUNC | |||
652 | unpack_bz2_stream(int src_fd, int dst_fd) | 724 | unpack_bz2_stream(int src_fd, int dst_fd) |
653 | { | 725 | { |
654 | IF_DESKTOP(long long total_written = 0;) | 726 | IF_DESKTOP(long long total_written = 0;) |
655 | char *outbuf; | ||
656 | bunzip_data *bd; | 727 | bunzip_data *bd; |
728 | char *outbuf; | ||
657 | int i; | 729 | int i; |
730 | unsigned len; | ||
658 | 731 | ||
659 | outbuf = xmalloc(IOBUF_SIZE); | 732 | outbuf = xmalloc(IOBUF_SIZE); |
660 | i = start_bunzip(&bd, src_fd, NULL, 0); | 733 | len = 0; |
661 | if (!i) { | 734 | while (1) { /* "Process one BZ... stream" loop */ |
662 | for (;;) { | 735 | |
663 | i = read_bunzip(bd, outbuf, IOBUF_SIZE); | 736 | i = start_bunzip(&bd, src_fd, outbuf + 2, len); |
664 | if (i <= 0) break; | 737 | |
665 | if (i != full_write(dst_fd, outbuf, i)) { | 738 | if (i == 0) { |
666 | i = RETVAL_SHORT_WRITE; | 739 | while (1) { /* "Produce some output bytes" loop */ |
667 | break; | 740 | i = read_bunzip(bd, outbuf, IOBUF_SIZE); |
741 | if (i < 0) /* error? */ | ||
742 | break; | ||
743 | i = IOBUF_SIZE - i; /* number of bytes produced */ | ||
744 | if (i == 0) /* EOF? */ | ||
745 | break; | ||
746 | if (i != full_write(dst_fd, outbuf, i)) { | ||
747 | bb_error_msg("short write"); | ||
748 | i = RETVAL_SHORT_WRITE; | ||
749 | goto release_mem; | ||
750 | } | ||
751 | IF_DESKTOP(total_written += i;) | ||
668 | } | 752 | } |
669 | IF_DESKTOP(total_written += i;) | ||
670 | } | 753 | } |
671 | } | ||
672 | |||
673 | /* Check CRC and release memory */ | ||
674 | 754 | ||
675 | if (i == RETVAL_LAST_BLOCK) { | 755 | if (i != RETVAL_LAST_BLOCK) { |
756 | bb_error_msg("bunzip error %d", i); | ||
757 | break; | ||
758 | } | ||
676 | if (bd->headerCRC != bd->totalCRC) { | 759 | if (bd->headerCRC != bd->totalCRC) { |
677 | bb_error_msg("CRC error"); | 760 | bb_error_msg("CRC error"); |
678 | } else { | 761 | break; |
679 | i = RETVAL_OK; | ||
680 | } | 762 | } |
681 | } else if (i == RETVAL_SHORT_WRITE) { | 763 | |
682 | bb_error_msg("short write"); | 764 | /* Successfully unpacked one BZ stream */ |
683 | } else { | 765 | i = RETVAL_OK; |
684 | bb_error_msg("bunzip error %d", i); | 766 | |
767 | /* Do we have "BZ..." after last processed byte? | ||
768 | * pbzip2 (parallelized bzip2) produces such files. | ||
769 | */ | ||
770 | len = bd->inbufCount - bd->inbufPos; | ||
771 | memcpy(outbuf, &bd->inbuf[bd->inbufPos], len); | ||
772 | if (len < 2) { | ||
773 | if (safe_read(src_fd, outbuf + len, 2 - len) != 2 - len) | ||
774 | break; | ||
775 | len = 2; | ||
776 | } | ||
777 | if (*(uint16_t*)outbuf != BZIP2_MAGIC) /* "BZ"? */ | ||
778 | break; | ||
779 | dealloc_bunzip(bd); | ||
780 | len -= 2; | ||
685 | } | 781 | } |
782 | |||
783 | release_mem: | ||
686 | dealloc_bunzip(bd); | 784 | dealloc_bunzip(bd); |
687 | free(outbuf); | 785 | free(outbuf); |
688 | 786 | ||
diff --git a/archival/libunarchive/decompress_uncompress.c b/archival/libarchive/decompress_uncompress.c index 285b4efeb..44d894244 100644 --- a/archival/libunarchive/decompress_uncompress.c +++ b/archival/libarchive/decompress_uncompress.c | |||
@@ -25,7 +25,7 @@ | |||
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include "libbb.h" | 27 | #include "libbb.h" |
28 | #include "unarchive.h" | 28 | #include "archive.h" |
29 | 29 | ||
30 | 30 | ||
31 | /* Default input buffer size */ | 31 | /* Default input buffer size */ |
diff --git a/archival/libunarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c index 1a3a8f86b..a04714341 100644 --- a/archival/libunarchive/decompress_unlzma.c +++ b/archival/libarchive/decompress_unlzma.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 9 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
10 | */ | 10 | */ |
11 | #include "libbb.h" | 11 | #include "libbb.h" |
12 | #include "unarchive.h" | 12 | #include "archive.h" |
13 | 13 | ||
14 | #if ENABLE_FEATURE_LZMA_FAST | 14 | #if ENABLE_FEATURE_LZMA_FAST |
15 | # define speed_inline ALWAYS_INLINE | 15 | # define speed_inline ALWAYS_INLINE |
diff --git a/archival/libunarchive/decompress_unxz.c b/archival/libarchive/decompress_unxz.c index ca427231e..e90dfb06f 100644 --- a/archival/libunarchive/decompress_unxz.c +++ b/archival/libarchive/decompress_unxz.c | |||
@@ -10,7 +10,7 @@ | |||
10 | * Licensed under GPLv2, see file LICENSE in this source tree. | 10 | * Licensed under GPLv2, see file LICENSE in this source tree. |
11 | */ | 11 | */ |
12 | #include "libbb.h" | 12 | #include "libbb.h" |
13 | #include "unarchive.h" | 13 | #include "archive.h" |
14 | 14 | ||
15 | #define XZ_FUNC FAST_FUNC | 15 | #define XZ_FUNC FAST_FUNC |
16 | #define XZ_EXTERN static | 16 | #define XZ_EXTERN static |
diff --git a/archival/libunarchive/decompress_unzip.c b/archival/libarchive/decompress_unzip.c index cb8a3d737..a29eef837 100644 --- a/archival/libunarchive/decompress_unzip.c +++ b/archival/libarchive/decompress_unzip.c | |||
@@ -35,7 +35,7 @@ | |||
35 | 35 | ||
36 | #include <setjmp.h> | 36 | #include <setjmp.h> |
37 | #include "libbb.h" | 37 | #include "libbb.h" |
38 | #include "unarchive.h" | 38 | #include "archive.h" |
39 | 39 | ||
40 | typedef struct huft_t { | 40 | typedef struct huft_t { |
41 | unsigned char e; /* number of extra bits or operation */ | 41 | unsigned char e; /* number of extra bits or operation */ |
diff --git a/archival/libunarchive/filter_accept_all.c b/archival/libarchive/filter_accept_all.c index cb1f506c8..e69deb679 100644 --- a/archival/libunarchive/filter_accept_all.c +++ b/archival/libarchive/filter_accept_all.c | |||
@@ -6,7 +6,7 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include "libbb.h" | 8 | #include "libbb.h" |
9 | #include "unarchive.h" | 9 | #include "archive.h" |
10 | 10 | ||
11 | /* Accept any non-null name, its not really a filter at all */ | 11 | /* Accept any non-null name, its not really a filter at all */ |
12 | char FAST_FUNC filter_accept_all(archive_handle_t *archive_handle) | 12 | char FAST_FUNC filter_accept_all(archive_handle_t *archive_handle) |
diff --git a/archival/libunarchive/filter_accept_list.c b/archival/libarchive/filter_accept_list.c index fe4414c85..a7640af79 100644 --- a/archival/libunarchive/filter_accept_list.c +++ b/archival/libarchive/filter_accept_list.c | |||
@@ -6,7 +6,7 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include "libbb.h" | 8 | #include "libbb.h" |
9 | #include "unarchive.h" | 9 | #include "archive.h" |
10 | 10 | ||
11 | /* | 11 | /* |
12 | * Accept names that are in the accept list, ignoring reject list. | 12 | * Accept names that are in the accept list, ignoring reject list. |
diff --git a/archival/libunarchive/filter_accept_list_reassign.c b/archival/libarchive/filter_accept_list_reassign.c index 891f58390..d80f71668 100644 --- a/archival/libunarchive/filter_accept_list_reassign.c +++ b/archival/libarchive/filter_accept_list_reassign.c | |||
@@ -6,7 +6,7 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include "libbb.h" | 8 | #include "libbb.h" |
9 | #include "unarchive.h" | 9 | #include "archive.h" |
10 | 10 | ||
11 | /* Built and used only if ENABLE_DPKG || ENABLE_DPKG_DEB */ | 11 | /* Built and used only if ENABLE_DPKG || ENABLE_DPKG_DEB */ |
12 | 12 | ||
diff --git a/archival/libunarchive/filter_accept_reject_list.c b/archival/libarchive/filter_accept_reject_list.c index 89a5502d5..3e86cca65 100644 --- a/archival/libunarchive/filter_accept_reject_list.c +++ b/archival/libarchive/filter_accept_reject_list.c | |||
@@ -6,7 +6,7 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include "libbb.h" | 8 | #include "libbb.h" |
9 | #include "unarchive.h" | 9 | #include "archive.h" |
10 | 10 | ||
11 | /* | 11 | /* |
12 | * Accept names that are in the accept list and not in the reject list | 12 | * Accept names that are in the accept list and not in the reject list |
diff --git a/archival/libunarchive/find_list_entry.c b/archival/libarchive/find_list_entry.c index 5c0c85f09..5efd1af2e 100644 --- a/archival/libunarchive/find_list_entry.c +++ b/archival/libarchive/find_list_entry.c | |||
@@ -7,7 +7,7 @@ | |||
7 | 7 | ||
8 | #include <fnmatch.h> | 8 | #include <fnmatch.h> |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | #include "unarchive.h" | 10 | #include "archive.h" |
11 | 11 | ||
12 | /* Find a string in a shell pattern list */ | 12 | /* Find a string in a shell pattern list */ |
13 | const llist_t* FAST_FUNC find_list_entry(const llist_t *list, const char *filename) | 13 | const llist_t* FAST_FUNC find_list_entry(const llist_t *list, const char *filename) |
diff --git a/archival/libunarchive/get_header_ar.c b/archival/libarchive/get_header_ar.c index 6bfc6bc27..df603b111 100644 --- a/archival/libunarchive/get_header_ar.c +++ b/archival/libarchive/get_header_ar.c | |||
@@ -5,7 +5,7 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include "libbb.h" | 7 | #include "libbb.h" |
8 | #include "unarchive.h" | 8 | #include "archive.h" |
9 | #include "ar.h" | 9 | #include "ar.h" |
10 | 10 | ||
11 | static unsigned read_num(const char *str, int base) | 11 | static unsigned read_num(const char *str, int base) |
diff --git a/archival/libunarchive/get_header_cpio.c b/archival/libarchive/get_header_cpio.c index 8cd1096ba..3d99b492a 100644 --- a/archival/libunarchive/get_header_cpio.c +++ b/archival/libarchive/get_header_cpio.c | |||
@@ -5,7 +5,7 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include "libbb.h" | 7 | #include "libbb.h" |
8 | #include "unarchive.h" | 8 | #include "archive.h" |
9 | 9 | ||
10 | typedef struct hardlinks_t { | 10 | typedef struct hardlinks_t { |
11 | struct hardlinks_t *next; | 11 | struct hardlinks_t *next; |
diff --git a/archival/libunarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c index cf6487207..78b0ae25f 100644 --- a/archival/libunarchive/get_header_tar.c +++ b/archival/libarchive/get_header_tar.c | |||
@@ -12,7 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include "libbb.h" | 14 | #include "libbb.h" |
15 | #include "unarchive.h" | 15 | #include "archive.h" |
16 | 16 | ||
17 | typedef uint32_t aliased_uint32_t FIX_ALIASING; | 17 | typedef uint32_t aliased_uint32_t FIX_ALIASING; |
18 | typedef off_t aliased_off_t FIX_ALIASING; | 18 | typedef off_t aliased_off_t FIX_ALIASING; |
diff --git a/archival/libunarchive/get_header_tar_bz2.c b/archival/libarchive/get_header_tar_bz2.c index 4ffc17086..60d32069f 100644 --- a/archival/libunarchive/get_header_tar_bz2.c +++ b/archival/libarchive/get_header_tar_bz2.c | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "libbb.h" | 6 | #include "libbb.h" |
7 | #include "unarchive.h" | 7 | #include "archive.h" |
8 | 8 | ||
9 | char FAST_FUNC get_header_tar_bz2(archive_handle_t *archive_handle) | 9 | char FAST_FUNC get_header_tar_bz2(archive_handle_t *archive_handle) |
10 | { | 10 | { |
diff --git a/archival/libunarchive/get_header_tar_gz.c b/archival/libarchive/get_header_tar_gz.c index a9af22e0e..b09f8691c 100644 --- a/archival/libunarchive/get_header_tar_gz.c +++ b/archival/libarchive/get_header_tar_gz.c | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "libbb.h" | 6 | #include "libbb.h" |
7 | #include "unarchive.h" | 7 | #include "archive.h" |
8 | 8 | ||
9 | char FAST_FUNC get_header_tar_gz(archive_handle_t *archive_handle) | 9 | char FAST_FUNC get_header_tar_gz(archive_handle_t *archive_handle) |
10 | { | 10 | { |
diff --git a/archival/libunarchive/get_header_tar_lzma.c b/archival/libarchive/get_header_tar_lzma.c index 9876b3827..da08e0c72 100644 --- a/archival/libunarchive/get_header_tar_lzma.c +++ b/archival/libarchive/get_header_tar_lzma.c | |||
@@ -7,7 +7,7 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | #include "unarchive.h" | 10 | #include "archive.h" |
11 | 11 | ||
12 | char FAST_FUNC get_header_tar_lzma(archive_handle_t *archive_handle) | 12 | char FAST_FUNC get_header_tar_lzma(archive_handle_t *archive_handle) |
13 | { | 13 | { |
diff --git a/archival/libunarchive/header_list.c b/archival/libarchive/header_list.c index 902d6ebe0..c4fc75f38 100644 --- a/archival/libunarchive/header_list.c +++ b/archival/libarchive/header_list.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 3 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
4 | */ | 4 | */ |
5 | #include "libbb.h" | 5 | #include "libbb.h" |
6 | #include "unarchive.h" | 6 | #include "archive.h" |
7 | 7 | ||
8 | void FAST_FUNC header_list(const file_header_t *file_header) | 8 | void FAST_FUNC header_list(const file_header_t *file_header) |
9 | { | 9 | { |
diff --git a/archival/libunarchive/header_skip.c b/archival/libarchive/header_skip.c index 2af36ac9c..2bfc5253c 100644 --- a/archival/libunarchive/header_skip.c +++ b/archival/libarchive/header_skip.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 3 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
4 | */ | 4 | */ |
5 | #include "libbb.h" | 5 | #include "libbb.h" |
6 | #include "unarchive.h" | 6 | #include "archive.h" |
7 | 7 | ||
8 | void FAST_FUNC header_skip(const file_header_t *file_header UNUSED_PARAM) | 8 | void FAST_FUNC header_skip(const file_header_t *file_header UNUSED_PARAM) |
9 | { | 9 | { |
diff --git a/archival/libunarchive/header_verbose_list.c b/archival/libarchive/header_verbose_list.c index d863e6a29..bc4e4154b 100644 --- a/archival/libunarchive/header_verbose_list.c +++ b/archival/libarchive/header_verbose_list.c | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "libbb.h" | 6 | #include "libbb.h" |
7 | #include "unarchive.h" | 7 | #include "archive.h" |
8 | 8 | ||
9 | void FAST_FUNC header_verbose_list(const file_header_t *file_header) | 9 | void FAST_FUNC header_verbose_list(const file_header_t *file_header) |
10 | { | 10 | { |
diff --git a/archival/libunarchive/init_handle.c b/archival/libarchive/init_handle.c index de7021f78..6644ea13b 100644 --- a/archival/libunarchive/init_handle.c +++ b/archival/libarchive/init_handle.c | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "libbb.h" | 6 | #include "libbb.h" |
7 | #include "unarchive.h" | 7 | #include "archive.h" |
8 | 8 | ||
9 | archive_handle_t* FAST_FUNC init_handle(void) | 9 | archive_handle_t* FAST_FUNC init_handle(void) |
10 | { | 10 | { |
diff --git a/archival/liblzo.h b/archival/libarchive/liblzo.h index 843997cb9..843997cb9 100644 --- a/archival/liblzo.h +++ b/archival/libarchive/liblzo.h | |||
diff --git a/archival/lzo1x_1.c b/archival/libarchive/lzo1x_1.c index a88839846..a88839846 100644 --- a/archival/lzo1x_1.c +++ b/archival/libarchive/lzo1x_1.c | |||
diff --git a/archival/lzo1x_1o.c b/archival/libarchive/lzo1x_1o.c index 3c61253e0..3c61253e0 100644 --- a/archival/lzo1x_1o.c +++ b/archival/libarchive/lzo1x_1o.c | |||
diff --git a/archival/lzo1x_9x.c b/archival/libarchive/lzo1x_9x.c index 483205155..483205155 100644 --- a/archival/lzo1x_9x.c +++ b/archival/libarchive/lzo1x_9x.c | |||
diff --git a/archival/lzo1x_c.c b/archival/libarchive/lzo1x_c.c index cc86f74b1..cc86f74b1 100644 --- a/archival/lzo1x_c.c +++ b/archival/libarchive/lzo1x_c.c | |||
diff --git a/archival/lzo1x_d.c b/archival/libarchive/lzo1x_d.c index 348a85510..348a85510 100644 --- a/archival/lzo1x_d.c +++ b/archival/libarchive/lzo1x_d.c | |||
diff --git a/archival/libunarchive/open_transformer.c b/archival/libarchive/open_transformer.c index ed6a556bb..26ae565f5 100644 --- a/archival/libunarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c | |||
@@ -4,12 +4,12 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "libbb.h" | 6 | #include "libbb.h" |
7 | #include "unarchive.h" | 7 | #include "archive.h" |
8 | 8 | ||
9 | /* transformer(), more than meets the eye */ | 9 | /* transformer(), more than meets the eye */ |
10 | /* | 10 | /* |
11 | * On MMU machine, the transform_prog is removed by macro magic | 11 | * On MMU machine, the transform_prog is removed by macro magic |
12 | * in include/unarchive.h. On NOMMU, transformer is removed. | 12 | * in include/archive.h. On NOMMU, transformer is removed. |
13 | */ | 13 | */ |
14 | void FAST_FUNC open_transformer(int fd, | 14 | void FAST_FUNC open_transformer(int fd, |
15 | IF_DESKTOP(long long) int FAST_FUNC (*transformer)(int src_fd, int dst_fd), | 15 | IF_DESKTOP(long long) int FAST_FUNC (*transformer)(int src_fd, int dst_fd), |
diff --git a/archival/libunarchive/seek_by_jump.c b/archival/libarchive/seek_by_jump.c index bda55e1b1..7c2c52ae1 100644 --- a/archival/libunarchive/seek_by_jump.c +++ b/archival/libarchive/seek_by_jump.c | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "libbb.h" | 6 | #include "libbb.h" |
7 | #include "unarchive.h" | 7 | #include "archive.h" |
8 | 8 | ||
9 | void FAST_FUNC seek_by_jump(int fd, off_t amount) | 9 | void FAST_FUNC seek_by_jump(int fd, off_t amount) |
10 | { | 10 | { |
diff --git a/archival/libunarchive/seek_by_read.c b/archival/libarchive/seek_by_read.c index 25b31365d..ad931a8de 100644 --- a/archival/libunarchive/seek_by_read.c +++ b/archival/libarchive/seek_by_read.c | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "libbb.h" | 6 | #include "libbb.h" |
7 | #include "unarchive.h" | 7 | #include "archive.h" |
8 | 8 | ||
9 | /* If we are reading through a pipe, or from stdin then we can't lseek, | 9 | /* If we are reading through a pipe, or from stdin then we can't lseek, |
10 | * we must read and discard the data to skip over it. | 10 | * we must read and discard the data to skip over it. |
diff --git a/archival/libunarchive/unpack_ar_archive.c b/archival/libarchive/unpack_ar_archive.c index 4f68ba3d8..18dbfd54d 100644 --- a/archival/libunarchive/unpack_ar_archive.c +++ b/archival/libarchive/unpack_ar_archive.c | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "libbb.h" | 6 | #include "libbb.h" |
7 | #include "unarchive.h" | 7 | #include "archive.h" |
8 | #include "ar.h" | 8 | #include "ar.h" |
9 | 9 | ||
10 | void FAST_FUNC unpack_ar_archive(archive_handle_t *ar_archive) | 10 | void FAST_FUNC unpack_ar_archive(archive_handle_t *ar_archive) |
diff --git a/archival/libunarchive/unxz/README b/archival/libarchive/unxz/README index c5972f6b8..c5972f6b8 100644 --- a/archival/libunarchive/unxz/README +++ b/archival/libarchive/unxz/README | |||
diff --git a/archival/libunarchive/unxz/xz.h b/archival/libarchive/unxz/xz.h index c6c071c4a..c6c071c4a 100644 --- a/archival/libunarchive/unxz/xz.h +++ b/archival/libarchive/unxz/xz.h | |||
diff --git a/archival/libunarchive/unxz/xz_config.h b/archival/libarchive/unxz/xz_config.h index 187e1cbed..187e1cbed 100644 --- a/archival/libunarchive/unxz/xz_config.h +++ b/archival/libarchive/unxz/xz_config.h | |||
diff --git a/archival/libunarchive/unxz/xz_dec_bcj.c b/archival/libarchive/unxz/xz_dec_bcj.c index 09162b51f..09162b51f 100644 --- a/archival/libunarchive/unxz/xz_dec_bcj.c +++ b/archival/libarchive/unxz/xz_dec_bcj.c | |||
diff --git a/archival/libunarchive/unxz/xz_dec_lzma2.c b/archival/libarchive/unxz/xz_dec_lzma2.c index da71cb4d4..da71cb4d4 100644 --- a/archival/libunarchive/unxz/xz_dec_lzma2.c +++ b/archival/libarchive/unxz/xz_dec_lzma2.c | |||
diff --git a/archival/libunarchive/unxz/xz_dec_stream.c b/archival/libarchive/unxz/xz_dec_stream.c index bdcbf1ba3..bdcbf1ba3 100644 --- a/archival/libunarchive/unxz/xz_dec_stream.c +++ b/archival/libarchive/unxz/xz_dec_stream.c | |||
diff --git a/archival/libunarchive/unxz/xz_lzma2.h b/archival/libarchive/unxz/xz_lzma2.h index 47f21afbc..47f21afbc 100644 --- a/archival/libunarchive/unxz/xz_lzma2.h +++ b/archival/libarchive/unxz/xz_lzma2.h | |||
diff --git a/archival/libunarchive/unxz/xz_private.h b/archival/libarchive/unxz/xz_private.h index 145649a83..145649a83 100644 --- a/archival/libunarchive/unxz/xz_private.h +++ b/archival/libarchive/unxz/xz_private.h | |||
diff --git a/archival/libunarchive/unxz/xz_stream.h b/archival/libarchive/unxz/xz_stream.h index 36f2a7cbf..36f2a7cbf 100644 --- a/archival/libunarchive/unxz/xz_stream.h +++ b/archival/libarchive/unxz/xz_stream.h | |||
diff --git a/archival/lzop.c b/archival/lzop.c index acb34fe14..094e78cf9 100644 --- a/archival/lzop.c +++ b/archival/lzop.c | |||
@@ -26,7 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include "libbb.h" | 28 | #include "libbb.h" |
29 | #include "unarchive.h" | 29 | #include "archive.h" |
30 | #include "liblzo_interface.h" | 30 | #include "liblzo_interface.h" |
31 | 31 | ||
32 | /* lzo-2.03/src/lzo_ptr.h */ | 32 | /* lzo-2.03/src/lzo_ptr.h */ |
diff --git a/archival/rpm.c b/archival/rpm.c index 7b316a5b8..380226f9b 100644 --- a/archival/rpm.c +++ b/archival/rpm.c | |||
@@ -8,7 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include "libbb.h" | 10 | #include "libbb.h" |
11 | #include "unarchive.h" | 11 | #include "archive.h" |
12 | #include "rpm.h" | 12 | #include "rpm.h" |
13 | 13 | ||
14 | #define RPM_CHAR_TYPE 1 | 14 | #define RPM_CHAR_TYPE 1 |
diff --git a/archival/rpm2cpio.c b/archival/rpm2cpio.c index 70021d539..ce8cd2c2c 100644 --- a/archival/rpm2cpio.c +++ b/archival/rpm2cpio.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | #include "unarchive.h" | 10 | #include "archive.h" |
11 | #include "rpm.h" | 11 | #include "rpm.h" |
12 | 12 | ||
13 | enum { rpm_fd = STDIN_FILENO }; | 13 | enum { rpm_fd = STDIN_FILENO }; |
diff --git a/archival/tar.c b/archival/tar.c index 1d6e63da0..150c6f393 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -23,9 +23,28 @@ | |||
23 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 23 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
24 | */ | 24 | */ |
25 | 25 | ||
26 | /* TODO: security with -C DESTDIR option can be enhanced. | ||
27 | * Consider tar file created via: | ||
28 | * $ tar cvf bug.tar anything.txt | ||
29 | * $ ln -s /tmp symlink | ||
30 | * $ tar --append -f bug.tar symlink | ||
31 | * $ rm symlink | ||
32 | * $ mkdir symlink | ||
33 | * $ tar --append -f bug.tar symlink/evil.py | ||
34 | * | ||
35 | * This will result in an archive which contains: | ||
36 | * $ tar --list -f bug.tar | ||
37 | * anything.txt | ||
38 | * symlink | ||
39 | * symlink/evil.py | ||
40 | * | ||
41 | * Untarring it puts evil.py in '/tmp' even if the -C DESTDIR is given. | ||
42 | * This doesn't feel right, and IIRC GNU tar doesn't do that. | ||
43 | */ | ||
44 | |||
26 | #include <fnmatch.h> | 45 | #include <fnmatch.h> |
27 | #include "libbb.h" | 46 | #include "libbb.h" |
28 | #include "unarchive.h" | 47 | #include "archive.h" |
29 | /* FIXME: Stop using this non-standard feature */ | 48 | /* FIXME: Stop using this non-standard feature */ |
30 | #ifndef FNM_LEADING_DIR | 49 | #ifndef FNM_LEADING_DIR |
31 | # define FNM_LEADING_DIR 0 | 50 | # define FNM_LEADING_DIR 0 |
@@ -884,7 +903,6 @@ int tar_main(int argc UNUSED_PARAM, char **argv) | |||
884 | /* Prepend '-' to the first argument if required */ | 903 | /* Prepend '-' to the first argument if required */ |
885 | opt_complementary = "--:" // first arg is options | 904 | opt_complementary = "--:" // first arg is options |
886 | "tt:vv:" // count -t,-v | 905 | "tt:vv:" // count -t,-v |
887 | "?:" // bail out with usage instead of error return | ||
888 | "X::T::" // cumulative lists | 906 | "X::T::" // cumulative lists |
889 | #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM | 907 | #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM |
890 | "\xff::" // cumulative lists for --exclude | 908 | "\xff::" // cumulative lists for --exclude |
diff --git a/archival/unzip.c b/archival/unzip.c index 204e34952..5d62c08cb 100644 --- a/archival/unzip.c +++ b/archival/unzip.c | |||
@@ -20,7 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include "libbb.h" | 22 | #include "libbb.h" |
23 | #include "unarchive.h" | 23 | #include "archive.h" |
24 | 24 | ||
25 | enum { | 25 | enum { |
26 | #if BB_BIG_ENDIAN | 26 | #if BB_BIG_ENDIAN |
diff --git a/console-tools/kbd_mode.c b/console-tools/kbd_mode.c index 14f2ae516..1481d0dbb 100644 --- a/console-tools/kbd_mode.c +++ b/console-tools/kbd_mode.c | |||
@@ -16,9 +16,9 @@ int kbd_mode_main(int argc UNUSED_PARAM, char **argv) | |||
16 | { | 16 | { |
17 | enum { | 17 | enum { |
18 | SCANCODE = (1 << 0), | 18 | SCANCODE = (1 << 0), |
19 | ASCII = (1 << 1), | 19 | ASCII = (1 << 1), |
20 | MEDIUMRAW = (1 << 2), | 20 | MEDIUMRAW = (1 << 2), |
21 | UNICODE = (1 << 3), | 21 | UNICODE = (1 << 3), |
22 | }; | 22 | }; |
23 | int fd; | 23 | int fd; |
24 | unsigned opt; | 24 | unsigned opt; |
diff --git a/console-tools/loadfont.c b/console-tools/loadfont.c index 3c77813b5..079626c20 100644 --- a/console-tools/loadfont.c +++ b/console-tools/loadfont.c | |||
@@ -136,7 +136,7 @@ static void do_loadfont(int fd, unsigned char *inbuf, int height, int width, int | |||
136 | * Example: | 136 | * Example: |
137 | * At the font position for a capital A-ring glyph, we | 137 | * At the font position for a capital A-ring glyph, we |
138 | * may have: | 138 | * may have: |
139 | * 00C5,212B,FFFE,0041,030A,FFFF | 139 | * 00C5,212B,FFFE,0041,030A,FFFF |
140 | * Some font positions may be described by sequences only, | 140 | * Some font positions may be described by sequences only, |
141 | * namely when there is no precomposed Unicode value for the glyph. | 141 | * namely when there is no precomposed Unicode value for the glyph. |
142 | */ | 142 | */ |
@@ -159,7 +159,7 @@ static void do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize, | |||
159 | int glyph; | 159 | int glyph; |
160 | uint16_t unicode; | 160 | uint16_t unicode; |
161 | 161 | ||
162 | maxct = tailsz; /* more than enough */ | 162 | maxct = tailsz; /* more than enough */ |
163 | up = xmalloc(maxct * sizeof(*up)); | 163 | up = xmalloc(maxct * sizeof(*up)); |
164 | 164 | ||
165 | for (glyph = 0; glyph < fontsize; glyph++) { | 165 | for (glyph = 0; glyph < fontsize; glyph++) { |
@@ -255,10 +255,10 @@ static void do_load(int fd, unsigned char *buffer, size_t len) | |||
255 | } else | 255 | } else |
256 | #endif | 256 | #endif |
257 | #if ENABLE_FEATURE_LOADFONT_RAW | 257 | #if ENABLE_FEATURE_LOADFONT_RAW |
258 | if (len == 9780) { /* file with three code pages? */ | 258 | if (len == 9780) { /* file with three code pages? */ |
259 | charsize = height = 16; | 259 | charsize = height = 16; |
260 | font += 40; | 260 | font += 40; |
261 | } else if ((len & 0377) == 0) { /* bare font */ | 261 | } else if ((len & 0377) == 0) { /* bare font */ |
262 | charsize = height = len / 256; | 262 | charsize = height = len / 256; |
263 | } else | 263 | } else |
264 | #endif | 264 | #endif |
diff --git a/console-tools/reset.c b/console-tools/reset.c index 7dffdea18..1806ce742 100644 --- a/console-tools/reset.c +++ b/console-tools/reset.c | |||
@@ -8,11 +8,13 @@ | |||
8 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 8 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include "libbb.h" | ||
12 | |||
13 | /* BTW, which "standard" package has this utility? It doesn't seem | 11 | /* BTW, which "standard" package has this utility? It doesn't seem |
14 | * to be ncurses, coreutils, console-tools... then what? */ | 12 | * to be ncurses, coreutils, console-tools... then what? */ |
15 | 13 | ||
14 | #include "libbb.h" | ||
15 | |||
16 | #define ESC "\033" | ||
17 | |||
16 | #if ENABLE_STTY | 18 | #if ENABLE_STTY |
17 | int stty_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 19 | int stty_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
18 | #endif | 20 | #endif |
@@ -26,15 +28,15 @@ int reset_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
26 | 28 | ||
27 | /* no options, no getopt */ | 29 | /* no options, no getopt */ |
28 | 30 | ||
29 | if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) { | 31 | if (/*isatty(STDIN_FILENO) &&*/ isatty(STDOUT_FILENO)) { |
30 | /* See 'man 4 console_codes' for details: | 32 | /* See 'man 4 console_codes' for details: |
31 | * "ESC c" -- Reset | 33 | * "ESC c" -- Reset |
32 | * "ESC ( K" -- Select user mapping | 34 | * "ESC ( K" -- Select user mapping |
33 | * "ESC [ J" -- Erase to the end of screen | ||
34 | * "ESC [ 0 m" -- Reset all display attributes | 35 | * "ESC [ 0 m" -- Reset all display attributes |
36 | * "ESC [ J" -- Erase to the end of screen | ||
35 | * "ESC [ ? 25 h" -- Make cursor visible | 37 | * "ESC [ ? 25 h" -- Make cursor visible |
36 | */ | 38 | */ |
37 | printf("\033c\033(K\033[J\033[0m\033[?25h"); | 39 | printf(ESC"c" ESC"(K" ESC"[0m" ESC"[J" ESC"[?25h"); |
38 | /* http://bugs.busybox.net/view.php?id=1414: | 40 | /* http://bugs.busybox.net/view.php?id=1414: |
39 | * people want it to reset echo etc: */ | 41 | * people want it to reset echo etc: */ |
40 | #if ENABLE_STTY | 42 | #if ENABLE_STTY |
diff --git a/console-tools/resize.c b/console-tools/resize.c index 12e50a116..fdfe2a6a0 100644 --- a/console-tools/resize.c +++ b/console-tools/resize.c | |||
@@ -17,7 +17,7 @@ static void | |||
17 | onintr(int sig UNUSED_PARAM) | 17 | onintr(int sig UNUSED_PARAM) |
18 | { | 18 | { |
19 | tcsetattr(STDERR_FILENO, TCSANOW, old_termios_p); | 19 | tcsetattr(STDERR_FILENO, TCSANOW, old_termios_p); |
20 | exit(EXIT_FAILURE); | 20 | _exit(EXIT_FAILURE); |
21 | } | 21 | } |
22 | 22 | ||
23 | int resize_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 23 | int resize_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
diff --git a/console-tools/showkey.c b/console-tools/showkey.c index 149ea6465..e7834f702 100644 --- a/console-tools/showkey.c +++ b/console-tools/showkey.c | |||
@@ -10,6 +10,20 @@ | |||
10 | #include "libbb.h" | 10 | #include "libbb.h" |
11 | #include <linux/kd.h> | 11 | #include <linux/kd.h> |
12 | 12 | ||
13 | |||
14 | struct globals { | ||
15 | int kbmode; | ||
16 | struct termios tio, tio0; | ||
17 | }; | ||
18 | #define G (*ptr_to_globals) | ||
19 | #define kbmode (G.kbmode) | ||
20 | #define tio (G.tio) | ||
21 | #define tio0 (G.tio0) | ||
22 | #define INIT_G() do { \ | ||
23 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | ||
24 | } while (0) | ||
25 | |||
26 | |||
13 | // set raw tty mode | 27 | // set raw tty mode |
14 | // also used by microcom | 28 | // also used by microcom |
15 | // libbb candidates? | 29 | // libbb candidates? |
@@ -20,62 +34,38 @@ static void xget1(struct termios *t, struct termios *oldt) | |||
20 | cfmakeraw(t); | 34 | cfmakeraw(t); |
21 | } | 35 | } |
22 | 36 | ||
23 | static void xset1(struct termios *tio) | 37 | static void xset1(struct termios *t) |
24 | { | 38 | { |
25 | int ret = tcsetattr(STDIN_FILENO, TCSAFLUSH, tio); | 39 | int ret = tcsetattr(STDIN_FILENO, TCSAFLUSH, t); |
26 | if (ret) { | 40 | if (ret) { |
27 | bb_perror_msg("can't tcsetattr for stdin"); | 41 | bb_perror_msg("can't tcsetattr for stdin"); |
28 | } | 42 | } |
29 | } | 43 | } |
30 | 44 | ||
31 | /* | ||
32 | * GLOBALS | ||
33 | */ | ||
34 | struct globals { | ||
35 | int kbmode; | ||
36 | struct termios tio, tio0; | ||
37 | }; | ||
38 | #define G (*ptr_to_globals) | ||
39 | #define kbmode (G.kbmode) | ||
40 | #define tio (G.tio) | ||
41 | #define tio0 (G.tio0) | ||
42 | #define INIT_G() do { \ | ||
43 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | ||
44 | } while (0) | ||
45 | |||
46 | |||
47 | static void signal_handler(int signo) | ||
48 | { | ||
49 | // restore keyboard and console settings | ||
50 | xset1(&tio0); | ||
51 | xioctl(STDIN_FILENO, KDSKBMODE, (void *)(ptrdiff_t)kbmode); | ||
52 | // alarmed? -> exit 0 | ||
53 | exit(SIGALRM == signo); | ||
54 | } | ||
55 | |||
56 | int showkey_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 45 | int showkey_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
57 | int showkey_main(int argc UNUSED_PARAM, char **argv) | 46 | int showkey_main(int argc UNUSED_PARAM, char **argv) |
58 | { | 47 | { |
59 | enum { | 48 | enum { |
60 | OPT_a = (1<<0), // display the decimal/octal/hex values of the keys | 49 | OPT_a = (1<<0), // display the decimal/octal/hex values of the keys |
61 | OPT_k = (1<<1), // display only the interpreted keycodes (default) | 50 | OPT_k = (1<<1), // display only the interpreted keycodes (default) |
62 | OPT_s = (1<<2), // display only the raw scan-codes | 51 | OPT_s = (1<<2), // display only the raw scan-codes |
63 | }; | 52 | }; |
64 | 53 | ||
54 | INIT_G(); | ||
55 | |||
65 | // FIXME: aks are all mutually exclusive | 56 | // FIXME: aks are all mutually exclusive |
66 | getopt32(argv, "aks"); | 57 | getopt32(argv, "aks"); |
67 | 58 | ||
68 | INIT_G(); | ||
69 | |||
70 | // get keyboard settings | 59 | // get keyboard settings |
71 | xioctl(STDIN_FILENO, KDGKBMODE, &kbmode); | 60 | xioctl(STDIN_FILENO, KDGKBMODE, &kbmode); |
72 | printf("kb mode was %s\n\nPress any keys. Program terminates %s\n\n", | 61 | printf("kb mode was %s\n\nPress any keys. Program terminates %s\n\n", |
73 | kbmode == K_RAW ? "RAW" : | 62 | kbmode == K_RAW ? "RAW" : |
74 | (kbmode == K_XLATE ? "XLATE" : | 63 | (kbmode == K_XLATE ? "XLATE" : |
75 | (kbmode == K_MEDIUMRAW ? "MEDIUMRAW" : | 64 | (kbmode == K_MEDIUMRAW ? "MEDIUMRAW" : |
76 | (kbmode == K_UNICODE ? "UNICODE" : "?UNKNOWN?"))) | 65 | (kbmode == K_UNICODE ? "UNICODE" : "UNKNOWN"))) |
77 | , (option_mask32 & OPT_a) ? "when CTRL+D pressed" : "10s after last keypress" | 66 | , (option_mask32 & OPT_a) ? "on EOF (ctrl-D)" : "10s after last keypress" |
78 | ); | 67 | ); |
68 | |||
79 | // prepare for raw mode | 69 | // prepare for raw mode |
80 | xget1(&tio, &tio0); | 70 | xget1(&tio, &tio0); |
81 | // put stdin in raw mode | 71 | // put stdin in raw mode |
@@ -83,34 +73,37 @@ int showkey_main(int argc UNUSED_PARAM, char **argv) | |||
83 | 73 | ||
84 | if (option_mask32 & OPT_a) { | 74 | if (option_mask32 & OPT_a) { |
85 | unsigned char c; | 75 | unsigned char c; |
76 | |||
86 | // just read stdin char by char | 77 | // just read stdin char by char |
87 | while (1 == safe_read(STDIN_FILENO, &c, 1)) { | 78 | while (1 == read(STDIN_FILENO, &c, 1)) { |
88 | printf("%3u 0%03o 0x%02x\r\n", c, c, c); | 79 | printf("%3u 0%03o 0x%02x\r\n", c, c, c); |
89 | if (04 /*CTRL-D*/ == c) | 80 | if (04 /*CTRL-D*/ == c) |
90 | break; | 81 | break; |
91 | } | 82 | } |
92 | } else { | 83 | } else { |
93 | // we should exit on any signal | ||
94 | bb_signals(BB_FATAL_SIGS, signal_handler); | ||
95 | // set raw keyboard mode | 84 | // set raw keyboard mode |
96 | xioctl(STDIN_FILENO, KDSKBMODE, (void *)(ptrdiff_t)((option_mask32 & OPT_k) ? K_MEDIUMRAW : K_RAW)); | 85 | xioctl(STDIN_FILENO, KDSKBMODE, (void *)(ptrdiff_t)((option_mask32 & OPT_k) ? K_MEDIUMRAW : K_RAW)); |
97 | 86 | ||
87 | // we should exit on any signal; signals should interrupt read | ||
88 | bb_signals_recursive_norestart(BB_FATAL_SIGS, record_signo); | ||
89 | |||
98 | // read and show scancodes | 90 | // read and show scancodes |
99 | while (1) { | 91 | while (!bb_got_signal) { |
100 | char buf[18]; | 92 | char buf[18]; |
101 | int i, n; | 93 | int i, n; |
94 | |||
102 | // setup 10s watchdog | 95 | // setup 10s watchdog |
103 | alarm(10); | 96 | alarm(10); |
104 | // read scancodes | 97 | // read scancodes |
105 | n = read(STDIN_FILENO, buf, sizeof(buf)); | 98 | n = read(STDIN_FILENO, buf, sizeof(buf)); |
106 | i = 0; | 99 | i = 0; |
107 | while (i < n) { | 100 | while (i < n) { |
108 | char c = buf[i]; | ||
109 | // show raw scancodes ordered? -> | ||
110 | if (option_mask32 & OPT_s) { | 101 | if (option_mask32 & OPT_s) { |
102 | // show raw scancodes | ||
111 | printf("0x%02x ", buf[i++]); | 103 | printf("0x%02x ", buf[i++]); |
112 | // show interpreted scancodes (default) ? -> | ||
113 | } else { | 104 | } else { |
105 | // show interpreted scancodes (default) | ||
106 | char c = buf[i]; | ||
114 | int kc; | 107 | int kc; |
115 | if (i+2 < n | 108 | if (i+2 < n |
116 | && (c & 0x7f) == 0 | 109 | && (c & 0x7f) == 0 |
@@ -130,9 +123,9 @@ int showkey_main(int argc UNUSED_PARAM, char **argv) | |||
130 | } | 123 | } |
131 | } | 124 | } |
132 | 125 | ||
133 | // cleanup | 126 | // restore keyboard and console settings |
134 | signal_handler(SIGALRM); | 127 | xset1(&tio0); |
128 | xioctl(STDIN_FILENO, KDSKBMODE, (void *)(ptrdiff_t)kbmode); | ||
135 | 129 | ||
136 | // should never be here! | ||
137 | return EXIT_SUCCESS; | 130 | return EXIT_SUCCESS; |
138 | } | 131 | } |
diff --git a/coreutils/Config.src b/coreutils/Config.src index adad4ba6d..b599f7999 100644 --- a/coreutils/Config.src +++ b/coreutils/Config.src | |||
@@ -664,13 +664,6 @@ config FEATURE_TEE_USE_BLOCK_IO | |||
664 | help | 664 | help |
665 | Enable this option for a faster tee, at expense of size. | 665 | Enable this option for a faster tee, at expense of size. |
666 | 666 | ||
667 | config TOUCH | ||
668 | bool "touch" | ||
669 | default y | ||
670 | help | ||
671 | touch is used to create or change the access and/or | ||
672 | modification timestamp of specified files. | ||
673 | |||
674 | config TRUE | 667 | config TRUE |
675 | bool "true" | 668 | bool "true" |
676 | default y | 669 | default y |
diff --git a/coreutils/Kbuild.src b/coreutils/Kbuild.src index 630b048df..4ea0fa50a 100644 --- a/coreutils/Kbuild.src +++ b/coreutils/Kbuild.src | |||
@@ -74,7 +74,6 @@ lib-$(CONFIG_SYNC) += sync.o | |||
74 | lib-$(CONFIG_TAC) += tac.o | 74 | lib-$(CONFIG_TAC) += tac.o |
75 | lib-$(CONFIG_TAIL) += tail.o | 75 | lib-$(CONFIG_TAIL) += tail.o |
76 | lib-$(CONFIG_TEE) += tee.o | 76 | lib-$(CONFIG_TEE) += tee.o |
77 | lib-$(CONFIG_TOUCH) += touch.o | ||
78 | lib-$(CONFIG_TRUE) += true.o | 77 | lib-$(CONFIG_TRUE) += true.o |
79 | lib-$(CONFIG_TTY) += tty.o | 78 | lib-$(CONFIG_TTY) += tty.o |
80 | lib-$(CONFIG_UNAME) += uname.o | 79 | lib-$(CONFIG_UNAME) += uname.o |
diff --git a/coreutils/date.c b/coreutils/date.c index eed4714f9..22d0a5327 100644 --- a/coreutils/date.c +++ b/coreutils/date.c | |||
@@ -250,6 +250,10 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
250 | ts.tv_sec = statbuf.st_mtime; | 250 | ts.tv_sec = statbuf.st_mtime; |
251 | #if ENABLE_FEATURE_DATE_NANO | 251 | #if ENABLE_FEATURE_DATE_NANO |
252 | ts.tv_nsec = statbuf.st_mtim.tv_nsec; | 252 | ts.tv_nsec = statbuf.st_mtim.tv_nsec; |
253 | /* Some toolchains use .st_mtimensec instead of st_mtim.tv_nsec. | ||
254 | * If you need #define _SVID_SOURCE 1 to enable st_mtim.tv_nsec, | ||
255 | * drop a mail to project mailing list please | ||
256 | */ | ||
253 | #endif | 257 | #endif |
254 | } else { | 258 | } else { |
255 | #if ENABLE_FEATURE_DATE_NANO | 259 | #if ENABLE_FEATURE_DATE_NANO |
@@ -278,7 +282,9 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
278 | } | 282 | } |
279 | 283 | ||
280 | /* Correct any day of week and day of year etc. fields */ | 284 | /* Correct any day of week and day of year etc. fields */ |
281 | tm_time.tm_isdst = -1; /* Be sure to recheck dst */ | 285 | /* Be sure to recheck dst (but not if date is time_t format) */ |
286 | if (date_str[0] != '@') | ||
287 | tm_time.tm_isdst = -1; | ||
282 | ts.tv_sec = validate_tm_time(date_str, &tm_time); | 288 | ts.tv_sec = validate_tm_time(date_str, &tm_time); |
283 | 289 | ||
284 | maybe_set_utc(opt); | 290 | maybe_set_utc(opt); |
diff --git a/coreutils/dd.c b/coreutils/dd.c index c22a39da7..da205ec69 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c | |||
@@ -24,7 +24,7 @@ static const struct suffix_mult dd_suffixes[] = { | |||
24 | { "b", 512 }, | 24 | { "b", 512 }, |
25 | { "kD", 1000 }, | 25 | { "kD", 1000 }, |
26 | { "k", 1024 }, | 26 | { "k", 1024 }, |
27 | { "K", 1024 }, /* compat with coreutils dd */ | 27 | { "K", 1024 }, /* compat with coreutils dd */ |
28 | { "MD", 1000000 }, | 28 | { "MD", 1000000 }, |
29 | { "M", 1048576 }, | 29 | { "M", 1048576 }, |
30 | { "GD", 1000000000 }, | 30 | { "GD", 1000000000 }, |
diff --git a/coreutils/ls.c b/coreutils/ls.c index 1a670201c..1afe28c8d 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c | |||
@@ -29,6 +29,71 @@ | |||
29 | * [2009-03] | 29 | * [2009-03] |
30 | * ls sorts listing now, and supports almost all options. | 30 | * ls sorts listing now, and supports almost all options. |
31 | */ | 31 | */ |
32 | |||
33 | //usage:#define ls_trivial_usage | ||
34 | //usage: "[-1AaCxd" | ||
35 | //usage: IF_FEATURE_LS_FOLLOWLINKS("LH") | ||
36 | //usage: IF_FEATURE_LS_RECURSIVE("R") | ||
37 | //usage: IF_FEATURE_LS_FILETYPES("Fp") "lins" | ||
38 | //usage: IF_FEATURE_LS_TIMESTAMPS("e") | ||
39 | //usage: IF_FEATURE_HUMAN_READABLE("h") | ||
40 | //usage: IF_FEATURE_LS_SORTFILES("rSXv") | ||
41 | //usage: IF_FEATURE_LS_TIMESTAMPS("ctu") | ||
42 | //usage: IF_SELINUX("kKZ") "]" | ||
43 | //usage: IF_FEATURE_AUTOWIDTH(" -w WIDTH") " [FILE]..." | ||
44 | //usage:#define ls_full_usage "\n\n" | ||
45 | //usage: "List directory contents\n" | ||
46 | //usage: "\nOptions:" | ||
47 | //usage: "\n -1 List in a single column" | ||
48 | //usage: "\n -A Don't list . and .." | ||
49 | //usage: "\n -a Don't hide entries starting with ." | ||
50 | //usage: "\n -C List by columns" | ||
51 | //usage: "\n -x List by lines" | ||
52 | //usage: "\n -d List directory entries instead of contents" | ||
53 | //usage: IF_FEATURE_LS_FOLLOWLINKS( | ||
54 | //usage: "\n -L Follow symlinks" | ||
55 | //usage: "\n -H Follow symlinks on command line only" | ||
56 | //usage: ) | ||
57 | //usage: IF_FEATURE_LS_RECURSIVE( | ||
58 | //usage: "\n -R Recurse" | ||
59 | //usage: ) | ||
60 | //usage: IF_FEATURE_LS_FILETYPES( | ||
61 | //usage: "\n -F Append indicator (one of */=@|) to entries" | ||
62 | //usage: "\n -p Append indicator (one of /=@|) to entries" | ||
63 | //usage: ) | ||
64 | //usage: "\n -l Long listing format" | ||
65 | //usage: "\n -i List inode numbers" | ||
66 | //usage: "\n -n List numeric UIDs and GIDs instead of names" | ||
67 | //usage: "\n -s List the size of each file, in blocks" | ||
68 | //usage: IF_FEATURE_LS_TIMESTAMPS( | ||
69 | //usage: "\n -e List full date and time" | ||
70 | //usage: ) | ||
71 | //usage: IF_FEATURE_HUMAN_READABLE( | ||
72 | //usage: "\n -h List sizes in human readable format (1K 243M 2G)" | ||
73 | //usage: ) | ||
74 | //usage: IF_FEATURE_LS_SORTFILES( | ||
75 | //usage: "\n -r Sort in reverse order" | ||
76 | //usage: "\n -S Sort by file size" | ||
77 | //usage: "\n -X Sort by extension" | ||
78 | //usage: "\n -v Sort by version" | ||
79 | //usage: ) | ||
80 | //usage: IF_FEATURE_LS_TIMESTAMPS( | ||
81 | //usage: "\n -c With -l: sort by ctime" | ||
82 | //usage: "\n -t With -l: sort by modification time" | ||
83 | //usage: "\n -u With -l: sort by access time" | ||
84 | //usage: ) | ||
85 | //usage: IF_SELINUX( | ||
86 | //usage: "\n -k List security context" | ||
87 | //usage: "\n -K List security context in long format" | ||
88 | //usage: "\n -Z List security context and permission" | ||
89 | //usage: ) | ||
90 | //usage: IF_FEATURE_AUTOWIDTH( | ||
91 | //usage: "\n -w N Assume the terminal is N columns wide" | ||
92 | //usage: ) | ||
93 | //usage: IF_FEATURE_LS_COLOR( | ||
94 | //usage: "\n --color[={always,never,auto}] Control coloring" | ||
95 | //usage: ) | ||
96 | |||
32 | #include "libbb.h" | 97 | #include "libbb.h" |
33 | #include "unicode.h" | 98 | #include "unicode.h" |
34 | 99 | ||
@@ -53,13 +118,12 @@ | |||
53 | 118 | ||
54 | enum { | 119 | enum { |
55 | TERMINAL_WIDTH = 80, /* use 79 if terminal has linefold bug */ | 120 | TERMINAL_WIDTH = 80, /* use 79 if terminal has linefold bug */ |
56 | COLUMN_GAP = 2, /* includes the file type char */ | ||
57 | 121 | ||
58 | /* what is the overall style of the listing */ | 122 | SPLIT_DIR = 1, |
59 | STYLE_COLUMNS = 1 << 21, /* fill columns */ | 123 | SPLIT_FILE = 0, |
60 | STYLE_LONG = 2 << 21, /* one record per line, extended info */ | 124 | SPLIT_SUBDIR = 2, |
61 | STYLE_SINGLE = 3 << 21, /* one record per line */ | 125 | |
62 | STYLE_MASK = STYLE_SINGLE, | 126 | /* Bits in all_fmt: */ |
63 | 127 | ||
64 | /* 51306 lrwxrwxrwx 1 root root 2 May 11 01:43 /bin/view -> vi* */ | 128 | /* 51306 lrwxrwxrwx 1 root root 2 May 11 01:43 /bin/view -> vi* */ |
65 | /* what file information will be listed */ | 129 | /* what file information will be listed */ |
@@ -71,75 +135,74 @@ LIST_ID_NAME = 1 << 4, | |||
71 | LIST_ID_NUMERIC = 1 << 5, | 135 | LIST_ID_NUMERIC = 1 << 5, |
72 | LIST_CONTEXT = 1 << 6, | 136 | LIST_CONTEXT = 1 << 6, |
73 | LIST_SIZE = 1 << 7, | 137 | LIST_SIZE = 1 << 7, |
74 | //LIST_DEV = 1 << 8, - unused, synonym to LIST_SIZE | 138 | LIST_DATE_TIME = 1 << 8, |
75 | LIST_DATE_TIME = 1 << 9, | 139 | LIST_FULLTIME = 1 << 9, |
76 | LIST_FULLTIME = 1 << 10, | 140 | LIST_SYMLINK = 1 << 10, |
77 | LIST_FILENAME = 1 << 11, | 141 | LIST_FILETYPE = 1 << 11, |
78 | LIST_SYMLINK = 1 << 12, | 142 | LIST_EXEC = 1 << 12, |
79 | LIST_FILETYPE = 1 << 13, | ||
80 | LIST_EXEC = 1 << 14, | ||
81 | LIST_MASK = (LIST_EXEC << 1) - 1, | 143 | LIST_MASK = (LIST_EXEC << 1) - 1, |
82 | 144 | ||
83 | /* what files will be displayed */ | 145 | /* what files will be displayed */ |
84 | DISP_DIRNAME = 1 << 15, /* 2 or more items? label directories */ | 146 | DISP_DIRNAME = 1 << 13, /* 2 or more items? label directories */ |
85 | DISP_HIDDEN = 1 << 16, /* show filenames starting with . */ | 147 | DISP_HIDDEN = 1 << 14, /* show filenames starting with . */ |
86 | DISP_DOT = 1 << 17, /* show . and .. */ | 148 | DISP_DOT = 1 << 15, /* show . and .. */ |
87 | DISP_NOLIST = 1 << 18, /* show directory as itself, not contents */ | 149 | DISP_NOLIST = 1 << 16, /* show directory as itself, not contents */ |
88 | DISP_RECURSIVE = 1 << 19, /* show directory and everything below it */ | 150 | DISP_RECURSIVE = 1 << 17, /* show directory and everything below it */ |
89 | DISP_ROWS = 1 << 20, /* print across rows */ | 151 | DISP_ROWS = 1 << 18, /* print across rows */ |
90 | DISP_MASK = ((DISP_ROWS << 1) - 1) & ~(DISP_DIRNAME - 1), | 152 | DISP_MASK = ((DISP_ROWS << 1) - 1) & ~(DISP_DIRNAME - 1), |
91 | 153 | ||
92 | /* how will the files be sorted (CONFIG_FEATURE_LS_SORTFILES) */ | 154 | /* what is the overall style of the listing */ |
93 | SORT_FORWARD = 0, /* sort in reverse order */ | 155 | STYLE_COLUMNAR = 1 << 19, /* many records per line */ |
94 | SORT_REVERSE = 1 << 27, /* sort in reverse order */ | 156 | STYLE_LONG = 2 << 19, /* one record per line, extended info */ |
95 | 157 | STYLE_SINGLE = 3 << 19, /* one record per line */ | |
96 | SORT_NAME = 0, /* sort by file name */ | 158 | STYLE_MASK = STYLE_SINGLE, |
97 | SORT_SIZE = 1 << 28, /* sort by file size */ | ||
98 | SORT_ATIME = 2 << 28, /* sort by last access time */ | ||
99 | SORT_CTIME = 3 << 28, /* sort by last change time */ | ||
100 | SORT_MTIME = 4 << 28, /* sort by last modification time */ | ||
101 | SORT_VERSION = 5 << 28, /* sort by version */ | ||
102 | SORT_EXT = 6 << 28, /* sort by file name extension */ | ||
103 | SORT_DIR = 7 << 28, /* sort by file or directory */ | ||
104 | SORT_MASK = (7 << 28) * ENABLE_FEATURE_LS_SORTFILES, | ||
105 | 159 | ||
106 | /* which of the three times will be used */ | 160 | /* which of the three times will be used */ |
107 | TIME_CHANGE = (1 << 23) * ENABLE_FEATURE_LS_TIMESTAMPS, | 161 | TIME_CHANGE = (1 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS, |
108 | TIME_ACCESS = (1 << 24) * ENABLE_FEATURE_LS_TIMESTAMPS, | 162 | TIME_ACCESS = (1 << 22) * ENABLE_FEATURE_LS_TIMESTAMPS, |
109 | TIME_MASK = (3 << 23) * ENABLE_FEATURE_LS_TIMESTAMPS, | 163 | TIME_MASK = (3 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS, |
110 | 164 | ||
111 | FOLLOW_LINKS = (1 << 25) * ENABLE_FEATURE_LS_FOLLOWLINKS, | 165 | /* how will the files be sorted (CONFIG_FEATURE_LS_SORTFILES) */ |
166 | SORT_REVERSE = 1 << 23, | ||
112 | 167 | ||
113 | LS_DISP_HR = (1 << 26) * ENABLE_FEATURE_HUMAN_READABLE, | 168 | SORT_NAME = 0, /* sort by file name */ |
169 | SORT_SIZE = 1 << 24, /* sort by file size */ | ||
170 | SORT_ATIME = 2 << 24, /* sort by last access time */ | ||
171 | SORT_CTIME = 3 << 24, /* sort by last change time */ | ||
172 | SORT_MTIME = 4 << 24, /* sort by last modification time */ | ||
173 | SORT_VERSION = 5 << 24, /* sort by version */ | ||
174 | SORT_EXT = 6 << 24, /* sort by file name extension */ | ||
175 | SORT_DIR = 7 << 24, /* sort by file or directory */ | ||
176 | SORT_MASK = (7 << 24) * ENABLE_FEATURE_LS_SORTFILES, | ||
114 | 177 | ||
115 | LIST_SHORT = LIST_FILENAME, | ||
116 | LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \ | 178 | LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \ |
117 | LIST_DATE_TIME | LIST_FILENAME | LIST_SYMLINK, | 179 | LIST_DATE_TIME | LIST_SYMLINK, |
118 | |||
119 | SPLIT_DIR = 1, | ||
120 | SPLIT_FILE = 0, | ||
121 | SPLIT_SUBDIR = 2, | ||
122 | }; | 180 | }; |
123 | 181 | ||
124 | /* "[-]Cadil1", POSIX mandated options, busybox always supports */ | 182 | /* -Cadil1 Std options, busybox always supports */ |
125 | /* "[-]gnsx", POSIX non-mandated options, busybox always supports */ | 183 | /* -gnsxA Std options, busybox always supports */ |
126 | /* "[-]Q" GNU option? busybox always supports */ | 184 | /* -Q GNU option, busybox always supports */ |
127 | /* "[-]Ak" GNU options, busybox always supports */ | 185 | /* -k SELinux option, busybox always supports (ignores if !SELinux) */ |
128 | /* "[-]FLRctur", POSIX mandated options, busybox optionally supports */ | 186 | /* Std has -k which means "show sizes in kbytes" */ |
129 | /* "[-]p", POSIX non-mandated options, busybox optionally supports */ | 187 | /* -FLHRctur Std options, busybox optionally supports */ |
130 | /* "[-]SXvThw", GNU options, busybox optionally supports */ | 188 | /* -p Std option, busybox optionally supports */ |
131 | /* "[-]K", SELinux mandated options, busybox optionally supports */ | 189 | /* Not fully compatible - we show not only '/' but other chars too */ |
132 | /* "[-]e", I think we made this one up */ | 190 | /* -SXvhTw GNU options, busybox optionally supports */ |
191 | /* -T TABWIDTH is ignored (we don't use tabs on output) */ | ||
192 | /* -K SELinux mandated options, busybox optionally supports */ | ||
193 | /* -e I think we made this one up (looks similar to GNU --full-time) */ | ||
194 | /* Std opts we do not support: */ | ||
195 | /* -H Follow the links on command line only */ | ||
133 | static const char ls_options[] ALIGN1 = | 196 | static const char ls_options[] ALIGN1 = |
134 | "Cadil1gnsxQAk" /* 13 opts, total 13 */ | 197 | "Cadil1gnsxQAk" /* 13 opts, total 13 */ |
135 | IF_FEATURE_LS_TIMESTAMPS("cetu") /* 4, 17 */ | 198 | IF_FEATURE_LS_TIMESTAMPS("cetu") /* 4, 17 */ |
136 | IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 21 */ | 199 | IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 21 */ |
137 | IF_FEATURE_LS_FILETYPES("Fp") /* 2, 23 */ | 200 | IF_FEATURE_LS_FILETYPES("Fp") /* 2, 23 */ |
138 | IF_FEATURE_LS_FOLLOWLINKS("L") /* 1, 24 */ | 201 | IF_FEATURE_LS_RECURSIVE("R") /* 1, 24 */ |
139 | IF_FEATURE_LS_RECURSIVE("R") /* 1, 25 */ | 202 | IF_SELINUX("KZ") /* 2, 26 */ |
140 | IF_FEATURE_HUMAN_READABLE("h") /* 1, 26 */ | 203 | IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 28 */ |
141 | IF_SELINUX("KZ") /* 2, 28 */ | 204 | IF_FEATURE_HUMAN_READABLE("h") /* 1, 29 */ |
142 | IF_FEATURE_AUTOWIDTH("T:w:") /* 2, 30 */ | 205 | IF_FEATURE_AUTOWIDTH("T:w:") /* 2, 31 */ |
143 | ; | 206 | ; |
144 | enum { | 207 | enum { |
145 | //OPT_C = (1 << 0), | 208 | //OPT_C = (1 << 0), |
@@ -155,75 +218,88 @@ enum { | |||
155 | OPT_Q = (1 << 10), | 218 | OPT_Q = (1 << 10), |
156 | //OPT_A = (1 << 11), | 219 | //OPT_A = (1 << 11), |
157 | //OPT_k = (1 << 12), | 220 | //OPT_k = (1 << 12), |
158 | OPTBIT_color = 13 | ||
159 | + 4 * ENABLE_FEATURE_LS_TIMESTAMPS | ||
160 | + 4 * ENABLE_FEATURE_LS_SORTFILES | ||
161 | + 2 * ENABLE_FEATURE_LS_FILETYPES | ||
162 | + 1 * ENABLE_FEATURE_LS_FOLLOWLINKS | ||
163 | + 1 * ENABLE_FEATURE_LS_RECURSIVE | ||
164 | + 1 * ENABLE_FEATURE_HUMAN_READABLE | ||
165 | + 2 * ENABLE_SELINUX | ||
166 | + 2 * ENABLE_FEATURE_AUTOWIDTH, | ||
167 | OPT_color = 1 << OPTBIT_color, | ||
168 | }; | ||
169 | 221 | ||
170 | enum { | 222 | OPTBIT_c = 13, |
171 | LIST_MASK_TRIGGER = 0, | 223 | OPTBIT_e, |
172 | STYLE_MASK_TRIGGER = STYLE_MASK, | 224 | OPTBIT_t, |
173 | DISP_MASK_TRIGGER = DISP_ROWS, | 225 | OPTBIT_u, |
174 | SORT_MASK_TRIGGER = SORT_MASK, | 226 | OPTBIT_S = OPTBIT_c + 4 * ENABLE_FEATURE_LS_TIMESTAMPS, |
227 | OPTBIT_X, /* 18 */ | ||
228 | OPTBIT_r, | ||
229 | OPTBIT_v, | ||
230 | OPTBIT_F = OPTBIT_S + 4 * ENABLE_FEATURE_LS_SORTFILES, | ||
231 | OPTBIT_p, /* 22 */ | ||
232 | OPTBIT_R = OPTBIT_F + 2 * ENABLE_FEATURE_LS_FILETYPES, | ||
233 | OPTBIT_K = OPTBIT_R + 1 * ENABLE_FEATURE_LS_RECURSIVE, | ||
234 | OPTBIT_Z, /* 25 */ | ||
235 | OPTBIT_L = OPTBIT_K + 2 * ENABLE_SELINUX, | ||
236 | OPTBIT_H, /* 27 */ | ||
237 | OPTBIT_h = OPTBIT_L + 1 * ENABLE_FEATURE_LS_FOLLOWLINKS, | ||
238 | OPTBIT_T = OPTBIT_h + 2 * ENABLE_FEATURE_HUMAN_READABLE, | ||
239 | OPTBIT_w, /* 30 */ | ||
240 | OPTBIT_color = OPTBIT_T + 2 * ENABLE_FEATURE_AUTOWIDTH, | ||
241 | |||
242 | OPT_c = (1 << OPTBIT_c) * ENABLE_FEATURE_LS_TIMESTAMPS, | ||
243 | OPT_e = (1 << OPTBIT_e) * ENABLE_FEATURE_LS_TIMESTAMPS, | ||
244 | OPT_t = (1 << OPTBIT_t) * ENABLE_FEATURE_LS_TIMESTAMPS, | ||
245 | OPT_u = (1 << OPTBIT_u) * ENABLE_FEATURE_LS_TIMESTAMPS, | ||
246 | OPT_S = (1 << OPTBIT_S) * ENABLE_FEATURE_LS_SORTFILES, | ||
247 | OPT_X = (1 << OPTBIT_X) * ENABLE_FEATURE_LS_SORTFILES, | ||
248 | OPT_r = (1 << OPTBIT_r) * ENABLE_FEATURE_LS_SORTFILES, | ||
249 | OPT_v = (1 << OPTBIT_v) * ENABLE_FEATURE_LS_SORTFILES, | ||
250 | OPT_F = (1 << OPTBIT_F) * ENABLE_FEATURE_LS_FILETYPES, | ||
251 | OPT_p = (1 << OPTBIT_p) * ENABLE_FEATURE_LS_FILETYPES, | ||
252 | OPT_R = (1 << OPTBIT_R) * ENABLE_FEATURE_LS_RECURSIVE, | ||
253 | OPT_K = (1 << OPTBIT_K) * ENABLE_SELINUX, | ||
254 | OPT_Z = (1 << OPTBIT_Z) * ENABLE_SELINUX, | ||
255 | OPT_L = (1 << OPTBIT_L) * ENABLE_FEATURE_LS_FOLLOWLINKS, | ||
256 | OPT_H = (1 << OPTBIT_H) * ENABLE_FEATURE_LS_FOLLOWLINKS, | ||
257 | OPT_h = (1 << OPTBIT_h) * ENABLE_FEATURE_HUMAN_READABLE, | ||
258 | OPT_T = (1 << OPTBIT_T) * ENABLE_FEATURE_AUTOWIDTH, | ||
259 | OPT_w = (1 << OPTBIT_w) * ENABLE_FEATURE_AUTOWIDTH, | ||
260 | OPT_color = (1 << OPTBIT_color) * ENABLE_FEATURE_LS_COLOR, | ||
175 | }; | 261 | }; |
176 | 262 | ||
177 | /* TODO: simple toggles may be stored as OPT_xxx bits instead */ | 263 | /* TODO: simple toggles may be stored as OPT_xxx bits instead */ |
178 | static const unsigned opt_flags[] = { | 264 | static const uint32_t opt_flags[] = { |
179 | LIST_SHORT | STYLE_COLUMNS, /* C */ | 265 | STYLE_COLUMNAR, /* C */ |
180 | DISP_HIDDEN | DISP_DOT, /* a */ | 266 | DISP_HIDDEN | DISP_DOT, /* a */ |
181 | DISP_NOLIST, /* d */ | 267 | DISP_NOLIST, /* d */ |
182 | LIST_INO, /* i */ | 268 | LIST_INO, /* i */ |
183 | LIST_LONG | STYLE_LONG, /* l - remember LS_DISP_HR in mask! */ | 269 | LIST_LONG | STYLE_LONG, /* l */ |
184 | LIST_SHORT | STYLE_SINGLE, /* 1 */ | 270 | STYLE_SINGLE, /* 1 */ |
185 | 0, /* g (don't show group) - handled via OPT_g */ | 271 | 0, /* g (don't show owner) - handled via OPT_g */ |
186 | LIST_ID_NUMERIC, /* n */ | 272 | LIST_ID_NUMERIC, /* n */ |
187 | LIST_BLOCKS, /* s */ | 273 | LIST_BLOCKS, /* s */ |
188 | DISP_ROWS, /* x */ | 274 | DISP_ROWS | STYLE_COLUMNAR, /* x */ |
189 | 0, /* Q (quote filename) - handled via OPT_Q */ | 275 | 0, /* Q (quote filename) - handled via OPT_Q */ |
190 | DISP_HIDDEN, /* A */ | 276 | DISP_HIDDEN, /* A */ |
191 | ENABLE_SELINUX * LIST_CONTEXT, /* k (ignored if !SELINUX) */ | 277 | ENABLE_SELINUX * LIST_CONTEXT, /* k (ignored if !SELINUX) */ |
192 | #if ENABLE_FEATURE_LS_TIMESTAMPS | 278 | #if ENABLE_FEATURE_LS_TIMESTAMPS |
193 | TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME), /* c */ | 279 | TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME), /* c */ |
194 | LIST_FULLTIME, /* e */ | 280 | LIST_FULLTIME, /* e */ |
195 | ENABLE_FEATURE_LS_SORTFILES * SORT_MTIME, /* t */ | 281 | ENABLE_FEATURE_LS_SORTFILES * SORT_MTIME, /* t */ |
196 | TIME_ACCESS | (ENABLE_FEATURE_LS_SORTFILES * SORT_ATIME), /* u */ | 282 | TIME_ACCESS | (ENABLE_FEATURE_LS_SORTFILES * SORT_ATIME), /* u */ |
197 | #endif | 283 | #endif |
198 | #if ENABLE_FEATURE_LS_SORTFILES | 284 | #if ENABLE_FEATURE_LS_SORTFILES |
199 | SORT_SIZE, /* S */ | 285 | SORT_SIZE, /* S */ |
200 | SORT_EXT, /* X */ | 286 | SORT_EXT, /* X */ |
201 | SORT_REVERSE, /* r */ | 287 | SORT_REVERSE, /* r */ |
202 | SORT_VERSION, /* v */ | 288 | SORT_VERSION, /* v */ |
203 | #endif | 289 | #endif |
204 | #if ENABLE_FEATURE_LS_FILETYPES | 290 | #if ENABLE_FEATURE_LS_FILETYPES |
205 | LIST_FILETYPE | LIST_EXEC, /* F */ | 291 | LIST_FILETYPE | LIST_EXEC, /* F */ |
206 | LIST_FILETYPE, /* p */ | 292 | LIST_FILETYPE, /* p */ |
207 | #endif | ||
208 | #if ENABLE_FEATURE_LS_FOLLOWLINKS | ||
209 | FOLLOW_LINKS, /* L */ | ||
210 | #endif | 293 | #endif |
211 | #if ENABLE_FEATURE_LS_RECURSIVE | 294 | #if ENABLE_FEATURE_LS_RECURSIVE |
212 | DISP_RECURSIVE, /* R */ | 295 | DISP_RECURSIVE, /* R */ |
213 | #endif | ||
214 | #if ENABLE_FEATURE_HUMAN_READABLE | ||
215 | LS_DISP_HR, /* h */ | ||
216 | #endif | 296 | #endif |
217 | #if ENABLE_SELINUX | 297 | #if ENABLE_SELINUX |
218 | LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME, /* K */ | 298 | LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME, /* K */ |
219 | #endif | ||
220 | #if ENABLE_SELINUX | ||
221 | LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT, /* Z */ | 299 | LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT, /* Z */ |
222 | #endif | 300 | #endif |
223 | (1U<<31) | 301 | (1U << 31) |
224 | /* options after Z are not processed through opt_flags: | 302 | /* options after Z are not processed through opt_flags */ |
225 | * T, w - ignored | ||
226 | */ | ||
227 | }; | 303 | }; |
228 | 304 | ||
229 | 305 | ||
@@ -246,7 +322,6 @@ struct globals { | |||
246 | smallint exit_code; | 322 | smallint exit_code; |
247 | unsigned all_fmt; | 323 | unsigned all_fmt; |
248 | #if ENABLE_FEATURE_AUTOWIDTH | 324 | #if ENABLE_FEATURE_AUTOWIDTH |
249 | unsigned tabstops; // = COLUMN_GAP; | ||
250 | unsigned terminal_width; // = TERMINAL_WIDTH; | 325 | unsigned terminal_width; // = TERMINAL_WIDTH; |
251 | #endif | 326 | #endif |
252 | #if ENABLE_FEATURE_LS_TIMESTAMPS | 327 | #if ENABLE_FEATURE_LS_TIMESTAMPS |
@@ -263,11 +338,9 @@ enum { show_color = 0 }; | |||
263 | #define exit_code (G.exit_code ) | 338 | #define exit_code (G.exit_code ) |
264 | #define all_fmt (G.all_fmt ) | 339 | #define all_fmt (G.all_fmt ) |
265 | #if ENABLE_FEATURE_AUTOWIDTH | 340 | #if ENABLE_FEATURE_AUTOWIDTH |
266 | # define tabstops (G.tabstops ) | ||
267 | # define terminal_width (G.terminal_width) | 341 | # define terminal_width (G.terminal_width) |
268 | #else | 342 | #else |
269 | enum { | 343 | enum { |
270 | tabstops = COLUMN_GAP, | ||
271 | terminal_width = TERMINAL_WIDTH, | 344 | terminal_width = TERMINAL_WIDTH, |
272 | }; | 345 | }; |
273 | #endif | 346 | #endif |
@@ -275,7 +348,6 @@ enum { | |||
275 | #define INIT_G() do { \ | 348 | #define INIT_G() do { \ |
276 | /* we have to zero it out because of NOEXEC */ \ | 349 | /* we have to zero it out because of NOEXEC */ \ |
277 | memset(&G, 0, sizeof(G)); \ | 350 | memset(&G, 0, sizeof(G)); \ |
278 | IF_FEATURE_AUTOWIDTH(tabstops = COLUMN_GAP;) \ | ||
279 | IF_FEATURE_AUTOWIDTH(terminal_width = TERMINAL_WIDTH;) \ | 351 | IF_FEATURE_AUTOWIDTH(terminal_width = TERMINAL_WIDTH;) \ |
280 | IF_FEATURE_LS_TIMESTAMPS(time(¤t_time_t);) \ | 352 | IF_FEATURE_LS_TIMESTAMPS(time(¤t_time_t);) \ |
281 | } while (0) | 353 | } while (0) |
@@ -287,7 +359,7 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f | |||
287 | struct dnode *cur; | 359 | struct dnode *cur; |
288 | IF_SELINUX(security_context_t sid = NULL;) | 360 | IF_SELINUX(security_context_t sid = NULL;) |
289 | 361 | ||
290 | if ((all_fmt & FOLLOW_LINKS) || force_follow) { | 362 | if ((option_mask32 & OPT_L) || force_follow) { |
291 | #if ENABLE_SELINUX | 363 | #if ENABLE_SELINUX |
292 | if (is_selinux_enabled()) { | 364 | if (is_selinux_enabled()) { |
293 | getfilecon(fullname, &sid); | 365 | getfilecon(fullname, &sid); |
@@ -547,7 +619,7 @@ static unsigned calc_name_len(const char *name) | |||
547 | 619 | ||
548 | 620 | ||
549 | /* Return the number of used columns. | 621 | /* Return the number of used columns. |
550 | * Note that only STYLE_COLUMNS uses return value. | 622 | * Note that only STYLE_COLUMNAR uses return value. |
551 | * STYLE_SINGLE and STYLE_LONG don't care. | 623 | * STYLE_SINGLE and STYLE_LONG don't care. |
552 | * coreutils 7.2 also supports: | 624 | * coreutils 7.2 also supports: |
553 | * ls -b (--escape) = octal escapes (although it doesn't look like working) | 625 | * ls -b (--escape) = octal escapes (although it doesn't look like working) |
@@ -581,7 +653,7 @@ static unsigned print_name(const char *name) | |||
581 | } | 653 | } |
582 | 654 | ||
583 | /* Return the number of used columns. | 655 | /* Return the number of used columns. |
584 | * Note that only STYLE_COLUMNS uses return value, | 656 | * Note that only STYLE_COLUMNAR uses return value, |
585 | * STYLE_SINGLE and STYLE_LONG don't care. | 657 | * STYLE_SINGLE and STYLE_LONG don't care. |
586 | */ | 658 | */ |
587 | static NOINLINE unsigned list_single(const struct dnode *dn) | 659 | static NOINLINE unsigned list_single(const struct dnode *dn) |
@@ -625,7 +697,7 @@ static NOINLINE unsigned list_single(const struct dnode *dn) | |||
625 | if (all_fmt & LIST_ID_NAME) { | 697 | if (all_fmt & LIST_ID_NAME) { |
626 | if (option_mask32 & OPT_g) { | 698 | if (option_mask32 & OPT_g) { |
627 | column += printf("%-8.8s ", | 699 | column += printf("%-8.8s ", |
628 | get_cached_username(dn->dstat.st_uid)); | 700 | get_cached_groupname(dn->dstat.st_gid)); |
629 | } else { | 701 | } else { |
630 | column += printf("%-8.8s %-8.8s ", | 702 | column += printf("%-8.8s %-8.8s ", |
631 | get_cached_username(dn->dstat.st_uid), | 703 | get_cached_username(dn->dstat.st_uid), |
@@ -635,19 +707,19 @@ static NOINLINE unsigned list_single(const struct dnode *dn) | |||
635 | #endif | 707 | #endif |
636 | if (all_fmt & LIST_ID_NUMERIC) { | 708 | if (all_fmt & LIST_ID_NUMERIC) { |
637 | if (option_mask32 & OPT_g) | 709 | if (option_mask32 & OPT_g) |
638 | column += printf("%-8u ", (int) dn->dstat.st_uid); | 710 | column += printf("%-8u ", (int) dn->dstat.st_gid); |
639 | else | 711 | else |
640 | column += printf("%-8u %-8u ", | 712 | column += printf("%-8u %-8u ", |
641 | (int) dn->dstat.st_uid, | 713 | (int) dn->dstat.st_uid, |
642 | (int) dn->dstat.st_gid); | 714 | (int) dn->dstat.st_gid); |
643 | } | 715 | } |
644 | if (all_fmt & (LIST_SIZE /*|LIST_DEV*/ )) { | 716 | if (all_fmt & LIST_SIZE) { |
645 | if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) { | 717 | if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) { |
646 | column += printf("%4u, %3u ", | 718 | column += printf("%4u, %3u ", |
647 | (int) major(dn->dstat.st_rdev), | 719 | (int) major(dn->dstat.st_rdev), |
648 | (int) minor(dn->dstat.st_rdev)); | 720 | (int) minor(dn->dstat.st_rdev)); |
649 | } else { | 721 | } else { |
650 | if (all_fmt & LS_DISP_HR) { | 722 | if (option_mask32 & OPT_h) { |
651 | column += printf("%"HUMAN_READABLE_MAX_WIDTH_STR"s ", | 723 | column += printf("%"HUMAN_READABLE_MAX_WIDTH_STR"s ", |
652 | /* print st_size, show one fractional, use suffixes */ | 724 | /* print st_size, show one fractional, use suffixes */ |
653 | make_human_readable_str(dn->dstat.st_size, 1, 0) | 725 | make_human_readable_str(dn->dstat.st_size, 1, 0) |
@@ -689,20 +761,20 @@ static NOINLINE unsigned list_single(const struct dnode *dn) | |||
689 | freecon(dn->sid); | 761 | freecon(dn->sid); |
690 | } | 762 | } |
691 | #endif | 763 | #endif |
692 | if (all_fmt & LIST_FILENAME) { | 764 | |
693 | #if ENABLE_FEATURE_LS_COLOR | 765 | #if ENABLE_FEATURE_LS_COLOR |
694 | if (show_color) { | 766 | if (show_color) { |
695 | info.st_mode = 0; /* for fgcolor() */ | 767 | info.st_mode = 0; /* for fgcolor() */ |
696 | lstat(dn->fullname, &info); | 768 | lstat(dn->fullname, &info); |
697 | printf("\033[%u;%um", bold(info.st_mode), | 769 | printf("\033[%u;%um", bold(info.st_mode), |
698 | fgcolor(info.st_mode)); | 770 | fgcolor(info.st_mode)); |
699 | } | 771 | } |
700 | #endif | 772 | #endif |
701 | column += print_name(dn->name); | 773 | column += print_name(dn->name); |
702 | if (show_color) { | 774 | if (show_color) { |
703 | printf("\033[0m"); | 775 | printf("\033[0m"); |
704 | } | ||
705 | } | 776 | } |
777 | |||
706 | if (all_fmt & LIST_SYMLINK) { | 778 | if (all_fmt & LIST_SYMLINK) { |
707 | if (S_ISLNK(dn->dstat.st_mode) && lpath) { | 779 | if (S_ISLNK(dn->dstat.st_mode) && lpath) { |
708 | printf(" -> "); | 780 | printf(" -> "); |
@@ -742,9 +814,9 @@ static NOINLINE unsigned list_single(const struct dnode *dn) | |||
742 | static void showfiles(struct dnode **dn, unsigned nfiles) | 814 | static void showfiles(struct dnode **dn, unsigned nfiles) |
743 | { | 815 | { |
744 | unsigned i, ncols, nrows, row, nc; | 816 | unsigned i, ncols, nrows, row, nc; |
745 | unsigned column = 0; | 817 | unsigned column; |
746 | unsigned nexttab = 0; | 818 | unsigned nexttab; |
747 | unsigned column_width = 0; /* used only by STYLE_COLUMNS */ | 819 | unsigned column_width = 0; /* used only by STYLE_COLUMNAR */ |
748 | 820 | ||
749 | if (all_fmt & STYLE_LONG) { /* STYLE_LONG or STYLE_SINGLE */ | 821 | if (all_fmt & STYLE_LONG) { /* STYLE_LONG or STYLE_SINGLE */ |
750 | ncols = 1; | 822 | ncols = 1; |
@@ -755,7 +827,7 @@ static void showfiles(struct dnode **dn, unsigned nfiles) | |||
755 | if (column_width < len) | 827 | if (column_width < len) |
756 | column_width = len; | 828 | column_width = len; |
757 | } | 829 | } |
758 | column_width += tabstops + | 830 | column_width += 1 + |
759 | IF_SELINUX( ((all_fmt & LIST_CONTEXT) ? 33 : 0) + ) | 831 | IF_SELINUX( ((all_fmt & LIST_CONTEXT) ? 33 : 0) + ) |
760 | ((all_fmt & LIST_INO) ? 8 : 0) + | 832 | ((all_fmt & LIST_INO) ? 8 : 0) + |
761 | ((all_fmt & LIST_BLOCKS) ? 5 : 0); | 833 | ((all_fmt & LIST_BLOCKS) ? 5 : 0); |
@@ -771,6 +843,8 @@ static void showfiles(struct dnode **dn, unsigned nfiles) | |||
771 | ncols = 1; | 843 | ncols = 1; |
772 | } | 844 | } |
773 | 845 | ||
846 | column = 0; | ||
847 | nexttab = 0; | ||
774 | for (row = 0; row < nrows; row++) { | 848 | for (row = 0; row < nrows; row++) { |
775 | for (nc = 0; nc < ncols; nc++) { | 849 | for (nc = 0; nc < ncols; nc++) { |
776 | /* reach into the array based on the column and row */ | 850 | /* reach into the array based on the column and row */ |
@@ -781,8 +855,8 @@ static void showfiles(struct dnode **dn, unsigned nfiles) | |||
781 | if (i < nfiles) { | 855 | if (i < nfiles) { |
782 | if (column > 0) { | 856 | if (column > 0) { |
783 | nexttab -= column; | 857 | nexttab -= column; |
784 | printf("%*s", nexttab, ""); | 858 | printf("%*s ", nexttab, ""); |
785 | column += nexttab; | 859 | column += nexttab + 1; |
786 | } | 860 | } |
787 | nexttab = column + column_width; | 861 | nexttab = column + column_width; |
788 | column += list_single(dn[i]); | 862 | column += list_single(dn[i]); |
@@ -835,12 +909,6 @@ static void showdirs(struct dnode **dn, int first) | |||
835 | struct dnode **subdnp; | 909 | struct dnode **subdnp; |
836 | struct dnode **dnd; | 910 | struct dnode **dnd; |
837 | 911 | ||
838 | /* Never happens: | ||
839 | if (dn == NULL || ndirs < 1) { | ||
840 | return; | ||
841 | } | ||
842 | */ | ||
843 | |||
844 | for (; *dn; dn++) { | 912 | for (; *dn; dn++) { |
845 | if (all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) { | 913 | if (all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) { |
846 | if (!first) | 914 | if (!first) |
@@ -981,8 +1049,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv) | |||
981 | 1049 | ||
982 | init_unicode(); | 1050 | init_unicode(); |
983 | 1051 | ||
984 | all_fmt = LIST_SHORT | | 1052 | all_fmt = ENABLE_FEATURE_LS_SORTFILES * SORT_NAME; |
985 | (ENABLE_FEATURE_LS_SORTFILES * (SORT_NAME | SORT_FORWARD)); | ||
986 | 1053 | ||
987 | #if ENABLE_FEATURE_AUTOWIDTH | 1054 | #if ENABLE_FEATURE_AUTOWIDTH |
988 | /* obtain the terminal width */ | 1055 | /* obtain the terminal width */ |
@@ -993,32 +1060,38 @@ int ls_main(int argc UNUSED_PARAM, char **argv) | |||
993 | 1060 | ||
994 | /* process options */ | 1061 | /* process options */ |
995 | IF_FEATURE_LS_COLOR(applet_long_options = ls_longopts;) | 1062 | IF_FEATURE_LS_COLOR(applet_long_options = ls_longopts;) |
996 | #if ENABLE_FEATURE_AUTOWIDTH | 1063 | opt_complementary = |
997 | opt_complementary = "T+:w+"; /* -T N, -w N */ | 1064 | /* -e implies -l */ |
998 | opt = getopt32(argv, ls_options, &tabstops, &terminal_width | 1065 | "el" |
999 | IF_FEATURE_LS_COLOR(, &color_opt)); | 1066 | /* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html: |
1000 | #else | 1067 | * in some pairs of opts, only last one takes effect: |
1001 | opt = getopt32(argv, ls_options IF_FEATURE_LS_COLOR(, &color_opt)); | 1068 | */ |
1002 | #endif | 1069 | IF_FEATURE_LS_TIMESTAMPS(IF_FEATURE_LS_SORTFILES(":t-S:S-t")) /* time/size */ |
1003 | for (i = 0; opt_flags[i] != (1U<<31); i++) { | 1070 | // ":m-l:l-m" - we don't have -m |
1071 | IF_FEATURE_LS_FOLLOWLINKS(":H-L:L-H") | ||
1072 | ":C-xl:x-Cl:l-xC" /* bycols/bylines/long */ | ||
1073 | ":C-1:1-C" /* bycols/oneline */ | ||
1074 | ":x-1:1-x" /* bylines/oneline (not in SuS, but in GNU coreutils 8.4) */ | ||
1075 | ":c-u:u-c" /* mtime/atime */ | ||
1076 | /* -w NUM: */ | ||
1077 | IF_FEATURE_AUTOWIDTH(":w+"); | ||
1078 | opt = getopt32(argv, ls_options | ||
1079 | IF_FEATURE_AUTOWIDTH(, NULL, &terminal_width) | ||
1080 | IF_FEATURE_LS_COLOR(, &color_opt) | ||
1081 | ); | ||
1082 | for (i = 0; opt_flags[i] != (1U << 31); i++) { | ||
1004 | if (opt & (1 << i)) { | 1083 | if (opt & (1 << i)) { |
1005 | unsigned flags = opt_flags[i]; | 1084 | uint32_t flags = opt_flags[i]; |
1006 | 1085 | ||
1007 | if (flags & LIST_MASK_TRIGGER) | 1086 | if (flags & STYLE_MASK) |
1008 | all_fmt &= ~LIST_MASK; | ||
1009 | if (flags & STYLE_MASK_TRIGGER) | ||
1010 | all_fmt &= ~STYLE_MASK; | 1087 | all_fmt &= ~STYLE_MASK; |
1011 | if (flags & SORT_MASK_TRIGGER) | 1088 | if (flags & SORT_MASK) |
1012 | all_fmt &= ~SORT_MASK; | 1089 | all_fmt &= ~SORT_MASK; |
1013 | if (flags & DISP_MASK_TRIGGER) | ||
1014 | all_fmt &= ~DISP_MASK; | ||
1015 | if (flags & TIME_MASK) | 1090 | if (flags & TIME_MASK) |
1016 | all_fmt &= ~TIME_MASK; | 1091 | all_fmt &= ~TIME_MASK; |
1092 | |||
1017 | if (flags & LIST_CONTEXT) | 1093 | if (flags & LIST_CONTEXT) |
1018 | all_fmt |= STYLE_SINGLE; | 1094 | all_fmt |= STYLE_SINGLE; |
1019 | /* huh?? opt cannot be 'l' */ | ||
1020 | //if (LS_DISP_HR && opt == 'l') | ||
1021 | // all_fmt &= ~LS_DISP_HR; | ||
1022 | all_fmt |= flags; | 1095 | all_fmt |= flags; |
1023 | } | 1096 | } |
1024 | } | 1097 | } |
@@ -1058,14 +1131,14 @@ int ls_main(int argc UNUSED_PARAM, char **argv) | |||
1058 | all_fmt = (all_fmt & ~SORT_MASK) | SORT_ATIME; | 1131 | all_fmt = (all_fmt & ~SORT_MASK) | SORT_ATIME; |
1059 | } | 1132 | } |
1060 | if ((all_fmt & STYLE_MASK) != STYLE_LONG) /* only for long list */ | 1133 | if ((all_fmt & STYLE_MASK) != STYLE_LONG) /* only for long list */ |
1061 | all_fmt &= ~(LIST_ID_NUMERIC|LIST_FULLTIME|LIST_ID_NAME|LIST_ID_NUMERIC); | 1134 | all_fmt &= ~(LIST_ID_NUMERIC|LIST_ID_NAME|LIST_FULLTIME); |
1062 | if (ENABLE_FEATURE_LS_USERNAME) | 1135 | if (ENABLE_FEATURE_LS_USERNAME) |
1063 | if ((all_fmt & STYLE_MASK) == STYLE_LONG && (all_fmt & LIST_ID_NUMERIC)) | 1136 | if ((all_fmt & STYLE_MASK) == STYLE_LONG && (all_fmt & LIST_ID_NUMERIC)) |
1064 | all_fmt &= ~LIST_ID_NAME; /* don't list names if numeric uid */ | 1137 | all_fmt &= ~LIST_ID_NAME; /* don't list names if numeric uid */ |
1065 | 1138 | ||
1066 | /* choose a display format */ | 1139 | /* choose a display format if one was not already specified by an option */ |
1067 | if (!(all_fmt & STYLE_MASK)) | 1140 | if (!(all_fmt & STYLE_MASK)) |
1068 | all_fmt |= (isatty(STDOUT_FILENO) ? STYLE_COLUMNS : STYLE_SINGLE); | 1141 | all_fmt |= (isatty(STDOUT_FILENO) ? STYLE_COLUMNAR : STYLE_SINGLE); |
1069 | 1142 | ||
1070 | argv += optind; | 1143 | argv += optind; |
1071 | if (!argv[0]) | 1144 | if (!argv[0]) |
@@ -1078,8 +1151,12 @@ int ls_main(int argc UNUSED_PARAM, char **argv) | |||
1078 | dn = NULL; | 1151 | dn = NULL; |
1079 | nfiles = 0; | 1152 | nfiles = 0; |
1080 | do { | 1153 | do { |
1081 | /* NB: follow links on command line unless -l or -s */ | 1154 | cur = my_stat(*argv, *argv, |
1082 | cur = my_stat(*argv, *argv, !(all_fmt & (STYLE_LONG|LIST_BLOCKS))); | 1155 | /* follow links on command line unless -l, -s or -F: */ |
1156 | !((all_fmt & (STYLE_LONG|LIST_BLOCKS)) || (option_mask32 & OPT_F)) | ||
1157 | /* ... or if -H: */ | ||
1158 | || (option_mask32 & OPT_H) | ||
1159 | ); | ||
1083 | argv++; | 1160 | argv++; |
1084 | if (!cur) | 1161 | if (!cur) |
1085 | continue; | 1162 | continue; |
diff --git a/coreutils/mv.c b/coreutils/mv.c index 245639bd0..399f391b2 100644 --- a/coreutils/mv.c +++ b/coreutils/mv.c | |||
@@ -92,7 +92,7 @@ int mv_main(int argc, char **argv) | |||
92 | || (flags & OPT_FILEUTILS_INTERACTIVE)) | 92 | || (flags & OPT_FILEUTILS_INTERACTIVE)) |
93 | ) { | 93 | ) { |
94 | if (fprintf(stderr, "mv: overwrite '%s'? ", dest) < 0) { | 94 | if (fprintf(stderr, "mv: overwrite '%s'? ", dest) < 0) { |
95 | goto RET_1; /* Ouch! fprintf failed! */ | 95 | goto RET_1; /* Ouch! fprintf failed! */ |
96 | } | 96 | } |
97 | if (!bb_ask_confirmation()) { | 97 | if (!bb_ask_confirmation()) { |
98 | goto RET_0; | 98 | goto RET_0; |
diff --git a/coreutils/nice.c b/coreutils/nice.c index 6b8fce24d..35d6bf3d9 100644 --- a/coreutils/nice.c +++ b/coreutils/nice.c | |||
@@ -17,12 +17,12 @@ int nice_main(int argc, char **argv) | |||
17 | 17 | ||
18 | old_priority = getpriority(PRIO_PROCESS, 0); | 18 | old_priority = getpriority(PRIO_PROCESS, 0); |
19 | 19 | ||
20 | if (!*++argv) { /* No args, so (GNU) output current nice value. */ | 20 | if (!*++argv) { /* No args, so (GNU) output current nice value. */ |
21 | printf("%d\n", old_priority); | 21 | printf("%d\n", old_priority); |
22 | fflush_stdout_and_exit(EXIT_SUCCESS); | 22 | fflush_stdout_and_exit(EXIT_SUCCESS); |
23 | } | 23 | } |
24 | 24 | ||
25 | adjustment = 10; /* Set default adjustment. */ | 25 | adjustment = 10; /* Set default adjustment. */ |
26 | 26 | ||
27 | if (argv[0][0] == '-') { | 27 | if (argv[0][0] == '-') { |
28 | if (argv[0][1] == 'n') { /* -n */ | 28 | if (argv[0][1] == 'n') { /* -n */ |
@@ -32,7 +32,7 @@ int nice_main(int argc, char **argv) | |||
32 | } else { /* -NNN (NNN may be negative) == -n NNN */ | 32 | } else { /* -NNN (NNN may be negative) == -n NNN */ |
33 | argv[0] += 1; argv--; argc++; | 33 | argv[0] += 1; argv--; argc++; |
34 | } | 34 | } |
35 | if (argc < 4) { /* Missing priority and/or utility! */ | 35 | if (argc < 4) { /* Missing priority and/or utility! */ |
36 | bb_show_usage(); | 36 | bb_show_usage(); |
37 | } | 37 | } |
38 | adjustment = xatoi_range(argv[1], INT_MIN/2, INT_MAX/2); | 38 | adjustment = xatoi_range(argv[1], INT_MIN/2, INT_MAX/2); |
diff --git a/coreutils/od.c b/coreutils/od.c index dcd693446..e62711671 100644 --- a/coreutils/od.c +++ b/coreutils/od.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Based on code from util-linux v 2.11l | 4 | * Based on code from util-linux v 2.11l |
5 | * | 5 | * |
6 | * Copyright (c) 1990 | 6 | * Copyright (c) 1990 |
7 | * The Regents of the University of California. All rights reserved. | 7 | * The Regents of the University of California. All rights reserved. |
8 | * | 8 | * |
9 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 9 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
10 | * | 10 | * |
@@ -174,7 +174,7 @@ int od_main(int argc, char **argv) | |||
174 | bb_dump_add(dumper, "\" \""); | 174 | bb_dump_add(dumper, "\" \""); |
175 | } | 175 | } |
176 | bb_dump_add(dumper, add_strings[(int)od_o2si[(p - od_opts)]]); | 176 | bb_dump_add(dumper, add_strings[(int)od_o2si[(p - od_opts)]]); |
177 | } else { /* P, p, s, w, or other unhandled */ | 177 | } else { /* P, p, s, w, or other unhandled */ |
178 | bb_show_usage(); | 178 | bb_show_usage(); |
179 | } | 179 | } |
180 | } | 180 | } |
diff --git a/coreutils/sort.c b/coreutils/sort.c index eccc2d437..3562464d1 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c | |||
@@ -52,8 +52,8 @@ enum { | |||
52 | static char key_separator; | 52 | static char key_separator; |
53 | 53 | ||
54 | static struct sort_key { | 54 | static struct sort_key { |
55 | struct sort_key *next_key; /* linked list */ | 55 | struct sort_key *next_key; /* linked list */ |
56 | unsigned range[4]; /* start word, start char, end word, end char */ | 56 | unsigned range[4]; /* start word, start char, end word, end char */ |
57 | unsigned flags; | 57 | unsigned flags; |
58 | } *key_list; | 58 | } *key_list; |
59 | 59 | ||
diff --git a/coreutils/stat.c b/coreutils/stat.c index b4e6f10fd..7351f5956 100644 --- a/coreutils/stat.c +++ b/coreutils/stat.c | |||
@@ -630,10 +630,9 @@ static bool do_stat(const char *filename, const char *format) | |||
630 | # if ENABLE_SELINUX | 630 | # if ENABLE_SELINUX |
631 | printf(" S_Context: %lc\n", *scontext); | 631 | printf(" S_Context: %lc\n", *scontext); |
632 | # endif | 632 | # endif |
633 | printf("Access: %s\n" "Modify: %s\n" "Change: %s\n", | 633 | printf("Access: %s\n", human_time(statbuf.st_atime)); |
634 | human_time(statbuf.st_atime), | 634 | printf("Modify: %s\n", human_time(statbuf.st_mtime)); |
635 | human_time(statbuf.st_mtime), | 635 | printf("Change: %s\n", human_time(statbuf.st_ctime)); |
636 | human_time(statbuf.st_ctime)); | ||
637 | } | 636 | } |
638 | #endif /* FEATURE_STAT_FORMAT */ | 637 | #endif /* FEATURE_STAT_FORMAT */ |
639 | return 1; | 638 | return 1; |
diff --git a/coreutils/test.c b/coreutils/test.c index 1952337b3..3e9ab7c65 100644 --- a/coreutils/test.c +++ b/coreutils/test.c | |||
@@ -49,9 +49,9 @@ | |||
49 | * state. */ | 49 | * state. */ |
50 | 50 | ||
51 | /* test(1) accepts the following grammar: | 51 | /* test(1) accepts the following grammar: |
52 | oexpr ::= aexpr | aexpr "-o" oexpr ; | 52 | oexpr ::= aexpr | aexpr "-o" oexpr ; |
53 | aexpr ::= nexpr | nexpr "-a" aexpr ; | 53 | aexpr ::= nexpr | nexpr "-a" aexpr ; |
54 | nexpr ::= primary | "!" primary | 54 | nexpr ::= primary | "!" primary |
55 | primary ::= unary-operator operand | 55 | primary ::= unary-operator operand |
56 | | operand binary-operator operand | 56 | | operand binary-operator operand |
57 | | operand | 57 | | operand |
@@ -901,7 +901,10 @@ int test_main(int argc, char **argv) | |||
901 | res = !oexpr(check_operator(*args)); | 901 | res = !oexpr(check_operator(*args)); |
902 | 902 | ||
903 | if (*args != NULL && *++args != NULL) { | 903 | if (*args != NULL && *++args != NULL) { |
904 | /* TODO: example when this happens? */ | 904 | /* Examples: |
905 | * test 3 -lt 5 6 | ||
906 | * test -t 1 2 | ||
907 | */ | ||
905 | bb_error_msg("%s: unknown operand", *args); | 908 | bb_error_msg("%s: unknown operand", *args); |
906 | res = 2; | 909 | res = 2; |
907 | } | 910 | } |
diff --git a/coreutils/touch.c b/coreutils/touch.c index afff36b4d..6c2b948e6 100644 --- a/coreutils/touch.c +++ b/coreutils/touch.c | |||
@@ -19,6 +19,35 @@ | |||
19 | 19 | ||
20 | #include "libbb.h" | 20 | #include "libbb.h" |
21 | 21 | ||
22 | //config:config TOUCH | ||
23 | //config: bool "touch" | ||
24 | //config: default y | ||
25 | //config: help | ||
26 | //config: touch is used to create or change the access and/or | ||
27 | //config: modification timestamp of specified files. | ||
28 | |||
29 | //applet:IF_TOUCH(APPLET_NOFORK(touch, touch, _BB_DIR_BIN, _BB_SUID_DROP, touch)) | ||
30 | |||
31 | //kbuild:lib-$(CONFIG_TOUCH) += touch.o | ||
32 | |||
33 | //usage:#define touch_trivial_usage | ||
34 | //usage: "[-c]" IF_DESKTOP(" [-d DATE] [-r FILE]") " FILE [FILE]..." | ||
35 | //usage:#define touch_full_usage "\n\n" | ||
36 | //usage: "Update the last-modified date on the given FILE[s]\n" | ||
37 | //usage: "\nOptions:" | ||
38 | //usage: "\n -c Don't create files" | ||
39 | //usage: IF_DESKTOP( | ||
40 | //usage: "\n -d DT Date/time to use" | ||
41 | //usage: "\n -r FILE Use FILE's date/time" | ||
42 | //usage: ) | ||
43 | //usage: | ||
44 | //usage:#define touch_example_usage | ||
45 | //usage: "$ ls -l /tmp/foo\n" | ||
46 | //usage: "/bin/ls: /tmp/foo: No such file or directory\n" | ||
47 | //usage: "$ touch /tmp/foo\n" | ||
48 | //usage: "$ ls -l /tmp/foo\n" | ||
49 | //usage: "-rw-rw-r-- 1 andersen andersen 0 Apr 15 01:11 /tmp/foo\n" | ||
50 | |||
22 | /* This is a NOFORK applet. Be very careful! */ | 51 | /* This is a NOFORK applet. Be very careful! */ |
23 | 52 | ||
24 | /* coreutils implements: | 53 | /* coreutils implements: |
@@ -91,9 +120,10 @@ int touch_main(int argc UNUSED_PARAM, char **argv) | |||
91 | struct tm tm_time; | 120 | struct tm tm_time; |
92 | time_t t; | 121 | time_t t; |
93 | 122 | ||
94 | //time(&t); | 123 | //memset(&tm_time, 0, sizeof(tm_time)); |
95 | //localtime_r(&t, &tm_time); | 124 | /* Better than memset: makes "HH:MM" dates meaningful */ |
96 | memset(&tm_time, 0, sizeof(tm_time)); | 125 | time(&t); |
126 | localtime_r(&t, &tm_time); | ||
97 | parse_datestr(date_str, &tm_time); | 127 | parse_datestr(date_str, &tm_time); |
98 | 128 | ||
99 | /* Correct any day of week and day of year etc. fields */ | 129 | /* Correct any day of week and day of year etc. fields */ |
diff --git a/coreutils/tr.c b/coreutils/tr.c index d6bc7d20a..21d77ef95 100644 --- a/coreutils/tr.c +++ b/coreutils/tr.c | |||
@@ -203,7 +203,7 @@ static unsigned expand(const char *arg, char **buffer_p) | |||
203 | buffer[pos++] = *arg; /* copy CHAR */ | 203 | buffer[pos++] = *arg; /* copy CHAR */ |
204 | if (!arg[0] || arg[1] != '=' || arg[2] != ']') | 204 | if (!arg[0] || arg[1] != '=' || arg[2] != ']') |
205 | bb_show_usage(); | 205 | bb_show_usage(); |
206 | arg += 3; /* skip CHAR=] */ | 206 | arg += 3; /* skip CHAR=] */ |
207 | continue; | 207 | continue; |
208 | } | 208 | } |
209 | /* The rest of "[xyz..." cases is treated as normal | 209 | /* The rest of "[xyz..." cases is treated as normal |
@@ -258,9 +258,9 @@ int tr_main(int argc UNUSED_PARAM, char **argv) | |||
258 | char *invec = vector + ASCII; | 258 | char *invec = vector + ASCII; |
259 | char *outvec = vector + ASCII * 2; | 259 | char *outvec = vector + ASCII * 2; |
260 | 260 | ||
261 | #define TR_OPT_complement (3 << 0) | 261 | #define TR_OPT_complement (3 << 0) |
262 | #define TR_OPT_delete (1 << 2) | 262 | #define TR_OPT_delete (1 << 2) |
263 | #define TR_OPT_squeeze_reps (1 << 3) | 263 | #define TR_OPT_squeeze_reps (1 << 3) |
264 | 264 | ||
265 | for (i = 0; i < ASCII; i++) { | 265 | for (i = 0; i < ASCII; i++) { |
266 | vector[i] = i; | 266 | vector[i] = i; |
diff --git a/coreutils/wc.c b/coreutils/wc.c index ecadae59b..fe3f274f8 100644 --- a/coreutils/wc.c +++ b/coreutils/wc.c | |||
@@ -153,7 +153,7 @@ int wc_main(int argc UNUSED_PARAM, char **argv) | |||
153 | bb_simple_perror_msg(arg); | 153 | bb_simple_perror_msg(arg); |
154 | status = EXIT_FAILURE; | 154 | status = EXIT_FAILURE; |
155 | } | 155 | } |
156 | goto DO_EOF; /* Treat an EOF as '\r'. */ | 156 | goto DO_EOF; /* Treat an EOF as '\r'. */ |
157 | } | 157 | } |
158 | 158 | ||
159 | /* Cater for -c and -m */ | 159 | /* Cater for -c and -m */ |
@@ -179,7 +179,7 @@ int wc_main(int argc UNUSED_PARAM, char **argv) | |||
179 | */ | 179 | */ |
180 | if (c == '\t') { | 180 | if (c == '\t') { |
181 | linepos = (linepos | 7) + 1; | 181 | linepos = (linepos | 7) + 1; |
182 | } else { /* '\n', '\r', '\f', or '\v' */ | 182 | } else { /* '\n', '\r', '\f', or '\v' */ |
183 | DO_EOF: | 183 | DO_EOF: |
184 | if (linepos > counts[WC_LENGTH]) { | 184 | if (linepos > counts[WC_LENGTH]) { |
185 | counts[WC_LENGTH] = linepos; | 185 | counts[WC_LENGTH] = linepos; |
@@ -230,7 +230,7 @@ int wc_main(int argc UNUSED_PARAM, char **argv) | |||
230 | * effect of trashing the totals array after outputting it, but that's | 230 | * effect of trashing the totals array after outputting it, but that's |
231 | * irrelavent since we no longer need it. */ | 231 | * irrelavent since we no longer need it. */ |
232 | if (num_files > 1) { | 232 | if (num_files > 1) { |
233 | num_files = 0; /* Make sure we don't get here again. */ | 233 | num_files = 0; /* Make sure we don't get here again. */ |
234 | arg = "total"; | 234 | arg = "total"; |
235 | pcounts = totals; | 235 | pcounts = totals; |
236 | --argv; | 236 | --argv; |
diff --git a/docs/keep_data_small.txt b/docs/keep_data_small.txt index 01c0d3c7b..21d732674 100644 --- a/docs/keep_data_small.txt +++ b/docs/keep_data_small.txt | |||
@@ -59,7 +59,7 @@ wait | |||
59 | Example 1 | 59 | Example 1 |
60 | 60 | ||
61 | One example how to reduce global data usage is in | 61 | One example how to reduce global data usage is in |
62 | archival/libunarchive/decompress_unzip.c: | 62 | archival/libarchive/decompress_unzip.c: |
63 | 63 | ||
64 | /* This is somewhat complex-looking arrangement, but it allows | 64 | /* This is somewhat complex-looking arrangement, but it allows |
65 | * to place decompressor state either in bss or in | 65 | * to place decompressor state either in bss or in |
diff --git a/docs/new-applet-HOWTO.txt b/docs/new-applet-HOWTO.txt index 2f237564d..bb29999cf 100644 --- a/docs/new-applet-HOWTO.txt +++ b/docs/new-applet-HOWTO.txt | |||
@@ -19,8 +19,7 @@ such as who you stole the code from and so forth. Also include the mini-GPL | |||
19 | boilerplate. Be sure to name the main function <applet>_main instead of main. | 19 | boilerplate. Be sure to name the main function <applet>_main instead of main. |
20 | And be sure to put it in <applet>.c. Usage does not have to be taken care of by | 20 | And be sure to put it in <applet>.c. Usage does not have to be taken care of by |
21 | your applet. | 21 | your applet. |
22 | Make sure to #include "libbb.h" as the first include file in your applet so | 22 | Make sure to #include "libbb.h" as the first include file in your applet. |
23 | the bb_config.h and appropriate platform specific files are included properly. | ||
24 | 23 | ||
25 | For a new applet mu, here is the code that would go in mu.c: | 24 | For a new applet mu, here is the code that would go in mu.c: |
26 | 25 | ||
@@ -99,14 +98,14 @@ int function(char *a) | |||
99 | ----end example code------ | 98 | ----end example code------ |
100 | 99 | ||
101 | Add <function_name>.o in the right alphabetically sorted place | 100 | Add <function_name>.o in the right alphabetically sorted place |
102 | in libbb/Kbuild. You should look at the conditional part of | 101 | in libbb/Kbuild.src. You should look at the conditional part of |
103 | libbb/Kbuild aswell. | 102 | libbb/Kbuild.src as well. |
104 | 103 | ||
105 | You should also try to find a suitable place in include/libbb.h for | 104 | You should also try to find a suitable place in include/libbb.h for |
106 | the function declaration. If not, add it somewhere anyway, with or without | 105 | the function declaration. If not, add it somewhere anyway, with or without |
107 | ifdefs to include or not. | 106 | ifdefs to include or not. |
108 | 107 | ||
109 | You can look at libbb/Config.in and try to find out if the function is | 108 | You can look at libbb/Config.src and try to find out if the function is |
110 | tunable and add it there if it is. | 109 | tunable and add it there if it is. |
111 | 110 | ||
112 | 111 | ||
@@ -118,11 +117,11 @@ Find the appropriate directory for your new applet. | |||
118 | Make sure you find the appropriate places in the files, the applets are | 117 | Make sure you find the appropriate places in the files, the applets are |
119 | sorted alphabetically. | 118 | sorted alphabetically. |
120 | 119 | ||
121 | Add the applet to Kbuild in the chosen directory: | 120 | Add the applet to Kbuild.src in the chosen directory: |
122 | 121 | ||
123 | lib-$(CONFIG_MU) += mu.o | 122 | lib-$(CONFIG_MU) += mu.o |
124 | 123 | ||
125 | Add the applet to Config.in in the chosen directory: | 124 | Add the applet to Config.src in the chosen directory: |
126 | 125 | ||
127 | config MU | 126 | config MU |
128 | bool "MU" | 127 | bool "MU" |
@@ -134,7 +133,7 @@ config MU | |||
134 | Usage String(s) | 133 | Usage String(s) |
135 | --------------- | 134 | --------------- |
136 | 135 | ||
137 | Next, add usage information for you applet to include/usage.h. | 136 | Next, add usage information for you applet to include/usage.src.h. |
138 | This should look like the following: | 137 | This should look like the following: |
139 | 138 | ||
140 | #define mu_trivial_usage \ | 139 | #define mu_trivial_usage \ |
@@ -149,17 +148,17 @@ This should look like the following: | |||
149 | If your program supports flags, the flags should be mentioned on the first | 148 | If your program supports flags, the flags should be mentioned on the first |
150 | line (-[abcde]) and a detailed description of each flag should go in the | 149 | line (-[abcde]) and a detailed description of each flag should go in the |
151 | mu_full_usage section, one flag per line. (Numerous examples of this | 150 | mu_full_usage section, one flag per line. (Numerous examples of this |
152 | currently exist in usage.h.) | 151 | currently exist in usage.src.h.) |
153 | 152 | ||
154 | 153 | ||
155 | Header Files | 154 | Header Files |
156 | ------------ | 155 | ------------ |
157 | 156 | ||
158 | Next, add an entry to include/applets.h. Be *sure* to keep the list | 157 | Next, add an entry to include/applets.src.h. Be *sure* to keep the list |
159 | in alphabetical order, or else it will break the binary-search lookup | 158 | in alphabetical order, or else it will break the binary-search lookup |
160 | algorithm in busybox.c and the Gods of BusyBox smite you. Yea, verily: | 159 | algorithm in busybox.c and the Gods of BusyBox smite you. Yea, verily: |
161 | 160 | ||
162 | Be sure to read the top of applets.h before adding your applet. | 161 | Be sure to read the top of applets.src.h before adding your applet. |
163 | 162 | ||
164 | /* all programs above here are alphabetically "less than" 'mu' */ | 163 | /* all programs above here are alphabetically "less than" 'mu' */ |
165 | IF_MU(APPLET(mu, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 164 | IF_MU(APPLET(mu, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
diff --git a/e2fsprogs/old_e2fsprogs/e2fsck.h b/e2fsprogs/old_e2fsprogs/e2fsck.h index fdfa2d84a..330209d69 100644 --- a/e2fsprogs/old_e2fsprogs/e2fsck.h +++ b/e2fsprogs/old_e2fsprogs/e2fsck.h | |||
@@ -629,7 +629,7 @@ struct e2fsck_struct { | |||
629 | }; | 629 | }; |
630 | 630 | ||
631 | 631 | ||
632 | #define tid_gt(x, y) ((x - y) > 0) | 632 | #define tid_gt(x, y) ((x - y) > 0) |
633 | 633 | ||
634 | static inline int tid_geq(tid_t x, tid_t y) | 634 | static inline int tid_geq(tid_t x, tid_t y) |
635 | { | 635 | { |
diff --git a/editors/Config.src b/editors/Config.src index fc824ccd5..201ee6eb9 100644 --- a/editors/Config.src +++ b/editors/Config.src | |||
@@ -60,12 +60,6 @@ config ED | |||
60 | Small, simple, evil. Part of SUSv3. If you're not already using | 60 | Small, simple, evil. Part of SUSv3. If you're not already using |
61 | this, you don't need it. | 61 | this, you don't need it. |
62 | 62 | ||
63 | config PATCH | ||
64 | bool "patch" | ||
65 | default y | ||
66 | help | ||
67 | Apply a unified diff formatted patch. | ||
68 | |||
69 | config SED | 63 | config SED |
70 | bool "sed" | 64 | bool "sed" |
71 | default y | 65 | default y |
diff --git a/editors/Kbuild.src b/editors/Kbuild.src index 98128064d..2f23ae12f 100644 --- a/editors/Kbuild.src +++ b/editors/Kbuild.src | |||
@@ -11,6 +11,5 @@ lib-$(CONFIG_AWK) += awk.o | |||
11 | lib-$(CONFIG_CMP) += cmp.o | 11 | lib-$(CONFIG_CMP) += cmp.o |
12 | lib-$(CONFIG_DIFF) += diff.o | 12 | lib-$(CONFIG_DIFF) += diff.o |
13 | lib-$(CONFIG_ED) += ed.o | 13 | lib-$(CONFIG_ED) += ed.o |
14 | lib-$(CONFIG_PATCH) += patch.o | ||
15 | lib-$(CONFIG_SED) += sed.o | 14 | lib-$(CONFIG_SED) += sed.o |
16 | lib-$(CONFIG_VI) += vi.o | 15 | lib-$(CONFIG_VI) += vi.o |
diff --git a/editors/awk.c b/editors/awk.c index 8bc56756c..2eeb9d77a 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -277,10 +277,10 @@ enum { | |||
277 | 277 | ||
278 | /* tokens and their corresponding info values */ | 278 | /* tokens and their corresponding info values */ |
279 | 279 | ||
280 | #define NTC "\377" /* switch to next token class (tc<<1) */ | 280 | #define NTC "\377" /* switch to next token class (tc<<1) */ |
281 | #define NTCC '\377' | 281 | #define NTCC '\377' |
282 | 282 | ||
283 | #define OC_B OC_BUILTIN | 283 | #define OC_B OC_BUILTIN |
284 | 284 | ||
285 | static const char tokenlist[] ALIGN1 = | 285 | static const char tokenlist[] ALIGN1 = |
286 | "\1(" NTC | 286 | "\1(" NTC |
@@ -368,7 +368,7 @@ static const uint32_t tokeninfo[] = { | |||
368 | OC_B|B_ss|P(0x8f), OC_FBLTIN|F_ti, OC_B|B_ti|P(0x0b), OC_B|B_mt|P(0x0b), | 368 | OC_B|B_ss|P(0x8f), OC_FBLTIN|F_ti, OC_B|B_ti|P(0x0b), OC_B|B_mt|P(0x0b), |
369 | OC_B|B_lo|P(0x49), OC_B|B_up|P(0x49), | 369 | OC_B|B_lo|P(0x49), OC_B|B_up|P(0x49), |
370 | OC_GETLINE|SV|P(0), | 370 | OC_GETLINE|SV|P(0), |
371 | 0, 0, | 371 | 0, 0, |
372 | 0, | 372 | 0, |
373 | 0 /* END */ | 373 | 0 /* END */ |
374 | }; | 374 | }; |
@@ -380,7 +380,7 @@ enum { | |||
380 | ORS, RS, RT, FILENAME, | 380 | ORS, RS, RT, FILENAME, |
381 | SUBSEP, F0, ARGIND, ARGC, | 381 | SUBSEP, F0, ARGIND, ARGC, |
382 | ARGV, ERRNO, FNR, NR, | 382 | ARGV, ERRNO, FNR, NR, |
383 | NF, IGNORECASE, ENVIRON, NUM_INTERNAL_VARS | 383 | NF, IGNORECASE, ENVIRON, NUM_INTERNAL_VARS |
384 | }; | 384 | }; |
385 | 385 | ||
386 | static const char vNames[] ALIGN1 = | 386 | static const char vNames[] ALIGN1 = |
@@ -2335,7 +2335,7 @@ static var *evaluate(node *op, var *res) | |||
2335 | #define fnargs (G.evaluate__fnargs) | 2335 | #define fnargs (G.evaluate__fnargs) |
2336 | /* seed is initialized to 1 */ | 2336 | /* seed is initialized to 1 */ |
2337 | #define seed (G.evaluate__seed) | 2337 | #define seed (G.evaluate__seed) |
2338 | #define sreg (G.evaluate__sreg) | 2338 | #define sreg (G.evaluate__sreg) |
2339 | 2339 | ||
2340 | var *v1; | 2340 | var *v1; |
2341 | 2341 | ||
@@ -2611,7 +2611,7 @@ static var *evaluate(node *op, var *res) | |||
2611 | rsm->F = popen(L.s, "r"); | 2611 | rsm->F = popen(L.s, "r"); |
2612 | rsm->is_pipe = TRUE; | 2612 | rsm->is_pipe = TRUE; |
2613 | } else { | 2613 | } else { |
2614 | rsm->F = fopen_for_read(L.s); /* not xfopen! */ | 2614 | rsm->F = fopen_for_read(L.s); /* not xfopen! */ |
2615 | } | 2615 | } |
2616 | } | 2616 | } |
2617 | } else { | 2617 | } else { |
diff --git a/editors/cmp.c b/editors/cmp.c index f495da7d2..f84a56e3e 100644 --- a/editors/cmp.c +++ b/editors/cmp.c | |||
@@ -33,8 +33,6 @@ int cmp_main(int argc UNUSED_PARAM, char **argv) | |||
33 | unsigned opt; | 33 | unsigned opt; |
34 | int retval = 0; | 34 | int retval = 0; |
35 | 35 | ||
36 | xfunc_error_retval = 2; /* 1 is returned if files are different. */ | ||
37 | |||
38 | opt_complementary = "-1" | 36 | opt_complementary = "-1" |
39 | IF_DESKTOP(":?4") | 37 | IF_DESKTOP(":?4") |
40 | IF_NOT_DESKTOP(":?2") | 38 | IF_NOT_DESKTOP(":?2") |
@@ -43,8 +41,6 @@ int cmp_main(int argc UNUSED_PARAM, char **argv) | |||
43 | argv += optind; | 41 | argv += optind; |
44 | 42 | ||
45 | filename1 = *argv; | 43 | filename1 = *argv; |
46 | fp1 = xfopen_stdin(filename1); | ||
47 | |||
48 | if (*++argv) { | 44 | if (*++argv) { |
49 | filename2 = *argv; | 45 | filename2 = *argv; |
50 | if (ENABLE_DESKTOP && *++argv) { | 46 | if (ENABLE_DESKTOP && *++argv) { |
@@ -55,6 +51,10 @@ int cmp_main(int argc UNUSED_PARAM, char **argv) | |||
55 | } | 51 | } |
56 | } | 52 | } |
57 | 53 | ||
54 | xfunc_error_retval = 2; /* missing file results in exitcode 2 */ | ||
55 | if (opt & CMP_OPT_s) | ||
56 | logmode = 0; /* -s suppresses open error messages */ | ||
57 | fp1 = xfopen_stdin(filename1); | ||
58 | fp2 = xfopen_stdin(filename2); | 58 | fp2 = xfopen_stdin(filename2); |
59 | if (fp1 == fp2) { /* Paranoia check... stdin == stdin? */ | 59 | if (fp1 == fp2) { /* Paranoia check... stdin == stdin? */ |
60 | /* Note that we don't bother reading stdin. Neither does gnu wc. | 60 | /* Note that we don't bother reading stdin. Neither does gnu wc. |
@@ -63,6 +63,7 @@ int cmp_main(int argc UNUSED_PARAM, char **argv) | |||
63 | */ | 63 | */ |
64 | return 0; | 64 | return 0; |
65 | } | 65 | } |
66 | logmode = LOGMODE_STDIO; | ||
66 | 67 | ||
67 | if (opt & CMP_OPT_l) | 68 | if (opt & CMP_OPT_l) |
68 | fmt = fmt_l_opt; | 69 | fmt = fmt_l_opt; |
diff --git a/editors/diff.c b/editors/diff.c index d9d709db6..cc7ba472e 100644 --- a/editors/diff.c +++ b/editors/diff.c | |||
@@ -230,7 +230,7 @@ static int search(const int *c, int k, int y, const struct cand *list) | |||
230 | { | 230 | { |
231 | int i, j; | 231 | int i, j; |
232 | 232 | ||
233 | if (list[c[k]].y < y) /* quick look for typical case */ | 233 | if (list[c[k]].y < y) /* quick look for typical case */ |
234 | return k + 1; | 234 | return k + 1; |
235 | 235 | ||
236 | for (i = 0, j = k + 1;;) { | 236 | for (i = 0, j = k + 1;;) { |
diff --git a/editors/patch.c b/editors/patch.c index 33ff8b569..9c6d967b9 100644 --- a/editors/patch.c +++ b/editors/patch.c | |||
@@ -1,8 +1,7 @@ | |||
1 | /* Adapted from toybox's patch. */ | ||
2 | |||
3 | /* vi: set sw=4 ts=4: | 1 | /* vi: set sw=4 ts=4: |
4 | * | 2 | * |
5 | * patch.c - Apply a "universal" diff. | 3 | * Apply a "universal" diff. |
4 | * Adapted from toybox's patch implementation. | ||
6 | * | 5 | * |
7 | * Copyright 2007 Rob Landley <rob@landley.net> | 6 | * Copyright 2007 Rob Landley <rob@landley.net> |
8 | * | 7 | * |
@@ -20,30 +19,45 @@ | |||
20 | * -f force (no questions asked) | 19 | * -f force (no questions asked) |
21 | * -F fuzz (number, default 2) | 20 | * -F fuzz (number, default 2) |
22 | * [file] which file to patch | 21 | * [file] which file to patch |
22 | */ | ||
23 | |||
24 | //applet:IF_PATCH(APPLET(patch, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | ||
25 | |||
26 | //kbuild:lib-$(CONFIG_PATCH) += patch.o | ||
27 | |||
28 | //config:config PATCH | ||
29 | //config: bool "patch" | ||
30 | //config: default y | ||
31 | //config: help | ||
32 | //config: Apply a unified diff formatted patch. | ||
33 | |||
34 | //usage:#define patch_trivial_usage | ||
35 | //usage: "[OPTIONS] [ORIGFILE [PATCHFILE]]" | ||
36 | //usage:#define patch_full_usage "\n\n" | ||
37 | //usage: IF_LONG_OPTS( | ||
38 | //usage: " -p,--strip N Strip N leading components from file names" | ||
39 | //usage: "\n -i,--input DIFF Read DIFF instead of stdin" | ||
40 | //usage: "\n -R,--reverse Reverse patch" | ||
41 | //usage: "\n -N,--forward Ignore already applied patches" | ||
42 | //usage: "\n --dry-run Don't actually change files" | ||
43 | //usage: "\n -E,--remove-empty-files Remove output files if they become empty" | ||
44 | //usage: ) | ||
45 | //usage: IF_NOT_LONG_OPTS( | ||
46 | //usage: " -p N Strip N leading components from file names" | ||
47 | //usage: "\n -i DIFF Read DIFF instead of stdin" | ||
48 | //usage: "\n -R Reverse patch" | ||
49 | //usage: "\n -N Ignore already applied patches" | ||
50 | //usage: "\n -E Remove output files if they become empty" | ||
51 | //usage: ) | ||
52 | //usage: | ||
53 | //usage:#define patch_example_usage | ||
54 | //usage: "$ patch -p1 < example.diff\n" | ||
55 | //usage: "$ patch -p0 -i example.diff" | ||
23 | 56 | ||
24 | USE_PATCH(NEWTOY(patch, USE_TOYBOX_DEBUG("x")"up#i:R", TOYFLAG_USR|TOYFLAG_BIN)) | 57 | #include "libbb.h" |
25 | |||
26 | config PATCH | ||
27 | bool "patch" | ||
28 | default y | ||
29 | help | ||
30 | usage: patch [-i file] [-p depth] [-Ru] | ||
31 | |||
32 | Apply a unified diff to one or more files. | ||
33 | 58 | ||
34 | -i Input file (defaults=stdin) | ||
35 | -p number of '/' to strip from start of file paths (default=all) | ||
36 | -R Reverse patch. | ||
37 | -u Ignored (only handles "unified" diffs) | ||
38 | 59 | ||
39 | This version of patch only handles unified diffs, and only modifies | 60 | // libbb candidate? |
40 | a file when all all hunks to that file apply. Patch prints failed | ||
41 | hunks to stderr, and exits with nonzero status if any hunks fail. | ||
42 | |||
43 | A file compared against /dev/null (or with a date <= the epoch) is | ||
44 | created or deleted if -E or --remove-empty-files set. | ||
45 | */ | ||
46 | #include "libbb.h" | ||
47 | 61 | ||
48 | struct double_list { | 62 | struct double_list { |
49 | struct double_list *next; | 63 | struct double_list *next; |
@@ -51,188 +65,55 @@ struct double_list { | |||
51 | char *data; | 65 | char *data; |
52 | }; | 66 | }; |
53 | 67 | ||
54 | // Return the first item from the list, advancing the list (which must be called | ||
55 | // as &list) | ||
56 | static | ||
57 | void *TOY_llist_pop(void *list) | ||
58 | { | ||
59 | // I'd use a void ** for the argument, and even accept the typecast in all | ||
60 | // callers as documentation you need the &, except the stupid compiler | ||
61 | // would then scream about type-punned pointers. Screw it. | ||
62 | void **llist = (void **)list; | ||
63 | void **next = (void **)*llist; | ||
64 | *llist = *next; | ||
65 | |||
66 | return (void *)next; | ||
67 | } | ||
68 | |||
69 | // Free all the elements of a linked list | 68 | // Free all the elements of a linked list |
70 | // if freeit!=NULL call freeit() on each element before freeing it. | 69 | // Call freeit() on each element before freeing it. |
71 | static | 70 | static |
72 | void TOY_llist_free(void *list, void (*freeit)(void *data)) | 71 | void dlist_free(struct double_list *list, void (*freeit)(void *data)) |
73 | { | 72 | { |
74 | while (list) { | 73 | while (list) { |
75 | void *pop = TOY_llist_pop(&list); | 74 | void *pop = list; |
76 | if (freeit) freeit(pop); | 75 | list = list->next; |
77 | else free(pop); | 76 | freeit(pop); |
78 | 77 | // Bail out also if list is circular. | |
79 | // End doubly linked list too. | 78 | if (list == pop) break; |
80 | if (list==pop) break; | ||
81 | } | 79 | } |
82 | } | 80 | } |
83 | //Override bbox's names | ||
84 | #define llist_pop TOY_llist_pop | ||
85 | #define llist_free TOY_llist_free | ||
86 | 81 | ||
87 | // Add an entry to the end off a doubly linked list | 82 | // Add an entry before "list" element in (circular) doubly linked list |
88 | static | 83 | static |
89 | struct double_list *dlist_add(struct double_list **list, char *data) | 84 | struct double_list *dlist_add(struct double_list **list, char *data) |
90 | { | 85 | { |
91 | struct double_list *line = xmalloc(sizeof(struct double_list)); | 86 | struct double_list *llist; |
87 | struct double_list *line = xmalloc(sizeof(*line)); | ||
92 | 88 | ||
93 | line->data = data; | 89 | line->data = data; |
94 | if (*list) { | 90 | llist = *list; |
95 | line->next = *list; | 91 | if (llist) { |
96 | line->prev = (*list)->prev; | 92 | struct double_list *p; |
97 | (*list)->prev->next = line; | 93 | line->next = llist; |
98 | (*list)->prev = line; | 94 | p = line->prev = llist->prev; |
99 | } else *list = line->next = line->prev = line; | 95 | // (list is circular, we assume p is never NULL) |
96 | p->next = line; | ||
97 | llist->prev = line; | ||
98 | } else | ||
99 | *list = line->next = line->prev = line; | ||
100 | 100 | ||
101 | return line; | 101 | return line; |
102 | } | 102 | } |
103 | 103 | ||
104 | // Ensure entire path exists. | ||
105 | // If mode != -1 set permissions on newly created dirs. | ||
106 | // Requires that path string be writable (for temporary null terminators). | ||
107 | static | ||
108 | void xmkpath(char *path, int mode) | ||
109 | { | ||
110 | char *p, old; | ||
111 | mode_t mask; | ||
112 | int rc; | ||
113 | struct stat st; | ||
114 | |||
115 | for (p = path; ; p++) { | ||
116 | if (!*p || *p == '/') { | ||
117 | old = *p; | ||
118 | *p = rc = 0; | ||
119 | if (stat(path, &st) || !S_ISDIR(st.st_mode)) { | ||
120 | if (mode != -1) { | ||
121 | mask = umask(0); | ||
122 | rc = mkdir(path, mode); | ||
123 | umask(mask); | ||
124 | } else rc = mkdir(path, 0777); | ||
125 | } | ||
126 | *p = old; | ||
127 | if(rc) bb_perror_msg_and_die("mkpath '%s'", path); | ||
128 | } | ||
129 | if (!*p) break; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | // Slow, but small. | ||
134 | static | ||
135 | char *get_rawline(int fd, long *plen, char end) | ||
136 | { | ||
137 | char c, *buf = NULL; | ||
138 | long len = 0; | ||
139 | |||
140 | for (;;) { | ||
141 | if (1>read(fd, &c, 1)) break; | ||
142 | if (!(len & 63)) buf=xrealloc(buf, len+65); | ||
143 | if ((buf[len++]=c) == end) break; | ||
144 | } | ||
145 | if (buf) buf[len]=0; | ||
146 | if (plen) *plen = len; | ||
147 | |||
148 | return buf; | ||
149 | } | ||
150 | |||
151 | static | ||
152 | char *get_line(int fd) | ||
153 | { | ||
154 | long len; | ||
155 | char *buf = get_rawline(fd, &len, '\n'); | ||
156 | |||
157 | if (buf && buf[--len]=='\n') buf[len]=0; | ||
158 | |||
159 | return buf; | ||
160 | } | ||
161 | |||
162 | // Copy the rest of in to out and close both files. | ||
163 | static | ||
164 | void xsendfile(int in, int out) | ||
165 | { | ||
166 | long len; | ||
167 | char buf[4096]; | ||
168 | |||
169 | if (in<0) return; | ||
170 | for (;;) { | ||
171 | len = safe_read(in, buf, 4096); | ||
172 | if (len<1) break; | ||
173 | xwrite(out, buf, len); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | // Copy the rest of the data and replace the original with the copy. | ||
178 | static | ||
179 | void replace_tempfile(int fdin, int fdout, char **tempname) | ||
180 | { | ||
181 | char *temp = xstrdup(*tempname); | ||
182 | |||
183 | temp[strlen(temp)-6]=0; | ||
184 | if (fdin != -1) { | ||
185 | xsendfile(fdin, fdout); | ||
186 | xclose(fdin); | ||
187 | } | ||
188 | xclose(fdout); | ||
189 | rename(*tempname, temp); | ||
190 | free(*tempname); | ||
191 | free(temp); | ||
192 | *tempname = NULL; | ||
193 | } | ||
194 | |||
195 | // Open a temporary file to copy an existing file into. | ||
196 | static | ||
197 | int copy_tempfile(int fdin, char *name, char **tempname) | ||
198 | { | ||
199 | struct stat statbuf; | ||
200 | int fd; | ||
201 | |||
202 | *tempname = xasprintf("%sXXXXXX", name); | ||
203 | fd = xmkstemp(*tempname); | ||
204 | |||
205 | // Set permissions of output file | ||
206 | fstat(fdin, &statbuf); | ||
207 | fchmod(fd, statbuf.st_mode); | ||
208 | |||
209 | return fd; | ||
210 | } | ||
211 | |||
212 | // Abort the copy and delete the temporary file. | ||
213 | static | ||
214 | void delete_tempfile(int fdin, int fdout, char **tempname) | ||
215 | { | ||
216 | close(fdin); | ||
217 | close(fdout); | ||
218 | unlink(*tempname); | ||
219 | free(*tempname); | ||
220 | *tempname = NULL; | ||
221 | } | ||
222 | |||
223 | |||
224 | 104 | ||
225 | struct globals { | 105 | struct globals { |
226 | char *infile; | 106 | char *infile; |
227 | long prefix; | 107 | long prefix; |
228 | 108 | ||
229 | struct double_list *current_hunk; | 109 | struct double_list *current_hunk; |
110 | |||
230 | long oldline, oldlen, newline, newlen; | 111 | long oldline, oldlen, newline, newlen; |
231 | long linenum; | 112 | long linenum; |
232 | int context, state, filein, fileout, filepatch, hunknum; | 113 | int context, state, hunknum; |
114 | int filein, fileout; | ||
233 | char *tempname; | 115 | char *tempname; |
234 | 116 | ||
235 | // was toys.foo: | ||
236 | int exitval; | 117 | int exitval; |
237 | }; | 118 | }; |
238 | #define TT (*ptr_to_globals) | 119 | #define TT (*ptr_to_globals) |
@@ -263,7 +144,7 @@ struct globals { | |||
263 | 144 | ||
264 | static void do_line(void *data) | 145 | static void do_line(void *data) |
265 | { | 146 | { |
266 | struct double_list *dlist = (struct double_list *)data; | 147 | struct double_list *dlist = data; |
267 | 148 | ||
268 | if (TT.state>1 && *dlist->data != TT.state) | 149 | if (TT.state>1 && *dlist->data != TT.state) |
269 | fdprintf(TT.state == 2 ? 2 : TT.fileout, | 150 | fdprintf(TT.state == 2 ? 2 : TT.fileout, |
@@ -272,19 +153,35 @@ static void do_line(void *data) | |||
272 | if (PATCH_DEBUG) fdprintf(2, "DO %d: %s\n", TT.state, dlist->data); | 153 | if (PATCH_DEBUG) fdprintf(2, "DO %d: %s\n", TT.state, dlist->data); |
273 | 154 | ||
274 | free(dlist->data); | 155 | free(dlist->data); |
275 | free(data); | 156 | free(dlist); |
276 | } | 157 | } |
277 | 158 | ||
278 | static void finish_oldfile(void) | 159 | static void finish_oldfile(void) |
279 | { | 160 | { |
280 | if (TT.tempname) replace_tempfile(TT.filein, TT.fileout, &TT.tempname); | 161 | if (TT.tempname) { |
162 | // Copy the rest of the data and replace the original with the copy. | ||
163 | char *temp; | ||
164 | |||
165 | if (TT.filein != -1) { | ||
166 | bb_copyfd_eof(TT.filein, TT.fileout); | ||
167 | xclose(TT.filein); | ||
168 | } | ||
169 | xclose(TT.fileout); | ||
170 | |||
171 | temp = xstrdup(TT.tempname); | ||
172 | temp[strlen(temp) - 6] = '\0'; | ||
173 | rename(TT.tempname, temp); | ||
174 | free(temp); | ||
175 | |||
176 | free(TT.tempname); | ||
177 | TT.tempname = NULL; | ||
178 | } | ||
281 | TT.fileout = TT.filein = -1; | 179 | TT.fileout = TT.filein = -1; |
282 | } | 180 | } |
283 | 181 | ||
284 | static void fail_hunk(void) | 182 | static void fail_hunk(void) |
285 | { | 183 | { |
286 | if (!TT.current_hunk) return; | 184 | if (!TT.current_hunk) return; |
287 | TT.current_hunk->prev->next = 0; | ||
288 | 185 | ||
289 | fdprintf(2, "Hunk %d FAILED %ld/%ld.\n", TT.hunknum, TT.oldline, TT.newline); | 186 | fdprintf(2, "Hunk %d FAILED %ld/%ld.\n", TT.hunknum, TT.oldline, TT.newline); |
290 | TT.exitval = 1; | 187 | TT.exitval = 1; |
@@ -293,9 +190,17 @@ static void fail_hunk(void) | |||
293 | // this file and advance to next file. | 190 | // this file and advance to next file. |
294 | 191 | ||
295 | TT.state = 2; | 192 | TT.state = 2; |
296 | llist_free(TT.current_hunk, do_line); | 193 | TT.current_hunk->prev->next = NULL; |
194 | dlist_free(TT.current_hunk, do_line); | ||
297 | TT.current_hunk = NULL; | 195 | TT.current_hunk = NULL; |
298 | delete_tempfile(TT.filein, TT.fileout, &TT.tempname); | 196 | |
197 | // Abort the copy and delete the temporary file. | ||
198 | close(TT.filein); | ||
199 | close(TT.fileout); | ||
200 | unlink(TT.tempname); | ||
201 | free(TT.tempname); | ||
202 | TT.tempname = NULL; | ||
203 | |||
299 | TT.state = 0; | 204 | TT.state = 0; |
300 | } | 205 | } |
301 | 206 | ||
@@ -333,8 +238,8 @@ static int apply_one_hunk(void) | |||
333 | // complete hunk. | 238 | // complete hunk. |
334 | plist = TT.current_hunk; | 239 | plist = TT.current_hunk; |
335 | buf = NULL; | 240 | buf = NULL; |
336 | if (TT.context) for (;;) { | 241 | if (reverse ? TT.oldlen : TT.newlen) for (;;) { |
337 | char *data = get_line(TT.filein); | 242 | char *data = xmalloc_reads(TT.filein, NULL, NULL); |
338 | 243 | ||
339 | TT.linenum++; | 244 | TT.linenum++; |
340 | 245 | ||
@@ -368,7 +273,9 @@ static int apply_one_hunk(void) | |||
368 | // File ended before we found a place for this hunk. | 273 | // File ended before we found a place for this hunk. |
369 | fail_hunk(); | 274 | fail_hunk(); |
370 | goto done; | 275 | goto done; |
371 | } else if (PATCH_DEBUG) fdprintf(2, "IN: %s\n", data); | 276 | } |
277 | |||
278 | if (PATCH_DEBUG) fdprintf(2, "IN: %s\n", data); | ||
372 | check = dlist_add(&buf, data); | 279 | check = dlist_add(&buf, data); |
373 | 280 | ||
374 | // Compare this line with next expected line of hunk. | 281 | // Compare this line with next expected line of hunk. |
@@ -390,7 +297,8 @@ static int apply_one_hunk(void) | |||
390 | fdprintf(2, "NOT: %s\n", plist->data); | 297 | fdprintf(2, "NOT: %s\n", plist->data); |
391 | 298 | ||
392 | TT.state = 3; | 299 | TT.state = 3; |
393 | check = llist_pop(&buf); | 300 | check = buf; |
301 | buf = buf->next; | ||
394 | check->prev->next = buf; | 302 | check->prev->next = buf; |
395 | buf->prev = check->prev; | 303 | buf->prev = check->prev; |
396 | do_line(check); | 304 | do_line(check); |
@@ -398,8 +306,8 @@ static int apply_one_hunk(void) | |||
398 | 306 | ||
399 | // If we've reached the end of the buffer without confirming a | 307 | // If we've reached the end of the buffer without confirming a |
400 | // match, read more lines. | 308 | // match, read more lines. |
401 | if (check==buf) { | 309 | if (check == buf) { |
402 | buf = 0; | 310 | buf = NULL; |
403 | break; | 311 | break; |
404 | } | 312 | } |
405 | check = buf; | 313 | check = buf; |
@@ -417,13 +325,13 @@ static int apply_one_hunk(void) | |||
417 | out: | 325 | out: |
418 | // We have a match. Emit changed data. | 326 | // We have a match. Emit changed data. |
419 | TT.state = "-+"[reverse ^ dummy_revert]; | 327 | TT.state = "-+"[reverse ^ dummy_revert]; |
420 | llist_free(TT.current_hunk, do_line); | 328 | dlist_free(TT.current_hunk, do_line); |
421 | TT.current_hunk = NULL; | 329 | TT.current_hunk = NULL; |
422 | TT.state = 1; | 330 | TT.state = 1; |
423 | done: | 331 | done: |
424 | if (buf) { | 332 | if (buf) { |
425 | buf->prev->next = NULL; | 333 | buf->prev->next = NULL; |
426 | llist_free(buf, do_line); | 334 | dlist_free(buf, do_line); |
427 | } | 335 | } |
428 | 336 | ||
429 | return TT.state; | 337 | return TT.state; |
@@ -444,6 +352,8 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
444 | int reverse, state = 0; | 352 | int reverse, state = 0; |
445 | char *oldname = NULL, *newname = NULL; | 353 | char *oldname = NULL, *newname = NULL; |
446 | char *opt_p, *opt_i; | 354 | char *opt_p, *opt_i; |
355 | long oldlen = oldlen; /* for compiler */ | ||
356 | long newlen = newlen; /* for compiler */ | ||
447 | 357 | ||
448 | INIT_TT(); | 358 | INIT_TT(); |
449 | 359 | ||
@@ -453,10 +363,10 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
453 | TT.prefix = (opts & FLAG_PATHLEN) ? xatoi(opt_p) : 0; // can be negative! | 363 | TT.prefix = (opts & FLAG_PATHLEN) ? xatoi(opt_p) : 0; // can be negative! |
454 | TT.filein = TT.fileout = -1; | 364 | TT.filein = TT.fileout = -1; |
455 | if (opts & FLAG_INPUT) { | 365 | if (opts & FLAG_INPUT) { |
456 | TT.filepatch = xopen_stdin(opt_i); | 366 | xmove_fd(xopen_stdin(opt_i), STDIN_FILENO); |
457 | } else { | 367 | } else { |
458 | if (argv[0] && argv[1]) { | 368 | if (argv[0] && argv[1]) { |
459 | TT.filepatch = xopen_stdin(argv[1]); | 369 | xmove_fd(xopen_stdin(argv[1]), STDIN_FILENO); |
460 | } | 370 | } |
461 | } | 371 | } |
462 | if (argv[0]) { | 372 | if (argv[0]) { |
@@ -468,7 +378,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
468 | for(;;) { | 378 | for(;;) { |
469 | char *patchline; | 379 | char *patchline; |
470 | 380 | ||
471 | patchline = get_line(TT.filepatch); | 381 | patchline = xmalloc_fgetline(stdin); |
472 | if (!patchline) break; | 382 | if (!patchline) break; |
473 | 383 | ||
474 | // Other versions of patch accept damaged patches, | 384 | // Other versions of patch accept damaged patches, |
@@ -483,8 +393,8 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
483 | if (*patchline==' ' || *patchline=='+' || *patchline=='-') { | 393 | if (*patchline==' ' || *patchline=='+' || *patchline=='-') { |
484 | dlist_add(&TT.current_hunk, patchline); | 394 | dlist_add(&TT.current_hunk, patchline); |
485 | 395 | ||
486 | if (*patchline != '+') TT.oldlen--; | 396 | if (*patchline != '+') oldlen--; |
487 | if (*patchline != '-') TT.newlen--; | 397 | if (*patchline != '-') newlen--; |
488 | 398 | ||
489 | // Context line? | 399 | // Context line? |
490 | if (*patchline==' ' && state==2) TT.context++; | 400 | if (*patchline==' ' && state==2) TT.context++; |
@@ -492,7 +402,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
492 | 402 | ||
493 | // If we've consumed all expected hunk lines, apply the hunk. | 403 | // If we've consumed all expected hunk lines, apply the hunk. |
494 | 404 | ||
495 | if (!TT.oldlen && !TT.newlen) state = apply_one_hunk(); | 405 | if (!oldlen && !newlen) state = apply_one_hunk(); |
496 | continue; | 406 | continue; |
497 | } | 407 | } |
498 | fail_hunk(); | 408 | fail_hunk(); |
@@ -539,11 +449,14 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
539 | 449 | ||
540 | // Read oldline[,oldlen] +newline[,newlen] | 450 | // Read oldline[,oldlen] +newline[,newlen] |
541 | 451 | ||
542 | TT.oldlen = TT.newlen = 1; | 452 | TT.oldlen = oldlen = TT.newlen = newlen = 1; |
543 | TT.oldline = strtol(s, &s, 10); | 453 | TT.oldline = strtol(s, &s, 10); |
544 | if (*s == ',') TT.oldlen=strtol(s+1, &s, 10); | 454 | if (*s == ',') TT.oldlen = oldlen = strtol(s+1, &s, 10); |
545 | TT.newline = strtol(s+2, &s, 10); | 455 | TT.newline = strtol(s+2, &s, 10); |
546 | if (*s == ',') TT.newlen = strtol(s+1, &s, 10); | 456 | if (*s == ',') TT.newlen = newlen = strtol(s+1, &s, 10); |
457 | |||
458 | if (oldlen < 1 && newlen < 1) | ||
459 | bb_error_msg_and_die("Really? %s", patchline); | ||
547 | 460 | ||
548 | TT.context = 0; | 461 | TT.context = 0; |
549 | state = 2; | 462 | state = 2; |
@@ -553,8 +466,8 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
553 | int oldsum, newsum, empty = 0; | 466 | int oldsum, newsum, empty = 0; |
554 | char *name; | 467 | char *name; |
555 | 468 | ||
556 | oldsum = TT.oldline + TT.oldlen; | 469 | oldsum = TT.oldline + oldlen; |
557 | newsum = TT.newline + TT.newlen; | 470 | newsum = TT.newline + newlen; |
558 | 471 | ||
559 | name = reverse ? oldname : newname; | 472 | name = reverse ? oldname : newname; |
560 | 473 | ||
@@ -588,13 +501,15 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
588 | } | 501 | } |
589 | // If we've got a file to open, do so. | 502 | // If we've got a file to open, do so. |
590 | } else if (!(option_mask32 & FLAG_PATHLEN) || i <= TT.prefix) { | 503 | } else if (!(option_mask32 & FLAG_PATHLEN) || i <= TT.prefix) { |
504 | struct stat statbuf; | ||
505 | |||
591 | // If the old file was null, we're creating a new one. | 506 | // If the old file was null, we're creating a new one. |
592 | if (!strcmp(oldname, "/dev/null") || !oldsum) { | 507 | if (!strcmp(oldname, "/dev/null") || !oldsum) { |
593 | printf("creating %s\n", name); | 508 | printf("creating %s\n", name); |
594 | s = strrchr(name, '/'); | 509 | s = strrchr(name, '/'); |
595 | if (s) { | 510 | if (s) { |
596 | *s = 0; | 511 | *s = 0; |
597 | xmkpath(name, -1); | 512 | bb_make_directory(name, -1, FILEUTILS_RECUR); |
598 | *s = '/'; | 513 | *s = '/'; |
599 | } | 514 | } |
600 | TT.filein = xopen(name, O_CREAT|O_EXCL|O_RDWR); | 515 | TT.filein = xopen(name, O_CREAT|O_EXCL|O_RDWR); |
@@ -602,7 +517,13 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
602 | printf("patching file %s\n", name); | 517 | printf("patching file %s\n", name); |
603 | TT.filein = xopen(name, O_RDONLY); | 518 | TT.filein = xopen(name, O_RDONLY); |
604 | } | 519 | } |
605 | TT.fileout = copy_tempfile(TT.filein, name, &TT.tempname); | 520 | |
521 | TT.tempname = xasprintf("%sXXXXXX", name); | ||
522 | TT.fileout = xmkstemp(TT.tempname); | ||
523 | // Set permissions of output file | ||
524 | fstat(TT.filein, &statbuf); | ||
525 | fchmod(TT.fileout, statbuf.st_mode); | ||
526 | |||
606 | TT.linenum = 0; | 527 | TT.linenum = 0; |
607 | TT.hunknum = 0; | 528 | TT.hunknum = 0; |
608 | } | 529 | } |
@@ -620,7 +541,6 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
620 | finish_oldfile(); | 541 | finish_oldfile(); |
621 | 542 | ||
622 | if (ENABLE_FEATURE_CLEAN_UP) { | 543 | if (ENABLE_FEATURE_CLEAN_UP) { |
623 | close(TT.filepatch); | ||
624 | free(oldname); | 544 | free(oldname); |
625 | free(newname); | 545 | free(newname); |
626 | } | 546 | } |
diff --git a/editors/sed.c b/editors/sed.c index 964d0405e..b91acfb7f 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -117,9 +117,9 @@ struct globals { | |||
117 | char *add_cmd_line; | 117 | char *add_cmd_line; |
118 | 118 | ||
119 | struct pipeline { | 119 | struct pipeline { |
120 | char *buf; /* Space to hold string */ | 120 | char *buf; /* Space to hold string */ |
121 | int idx; /* Space used */ | 121 | int idx; /* Space used */ |
122 | int len; /* Space allocated */ | 122 | int len; /* Space allocated */ |
123 | } pipeline; | 123 | } pipeline; |
124 | } FIX_ALIASING; | 124 | } FIX_ALIASING; |
125 | #define G (*(struct globals*)&bb_common_bufsiz1) | 125 | #define G (*(struct globals*)&bb_common_bufsiz1) |
diff --git a/examples/depmod.pl b/examples/depmod.pl index 8c6548d28..f324b121a 100755 --- a/examples/depmod.pl +++ b/examples/depmod.pl | |||
@@ -173,6 +173,9 @@ sub add_mod_deps | |||
173 | 173 | ||
174 | $depth .= " "; | 174 | $depth .= " "; |
175 | warn "${depth}loading deps of module: $this_module\n" if $verbose; | 175 | warn "${depth}loading deps of module: $this_module\n" if $verbose; |
176 | if (length($depth) > 50) { | ||
177 | die "too much recursion (circular dependencies in modules?)"; | ||
178 | } | ||
176 | 179 | ||
177 | foreach my $md (keys %{$mod->{$this_module}}) { | 180 | foreach my $md (keys %{$mod->{$this_module}}) { |
178 | add_mod_deps ($depth, $mod, $mod2, $module, $md); | 181 | add_mod_deps ($depth, $mod, $mod2, $module, $md); |
diff --git a/examples/var_service/README b/examples/var_service/README new file mode 100644 index 000000000..06817c8bc --- /dev/null +++ b/examples/var_service/README | |||
@@ -0,0 +1,59 @@ | |||
1 | In many cases, network configuration makes it necessary to run several daemons: | ||
2 | dhcp, zeroconf, ppp, openvpn and such. They need to be controlled, | ||
3 | and in many cases you also want to babysit them. runsvdir is a good tool for this. | ||
4 | examples/var_service directory provides a few examples. It is meant to be used | ||
5 | this way: copy it somewhere (say, /var/service) and run something like | ||
6 | |||
7 | env - PATH=... <other vars=...> runsvdir /var/service & | ||
8 | |||
9 | from one of system startup scripts. (Google "man runsvdir" and "man runsv" | ||
10 | for more info about these tools). | ||
11 | |||
12 | Some existing examples: | ||
13 | |||
14 | var_service/dhcp_if - | ||
15 | controls a udhcpc instance which provides dhpc-assigned IP | ||
16 | address on interface named "if". Copy/rename this directory as needed to run | ||
17 | udhcpc on other interfaces (var_service/dhcp_if/run script uses _foo suffix | ||
18 | of the parent directory as interface name). When IP address is obtained or lost, | ||
19 | var_service/dhcp_if/dhcp_handler is run. It saves new config data to | ||
20 | /var/run/service/fw/dhcp_if.ipconf and (re)starts /var/service/fw service. | ||
21 | This example can be used as a template for other dynamic network link services | ||
22 | (ppp/vpn/zcip). | ||
23 | |||
24 | var_service/ifplugd_if - | ||
25 | watches link status of interface if. Downs and ups /var/service/dhcp_if | ||
26 | service accordingly. In effect, it allows you to unplug/plug-to-different-network | ||
27 | and have your IP properly re-negotiated at once. | ||
28 | |||
29 | var_service/dhcp_if_pinger - | ||
30 | Uses var_service/dhcp_if's data (/var/service/dhcp_if/dhcp_if.out file) | ||
31 | to determine router IP. Pings it. If ping fails, restarts /var/service/dhcp_if | ||
32 | service. Basically, an example of watchdog service for networks | ||
33 | which are not reliable and need babysitting. | ||
34 | |||
35 | var_service/fw - | ||
36 | A *one-shot* service which reconfigures network based on current known state | ||
37 | of ALL interfaces. Uses conf/*.ipconf (static config) and /var/run/service/fw/*.ipconf | ||
38 | (dynamic config from dhcp/ppp/vpn/etc) to determine what to do. | ||
39 | One-shot-ness of this service means that it shuts itself off after single run. | ||
40 | IOW: it is not a constantly running daemon sort of thing. | ||
41 | It starts, it configures the network, it shuts down, all done | ||
42 | (unlike infamous NetworkManagers which sit in RAM forever, doing hell knows what). | ||
43 | |||
44 | However, any dhcp/ppp/vpn or similar service can restart it anytime | ||
45 | when it senses the change in network configuration. | ||
46 | This even works while fw service runs: if dhcp signals fw to (re)start | ||
47 | while fw runs, fw will not stop after its execution, but will re-execute once, | ||
48 | picking up dhcp's new configuration. | ||
49 | This is achieved very simply by having | ||
50 | # Make ourself one-shot | ||
51 | sv o . | ||
52 | at the very beginning of fw/run script, not at the end. | ||
53 | Therefore, any "sv u /var/run/service/fw" command by any other | ||
54 | script "undoes" o(ne-shot) command if fw still runs, thus | ||
55 | runsv will rerun it; or start it in a normal way if fw is not running. | ||
56 | |||
57 | System administrators are expected to edit fw/run script, since | ||
58 | network configuration needs are likely to be very complex and different | ||
59 | for non-trivial installations. | ||
diff --git a/include/applets.src.h b/include/applets.src.h index 879dbf760..261ef2333 100644 --- a/include/applets.src.h +++ b/include/applets.src.h | |||
@@ -16,6 +16,8 @@ s - suid type: | |||
16 | and is run by non-root (applet_main() will not be called at all) | 16 | and is run by non-root (applet_main() will not be called at all) |
17 | _BB_SUID_DROP: will drop suid prior to applet_main() | 17 | _BB_SUID_DROP: will drop suid prior to applet_main() |
18 | _BB_SUID_MAYBE: neither of the above | 18 | _BB_SUID_MAYBE: neither of the above |
19 | (every instance of _BB_SUID_REQUIRE and _BB_SUID_MAYBE | ||
20 | needs to be justified in comment) | ||
19 | */ | 21 | */ |
20 | 22 | ||
21 | #if defined(PROTOTYPES) | 23 | #if defined(PROTOTYPES) |
@@ -56,6 +58,11 @@ s - suid type: | |||
56 | # define APPLET_NOFORK(name,main,l,s,name2) { #name, #main, l, s, 1, 1 }, | 58 | # define APPLET_NOFORK(name,main,l,s,name2) { #name, #main, l, s, 1, 1 }, |
57 | #endif | 59 | #endif |
58 | 60 | ||
61 | #if ENABLE_INSTALL_NO_USR | ||
62 | # define _BB_DIR_USR_BIN _BB_DIR_BIN | ||
63 | # define _BB_DIR_USR_SBIN _BB_DIR_SBIN | ||
64 | #endif | ||
65 | |||
59 | 66 | ||
60 | INSERT | 67 | INSERT |
61 | IF_TEST(APPLET_NOFORK([, test, _BB_DIR_USR_BIN, _BB_SUID_DROP, test)) | 68 | IF_TEST(APPLET_NOFORK([, test, _BB_DIR_USR_BIN, _BB_SUID_DROP, test)) |
@@ -95,6 +102,7 @@ IF_COMM(APPLET(comm, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | |||
95 | IF_CP(APPLET_NOEXEC(cp, cp, _BB_DIR_BIN, _BB_SUID_DROP, cp)) | 102 | IF_CP(APPLET_NOEXEC(cp, cp, _BB_DIR_BIN, _BB_SUID_DROP, cp)) |
96 | IF_CPIO(APPLET(cpio, _BB_DIR_BIN, _BB_SUID_DROP)) | 103 | IF_CPIO(APPLET(cpio, _BB_DIR_BIN, _BB_SUID_DROP)) |
97 | IF_CROND(APPLET(crond, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 104 | IF_CROND(APPLET(crond, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
105 | /* Needs to be run by root or be suid root - needs to change /var/spool/cron* files: */ | ||
98 | IF_CRONTAB(APPLET(crontab, _BB_DIR_USR_BIN, _BB_SUID_REQUIRE)) | 106 | IF_CRONTAB(APPLET(crontab, _BB_DIR_USR_BIN, _BB_SUID_REQUIRE)) |
99 | IF_CRYPTPW(APPLET(cryptpw, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 107 | IF_CRYPTPW(APPLET(cryptpw, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
100 | IF_CUT(APPLET_NOEXEC(cut, cut, _BB_DIR_USR_BIN, _BB_SUID_DROP, cut)) | 108 | IF_CUT(APPLET_NOEXEC(cut, cut, _BB_DIR_USR_BIN, _BB_SUID_DROP, cut)) |
@@ -110,6 +118,7 @@ IF_DHCPRELAY(APPLET(dhcprelay, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | |||
110 | IF_DIFF(APPLET(diff, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 118 | IF_DIFF(APPLET(diff, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
111 | IF_DIRNAME(APPLET_NOFORK(dirname, dirname, _BB_DIR_USR_BIN, _BB_SUID_DROP, dirname)) | 119 | IF_DIRNAME(APPLET_NOFORK(dirname, dirname, _BB_DIR_USR_BIN, _BB_SUID_DROP, dirname)) |
112 | IF_DMESG(APPLET(dmesg, _BB_DIR_BIN, _BB_SUID_DROP)) | 120 | IF_DMESG(APPLET(dmesg, _BB_DIR_BIN, _BB_SUID_DROP)) |
121 | /* Why _BB_SUID_REQUIRE? */ | ||
113 | IF_DNSD(APPLET(dnsd, _BB_DIR_USR_SBIN, _BB_SUID_REQUIRE)) | 122 | IF_DNSD(APPLET(dnsd, _BB_DIR_USR_SBIN, _BB_SUID_REQUIRE)) |
114 | IF_HOSTNAME(APPLET_ODDNAME(dnsdomainname, hostname, _BB_DIR_BIN, _BB_SUID_DROP, dnsdomainname)) | 123 | IF_HOSTNAME(APPLET_ODDNAME(dnsdomainname, hostname, _BB_DIR_BIN, _BB_SUID_DROP, dnsdomainname)) |
115 | IF_DOS2UNIX(APPLET_NOEXEC(dos2unix, dos2unix, _BB_DIR_USR_BIN, _BB_SUID_DROP, dos2unix)) | 124 | IF_DOS2UNIX(APPLET_NOEXEC(dos2unix, dos2unix, _BB_DIR_USR_BIN, _BB_SUID_DROP, dos2unix)) |
@@ -137,6 +146,7 @@ IF_FDFLUSH(APPLET_ODDNAME(fdflush, freeramdisk, _BB_DIR_BIN, _BB_SUID_DROP, fdfl | |||
137 | IF_FDFORMAT(APPLET(fdformat, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 146 | IF_FDFORMAT(APPLET(fdformat, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
138 | IF_FDISK(APPLET(fdisk, _BB_DIR_SBIN, _BB_SUID_DROP)) | 147 | IF_FDISK(APPLET(fdisk, _BB_DIR_SBIN, _BB_SUID_DROP)) |
139 | IF_FGCONSOLE(APPLET(fgconsole, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 148 | IF_FGCONSOLE(APPLET(fgconsole, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
149 | /* Benefits from suid root: better access to /dev/BLOCKDEVs: */ | ||
140 | IF_FINDFS(APPLET(findfs, _BB_DIR_SBIN, _BB_SUID_MAYBE)) | 150 | IF_FINDFS(APPLET(findfs, _BB_DIR_SBIN, _BB_SUID_MAYBE)) |
141 | IF_FLASH_ERASEALL(APPLET(flash_eraseall, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 151 | IF_FLASH_ERASEALL(APPLET(flash_eraseall, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
142 | IF_FLASH_LOCK(APPLET_ODDNAME(flash_lock, flash_lock_unlock, _BB_DIR_USR_SBIN, _BB_SUID_DROP, flash_lock)) | 152 | IF_FLASH_LOCK(APPLET_ODDNAME(flash_lock, flash_lock_unlock, _BB_DIR_USR_SBIN, _BB_SUID_DROP, flash_lock)) |
@@ -188,7 +198,9 @@ IF_IP(APPLET(ip, _BB_DIR_BIN, _BB_SUID_DROP)) | |||
188 | #endif | 198 | #endif |
189 | IF_IPADDR(APPLET(ipaddr, _BB_DIR_BIN, _BB_SUID_DROP)) | 199 | IF_IPADDR(APPLET(ipaddr, _BB_DIR_BIN, _BB_SUID_DROP)) |
190 | IF_IPCALC(APPLET(ipcalc, _BB_DIR_BIN, _BB_SUID_DROP)) | 200 | IF_IPCALC(APPLET(ipcalc, _BB_DIR_BIN, _BB_SUID_DROP)) |
201 | /* Why _BB_SUID_REQUIRE? On Fedora, it isn't suid root */ | ||
191 | IF_IPCRM(APPLET(ipcrm, _BB_DIR_USR_BIN, _BB_SUID_REQUIRE)) | 202 | IF_IPCRM(APPLET(ipcrm, _BB_DIR_USR_BIN, _BB_SUID_REQUIRE)) |
203 | /* Why _BB_SUID_REQUIRE? On Fedora, it isn't suid root */ | ||
192 | IF_IPCS(APPLET(ipcs, _BB_DIR_USR_BIN, _BB_SUID_REQUIRE)) | 204 | IF_IPCS(APPLET(ipcs, _BB_DIR_USR_BIN, _BB_SUID_REQUIRE)) |
193 | IF_IPLINK(APPLET(iplink, _BB_DIR_BIN, _BB_SUID_DROP)) | 205 | IF_IPLINK(APPLET(iplink, _BB_DIR_BIN, _BB_SUID_DROP)) |
194 | IF_IPROUTE(APPLET(iproute, _BB_DIR_BIN, _BB_SUID_DROP)) | 206 | IF_IPROUTE(APPLET(iproute, _BB_DIR_BIN, _BB_SUID_DROP)) |
@@ -209,6 +221,7 @@ IF_LOAD_POLICY(APPLET(load_policy, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | |||
209 | IF_LOADFONT(APPLET(loadfont, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 221 | IF_LOADFONT(APPLET(loadfont, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
210 | IF_LOADKMAP(APPLET(loadkmap, _BB_DIR_SBIN, _BB_SUID_DROP)) | 222 | IF_LOADKMAP(APPLET(loadkmap, _BB_DIR_SBIN, _BB_SUID_DROP)) |
211 | IF_LOGGER(APPLET(logger, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 223 | IF_LOGGER(APPLET(logger, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
224 | /* Needs to be run by root or be suid root - needs to change uid and gid: */ | ||
212 | IF_LOGIN(APPLET(login, _BB_DIR_BIN, _BB_SUID_REQUIRE)) | 225 | IF_LOGIN(APPLET(login, _BB_DIR_BIN, _BB_SUID_REQUIRE)) |
213 | IF_LOGNAME(APPLET_NOFORK(logname, logname, _BB_DIR_USR_BIN, _BB_SUID_DROP, logname)) | 226 | IF_LOGNAME(APPLET_NOFORK(logname, logname, _BB_DIR_USR_BIN, _BB_SUID_DROP, logname)) |
214 | IF_LOGREAD(APPLET(logread, _BB_DIR_SBIN, _BB_SUID_DROP)) | 227 | IF_LOGREAD(APPLET(logread, _BB_DIR_SBIN, _BB_SUID_DROP)) |
@@ -245,6 +258,10 @@ IF_CRYPTPW(APPLET_ODDNAME(mkpasswd, cryptpw, _BB_DIR_USR_BIN, _BB_SUID_DROP, mkp | |||
245 | IF_MKSWAP(APPLET(mkswap, _BB_DIR_SBIN, _BB_SUID_DROP)) | 258 | IF_MKSWAP(APPLET(mkswap, _BB_DIR_SBIN, _BB_SUID_DROP)) |
246 | IF_MKTEMP(APPLET(mktemp, _BB_DIR_BIN, _BB_SUID_DROP)) | 259 | IF_MKTEMP(APPLET(mktemp, _BB_DIR_BIN, _BB_SUID_DROP)) |
247 | IF_MORE(APPLET(more, _BB_DIR_BIN, _BB_SUID_DROP)) | 260 | IF_MORE(APPLET(more, _BB_DIR_BIN, _BB_SUID_DROP)) |
261 | /* On full-blown systems, requires suid for user mounts. | ||
262 | * But it's not unthinkable to have it available in non-suid flavor on some systems, | ||
263 | * for viewing mount table. | ||
264 | * Therefore we use _BB_SUID_MAYBE instead of _BB_SUID_REQUIRE: */ | ||
248 | IF_MOUNT(APPLET(mount, _BB_DIR_BIN, IF_DESKTOP(_BB_SUID_MAYBE) IF_NOT_DESKTOP(_BB_SUID_DROP))) | 265 | IF_MOUNT(APPLET(mount, _BB_DIR_BIN, IF_DESKTOP(_BB_SUID_MAYBE) IF_NOT_DESKTOP(_BB_SUID_DROP))) |
249 | IF_MOUNTPOINT(APPLET(mountpoint, _BB_DIR_BIN, _BB_SUID_DROP)) | 266 | IF_MOUNTPOINT(APPLET(mountpoint, _BB_DIR_BIN, _BB_SUID_DROP)) |
250 | IF_MT(APPLET(mt, _BB_DIR_BIN, _BB_SUID_DROP)) | 267 | IF_MT(APPLET(mt, _BB_DIR_BIN, _BB_SUID_DROP)) |
@@ -253,19 +270,16 @@ IF_NAMEIF(APPLET(nameif, _BB_DIR_SBIN, _BB_SUID_DROP)) | |||
253 | IF_NC(APPLET(nc, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 270 | IF_NC(APPLET(nc, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
254 | IF_NETSTAT(APPLET(netstat, _BB_DIR_BIN, _BB_SUID_DROP)) | 271 | IF_NETSTAT(APPLET(netstat, _BB_DIR_BIN, _BB_SUID_DROP)) |
255 | IF_NICE(APPLET(nice, _BB_DIR_BIN, _BB_SUID_DROP)) | 272 | IF_NICE(APPLET(nice, _BB_DIR_BIN, _BB_SUID_DROP)) |
256 | IF_NMETER(APPLET(nmeter, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | ||
257 | IF_NOHUP(APPLET(nohup, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 273 | IF_NOHUP(APPLET(nohup, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
258 | IF_NSLOOKUP(APPLET(nslookup, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 274 | IF_NSLOOKUP(APPLET(nslookup, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
259 | IF_NTPD(APPLET(ntpd, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 275 | IF_NTPD(APPLET(ntpd, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
260 | IF_OD(APPLET(od, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 276 | IF_OD(APPLET(od, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
261 | IF_OPENVT(APPLET(openvt, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 277 | IF_OPENVT(APPLET(openvt, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
262 | //IF_PARSE(APPLET(parse, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 278 | //IF_PARSE(APPLET(parse, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
279 | /* Needs to be run by root or be suid root - needs to change /etc/{passwd,shadow}: */ | ||
263 | IF_PASSWD(APPLET(passwd, _BB_DIR_USR_BIN, _BB_SUID_REQUIRE)) | 280 | IF_PASSWD(APPLET(passwd, _BB_DIR_USR_BIN, _BB_SUID_REQUIRE)) |
264 | IF_PATCH(APPLET(patch, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | ||
265 | IF_PGREP(APPLET(pgrep, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 281 | IF_PGREP(APPLET(pgrep, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
266 | IF_PIDOF(APPLET(pidof, _BB_DIR_BIN, _BB_SUID_DROP)) | 282 | IF_PIDOF(APPLET(pidof, _BB_DIR_BIN, _BB_SUID_DROP)) |
267 | IF_PING(APPLET(ping, _BB_DIR_BIN, _BB_SUID_MAYBE)) | ||
268 | IF_PING6(APPLET(ping6, _BB_DIR_BIN, _BB_SUID_MAYBE)) | ||
269 | IF_PIPE_PROGRESS(APPLET(pipe_progress, _BB_DIR_BIN, _BB_SUID_DROP)) | 283 | IF_PIPE_PROGRESS(APPLET(pipe_progress, _BB_DIR_BIN, _BB_SUID_DROP)) |
270 | IF_PIVOT_ROOT(APPLET(pivot_root, _BB_DIR_SBIN, _BB_SUID_DROP)) | 284 | IF_PIVOT_ROOT(APPLET(pivot_root, _BB_DIR_SBIN, _BB_SUID_DROP)) |
271 | IF_PKILL(APPLET_ODDNAME(pkill, pgrep, _BB_DIR_USR_BIN, _BB_SUID_DROP, pkill)) | 285 | IF_PKILL(APPLET_ODDNAME(pkill, pgrep, _BB_DIR_USR_BIN, _BB_SUID_DROP, pkill)) |
@@ -322,7 +336,7 @@ IF_SHA256SUM(APPLET_NOEXEC(sha256sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DR | |||
322 | IF_SHA512SUM(APPLET_NOEXEC(sha512sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, sha512sum)) | 336 | IF_SHA512SUM(APPLET_NOEXEC(sha512sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, sha512sum)) |
323 | IF_SHOWKEY(APPLET(showkey, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 337 | IF_SHOWKEY(APPLET(showkey, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
324 | IF_SLATTACH(APPLET(slattach, _BB_DIR_SBIN, _BB_SUID_DROP)) | 338 | IF_SLATTACH(APPLET(slattach, _BB_DIR_SBIN, _BB_SUID_DROP)) |
325 | /* Do not make this applet NOFORK. It breaks ^C-ing of pauses in shells */ | 339 | /* Do not make this applet NOFORK. It breaks ^C-ing of pauses in shells: */ |
326 | IF_SLEEP(APPLET(sleep, _BB_DIR_BIN, _BB_SUID_DROP)) | 340 | IF_SLEEP(APPLET(sleep, _BB_DIR_BIN, _BB_SUID_DROP)) |
327 | IF_SOFTLIMIT(APPLET_ODDNAME(softlimit, chpst, _BB_DIR_USR_BIN, _BB_SUID_DROP, softlimit)) | 341 | IF_SOFTLIMIT(APPLET_ODDNAME(softlimit, chpst, _BB_DIR_USR_BIN, _BB_SUID_DROP, softlimit)) |
328 | IF_SORT(APPLET_NOEXEC(sort, sort, _BB_DIR_USR_BIN, _BB_SUID_DROP, sort)) | 342 | IF_SORT(APPLET_NOEXEC(sort, sort, _BB_DIR_USR_BIN, _BB_SUID_DROP, sort)) |
@@ -331,6 +345,7 @@ IF_START_STOP_DAEMON(APPLET_ODDNAME(start-stop-daemon, start_stop_daemon, _BB_DI | |||
331 | IF_STAT(APPLET(stat, _BB_DIR_BIN, _BB_SUID_DROP)) | 345 | IF_STAT(APPLET(stat, _BB_DIR_BIN, _BB_SUID_DROP)) |
332 | IF_STRINGS(APPLET(strings, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 346 | IF_STRINGS(APPLET(strings, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
333 | IF_STTY(APPLET(stty, _BB_DIR_BIN, _BB_SUID_DROP)) | 347 | IF_STTY(APPLET(stty, _BB_DIR_BIN, _BB_SUID_DROP)) |
348 | /* Needs to be run by root or be suid root - needs to change uid and gid: */ | ||
334 | IF_SU(APPLET(su, _BB_DIR_BIN, _BB_SUID_REQUIRE)) | 349 | IF_SU(APPLET(su, _BB_DIR_BIN, _BB_SUID_REQUIRE)) |
335 | IF_SULOGIN(APPLET(sulogin, _BB_DIR_SBIN, _BB_SUID_DROP)) | 350 | IF_SULOGIN(APPLET(sulogin, _BB_DIR_SBIN, _BB_SUID_DROP)) |
336 | IF_SUM(APPLET(sum, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 351 | IF_SUM(APPLET(sum, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
@@ -359,8 +374,8 @@ IF_TFTPD(APPLET(tftpd, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | |||
359 | IF_TIME(APPLET(time, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 374 | IF_TIME(APPLET(time, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
360 | IF_TIMEOUT(APPLET(timeout, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 375 | IF_TIMEOUT(APPLET(timeout, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
361 | IF_TOP(APPLET(top, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 376 | IF_TOP(APPLET(top, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
362 | IF_TOUCH(APPLET_NOFORK(touch, touch, _BB_DIR_BIN, _BB_SUID_DROP, touch)) | ||
363 | IF_TR(APPLET(tr, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 377 | IF_TR(APPLET(tr, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
378 | /* Needs socket(AF_INET, SOCK_RAW, IPPROTO_ICMP), therefore _BB_SUID_MAYBE: */ | ||
364 | IF_TRACEROUTE(APPLET(traceroute, _BB_DIR_USR_BIN, _BB_SUID_MAYBE)) | 379 | IF_TRACEROUTE(APPLET(traceroute, _BB_DIR_USR_BIN, _BB_SUID_MAYBE)) |
365 | IF_TRACEROUTE6(APPLET(traceroute6, _BB_DIR_USR_BIN, _BB_SUID_MAYBE)) | 380 | IF_TRACEROUTE6(APPLET(traceroute6, _BB_DIR_USR_BIN, _BB_SUID_MAYBE)) |
366 | IF_TRUE(APPLET_NOFORK(true, true, _BB_DIR_BIN, _BB_SUID_DROP, true)) | 381 | IF_TRUE(APPLET_NOFORK(true, true, _BB_DIR_BIN, _BB_SUID_DROP, true)) |
@@ -387,8 +402,10 @@ IF_UUDECODE(APPLET(uudecode, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | |||
387 | IF_UUENCODE(APPLET(uuencode, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 402 | IF_UUENCODE(APPLET(uuencode, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
388 | IF_VCONFIG(APPLET(vconfig, _BB_DIR_SBIN, _BB_SUID_DROP)) | 403 | IF_VCONFIG(APPLET(vconfig, _BB_DIR_SBIN, _BB_SUID_DROP)) |
389 | IF_VI(APPLET(vi, _BB_DIR_BIN, _BB_SUID_DROP)) | 404 | IF_VI(APPLET(vi, _BB_DIR_BIN, _BB_SUID_DROP)) |
405 | /* Needs to be run by root or be suid root - needs to change uid and gid: */ | ||
390 | IF_VLOCK(APPLET(vlock, _BB_DIR_USR_BIN, _BB_SUID_REQUIRE)) | 406 | IF_VLOCK(APPLET(vlock, _BB_DIR_USR_BIN, _BB_SUID_REQUIRE)) |
391 | IF_VOLNAME(APPLET(volname, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 407 | IF_VOLNAME(APPLET(volname, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
408 | /* Needs to be run by root or be suid root - needs to write to /dev/TTY: */ | ||
392 | IF_WALL(APPLET(wall, _BB_DIR_USR_BIN, _BB_SUID_REQUIRE)) | 409 | IF_WALL(APPLET(wall, _BB_DIR_USR_BIN, _BB_SUID_REQUIRE)) |
393 | IF_WATCH(APPLET(watch, _BB_DIR_BIN, _BB_SUID_DROP)) | 410 | IF_WATCH(APPLET(watch, _BB_DIR_BIN, _BB_SUID_DROP)) |
394 | IF_WATCHDOG(APPLET(watchdog, _BB_DIR_SBIN, _BB_SUID_DROP)) | 411 | IF_WATCHDOG(APPLET(watchdog, _BB_DIR_SBIN, _BB_SUID_DROP)) |
diff --git a/include/unarchive.h b/include/archive.h index b55af6d9d..ba6d323e0 100644 --- a/include/unarchive.h +++ b/include/archive.h | |||
@@ -193,7 +193,9 @@ extern const llist_t *find_list_entry2(const llist_t *list, const char *filename | |||
193 | 193 | ||
194 | /* A bit of bunzip2 internals are exposed for compressed help support: */ | 194 | /* A bit of bunzip2 internals are exposed for compressed help support: */ |
195 | typedef struct bunzip_data bunzip_data; | 195 | typedef struct bunzip_data bunzip_data; |
196 | int start_bunzip(bunzip_data **bdp, int in_fd, const unsigned char *inbuf, int len) FAST_FUNC; | 196 | int start_bunzip(bunzip_data **bdp, int in_fd, const void *inbuf, int len) FAST_FUNC; |
197 | /* NB: read_bunzip returns < 0 on error, or the number of *unfilled* bytes | ||
198 | * in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0: */ | ||
197 | int read_bunzip(bunzip_data *bd, char *outbuf, int len) FAST_FUNC; | 199 | int read_bunzip(bunzip_data *bd, char *outbuf, int len) FAST_FUNC; |
198 | void dealloc_bunzip(bunzip_data *bd) FAST_FUNC; | 200 | void dealloc_bunzip(bunzip_data *bd) FAST_FUNC; |
199 | 201 | ||
diff --git a/include/grp_.h b/include/grp_.h index 7a95f88a6..5c24d558a 100644 --- a/include/grp_.h +++ b/include/grp_.h | |||
@@ -18,7 +18,7 @@ | |||
18 | 02111-1307 USA. | 18 | 02111-1307 USA. |
19 | */ | 19 | */ |
20 | /* | 20 | /* |
21 | * POSIX Standard: 9.2.1 Group Database Access <grp.h> | 21 | * POSIX Standard: 9.2.1 Group Database Access <grp.h> |
22 | */ | 22 | */ |
23 | #ifndef BB_GRP_H | 23 | #ifndef BB_GRP_H |
24 | #define BB_GRP_H 1 | 24 | #define BB_GRP_H 1 |
diff --git a/include/libbb.h b/include/libbb.h index 715f1e102..fdd920f3c 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -1440,6 +1440,7 @@ typedef struct procps_status_t { | |||
1440 | char *argv0; | 1440 | char *argv0; |
1441 | char *exe; | 1441 | char *exe; |
1442 | IF_SELINUX(char *context;) | 1442 | IF_SELINUX(char *context;) |
1443 | IF_FEATURE_SHOW_THREADS(unsigned main_thread_pid;) | ||
1443 | /* Everything below must contain no ptrs to malloc'ed data: | 1444 | /* Everything below must contain no ptrs to malloc'ed data: |
1444 | * it is memset(0) for each process in procps_scan() */ | 1445 | * it is memset(0) for each process in procps_scan() */ |
1445 | unsigned long vsz, rss; /* we round it to kbytes */ | 1446 | unsigned long vsz, rss; /* we round it to kbytes */ |
diff --git a/archival/liblzo_interface.h b/include/liblzo_interface.h index 9a84c0b6b..9a84c0b6b 100644 --- a/archival/liblzo_interface.h +++ b/include/liblzo_interface.h | |||
diff --git a/include/platform.h b/include/platform.h index 04fee8d03..5f49deb41 100644 --- a/include/platform.h +++ b/include/platform.h | |||
@@ -165,7 +165,7 @@ | |||
165 | # include <sex.h> | 165 | # include <sex.h> |
166 | #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ | 166 | #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ |
167 | || defined(__APPLE__) | 167 | || defined(__APPLE__) |
168 | # include <sys/resource.h> /* rlimit */ | 168 | # include <sys/resource.h> /* rlimit */ |
169 | # include <machine/endian.h> | 169 | # include <machine/endian.h> |
170 | # define bswap_64 __bswap64 | 170 | # define bswap_64 __bswap64 |
171 | # define bswap_32 __bswap32 | 171 | # define bswap_32 __bswap32 |
diff --git a/include/pwd_.h b/include/pwd_.h index aa63ac940..e40b71dab 100644 --- a/include/pwd_.h +++ b/include/pwd_.h | |||
@@ -18,7 +18,7 @@ | |||
18 | 02111-1307 USA. */ | 18 | 02111-1307 USA. */ |
19 | 19 | ||
20 | /* | 20 | /* |
21 | * POSIX Standard: 9.2.2 User Database Access <pwd.h> | 21 | * POSIX Standard: 9.2.2 User Database Access <pwd.h> |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #ifndef BB_PWD_H | 24 | #ifndef BB_PWD_H |
diff --git a/include/rtc_.h b/include/rtc_.h index bd322c940..750fc20ec 100644 --- a/include/rtc_.h +++ b/include/rtc_.h | |||
@@ -35,9 +35,9 @@ struct linux_rtc_time { | |||
35 | }; | 35 | }; |
36 | 36 | ||
37 | struct linux_rtc_wkalrm { | 37 | struct linux_rtc_wkalrm { |
38 | unsigned char enabled; /* 0 = alarm disabled, 1 = alarm enabled */ | 38 | unsigned char enabled; /* 0 = alarm disabled, 1 = alarm enabled */ |
39 | unsigned char pending; /* 0 = alarm not pending, 1 = alarm pending */ | 39 | unsigned char pending; /* 0 = alarm not pending, 1 = alarm pending */ |
40 | struct linux_rtc_time time; /* time the alarm is set to */ | 40 | struct linux_rtc_time time; /* time the alarm is set to */ |
41 | }; | 41 | }; |
42 | 42 | ||
43 | /* | 43 | /* |
diff --git a/include/usage.src.h b/include/usage.src.h index 6973c93ef..ea0e6a452 100644 --- a/include/usage.src.h +++ b/include/usage.src.h | |||
@@ -592,35 +592,6 @@ INSERT | |||
592 | "\n -i Prompt before overwrite" \ | 592 | "\n -i Prompt before overwrite" \ |
593 | "\n -l,-s Create (sym)links" \ | 593 | "\n -l,-s Create (sym)links" \ |
594 | 594 | ||
595 | #define cpio_trivial_usage \ | ||
596 | "[-dmvu] [-F FILE]" IF_FEATURE_CPIO_O(" [-H newc]") \ | ||
597 | " [-ti"IF_FEATURE_CPIO_O("o")"]" IF_FEATURE_CPIO_P(" [-p DIR]") | ||
598 | #define cpio_full_usage "\n\n" \ | ||
599 | "Extract or list files from a cpio archive" \ | ||
600 | IF_FEATURE_CPIO_O(", or" \ | ||
601 | "\ncreate an archive" IF_FEATURE_CPIO_P(" (-o) or copy files (-p)") \ | ||
602 | " using file list on stdin" \ | ||
603 | ) \ | ||
604 | "\n" \ | ||
605 | "\nMain operation mode:" \ | ||
606 | "\n -t List" \ | ||
607 | "\n -i Extract" \ | ||
608 | IF_FEATURE_CPIO_O( \ | ||
609 | "\n -o Create (requires -H newc)" \ | ||
610 | ) \ | ||
611 | IF_FEATURE_CPIO_P( \ | ||
612 | "\n -p DIR Copy files to DIR" \ | ||
613 | ) \ | ||
614 | "\nOptions:" \ | ||
615 | "\n -d Make leading directories" \ | ||
616 | "\n -m Preserve mtime" \ | ||
617 | "\n -v Verbose" \ | ||
618 | "\n -u Overwrite" \ | ||
619 | "\n -F FILE Input (-t,-i,-p) or output (-o) file" \ | ||
620 | IF_FEATURE_CPIO_O( \ | ||
621 | "\n -H newc Archive format" \ | ||
622 | ) \ | ||
623 | |||
624 | #define crond_trivial_usage \ | 595 | #define crond_trivial_usage \ |
625 | "-fbS -l N " IF_FEATURE_CROND_D("-d N ") "-L LOGFILE -c DIR" | 596 | "-fbS -l N " IF_FEATURE_CROND_D("-d N ") "-L LOGFILE -c DIR" |
626 | #define crond_full_usage "\n\n" \ | 597 | #define crond_full_usage "\n\n" \ |
@@ -1577,8 +1548,8 @@ INSERT | |||
1577 | "\n -c One-byte character display" \ | 1548 | "\n -c One-byte character display" \ |
1578 | "\n -C Canonical hex+ASCII, 16 bytes per line" \ | 1549 | "\n -C Canonical hex+ASCII, 16 bytes per line" \ |
1579 | "\n -d Two-byte decimal display" \ | 1550 | "\n -d Two-byte decimal display" \ |
1580 | "\n -e FORMAT STRING" \ | 1551 | "\n -e FORMAT_STRING" \ |
1581 | "\n -f FORMAT FILE" \ | 1552 | "\n -f FORMAT_FILE" \ |
1582 | "\n -n LENGTH Interpret only LENGTH bytes of input" \ | 1553 | "\n -n LENGTH Interpret only LENGTH bytes of input" \ |
1583 | "\n -o Two-byte octal display" \ | 1554 | "\n -o Two-byte octal display" \ |
1584 | "\n -s OFFSET Skip OFFSET bytes" \ | 1555 | "\n -s OFFSET Skip OFFSET bytes" \ |
@@ -2044,9 +2015,6 @@ INSERT | |||
2044 | #define linux64_trivial_usage NOUSAGE_STR | 2015 | #define linux64_trivial_usage NOUSAGE_STR |
2045 | #define linux64_full_usage "" | 2016 | #define linux64_full_usage "" |
2046 | 2017 | ||
2047 | #define linuxrc_trivial_usage NOUSAGE_STR | ||
2048 | #define linuxrc_full_usage "" | ||
2049 | |||
2050 | #define setarch_trivial_usage \ | 2018 | #define setarch_trivial_usage \ |
2051 | "personality PROG ARGS" | 2019 | "personality PROG ARGS" |
2052 | #define setarch_full_usage "\n\n" \ | 2020 | #define setarch_full_usage "\n\n" \ |
@@ -2176,67 +2144,6 @@ INSERT | |||
2176 | "\n -h Print banner page too" \ | 2144 | "\n -h Print banner page too" \ |
2177 | "\n -V Verbose" \ | 2145 | "\n -V Verbose" \ |
2178 | 2146 | ||
2179 | #define ls_trivial_usage \ | ||
2180 | "[-1Aa" IF_FEATURE_LS_TIMESTAMPS("c") "Cd" \ | ||
2181 | IF_FEATURE_LS_TIMESTAMPS("e") IF_FEATURE_LS_FILETYPES("F") "iln" \ | ||
2182 | IF_FEATURE_LS_FILETYPES("p") IF_FEATURE_LS_FOLLOWLINKS("L") \ | ||
2183 | IF_FEATURE_LS_RECURSIVE("R") IF_FEATURE_LS_SORTFILES("rS") "s" \ | ||
2184 | IF_FEATURE_AUTOWIDTH("T") IF_FEATURE_LS_TIMESTAMPS("tu") \ | ||
2185 | IF_FEATURE_LS_SORTFILES("v") IF_FEATURE_AUTOWIDTH("w") "x" \ | ||
2186 | IF_FEATURE_LS_SORTFILES("X") IF_FEATURE_HUMAN_READABLE("h") "k" \ | ||
2187 | IF_SELINUX("K") "] [FILE]..." | ||
2188 | #define ls_full_usage "\n\n" \ | ||
2189 | "List directory contents\n" \ | ||
2190 | "\nOptions:" \ | ||
2191 | "\n -1 List in a single column" \ | ||
2192 | "\n -A Don't list . and .." \ | ||
2193 | "\n -a Don't hide entries starting with ." \ | ||
2194 | "\n -C List by columns" \ | ||
2195 | IF_FEATURE_LS_TIMESTAMPS( \ | ||
2196 | "\n -c With -l: sort by ctime") \ | ||
2197 | IF_FEATURE_LS_COLOR( \ | ||
2198 | "\n --color[={always,never,auto}] Control coloring") \ | ||
2199 | "\n -d List directory entries instead of contents" \ | ||
2200 | IF_FEATURE_LS_TIMESTAMPS( \ | ||
2201 | "\n -e List full date and time") \ | ||
2202 | IF_FEATURE_LS_FILETYPES( \ | ||
2203 | "\n -F Append indicator (one of */=@|) to entries") \ | ||
2204 | "\n -i List inode numbers" \ | ||
2205 | "\n -l Long listing format" \ | ||
2206 | "\n -n List numeric UIDs and GIDs instead of names" \ | ||
2207 | IF_FEATURE_LS_FILETYPES( \ | ||
2208 | "\n -p Append indicator (one of /=@|) to entries") \ | ||
2209 | IF_FEATURE_LS_FOLLOWLINKS( \ | ||
2210 | "\n -L List entries pointed to by symlinks") \ | ||
2211 | IF_FEATURE_LS_RECURSIVE( \ | ||
2212 | "\n -R Recurse") \ | ||
2213 | IF_FEATURE_LS_SORTFILES( \ | ||
2214 | "\n -r Sort in reverse order") \ | ||
2215 | IF_FEATURE_LS_SORTFILES( \ | ||
2216 | "\n -S Sort by file size") \ | ||
2217 | "\n -s List the size of each file, in blocks" \ | ||
2218 | IF_FEATURE_AUTOWIDTH( \ | ||
2219 | "\n -T N Assume tabstop every N columns") \ | ||
2220 | IF_FEATURE_LS_TIMESTAMPS( \ | ||
2221 | "\n -t With -l: sort by modification time") \ | ||
2222 | IF_FEATURE_LS_TIMESTAMPS( \ | ||
2223 | "\n -u With -l: sort by access time") \ | ||
2224 | IF_FEATURE_LS_SORTFILES( \ | ||
2225 | "\n -v Sort by version") \ | ||
2226 | IF_FEATURE_AUTOWIDTH( \ | ||
2227 | "\n -w N Assume the terminal is N columns wide") \ | ||
2228 | "\n -x List by lines" \ | ||
2229 | IF_FEATURE_LS_SORTFILES( \ | ||
2230 | "\n -X Sort by extension") \ | ||
2231 | IF_FEATURE_HUMAN_READABLE( \ | ||
2232 | "\n -h List sizes in human readable format (1K 243M 2G)") \ | ||
2233 | IF_SELINUX( \ | ||
2234 | "\n -k List security context") \ | ||
2235 | IF_SELINUX( \ | ||
2236 | "\n -K List security context in long format") \ | ||
2237 | IF_SELINUX( \ | ||
2238 | "\n -Z List security context and permission") \ | ||
2239 | |||
2240 | #define lsattr_trivial_usage \ | 2147 | #define lsattr_trivial_usage \ |
2241 | "[-Radlv] [FILE]..." | 2148 | "[-Radlv] [FILE]..." |
2242 | #define lsattr_full_usage "\n\n" \ | 2149 | #define lsattr_full_usage "\n\n" \ |
@@ -2709,31 +2616,6 @@ INSERT | |||
2709 | " or\n" \ | 2616 | " or\n" \ |
2710 | "$ nameif -c /etc/my_mactab_file\n" \ | 2617 | "$ nameif -c /etc/my_mactab_file\n" \ |
2711 | 2618 | ||
2712 | #define nmeter_trivial_usage \ | ||
2713 | "format_string" | ||
2714 | #define nmeter_full_usage "\n\n" \ | ||
2715 | "Monitor system in real time\n\n" \ | ||
2716 | "Format specifiers:\n" \ | ||
2717 | " %Nc or %[cN] Monitor CPU. N - bar size, default 10\n" \ | ||
2718 | " (displays: S:system U:user N:niced D:iowait I:irq i:softirq)\n" \ | ||
2719 | " %[niface] Monitor network interface 'iface'\n" \ | ||
2720 | " %m Monitor allocated memory\n" \ | ||
2721 | " %[mf] Monitor free memory\n" \ | ||
2722 | " %[mt] Monitor total memory\n" \ | ||
2723 | " %s Monitor allocated swap\n" \ | ||
2724 | " %f Monitor number of used file descriptors\n" \ | ||
2725 | " %Ni Monitor total/specific IRQ rate\n" \ | ||
2726 | " %x Monitor context switch rate\n" \ | ||
2727 | " %p Monitor forks\n" \ | ||
2728 | " %[pn] Monitor # of processes\n" \ | ||
2729 | " %b Monitor block io\n" \ | ||
2730 | " %Nt Show time (with N decimal points)\n" \ | ||
2731 | " %Nd Milliseconds between updates (default:1000)\n" \ | ||
2732 | " %r Print <cr> instead of <lf> at EOL" \ | ||
2733 | |||
2734 | #define nmeter_example_usage \ | ||
2735 | "nmeter '%250d%t %20c int %i bio %b mem %m forks%p'" | ||
2736 | |||
2737 | #define nohup_trivial_usage \ | 2619 | #define nohup_trivial_usage \ |
2738 | "PROG ARGS" | 2620 | "PROG ARGS" |
2739 | #define nohup_full_usage "\n\n" \ | 2621 | #define nohup_full_usage "\n\n" \ |
@@ -2820,29 +2702,6 @@ INSERT | |||
2820 | "\n -m Use MD5 encryption instead of DES" \ | 2702 | "\n -m Use MD5 encryption instead of DES" \ |
2821 | ) | 2703 | ) |
2822 | 2704 | ||
2823 | #define patch_trivial_usage \ | ||
2824 | "[OPTIONS] [ORIGFILE [PATCHFILE]]" | ||
2825 | #define patch_full_usage "\n\n" \ | ||
2826 | IF_LONG_OPTS( \ | ||
2827 | " -p,--strip N Strip N leading components from file names" \ | ||
2828 | "\n -i,--input DIFF Read DIFF instead of stdin" \ | ||
2829 | "\n -R,--reverse Reverse patch" \ | ||
2830 | "\n -N,--forward Ignore already applied patches" \ | ||
2831 | "\n --dry-run Don't actually change files" \ | ||
2832 | "\n -E,--remove-empty-files Remove output files if they become empty" \ | ||
2833 | ) \ | ||
2834 | IF_NOT_LONG_OPTS( \ | ||
2835 | " -p N Strip N leading components from file names" \ | ||
2836 | "\n -i DIFF Read DIFF instead of stdin" \ | ||
2837 | "\n -R Reverse patch" \ | ||
2838 | "\n -N Ignore already applied patches" \ | ||
2839 | "\n -E Remove output files if they become empty" \ | ||
2840 | ) | ||
2841 | |||
2842 | #define patch_example_usage \ | ||
2843 | "$ patch -p1 < example.diff\n" \ | ||
2844 | "$ patch -p0 -i example.diff" | ||
2845 | |||
2846 | #define pgrep_trivial_usage \ | 2705 | #define pgrep_trivial_usage \ |
2847 | "[-flnovx] [-s SID|-P PPID|PATTERN]" | 2706 | "[-flnovx] [-s SID|-P PPID|PATTERN]" |
2848 | #define pgrep_full_usage "\n\n" \ | 2707 | #define pgrep_full_usage "\n\n" \ |
@@ -2885,61 +2744,6 @@ INSERT | |||
2885 | IF_FEATURE_PIDOF_OMIT( \ | 2744 | IF_FEATURE_PIDOF_OMIT( \ |
2886 | "$ pidof /bin/sh -o %PPID\n20351 5950") | 2745 | "$ pidof /bin/sh -o %PPID\n20351 5950") |
2887 | 2746 | ||
2888 | #if !ENABLE_FEATURE_FANCY_PING | ||
2889 | #define ping_trivial_usage \ | ||
2890 | "host" | ||
2891 | #define ping_full_usage "\n\n" \ | ||
2892 | "Send ICMP ECHO_REQUEST packets to network hosts" | ||
2893 | #define ping6_trivial_usage \ | ||
2894 | "host" | ||
2895 | #define ping6_full_usage "\n\n" \ | ||
2896 | "Send ICMP ECHO_REQUEST packets to network hosts" | ||
2897 | #else | ||
2898 | #define ping_trivial_usage \ | ||
2899 | "[OPTIONS] HOST" | ||
2900 | #define ping_full_usage "\n\n" \ | ||
2901 | "Send ICMP ECHO_REQUEST packets to network hosts\n" \ | ||
2902 | "\nOptions:" \ | ||
2903 | "\n -4,-6 Force IP or IPv6 name resolution" \ | ||
2904 | "\n -c CNT Send only CNT pings" \ | ||
2905 | "\n -s SIZE Send SIZE data bytes in packets (default:56)" \ | ||
2906 | "\n -I IFACE/IP Use interface or IP address as source" \ | ||
2907 | "\n -W SEC Seconds to wait for the first response (default:10)" \ | ||
2908 | "\n (after all -c CNT packets are sent)" \ | ||
2909 | "\n -w SEC Seconds until ping exits (default:infinite)" \ | ||
2910 | "\n (can exit earlier with -c CNT)" \ | ||
2911 | "\n -q Quiet, only displays output at start" \ | ||
2912 | "\n and when finished" \ | ||
2913 | |||
2914 | #define ping6_trivial_usage \ | ||
2915 | "[OPTIONS] HOST" | ||
2916 | #define ping6_full_usage "\n\n" \ | ||
2917 | "Send ICMP ECHO_REQUEST packets to network hosts\n" \ | ||
2918 | "\nOptions:" \ | ||
2919 | "\n -c CNT Send only CNT pings" \ | ||
2920 | "\n -s SIZE Send SIZE data bytes in packets (default:56)" \ | ||
2921 | "\n -I IFACE/IP Use interface or IP address as source" \ | ||
2922 | "\n -q Quiet, only displays output at start" \ | ||
2923 | "\n and when finished" \ | ||
2924 | |||
2925 | #endif | ||
2926 | #define ping_example_usage \ | ||
2927 | "$ ping localhost\n" \ | ||
2928 | "PING slag (127.0.0.1): 56 data bytes\n" \ | ||
2929 | "64 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=20.1 ms\n" \ | ||
2930 | "\n" \ | ||
2931 | "--- debian ping statistics ---\n" \ | ||
2932 | "1 packets transmitted, 1 packets received, 0% packet loss\n" \ | ||
2933 | "round-trip min/avg/max = 20.1/20.1/20.1 ms\n" | ||
2934 | #define ping6_example_usage \ | ||
2935 | "$ ping6 ip6-localhost\n" \ | ||
2936 | "PING ip6-localhost (::1): 56 data bytes\n" \ | ||
2937 | "64 bytes from ::1: icmp6_seq=0 ttl=64 time=20.1 ms\n" \ | ||
2938 | "\n" \ | ||
2939 | "--- ip6-localhost ping statistics ---\n" \ | ||
2940 | "1 packets transmitted, 1 packets received, 0% packet loss\n" \ | ||
2941 | "round-trip min/avg/max = 20.1/20.1/20.1 ms\n" | ||
2942 | |||
2943 | #define pipe_progress_trivial_usage NOUSAGE_STR | 2747 | #define pipe_progress_trivial_usage NOUSAGE_STR |
2944 | #define pipe_progress_full_usage "" | 2748 | #define pipe_progress_full_usage "" |
2945 | 2749 | ||
@@ -3378,36 +3182,6 @@ INSERT | |||
3378 | #define selinuxenabled_trivial_usage NOUSAGE_STR | 3182 | #define selinuxenabled_trivial_usage NOUSAGE_STR |
3379 | #define selinuxenabled_full_usage "" | 3183 | #define selinuxenabled_full_usage "" |
3380 | 3184 | ||
3381 | #define sendmail_trivial_usage \ | ||
3382 | "[OPTIONS] [RECIPIENT_EMAIL]..." | ||
3383 | #define sendmail_full_usage "\n\n" \ | ||
3384 | "Read email from stdin and send it\n" \ | ||
3385 | "\nStandard options:" \ | ||
3386 | "\n -t Read additional recipients from message body" \ | ||
3387 | "\n -f sender Sender (required)" \ | ||
3388 | "\n -o options Various options. -oi implied, others are ignored" \ | ||
3389 | "\n -i -oi synonym. implied and ignored" \ | ||
3390 | "\n" \ | ||
3391 | "\nBusybox specific options:" \ | ||
3392 | "\n -w seconds Network timeout" \ | ||
3393 | "\n -H 'PROG ARGS' Run connection helper" \ | ||
3394 | "\n Examples:" \ | ||
3395 | "\n -H 'exec openssl s_client -quiet -tls1 -starttls smtp" \ | ||
3396 | "\n -connect smtp.gmail.com:25' <email.txt" \ | ||
3397 | "\n [4<username_and_passwd.txt | -au<username> -ap<password>]" \ | ||
3398 | "\n -H 'exec openssl s_client -quiet -tls1" \ | ||
3399 | "\n -connect smtp.gmail.com:465' <email.txt" \ | ||
3400 | "\n [4<username_and_passwd.txt | -au<username> -ap<password>]" \ | ||
3401 | "\n -S server[:port] Server" \ | ||
3402 | "\n -au<username> Username for AUTH LOGIN" \ | ||
3403 | "\n -ap<password> Password for AUTH LOGIN" \ | ||
3404 | "\n -am<method> Authentication method. Ignored. LOGIN is implied" \ | ||
3405 | "\n" \ | ||
3406 | "\nOther options are silently ignored; -oi -t is implied" \ | ||
3407 | IF_MAKEMIME( \ | ||
3408 | "\nUse makemime applet to create message with attachments" \ | ||
3409 | ) | ||
3410 | |||
3411 | #define seq_trivial_usage \ | 3185 | #define seq_trivial_usage \ |
3412 | "[-w] [-s SEP] [FIRST [INC]] LAST" | 3186 | "[-w] [-s SEP] [FIRST [INC]] LAST" |
3413 | #define seq_full_usage "\n\n" \ | 3187 | #define seq_full_usage "\n\n" \ |
@@ -3750,15 +3524,6 @@ INSERT | |||
3750 | "\n -g Print in stty-readable form" \ | 3524 | "\n -g Print in stty-readable form" \ |
3751 | "\n [SETTING] See manpage" \ | 3525 | "\n [SETTING] See manpage" \ |
3752 | 3526 | ||
3753 | #define su_trivial_usage \ | ||
3754 | "[OPTIONS] [-] [USERNAME]" | ||
3755 | #define su_full_usage "\n\n" \ | ||
3756 | "Change user id or become root\n" \ | ||
3757 | "\nOptions:" \ | ||
3758 | "\n -p,-m Preserve environment" \ | ||
3759 | "\n -c CMD Command to pass to 'sh -c'" \ | ||
3760 | "\n -s SH Shell to use instead of default shell" \ | ||
3761 | |||
3762 | #define sulogin_trivial_usage \ | 3527 | #define sulogin_trivial_usage \ |
3763 | "[-t N] [TTY]" | 3528 | "[-t N] [TTY]" |
3764 | #define sulogin_full_usage "\n\n" \ | 3529 | #define sulogin_full_usage "\n\n" \ |
@@ -4086,22 +3851,6 @@ INSERT | |||
4086 | "and display a screenful of them." \ | 3851 | "and display a screenful of them." \ |
4087 | //TODO: add options and keyboard commands | 3852 | //TODO: add options and keyboard commands |
4088 | 3853 | ||
4089 | #define touch_trivial_usage \ | ||
4090 | "[-c] [-d DATE] [-r FILE] FILE [FILE]..." | ||
4091 | #define touch_full_usage "\n\n" \ | ||
4092 | "Update the last-modified date on the given FILE[s]\n" \ | ||
4093 | "\nOptions:" \ | ||
4094 | "\n -c Don't create files" \ | ||
4095 | "\n -d DT Date/time to use" \ | ||
4096 | "\n -r FILE Use FILE's date/time" \ | ||
4097 | |||
4098 | #define touch_example_usage \ | ||
4099 | "$ ls -l /tmp/foo\n" \ | ||
4100 | "/bin/ls: /tmp/foo: No such file or directory\n" \ | ||
4101 | "$ touch /tmp/foo\n" \ | ||
4102 | "$ ls -l /tmp/foo\n" \ | ||
4103 | "-rw-rw-r-- 1 andersen andersen 0 Apr 15 01:11 /tmp/foo\n" | ||
4104 | |||
4105 | #define tr_trivial_usage \ | 3854 | #define tr_trivial_usage \ |
4106 | "[-cds] STRING1 [STRING2]" | 3855 | "[-cds] STRING1 [STRING2]" |
4107 | #define tr_full_usage "\n\n" \ | 3856 | #define tr_full_usage "\n\n" \ |
diff --git a/include/volume_id.h b/include/volume_id.h index 77e874d40..4a78cd1e4 100644 --- a/include/volume_id.h +++ b/include/volume_id.h | |||
@@ -28,3 +28,4 @@ void display_uuid_cache(void); | |||
28 | * *fsname is replaced if device with such UUID or LABEL is found | 28 | * *fsname is replaced if device with such UUID or LABEL is found |
29 | */ | 29 | */ |
30 | int resolve_mount_spec(char **fsname); | 30 | int resolve_mount_spec(char **fsname); |
31 | int add_to_uuid_cache(const char *device); | ||
diff --git a/init/bootchartd.c b/init/bootchartd.c index 5a1b3e8e8..ac3f261c8 100644 --- a/init/bootchartd.c +++ b/init/bootchartd.c | |||
@@ -441,8 +441,7 @@ int bootchartd_main(int argc UNUSED_PARAM, char **argv) | |||
441 | pid_t pid = xvfork(); | 441 | pid_t pid = xvfork(); |
442 | if (pid == 0) { /* child */ | 442 | if (pid == 0) { /* child */ |
443 | argv += 2; | 443 | argv += 2; |
444 | execvp(argv[0], argv); | 444 | BB_EXECVP_or_die(argv); |
445 | bb_perror_msg_and_die("can't execute '%s'", argv[0]); | ||
446 | } | 445 | } |
447 | /* parent */ | 446 | /* parent */ |
448 | waitpid(pid, NULL, 0); | 447 | waitpid(pid, NULL, 0); |
diff --git a/init/init.c b/init/init.c index a7bbd5e64..a2cc3b5f5 100644 --- a/init/init.c +++ b/init/init.c | |||
@@ -108,138 +108,6 @@ | |||
108 | //config: Note that on Linux, init attempts to detect serial terminal and | 108 | //config: Note that on Linux, init attempts to detect serial terminal and |
109 | //config: sets TERM to "vt102" if one is found. | 109 | //config: sets TERM to "vt102" if one is found. |
110 | 110 | ||
111 | //usage:#define init_trivial_usage | ||
112 | //usage: "" | ||
113 | //usage:#define init_full_usage "\n\n" | ||
114 | //usage: "Init is the parent of all processes" | ||
115 | //usage: | ||
116 | //usage:#define init_notes_usage | ||
117 | //usage: "This version of init is designed to be run only by the kernel.\n" | ||
118 | //usage: "\n" | ||
119 | //usage: "BusyBox init doesn't support multiple runlevels. The runlevels field of\n" | ||
120 | //usage: "the /etc/inittab file is completely ignored by BusyBox init. If you want\n" | ||
121 | //usage: "runlevels, use sysvinit.\n" | ||
122 | //usage: "\n" | ||
123 | //usage: "BusyBox init works just fine without an inittab. If no inittab is found,\n" | ||
124 | //usage: "it has the following default behavior:\n" | ||
125 | //usage: "\n" | ||
126 | //usage: " ::sysinit:/etc/init.d/rcS\n" | ||
127 | //usage: " ::askfirst:/bin/sh\n" | ||
128 | //usage: " ::ctrlaltdel:/sbin/reboot\n" | ||
129 | //usage: " ::shutdown:/sbin/swapoff -a\n" | ||
130 | //usage: " ::shutdown:/bin/umount -a -r\n" | ||
131 | //usage: " ::restart:/sbin/init\n" | ||
132 | //usage: "\n" | ||
133 | //usage: "if it detects that /dev/console is _not_ a serial console, it will also run:\n" | ||
134 | //usage: "\n" | ||
135 | //usage: " tty2::askfirst:/bin/sh\n" | ||
136 | //usage: " tty3::askfirst:/bin/sh\n" | ||
137 | //usage: " tty4::askfirst:/bin/sh\n" | ||
138 | //usage: "\n" | ||
139 | //usage: "If you choose to use an /etc/inittab file, the inittab entry format is as follows:\n" | ||
140 | //usage: "\n" | ||
141 | //usage: " <id>:<runlevels>:<action>:<process>\n" | ||
142 | //usage: "\n" | ||
143 | //usage: " <id>:\n" | ||
144 | //usage: "\n" | ||
145 | //usage: " WARNING: This field has a non-traditional meaning for BusyBox init!\n" | ||
146 | //usage: " The id field is used by BusyBox init to specify the controlling tty for\n" | ||
147 | //usage: " the specified process to run on. The contents of this field are\n" | ||
148 | //usage: " appended to \"/dev/\" and used as-is. There is no need for this field to\n" | ||
149 | //usage: " be unique, although if it isn't you may have strange results. If this\n" | ||
150 | //usage: " field is left blank, the controlling tty is set to the console. Also\n" | ||
151 | //usage: " note that if BusyBox detects that a serial console is in use, then only\n" | ||
152 | //usage: " entries whose controlling tty is either the serial console or /dev/null\n" | ||
153 | //usage: " will be run. BusyBox init does nothing with utmp. We don't need no\n" | ||
154 | //usage: " stinkin' utmp.\n" | ||
155 | //usage: "\n" | ||
156 | //usage: " <runlevels>:\n" | ||
157 | //usage: "\n" | ||
158 | //usage: " The runlevels field is completely ignored.\n" | ||
159 | //usage: "\n" | ||
160 | //usage: " <action>:\n" | ||
161 | //usage: "\n" | ||
162 | //usage: " Valid actions include: sysinit, respawn, askfirst, wait,\n" | ||
163 | //usage: " once, restart, ctrlaltdel, and shutdown.\n" | ||
164 | //usage: "\n" | ||
165 | //usage: " The available actions can be classified into two groups: actions\n" | ||
166 | //usage: " that are run only once, and actions that are re-run when the specified\n" | ||
167 | //usage: " process exits.\n" | ||
168 | //usage: "\n" | ||
169 | //usage: " Run only-once actions:\n" | ||
170 | //usage: "\n" | ||
171 | //usage: " 'sysinit' is the first item run on boot. init waits until all\n" | ||
172 | //usage: " sysinit actions are completed before continuing. Following the\n" | ||
173 | //usage: " completion of all sysinit actions, all 'wait' actions are run.\n" | ||
174 | //usage: " 'wait' actions, like 'sysinit' actions, cause init to wait until\n" | ||
175 | //usage: " the specified task completes. 'once' actions are asynchronous,\n" | ||
176 | //usage: " therefore, init does not wait for them to complete. 'restart' is\n" | ||
177 | //usage: " the action taken to restart the init process. By default this should\n" | ||
178 | //usage: " simply run /sbin/init, but can be a script which runs pivot_root or it\n" | ||
179 | //usage: " can do all sorts of other interesting things. The 'ctrlaltdel' init\n" | ||
180 | //usage: " actions are run when the system detects that someone on the system\n" | ||
181 | //usage: " console has pressed the CTRL-ALT-DEL key combination. Typically one\n" | ||
182 | //usage: " wants to run 'reboot' at this point to cause the system to reboot.\n" | ||
183 | //usage: " Finally the 'shutdown' action specifies the actions to taken when\n" | ||
184 | //usage: " init is told to reboot. Unmounting filesystems and disabling swap\n" | ||
185 | //usage: " is a very good here.\n" | ||
186 | //usage: "\n" | ||
187 | //usage: " Run repeatedly actions:\n" | ||
188 | //usage: "\n" | ||
189 | //usage: " 'respawn' actions are run after the 'once' actions. When a process\n" | ||
190 | //usage: " started with a 'respawn' action exits, init automatically restarts\n" | ||
191 | //usage: " it. Unlike sysvinit, BusyBox init does not stop processes from\n" | ||
192 | //usage: " respawning out of control. The 'askfirst' actions acts just like\n" | ||
193 | //usage: " respawn, except that before running the specified process it\n" | ||
194 | //usage: " displays the line \"Please press Enter to activate this console.\"\n" | ||
195 | //usage: " and then waits for the user to press enter before starting the\n" | ||
196 | //usage: " specified process.\n" | ||
197 | //usage: "\n" | ||
198 | //usage: " Unrecognized actions (like initdefault) will cause init to emit an\n" | ||
199 | //usage: " error message, and then go along with its business. All actions are\n" | ||
200 | //usage: " run in the order they appear in /etc/inittab.\n" | ||
201 | //usage: "\n" | ||
202 | //usage: " <process>:\n" | ||
203 | //usage: "\n" | ||
204 | //usage: " Specifies the process to be executed and its command line.\n" | ||
205 | //usage: "\n" | ||
206 | //usage: "Example /etc/inittab file:\n" | ||
207 | //usage: "\n" | ||
208 | //usage: " # This is run first except when booting in single-user mode\n" | ||
209 | //usage: " #\n" | ||
210 | //usage: " ::sysinit:/etc/init.d/rcS\n" | ||
211 | //usage: " \n" | ||
212 | //usage: " # /bin/sh invocations on selected ttys\n" | ||
213 | //usage: " #\n" | ||
214 | //usage: " # Start an \"askfirst\" shell on the console (whatever that may be)\n" | ||
215 | //usage: " ::askfirst:-/bin/sh\n" | ||
216 | //usage: " # Start an \"askfirst\" shell on /dev/tty2-4\n" | ||
217 | //usage: " tty2::askfirst:-/bin/sh\n" | ||
218 | //usage: " tty3::askfirst:-/bin/sh\n" | ||
219 | //usage: " tty4::askfirst:-/bin/sh\n" | ||
220 | //usage: " \n" | ||
221 | //usage: " # /sbin/getty invocations for selected ttys\n" | ||
222 | //usage: " #\n" | ||
223 | //usage: " tty4::respawn:/sbin/getty 38400 tty4\n" | ||
224 | //usage: " tty5::respawn:/sbin/getty 38400 tty5\n" | ||
225 | //usage: " \n" | ||
226 | //usage: " \n" | ||
227 | //usage: " # Example of how to put a getty on a serial line (for a terminal)\n" | ||
228 | //usage: " #\n" | ||
229 | //usage: " #::respawn:/sbin/getty -L ttyS0 9600 vt100\n" | ||
230 | //usage: " #::respawn:/sbin/getty -L ttyS1 9600 vt100\n" | ||
231 | //usage: " #\n" | ||
232 | //usage: " # Example how to put a getty on a modem line\n" | ||
233 | //usage: " #::respawn:/sbin/getty 57600 ttyS2\n" | ||
234 | //usage: " \n" | ||
235 | //usage: " # Stuff to do when restarting the init process\n" | ||
236 | //usage: " ::restart:/sbin/init\n" | ||
237 | //usage: " \n" | ||
238 | //usage: " # Stuff to do before rebooting\n" | ||
239 | //usage: " ::ctrlaltdel:/sbin/reboot\n" | ||
240 | //usage: " ::shutdown:/bin/umount -a -r\n" | ||
241 | //usage: " ::shutdown:/sbin/swapoff -a\n" | ||
242 | |||
243 | #include "libbb.h" | 111 | #include "libbb.h" |
244 | #include <syslog.h> | 112 | #include <syslog.h> |
245 | #include <paths.h> | 113 | #include <paths.h> |
@@ -533,20 +401,22 @@ static void init_exec(const char *command) | |||
533 | char buf[COMMAND_SIZE + 6]; /* COMMAND_SIZE+strlen("exec ")+1 */ | 401 | char buf[COMMAND_SIZE + 6]; /* COMMAND_SIZE+strlen("exec ")+1 */ |
534 | int dash = (command[0] == '-' /* maybe? && command[1] == '/' */); | 402 | int dash = (command[0] == '-' /* maybe? && command[1] == '/' */); |
535 | 403 | ||
404 | command += dash; | ||
405 | |||
536 | /* See if any special /bin/sh requiring characters are present */ | 406 | /* See if any special /bin/sh requiring characters are present */ |
537 | if (strpbrk(command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) { | 407 | if (strpbrk(command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) { |
538 | strcpy(buf, "exec "); | 408 | sprintf(buf, "exec %s", command); /* excluding "-" */ |
539 | strcpy(buf + 5, command + dash); /* excluding "-" */ | ||
540 | /* NB: LIBBB_DEFAULT_LOGIN_SHELL define has leading dash */ | 409 | /* NB: LIBBB_DEFAULT_LOGIN_SHELL define has leading dash */ |
541 | cmd[0] = (char*)(LIBBB_DEFAULT_LOGIN_SHELL + !dash); | 410 | cmd[0] = (char*)(LIBBB_DEFAULT_LOGIN_SHELL + !dash); |
542 | cmd[1] = (char*)"-c"; | 411 | cmd[1] = (char*)"-c"; |
543 | cmd[2] = buf; | 412 | cmd[2] = buf; |
544 | cmd[3] = NULL; | 413 | cmd[3] = NULL; |
414 | command = LIBBB_DEFAULT_LOGIN_SHELL + 1; | ||
545 | } else { | 415 | } else { |
546 | /* Convert command (char*) into cmd (char**, one word per string) */ | 416 | /* Convert command (char*) into cmd (char**, one word per string) */ |
547 | char *word, *next; | 417 | char *word, *next; |
548 | int i = 0; | 418 | int i = 0; |
549 | next = strcpy(buf, command); /* including "-" */ | 419 | next = strcpy(buf, command - dash); /* command including "-" */ |
550 | while ((word = strsep(&next, " \t")) != NULL) { | 420 | while ((word = strsep(&next, " \t")) != NULL) { |
551 | if (*word != '\0') { /* not two spaces/tabs together? */ | 421 | if (*word != '\0') { /* not two spaces/tabs together? */ |
552 | cmd[i] = word; | 422 | cmd[i] = word; |
@@ -557,14 +427,14 @@ static void init_exec(const char *command) | |||
557 | } | 427 | } |
558 | /* If we saw leading "-", it is interactive shell. | 428 | /* If we saw leading "-", it is interactive shell. |
559 | * Try harder to give it a controlling tty. | 429 | * Try harder to give it a controlling tty. |
560 | * And skip "-" in actual exec call. */ | 430 | */ |
561 | if (dash) { | 431 | if (ENABLE_FEATURE_INIT_SCTTY && dash) { |
562 | /* _Attempt_ to make stdin a controlling tty. */ | 432 | /* _Attempt_ to make stdin a controlling tty. */ |
563 | if (ENABLE_FEATURE_INIT_SCTTY) | 433 | ioctl(STDIN_FILENO, TIOCSCTTY, 0 /*only try, don't steal*/); |
564 | ioctl(STDIN_FILENO, TIOCSCTTY, 0 /*only try, don't steal*/); | ||
565 | } | 434 | } |
566 | BB_EXECVP(cmd[0] + dash, cmd); | 435 | /* Here command never contains the dash, cmd[0] might */ |
567 | message(L_LOG | L_CONSOLE, "can't run '%s': %s", cmd[0], strerror(errno)); | 436 | BB_EXECVP(command, cmd); |
437 | message(L_LOG | L_CONSOLE, "can't run '%s': %s", command, strerror(errno)); | ||
568 | /* returns if execvp fails */ | 438 | /* returns if execvp fails */ |
569 | } | 439 | } |
570 | 440 | ||
@@ -1095,9 +965,9 @@ int init_main(int argc UNUSED_PARAM, char **argv) | |||
1095 | if (!DEBUG_INIT) { | 965 | if (!DEBUG_INIT) { |
1096 | /* Expect to be invoked as init with PID=1 or be invoked as linuxrc */ | 966 | /* Expect to be invoked as init with PID=1 or be invoked as linuxrc */ |
1097 | if (getpid() != 1 | 967 | if (getpid() != 1 |
1098 | && (!ENABLE_FEATURE_INITRD || !strstr(applet_name, "linuxrc")) | 968 | && (!ENABLE_FEATURE_INITRD || applet_name[0] != 'l') /* not linuxrc? */ |
1099 | ) { | 969 | ) { |
1100 | bb_show_usage(); | 970 | bb_error_msg_and_die("must be run as PID 1"); |
1101 | } | 971 | } |
1102 | #ifdef RB_DISABLE_CAD | 972 | #ifdef RB_DISABLE_CAD |
1103 | /* Turn off rebooting via CTL-ALT-DEL - we get a | 973 | /* Turn off rebooting via CTL-ALT-DEL - we get a |
@@ -1286,3 +1156,138 @@ int init_main(int argc UNUSED_PARAM, char **argv) | |||
1286 | } | 1156 | } |
1287 | } /* while (1) */ | 1157 | } /* while (1) */ |
1288 | } | 1158 | } |
1159 | |||
1160 | //usage:#define linuxrc_trivial_usage NOUSAGE_STR | ||
1161 | //usage:#define linuxrc_full_usage "" | ||
1162 | |||
1163 | //usage:#define init_trivial_usage | ||
1164 | //usage: "" | ||
1165 | //usage:#define init_full_usage "\n\n" | ||
1166 | //usage: "Init is the parent of all processes" | ||
1167 | //usage: | ||
1168 | //usage:#define init_notes_usage | ||
1169 | //usage: "This version of init is designed to be run only by the kernel.\n" | ||
1170 | //usage: "\n" | ||
1171 | //usage: "BusyBox init doesn't support multiple runlevels. The runlevels field of\n" | ||
1172 | //usage: "the /etc/inittab file is completely ignored by BusyBox init. If you want\n" | ||
1173 | //usage: "runlevels, use sysvinit.\n" | ||
1174 | //usage: "\n" | ||
1175 | //usage: "BusyBox init works just fine without an inittab. If no inittab is found,\n" | ||
1176 | //usage: "it has the following default behavior:\n" | ||
1177 | //usage: "\n" | ||
1178 | //usage: " ::sysinit:/etc/init.d/rcS\n" | ||
1179 | //usage: " ::askfirst:/bin/sh\n" | ||
1180 | //usage: " ::ctrlaltdel:/sbin/reboot\n" | ||
1181 | //usage: " ::shutdown:/sbin/swapoff -a\n" | ||
1182 | //usage: " ::shutdown:/bin/umount -a -r\n" | ||
1183 | //usage: " ::restart:/sbin/init\n" | ||
1184 | //usage: "\n" | ||
1185 | //usage: "if it detects that /dev/console is _not_ a serial console, it will also run:\n" | ||
1186 | //usage: "\n" | ||
1187 | //usage: " tty2::askfirst:/bin/sh\n" | ||
1188 | //usage: " tty3::askfirst:/bin/sh\n" | ||
1189 | //usage: " tty4::askfirst:/bin/sh\n" | ||
1190 | //usage: "\n" | ||
1191 | //usage: "If you choose to use an /etc/inittab file, the inittab entry format is as follows:\n" | ||
1192 | //usage: "\n" | ||
1193 | //usage: " <id>:<runlevels>:<action>:<process>\n" | ||
1194 | //usage: "\n" | ||
1195 | //usage: " <id>:\n" | ||
1196 | //usage: "\n" | ||
1197 | //usage: " WARNING: This field has a non-traditional meaning for BusyBox init!\n" | ||
1198 | //usage: " The id field is used by BusyBox init to specify the controlling tty for\n" | ||
1199 | //usage: " the specified process to run on. The contents of this field are\n" | ||
1200 | //usage: " appended to \"/dev/\" and used as-is. There is no need for this field to\n" | ||
1201 | //usage: " be unique, although if it isn't you may have strange results. If this\n" | ||
1202 | //usage: " field is left blank, the controlling tty is set to the console. Also\n" | ||
1203 | //usage: " note that if BusyBox detects that a serial console is in use, then only\n" | ||
1204 | //usage: " entries whose controlling tty is either the serial console or /dev/null\n" | ||
1205 | //usage: " will be run. BusyBox init does nothing with utmp. We don't need no\n" | ||
1206 | //usage: " stinkin' utmp.\n" | ||
1207 | //usage: "\n" | ||
1208 | //usage: " <runlevels>:\n" | ||
1209 | //usage: "\n" | ||
1210 | //usage: " The runlevels field is completely ignored.\n" | ||
1211 | //usage: "\n" | ||
1212 | //usage: " <action>:\n" | ||
1213 | //usage: "\n" | ||
1214 | //usage: " Valid actions include: sysinit, respawn, askfirst, wait,\n" | ||
1215 | //usage: " once, restart, ctrlaltdel, and shutdown.\n" | ||
1216 | //usage: "\n" | ||
1217 | //usage: " The available actions can be classified into two groups: actions\n" | ||
1218 | //usage: " that are run only once, and actions that are re-run when the specified\n" | ||
1219 | //usage: " process exits.\n" | ||
1220 | //usage: "\n" | ||
1221 | //usage: " Run only-once actions:\n" | ||
1222 | //usage: "\n" | ||
1223 | //usage: " 'sysinit' is the first item run on boot. init waits until all\n" | ||
1224 | //usage: " sysinit actions are completed before continuing. Following the\n" | ||
1225 | //usage: " completion of all sysinit actions, all 'wait' actions are run.\n" | ||
1226 | //usage: " 'wait' actions, like 'sysinit' actions, cause init to wait until\n" | ||
1227 | //usage: " the specified task completes. 'once' actions are asynchronous,\n" | ||
1228 | //usage: " therefore, init does not wait for them to complete. 'restart' is\n" | ||
1229 | //usage: " the action taken to restart the init process. By default this should\n" | ||
1230 | //usage: " simply run /sbin/init, but can be a script which runs pivot_root or it\n" | ||
1231 | //usage: " can do all sorts of other interesting things. The 'ctrlaltdel' init\n" | ||
1232 | //usage: " actions are run when the system detects that someone on the system\n" | ||
1233 | //usage: " console has pressed the CTRL-ALT-DEL key combination. Typically one\n" | ||
1234 | //usage: " wants to run 'reboot' at this point to cause the system to reboot.\n" | ||
1235 | //usage: " Finally the 'shutdown' action specifies the actions to taken when\n" | ||
1236 | //usage: " init is told to reboot. Unmounting filesystems and disabling swap\n" | ||
1237 | //usage: " is a very good here.\n" | ||
1238 | //usage: "\n" | ||
1239 | //usage: " Run repeatedly actions:\n" | ||
1240 | //usage: "\n" | ||
1241 | //usage: " 'respawn' actions are run after the 'once' actions. When a process\n" | ||
1242 | //usage: " started with a 'respawn' action exits, init automatically restarts\n" | ||
1243 | //usage: " it. Unlike sysvinit, BusyBox init does not stop processes from\n" | ||
1244 | //usage: " respawning out of control. The 'askfirst' actions acts just like\n" | ||
1245 | //usage: " respawn, except that before running the specified process it\n" | ||
1246 | //usage: " displays the line \"Please press Enter to activate this console.\"\n" | ||
1247 | //usage: " and then waits for the user to press enter before starting the\n" | ||
1248 | //usage: " specified process.\n" | ||
1249 | //usage: "\n" | ||
1250 | //usage: " Unrecognized actions (like initdefault) will cause init to emit an\n" | ||
1251 | //usage: " error message, and then go along with its business. All actions are\n" | ||
1252 | //usage: " run in the order they appear in /etc/inittab.\n" | ||
1253 | //usage: "\n" | ||
1254 | //usage: " <process>:\n" | ||
1255 | //usage: "\n" | ||
1256 | //usage: " Specifies the process to be executed and its command line.\n" | ||
1257 | //usage: "\n" | ||
1258 | //usage: "Example /etc/inittab file:\n" | ||
1259 | //usage: "\n" | ||
1260 | //usage: " # This is run first except when booting in single-user mode\n" | ||
1261 | //usage: " #\n" | ||
1262 | //usage: " ::sysinit:/etc/init.d/rcS\n" | ||
1263 | //usage: " \n" | ||
1264 | //usage: " # /bin/sh invocations on selected ttys\n" | ||
1265 | //usage: " #\n" | ||
1266 | //usage: " # Start an \"askfirst\" shell on the console (whatever that may be)\n" | ||
1267 | //usage: " ::askfirst:-/bin/sh\n" | ||
1268 | //usage: " # Start an \"askfirst\" shell on /dev/tty2-4\n" | ||
1269 | //usage: " tty2::askfirst:-/bin/sh\n" | ||
1270 | //usage: " tty3::askfirst:-/bin/sh\n" | ||
1271 | //usage: " tty4::askfirst:-/bin/sh\n" | ||
1272 | //usage: " \n" | ||
1273 | //usage: " # /sbin/getty invocations for selected ttys\n" | ||
1274 | //usage: " #\n" | ||
1275 | //usage: " tty4::respawn:/sbin/getty 38400 tty4\n" | ||
1276 | //usage: " tty5::respawn:/sbin/getty 38400 tty5\n" | ||
1277 | //usage: " \n" | ||
1278 | //usage: " \n" | ||
1279 | //usage: " # Example of how to put a getty on a serial line (for a terminal)\n" | ||
1280 | //usage: " #\n" | ||
1281 | //usage: " #::respawn:/sbin/getty -L ttyS0 9600 vt100\n" | ||
1282 | //usage: " #::respawn:/sbin/getty -L ttyS1 9600 vt100\n" | ||
1283 | //usage: " #\n" | ||
1284 | //usage: " # Example how to put a getty on a modem line\n" | ||
1285 | //usage: " #::respawn:/sbin/getty 57600 ttyS2\n" | ||
1286 | //usage: " \n" | ||
1287 | //usage: " # Stuff to do when restarting the init process\n" | ||
1288 | //usage: " ::restart:/sbin/init\n" | ||
1289 | //usage: " \n" | ||
1290 | //usage: " # Stuff to do before rebooting\n" | ||
1291 | //usage: " ::ctrlaltdel:/sbin/reboot\n" | ||
1292 | //usage: " ::shutdown:/bin/umount -a -r\n" | ||
1293 | //usage: " ::shutdown:/sbin/swapoff -a\n" | ||
diff --git a/libbb/Config.src b/libbb/Config.src index f6c7a11ea..85892d3fe 100644 --- a/libbb/Config.src +++ b/libbb/Config.src | |||
@@ -135,7 +135,7 @@ config FEATURE_NON_POSIX_CP | |||
135 | and create a regular file. This does not conform to POSIX, | 135 | and create a regular file. This does not conform to POSIX, |
136 | but prevents a symlink attack. | 136 | but prevents a symlink attack. |
137 | Similarly, "cp file device" will not send file's data | 137 | Similarly, "cp file device" will not send file's data |
138 | to the device. | 138 | to the device. (To do that, use "cat file >device") |
139 | 139 | ||
140 | config FEATURE_VERBOSE_CP_MESSAGE | 140 | config FEATURE_VERBOSE_CP_MESSAGE |
141 | bool "Give more precise messages when copy fails (cp, mv etc)" | 141 | bool "Give more precise messages when copy fails (cp, mv etc)" |
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index e3866e456..b88fa8fe7 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src | |||
@@ -159,6 +159,7 @@ lib-$(CONFIG_RTCWAKE) += rtc.o | |||
159 | 159 | ||
160 | lib-$(CONFIG_IOSTAT) += get_cpu_count.o | 160 | lib-$(CONFIG_IOSTAT) += get_cpu_count.o |
161 | lib-$(CONFIG_MPSTAT) += get_cpu_count.o | 161 | lib-$(CONFIG_MPSTAT) += get_cpu_count.o |
162 | lib-$(CONFIG_POWERTOP) += get_cpu_count.o | ||
162 | 163 | ||
163 | # We shouldn't build xregcomp.c if we don't need it - this ensures we don't | 164 | # We shouldn't build xregcomp.c if we don't need it - this ensures we don't |
164 | # require regex.h to be in the include dir even if we don't need it thereby | 165 | # require regex.h to be in the include dir even if we don't need it thereby |
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 3b691f945..b1c772cf3 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -28,7 +28,11 @@ | |||
28 | */ | 28 | */ |
29 | #include "busybox.h" | 29 | #include "busybox.h" |
30 | #include <assert.h> | 30 | #include <assert.h> |
31 | #include <malloc.h> | 31 | #if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ |
32 | || defined(__APPLE__) \ | ||
33 | ) | ||
34 | # include <malloc.h> /* for mallopt */ | ||
35 | #endif | ||
32 | /* Try to pull in PAGE_SIZE */ | 36 | /* Try to pull in PAGE_SIZE */ |
33 | #ifdef __linux__ | 37 | #ifdef __linux__ |
34 | # include <sys/user.h> | 38 | # include <sys/user.h> |
@@ -66,7 +70,7 @@ static const char usage_messages[] ALIGN1 = UNPACKED_USAGE; | |||
66 | #if ENABLE_FEATURE_COMPRESS_USAGE | 70 | #if ENABLE_FEATURE_COMPRESS_USAGE |
67 | 71 | ||
68 | static const char packed_usage[] ALIGN1 = { PACKED_USAGE }; | 72 | static const char packed_usage[] ALIGN1 = { PACKED_USAGE }; |
69 | # include "unarchive.h" | 73 | # include "archive.h" |
70 | static const char *unpack_usage_messages(void) | 74 | static const char *unpack_usage_messages(void) |
71 | { | 75 | { |
72 | char *outbuf = NULL; | 76 | char *outbuf = NULL; |
@@ -75,7 +79,7 @@ static const char *unpack_usage_messages(void) | |||
75 | 79 | ||
76 | i = start_bunzip(&bd, | 80 | i = start_bunzip(&bd, |
77 | /* src_fd: */ -1, | 81 | /* src_fd: */ -1, |
78 | /* inbuf: */ (void *)packed_usage, | 82 | /* inbuf: */ packed_usage, |
79 | /* len: */ sizeof(packed_usage)); | 83 | /* len: */ sizeof(packed_usage)); |
80 | /* read_bunzip can longjmp to start_bunzip, and ultimately | 84 | /* read_bunzip can longjmp to start_bunzip, and ultimately |
81 | * end up here with i != 0 on read data errors! Not trivial */ | 85 | * end up here with i != 0 on read data errors! Not trivial */ |
@@ -103,14 +107,13 @@ void FAST_FUNC bb_show_usage(void) | |||
103 | if (ENABLE_SHOW_USAGE) { | 107 | if (ENABLE_SHOW_USAGE) { |
104 | #ifdef SINGLE_APPLET_STR | 108 | #ifdef SINGLE_APPLET_STR |
105 | /* Imagine that this applet is "true". Dont suck in printf! */ | 109 | /* Imagine that this applet is "true". Dont suck in printf! */ |
106 | const char *p; | 110 | const char *usage_string = unpack_usage_messages(); |
107 | const char *usage_string = p = unpack_usage_messages(); | ||
108 | 111 | ||
109 | if (*p == '\b') { | 112 | if (*usage_string == '\b') { |
110 | full_write2_str("No help available.\n\n"); | 113 | full_write2_str("No help available.\n\n"); |
111 | } else { | 114 | } else { |
112 | full_write2_str("Usage: "SINGLE_APPLET_STR" "); | 115 | full_write2_str("Usage: "SINGLE_APPLET_STR" "); |
113 | full_write2_str(p); | 116 | full_write2_str(usage_string); |
114 | full_write2_str("\n\n"); | 117 | full_write2_str("\n\n"); |
115 | } | 118 | } |
116 | if (ENABLE_FEATURE_CLEAN_UP) | 119 | if (ENABLE_FEATURE_CLEAN_UP) |
@@ -228,7 +231,7 @@ bool re_execed; | |||
228 | 231 | ||
229 | IF_FEATURE_SUID(static uid_t ruid;) /* real uid */ | 232 | IF_FEATURE_SUID(static uid_t ruid;) /* real uid */ |
230 | 233 | ||
231 | #if ENABLE_FEATURE_SUID_CONFIG | 234 | # if ENABLE_FEATURE_SUID_CONFIG |
232 | 235 | ||
233 | /* applets[] is const, so we have to define this "override" structure */ | 236 | /* applets[] is const, so we have to define this "override" structure */ |
234 | static struct BB_suid_config { | 237 | static struct BB_suid_config { |
@@ -499,15 +502,15 @@ static void parse_config_file(void) | |||
499 | sct_head = sct; | 502 | sct_head = sct; |
500 | } | 503 | } |
501 | } | 504 | } |
502 | #else | 505 | # else |
503 | static inline void parse_config_file(void) | 506 | static inline void parse_config_file(void) |
504 | { | 507 | { |
505 | IF_FEATURE_SUID(ruid = getuid();) | 508 | IF_FEATURE_SUID(ruid = getuid();) |
506 | } | 509 | } |
507 | #endif /* FEATURE_SUID_CONFIG */ | 510 | # endif /* FEATURE_SUID_CONFIG */ |
508 | 511 | ||
509 | 512 | ||
510 | #if ENABLE_FEATURE_SUID | 513 | # if ENABLE_FEATURE_SUID |
511 | static void check_suid(int applet_no) | 514 | static void check_suid(int applet_no) |
512 | { | 515 | { |
513 | gid_t rgid; /* real gid */ | 516 | gid_t rgid; /* real gid */ |
@@ -516,7 +519,7 @@ static void check_suid(int applet_no) | |||
516 | return; /* run by root - no need to check more */ | 519 | return; /* run by root - no need to check more */ |
517 | rgid = getgid(); | 520 | rgid = getgid(); |
518 | 521 | ||
519 | #if ENABLE_FEATURE_SUID_CONFIG | 522 | # if ENABLE_FEATURE_SUID_CONFIG |
520 | if (suid_cfg_readable) { | 523 | if (suid_cfg_readable) { |
521 | uid_t uid; | 524 | uid_t uid; |
522 | struct BB_suid_config *sct; | 525 | struct BB_suid_config *sct; |
@@ -559,7 +562,7 @@ static void check_suid(int applet_no) | |||
559 | bb_perror_msg_and_die("setresuid"); | 562 | bb_perror_msg_and_die("setresuid"); |
560 | return; | 563 | return; |
561 | } | 564 | } |
562 | #if !ENABLE_FEATURE_SUID_CONFIG_QUIET | 565 | # if !ENABLE_FEATURE_SUID_CONFIG_QUIET |
563 | { | 566 | { |
564 | static bool onetime = 0; | 567 | static bool onetime = 0; |
565 | 568 | ||
@@ -568,9 +571,9 @@ static void check_suid(int applet_no) | |||
568 | fprintf(stderr, "Using fallback suid method\n"); | 571 | fprintf(stderr, "Using fallback suid method\n"); |
569 | } | 572 | } |
570 | } | 573 | } |
571 | #endif | 574 | # endif |
572 | check_need_suid: | 575 | check_need_suid: |
573 | #endif | 576 | # endif |
574 | if (APPLET_SUID(applet_no) == _BB_SUID_REQUIRE) { | 577 | if (APPLET_SUID(applet_no) == _BB_SUID_REQUIRE) { |
575 | /* Real uid is not 0. If euid isn't 0 too, suid bit | 578 | /* Real uid is not 0. If euid isn't 0 too, suid bit |
576 | * is most probably not set on our executable */ | 579 | * is most probably not set on our executable */ |
@@ -581,25 +584,24 @@ static void check_suid(int applet_no) | |||
581 | xsetuid(ruid); | 584 | xsetuid(ruid); |
582 | } | 585 | } |
583 | } | 586 | } |
584 | #else | 587 | # else |
585 | #define check_suid(x) ((void)0) | 588 | # define check_suid(x) ((void)0) |
586 | #endif /* FEATURE_SUID */ | 589 | # endif /* FEATURE_SUID */ |
587 | 590 | ||
588 | 591 | ||
589 | #if ENABLE_FEATURE_INSTALLER | 592 | # if ENABLE_FEATURE_INSTALLER |
590 | static const char usr_bin [] ALIGN1 = "/usr/bin/"; | 593 | static const char usr_bin [] ALIGN1 = "/usr/bin/"; |
591 | static const char usr_sbin[] ALIGN1 = "/usr/sbin/"; | 594 | static const char usr_sbin[] ALIGN1 = "/usr/sbin/"; |
592 | static const char *const install_dir[] = { | 595 | static const char *const install_dir[] = { |
593 | &usr_bin [8], /* "/" */ | 596 | &usr_bin [8], /* "/" */ |
594 | &usr_bin [4], /* "/bin/" */ | 597 | &usr_bin [4], /* "/bin/" */ |
595 | &usr_sbin[4] /* "/sbin/" */ | 598 | &usr_sbin[4] /* "/sbin/" */ |
596 | # if !ENABLE_INSTALL_NO_USR | 599 | # if !ENABLE_INSTALL_NO_USR |
597 | ,usr_bin | 600 | ,usr_bin |
598 | ,usr_sbin | 601 | ,usr_sbin |
599 | # endif | 602 | # endif |
600 | }; | 603 | }; |
601 | 604 | ||
602 | |||
603 | /* create (sym)links for each applet */ | 605 | /* create (sym)links for each applet */ |
604 | static void install_links(const char *busybox, int use_symbolic_links, | 606 | static void install_links(const char *busybox, int use_symbolic_links, |
605 | char *custom_install_dir) | 607 | char *custom_install_dir) |
@@ -629,9 +631,9 @@ static void install_links(const char *busybox, int use_symbolic_links, | |||
629 | free(fpc); | 631 | free(fpc); |
630 | } | 632 | } |
631 | } | 633 | } |
632 | #else | 634 | # else |
633 | # define install_links(x,y,z) ((void)0) | 635 | # define install_links(x,y,z) ((void)0) |
634 | #endif | 636 | # endif |
635 | 637 | ||
636 | /* If we were called as "busybox..." */ | 638 | /* If we were called as "busybox..." */ |
637 | static int busybox_main(char **argv) | 639 | static int busybox_main(char **argv) |
@@ -696,10 +698,10 @@ static int busybox_main(char **argv) | |||
696 | const char *a = applet_names; | 698 | const char *a = applet_names; |
697 | dup2(1, 2); | 699 | dup2(1, 2); |
698 | while (*a) { | 700 | while (*a) { |
699 | #if ENABLE_FEATURE_INSTALLER | 701 | # if ENABLE_FEATURE_INSTALLER |
700 | if (argv[1][6]) /* --list-path? */ | 702 | if (argv[1][6]) /* --list-path? */ |
701 | full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1); | 703 | full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1); |
702 | #endif | 704 | # endif |
703 | full_write2_str(a); | 705 | full_write2_str(a); |
704 | full_write2_str("\n"); | 706 | full_write2_str("\n"); |
705 | i++; | 707 | i++; |
@@ -772,7 +774,7 @@ void FAST_FUNC run_applet_and_exit(const char *name, char **argv) | |||
772 | int applet = find_applet_by_name(name); | 774 | int applet = find_applet_by_name(name); |
773 | if (applet >= 0) | 775 | if (applet >= 0) |
774 | run_applet_no_and_exit(applet, argv); | 776 | run_applet_no_and_exit(applet, argv); |
775 | if (!strncmp(name, "busybox", 7)) | 777 | if (strncmp(name, "busybox", 7) == 0) |
776 | exit(busybox_main(argv)); | 778 | exit(busybox_main(argv)); |
777 | } | 779 | } |
778 | 780 | ||
@@ -804,14 +806,6 @@ int main(int argc UNUSED_PARAM, char **argv) | |||
804 | mallopt(M_MMAP_THRESHOLD, 8 * PAGE_SIZE - 256); | 806 | mallopt(M_MMAP_THRESHOLD, 8 * PAGE_SIZE - 256); |
805 | #endif | 807 | #endif |
806 | 808 | ||
807 | #if defined(SINGLE_APPLET_MAIN) | ||
808 | /* Only one applet is selected by the user! */ | ||
809 | /* applet_names in this case is just "applet\0\0" */ | ||
810 | lbb_prepare(applet_names IF_FEATURE_INDIVIDUAL(, argv)); | ||
811 | return SINGLE_APPLET_MAIN(argc, argv); | ||
812 | #else | ||
813 | lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv)); | ||
814 | |||
815 | #if !BB_MMU | 809 | #if !BB_MMU |
816 | /* NOMMU re-exec trick sets high-order bit in first byte of name */ | 810 | /* NOMMU re-exec trick sets high-order bit in first byte of name */ |
817 | if (argv[0][0] & 0x80) { | 811 | if (argv[0][0] & 0x80) { |
@@ -819,6 +813,19 @@ int main(int argc UNUSED_PARAM, char **argv) | |||
819 | argv[0][0] &= 0x7f; | 813 | argv[0][0] &= 0x7f; |
820 | } | 814 | } |
821 | #endif | 815 | #endif |
816 | |||
817 | #if defined(SINGLE_APPLET_MAIN) | ||
818 | /* Only one applet is selected in .config */ | ||
819 | if (argv[1] && strncmp(argv[0], "busybox", 7) == 0) { | ||
820 | /* "busybox <applet> <params>" should still work as expected */ | ||
821 | argv++; | ||
822 | } | ||
823 | /* applet_names in this case is just "applet\0\0" */ | ||
824 | lbb_prepare(applet_names IF_FEATURE_INDIVIDUAL(, argv)); | ||
825 | return SINGLE_APPLET_MAIN(argc, argv); | ||
826 | #else | ||
827 | lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv)); | ||
828 | |||
822 | applet_name = argv[0]; | 829 | applet_name = argv[0]; |
823 | if (applet_name[0] == '-') | 830 | if (applet_name[0] == '-') |
824 | applet_name++; | 831 | applet_name++; |
diff --git a/libbb/find_root_device.c b/libbb/find_root_device.c index 32c86cea8..8436cd664 100644 --- a/libbb/find_root_device.c +++ b/libbb/find_root_device.c | |||
@@ -29,14 +29,15 @@ static char *find_block_device_in_dir(struct arena *ap) | |||
29 | char *retpath = NULL; | 29 | char *retpath = NULL; |
30 | int len, rem; | 30 | int len, rem; |
31 | 31 | ||
32 | dir = opendir(ap->devpath); | ||
33 | if (!dir) | ||
34 | return NULL; | ||
35 | |||
36 | len = strlen(ap->devpath); | 32 | len = strlen(ap->devpath); |
37 | rem = DEVNAME_MAX-2 - len; | 33 | rem = DEVNAME_MAX-2 - len; |
38 | if (rem <= 0) | 34 | if (rem <= 0) |
39 | return NULL; | 35 | return NULL; |
36 | |||
37 | dir = opendir(ap->devpath); | ||
38 | if (!dir) | ||
39 | return NULL; | ||
40 | |||
40 | ap->devpath[len++] = '/'; | 41 | ap->devpath[len++] = '/'; |
41 | 42 | ||
42 | while ((entry = readdir(dir)) != NULL) { | 43 | while ((entry = readdir(dir)) != NULL) { |
diff --git a/libbb/getopt32.c b/libbb/getopt32.c index ab77755fc..187cb3a79 100644 --- a/libbb/getopt32.c +++ b/libbb/getopt32.c | |||
@@ -115,7 +115,7 @@ const char *opt_complementary | |||
115 | found. | 115 | found. |
116 | 116 | ||
117 | "ww" Adjacent double options have a counter associated which indicates | 117 | "ww" Adjacent double options have a counter associated which indicates |
118 | the number of occurences of the option. | 118 | the number of occurrences of the option. |
119 | For example the ps applet needs: | 119 | For example the ps applet needs: |
120 | if w is given once, GNU ps sets the width to 132, | 120 | if w is given once, GNU ps sets the width to 132, |
121 | if w is given more than once, it is "unlimited" | 121 | if w is given more than once, it is "unlimited" |
diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c index e427f6080..b87d1dde8 100644 --- a/libbb/hash_md5_sha.c +++ b/libbb/hash_md5_sha.c | |||
@@ -158,11 +158,11 @@ static void FAST_FUNC md5_process_block64(md5_ctx_t *ctx) | |||
158 | }; | 158 | }; |
159 | static const char P_array[] ALIGN1 = { | 159 | static const char P_array[] ALIGN1 = { |
160 | # if MD5_SIZE_VS_SPEED > 1 | 160 | # if MD5_SIZE_VS_SPEED > 1 |
161 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */ | 161 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */ |
162 | # endif | 162 | # endif |
163 | 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */ | 163 | 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */ |
164 | 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */ | 164 | 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */ |
165 | 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */ | 165 | 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */ |
166 | }; | 166 | }; |
167 | #endif | 167 | #endif |
168 | uint32_t *words = (void*) ctx->wbuffer; | 168 | uint32_t *words = (void*) ctx->wbuffer; |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 182dfac13..f9658711a 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -94,8 +94,10 @@ static bool BB_ispunct(CHAR_T c) { return ((unsigned)c < 256 && ispunct(c)); } | |||
94 | #endif | 94 | #endif |
95 | 95 | ||
96 | 96 | ||
97 | #define SEQ_CLEAR_TILL_END_OF_SCREEN "\033[J" | 97 | #define ESC "\033" |
98 | //#define SEQ_CLEAR_TILL_END_OF_LINE "\033[K" | 98 | |
99 | #define SEQ_CLEAR_TILL_END_OF_SCREEN ESC"[J" | ||
100 | //#define SEQ_CLEAR_TILL_END_OF_LINE ESC"[K" | ||
99 | 101 | ||
100 | 102 | ||
101 | enum { | 103 | enum { |
@@ -446,7 +448,7 @@ static void input_backward(unsigned num) | |||
446 | } while (--num); | 448 | } while (--num); |
447 | return; | 449 | return; |
448 | } | 450 | } |
449 | printf("\033[%uD", num); | 451 | printf(ESC"[%uD", num); |
450 | return; | 452 | return; |
451 | } | 453 | } |
452 | 454 | ||
@@ -471,7 +473,7 @@ static void input_backward(unsigned num) | |||
471 | */ | 473 | */ |
472 | unsigned sv_cursor; | 474 | unsigned sv_cursor; |
473 | /* go to 1st column; go up to first line */ | 475 | /* go to 1st column; go up to first line */ |
474 | printf("\r" "\033[%uA", cmdedit_y); | 476 | printf("\r" ESC"[%uA", cmdedit_y); |
475 | cmdedit_y = 0; | 477 | cmdedit_y = 0; |
476 | sv_cursor = cursor; | 478 | sv_cursor = cursor; |
477 | put_prompt(); /* sets cursor to 0 */ | 479 | put_prompt(); /* sets cursor to 0 */ |
@@ -488,12 +490,12 @@ static void input_backward(unsigned num) | |||
488 | cmdedit_x = (width * cmdedit_y - num) % width; | 490 | cmdedit_x = (width * cmdedit_y - num) % width; |
489 | cmdedit_y -= lines_up; | 491 | cmdedit_y -= lines_up; |
490 | /* go to 1st column; go up */ | 492 | /* go to 1st column; go up */ |
491 | printf("\r" "\033[%uA", lines_up); | 493 | printf("\r" ESC"[%uA", lines_up); |
492 | /* go to correct column. | 494 | /* go to correct column. |
493 | * xterm, konsole, Linux VT interpret 0 as 1 below! wow. | 495 | * xterm, konsole, Linux VT interpret 0 as 1 below! wow. |
494 | * need to *make sure* we skip it if cmdedit_x == 0 */ | 496 | * need to *make sure* we skip it if cmdedit_x == 0 */ |
495 | if (cmdedit_x) | 497 | if (cmdedit_x) |
496 | printf("\033[%uC", cmdedit_x); | 498 | printf(ESC"[%uC", cmdedit_x); |
497 | } | 499 | } |
498 | } | 500 | } |
499 | 501 | ||
@@ -501,7 +503,7 @@ static void input_backward(unsigned num) | |||
501 | static void redraw(int y, int back_cursor) | 503 | static void redraw(int y, int back_cursor) |
502 | { | 504 | { |
503 | if (y > 0) /* up y lines */ | 505 | if (y > 0) /* up y lines */ |
504 | printf("\033[%uA", y); | 506 | printf(ESC"[%uA", y); |
505 | bb_putchar('\r'); | 507 | bb_putchar('\r'); |
506 | put_prompt(); | 508 | put_prompt(); |
507 | put_till_end_and_adv_cursor(); | 509 | put_till_end_and_adv_cursor(); |
@@ -582,6 +584,12 @@ static void input_forward(void) | |||
582 | 584 | ||
583 | #if ENABLE_FEATURE_TAB_COMPLETION | 585 | #if ENABLE_FEATURE_TAB_COMPLETION |
584 | 586 | ||
587 | //FIXME: | ||
588 | //needs to be more clever: currently it thinks that "foo\ b<TAB> | ||
589 | //matches the file named "foo bar", which is untrue. | ||
590 | //Also, perhaps "foo b<TAB> needs to complete to "foo bar" <cursor>, | ||
591 | //not "foo bar <cursor>... | ||
592 | |||
585 | static void free_tab_completion_data(void) | 593 | static void free_tab_completion_data(void) |
586 | { | 594 | { |
587 | if (matches) { | 595 | if (matches) { |
@@ -599,7 +607,7 @@ static void add_match(char *matched) | |||
599 | num_matches++; | 607 | num_matches++; |
600 | } | 608 | } |
601 | 609 | ||
602 | #if ENABLE_FEATURE_USERNAME_COMPLETION | 610 | # if ENABLE_FEATURE_USERNAME_COMPLETION |
603 | /* Replace "~user/..." with "/homedir/...". | 611 | /* Replace "~user/..." with "/homedir/...". |
604 | * The parameter is malloced, free it or return it | 612 | * The parameter is malloced, free it or return it |
605 | * unchanged if no user is matched. | 613 | * unchanged if no user is matched. |
@@ -655,7 +663,7 @@ static NOINLINE unsigned complete_username(const char *ud) | |||
655 | 663 | ||
656 | return 1 + userlen; | 664 | return 1 + userlen; |
657 | } | 665 | } |
658 | #endif /* FEATURE_USERNAME_COMPLETION */ | 666 | # endif /* FEATURE_USERNAME_COMPLETION */ |
659 | 667 | ||
660 | enum { | 668 | enum { |
661 | FIND_EXE_ONLY = 0, | 669 | FIND_EXE_ONLY = 0, |
@@ -740,10 +748,10 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
740 | pfind++; | 748 | pfind++; |
741 | /* dirbuf = ".../.../.../" */ | 749 | /* dirbuf = ".../.../.../" */ |
742 | dirbuf = xstrndup(command, pfind - command); | 750 | dirbuf = xstrndup(command, pfind - command); |
743 | #if ENABLE_FEATURE_USERNAME_COMPLETION | 751 | # if ENABLE_FEATURE_USERNAME_COMPLETION |
744 | if (dirbuf[0] == '~') /* ~/... or ~user/... */ | 752 | if (dirbuf[0] == '~') /* ~/... or ~user/... */ |
745 | dirbuf = username_path_completion(dirbuf); | 753 | dirbuf = username_path_completion(dirbuf); |
746 | #endif | 754 | # endif |
747 | path1[0] = dirbuf; | 755 | path1[0] = dirbuf; |
748 | } | 756 | } |
749 | pf_len = strlen(pfind); | 757 | pf_len = strlen(pfind); |
@@ -1021,13 +1029,18 @@ static void showfiles(void) | |||
1021 | } | 1029 | } |
1022 | } | 1030 | } |
1023 | 1031 | ||
1024 | static char *add_quote_for_spec_chars(char *found) | 1032 | static const char *is_special_char(char c) |
1033 | { | ||
1034 | return strchr(" `\"#$%^&*()=+{}[]:;'|\\<>", c); | ||
1035 | } | ||
1036 | |||
1037 | static char *quote_special_chars(char *found) | ||
1025 | { | 1038 | { |
1026 | int l = 0; | 1039 | int l = 0; |
1027 | char *s = xzalloc((strlen(found) + 1) * 2); | 1040 | char *s = xzalloc((strlen(found) + 1) * 2); |
1028 | 1041 | ||
1029 | while (*found) { | 1042 | while (*found) { |
1030 | if (strchr(" `\"#$%^&*()=+{}[]:;'|\\<>", *found)) | 1043 | if (is_special_char(*found)) |
1031 | s[l++] = '\\'; | 1044 | s[l++] = '\\'; |
1032 | s[l++] = *found++; | 1045 | s[l++] = *found++; |
1033 | } | 1046 | } |
@@ -1044,10 +1057,10 @@ static NOINLINE void input_tab(smallint *lastWasTab) | |||
1044 | /* Length of string used for matching */ | 1057 | /* Length of string used for matching */ |
1045 | unsigned match_pfx_len = match_pfx_len; | 1058 | unsigned match_pfx_len = match_pfx_len; |
1046 | int find_type; | 1059 | int find_type; |
1047 | #if ENABLE_UNICODE_SUPPORT | 1060 | # if ENABLE_UNICODE_SUPPORT |
1048 | /* cursor pos in command converted to multibyte form */ | 1061 | /* cursor pos in command converted to multibyte form */ |
1049 | int cursor_mb; | 1062 | int cursor_mb; |
1050 | #endif | 1063 | # endif |
1051 | if (!(state->flags & TAB_COMPLETION)) | 1064 | if (!(state->flags & TAB_COMPLETION)) |
1052 | return; | 1065 | return; |
1053 | 1066 | ||
@@ -1074,9 +1087,9 @@ static NOINLINE void input_tab(smallint *lastWasTab) | |||
1074 | * (we then also (ab)use this extra space later - see (**)) | 1087 | * (we then also (ab)use this extra space later - see (**)) |
1075 | */ | 1088 | */ |
1076 | match_buf = xmalloc(MAX_LINELEN * sizeof(int16_t)); | 1089 | match_buf = xmalloc(MAX_LINELEN * sizeof(int16_t)); |
1077 | #if !ENABLE_UNICODE_SUPPORT | 1090 | # if !ENABLE_UNICODE_SUPPORT |
1078 | save_string(match_buf, cursor + 1); /* +1 for NUL */ | 1091 | save_string(match_buf, cursor + 1); /* +1 for NUL */ |
1079 | #else | 1092 | # else |
1080 | { | 1093 | { |
1081 | CHAR_T wc = command_ps[cursor]; | 1094 | CHAR_T wc = command_ps[cursor]; |
1082 | command_ps[cursor] = BB_NUL; | 1095 | command_ps[cursor] = BB_NUL; |
@@ -1084,26 +1097,37 @@ static NOINLINE void input_tab(smallint *lastWasTab) | |||
1084 | command_ps[cursor] = wc; | 1097 | command_ps[cursor] = wc; |
1085 | cursor_mb = strlen(match_buf); | 1098 | cursor_mb = strlen(match_buf); |
1086 | } | 1099 | } |
1087 | #endif | 1100 | # endif |
1088 | find_type = build_match_prefix(match_buf); | 1101 | find_type = build_match_prefix(match_buf); |
1089 | 1102 | ||
1090 | /* Free up any memory already allocated */ | 1103 | /* Free up any memory already allocated */ |
1091 | free_tab_completion_data(); | 1104 | free_tab_completion_data(); |
1092 | 1105 | ||
1093 | #if ENABLE_FEATURE_USERNAME_COMPLETION | 1106 | # if ENABLE_FEATURE_USERNAME_COMPLETION |
1094 | /* If the word starts with `~' and there is no slash in the word, | 1107 | /* If the word starts with ~ and there is no slash in the word, |
1095 | * then try completing this word as a username. */ | 1108 | * then try completing this word as a username. */ |
1096 | if (state->flags & USERNAME_COMPLETION) | 1109 | if (state->flags & USERNAME_COMPLETION) |
1097 | if (match_buf[0] == '~' && strchr(match_buf, '/') == NULL) | 1110 | if (match_buf[0] == '~' && strchr(match_buf, '/') == NULL) |
1098 | match_pfx_len = complete_username(match_buf); | 1111 | match_pfx_len = complete_username(match_buf); |
1099 | #endif | 1112 | # endif |
1100 | /* Try to match a command in $PATH, or a directory, or a file */ | 1113 | /* If complete_username() did not match, |
1114 | * try to match a command in $PATH, or a directory, or a file */ | ||
1101 | if (!matches) | 1115 | if (!matches) |
1102 | match_pfx_len = complete_cmd_dir_file(match_buf, find_type); | 1116 | match_pfx_len = complete_cmd_dir_file(match_buf, find_type); |
1117 | |||
1118 | /* Account for backslashes which will be inserted | ||
1119 | * by quote_special_chars() later */ | ||
1120 | { | ||
1121 | const char *e = match_buf + strlen(match_buf); | ||
1122 | const char *s = e - match_pfx_len; | ||
1123 | while (s < e) | ||
1124 | if (is_special_char(*s++)) | ||
1125 | match_pfx_len++; | ||
1126 | } | ||
1127 | |||
1103 | /* Remove duplicates */ | 1128 | /* Remove duplicates */ |
1104 | if (matches) { | 1129 | if (matches) { |
1105 | unsigned i; | 1130 | unsigned i, n = 0; |
1106 | unsigned n = 0; | ||
1107 | qsort_string_vector(matches, num_matches); | 1131 | qsort_string_vector(matches, num_matches); |
1108 | for (i = 0; i < num_matches - 1; ++i) { | 1132 | for (i = 0; i < num_matches - 1; ++i) { |
1109 | //if (matches[i] && matches[i+1]) { /* paranoia */ | 1133 | //if (matches[i] && matches[i+1]) { /* paranoia */ |
@@ -1118,6 +1142,7 @@ static NOINLINE void input_tab(smallint *lastWasTab) | |||
1118 | matches[n++] = matches[i]; | 1142 | matches[n++] = matches[i]; |
1119 | num_matches = n; | 1143 | num_matches = n; |
1120 | } | 1144 | } |
1145 | |||
1121 | /* Did we find exactly one match? */ | 1146 | /* Did we find exactly one match? */ |
1122 | if (num_matches != 1) { /* no */ | 1147 | if (num_matches != 1) { /* no */ |
1123 | char *cp; | 1148 | char *cp; |
@@ -1139,7 +1164,7 @@ static NOINLINE void input_tab(smallint *lastWasTab) | |||
1139 | goto ret; /* no */ | 1164 | goto ret; /* no */ |
1140 | } | 1165 | } |
1141 | *cp = '\0'; | 1166 | *cp = '\0'; |
1142 | cp = add_quote_for_spec_chars(chosen_match); | 1167 | cp = quote_special_chars(chosen_match); |
1143 | free(chosen_match); | 1168 | free(chosen_match); |
1144 | chosen_match = cp; | 1169 | chosen_match = cp; |
1145 | len_found = strlen(chosen_match); | 1170 | len_found = strlen(chosen_match); |
@@ -1147,7 +1172,7 @@ static NOINLINE void input_tab(smallint *lastWasTab) | |||
1147 | /* Next <tab> is not a double-tab */ | 1172 | /* Next <tab> is not a double-tab */ |
1148 | *lastWasTab = 0; | 1173 | *lastWasTab = 0; |
1149 | 1174 | ||
1150 | chosen_match = add_quote_for_spec_chars(matches[0]); | 1175 | chosen_match = quote_special_chars(matches[0]); |
1151 | len_found = strlen(chosen_match); | 1176 | len_found = strlen(chosen_match); |
1152 | if (chosen_match[len_found-1] != '/') { | 1177 | if (chosen_match[len_found-1] != '/') { |
1153 | chosen_match[len_found] = ' '; | 1178 | chosen_match[len_found] = ' '; |
@@ -1155,7 +1180,7 @@ static NOINLINE void input_tab(smallint *lastWasTab) | |||
1155 | } | 1180 | } |
1156 | } | 1181 | } |
1157 | 1182 | ||
1158 | #if !ENABLE_UNICODE_SUPPORT | 1183 | # if !ENABLE_UNICODE_SUPPORT |
1159 | /* Have space to place the match? */ | 1184 | /* Have space to place the match? */ |
1160 | /* The result consists of three parts with these lengths: */ | 1185 | /* The result consists of three parts with these lengths: */ |
1161 | /* cursor + (len_found - match_pfx_len) + (command_len - cursor) */ | 1186 | /* cursor + (len_found - match_pfx_len) + (command_len - cursor) */ |
@@ -1172,7 +1197,7 @@ static NOINLINE void input_tab(smallint *lastWasTab) | |||
1172 | /* write out the matched command */ | 1197 | /* write out the matched command */ |
1173 | redraw(cmdedit_y, command_len - pos); | 1198 | redraw(cmdedit_y, command_len - pos); |
1174 | } | 1199 | } |
1175 | #else | 1200 | # else |
1176 | { | 1201 | { |
1177 | /* Use 2nd half of match_buf as scratch space - see (**) */ | 1202 | /* Use 2nd half of match_buf as scratch space - see (**) */ |
1178 | char *command = match_buf + MAX_LINELEN; | 1203 | char *command = match_buf + MAX_LINELEN; |
@@ -1196,7 +1221,7 @@ static NOINLINE void input_tab(smallint *lastWasTab) | |||
1196 | redraw(cmdedit_y, pos >= 0 ? pos : 0); | 1221 | redraw(cmdedit_y, pos >= 0 ? pos : 0); |
1197 | } | 1222 | } |
1198 | } | 1223 | } |
1199 | #endif | 1224 | # endif |
1200 | ret: | 1225 | ret: |
1201 | free(chosen_match); | 1226 | free(chosen_match); |
1202 | free(match_buf); | 1227 | free(match_buf); |
@@ -1342,7 +1367,7 @@ static void save_history(char *str) | |||
1342 | int fd; | 1367 | int fd; |
1343 | int len, len2; | 1368 | int len, len2; |
1344 | 1369 | ||
1345 | fd = open(state->hist_file, O_WRONLY | O_CREAT | O_APPEND, 0666); | 1370 | fd = open(state->hist_file, O_WRONLY | O_CREAT | O_APPEND, 0600); |
1346 | if (fd < 0) | 1371 | if (fd < 0) |
1347 | return; | 1372 | return; |
1348 | xlseek(fd, 0, SEEK_END); /* paranoia */ | 1373 | xlseek(fd, 0, SEEK_END); /* paranoia */ |
@@ -1357,10 +1382,8 @@ static void save_history(char *str) | |||
1357 | /* did we write so much that history file needs trimming? */ | 1382 | /* did we write so much that history file needs trimming? */ |
1358 | state->cnt_history_in_file++; | 1383 | state->cnt_history_in_file++; |
1359 | if (state->cnt_history_in_file > MAX_HISTORY * 4) { | 1384 | if (state->cnt_history_in_file > MAX_HISTORY * 4) { |
1360 | FILE *fp; | ||
1361 | char *new_name; | 1385 | char *new_name; |
1362 | line_input_t *st_temp; | 1386 | line_input_t *st_temp; |
1363 | int i; | ||
1364 | 1387 | ||
1365 | /* we may have concurrently written entries from others. | 1388 | /* we may have concurrently written entries from others. |
1366 | * load them */ | 1389 | * load them */ |
@@ -1370,8 +1393,12 @@ static void save_history(char *str) | |||
1370 | 1393 | ||
1371 | /* write out temp file and replace hist_file atomically */ | 1394 | /* write out temp file and replace hist_file atomically */ |
1372 | new_name = xasprintf("%s.%u.new", state->hist_file, (int) getpid()); | 1395 | new_name = xasprintf("%s.%u.new", state->hist_file, (int) getpid()); |
1373 | fp = fopen_for_write(new_name); | 1396 | fd = open(state->hist_file, O_WRONLY | O_CREAT | O_TRUNC, 0600); |
1374 | if (fp) { | 1397 | if (fd >= 0) { |
1398 | FILE *fp; | ||
1399 | int i; | ||
1400 | |||
1401 | fp = xfdopen_for_write(fd); | ||
1375 | for (i = 0; i < st_temp->cnt_history; i++) | 1402 | for (i = 0; i < st_temp->cnt_history; i++) |
1376 | fprintf(fp, "%s\n", st_temp->history[i]); | 1403 | fprintf(fp, "%s\n", st_temp->history[i]); |
1377 | fclose(fp); | 1404 | fclose(fp); |
@@ -1634,7 +1661,7 @@ static void ask_terminal(void) | |||
1634 | pfd.events = POLLIN; | 1661 | pfd.events = POLLIN; |
1635 | if (safe_poll(&pfd, 1, 0) == 0) { | 1662 | if (safe_poll(&pfd, 1, 0) == 0) { |
1636 | S.sent_ESC_br6n = 1; | 1663 | S.sent_ESC_br6n = 1; |
1637 | fputs("\033" "[6n", stdout); | 1664 | fputs(ESC"[6n", stdout); |
1638 | fflush_all(); /* make terminal see it ASAP! */ | 1665 | fflush_all(); /* make terminal see it ASAP! */ |
1639 | } | 1666 | } |
1640 | } | 1667 | } |
@@ -2089,7 +2116,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
2089 | case CTRL('L'): | 2116 | case CTRL('L'): |
2090 | vi_case(CTRL('L')|VI_CMDMODE_BIT:) | 2117 | vi_case(CTRL('L')|VI_CMDMODE_BIT:) |
2091 | /* Control-l -- clear screen */ | 2118 | /* Control-l -- clear screen */ |
2092 | printf("\033[H"); /* cursor to top,left */ | 2119 | printf(ESC"[H"); /* cursor to top,left */ |
2093 | redraw(0, command_len - cursor); | 2120 | redraw(0, command_len - cursor); |
2094 | break; | 2121 | break; |
2095 | #if MAX_HISTORY > 0 | 2122 | #if MAX_HISTORY > 0 |
diff --git a/libbb/procps.c b/libbb/procps.c index ec43b221e..fcf86d9bb 100644 --- a/libbb/procps.c +++ b/libbb/procps.c | |||
@@ -303,6 +303,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags) | |||
303 | goto got_entry; | 303 | goto got_entry; |
304 | closedir(sp->task_dir); | 304 | closedir(sp->task_dir); |
305 | sp->task_dir = NULL; | 305 | sp->task_dir = NULL; |
306 | sp->main_thread_pid = 0; | ||
306 | } | 307 | } |
307 | #endif | 308 | #endif |
308 | entry = readdir(sp->dir); | 309 | entry = readdir(sp->dir); |
@@ -322,6 +323,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags) | |||
322 | char task_dir[sizeof("/proc/%u/task") + sizeof(int)*3]; | 323 | char task_dir[sizeof("/proc/%u/task") + sizeof(int)*3]; |
323 | sprintf(task_dir, "/proc/%u/task", pid); | 324 | sprintf(task_dir, "/proc/%u/task", pid); |
324 | sp->task_dir = xopendir(task_dir); | 325 | sp->task_dir = xopendir(task_dir); |
326 | sp->main_thread_pid = pid; | ||
325 | continue; | 327 | continue; |
326 | } | 328 | } |
327 | #endif | 329 | #endif |
diff --git a/libbb/pw_encrypt_sha.c b/libbb/pw_encrypt_sha.c index 070e0d442..8aeaacad6 100644 --- a/libbb/pw_encrypt_sha.c +++ b/libbb/pw_encrypt_sha.c | |||
@@ -3,7 +3,7 @@ | |||
3 | */ | 3 | */ |
4 | 4 | ||
5 | /* Prefix for optional rounds specification. */ | 5 | /* Prefix for optional rounds specification. */ |
6 | static const char str_rounds[] = "rounds=%u$"; | 6 | static const char str_rounds[] ALIGN1 = "rounds=%u$"; |
7 | 7 | ||
8 | /* Maximum salt string length. */ | 8 | /* Maximum salt string length. */ |
9 | #define SALT_LEN_MAX 16 | 9 | #define SALT_LEN_MAX 16 |
@@ -19,8 +19,8 @@ NOINLINE | |||
19 | sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data) | 19 | sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data) |
20 | { | 20 | { |
21 | void (*sha_begin)(void *ctx) FAST_FUNC; | 21 | void (*sha_begin)(void *ctx) FAST_FUNC; |
22 | void (*sha_hash)(const void *buffer, size_t len, void *ctx) FAST_FUNC; | 22 | void (*sha_hash)(void *ctx, const void *buffer, size_t len) FAST_FUNC; |
23 | void (*sha_end)(void *resbuf, void *ctx) FAST_FUNC; | 23 | void (*sha_end)(void *ctx, void *resbuf) FAST_FUNC; |
24 | int _32or64; | 24 | int _32or64; |
25 | 25 | ||
26 | char *result, *resptr; | 26 | char *result, *resptr; |
@@ -103,40 +103,40 @@ sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data) | |||
103 | 103 | ||
104 | /* Add KEY, SALT. */ | 104 | /* Add KEY, SALT. */ |
105 | sha_begin(&ctx); | 105 | sha_begin(&ctx); |
106 | sha_hash(key_data, key_len, &ctx); | 106 | sha_hash(&ctx, key_data, key_len); |
107 | sha_hash(salt_data, salt_len, &ctx); | 107 | sha_hash(&ctx, salt_data, salt_len); |
108 | 108 | ||
109 | /* Compute alternate SHA sum with input KEY, SALT, and KEY. | 109 | /* Compute alternate SHA sum with input KEY, SALT, and KEY. |
110 | The final result will be added to the first context. */ | 110 | The final result will be added to the first context. */ |
111 | sha_begin(&alt_ctx); | 111 | sha_begin(&alt_ctx); |
112 | sha_hash(key_data, key_len, &alt_ctx); | 112 | sha_hash(&alt_ctx, key_data, key_len); |
113 | sha_hash(salt_data, salt_len, &alt_ctx); | 113 | sha_hash(&alt_ctx, salt_data, salt_len); |
114 | sha_hash(key_data, key_len, &alt_ctx); | 114 | sha_hash(&alt_ctx, key_data, key_len); |
115 | sha_end(alt_result, &alt_ctx); | 115 | sha_end(&alt_ctx, alt_result); |
116 | 116 | ||
117 | /* Add result of this to the other context. */ | 117 | /* Add result of this to the other context. */ |
118 | /* Add for any character in the key one byte of the alternate sum. */ | 118 | /* Add for any character in the key one byte of the alternate sum. */ |
119 | for (cnt = key_len; cnt > _32or64; cnt -= _32or64) | 119 | for (cnt = key_len; cnt > _32or64; cnt -= _32or64) |
120 | sha_hash(alt_result, _32or64, &ctx); | 120 | sha_hash(&ctx, alt_result, _32or64); |
121 | sha_hash(alt_result, cnt, &ctx); | 121 | sha_hash(&ctx, alt_result, cnt); |
122 | 122 | ||
123 | /* Take the binary representation of the length of the key and for every | 123 | /* Take the binary representation of the length of the key and for every |
124 | 1 add the alternate sum, for every 0 the key. */ | 124 | 1 add the alternate sum, for every 0 the key. */ |
125 | for (cnt = key_len; cnt != 0; cnt >>= 1) | 125 | for (cnt = key_len; cnt != 0; cnt >>= 1) |
126 | if ((cnt & 1) != 0) | 126 | if ((cnt & 1) != 0) |
127 | sha_hash(alt_result, _32or64, &ctx); | 127 | sha_hash(&ctx, alt_result, _32or64); |
128 | else | 128 | else |
129 | sha_hash(key_data, key_len, &ctx); | 129 | sha_hash(&ctx, key_data, key_len); |
130 | 130 | ||
131 | /* Create intermediate result. */ | 131 | /* Create intermediate result. */ |
132 | sha_end(alt_result, &ctx); | 132 | sha_end(&ctx, alt_result); |
133 | 133 | ||
134 | /* Start computation of P byte sequence. */ | 134 | /* Start computation of P byte sequence. */ |
135 | /* For every character in the password add the entire password. */ | 135 | /* For every character in the password add the entire password. */ |
136 | sha_begin(&alt_ctx); | 136 | sha_begin(&alt_ctx); |
137 | for (cnt = 0; cnt < key_len; ++cnt) | 137 | for (cnt = 0; cnt < key_len; ++cnt) |
138 | sha_hash(key_data, key_len, &alt_ctx); | 138 | sha_hash(&alt_ctx, key_data, key_len); |
139 | sha_end(temp_result, &alt_ctx); | 139 | sha_end(&alt_ctx, temp_result); |
140 | 140 | ||
141 | /* NB: past this point, raw key_data is not used anymore */ | 141 | /* NB: past this point, raw key_data is not used anymore */ |
142 | 142 | ||
@@ -153,8 +153,8 @@ sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data) | |||
153 | /* For every character in the password add the entire password. */ | 153 | /* For every character in the password add the entire password. */ |
154 | sha_begin(&alt_ctx); | 154 | sha_begin(&alt_ctx); |
155 | for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) | 155 | for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) |
156 | sha_hash(salt_data, salt_len, &alt_ctx); | 156 | sha_hash(&alt_ctx, salt_data, salt_len); |
157 | sha_end(temp_result, &alt_ctx); | 157 | sha_end(&alt_ctx, temp_result); |
158 | 158 | ||
159 | /* NB: past this point, raw salt_data is not used anymore */ | 159 | /* NB: past this point, raw salt_data is not used anymore */ |
160 | 160 | ||
@@ -174,31 +174,31 @@ sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data) | |||
174 | 174 | ||
175 | /* Add key or last result. */ | 175 | /* Add key or last result. */ |
176 | if ((cnt & 1) != 0) | 176 | if ((cnt & 1) != 0) |
177 | sha_hash(p_bytes, key_len, &ctx); | 177 | sha_hash(&ctx, p_bytes, key_len); |
178 | else | 178 | else |
179 | sha_hash(alt_result, _32or64, &ctx); | 179 | sha_hash(&ctx, alt_result, _32or64); |
180 | /* Add salt for numbers not divisible by 3. */ | 180 | /* Add salt for numbers not divisible by 3. */ |
181 | if (cnt % 3 != 0) | 181 | if (cnt % 3 != 0) |
182 | sha_hash(s_bytes, salt_len, &ctx); | 182 | sha_hash(&ctx, s_bytes, salt_len); |
183 | /* Add key for numbers not divisible by 7. */ | 183 | /* Add key for numbers not divisible by 7. */ |
184 | if (cnt % 7 != 0) | 184 | if (cnt % 7 != 0) |
185 | sha_hash(p_bytes, key_len, &ctx); | 185 | sha_hash(&ctx, p_bytes, key_len); |
186 | /* Add key or last result. */ | 186 | /* Add key or last result. */ |
187 | if ((cnt & 1) != 0) | 187 | if ((cnt & 1) != 0) |
188 | sha_hash(alt_result, _32or64, &ctx); | 188 | sha_hash(&ctx, alt_result, _32or64); |
189 | else | 189 | else |
190 | sha_hash(p_bytes, key_len, &ctx); | 190 | sha_hash(&ctx, p_bytes, key_len); |
191 | 191 | ||
192 | sha_end(alt_result, &ctx); | 192 | sha_end(&ctx, alt_result); |
193 | } | 193 | } |
194 | 194 | ||
195 | /* Append encrypted password to result buffer */ | 195 | /* Append encrypted password to result buffer */ |
196 | //TODO: replace with something like | 196 | //TODO: replace with something like |
197 | // bb_uuencode(cp, src, length, bb_uuenc_tbl_XXXbase64); | 197 | // bb_uuencode(cp, src, length, bb_uuenc_tbl_XXXbase64); |
198 | #define b64_from_24bit(B2, B1, B0, N) \ | 198 | #define b64_from_24bit(B2, B1, B0, N) \ |
199 | do { \ | 199 | do { \ |
200 | unsigned w = ((B2) << 16) | ((B1) << 8) | (B0); \ | 200 | unsigned w = ((B2) << 16) | ((B1) << 8) | (B0); \ |
201 | resptr = to64(resptr, w, N); \ | 201 | resptr = to64(resptr, w, N); \ |
202 | } while (0) | 202 | } while (0) |
203 | if (is_sha512 == '5') { | 203 | if (is_sha512 == '5') { |
204 | unsigned i = 0; | 204 | unsigned i = 0; |
diff --git a/libbb/read_printf.c b/libbb/read_printf.c index 7ca3d68c3..8664bc625 100644 --- a/libbb/read_printf.c +++ b/libbb/read_printf.c | |||
@@ -15,7 +15,7 @@ | |||
15 | ) | 15 | ) |
16 | 16 | ||
17 | #if ZIPPED | 17 | #if ZIPPED |
18 | # include "unarchive.h" | 18 | # include "archive.h" |
19 | #endif | 19 | #endif |
20 | 20 | ||
21 | 21 | ||
diff --git a/libbb/simplify_path.c b/libbb/simplify_path.c index 3818d32be..89dc5bdf2 100644 --- a/libbb/simplify_path.c +++ b/libbb/simplify_path.c | |||
@@ -15,17 +15,17 @@ char* FAST_FUNC bb_simplify_abs_path_inplace(char *start) | |||
15 | p = s = start; | 15 | p = s = start; |
16 | do { | 16 | do { |
17 | if (*p == '/') { | 17 | if (*p == '/') { |
18 | if (*s == '/') { /* skip duplicate (or initial) slash */ | 18 | if (*s == '/') { /* skip duplicate (or initial) slash */ |
19 | continue; | 19 | continue; |
20 | } | 20 | } |
21 | if (*s == '.') { | 21 | if (*s == '.') { |
22 | if (s[1] == '/' || !s[1]) { /* remove extra '.' */ | 22 | if (s[1] == '/' || !s[1]) { /* remove extra '.' */ |
23 | continue; | 23 | continue; |
24 | } | 24 | } |
25 | if ((s[1] == '.') && (s[2] == '/' || !s[2])) { | 25 | if ((s[1] == '.') && (s[2] == '/' || !s[2])) { |
26 | ++s; | 26 | ++s; |
27 | if (p > start) { | 27 | if (p > start) { |
28 | while (*--p != '/') /* omit previous dir */ | 28 | while (*--p != '/') /* omit previous dir */ |
29 | continue; | 29 | continue; |
30 | } | 30 | } |
31 | continue; | 31 | continue; |
@@ -35,8 +35,8 @@ char* FAST_FUNC bb_simplify_abs_path_inplace(char *start) | |||
35 | *++p = *s; | 35 | *++p = *s; |
36 | } while (*++s); | 36 | } while (*++s); |
37 | 37 | ||
38 | if ((p == start) || (*p != '/')) { /* not a trailing slash */ | 38 | if ((p == start) || (*p != '/')) { /* not a trailing slash */ |
39 | ++p; /* so keep last character */ | 39 | ++p; /* so keep last character */ |
40 | } | 40 | } |
41 | *p = '\0'; | 41 | *p = '\0'; |
42 | return p; | 42 | return p; |
diff --git a/libbb/time.c b/libbb/time.c index 2a74d34c2..1eb2d75c2 100644 --- a/libbb/time.c +++ b/libbb/time.c | |||
@@ -93,6 +93,7 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm) | |||
93 | * | 93 | * |
94 | * This coincides with the format of "touch -t TIME" | 94 | * This coincides with the format of "touch -t TIME" |
95 | */ | 95 | */ |
96 | unsigned cur_year = ptm->tm_year; | ||
96 | int len = strchrnul(date_str, '.') - date_str; | 97 | int len = strchrnul(date_str, '.') - date_str; |
97 | 98 | ||
98 | /* MM[.SS] */ | 99 | /* MM[.SS] */ |
@@ -133,6 +134,17 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm) | |||
133 | &end) >= 5) { | 134 | &end) >= 5) { |
134 | /* Adjust month from 1-12 to 0-11 */ | 135 | /* Adjust month from 1-12 to 0-11 */ |
135 | ptm->tm_mon -= 1; | 136 | ptm->tm_mon -= 1; |
137 | if ((int)cur_year >= 50) { /* >= 1950 */ | ||
138 | /* Adjust year: */ | ||
139 | /* 1. Put it in the current century */ | ||
140 | ptm->tm_year += (cur_year / 100) * 100; | ||
141 | /* 2. If too far in the past, +100 years */ | ||
142 | if (ptm->tm_year < cur_year - 50) | ||
143 | ptm->tm_year += 100; | ||
144 | /* 3. If too far in the future, -100 years */ | ||
145 | if (ptm->tm_year > cur_year + 50) | ||
146 | ptm->tm_year -= 100; | ||
147 | } | ||
136 | } else | 148 | } else |
137 | /* ccyymmddHHMM[.SS] */ | 149 | /* ccyymmddHHMM[.SS] */ |
138 | if (len == 12 && sscanf(date_str, "%4u%2u%2u%2u%2u%c", | 150 | if (len == 12 && sscanf(date_str, "%4u%2u%2u%2u%2u%c", |
diff --git a/libbb/u_signal_names.c b/libbb/u_signal_names.c index 9263859f5..8c78f5e20 100644 --- a/libbb/u_signal_names.c +++ b/libbb/u_signal_names.c | |||
@@ -7,6 +7,13 @@ | |||
7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | //config:config FEATURE_RTMINMAX | ||
11 | //config: bool "Support RTMIN[+n] and RTMAX[-n] signal names" | ||
12 | //config: default y | ||
13 | //config: help | ||
14 | //config: Support RTMIN[+n] and RTMAX[-n] signal names | ||
15 | //config: in kill, killall etc. This costs ~250 bytes. | ||
16 | |||
10 | #include "libbb.h" | 17 | #include "libbb.h" |
11 | 18 | ||
12 | /* Believe it or not, but some arches have more than 32 SIGs! | 19 | /* Believe it or not, but some arches have more than 32 SIGs! |
@@ -117,6 +124,16 @@ static const char signals[][7] = { | |||
117 | #ifdef SIGSYS | 124 | #ifdef SIGSYS |
118 | [SIGSYS ] = "SYS", | 125 | [SIGSYS ] = "SYS", |
119 | #endif | 126 | #endif |
127 | #if ENABLE_FEATURE_RTMINMAX | ||
128 | # ifdef __SIGRTMIN | ||
129 | [__SIGRTMIN] = "RTMIN", | ||
130 | # endif | ||
131 | // This makes array about x2 bigger. | ||
132 | // More compact approach is to special-case SIGRTMAX in print_signames() | ||
133 | //# ifdef __SIGRTMAX | ||
134 | // [__SIGRTMAX] = "RTMAX", | ||
135 | //# endif | ||
136 | #endif | ||
120 | }; | 137 | }; |
121 | 138 | ||
122 | // Convert signal name to number. | 139 | // Convert signal name to number. |
@@ -134,20 +151,54 @@ int FAST_FUNC get_signum(const char *name) | |||
134 | if (strcasecmp(name, signals[i]) == 0) | 151 | if (strcasecmp(name, signals[i]) == 0) |
135 | return i; | 152 | return i; |
136 | 153 | ||
137 | #if ENABLE_DESKTOP && (defined(SIGIOT) || defined(SIGIO)) | 154 | #if ENABLE_DESKTOP |
155 | # if defined(SIGIOT) || defined(SIGIO) | ||
138 | /* SIGIO[T] are aliased to other names, | 156 | /* SIGIO[T] are aliased to other names, |
139 | * thus cannot be stored in the signals[] array. | 157 | * thus cannot be stored in the signals[] array. |
140 | * Need special code to recognize them */ | 158 | * Need special code to recognize them */ |
141 | if ((name[0] | 0x20) == 'i' && (name[1] | 0x20) == 'o') { | 159 | if ((name[0] | 0x20) == 'i' && (name[1] | 0x20) == 'o') { |
142 | #ifdef SIGIO | 160 | # ifdef SIGIO |
143 | if (!name[2]) | 161 | if (!name[2]) |
144 | return SIGIO; | 162 | return SIGIO; |
145 | #endif | 163 | # endif |
146 | #ifdef SIGIOT | 164 | # ifdef SIGIOT |
147 | if ((name[2] | 0x20) == 't' && !name[3]) | 165 | if ((name[2] | 0x20) == 't' && !name[3]) |
148 | return SIGIOT; | 166 | return SIGIOT; |
149 | #endif | 167 | # endif |
150 | } | 168 | } |
169 | # endif | ||
170 | #endif | ||
171 | |||
172 | #if ENABLE_FEATURE_RTMINMAX | ||
173 | # if defined(SIGRTMIN) && defined(SIGRTMAX) | ||
174 | /* libc may use some rt sigs for pthreads and therefore "remap" SIGRTMIN/MAX, | ||
175 | * but we want to use "raw" SIGRTMIN/MAX. Underscored names, if exist, provide | ||
176 | * them. If they don't exist, fall back to non-underscored ones: */ | ||
177 | # if !defined(__SIGRTMIN) | ||
178 | # define __SIGRTMIN SIGRTMIN | ||
179 | # endif | ||
180 | # if !defined(__SIGRTMAX) | ||
181 | # define __SIGRTMAX SIGRTMAX | ||
182 | # endif | ||
183 | if (strncasecmp(name, "RTMIN", 5) == 0) { | ||
184 | if (!name[5]) | ||
185 | return __SIGRTMIN; | ||
186 | if (name[5] == '+') { | ||
187 | i = bb_strtou(name + 6, NULL, 10); | ||
188 | if (!errno && i <= __SIGRTMAX - __SIGRTMIN) | ||
189 | return __SIGRTMIN + i; | ||
190 | } | ||
191 | } | ||
192 | else if (strncasecmp(name, "RTMAX", 5) == 0) { | ||
193 | if (!name[5]) | ||
194 | return __SIGRTMAX; | ||
195 | if (name[5] == '-') { | ||
196 | i = bb_strtou(name + 6, NULL, 10); | ||
197 | if (!errno && i <= __SIGRTMAX - __SIGRTMIN) | ||
198 | return __SIGRTMAX - i; | ||
199 | } | ||
200 | } | ||
201 | # endif | ||
151 | #endif | 202 | #endif |
152 | 203 | ||
153 | return -1; | 204 | return -1; |
@@ -175,6 +226,11 @@ void FAST_FUNC print_signames(void) | |||
175 | for (signo = 1; signo < ARRAY_SIZE(signals); signo++) { | 226 | for (signo = 1; signo < ARRAY_SIZE(signals); signo++) { |
176 | const char *name = signals[signo]; | 227 | const char *name = signals[signo]; |
177 | if (name[0]) | 228 | if (name[0]) |
178 | puts(name); | 229 | printf("%2u) %s\n", signo, name); |
179 | } | 230 | } |
231 | #if ENABLE_FEATURE_RTMINMAX | ||
232 | # ifdef __SIGRTMAX | ||
233 | printf("%2u) %s\n", __SIGRTMAX, "RTMAX"); | ||
234 | # endif | ||
235 | #endif | ||
180 | } | 236 | } |
diff --git a/libbb/unicode.c b/libbb/unicode.c index 70c6abe00..cf0c6bed9 100644 --- a/libbb/unicode.c +++ b/libbb/unicode.c | |||
@@ -1005,8 +1005,11 @@ static char* FAST_FUNC unicode_conv_to_printable2(uni_stat_t *stats, const char | |||
1005 | d++; | 1005 | d++; |
1006 | } | 1006 | } |
1007 | } | 1007 | } |
1008 | if (stats) | 1008 | if (stats) { |
1009 | stats->byte_count = stats->unicode_count = (d - dst); | 1009 | stats->byte_count = (d - dst); |
1010 | stats->unicode_count = (d - dst); | ||
1011 | stats->unicode_width = (d - dst); | ||
1012 | } | ||
1010 | return dst; | 1013 | return dst; |
1011 | } | 1014 | } |
1012 | 1015 | ||
diff --git a/libbb/update_passwd.c b/libbb/update_passwd.c index dc5029223..a30af6f72 100644 --- a/libbb/update_passwd.c +++ b/libbb/update_passwd.c | |||
@@ -58,7 +58,7 @@ static void check_selinux_update_passwd(const char *username) | |||
58 | 6) delete a user from a group: update_passwd(FILE, GROUP, NULL, MEMBER) | 58 | 6) delete a user from a group: update_passwd(FILE, GROUP, NULL, MEMBER) |
59 | only if CONFIG_FEATURE_DEL_USER_FROM_GROUP=y and member != NULL | 59 | only if CONFIG_FEATURE_DEL_USER_FROM_GROUP=y and member != NULL |
60 | 60 | ||
61 | 7) change user's passord: update_passwd(FILE, USER, NEW_PASSWD, NULL) | 61 | 7) change user's password: update_passwd(FILE, USER, NEW_PASSWD, NULL) |
62 | only if CONFIG_PASSWD=y and applet_name[0] == 'p' like in passwd | 62 | only if CONFIG_PASSWD=y and applet_name[0] == 'p' like in passwd |
63 | or if CONFIG_CHPASSWD=y and applet_name[0] == 'c' like in chpasswd | 63 | or if CONFIG_CHPASSWD=y and applet_name[0] == 'c' like in chpasswd |
64 | 64 | ||
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index 07504b75b..a02a504b0 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c | |||
@@ -234,7 +234,7 @@ static int wh_helper(int value, int def_val, const char *env_name, int *err) | |||
234 | char *s = getenv(env_name); | 234 | char *s = getenv(env_name); |
235 | if (s) { | 235 | if (s) { |
236 | value = atoi(s); | 236 | value = atoi(s); |
237 | /* If LINES/COLUMNS are set, pretent that there is | 237 | /* If LINES/COLUMNS are set, pretend that there is |
238 | * no error getting w/h, this prevents some ugly | 238 | * no error getting w/h, this prevents some ugly |
239 | * cursor tricks by our callers */ | 239 | * cursor tricks by our callers */ |
240 | *err = 0; | 240 | *err = 0; |
diff --git a/libpwdgrp/pwd_grp_internal.c b/libpwdgrp/pwd_grp_internal.c index 04e436fae..d6483be84 100644 --- a/libpwdgrp/pwd_grp_internal.c +++ b/libpwdgrp/pwd_grp_internal.c | |||
@@ -37,12 +37,12 @@ int GETXXKEY_R_FUNC(GETXXKEY_R_KEYTYPE key, | |||
37 | while (1) { | 37 | while (1) { |
38 | rv = bb__pgsreader(GETXXKEY_R_PARSER, resultbuf, buffer, buflen, stream); | 38 | rv = bb__pgsreader(GETXXKEY_R_PARSER, resultbuf, buffer, buflen, stream); |
39 | if (!rv) { | 39 | if (!rv) { |
40 | if (GETXXKEY_R_TEST(resultbuf)) { /* Found key? */ | 40 | if (GETXXKEY_R_TEST(resultbuf)) { /* found key? */ |
41 | *result = resultbuf; | 41 | *result = resultbuf; |
42 | break; | 42 | break; |
43 | } | 43 | } |
44 | } else { | 44 | } else { |
45 | if (rv == ENOENT) { /* end-of-file encountered. */ | 45 | if (rv == ENOENT) { /* EOF encountered */ |
46 | rv = 0; | 46 | rv = 0; |
47 | } | 47 | } |
48 | break; | 48 | break; |
diff --git a/loginutils/deluser.c b/loginutils/deluser.c index 08ca266d0..47a10fe14 100644 --- a/loginutils/deluser.c +++ b/loginutils/deluser.c | |||
@@ -14,41 +14,90 @@ | |||
14 | int deluser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 14 | int deluser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
15 | int deluser_main(int argc, char **argv) | 15 | int deluser_main(int argc, char **argv) |
16 | { | 16 | { |
17 | if (argc != 2 | 17 | /* User or group name */ |
18 | && (!ENABLE_FEATURE_DEL_USER_FROM_GROUP | 18 | char *name; |
19 | || applet_name[3] != 'g' | 19 | /* Username (non-NULL only in "delgroup USER GROUP" case) */ |
20 | || argc != 3) | 20 | char *member; |
21 | ) { | 21 | /* Name of passwd or group file */ |
22 | bb_show_usage(); | 22 | const char *pfile; |
23 | } | 23 | /* Name of shadow or gshadow file */ |
24 | const char *sfile; | ||
25 | /* Are we deluser or delgroup? */ | ||
26 | int do_deluser = (ENABLE_DELUSER && (!ENABLE_DELGROUP || applet_name[3] == 'u')); | ||
24 | 27 | ||
25 | if (geteuid()) | 28 | if (geteuid() != 0) |
26 | bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); | 29 | bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); |
27 | 30 | ||
28 | if (ENABLE_DELUSER && applet_name[3] == 'u') { | 31 | name = argv[1]; |
29 | /* deluser USER */ | 32 | member = NULL; |
30 | if (update_passwd(bb_path_passwd_file, argv[1], NULL, NULL) < 0) | 33 | |
31 | return EXIT_FAILURE; | 34 | switch (argc) { |
32 | if (ENABLE_FEATURE_SHADOWPASSWDS) | 35 | case 3: |
33 | if (update_passwd(bb_path_shadow_file, argv[1], NULL, NULL) < 0) | 36 | if (!ENABLE_FEATURE_DEL_USER_FROM_GROUP || do_deluser) |
34 | return EXIT_FAILURE; | 37 | break; |
35 | } else if (ENABLE_DELGROUP) { | 38 | /* It's "delgroup USER GROUP" */ |
36 | /* delgroup ... */ | 39 | member = name; |
37 | if (!ENABLE_FEATURE_DEL_USER_FROM_GROUP || argc != 3) { | 40 | name = argv[2]; |
38 | /* delgroup GROUP */ | 41 | /* Fallthrough */ |
39 | if (update_passwd(bb_path_group_file, argv[1], NULL, NULL) < 0) | 42 | |
40 | return EXIT_FAILURE; | 43 | case 2: |
44 | if (do_deluser) { | ||
45 | /* "deluser USER" */ | ||
46 | xgetpwnam(name); /* bail out if USER is wrong */ | ||
47 | pfile = bb_path_passwd_file; | ||
41 | if (ENABLE_FEATURE_SHADOWPASSWDS) | 48 | if (ENABLE_FEATURE_SHADOWPASSWDS) |
42 | if (update_passwd(bb_path_gshadow_file, argv[1], NULL, NULL) < 0) | 49 | sfile = bb_path_shadow_file; |
43 | return EXIT_FAILURE; | ||
44 | } else { | 50 | } else { |
45 | /* delgroup USER GROUP */ | 51 | struct group *gr; |
46 | if (update_passwd(bb_path_group_file, argv[2], NULL, argv[1]) < 0) | 52 | do_delgroup: |
47 | return EXIT_FAILURE; | 53 | /* "delgroup GROUP" or "delgroup USER GROUP" */ |
54 | if (do_deluser < 0) { /* delgroup after deluser? */ | ||
55 | gr = getgrnam(name); | ||
56 | if (!gr) | ||
57 | return EXIT_SUCCESS; | ||
58 | } else { | ||
59 | gr = xgetgrnam(name); /* bail out if GROUP is wrong */ | ||
60 | } | ||
61 | if (!member) { | ||
62 | /* "delgroup GROUP" */ | ||
63 | struct passwd *pw; | ||
64 | struct passwd pwent; | ||
65 | /* Check if the group is in use */ | ||
66 | #define passwd_buf bb_common_bufsiz1 | ||
67 | while (!getpwent_r(&pwent, passwd_buf, sizeof(passwd_buf), &pw)) { | ||
68 | if (pwent.pw_gid == gr->gr_gid) | ||
69 | bb_error_msg_and_die("'%s' still has '%s' as their primary group!", pwent.pw_name, name); | ||
70 | } | ||
71 | //endpwent(); | ||
72 | } | ||
73 | pfile = bb_path_group_file; | ||
48 | if (ENABLE_FEATURE_SHADOWPASSWDS) | 74 | if (ENABLE_FEATURE_SHADOWPASSWDS) |
49 | if (update_passwd(bb_path_gshadow_file, argv[2], NULL, argv[1]) < 0) | 75 | sfile = bb_path_gshadow_file; |
50 | return EXIT_FAILURE; | 76 | } |
77 | |||
78 | /* Modify pfile, then sfile */ | ||
79 | do { | ||
80 | if (update_passwd(pfile, name, NULL, member) == -1) | ||
81 | return EXIT_FAILURE; | ||
82 | if (ENABLE_FEATURE_SHADOWPASSWDS) { | ||
83 | pfile = sfile; | ||
84 | sfile = NULL; | ||
85 | } | ||
86 | } while (ENABLE_FEATURE_SHADOWPASSWDS && pfile); | ||
87 | |||
88 | if (ENABLE_DELGROUP && do_deluser > 0) { | ||
89 | /* "deluser USER" also should try to delete | ||
90 | * same-named group. IOW: do "delgroup USER" | ||
91 | */ | ||
92 | // On debian deluser is a perl script that calls userdel. | ||
93 | // From man userdel: | ||
94 | // If USERGROUPS_ENAB is defined to yes in /etc/login.defs, userdel will | ||
95 | // delete the group with the same name as the user. | ||
96 | do_deluser = -1; | ||
97 | goto do_delgroup; | ||
51 | } | 98 | } |
99 | return EXIT_SUCCESS; | ||
52 | } | 100 | } |
53 | return EXIT_SUCCESS; | 101 | /* Reached only if number of command line args is wrong */ |
102 | bb_show_usage(); | ||
54 | } | 103 | } |
diff --git a/loginutils/login.c b/loginutils/login.c index 9a624df9a..c285b45a1 100644 --- a/loginutils/login.c +++ b/loginutils/login.c | |||
@@ -217,6 +217,7 @@ int login_main(int argc UNUSED_PARAM, char **argv) | |||
217 | const char *failed_msg; | 217 | const char *failed_msg; |
218 | struct passwd pwdstruct; | 218 | struct passwd pwdstruct; |
219 | char pwdbuf[256]; | 219 | char pwdbuf[256]; |
220 | char **pamenv; | ||
220 | #endif | 221 | #endif |
221 | 222 | ||
222 | username[0] = '\0'; | 223 | username[0] = '\0'; |
@@ -400,6 +401,16 @@ int login_main(int argc UNUSED_PARAM, char **argv) | |||
400 | (!(opt & LOGIN_OPT_p) * SETUP_ENV_CLEARENV) + SETUP_ENV_CHANGEENV, | 401 | (!(opt & LOGIN_OPT_p) * SETUP_ENV_CLEARENV) + SETUP_ENV_CHANGEENV, |
401 | pw); | 402 | pw); |
402 | 403 | ||
404 | #if ENABLE_PAM | ||
405 | /* Modules such as pam_env will setup the PAM environment, | ||
406 | * which should be copied into the new environment. */ | ||
407 | pamenv = pam_getenvlist(pamh); | ||
408 | if (pamenv) while (*pamenv) { | ||
409 | putenv(*pamenv); | ||
410 | pamenv++; | ||
411 | } | ||
412 | #endif | ||
413 | |||
403 | motd(); | 414 | motd(); |
404 | 415 | ||
405 | if (pw->pw_uid == 0) | 416 | if (pw->pw_uid == 0) |
diff --git a/loginutils/su.c b/loginutils/su.c index 5bec4bc8b..db303af6d 100644 --- a/loginutils/su.c +++ b/loginutils/su.c | |||
@@ -8,6 +8,16 @@ | |||
8 | #include "libbb.h" | 8 | #include "libbb.h" |
9 | #include <syslog.h> | 9 | #include <syslog.h> |
10 | 10 | ||
11 | //usage:#define su_trivial_usage | ||
12 | //usage: "[OPTIONS] [-] [USER]" | ||
13 | //usage:#define su_full_usage "\n\n" | ||
14 | //usage: "Run shell under USER (by default, root)\n" | ||
15 | //usage: "\nOptions:" | ||
16 | //usage: "\n -,-l Clear environment, run shell as login shell" | ||
17 | //usage: "\n -p,-m Do not set new $HOME, $SHELL, $USER, $LOGNAME" | ||
18 | //usage: "\n -c CMD Command to pass to 'sh -c'" | ||
19 | //usage: "\n -s SH Shell to use instead of user's default" | ||
20 | |||
11 | #if ENABLE_FEATURE_SU_CHECKS_SHELLS | 21 | #if ENABLE_FEATURE_SU_CHECKS_SHELLS |
12 | /* Return 1 if SHELL is a restricted shell (one not returned by | 22 | /* Return 1 if SHELL is a restricted shell (one not returned by |
13 | * getusershell), else 0, meaning it is a standard shell. */ | 23 | * getusershell), else 0, meaning it is a standard shell. */ |
@@ -42,7 +52,9 @@ int su_main(int argc UNUSED_PARAM, char **argv) | |||
42 | struct passwd *pw; | 52 | struct passwd *pw; |
43 | uid_t cur_uid = getuid(); | 53 | uid_t cur_uid = getuid(); |
44 | const char *tty; | 54 | const char *tty; |
55 | #if ENABLE_FEATURE_UTMP | ||
45 | char user_buf[64]; | 56 | char user_buf[64]; |
57 | #endif | ||
46 | const char *old_user; | 58 | const char *old_user; |
47 | 59 | ||
48 | flags = getopt32(argv, "mplc:s:", &opt_command, &opt_shell); | 60 | flags = getopt32(argv, "mplc:s:", &opt_command, &opt_shell); |
diff --git a/mailutils/mail.c b/mailutils/mail.c index 9b4bebce5..44957016f 100644 --- a/mailutils/mail.c +++ b/mailutils/mail.c | |||
@@ -75,13 +75,16 @@ void FAST_FUNC launch_helper(const char **argv) | |||
75 | atexit(kill_helper); | 75 | atexit(kill_helper); |
76 | } | 76 | } |
77 | 77 | ||
78 | const FAST_FUNC char *command(const char *fmt, const char *param) | 78 | char* FAST_FUNC send_mail_command(const char *fmt, const char *param) |
79 | { | 79 | { |
80 | const char *msg = fmt; | 80 | char *msg; |
81 | if (timeout) | 81 | if (timeout) |
82 | alarm(timeout); | 82 | alarm(timeout); |
83 | if (msg) { | 83 | msg = (char*)fmt; |
84 | if (fmt) { | ||
84 | msg = xasprintf(fmt, param); | 85 | msg = xasprintf(fmt, param); |
86 | if (verbose) | ||
87 | bb_error_msg("send:'%s'", msg); | ||
85 | printf("%s\r\n", msg); | 88 | printf("%s\r\n", msg); |
86 | } | 89 | } |
87 | fflush_all(); | 90 | fflush_all(); |
@@ -90,7 +93,7 @@ const FAST_FUNC char *command(const char *fmt, const char *param) | |||
90 | 93 | ||
91 | // NB: parse_url can modify url[] (despite const), but only if '@' is there | 94 | // NB: parse_url can modify url[] (despite const), but only if '@' is there |
92 | /* | 95 | /* |
93 | static char FAST_FUNC *parse_url(char *url, char **user, char **pass) | 96 | static char* FAST_FUNC parse_url(char *url, char **user, char **pass) |
94 | { | 97 | { |
95 | // parse [user[:pass]@]host | 98 | // parse [user[:pass]@]host |
96 | // return host | 99 | // return host |
diff --git a/mailutils/mail.h b/mailutils/mail.h index e0048fbfa..d1d783055 100644 --- a/mailutils/mail.h +++ b/mailutils/mail.h | |||
@@ -1,7 +1,16 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * helper routines | ||
4 | * | ||
5 | * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com> | ||
6 | * | ||
7 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
8 | */ | ||
1 | 9 | ||
2 | struct globals { | 10 | struct globals { |
3 | pid_t helper_pid; | 11 | pid_t helper_pid; |
4 | unsigned timeout; | 12 | unsigned timeout; |
13 | unsigned verbose; | ||
5 | unsigned opts; | 14 | unsigned opts; |
6 | char *user; | 15 | char *user; |
7 | char *pass; | 16 | char *pass; |
@@ -12,6 +21,7 @@ struct globals { | |||
12 | 21 | ||
13 | #define G (*ptr_to_globals) | 22 | #define G (*ptr_to_globals) |
14 | #define timeout (G.timeout ) | 23 | #define timeout (G.timeout ) |
24 | #define verbose (G.verbose ) | ||
15 | #define opts (G.opts ) | 25 | #define opts (G.opts ) |
16 | //#define user (G.user ) | 26 | //#define user (G.user ) |
17 | //#define pass (G.pass ) | 27 | //#define pass (G.pass ) |
@@ -26,9 +36,9 @@ struct globals { | |||
26 | 36 | ||
27 | //char FAST_FUNC *parse_url(char *url, char **user, char **pass); | 37 | //char FAST_FUNC *parse_url(char *url, char **user, char **pass); |
28 | 38 | ||
29 | void FAST_FUNC launch_helper(const char **argv); | 39 | void launch_helper(const char **argv) FAST_FUNC; |
30 | void FAST_FUNC get_cred_or_die(int fd); | 40 | void get_cred_or_die(int fd) FAST_FUNC; |
31 | 41 | ||
32 | const FAST_FUNC char *command(const char *fmt, const char *param); | 42 | char *send_mail_command(const char *fmt, const char *param) FAST_FUNC; |
33 | 43 | ||
34 | void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol); | 44 | void encode_base64(char *fname, const char *text, const char *eol) FAST_FUNC; |
diff --git a/mailutils/mime.c b/mailutils/mime.c index 682cf4536..1e393ed31 100644 --- a/mailutils/mime.c +++ b/mailutils/mime.c | |||
@@ -99,6 +99,28 @@ Content-Transfer-Encoding: 7bit | |||
99 | ...random junk added by mailing list robots and such... | 99 | ...random junk added by mailing list robots and such... |
100 | */ | 100 | */ |
101 | 101 | ||
102 | /* man makemime: | ||
103 | |||
104 | * -c TYPE: create a (non-multipart) MIME section with Content-Type: TYPE | ||
105 | * makemime -c TYPE [-e ENCODING] [-o OUTFILE] [-C CHARSET] [-N NAME] [-a HEADER...] FILE | ||
106 | * The -C option sets the MIME charset attribute for text/plain content. | ||
107 | * The -N option sets the name attribute for Content-Type: | ||
108 | * Encoding must be one of the following: 7bit, 8bit, quoted-printable, or base64. | ||
109 | |||
110 | * -m multipart/TYPE: create a multipart MIME collection with Content-Type: multipart/TYPE | ||
111 | * makemime -m multipart/TYPE [-e ENCODING] [-o OUTFILE] [-a HEADER...] FILE | ||
112 | * Type must be either "multipart/mixed", "multipart/alternative", or some other MIME multipart content type. | ||
113 | * Additionally, encoding can only be "7bit" or "8bit", and will default to "8bit" if not specified. | ||
114 | * Finally, filename must be a MIME-formatted section, NOT a regular file. | ||
115 | * The -m option creates an initial multipart MIME collection, that contains only one MIME section, taken from filename. | ||
116 | * The collection is written to standard output, or the pipe or to outputfile. | ||
117 | |||
118 | * -j FILE1: add a section to a multipart MIME collection | ||
119 | * makemime -j FILE1 [-o OUTFILE] FILE2 | ||
120 | * FILE1 must be a MIME collection that was previously created by the -m option. | ||
121 | * FILE2 must be a MIME section that was previously created by the -c option. | ||
122 | * The -j options adds the MIME section in FILE2 to the MIME collection in FILE1. | ||
123 | */ | ||
102 | int makemime_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 124 | int makemime_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
103 | int makemime_main(int argc UNUSED_PARAM, char **argv) | 125 | int makemime_main(int argc UNUSED_PARAM, char **argv) |
104 | { | 126 | { |
@@ -107,14 +129,14 @@ int makemime_main(int argc UNUSED_PARAM, char **argv) | |||
107 | #define boundary opt_output | 129 | #define boundary opt_output |
108 | 130 | ||
109 | enum { | 131 | enum { |
110 | OPT_c = 1 << 0, // Content-Type: | 132 | OPT_c = 1 << 0, // create (non-multipart) section |
111 | OPT_e = 1 << 1, // Content-Transfer-Encoding. Ignored. Assumed base64 | 133 | OPT_e = 1 << 1, // Content-Transfer-Encoding. Ignored. Assumed base64 |
112 | OPT_o = 1 << 2, // output to | 134 | OPT_o = 1 << 2, // output to |
113 | OPT_C = 1 << 3, // charset | 135 | OPT_C = 1 << 3, // charset |
114 | OPT_N = 1 << 4, // COMPAT | 136 | OPT_N = 1 << 4, // COMPAT |
115 | OPT_a = 1 << 5, // additional headers | 137 | OPT_a = 1 << 5, // additional headers |
116 | OPT_m = 1 << 6, // COMPAT | 138 | //OPT_m = 1 << 6, // create mutipart section |
117 | OPT_j = 1 << 7, // COMPAT | 139 | //OPT_j = 1 << 7, // join section to multipart section |
118 | }; | 140 | }; |
119 | 141 | ||
120 | INIT_G(); | 142 | INIT_G(); |
@@ -122,8 +144,8 @@ int makemime_main(int argc UNUSED_PARAM, char **argv) | |||
122 | // parse options | 144 | // parse options |
123 | opt_complementary = "a::"; | 145 | opt_complementary = "a::"; |
124 | opts = getopt32(argv, | 146 | opts = getopt32(argv, |
125 | "c:e:o:C:N:a:m:j:", | 147 | "c:e:o:C:N:a", //:m:j:", |
126 | &G.content_type, NULL, &opt_output, &G.opt_charset, NULL, &opt_headers, NULL, NULL | 148 | &G.content_type, NULL, &opt_output, &G.opt_charset, NULL, &opt_headers //, NULL, NULL |
127 | ); | 149 | ); |
128 | //argc -= optind; | 150 | //argc -= optind; |
129 | argv += optind; | 151 | argv += optind; |
diff --git a/mailutils/popmaildir.c b/mailutils/popmaildir.c index 77ec71129..6b733441f 100644 --- a/mailutils/popmaildir.c +++ b/mailutils/popmaildir.c | |||
@@ -14,9 +14,10 @@ | |||
14 | 14 | ||
15 | static void pop3_checkr(const char *fmt, const char *param, char **ret) | 15 | static void pop3_checkr(const char *fmt, const char *param, char **ret) |
16 | { | 16 | { |
17 | const char *msg = command(fmt, param); | 17 | char *msg = send_mail_command(fmt, param); |
18 | char *answer = xmalloc_fgetline(stdin); | 18 | char *answer = xmalloc_fgetline(stdin); |
19 | if (answer && '+' == answer[0]) { | 19 | if (answer && '+' == answer[0]) { |
20 | free(msg); | ||
20 | if (timeout) | 21 | if (timeout) |
21 | alarm(0); | 22 | alarm(0); |
22 | if (ret) { | 23 | if (ret) { |
@@ -27,7 +28,7 @@ static void pop3_checkr(const char *fmt, const char *param, char **ret) | |||
27 | free(answer); | 28 | free(answer); |
28 | return; | 29 | return; |
29 | } | 30 | } |
30 | bb_error_msg_and_die("%s failed: %s", msg, answer); | 31 | bb_error_msg_and_die("%s failed, reply was: %s", msg, answer); |
31 | } | 32 | } |
32 | 33 | ||
33 | static void pop3_check(const char *fmt, const char *param) | 34 | static void pop3_check(const char *fmt, const char *param) |
diff --git a/mailutils/sendmail.c b/mailutils/sendmail.c index ec97cf8af..8096288ef 100644 --- a/mailutils/sendmail.c +++ b/mailutils/sendmail.c | |||
@@ -6,6 +6,38 @@ | |||
6 | * | 6 | * |
7 | * Licensed under GPLv2, see file LICENSE in this source tree. | 7 | * Licensed under GPLv2, see file LICENSE in this source tree. |
8 | */ | 8 | */ |
9 | |||
10 | //usage:#define sendmail_trivial_usage | ||
11 | //usage: "[OPTIONS] [RECIPIENT_EMAIL]..." | ||
12 | //usage:#define sendmail_full_usage "\n\n" | ||
13 | //usage: "Read email from stdin and send it\n" | ||
14 | //usage: "\nStandard options:" | ||
15 | //usage: "\n -t Read additional recipients from message body" | ||
16 | //usage: "\n -f SENDER Sender (required)" | ||
17 | //usage: "\n -o OPTIONS Various options. -oi implied, others are ignored" | ||
18 | //usage: "\n -i -oi synonym. implied and ignored" | ||
19 | //usage: "\n" | ||
20 | //usage: "\nBusybox specific options:" | ||
21 | //usage: "\n -v Verbose" | ||
22 | //usage: "\n -w SECS Network timeout" | ||
23 | //usage: "\n -H 'PROG ARGS' Run connection helper" | ||
24 | //usage: "\n Examples:" | ||
25 | //usage: "\n -H 'exec openssl s_client -quiet -tls1 -starttls smtp" | ||
26 | //usage: "\n -connect smtp.gmail.com:25' <email.txt" | ||
27 | //usage: "\n [4<username_and_passwd.txt | -au<username> -ap<password>]" | ||
28 | //usage: "\n -H 'exec openssl s_client -quiet -tls1" | ||
29 | //usage: "\n -connect smtp.gmail.com:465' <email.txt" | ||
30 | //usage: "\n [4<username_and_passwd.txt | -au<username> -ap<password>]" | ||
31 | //usage: "\n -S HOST[:PORT] Server" | ||
32 | //usage: "\n -au<username> Username for AUTH LOGIN" | ||
33 | //usage: "\n -ap<password> Password for AUTH LOGIN" | ||
34 | //usage: "\n -am<method> Authentication method. Ignored. LOGIN is implied" | ||
35 | //usage: "\n" | ||
36 | //usage: "\nOther options are silently ignored; -oi -t is implied" | ||
37 | //usage: IF_MAKEMIME( | ||
38 | //usage: "\nUse makemime applet to create message with attachments" | ||
39 | //usage: ) | ||
40 | |||
9 | #include "libbb.h" | 41 | #include "libbb.h" |
10 | #include "mail.h" | 42 | #include "mail.h" |
11 | 43 | ||
@@ -13,23 +45,35 @@ | |||
13 | // set to 0 to not limit | 45 | // set to 0 to not limit |
14 | #define MAX_HEADERS 256 | 46 | #define MAX_HEADERS 256 |
15 | 47 | ||
48 | static void send_r_n(const char *s) | ||
49 | { | ||
50 | if (verbose) | ||
51 | bb_error_msg("send:'%s'", s); | ||
52 | printf("%s\r\n", s); | ||
53 | } | ||
54 | |||
16 | static int smtp_checkp(const char *fmt, const char *param, int code) | 55 | static int smtp_checkp(const char *fmt, const char *param, int code) |
17 | { | 56 | { |
18 | char *answer; | 57 | char *answer; |
19 | const char *msg = command(fmt, param); | 58 | char *msg = send_mail_command(fmt, param); |
20 | // read stdin | 59 | // read stdin |
21 | // if the string has a form \d\d\d- -- read next string. E.g. EHLO response | 60 | // if the string has a form NNN- -- read next string. E.g. EHLO response |
22 | // parse first bytes to a number | 61 | // parse first bytes to a number |
23 | // if code = -1 then just return this number | 62 | // if code = -1 then just return this number |
24 | // if code != -1 then checks whether the number equals the code | 63 | // if code != -1 then checks whether the number equals the code |
25 | // if not equal -> die saying msg | 64 | // if not equal -> die saying msg |
26 | while ((answer = xmalloc_fgetline(stdin)) != NULL) | 65 | while ((answer = xmalloc_fgetline(stdin)) != NULL) { |
66 | if (verbose) | ||
67 | bb_error_msg("recv:'%.*s' %d", (int)(strchrnul(answer, '\r') - answer), answer, verbose); | ||
27 | if (strlen(answer) <= 3 || '-' != answer[3]) | 68 | if (strlen(answer) <= 3 || '-' != answer[3]) |
28 | break; | 69 | break; |
70 | free(answer); | ||
71 | } | ||
29 | if (answer) { | 72 | if (answer) { |
30 | int n = atoi(answer); | 73 | int n = atoi(answer); |
31 | if (timeout) | 74 | if (timeout) |
32 | alarm(0); | 75 | alarm(0); |
76 | free(msg); | ||
33 | free(answer); | 77 | free(answer); |
34 | if (-1 == code || n == code) | 78 | if (-1 == code || n == code) |
35 | return n; | 79 | return n; |
@@ -86,6 +130,7 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv) | |||
86 | OPT_H = 1 << 5, // use external connection helper | 130 | OPT_H = 1 << 5, // use external connection helper |
87 | OPT_S = 1 << 6, // specify connection string | 131 | OPT_S = 1 << 6, // specify connection string |
88 | OPT_a = 1 << 7, // authentication tokens | 132 | OPT_a = 1 << 7, // authentication tokens |
133 | OPT_v = 1 << 8, // verbosity | ||
89 | }; | 134 | }; |
90 | 135 | ||
91 | // init global variables | 136 | // init global variables |
@@ -96,12 +141,13 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv) | |||
96 | G.fp0 = xfdopen_for_read(3); | 141 | G.fp0 = xfdopen_for_read(3); |
97 | 142 | ||
98 | // parse options | 143 | // parse options |
99 | // -f is required. -H and -S are mutually exclusive | 144 | // -v is a counter, -f is required. -H and -S are mutually exclusive, -a is a list |
100 | opt_complementary = "f:w+:H--S:S--H:a::"; | 145 | opt_complementary = "vv:f:w+:H--S:S--H:a::"; |
101 | // N.B. since -H and -S are mutually exclusive they do not interfere in opt_connect | 146 | // N.B. since -H and -S are mutually exclusive they do not interfere in opt_connect |
102 | // -a is for ssmtp (http://downloads.openwrt.org/people/nico/man/man8/ssmtp.8.html) compatibility, | 147 | // -a is for ssmtp (http://downloads.openwrt.org/people/nico/man/man8/ssmtp.8.html) compatibility, |
103 | // it is still under development. | 148 | // it is still under development. |
104 | opts = getopt32(argv, "tf:o:iw:H:S:a::", &opt_from, NULL, &timeout, &opt_connect, &opt_connect, &list); | 149 | opts = getopt32(argv, "tf:o:iw:H:S:a::v", &opt_from, NULL, |
150 | &timeout, &opt_connect, &opt_connect, &list, &verbose); | ||
105 | //argc -= optind; | 151 | //argc -= optind; |
106 | argv += optind; | 152 | argv += optind; |
107 | 153 | ||
@@ -214,7 +260,7 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv) | |||
214 | if ('.' == s[0] /*&& '\0' == s[1] */) | 260 | if ('.' == s[0] /*&& '\0' == s[1] */) |
215 | printf("."); | 261 | printf("."); |
216 | // dump read line | 262 | // dump read line |
217 | printf("%s\r\n", s); | 263 | send_r_n(s); |
218 | free(s); | 264 | free(s); |
219 | continue; | 265 | continue; |
220 | } | 266 | } |
@@ -261,14 +307,14 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv) | |||
261 | goto bail; | 307 | goto bail; |
262 | // dump the headers | 308 | // dump the headers |
263 | while (list) { | 309 | while (list) { |
264 | printf("%s\r\n", (char *) llist_pop(&list)); | 310 | send_r_n((char *) llist_pop(&list)); |
265 | } | 311 | } |
266 | // stop analyzing headers | 312 | // stop analyzing headers |
267 | code++; | 313 | code++; |
268 | // N.B. !s means: we read nothing, and nothing to be read in the future. | 314 | // N.B. !s means: we read nothing, and nothing to be read in the future. |
269 | // just dump empty line and break the loop | 315 | // just dump empty line and break the loop |
270 | if (!s) { | 316 | if (!s) { |
271 | puts("\r"); | 317 | send_r_n(""); |
272 | break; | 318 | break; |
273 | } | 319 | } |
274 | // go dump message body | 320 | // go dump message body |
diff --git a/miscutils/bbconfig.c b/miscutils/bbconfig.c index 286077168..7c30669a3 100644 --- a/miscutils/bbconfig.c +++ b/miscutils/bbconfig.c | |||
@@ -4,7 +4,7 @@ | |||
4 | #include "libbb.h" | 4 | #include "libbb.h" |
5 | #include "bbconfigopts.h" | 5 | #include "bbconfigopts.h" |
6 | #if ENABLE_FEATURE_COMPRESS_BBCONFIG | 6 | #if ENABLE_FEATURE_COMPRESS_BBCONFIG |
7 | # include "unarchive.h" | 7 | # include "archive.h" |
8 | # include "bbconfigopts_bz2.h" | 8 | # include "bbconfigopts_bz2.h" |
9 | #endif | 9 | #endif |
10 | 10 | ||
@@ -15,7 +15,7 @@ int bbconfig_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
15 | bunzip_data *bd; | 15 | bunzip_data *bd; |
16 | int i = start_bunzip(&bd, | 16 | int i = start_bunzip(&bd, |
17 | /* src_fd: */ -1, | 17 | /* src_fd: */ -1, |
18 | /* inbuf: */ (void *)bbconfig_config_bz2, | 18 | /* inbuf: */ bbconfig_config_bz2, |
19 | /* len: */ sizeof(bbconfig_config_bz2)); | 19 | /* len: */ sizeof(bbconfig_config_bz2)); |
20 | /* read_bunzip can longjmp to start_bunzip, and ultimately | 20 | /* read_bunzip can longjmp to start_bunzip, and ultimately |
21 | * end up here with i != 0 on read data errors! Not trivial */ | 21 | * end up here with i != 0 on read data errors! Not trivial */ |
diff --git a/miscutils/chat.c b/miscutils/chat.c index 8b151fda4..d8370a963 100644 --- a/miscutils/chat.c +++ b/miscutils/chat.c | |||
@@ -175,23 +175,24 @@ int chat_main(int argc UNUSED_PARAM, char **argv) | |||
175 | llist_add_to_end(&aborts, arg); | 175 | llist_add_to_end(&aborts, arg); |
176 | #if ENABLE_FEATURE_CHAT_CLR_ABORT | 176 | #if ENABLE_FEATURE_CHAT_CLR_ABORT |
177 | } else if (DIR_CLR_ABORT == key) { | 177 | } else if (DIR_CLR_ABORT == key) { |
178 | llist_t *l; | ||
178 | // remove the string from abort conditions | 179 | // remove the string from abort conditions |
179 | // N.B. gotta refresh maximum length too... | 180 | // N.B. gotta refresh maximum length too... |
180 | #if ENABLE_FEATURE_CHAT_VAR_ABORT_LEN | 181 | # if ENABLE_FEATURE_CHAT_VAR_ABORT_LEN |
181 | max_abort_len = 0; | 182 | max_abort_len = 0; |
182 | #endif | 183 | # endif |
183 | for (llist_t *l = aborts; l; l = l->link) { | 184 | for (l = aborts; l; l = l->link) { |
184 | #if ENABLE_FEATURE_CHAT_VAR_ABORT_LEN | 185 | # if ENABLE_FEATURE_CHAT_VAR_ABORT_LEN |
185 | size_t len = strlen(l->data); | 186 | size_t len = strlen(l->data); |
186 | #endif | 187 | # endif |
187 | if (!strcmp(arg, l->data)) { | 188 | if (strcmp(arg, l->data) == 0) { |
188 | llist_unlink(&aborts, l); | 189 | llist_unlink(&aborts, l); |
189 | continue; | 190 | continue; |
190 | } | 191 | } |
191 | #if ENABLE_FEATURE_CHAT_VAR_ABORT_LEN | 192 | # if ENABLE_FEATURE_CHAT_VAR_ABORT_LEN |
192 | if (len > max_abort_len) | 193 | if (len > max_abort_len) |
193 | max_abort_len = len; | 194 | max_abort_len = len; |
194 | #endif | 195 | # endif |
195 | } | 196 | } |
196 | #endif | 197 | #endif |
197 | } else if (DIR_TIMEOUT == key) { | 198 | } else if (DIR_TIMEOUT == key) { |
diff --git a/miscutils/chrt.c b/miscutils/chrt.c index c40277b39..1c6737a3c 100644 --- a/miscutils/chrt.c +++ b/miscutils/chrt.c | |||
@@ -53,23 +53,25 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) | |||
53 | const char *current_new; | 53 | const char *current_new; |
54 | int policy = SCHED_RR; | 54 | int policy = SCHED_RR; |
55 | 55 | ||
56 | /* at least 1 arg; only one policy accepted */ | 56 | /* only one policy accepted */ |
57 | opt_complementary = "-1:r--fo:f--ro:r--fo"; | 57 | opt_complementary = "r--fo:f--ro:o--rf"; |
58 | opt = getopt32(argv, "+mprfo"); | 58 | opt = getopt32(argv, "+mprfo"); |
59 | if (opt & OPT_m) { /* print min/max and exit */ | ||
60 | show_min_max(SCHED_FIFO); | ||
61 | show_min_max(SCHED_RR); | ||
62 | show_min_max(SCHED_OTHER); | ||
63 | fflush_stdout_and_exit(EXIT_SUCCESS); | ||
64 | } | ||
59 | if (opt & OPT_r) | 65 | if (opt & OPT_r) |
60 | policy = SCHED_RR; | 66 | policy = SCHED_RR; |
61 | if (opt & OPT_f) | 67 | if (opt & OPT_f) |
62 | policy = SCHED_FIFO; | 68 | policy = SCHED_FIFO; |
63 | if (opt & OPT_o) | 69 | if (opt & OPT_o) |
64 | policy = SCHED_OTHER; | 70 | policy = SCHED_OTHER; |
65 | if (opt & OPT_m) { /* print min/max */ | ||
66 | show_min_max(SCHED_FIFO); | ||
67 | show_min_max(SCHED_RR); | ||
68 | show_min_max(SCHED_OTHER); | ||
69 | fflush_stdout_and_exit(EXIT_SUCCESS); | ||
70 | } | ||
71 | 71 | ||
72 | argv += optind; | 72 | argv += optind; |
73 | if (!argv[0]) | ||
74 | bb_show_usage(); | ||
73 | if (opt & OPT_p) { | 75 | if (opt & OPT_p) { |
74 | pid_str = *argv++; | 76 | pid_str = *argv++; |
75 | if (*argv) { /* "-p <priority> <pid> [...]" */ | 77 | if (*argv) { /* "-p <priority> <pid> [...]" */ |
@@ -90,13 +92,13 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) | |||
90 | print_rt_info: | 92 | print_rt_info: |
91 | pol = sched_getscheduler(pid); | 93 | pol = sched_getscheduler(pid); |
92 | if (pol < 0) | 94 | if (pol < 0) |
93 | bb_perror_msg_and_die("can't %cet pid %d's policy", 'g', pid); | 95 | bb_perror_msg_and_die("can't %cet pid %d's policy", 'g', (int)pid); |
94 | printf("pid %d's %s scheduling policy: %s\n", | 96 | printf("pid %d's %s scheduling policy: %s\n", |
95 | pid, current_new, policies[pol].name); | 97 | pid, current_new, policies[pol].name); |
96 | if (sched_getparam(pid, &sp)) | 98 | if (sched_getparam(pid, &sp)) |
97 | bb_perror_msg_and_die("can't get pid %d's attributes", pid); | 99 | bb_perror_msg_and_die("can't get pid %d's attributes", (int)pid); |
98 | printf("pid %d's %s scheduling priority: %d\n", | 100 | printf("pid %d's %s scheduling priority: %d\n", |
99 | pid, current_new, sp.sched_priority); | 101 | (int)pid, current_new, sp.sched_priority); |
100 | if (!*argv) { | 102 | if (!*argv) { |
101 | /* Either it was just "-p <pid>", | 103 | /* Either it was just "-p <pid>", |
102 | * or it was "-p <priority> <pid>" and we came here | 104 | * or it was "-p <priority> <pid>" and we came here |
@@ -115,7 +117,7 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) | |||
115 | sp.sched_priority = xstrtou_range(priority, 0, policy != SCHED_OTHER ? 1 : 0, 99); | 117 | sp.sched_priority = xstrtou_range(priority, 0, policy != SCHED_OTHER ? 1 : 0, 99); |
116 | 118 | ||
117 | if (sched_setscheduler(pid, policy, &sp) < 0) | 119 | if (sched_setscheduler(pid, policy, &sp) < 0) |
118 | bb_perror_msg_and_die("can't %cet pid %d's policy", 's', pid); | 120 | bb_perror_msg_and_die("can't %cet pid %d's policy", 's', (int)pid); |
119 | 121 | ||
120 | if (!argv[0]) /* "-p <priority> <pid> [...]" */ | 122 | if (!argv[0]) /* "-p <priority> <pid> [...]" */ |
121 | goto print_rt_info; | 123 | goto print_rt_info; |
diff --git a/miscutils/conspy.c b/miscutils/conspy.c index 01928b35f..723b4208a 100644 --- a/miscutils/conspy.c +++ b/miscutils/conspy.c | |||
@@ -43,6 +43,9 @@ | |||
43 | #include "libbb.h" | 43 | #include "libbb.h" |
44 | #include <sys/kd.h> | 44 | #include <sys/kd.h> |
45 | 45 | ||
46 | |||
47 | #define ESC "\033" | ||
48 | |||
46 | struct screen_info { | 49 | struct screen_info { |
47 | unsigned char lines, cols, cursor_x, cursor_y; | 50 | unsigned char lines, cols, cursor_x, cursor_y; |
48 | }; | 51 | }; |
@@ -70,7 +73,7 @@ struct globals { | |||
70 | unsigned col; | 73 | unsigned col; |
71 | unsigned line; | 74 | unsigned line; |
72 | smallint curoff; // unknown:0 cursor on:-1 cursor off:1 | 75 | smallint curoff; // unknown:0 cursor on:-1 cursor off:1 |
73 | char attrbuf[sizeof("\033[0;1;5;30;40m")]; | 76 | char attrbuf[sizeof(ESC"[0;1;5;30;40m")]; |
74 | // remote console | 77 | // remote console |
75 | struct screen_info remote; | 78 | struct screen_info remote; |
76 | // saved local tty terminfo | 79 | // saved local tty terminfo |
@@ -101,7 +104,7 @@ enum { | |||
101 | static void clrscr(void) | 104 | static void clrscr(void) |
102 | { | 105 | { |
103 | // Home, clear till end of screen | 106 | // Home, clear till end of screen |
104 | fputs("\033[1;1H" "\033[J", stdout); | 107 | fputs(ESC"[1;1H" ESC"[J", stdout); |
105 | G.col = G.line = 0; | 108 | G.col = G.line = 0; |
106 | } | 109 | } |
107 | 110 | ||
@@ -109,7 +112,7 @@ static void set_cursor(int state) | |||
109 | { | 112 | { |
110 | if (G.curoff != state) { | 113 | if (G.curoff != state) { |
111 | G.curoff = state; | 114 | G.curoff = state; |
112 | fputs("\033[?25", stdout); | 115 | fputs(ESC"[?25", stdout); |
113 | bb_putchar("h?l"[1 + state]); | 116 | bb_putchar("h?l"[1 + state]); |
114 | } | 117 | } |
115 | } | 118 | } |
@@ -119,7 +122,7 @@ static void gotoxy(int col, int line) | |||
119 | if (G.col != col || G.line != line) { | 122 | if (G.col != col || G.line != line) { |
120 | G.col = col; | 123 | G.col = col; |
121 | G.line = line; | 124 | G.line = line; |
122 | printf("\033[%u;%uH", line + 1, col + 1); | 125 | printf(ESC"[%u;%uH", line + 1, col + 1); |
123 | } | 126 | } |
124 | } | 127 | } |
125 | 128 | ||
@@ -132,7 +135,7 @@ static void cleanup(int code) | |||
132 | } | 135 | } |
133 | // Reset attributes | 136 | // Reset attributes |
134 | if (!BW) | 137 | if (!BW) |
135 | fputs("\033[0m", stdout); | 138 | fputs(ESC"[0m", stdout); |
136 | bb_putchar('\n'); | 139 | bb_putchar('\n'); |
137 | if (code > 1) | 140 | if (code > 1) |
138 | kill_myself_with_sig(code); | 141 | kill_myself_with_sig(code); |
@@ -417,19 +420,19 @@ int conspy_main(int argc UNUSED_PARAM, char **argv) | |||
417 | 420 | ||
418 | if (G.remote.cursor_x < G.x) { | 421 | if (G.remote.cursor_x < G.x) { |
419 | G.x = G.remote.cursor_x; | 422 | G.x = G.remote.cursor_x; |
420 | i = 0; // force refresh | 423 | i = 0; // force refresh |
421 | } | 424 | } |
422 | if (nx > G.x) { | 425 | if (nx > G.x) { |
423 | G.x = nx; | 426 | G.x = nx; |
424 | i = 0; // force refresh | 427 | i = 0; // force refresh |
425 | } | 428 | } |
426 | if (G.remote.cursor_y < G.y) { | 429 | if (G.remote.cursor_y < G.y) { |
427 | G.y = G.remote.cursor_y; | 430 | G.y = G.remote.cursor_y; |
428 | i = 0; // force refresh | 431 | i = 0; // force refresh |
429 | } | 432 | } |
430 | if (ny > G.y) { | 433 | if (ny > G.y) { |
431 | G.y = ny; | 434 | G.y = ny; |
432 | i = 0; // force refresh | 435 | i = 0; // force refresh |
433 | } | 436 | } |
434 | } | 437 | } |
435 | 438 | ||
diff --git a/miscutils/less.c b/miscutils/less.c index 500059d2a..9e12c11a7 100644 --- a/miscutils/less.c +++ b/miscutils/less.c | |||
@@ -28,13 +28,15 @@ | |||
28 | #include "xregex.h" | 28 | #include "xregex.h" |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | |||
32 | #define ESC "\033" | ||
31 | /* The escape codes for highlighted and normal text */ | 33 | /* The escape codes for highlighted and normal text */ |
32 | #define HIGHLIGHT "\033[7m" | 34 | #define HIGHLIGHT ESC"[7m" |
33 | #define NORMAL "\033[0m" | 35 | #define NORMAL ESC"[0m" |
34 | /* The escape code to home and clear to the end of screen */ | 36 | /* The escape code to home and clear to the end of screen */ |
35 | #define CLEAR "\033[H\033[J" | 37 | #define CLEAR ESC"[H\033[J" |
36 | /* The escape code to clear to the end of line */ | 38 | /* The escape code to clear to the end of line */ |
37 | #define CLEAR_2_EOL "\033[K" | 39 | #define CLEAR_2_EOL ESC"[K" |
38 | 40 | ||
39 | enum { | 41 | enum { |
40 | /* Absolute max of lines eaten */ | 42 | /* Absolute max of lines eaten */ |
@@ -165,12 +167,12 @@ static void set_tty_cooked(void) | |||
165 | top-left corner of the console */ | 167 | top-left corner of the console */ |
166 | static void move_cursor(int line, int row) | 168 | static void move_cursor(int line, int row) |
167 | { | 169 | { |
168 | printf("\033[%u;%uH", line, row); | 170 | printf(ESC"[%u;%uH", line, row); |
169 | } | 171 | } |
170 | 172 | ||
171 | static void clear_line(void) | 173 | static void clear_line(void) |
172 | { | 174 | { |
173 | printf("\033[%u;0H" CLEAR_2_EOL, max_displayed_line + 2); | 175 | printf(ESC"[%u;0H" CLEAR_2_EOL, max_displayed_line + 2); |
174 | } | 176 | } |
175 | 177 | ||
176 | static void print_hilite(const char *str) | 178 | static void print_hilite(const char *str) |
diff --git a/miscutils/ubi_attach_detach.c b/miscutils/ubi_attach_detach.c index 18ffd4df2..b74d97b68 100644 --- a/miscutils/ubi_attach_detach.c +++ b/miscutils/ubi_attach_detach.c | |||
@@ -26,8 +26,8 @@ | |||
26 | #include "libbb.h" | 26 | #include "libbb.h" |
27 | #include <mtd/ubi-user.h> | 27 | #include <mtd/ubi-user.h> |
28 | 28 | ||
29 | #define OPTION_M (1 << 0) | 29 | #define OPTION_M (1 << 0) |
30 | #define OPTION_D (1 << 1) | 30 | #define OPTION_D (1 << 1) |
31 | 31 | ||
32 | #define do_attach (ENABLE_UBIATTACH && \ | 32 | #define do_attach (ENABLE_UBIATTACH && \ |
33 | (!ENABLE_UBIDETACH || (applet_name[3] == 'a'))) | 33 | (!ENABLE_UBIDETACH || (applet_name[3] == 'a'))) |
diff --git a/miscutils/watchdog.c b/miscutils/watchdog.c index 36902a214..630782660 100644 --- a/miscutils/watchdog.c +++ b/miscutils/watchdog.c | |||
@@ -24,7 +24,7 @@ static void watchdog_shutdown(int sig UNUSED_PARAM) | |||
24 | write(3, &V, 1); /* Magic, see watchdog-api.txt in kernel */ | 24 | write(3, &V, 1); /* Magic, see watchdog-api.txt in kernel */ |
25 | if (ENABLE_FEATURE_CLEAN_UP) | 25 | if (ENABLE_FEATURE_CLEAN_UP) |
26 | close(3); | 26 | close(3); |
27 | exit(EXIT_SUCCESS); | 27 | _exit(EXIT_SUCCESS); |
28 | } | 28 | } |
29 | 29 | ||
30 | int watchdog_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 30 | int watchdog_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
diff --git a/modutils/modprobe.c b/modutils/modprobe.c index a5cf4babf..73df39c6c 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c | |||
@@ -10,6 +10,20 @@ | |||
10 | 10 | ||
11 | //applet:IF_MODPROBE(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_DROP)) | 11 | //applet:IF_MODPROBE(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_DROP)) |
12 | 12 | ||
13 | #include "libbb.h" | ||
14 | #include "modutils.h" | ||
15 | #include <sys/utsname.h> | ||
16 | #include <fnmatch.h> | ||
17 | |||
18 | //#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) | ||
19 | #define DBG(...) ((void)0) | ||
20 | |||
21 | /* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t), | ||
22 | * we expect the full dependency list to be specified in modules.dep. | ||
23 | * Older versions would only export the direct dependency list. | ||
24 | */ | ||
25 | |||
26 | |||
13 | //usage:#if !ENABLE_MODPROBE_SMALL | 27 | //usage:#if !ENABLE_MODPROBE_SMALL |
14 | //usage:#define modprobe_notes_usage | 28 | //usage:#define modprobe_notes_usage |
15 | //usage: "modprobe can (un)load a stack of modules, passing each module options (when\n" | 29 | //usage: "modprobe can (un)load a stack of modules, passing each module options (when\n" |
@@ -72,9 +86,8 @@ | |||
72 | //usage: " from the command line\n" | 86 | //usage: " from the command line\n" |
73 | //usage: | 87 | //usage: |
74 | //usage:#define modprobe_trivial_usage | 88 | //usage:#define modprobe_trivial_usage |
75 | //usage: "[-alrqvs" | 89 | //usage: "[-alrqvsD" IF_FEATURE_MODPROBE_BLACKLIST("b") "]" |
76 | //usage: IF_FEATURE_MODPROBE_BLACKLIST("b") | 90 | //usage: " MODULE [symbol=value]..." |
77 | //usage: "] MODULE [symbol=value]..." | ||
78 | //usage:#define modprobe_full_usage "\n\n" | 91 | //usage:#define modprobe_full_usage "\n\n" |
79 | //usage: "Options:" | 92 | //usage: "Options:" |
80 | //usage: "\n -a Load multiple MODULEs" | 93 | //usage: "\n -a Load multiple MODULEs" |
@@ -83,43 +96,50 @@ | |||
83 | //usage: "\n -q Quiet" | 96 | //usage: "\n -q Quiet" |
84 | //usage: "\n -v Verbose" | 97 | //usage: "\n -v Verbose" |
85 | //usage: "\n -s Log to syslog" | 98 | //usage: "\n -s Log to syslog" |
99 | //usage: "\n -D Show dependencies" | ||
86 | //usage: IF_FEATURE_MODPROBE_BLACKLIST( | 100 | //usage: IF_FEATURE_MODPROBE_BLACKLIST( |
87 | //usage: "\n -b Apply blacklist to module names too" | 101 | //usage: "\n -b Apply blacklist to module names too" |
88 | //usage: ) | 102 | //usage: ) |
89 | //usage:#endif /* !ENABLE_MODPROBE_SMALL */ | 103 | //usage:#endif /* !ENABLE_MODPROBE_SMALL */ |
90 | 104 | ||
91 | #include "libbb.h" | ||
92 | #include "modutils.h" | ||
93 | #include <sys/utsname.h> | ||
94 | #include <fnmatch.h> | ||
95 | |||
96 | //#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) | ||
97 | #define DBG(...) ((void)0) | ||
98 | |||
99 | /* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t), | ||
100 | * we expect the full dependency list to be specified in modules.dep. | ||
101 | * Older versions would only export the direct dependency list. | ||
102 | */ | ||
103 | |||
104 | /* Note that usage text doesn't document various 2.4 options | 105 | /* Note that usage text doesn't document various 2.4 options |
105 | * we pull in through INSMOD_OPTS define */ | 106 | * we pull in through INSMOD_OPTS define */ |
106 | 107 | #define MODPROBE_OPTS "alrD" IF_FEATURE_MODPROBE_BLACKLIST("b") | |
107 | #define MODPROBE_COMPLEMENTARY "q-v:v-q:l--ar:a--lr:r--al" | 108 | /* -a and -D _are_ in fact compatible */ |
108 | #define MODPROBE_OPTS "alr" IF_FEATURE_MODPROBE_BLACKLIST("b") | 109 | #define MODPROBE_COMPLEMENTARY ("q-v:v-q:l--arD:r--alD:a--lr:D--rl") |
109 | //#define MODPROBE_COMPLEMENTARY "q-v:v-q:l--acr:a--lr:r--al" | ||
110 | //#define MODPROBE_OPTS "acd:lnrt:C:" IF_FEATURE_MODPROBE_BLACKLIST("b") | 110 | //#define MODPROBE_OPTS "acd:lnrt:C:" IF_FEATURE_MODPROBE_BLACKLIST("b") |
111 | //#define MODPROBE_COMPLEMENTARY "q-v:v-q:l--acr:a--lr:r--al" | ||
111 | enum { | 112 | enum { |
112 | MODPROBE_OPT_INSERT_ALL = (INSMOD_OPT_UNUSED << 0), /* a */ | 113 | OPT_INSERT_ALL = (INSMOD_OPT_UNUSED << 0), /* a */ |
113 | //MODPROBE_OPT_DUMP_ONLY= (INSMOD_OPT_UNUSED << x), /* c */ | 114 | //OPT_DUMP_ONLY = (INSMOD_OPT_UNUSED << x), /* c */ |
114 | //MODPROBE_OPT_DIRNAME = (INSMOD_OPT_UNUSED << x), /* d */ | 115 | //OPT_DIRNAME = (INSMOD_OPT_UNUSED << x), /* d */ |
115 | MODPROBE_OPT_LIST_ONLY = (INSMOD_OPT_UNUSED << 1), /* l */ | 116 | OPT_LIST_ONLY = (INSMOD_OPT_UNUSED << 1), /* l */ |
116 | //MODPROBE_OPT_SHOW_ONLY= (INSMOD_OPT_UNUSED << x), /* n */ | 117 | //OPT_SHOW_ONLY = (INSMOD_OPT_UNUSED << x), /* n */ |
117 | MODPROBE_OPT_REMOVE = (INSMOD_OPT_UNUSED << 2), /* r */ | 118 | OPT_REMOVE = (INSMOD_OPT_UNUSED << 2), /* r */ |
118 | //MODPROBE_OPT_RESTRICT = (INSMOD_OPT_UNUSED << x), /* t */ | 119 | //OPT_RESTRICT = (INSMOD_OPT_UNUSED << x), /* t */ |
119 | //MODPROBE_OPT_VERONLY = (INSMOD_OPT_UNUSED << x), /* V */ | 120 | //OPT_VERONLY = (INSMOD_OPT_UNUSED << x), /* V */ |
120 | //MODPROBE_OPT_CONFIGFILE=(INSMOD_OPT_UNUSED << x), /* C */ | 121 | //OPT_CONFIGFILE = (INSMOD_OPT_UNUSED << x), /* C */ |
121 | MODPROBE_OPT_BLACKLIST = (INSMOD_OPT_UNUSED << 3) * ENABLE_FEATURE_MODPROBE_BLACKLIST, | 122 | OPT_SHOW_DEPS = (INSMOD_OPT_UNUSED << 3), /* D */ |
123 | OPT_BLACKLIST = (INSMOD_OPT_UNUSED << 4) * ENABLE_FEATURE_MODPROBE_BLACKLIST, | ||
122 | }; | 124 | }; |
125 | #if ENABLE_LONG_OPTS | ||
126 | static const char modprobe_longopts[] ALIGN1 = | ||
127 | /* nobody asked for long opts (yet) */ | ||
128 | // "all\0" No_argument "a" | ||
129 | // "list\0" No_argument "l" | ||
130 | // "remove\0" No_argument "r" | ||
131 | // "quiet\0" No_argument "q" | ||
132 | // "verbose\0" No_argument "v" | ||
133 | // "syslog\0" No_argument "s" | ||
134 | /* module-init-tools 3.11.1 has only long opt --show-depends | ||
135 | * but no short -D, we provide long opt for scripts which | ||
136 | * were written for 3.11.1: */ | ||
137 | "show-depends\0" No_argument "D" | ||
138 | // IF_FEATURE_MODPROBE_BLACKLIST( | ||
139 | // "use-blacklist\0" No_argument "b" | ||
140 | // ) | ||
141 | ; | ||
142 | #endif | ||
123 | 143 | ||
124 | #define MODULE_FLAG_LOADED 0x0001 | 144 | #define MODULE_FLAG_LOADED 0x0001 |
125 | #define MODULE_FLAG_NEED_DEPS 0x0002 | 145 | #define MODULE_FLAG_NEED_DEPS 0x0002 |
@@ -145,9 +165,13 @@ struct globals { | |||
145 | int num_unresolved_deps; | 165 | int num_unresolved_deps; |
146 | /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */ | 166 | /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */ |
147 | smallint need_symbols; | 167 | smallint need_symbols; |
168 | struct utsname uts; | ||
148 | } FIX_ALIASING; | 169 | } FIX_ALIASING; |
149 | #define G (*(struct globals*)&bb_common_bufsiz1) | 170 | #define G (*(struct globals*)&bb_common_bufsiz1) |
150 | #define INIT_G() do { } while (0) | 171 | #define INIT_G() do { } while (0) |
172 | struct BUG_G_too_big { | ||
173 | char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; | ||
174 | }; | ||
151 | 175 | ||
152 | 176 | ||
153 | static int read_config(const char *path); | 177 | static int read_config(const char *path); |
@@ -202,7 +226,7 @@ static void add_probe(const char *name) | |||
202 | struct module_entry *m; | 226 | struct module_entry *m; |
203 | 227 | ||
204 | m = get_or_add_modentry(name); | 228 | m = get_or_add_modentry(name); |
205 | if (!(option_mask32 & MODPROBE_OPT_REMOVE) | 229 | if (!(option_mask32 & (OPT_REMOVE | OPT_SHOW_DEPS)) |
206 | && (m->flags & MODULE_FLAG_LOADED) | 230 | && (m->flags & MODULE_FLAG_LOADED) |
207 | ) { | 231 | ) { |
208 | DBG("skipping %s, it is already loaded", name); | 232 | DBG("skipping %s, it is already loaded", name); |
@@ -353,8 +377,6 @@ static char *parse_and_add_kcmdline_module_options(char *options, const char *mo | |||
353 | */ | 377 | */ |
354 | static int do_modprobe(struct module_entry *m) | 378 | static int do_modprobe(struct module_entry *m) |
355 | { | 379 | { |
356 | struct module_entry *m2 = m2; /* for compiler */ | ||
357 | char *fn, *options; | ||
358 | int rc, first; | 380 | int rc, first; |
359 | llist_t *l; | 381 | llist_t *l; |
360 | 382 | ||
@@ -366,7 +388,7 @@ static int do_modprobe(struct module_entry *m) | |||
366 | } | 388 | } |
367 | DBG("do_modprob'ing %s", m->modname); | 389 | DBG("do_modprob'ing %s", m->modname); |
368 | 390 | ||
369 | if (!(option_mask32 & MODPROBE_OPT_REMOVE)) | 391 | if (!(option_mask32 & OPT_REMOVE)) |
370 | m->deps = llist_rev(m->deps); | 392 | m->deps = llist_rev(m->deps); |
371 | 393 | ||
372 | for (l = m->deps; l != NULL; l = l->link) | 394 | for (l = m->deps; l != NULL; l = l->link) |
@@ -375,11 +397,14 @@ static int do_modprobe(struct module_entry *m) | |||
375 | first = 1; | 397 | first = 1; |
376 | rc = 0; | 398 | rc = 0; |
377 | while (m->deps) { | 399 | while (m->deps) { |
400 | struct module_entry *m2; | ||
401 | char *fn, *options; | ||
402 | |||
378 | rc = 0; | 403 | rc = 0; |
379 | fn = llist_pop(&m->deps); /* we leak it */ | 404 | fn = llist_pop(&m->deps); /* we leak it */ |
380 | m2 = get_or_add_modentry(fn); | 405 | m2 = get_or_add_modentry(fn); |
381 | 406 | ||
382 | if (option_mask32 & MODPROBE_OPT_REMOVE) { | 407 | if (option_mask32 & OPT_REMOVE) { |
383 | /* modprobe -r */ | 408 | /* modprobe -r */ |
384 | if (m2->flags & MODULE_FLAG_LOADED) { | 409 | if (m2->flags & MODULE_FLAG_LOADED) { |
385 | rc = bb_delete_module(m2->modname, O_EXCL); | 410 | rc = bb_delete_module(m2->modname, O_EXCL); |
@@ -399,16 +424,27 @@ static int do_modprobe(struct module_entry *m) | |||
399 | continue; | 424 | continue; |
400 | } | 425 | } |
401 | 426 | ||
402 | if (m2->flags & MODULE_FLAG_LOADED) { | ||
403 | DBG("%s is already loaded, skipping", fn); | ||
404 | continue; | ||
405 | } | ||
406 | |||
407 | options = m2->options; | 427 | options = m2->options; |
408 | m2->options = NULL; | 428 | m2->options = NULL; |
409 | options = parse_and_add_kcmdline_module_options(options, m2->modname); | 429 | options = parse_and_add_kcmdline_module_options(options, m2->modname); |
410 | if (m == m2) | 430 | if (m == m2) |
411 | options = gather_options_str(options, G.cmdline_mopts); | 431 | options = gather_options_str(options, G.cmdline_mopts); |
432 | |||
433 | if (option_mask32 & OPT_SHOW_DEPS) { | ||
434 | printf(options ? "insmod %s/%s/%s %s\n" | ||
435 | : "insmod %s/%s/%s\n", | ||
436 | CONFIG_DEFAULT_MODULES_DIR, G.uts.release, fn, | ||
437 | options); | ||
438 | free(options); | ||
439 | continue; | ||
440 | } | ||
441 | |||
442 | if (m2->flags & MODULE_FLAG_LOADED) { | ||
443 | DBG("%s is already loaded, skipping", fn); | ||
444 | free(options); | ||
445 | continue; | ||
446 | } | ||
447 | |||
412 | rc = bb_init_module(fn, options); | 448 | rc = bb_init_module(fn, options); |
413 | DBG("loaded %s '%s', rc:%d", fn, options, rc); | 449 | DBG("loaded %s '%s', rc:%d", fn, options, rc); |
414 | if (rc == EEXIST) | 450 | if (rc == EEXIST) |
@@ -456,7 +492,7 @@ static void load_modules_dep(void) | |||
456 | 492 | ||
457 | /* Optimization... */ | 493 | /* Optimization... */ |
458 | if ((m->flags & MODULE_FLAG_LOADED) | 494 | if ((m->flags & MODULE_FLAG_LOADED) |
459 | && !(option_mask32 & MODPROBE_OPT_REMOVE) | 495 | && !(option_mask32 & (OPT_REMOVE | OPT_SHOW_DEPS)) |
460 | ) { | 496 | ) { |
461 | DBG("skip deps of %s, it's already loaded", tokens[0]); | 497 | DBG("skip deps of %s, it's already loaded", tokens[0]); |
462 | continue; | 498 | continue; |
@@ -477,21 +513,23 @@ static void load_modules_dep(void) | |||
477 | int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 513 | int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
478 | int modprobe_main(int argc UNUSED_PARAM, char **argv) | 514 | int modprobe_main(int argc UNUSED_PARAM, char **argv) |
479 | { | 515 | { |
480 | struct utsname uts; | ||
481 | int rc; | 516 | int rc; |
482 | unsigned opt; | 517 | unsigned opt; |
483 | struct module_entry *me; | 518 | struct module_entry *me; |
484 | 519 | ||
520 | INIT_G(); | ||
521 | |||
522 | IF_LONG_OPTS(applet_long_options = modprobe_longopts;) | ||
485 | opt_complementary = MODPROBE_COMPLEMENTARY; | 523 | opt_complementary = MODPROBE_COMPLEMENTARY; |
486 | opt = getopt32(argv, INSMOD_OPTS MODPROBE_OPTS INSMOD_ARGS); | 524 | opt = getopt32(argv, INSMOD_OPTS MODPROBE_OPTS INSMOD_ARGS); |
487 | argv += optind; | 525 | argv += optind; |
488 | 526 | ||
489 | /* Goto modules location */ | 527 | /* Goto modules location */ |
490 | xchdir(CONFIG_DEFAULT_MODULES_DIR); | 528 | xchdir(CONFIG_DEFAULT_MODULES_DIR); |
491 | uname(&uts); | 529 | uname(&G.uts); |
492 | xchdir(uts.release); | 530 | xchdir(G.uts.release); |
493 | 531 | ||
494 | if (opt & MODPROBE_OPT_LIST_ONLY) { | 532 | if (opt & OPT_LIST_ONLY) { |
495 | char name[MODULE_NAME_LEN]; | 533 | char name[MODULE_NAME_LEN]; |
496 | char *colon, *tokens[2]; | 534 | char *colon, *tokens[2]; |
497 | parser_t *p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read); | 535 | parser_t *p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read); |
@@ -521,7 +559,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
521 | logmode = LOGMODE_SYSLOG; | 559 | logmode = LOGMODE_SYSLOG; |
522 | 560 | ||
523 | if (!argv[0]) { | 561 | if (!argv[0]) { |
524 | if (opt & MODPROBE_OPT_REMOVE) { | 562 | if (opt & OPT_REMOVE) { |
525 | /* "modprobe -r" (w/o params). | 563 | /* "modprobe -r" (w/o params). |
526 | * "If name is NULL, all unused modules marked | 564 | * "If name is NULL, all unused modules marked |
527 | * autoclean will be removed". | 565 | * autoclean will be removed". |
@@ -541,7 +579,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
541 | config_close(parser); | 579 | config_close(parser); |
542 | } | 580 | } |
543 | 581 | ||
544 | if (opt & (MODPROBE_OPT_INSERT_ALL | MODPROBE_OPT_REMOVE)) { | 582 | if (opt & (OPT_INSERT_ALL | OPT_REMOVE)) { |
545 | /* Each argument is a module name */ | 583 | /* Each argument is a module name */ |
546 | do { | 584 | do { |
547 | DBG("adding module %s", *argv); | 585 | DBG("adding module %s", *argv); |
@@ -575,7 +613,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
575 | /* This is not an alias. Literal names are blacklisted | 613 | /* This is not an alias. Literal names are blacklisted |
576 | * only if '-b' is given. | 614 | * only if '-b' is given. |
577 | */ | 615 | */ |
578 | if (!(opt & MODPROBE_OPT_BLACKLIST) | 616 | if (!(opt & OPT_BLACKLIST) |
579 | || !(me->flags & MODULE_FLAG_BLACKLISTED) | 617 | || !(me->flags & MODULE_FLAG_BLACKLISTED) |
580 | ) { | 618 | ) { |
581 | rc |= do_modprobe(me); | 619 | rc |= do_modprobe(me); |
@@ -592,7 +630,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
592 | m2 = get_or_add_modentry(realname); | 630 | m2 = get_or_add_modentry(realname); |
593 | if (!(m2->flags & MODULE_FLAG_BLACKLISTED) | 631 | if (!(m2->flags & MODULE_FLAG_BLACKLISTED) |
594 | && (!(m2->flags & MODULE_FLAG_LOADED) | 632 | && (!(m2->flags & MODULE_FLAG_LOADED) |
595 | || (opt & MODPROBE_OPT_REMOVE)) | 633 | || (opt & (OPT_REMOVE | OPT_SHOW_DEPS))) |
596 | ) { | 634 | ) { |
597 | //TODO: we can pass "me" as 2nd param to do_modprobe, | 635 | //TODO: we can pass "me" as 2nd param to do_modprobe, |
598 | //and make do_modprobe emit more meaningful error messages | 636 | //and make do_modprobe emit more meaningful error messages |
diff --git a/modutils/rmmod.c b/modutils/rmmod.c index dde77731f..2486511d7 100644 --- a/modutils/rmmod.c +++ b/modutils/rmmod.c | |||
@@ -35,9 +35,9 @@ int rmmod_main(int argc UNUSED_PARAM, char **argv) | |||
35 | /* Parse command line. */ | 35 | /* Parse command line. */ |
36 | n = getopt32(argv, "wfas"); // -s ignored | 36 | n = getopt32(argv, "wfas"); // -s ignored |
37 | argv += optind; | 37 | argv += optind; |
38 | if (n & 1) // --wait | 38 | if (n & 1) // --wait |
39 | flags &= ~O_NONBLOCK; | 39 | flags &= ~O_NONBLOCK; |
40 | if (n & 2) // --force | 40 | if (n & 2) // --force |
41 | flags |= O_TRUNC; | 41 | flags |= O_TRUNC; |
42 | if (n & 4) { | 42 | if (n & 4) { |
43 | /* Unload _all_ unused modules via NULL delete_module() call */ | 43 | /* Unload _all_ unused modules via NULL delete_module() call */ |
diff --git a/networking/Config.src b/networking/Config.src index 6dd7df754..274fcae3a 100644 --- a/networking/Config.src +++ b/networking/Config.src | |||
@@ -684,29 +684,6 @@ config FEATURE_NTPD_SERVER | |||
684 | Make ntpd usable as a NTP server. If you disable this option | 684 | Make ntpd usable as a NTP server. If you disable this option |
685 | ntpd will be usable only as a NTP client. | 685 | ntpd will be usable only as a NTP client. |
686 | 686 | ||
687 | config PING | ||
688 | bool "ping" | ||
689 | default y | ||
690 | depends on PLATFORM_LINUX | ||
691 | help | ||
692 | ping uses the ICMP protocol's mandatory ECHO_REQUEST datagram to | ||
693 | elicit an ICMP ECHO_RESPONSE from a host or gateway. | ||
694 | |||
695 | config PING6 | ||
696 | bool "ping6" | ||
697 | default y | ||
698 | depends on FEATURE_IPV6 && PING | ||
699 | help | ||
700 | This will give you a ping that can talk IPv6. | ||
701 | |||
702 | config FEATURE_FANCY_PING | ||
703 | bool "Enable fancy ping output" | ||
704 | default y | ||
705 | depends on PING | ||
706 | help | ||
707 | Make the output from the ping applet include statistics, and at the | ||
708 | same time provide full support for ICMP packets. | ||
709 | |||
710 | config PSCAN | 687 | config PSCAN |
711 | bool "pscan" | 688 | bool "pscan" |
712 | default y | 689 | default y |
diff --git a/networking/Kbuild.src b/networking/Kbuild.src index f41a2df70..944f27be1 100644 --- a/networking/Kbuild.src +++ b/networking/Kbuild.src | |||
@@ -30,8 +30,6 @@ lib-$(CONFIG_NC) += nc.o | |||
30 | lib-$(CONFIG_NETSTAT) += netstat.o | 30 | lib-$(CONFIG_NETSTAT) += netstat.o |
31 | lib-$(CONFIG_NSLOOKUP) += nslookup.o | 31 | lib-$(CONFIG_NSLOOKUP) += nslookup.o |
32 | lib-$(CONFIG_NTPD) += ntpd.o | 32 | lib-$(CONFIG_NTPD) += ntpd.o |
33 | lib-$(CONFIG_PING) += ping.o | ||
34 | lib-$(CONFIG_PING6) += ping.o | ||
35 | lib-$(CONFIG_PSCAN) += pscan.o | 33 | lib-$(CONFIG_PSCAN) += pscan.o |
36 | lib-$(CONFIG_ROUTE) += route.o | 34 | lib-$(CONFIG_ROUTE) += route.o |
37 | lib-$(CONFIG_SLATTACH) += slattach.o | 35 | lib-$(CONFIG_SLATTACH) += slattach.o |
diff --git a/networking/arping.c b/networking/arping.c index f2b12ed04..6f6b59cfb 100644 --- a/networking/arping.c +++ b/networking/arping.c | |||
@@ -1,10 +1,8 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * arping.c - Ping hosts by ARP requests/replies | ||
4 | * | ||
5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 3 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
6 | * | 4 | * |
7 | * Author: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> | 5 | * Author: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> |
8 | * Busybox port: Nick Fedchik <nick@fedchik.org.ua> | 6 | * Busybox port: Nick Fedchik <nick@fedchik.org.ua> |
9 | */ | 7 | */ |
10 | 8 | ||
diff --git a/networking/dnsd.c b/networking/dnsd.c index 92d4867aa..8ed31cea2 100644 --- a/networking/dnsd.c +++ b/networking/dnsd.c | |||
@@ -388,7 +388,7 @@ static int process_packet(struct dns_entry *conf_data, | |||
388 | query_len = strlen(query_string) + 1; | 388 | query_len = strlen(query_string) + 1; |
389 | /* may be unaligned! */ | 389 | /* may be unaligned! */ |
390 | unaligned_type_class = (void *)(query_string + query_len); | 390 | unaligned_type_class = (void *)(query_string + query_len); |
391 | query_len += sizeof(unaligned_type_class); | 391 | query_len += sizeof(*unaligned_type_class); |
392 | /* where to append answer block */ | 392 | /* where to append answer block */ |
393 | answb = (void *)(unaligned_type_class + 1); | 393 | answb = (void *)(unaligned_type_class + 1); |
394 | 394 | ||
diff --git a/networking/httpd.c b/networking/httpd.c index c174958e2..fa42d9850 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -231,7 +231,7 @@ struct globals { | |||
231 | int verbose; /* must be int (used by getopt32) */ | 231 | int verbose; /* must be int (used by getopt32) */ |
232 | smallint flg_deny_all; | 232 | smallint flg_deny_all; |
233 | 233 | ||
234 | unsigned rmt_ip; /* used for IP-based allow/deny rules */ | 234 | unsigned rmt_ip; /* used for IP-based allow/deny rules */ |
235 | time_t last_mod; | 235 | time_t last_mod; |
236 | char *rmt_ip_str; /* for $REMOTE_ADDR and $REMOTE_PORT */ | 236 | char *rmt_ip_str; /* for $REMOTE_ADDR and $REMOTE_PORT */ |
237 | const char *bind_addr_or_port; | 237 | const char *bind_addr_or_port; |
@@ -267,7 +267,7 @@ struct globals { | |||
267 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | 267 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR |
268 | Htaccess *script_i; /* config script interpreters */ | 268 | Htaccess *script_i; /* config script interpreters */ |
269 | #endif | 269 | #endif |
270 | char *iobuf; /* [IOBUF_SIZE] */ | 270 | char *iobuf; /* [IOBUF_SIZE] */ |
271 | #define hdr_buf bb_common_bufsiz1 | 271 | #define hdr_buf bb_common_bufsiz1 |
272 | char *hdr_ptr; | 272 | char *hdr_ptr; |
273 | int hdr_cnt; | 273 | int hdr_cnt; |
diff --git a/networking/ifupdown.c b/networking/ifupdown.c index 3cb1ec858..59df4e80f 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c | |||
@@ -164,7 +164,7 @@ static char *get_var(const char *id, size_t idlen, struct interface_defn_t *ifd) | |||
164 | return NULL; | 164 | return NULL; |
165 | } | 165 | } |
166 | 166 | ||
167 | #if ENABLE_FEATURE_IFUPDOWN_IP | 167 | # if ENABLE_FEATURE_IFUPDOWN_IP |
168 | static int count_netmask_bits(const char *dotted_quad) | 168 | static int count_netmask_bits(const char *dotted_quad) |
169 | { | 169 | { |
170 | // int result; | 170 | // int result; |
@@ -195,7 +195,7 @@ static int count_netmask_bits(const char *dotted_quad) | |||
195 | } | 195 | } |
196 | return result; | 196 | return result; |
197 | } | 197 | } |
198 | #endif | 198 | # endif |
199 | 199 | ||
200 | static char *parse(const char *command, struct interface_defn_t *ifd) | 200 | static char *parse(const char *command, struct interface_defn_t *ifd) |
201 | { | 201 | { |
@@ -258,17 +258,17 @@ static char *parse(const char *command, struct interface_defn_t *ifd) | |||
258 | varvalue = get_var(command, nextpercent - command, ifd); | 258 | varvalue = get_var(command, nextpercent - command, ifd); |
259 | 259 | ||
260 | if (varvalue) { | 260 | if (varvalue) { |
261 | #if ENABLE_FEATURE_IFUPDOWN_IP | 261 | # if ENABLE_FEATURE_IFUPDOWN_IP |
262 | /* "hwaddress <class> <address>": | 262 | /* "hwaddress <class> <address>": |
263 | * unlike ifconfig, ip doesnt want <class> | 263 | * unlike ifconfig, ip doesnt want <class> |
264 | * (usually "ether" keyword). Skip it. */ | 264 | * (usually "ether" keyword). Skip it. */ |
265 | if (strncmp(command, "hwaddress", 9) == 0) { | 265 | if (strncmp(command, "hwaddress", 9) == 0) { |
266 | varvalue = skip_whitespace(skip_non_whitespace(varvalue)); | 266 | varvalue = skip_whitespace(skip_non_whitespace(varvalue)); |
267 | } | 267 | } |
268 | #endif | 268 | # endif |
269 | addstr(&result, varvalue, strlen(varvalue)); | 269 | addstr(&result, varvalue, strlen(varvalue)); |
270 | } else { | 270 | } else { |
271 | #if ENABLE_FEATURE_IFUPDOWN_IP | 271 | # if ENABLE_FEATURE_IFUPDOWN_IP |
272 | /* Sigh... Add a special case for 'ip' to convert from | 272 | /* Sigh... Add a special case for 'ip' to convert from |
273 | * dotted quad to bit count style netmasks. */ | 273 | * dotted quad to bit count style netmasks. */ |
274 | if (strncmp(command, "bnmask", 6) == 0) { | 274 | if (strncmp(command, "bnmask", 6) == 0) { |
@@ -284,7 +284,7 @@ static char *parse(const char *command, struct interface_defn_t *ifd) | |||
284 | } | 284 | } |
285 | } | 285 | } |
286 | } | 286 | } |
287 | #endif | 287 | # endif |
288 | okay[opt_depth - 1] = 0; | 288 | okay[opt_depth - 1] = 0; |
289 | } | 289 | } |
290 | 290 | ||
@@ -329,56 +329,64 @@ static int execute(const char *command, struct interface_defn_t *ifd, execfn *ex | |||
329 | } | 329 | } |
330 | return 1; | 330 | return 1; |
331 | } | 331 | } |
332 | #endif | 332 | |
333 | #endif /* FEATURE_IFUPDOWN_IPV4 || FEATURE_IFUPDOWN_IPV6 */ | ||
334 | |||
333 | 335 | ||
334 | #if ENABLE_FEATURE_IFUPDOWN_IPV6 | 336 | #if ENABLE_FEATURE_IFUPDOWN_IPV6 |
337 | |||
335 | static int FAST_FUNC loopback_up6(struct interface_defn_t *ifd, execfn *exec) | 338 | static int FAST_FUNC loopback_up6(struct interface_defn_t *ifd, execfn *exec) |
336 | { | 339 | { |
337 | #if ENABLE_FEATURE_IFUPDOWN_IP | 340 | # if ENABLE_FEATURE_IFUPDOWN_IP |
338 | int result; | 341 | int result; |
339 | result = execute("ip addr add ::1 dev %iface%", ifd, exec); | 342 | result = execute("ip addr add ::1 dev %iface%", ifd, exec); |
340 | result += execute("ip link set %iface% up", ifd, exec); | 343 | result += execute("ip link set %iface% up", ifd, exec); |
341 | return ((result == 2) ? 2 : 0); | 344 | return ((result == 2) ? 2 : 0); |
342 | #else | 345 | # else |
343 | return execute("ifconfig %iface% add ::1", ifd, exec); | 346 | return execute("ifconfig %iface% add ::1", ifd, exec); |
344 | #endif | 347 | # endif |
345 | } | 348 | } |
346 | 349 | ||
347 | static int FAST_FUNC loopback_down6(struct interface_defn_t *ifd, execfn *exec) | 350 | static int FAST_FUNC loopback_down6(struct interface_defn_t *ifd, execfn *exec) |
348 | { | 351 | { |
349 | #if ENABLE_FEATURE_IFUPDOWN_IP | 352 | # if ENABLE_FEATURE_IFUPDOWN_IP |
350 | return execute("ip link set %iface% down", ifd, exec); | 353 | return execute("ip link set %iface% down", ifd, exec); |
351 | #else | 354 | # else |
352 | return execute("ifconfig %iface% del ::1", ifd, exec); | 355 | return execute("ifconfig %iface% del ::1", ifd, exec); |
353 | #endif | 356 | # endif |
357 | } | ||
358 | |||
359 | static int FAST_FUNC manual_up_down6(struct interface_defn_t *ifd UNUSED_PARAM, execfn *exec UNUSED_PARAM) | ||
360 | { | ||
361 | return 1; | ||
354 | } | 362 | } |
355 | 363 | ||
356 | static int FAST_FUNC static_up6(struct interface_defn_t *ifd, execfn *exec) | 364 | static int FAST_FUNC static_up6(struct interface_defn_t *ifd, execfn *exec) |
357 | { | 365 | { |
358 | int result; | 366 | int result; |
359 | #if ENABLE_FEATURE_IFUPDOWN_IP | 367 | # if ENABLE_FEATURE_IFUPDOWN_IP |
360 | result = execute("ip addr add %address%/%netmask% dev %iface%[[ label %label%]]", ifd, exec); | 368 | result = execute("ip addr add %address%/%netmask% dev %iface%[[ label %label%]]", ifd, exec); |
361 | result += execute("ip link set[[ mtu %mtu%]][[ addr %hwaddress%]] %iface% up", ifd, exec); | 369 | result += execute("ip link set[[ mtu %mtu%]][[ addr %hwaddress%]] %iface% up", ifd, exec); |
362 | /* Was: "[[ ip ....%gateway% ]]". Removed extra spaces w/o checking */ | 370 | /* Was: "[[ ip ....%gateway% ]]". Removed extra spaces w/o checking */ |
363 | result += execute("[[ip route add ::/0 via %gateway%]]", ifd, exec); | 371 | result += execute("[[ip route add ::/0 via %gateway%]]", ifd, exec); |
364 | #else | 372 | # else |
365 | result = execute("ifconfig %iface%[[ media %media%]][[ hw %hwaddress%]][[ mtu %mtu%]] up", ifd, exec); | 373 | result = execute("ifconfig %iface%[[ media %media%]][[ hw %hwaddress%]][[ mtu %mtu%]] up", ifd, exec); |
366 | result += execute("ifconfig %iface% add %address%/%netmask%", ifd, exec); | 374 | result += execute("ifconfig %iface% add %address%/%netmask%", ifd, exec); |
367 | result += execute("[[route -A inet6 add ::/0 gw %gateway%]]", ifd, exec); | 375 | result += execute("[[route -A inet6 add ::/0 gw %gateway%]]", ifd, exec); |
368 | #endif | 376 | # endif |
369 | return ((result == 3) ? 3 : 0); | 377 | return ((result == 3) ? 3 : 0); |
370 | } | 378 | } |
371 | 379 | ||
372 | static int FAST_FUNC static_down6(struct interface_defn_t *ifd, execfn *exec) | 380 | static int FAST_FUNC static_down6(struct interface_defn_t *ifd, execfn *exec) |
373 | { | 381 | { |
374 | #if ENABLE_FEATURE_IFUPDOWN_IP | 382 | # if ENABLE_FEATURE_IFUPDOWN_IP |
375 | return execute("ip link set %iface% down", ifd, exec); | 383 | return execute("ip link set %iface% down", ifd, exec); |
376 | #else | 384 | # else |
377 | return execute("ifconfig %iface% down", ifd, exec); | 385 | return execute("ifconfig %iface% down", ifd, exec); |
378 | #endif | 386 | # endif |
379 | } | 387 | } |
380 | 388 | ||
381 | #if ENABLE_FEATURE_IFUPDOWN_IP | 389 | # if ENABLE_FEATURE_IFUPDOWN_IP |
382 | static int FAST_FUNC v4tunnel_up(struct interface_defn_t *ifd, execfn *exec) | 390 | static int FAST_FUNC v4tunnel_up(struct interface_defn_t *ifd, execfn *exec) |
383 | { | 391 | { |
384 | int result; | 392 | int result; |
@@ -394,14 +402,15 @@ static int FAST_FUNC v4tunnel_down(struct interface_defn_t * ifd, execfn * exec) | |||
394 | { | 402 | { |
395 | return execute("ip tunnel del %iface%", ifd, exec); | 403 | return execute("ip tunnel del %iface%", ifd, exec); |
396 | } | 404 | } |
397 | #endif | 405 | # endif |
398 | 406 | ||
399 | static const struct method_t methods6[] = { | 407 | static const struct method_t methods6[] = { |
400 | #if ENABLE_FEATURE_IFUPDOWN_IP | 408 | # if ENABLE_FEATURE_IFUPDOWN_IP |
401 | { "v4tunnel", v4tunnel_up, v4tunnel_down, }, | 409 | { "v4tunnel" , v4tunnel_up , v4tunnel_down , }, |
402 | #endif | 410 | # endif |
403 | { "static", static_up6, static_down6, }, | 411 | { "static" , static_up6 , static_down6 , }, |
404 | { "loopback", loopback_up6, loopback_down6, }, | 412 | { "manual" , manual_up_down6 , manual_up_down6 , }, |
413 | { "loopback" , loopback_up6 , loopback_down6 , }, | ||
405 | }; | 414 | }; |
406 | 415 | ||
407 | static const struct address_family_t addr_inet6 = { | 416 | static const struct address_family_t addr_inet6 = { |
@@ -409,43 +418,46 @@ static const struct address_family_t addr_inet6 = { | |||
409 | ARRAY_SIZE(methods6), | 418 | ARRAY_SIZE(methods6), |
410 | methods6 | 419 | methods6 |
411 | }; | 420 | }; |
421 | |||
412 | #endif /* FEATURE_IFUPDOWN_IPV6 */ | 422 | #endif /* FEATURE_IFUPDOWN_IPV6 */ |
413 | 423 | ||
424 | |||
414 | #if ENABLE_FEATURE_IFUPDOWN_IPV4 | 425 | #if ENABLE_FEATURE_IFUPDOWN_IPV4 |
426 | |||
415 | static int FAST_FUNC loopback_up(struct interface_defn_t *ifd, execfn *exec) | 427 | static int FAST_FUNC loopback_up(struct interface_defn_t *ifd, execfn *exec) |
416 | { | 428 | { |
417 | #if ENABLE_FEATURE_IFUPDOWN_IP | 429 | # if ENABLE_FEATURE_IFUPDOWN_IP |
418 | int result; | 430 | int result; |
419 | result = execute("ip addr add 127.0.0.1/8 dev %iface%", ifd, exec); | 431 | result = execute("ip addr add 127.0.0.1/8 dev %iface%", ifd, exec); |
420 | result += execute("ip link set %iface% up", ifd, exec); | 432 | result += execute("ip link set %iface% up", ifd, exec); |
421 | return ((result == 2) ? 2 : 0); | 433 | return ((result == 2) ? 2 : 0); |
422 | #else | 434 | # else |
423 | return execute("ifconfig %iface% 127.0.0.1 up", ifd, exec); | 435 | return execute("ifconfig %iface% 127.0.0.1 up", ifd, exec); |
424 | #endif | 436 | # endif |
425 | } | 437 | } |
426 | 438 | ||
427 | static int FAST_FUNC loopback_down(struct interface_defn_t *ifd, execfn *exec) | 439 | static int FAST_FUNC loopback_down(struct interface_defn_t *ifd, execfn *exec) |
428 | { | 440 | { |
429 | #if ENABLE_FEATURE_IFUPDOWN_IP | 441 | # if ENABLE_FEATURE_IFUPDOWN_IP |
430 | int result; | 442 | int result; |
431 | result = execute("ip addr flush dev %iface%", ifd, exec); | 443 | result = execute("ip addr flush dev %iface%", ifd, exec); |
432 | result += execute("ip link set %iface% down", ifd, exec); | 444 | result += execute("ip link set %iface% down", ifd, exec); |
433 | return ((result == 2) ? 2 : 0); | 445 | return ((result == 2) ? 2 : 0); |
434 | #else | 446 | # else |
435 | return execute("ifconfig %iface% 127.0.0.1 down", ifd, exec); | 447 | return execute("ifconfig %iface% 127.0.0.1 down", ifd, exec); |
436 | #endif | 448 | # endif |
437 | } | 449 | } |
438 | 450 | ||
439 | static int FAST_FUNC static_up(struct interface_defn_t *ifd, execfn *exec) | 451 | static int FAST_FUNC static_up(struct interface_defn_t *ifd, execfn *exec) |
440 | { | 452 | { |
441 | int result; | 453 | int result; |
442 | #if ENABLE_FEATURE_IFUPDOWN_IP | 454 | # if ENABLE_FEATURE_IFUPDOWN_IP |
443 | result = execute("ip addr add %address%/%bnmask%[[ broadcast %broadcast%]] " | 455 | result = execute("ip addr add %address%/%bnmask%[[ broadcast %broadcast%]] " |
444 | "dev %iface%[[ peer %pointopoint%]][[ label %label%]]", ifd, exec); | 456 | "dev %iface%[[ peer %pointopoint%]][[ label %label%]]", ifd, exec); |
445 | result += execute("ip link set[[ mtu %mtu%]][[ addr %hwaddress%]] %iface% up", ifd, exec); | 457 | result += execute("ip link set[[ mtu %mtu%]][[ addr %hwaddress%]] %iface% up", ifd, exec); |
446 | result += execute("[[ip route add default via %gateway% dev %iface%]]", ifd, exec); | 458 | result += execute("[[ip route add default via %gateway% dev %iface%]]", ifd, exec); |
447 | return ((result == 3) ? 3 : 0); | 459 | return ((result == 3) ? 3 : 0); |
448 | #else | 460 | # else |
449 | /* ifconfig said to set iface up before it processes hw %hwaddress%, | 461 | /* ifconfig said to set iface up before it processes hw %hwaddress%, |
450 | * which then of course fails. Thus we run two separate ifconfig */ | 462 | * which then of course fails. Thus we run two separate ifconfig */ |
451 | result = execute("ifconfig %iface%[[ hw %hwaddress%]][[ media %media%]][[ mtu %mtu%]] up", | 463 | result = execute("ifconfig %iface%[[ hw %hwaddress%]][[ media %media%]][[ mtu %mtu%]] up", |
@@ -455,26 +467,26 @@ static int FAST_FUNC static_up(struct interface_defn_t *ifd, execfn *exec) | |||
455 | ifd, exec); | 467 | ifd, exec); |
456 | result += execute("[[route add default gw %gateway% %iface%]]", ifd, exec); | 468 | result += execute("[[route add default gw %gateway% %iface%]]", ifd, exec); |
457 | return ((result == 3) ? 3 : 0); | 469 | return ((result == 3) ? 3 : 0); |
458 | #endif | 470 | # endif |
459 | } | 471 | } |
460 | 472 | ||
461 | static int FAST_FUNC static_down(struct interface_defn_t *ifd, execfn *exec) | 473 | static int FAST_FUNC static_down(struct interface_defn_t *ifd, execfn *exec) |
462 | { | 474 | { |
463 | int result; | 475 | int result; |
464 | #if ENABLE_FEATURE_IFUPDOWN_IP | 476 | # if ENABLE_FEATURE_IFUPDOWN_IP |
465 | result = execute("ip addr flush dev %iface%", ifd, exec); | 477 | result = execute("ip addr flush dev %iface%", ifd, exec); |
466 | result += execute("ip link set %iface% down", ifd, exec); | 478 | result += execute("ip link set %iface% down", ifd, exec); |
467 | #else | 479 | # else |
468 | /* result = execute("[[route del default gw %gateway% %iface%]]", ifd, exec); */ | 480 | /* result = execute("[[route del default gw %gateway% %iface%]]", ifd, exec); */ |
469 | /* Bringing the interface down deletes the routes in itself. | 481 | /* Bringing the interface down deletes the routes in itself. |
470 | Otherwise this fails if we reference 'gateway' when using this from dhcp_down */ | 482 | Otherwise this fails if we reference 'gateway' when using this from dhcp_down */ |
471 | result = 1; | 483 | result = 1; |
472 | result += execute("ifconfig %iface% down", ifd, exec); | 484 | result += execute("ifconfig %iface% down", ifd, exec); |
473 | #endif | 485 | # endif |
474 | return ((result == 2) ? 2 : 0); | 486 | return ((result == 2) ? 2 : 0); |
475 | } | 487 | } |
476 | 488 | ||
477 | #if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP | 489 | # if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP |
478 | struct dhcp_client_t { | 490 | struct dhcp_client_t { |
479 | const char *name; | 491 | const char *name; |
480 | const char *startcmd; | 492 | const char *startcmd; |
@@ -500,21 +512,21 @@ static const struct dhcp_client_t ext_dhcp_clients[] = { | |||
500 | "kill `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", | 512 | "kill `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", |
501 | }, | 513 | }, |
502 | }; | 514 | }; |
503 | #endif /* ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCPC */ | 515 | # endif /* FEATURE_IFUPDOWN_EXTERNAL_DHCPC */ |
504 | 516 | ||
505 | #if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP | 517 | # if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP |
506 | static int FAST_FUNC dhcp_up(struct interface_defn_t *ifd, execfn *exec) | 518 | static int FAST_FUNC dhcp_up(struct interface_defn_t *ifd, execfn *exec) |
507 | { | 519 | { |
508 | unsigned i; | 520 | unsigned i; |
509 | #if ENABLE_FEATURE_IFUPDOWN_IP | 521 | # if ENABLE_FEATURE_IFUPDOWN_IP |
510 | /* ip doesn't up iface when it configures it (unlike ifconfig) */ | 522 | /* ip doesn't up iface when it configures it (unlike ifconfig) */ |
511 | if (!execute("ip link set[[ addr %hwaddress%]] %iface% up", ifd, exec)) | 523 | if (!execute("ip link set[[ addr %hwaddress%]] %iface% up", ifd, exec)) |
512 | return 0; | 524 | return 0; |
513 | #else | 525 | # else |
514 | /* needed if we have hwaddress on dhcp iface */ | 526 | /* needed if we have hwaddress on dhcp iface */ |
515 | if (!execute("ifconfig %iface%[[ hw %hwaddress%]] up", ifd, exec)) | 527 | if (!execute("ifconfig %iface%[[ hw %hwaddress%]] up", ifd, exec)) |
516 | return 0; | 528 | return 0; |
517 | #endif | 529 | # endif |
518 | for (i = 0; i < ARRAY_SIZE(ext_dhcp_clients); i++) { | 530 | for (i = 0; i < ARRAY_SIZE(ext_dhcp_clients); i++) { |
519 | if (exists_execable(ext_dhcp_clients[i].name)) | 531 | if (exists_execable(ext_dhcp_clients[i].name)) |
520 | return execute(ext_dhcp_clients[i].startcmd, ifd, exec); | 532 | return execute(ext_dhcp_clients[i].startcmd, ifd, exec); |
@@ -522,31 +534,31 @@ static int FAST_FUNC dhcp_up(struct interface_defn_t *ifd, execfn *exec) | |||
522 | bb_error_msg("no dhcp clients found"); | 534 | bb_error_msg("no dhcp clients found"); |
523 | return 0; | 535 | return 0; |
524 | } | 536 | } |
525 | #elif ENABLE_UDHCPC | 537 | # elif ENABLE_UDHCPC |
526 | static int FAST_FUNC dhcp_up(struct interface_defn_t *ifd, execfn *exec) | 538 | static int FAST_FUNC dhcp_up(struct interface_defn_t *ifd, execfn *exec) |
527 | { | 539 | { |
528 | #if ENABLE_FEATURE_IFUPDOWN_IP | 540 | # if ENABLE_FEATURE_IFUPDOWN_IP |
529 | /* ip doesn't up iface when it configures it (unlike ifconfig) */ | 541 | /* ip doesn't up iface when it configures it (unlike ifconfig) */ |
530 | if (!execute("ip link set[[ addr %hwaddress%]] %iface% up", ifd, exec)) | 542 | if (!execute("ip link set[[ addr %hwaddress%]] %iface% up", ifd, exec)) |
531 | return 0; | 543 | return 0; |
532 | #else | 544 | # else |
533 | /* needed if we have hwaddress on dhcp iface */ | 545 | /* needed if we have hwaddress on dhcp iface */ |
534 | if (!execute("ifconfig %iface%[[ hw %hwaddress%]] up", ifd, exec)) | 546 | if (!execute("ifconfig %iface%[[ hw %hwaddress%]] up", ifd, exec)) |
535 | return 0; | 547 | return 0; |
536 | #endif | 548 | # endif |
537 | return execute("udhcpc " UDHCPC_CMD_OPTIONS " -p /var/run/udhcpc.%iface%.pid " | 549 | return execute("udhcpc " UDHCPC_CMD_OPTIONS " -p /var/run/udhcpc.%iface%.pid " |
538 | "-i %iface%[[ -H %hostname%]][[ -c %client%]][[ -s %script%]][[ %udhcpc_opts%]]", | 550 | "-i %iface%[[ -H %hostname%]][[ -c %client%]][[ -s %script%]][[ %udhcpc_opts%]]", |
539 | ifd, exec); | 551 | ifd, exec); |
540 | } | 552 | } |
541 | #else | 553 | # else |
542 | static int FAST_FUNC dhcp_up(struct interface_defn_t *ifd UNUSED_PARAM, | 554 | static int FAST_FUNC dhcp_up(struct interface_defn_t *ifd UNUSED_PARAM, |
543 | execfn *exec UNUSED_PARAM) | 555 | execfn *exec UNUSED_PARAM) |
544 | { | 556 | { |
545 | return 0; /* no dhcp support */ | 557 | return 0; /* no dhcp support */ |
546 | } | 558 | } |
547 | #endif | 559 | # endif |
548 | 560 | ||
549 | #if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP | 561 | # if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP |
550 | static int FAST_FUNC dhcp_down(struct interface_defn_t *ifd, execfn *exec) | 562 | static int FAST_FUNC dhcp_down(struct interface_defn_t *ifd, execfn *exec) |
551 | { | 563 | { |
552 | int result = 0; | 564 | int result = 0; |
@@ -569,7 +581,7 @@ static int FAST_FUNC dhcp_down(struct interface_defn_t *ifd, execfn *exec) | |||
569 | result += static_down(ifd, exec); | 581 | result += static_down(ifd, exec); |
570 | return ((result == 3) ? 3 : 0); | 582 | return ((result == 3) ? 3 : 0); |
571 | } | 583 | } |
572 | #elif ENABLE_UDHCPC | 584 | # elif ENABLE_UDHCPC |
573 | static int FAST_FUNC dhcp_down(struct interface_defn_t *ifd, execfn *exec) | 585 | static int FAST_FUNC dhcp_down(struct interface_defn_t *ifd, execfn *exec) |
574 | { | 586 | { |
575 | int result; | 587 | int result; |
@@ -586,13 +598,13 @@ static int FAST_FUNC dhcp_down(struct interface_defn_t *ifd, execfn *exec) | |||
586 | result += static_down(ifd, exec); | 598 | result += static_down(ifd, exec); |
587 | return ((result == 3) ? 3 : 0); | 599 | return ((result == 3) ? 3 : 0); |
588 | } | 600 | } |
589 | #else | 601 | # else |
590 | static int FAST_FUNC dhcp_down(struct interface_defn_t *ifd UNUSED_PARAM, | 602 | static int FAST_FUNC dhcp_down(struct interface_defn_t *ifd UNUSED_PARAM, |
591 | execfn *exec UNUSED_PARAM) | 603 | execfn *exec UNUSED_PARAM) |
592 | { | 604 | { |
593 | return 0; /* no dhcp support */ | 605 | return 0; /* no dhcp support */ |
594 | } | 606 | } |
595 | #endif | 607 | # endif |
596 | 608 | ||
597 | static int FAST_FUNC manual_up_down(struct interface_defn_t *ifd UNUSED_PARAM, execfn *exec UNUSED_PARAM) | 609 | static int FAST_FUNC manual_up_down(struct interface_defn_t *ifd UNUSED_PARAM, execfn *exec UNUSED_PARAM) |
598 | { | 610 | { |
@@ -644,7 +656,8 @@ static const struct address_family_t addr_inet = { | |||
644 | methods | 656 | methods |
645 | }; | 657 | }; |
646 | 658 | ||
647 | #endif /* if ENABLE_FEATURE_IFUPDOWN_IPV4 */ | 659 | #endif /* FEATURE_IFUPDOWN_IPV4 */ |
660 | |||
648 | 661 | ||
649 | /* Returns pointer to the next word, or NULL. | 662 | /* Returns pointer to the next word, or NULL. |
650 | * In 1st case, advances *buf to the word after this one. | 663 | * In 1st case, advances *buf to the word after this one. |
diff --git a/networking/inetd.c b/networking/inetd.c index 7030062b6..fb00c6cd7 100644 --- a/networking/inetd.c +++ b/networking/inetd.c | |||
@@ -295,7 +295,7 @@ struct globals { | |||
295 | struct rlimit rlim_ofile; | 295 | struct rlimit rlim_ofile; |
296 | servtab_t *serv_list; | 296 | servtab_t *serv_list; |
297 | int global_queuelen; | 297 | int global_queuelen; |
298 | int maxsock; /* max fd# in allsock, -1: unknown */ | 298 | int maxsock; /* max fd# in allsock, -1: unknown */ |
299 | /* whenever maxsock grows, prev_maxsock is set to new maxsock, | 299 | /* whenever maxsock grows, prev_maxsock is set to new maxsock, |
300 | * but if maxsock is set to -1, prev_maxsock is not changed */ | 300 | * but if maxsock is set to -1, prev_maxsock is not changed */ |
301 | int prev_maxsock; | 301 | int prev_maxsock; |
@@ -778,6 +778,12 @@ static servtab_t *parse_one_line(void) | |||
778 | argc = 0; | 778 | argc = 0; |
779 | while ((arg = token[6+argc]) != NULL && argc < MAXARGV) | 779 | while ((arg = token[6+argc]) != NULL && argc < MAXARGV) |
780 | sep->se_argv[argc++] = xstrdup(arg); | 780 | sep->se_argv[argc++] = xstrdup(arg); |
781 | /* Some inetd.conf files have no argv's, not even argv[0]. | ||
782 | * Fix them up. | ||
783 | * (Technically, programs can be execed with argv[0] = NULL, | ||
784 | * but many programs do not like that at all) */ | ||
785 | if (argc == 0) | ||
786 | sep->se_argv[0] = xstrdup(sep->se_program); | ||
781 | 787 | ||
782 | /* catch mixups. "<service> stream udp ..." == wtf */ | 788 | /* catch mixups. "<service> stream udp ..." == wtf */ |
783 | if (sep->se_socktype == SOCK_STREAM) { | 789 | if (sep->se_socktype == SOCK_STREAM) { |
diff --git a/networking/ip.c b/networking/ip.c index 7b1e2eb6a..350656cef 100644 --- a/networking/ip.c +++ b/networking/ip.c | |||
@@ -1,13 +1,11 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * "ip" utility frontend. | ||
4 | * | ||
5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 3 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
6 | * | 4 | * |
7 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | 5 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
8 | * | 6 | * |
9 | * Changes: | 7 | * Changes: |
10 | * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses | 8 | * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses |
11 | * Bernhard Reutner-Fischer rewrote to use index_in_substr_array | 9 | * Bernhard Reutner-Fischer rewrote to use index_in_substr_array |
12 | */ | 10 | */ |
13 | 11 | ||
diff --git a/networking/ipcalc.c b/networking/ipcalc.c index d4aa885c6..acbaa4ac5 100644 --- a/networking/ipcalc.c +++ b/networking/ipcalc.c | |||
@@ -15,9 +15,9 @@ | |||
15 | /* After libbb.h, because on some systems it needs other includes */ | 15 | /* After libbb.h, because on some systems it needs other includes */ |
16 | #include <arpa/inet.h> | 16 | #include <arpa/inet.h> |
17 | 17 | ||
18 | #define CLASS_A_NETMASK ntohl(0xFF000000) | 18 | #define CLASS_A_NETMASK ntohl(0xFF000000) |
19 | #define CLASS_B_NETMASK ntohl(0xFFFF0000) | 19 | #define CLASS_B_NETMASK ntohl(0xFFFF0000) |
20 | #define CLASS_C_NETMASK ntohl(0xFFFFFF00) | 20 | #define CLASS_C_NETMASK ntohl(0xFFFFFF00) |
21 | 21 | ||
22 | static unsigned long get_netmask(unsigned long ipaddr) | 22 | static unsigned long get_netmask(unsigned long ipaddr) |
23 | { | 23 | { |
diff --git a/networking/libiproute/ip_parse_common_args.c b/networking/libiproute/ip_parse_common_args.c index bf01528c4..59c759b23 100644 --- a/networking/libiproute/ip_parse_common_args.c +++ b/networking/libiproute/ip_parse_common_args.c | |||
@@ -1,18 +1,15 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * ip.c "ip" utility frontend. | 3 | * This program is free software; you can redistribute it and/or |
4 | * | 4 | * modify it under the terms of the GNU General Public License |
5 | * This program is free software; you can redistribute it and/or | 5 | * as published by the Free Software Foundation; either version |
6 | * modify it under the terms of the GNU General Public License | 6 | * 2 of the License, or (at your option) any later version. |
7 | * as published by the Free Software Foundation; either version | ||
8 | * 2 of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | ||
11 | * | 7 | * |
8 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | ||
12 | * | 9 | * |
13 | * Changes: | 10 | * Changes: |
14 | * | 11 | * |
15 | * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses | 12 | * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses |
16 | */ | 13 | */ |
17 | 14 | ||
18 | #include "ip_common.h" /* #include "libbb.h" is inside */ | 15 | #include "ip_common.h" /* #include "libbb.h" is inside */ |
diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c index 1be03a6c3..397a8ee34 100644 --- a/networking/libiproute/ipaddress.c +++ b/networking/libiproute/ipaddress.c | |||
@@ -1,13 +1,11 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * ipaddress.c "ip address". | ||
4 | * | ||
5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 3 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
6 | * | 4 | * |
7 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | 5 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
8 | * | 6 | * |
9 | * Changes: | 7 | * Changes: |
10 | * Laszlo Valko <valko@linux.karinthy.hu> 990223: address label must be zero terminated | 8 | * Laszlo Valko <valko@linux.karinthy.hu> 990223: address label must be zero terminated |
11 | */ | 9 | */ |
12 | 10 | ||
13 | #include <fnmatch.h> | 11 | #include <fnmatch.h> |
@@ -20,7 +18,7 @@ | |||
20 | 18 | ||
21 | #ifndef IFF_LOWER_UP | 19 | #ifndef IFF_LOWER_UP |
22 | /* from linux/if.h */ | 20 | /* from linux/if.h */ |
23 | #define IFF_LOWER_UP 0x10000 /* driver signals L1 up*/ | 21 | #define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ |
24 | #endif | 22 | #endif |
25 | 23 | ||
26 | struct filter_t { | 24 | struct filter_t { |
@@ -365,7 +363,7 @@ static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM, | |||
365 | 363 | ||
366 | struct nlmsg_list { | 364 | struct nlmsg_list { |
367 | struct nlmsg_list *next; | 365 | struct nlmsg_list *next; |
368 | struct nlmsghdr h; | 366 | struct nlmsghdr h; |
369 | }; | 367 | }; |
370 | 368 | ||
371 | static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo) | 369 | static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo) |
diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c index c5ba294aa..82ab979a5 100644 --- a/networking/libiproute/iplink.c +++ b/networking/libiproute/iplink.c | |||
@@ -1,7 +1,5 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * iplink.c "ip link". | ||
4 | * | ||
5 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | 3 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
6 | * | 4 | * |
7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
@@ -296,9 +294,9 @@ static int do_change(char **argv, const unsigned rtm) | |||
296 | }; | 294 | }; |
297 | struct rtnl_handle rth; | 295 | struct rtnl_handle rth; |
298 | struct { | 296 | struct { |
299 | struct nlmsghdr n; | 297 | struct nlmsghdr n; |
300 | struct ifinfomsg i; | 298 | struct ifinfomsg i; |
301 | char buf[1024]; | 299 | char buf[1024]; |
302 | } req; | 300 | } req; |
303 | smalluint arg; | 301 | smalluint arg; |
304 | char *name_str = NULL, *link_str = NULL, *type_str = NULL, *dev_str = NULL; | 302 | char *name_str = NULL, *link_str = NULL, *type_str = NULL, *dev_str = NULL; |
diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c index 1696e6a34..f6071b463 100644 --- a/networking/libiproute/iproute.c +++ b/networking/libiproute/iproute.c | |||
@@ -1,19 +1,16 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * iproute.c "ip route". | ||
4 | * | ||
5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 3 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
6 | * | 4 | * |
7 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | 5 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
8 | * | ||
9 | * | 6 | * |
10 | * Changes: | 7 | * Changes: |
11 | * | 8 | * |
12 | * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses | 9 | * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses |
13 | * Kunihiro Ishiguro <kunihiro@zebra.org> 001102: rtnh_ifindex was not initialized | 10 | * Kunihiro Ishiguro <kunihiro@zebra.org> 001102: rtnh_ifindex was not initialized |
14 | */ | 11 | */ |
15 | 12 | ||
16 | #include "ip_common.h" /* #include "libbb.h" is inside */ | 13 | #include "ip_common.h" /* #include "libbb.h" is inside */ |
17 | #include "rt_names.h" | 14 | #include "rt_names.h" |
18 | #include "utils.h" | 15 | #include "utils.h" |
19 | 16 | ||
@@ -327,9 +324,9 @@ IF_FEATURE_IP_RULE(ARG_table,) | |||
327 | }; | 324 | }; |
328 | struct rtnl_handle rth; | 325 | struct rtnl_handle rth; |
329 | struct { | 326 | struct { |
330 | struct nlmsghdr n; | 327 | struct nlmsghdr n; |
331 | struct rtmsg r; | 328 | struct rtmsg r; |
332 | char buf[1024]; | 329 | char buf[1024]; |
333 | } req; | 330 | } req; |
334 | char mxbuf[256]; | 331 | char mxbuf[256]; |
335 | struct rtattr * mxrta = (void*)mxbuf; | 332 | struct rtattr * mxrta = (void*)mxbuf; |
@@ -791,8 +788,8 @@ static int iproute_get(char **argv) | |||
791 | } | 788 | } |
792 | req.r.rtm_dst_len = addr.bitlen; | 789 | req.r.rtm_dst_len = addr.bitlen; |
793 | } | 790 | } |
794 | argv++; | ||
795 | } | 791 | } |
792 | argv++; | ||
796 | } | 793 | } |
797 | 794 | ||
798 | if (req.r.rtm_dst_len == 0) { | 795 | if (req.r.rtm_dst_len == 0) { |
diff --git a/networking/libiproute/iprule.c b/networking/libiproute/iprule.c index 3af6a83a8..dd3265c7c 100644 --- a/networking/libiproute/iprule.c +++ b/networking/libiproute/iprule.c | |||
@@ -1,18 +1,15 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * iprule.c "ip rule". | 3 | * This program is free software; you can redistribute it and/or |
4 | * | 4 | * modify it under the terms of the GNU General Public License |
5 | * This program is free software; you can redistribute it and/or | 5 | * as published by the Free Software Foundation; either version |
6 | * modify it under the terms of the GNU General Public License | 6 | * 2 of the License, or (at your option) any later version. |
7 | * as published by the Free Software Foundation; either version | ||
8 | * 2 of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | ||
11 | * | 7 | * |
8 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | ||
12 | * | 9 | * |
13 | * Changes: | 10 | * Changes: |
14 | * | 11 | * |
15 | * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses | 12 | * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses |
16 | * initially integrated into busybox by Bernhard Reutner-Fischer | 13 | * initially integrated into busybox by Bernhard Reutner-Fischer |
17 | */ | 14 | */ |
18 | 15 | ||
@@ -191,9 +188,9 @@ static int iprule_modify(int cmd, char **argv) | |||
191 | bool table_ok = 0; | 188 | bool table_ok = 0; |
192 | struct rtnl_handle rth; | 189 | struct rtnl_handle rth; |
193 | struct { | 190 | struct { |
194 | struct nlmsghdr n; | 191 | struct nlmsghdr n; |
195 | struct rtmsg r; | 192 | struct rtmsg r; |
196 | char buf[1024]; | 193 | char buf[1024]; |
197 | } req; | 194 | } req; |
198 | smalluint key; | 195 | smalluint key; |
199 | 196 | ||
diff --git a/networking/libiproute/iptunnel.c b/networking/libiproute/iptunnel.c index bce373d05..5942feafc 100644 --- a/networking/libiproute/iptunnel.c +++ b/networking/libiproute/iptunnel.c | |||
@@ -1,16 +1,14 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * iptunnel.c "ip tunnel" | ||
4 | * | ||
5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 3 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
6 | * | 4 | * |
7 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | 5 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
8 | * | 6 | * |
9 | * Changes: | 7 | * Changes: |
10 | * | 8 | * |
11 | * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses | 9 | * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses |
12 | * Rani Assaf <rani@magic.metawire.com> 980930: do not allow key for ipip/sit | 10 | * Rani Assaf <rani@magic.metawire.com> 980930: do not allow key for ipip/sit |
13 | * Phil Karn <karn@ka9q.ampr.org> 990408: "pmtudisc" flag | 11 | * Phil Karn <karn@ka9q.ampr.org> 990408: "pmtudisc" flag |
14 | */ | 12 | */ |
15 | 13 | ||
16 | #include <netinet/ip.h> | 14 | #include <netinet/ip.h> |
diff --git a/networking/libiproute/libnetlink.c b/networking/libiproute/libnetlink.c index 8da80b2fc..7291ee2f1 100644 --- a/networking/libiproute/libnetlink.c +++ b/networking/libiproute/libnetlink.c | |||
@@ -1,7 +1,5 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * RTnetlink service routines. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | 3 | * This program is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU General Public License | 4 | * modify it under the terms of the GNU General Public License |
7 | * as published by the Free Software Foundation; either version | 5 | * as published by the Free Software Foundation; either version |
@@ -74,8 +72,8 @@ int FAST_FUNC rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, in | |||
74 | struct iovec iov[2] = { { &nlh, sizeof(nlh) }, { req, len } }; | 72 | struct iovec iov[2] = { { &nlh, sizeof(nlh) }, { req, len } }; |
75 | struct msghdr msg = { | 73 | struct msghdr msg = { |
76 | (void*)&nladdr, sizeof(nladdr), | 74 | (void*)&nladdr, sizeof(nladdr), |
77 | iov, 2, | 75 | iov, 2, |
78 | NULL, 0, | 76 | NULL, 0, |
79 | 0 | 77 | 0 |
80 | }; | 78 | }; |
81 | 79 | ||
@@ -108,8 +106,8 @@ static int rtnl_dump_filter(struct rtnl_handle *rth, | |||
108 | 106 | ||
109 | struct msghdr msg = { | 107 | struct msghdr msg = { |
110 | (void*)&nladdr, sizeof(nladdr), | 108 | (void*)&nladdr, sizeof(nladdr), |
111 | &iov, 1, | 109 | &iov, 1, |
112 | NULL, 0, | 110 | NULL, 0, |
113 | 0 | 111 | 0 |
114 | }; | 112 | }; |
115 | 113 | ||
@@ -214,8 +212,8 @@ int FAST_FUNC rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, | |||
214 | char *buf = xmalloc(8*1024); /* avoid big stack buffer */ | 212 | char *buf = xmalloc(8*1024); /* avoid big stack buffer */ |
215 | struct msghdr msg = { | 213 | struct msghdr msg = { |
216 | (void*)&nladdr, sizeof(nladdr), | 214 | (void*)&nladdr, sizeof(nladdr), |
217 | &iov, 1, | 215 | &iov, 1, |
218 | NULL, 0, | 216 | NULL, 0, |
219 | 0 | 217 | 0 |
220 | }; | 218 | }; |
221 | 219 | ||
diff --git a/networking/libiproute/libnetlink.h b/networking/libiproute/libnetlink.h index 4e4d5b7b9..51bee2d67 100644 --- a/networking/libiproute/libnetlink.h +++ b/networking/libiproute/libnetlink.h | |||
@@ -11,11 +11,11 @@ | |||
11 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | 11 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN |
12 | 12 | ||
13 | struct rtnl_handle { | 13 | struct rtnl_handle { |
14 | int fd; | 14 | int fd; |
15 | struct sockaddr_nl local; | 15 | struct sockaddr_nl local; |
16 | struct sockaddr_nl peer; | 16 | struct sockaddr_nl peer; |
17 | uint32_t seq; | 17 | uint32_t seq; |
18 | uint32_t dump; | 18 | uint32_t dump; |
19 | }; | 19 | }; |
20 | 20 | ||
21 | extern void xrtnl_open(struct rtnl_handle *rth) FAST_FUNC; | 21 | extern void xrtnl_open(struct rtnl_handle *rth) FAST_FUNC; |
diff --git a/networking/libiproute/ll_addr.c b/networking/libiproute/ll_addr.c index c2c01305d..33a54ea6c 100644 --- a/networking/libiproute/ll_addr.c +++ b/networking/libiproute/ll_addr.c | |||
@@ -1,13 +1,11 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * ll_addr.c | 3 | * This program is free software; you can redistribute it and/or |
4 | * modify it under the terms of the GNU General Public License | ||
5 | * as published by the Free Software Foundation; either version | ||
6 | * 2 of the License, or (at your option) any later version. | ||
4 | * | 7 | * |
5 | * This program is free software; you can redistribute it and/or | 8 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version | ||
8 | * 2 of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | ||
11 | */ | 9 | */ |
12 | 10 | ||
13 | #include <net/if_arp.h> | 11 | #include <net/if_arp.h> |
diff --git a/networking/libiproute/ll_map.c b/networking/libiproute/ll_map.c index 246b9e33a..27cd90f34 100644 --- a/networking/libiproute/ll_map.c +++ b/networking/libiproute/ll_map.c | |||
@@ -1,17 +1,14 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * ll_map.c | 3 | * This program is free software; you can redistribute it and/or |
4 | * | 4 | * modify it under the terms of the GNU General Public License |
5 | * This program is free software; you can redistribute it and/or | 5 | * as published by the Free Software Foundation; either version |
6 | * modify it under the terms of the GNU General Public License | 6 | * 2 of the License, or (at your option) any later version. |
7 | * as published by the Free Software Foundation; either version | ||
8 | * 2 of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | ||
11 | * | 7 | * |
8 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | ||
12 | */ | 9 | */ |
13 | 10 | ||
14 | #include <net/if.h> /* struct ifreq and co. */ | 11 | #include <net/if.h> /* struct ifreq and co. */ |
15 | 12 | ||
16 | #include "libbb.h" | 13 | #include "libbb.h" |
17 | #include "libnetlink.h" | 14 | #include "libnetlink.h" |
diff --git a/networking/libiproute/ll_proto.c b/networking/libiproute/ll_proto.c index 1cd576f1d..04925ecf6 100644 --- a/networking/libiproute/ll_proto.c +++ b/networking/libiproute/ll_proto.c | |||
@@ -1,13 +1,11 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * ll_proto.c | 3 | * This program is free software; you can redistribute it and/or |
4 | * modify it under the terms of the GNU General Public License | ||
5 | * as published by the Free Software Foundation; either version | ||
6 | * 2 of the License, or (at your option) any later version. | ||
4 | * | 7 | * |
5 | * This program is free software; you can redistribute it and/or | 8 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version | ||
8 | * 2 of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | ||
11 | */ | 9 | */ |
12 | 10 | ||
13 | #include "libbb.h" | 11 | #include "libbb.h" |
diff --git a/networking/libiproute/ll_types.c b/networking/libiproute/ll_types.c index 3861c2870..38b6c0516 100644 --- a/networking/libiproute/ll_types.c +++ b/networking/libiproute/ll_types.c | |||
@@ -1,13 +1,11 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * ll_types.c | 3 | * This program is free software; you can redistribute it and/or |
4 | * modify it under the terms of the GNU General Public License | ||
5 | * as published by the Free Software Foundation; either version | ||
6 | * 2 of the License, or (at your option) any later version. | ||
4 | * | 7 | * |
5 | * This program is free software; you can redistribute it and/or | 8 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version | ||
8 | * 2 of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | ||
11 | */ | 9 | */ |
12 | #include <arpa/inet.h> | 10 | #include <arpa/inet.h> |
13 | #include <linux/if_arp.h> | 11 | #include <linux/if_arp.h> |
diff --git a/networking/libiproute/rt_names.c b/networking/libiproute/rt_names.c index 8dd16e3d3..c474ab903 100644 --- a/networking/libiproute/rt_names.c +++ b/networking/libiproute/rt_names.c | |||
@@ -1,13 +1,11 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * rt_names.c rtnetlink names DB. | 3 | * This program is free software; you can redistribute it and/or |
4 | * modify it under the terms of the GNU General Public License | ||
5 | * as published by the Free Software Foundation; either version | ||
6 | * 2 of the License, or (at your option) any later version. | ||
4 | * | 7 | * |
5 | * This program is free software; you can redistribute it and/or | 8 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version | ||
8 | * 2 of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | ||
11 | */ | 9 | */ |
12 | #include "libbb.h" | 10 | #include "libbb.h" |
13 | #include "rt_names.h" | 11 | #include "rt_names.h" |
diff --git a/networking/libiproute/rtm_map.c b/networking/libiproute/rtm_map.c index 5e358e105..3bab53baf 100644 --- a/networking/libiproute/rtm_map.c +++ b/networking/libiproute/rtm_map.c | |||
@@ -1,14 +1,11 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * rtm_map.c | 3 | * This program is free software; you can redistribute it and/or |
4 | * | 4 | * modify it under the terms of the GNU General Public License |
5 | * This program is free software; you can redistribute it and/or | 5 | * as published by the Free Software Foundation; either version |
6 | * modify it under the terms of the GNU General Public License | 6 | * 2 of the License, or (at your option) any later version. |
7 | * as published by the Free Software Foundation; either version | ||
8 | * 2 of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | ||
11 | * | 7 | * |
8 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | ||
12 | */ | 9 | */ |
13 | 10 | ||
14 | #include "libbb.h" | 11 | #include "libbb.h" |
diff --git a/networking/libiproute/utils.c b/networking/libiproute/utils.c index 2b646f0ea..d32db8de5 100644 --- a/networking/libiproute/utils.c +++ b/networking/libiproute/utils.c | |||
@@ -1,14 +1,12 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * utils.c | ||
4 | * | ||
5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 3 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
6 | * | 4 | * |
7 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | 5 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
8 | * | 6 | * |
9 | * Changes: | 7 | * Changes: |
10 | * | 8 | * |
11 | * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses | 9 | * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses |
12 | */ | 10 | */ |
13 | 11 | ||
14 | #include "libbb.h" | 12 | #include "libbb.h" |
diff --git a/networking/libiproute/utils.h b/networking/libiproute/utils.h index ed03e785a..93c9d25d6 100644 --- a/networking/libiproute/utils.h +++ b/networking/libiproute/utils.h | |||
@@ -17,14 +17,14 @@ extern smallint oneline; | |||
17 | extern char _SL_; | 17 | extern char _SL_; |
18 | 18 | ||
19 | #ifndef IPPROTO_ESP | 19 | #ifndef IPPROTO_ESP |
20 | #define IPPROTO_ESP 50 | 20 | #define IPPROTO_ESP 50 |
21 | #endif | 21 | #endif |
22 | #ifndef IPPROTO_AH | 22 | #ifndef IPPROTO_AH |
23 | #define IPPROTO_AH 51 | 23 | #define IPPROTO_AH 51 |
24 | #endif | 24 | #endif |
25 | 25 | ||
26 | #define SPRINT_BSIZE 64 | 26 | #define SPRINT_BSIZE 64 |
27 | #define SPRINT_BUF(x) char x[SPRINT_BSIZE] | 27 | #define SPRINT_BUF(x) char x[SPRINT_BSIZE] |
28 | 28 | ||
29 | extern void incomplete_command(void) NORETURN; | 29 | extern void incomplete_command(void) NORETURN; |
30 | 30 | ||
diff --git a/networking/nameif.c b/networking/nameif.c index 45a3229f4..d02c2c11b 100644 --- a/networking/nameif.c +++ b/networking/nameif.c | |||
@@ -21,10 +21,10 @@ | |||
21 | #endif | 21 | #endif |
22 | 22 | ||
23 | /* Taken from linux/sockios.h */ | 23 | /* Taken from linux/sockios.h */ |
24 | #define SIOCSIFNAME 0x8923 /* set interface name */ | 24 | #define SIOCSIFNAME 0x8923 /* set interface name */ |
25 | 25 | ||
26 | /* Octets in one Ethernet addr, from <linux/if_ether.h> */ | 26 | /* Octets in one Ethernet addr, from <linux/if_ether.h> */ |
27 | #define ETH_ALEN 6 | 27 | #define ETH_ALEN 6 |
28 | 28 | ||
29 | #ifndef ifr_newname | 29 | #ifndef ifr_newname |
30 | #define ifr_newname ifr_ifru.ifru_slave | 30 | #define ifr_newname ifr_ifru.ifru_slave |
diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c index 8594a67a6..e98a5dd5b 100644 --- a/networking/nc_bloaty.c +++ b/networking/nc_bloaty.c | |||
@@ -268,8 +268,7 @@ static int doexec(char **proggie) | |||
268 | dup2(0, 1); | 268 | dup2(0, 1); |
269 | /* dup2(0, 2); - do we *really* want this? NO! | 269 | /* dup2(0, 2); - do we *really* want this? NO! |
270 | * exec'ed prog can do it yourself, if needed */ | 270 | * exec'ed prog can do it yourself, if needed */ |
271 | execvp(proggie[0], proggie); | 271 | BB_EXECVP_or_die(proggie); |
272 | bb_perror_msg_and_die("can't execute '%s'", proggie[0]); | ||
273 | } | 272 | } |
274 | 273 | ||
275 | /* connect_w_timeout: | 274 | /* connect_w_timeout: |
@@ -766,7 +765,7 @@ int nc_main(int argc UNUSED_PARAM, char **argv) | |||
766 | getopt32(argv, "hnp:s:uvw:" IF_NC_SERVER("l") | 765 | getopt32(argv, "hnp:s:uvw:" IF_NC_SERVER("l") |
767 | IF_NC_EXTRA("i:o:z"), | 766 | IF_NC_EXTRA("i:o:z"), |
768 | &str_p, &str_s, &o_wait | 767 | &str_p, &str_s, &o_wait |
769 | IF_NC_EXTRA(, &str_i, &str_o, &o_verbose)); | 768 | IF_NC_EXTRA(, &str_i, &str_o), &o_verbose); |
770 | argv += optind; | 769 | argv += optind; |
771 | #if ENABLE_NC_EXTRA | 770 | #if ENABLE_NC_EXTRA |
772 | if (option_mask32 & OPT_i) /* line-interval time */ | 771 | if (option_mask32 & OPT_i) /* line-interval time */ |
diff --git a/networking/netstat.c b/networking/netstat.c index 2a83af3ac..356fb53cb 100644 --- a/networking/netstat.c +++ b/networking/netstat.c | |||
@@ -699,7 +699,7 @@ int netstat_main(int argc UNUSED_PARAM, char **argv) | |||
699 | flags |= opt; | 699 | flags |= opt; |
700 | } | 700 | } |
701 | if (flags & (NETSTAT_TCP|NETSTAT_UDP|NETSTAT_RAW)) { | 701 | if (flags & (NETSTAT_TCP|NETSTAT_UDP|NETSTAT_RAW)) { |
702 | printf("Active Internet connections "); /* xxx */ | 702 | printf("Active Internet connections "); /* xxx */ |
703 | 703 | ||
704 | if ((flags & (NETSTAT_LISTENING|NETSTAT_CONNECTED)) == (NETSTAT_LISTENING|NETSTAT_CONNECTED)) | 704 | if ((flags & (NETSTAT_LISTENING|NETSTAT_CONNECTED)) == (NETSTAT_LISTENING|NETSTAT_CONNECTED)) |
705 | printf("(servers and established)"); | 705 | printf("(servers and established)"); |
diff --git a/networking/ntpd.c b/networking/ntpd.c index b7bd239b5..8fe529edb 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c | |||
@@ -89,7 +89,7 @@ | |||
89 | //UNUSED: #define PANIC_THRESHOLD 1000 /* panic threshold (sec) */ | 89 | //UNUSED: #define PANIC_THRESHOLD 1000 /* panic threshold (sec) */ |
90 | 90 | ||
91 | #define FREQ_TOLERANCE 0.000015 /* frequency tolerance (15 PPM) */ | 91 | #define FREQ_TOLERANCE 0.000015 /* frequency tolerance (15 PPM) */ |
92 | #define BURSTPOLL 0 /* initial poll */ | 92 | #define BURSTPOLL 0 /* initial poll */ |
93 | #define MINPOLL 5 /* minimum poll interval. std ntpd uses 6 (6: 64 sec) */ | 93 | #define MINPOLL 5 /* minimum poll interval. std ntpd uses 6 (6: 64 sec) */ |
94 | #define BIGPOLL 10 /* drop to lower poll at any trouble (10: 17 min) */ | 94 | #define BIGPOLL 10 /* drop to lower poll at any trouble (10: 17 min) */ |
95 | #define MAXPOLL 12 /* maximum poll interval (12: 1.1h, 17: 36.4h). std ntpd uses 17 */ | 95 | #define MAXPOLL 12 /* maximum poll interval (12: 1.1h, 17: 36.4h). std ntpd uses 17 */ |
@@ -865,7 +865,7 @@ fit(peer_t *p, double rd) | |||
865 | VERB3 bb_error_msg("peer %s unfit for selection: unreachable", p->p_dotted); | 865 | VERB3 bb_error_msg("peer %s unfit for selection: unreachable", p->p_dotted); |
866 | return 0; | 866 | return 0; |
867 | } | 867 | } |
868 | #if 0 /* we filter out such packets earlier */ | 868 | #if 0 /* we filter out such packets earlier */ |
869 | if ((p->lastpkt_status & LI_ALARM) == LI_ALARM | 869 | if ((p->lastpkt_status & LI_ALARM) == LI_ALARM |
870 | || p->lastpkt_stratum >= MAXSTRAT | 870 | || p->lastpkt_stratum >= MAXSTRAT |
871 | ) { | 871 | ) { |
@@ -2110,7 +2110,7 @@ direct_freq(double fp_offset) | |||
2110 | } | 2110 | } |
2111 | 2111 | ||
2112 | static void | 2112 | static void |
2113 | set_freq(double freq) /* frequency update */ | 2113 | set_freq(double freq) /* frequency update */ |
2114 | { | 2114 | { |
2115 | char tbuf[80]; | 2115 | char tbuf[80]; |
2116 | 2116 | ||
diff --git a/networking/ntpd_simple.c b/networking/ntpd_simple.c index 5905e54e9..4ad44e4f3 100644 --- a/networking/ntpd_simple.c +++ b/networking/ntpd_simple.c | |||
@@ -870,7 +870,7 @@ static NOINLINE void ntp_init(char **argv) | |||
870 | int prec = 0; | 870 | int prec = 0; |
871 | int b; | 871 | int b; |
872 | # if 0 | 872 | # if 0 |
873 | struct timespec tp; | 873 | struct timespec tp; |
874 | /* We can use sys_clock_getres but assuming 10ms tick should be fine */ | 874 | /* We can use sys_clock_getres but assuming 10ms tick should be fine */ |
875 | clock_getres(CLOCK_REALTIME, &tp); | 875 | clock_getres(CLOCK_REALTIME, &tp); |
876 | tp.tv_sec = 0; | 876 | tp.tv_sec = 0; |
diff --git a/networking/ping.c b/networking/ping.c index 3aba4906e..366a98668 100644 --- a/networking/ping.c +++ b/networking/ping.c | |||
@@ -29,6 +29,93 @@ | |||
29 | #include <netinet/ip_icmp.h> | 29 | #include <netinet/ip_icmp.h> |
30 | #include "libbb.h" | 30 | #include "libbb.h" |
31 | 31 | ||
32 | //config:config PING | ||
33 | //config: bool "ping" | ||
34 | //config: default y | ||
35 | //config: depends on PLATFORM_LINUX | ||
36 | //config: help | ||
37 | //config: ping uses the ICMP protocol's mandatory ECHO_REQUEST datagram to | ||
38 | //config: elicit an ICMP ECHO_RESPONSE from a host or gateway. | ||
39 | //config: | ||
40 | //config:config PING6 | ||
41 | //config: bool "ping6" | ||
42 | //config: default y | ||
43 | //config: depends on FEATURE_IPV6 && PING | ||
44 | //config: help | ||
45 | //config: This will give you a ping that can talk IPv6. | ||
46 | //config: | ||
47 | //config:config FEATURE_FANCY_PING | ||
48 | //config: bool "Enable fancy ping output" | ||
49 | //config: default y | ||
50 | //config: depends on PING | ||
51 | //config: help | ||
52 | //config: Make the output from the ping applet include statistics, and at the | ||
53 | //config: same time provide full support for ICMP packets. | ||
54 | |||
55 | /* Needs socket(AF_INET, SOCK_RAW, IPPROTO_ICMP), therefore _BB_SUID_MAYBE: */ | ||
56 | //applet:IF_PING(APPLET(ping, _BB_DIR_BIN, _BB_SUID_MAYBE)) | ||
57 | //applet:IF_PING6(APPLET(ping6, _BB_DIR_BIN, _BB_SUID_MAYBE)) | ||
58 | |||
59 | //kbuild:lib-$(CONFIG_PING) += ping.o | ||
60 | //kbuild:lib-$(CONFIG_PING6) += ping.o | ||
61 | |||
62 | //usage:#if !ENABLE_FEATURE_FANCY_PING | ||
63 | //usage:# define ping_trivial_usage | ||
64 | //usage: "HOST" | ||
65 | //usage:# define ping_full_usage "\n\n" | ||
66 | //usage: "Send ICMP ECHO_REQUEST packets to network hosts" | ||
67 | //usage:# define ping6_trivial_usage | ||
68 | //usage: "HOST" | ||
69 | //usage:# define ping6_full_usage "\n\n" | ||
70 | //usage: "Send ICMP ECHO_REQUEST packets to network hosts" | ||
71 | //usage:#else | ||
72 | //usage:# define ping_trivial_usage | ||
73 | //usage: "[OPTIONS] HOST" | ||
74 | //usage:# define ping_full_usage "\n\n" | ||
75 | //usage: "Send ICMP ECHO_REQUEST packets to network hosts\n" | ||
76 | //usage: "\nOptions:" | ||
77 | //usage: "\n -4,-6 Force IP or IPv6 name resolution" | ||
78 | //usage: "\n -c CNT Send only CNT pings" | ||
79 | //usage: "\n -s SIZE Send SIZE data bytes in packets (default:56)" | ||
80 | //usage: "\n -t TTL Set TTL" | ||
81 | //usage: "\n -I IFACE/IP Use interface or IP address as source" | ||
82 | //usage: "\n -W SEC Seconds to wait for the first response (default:10)" | ||
83 | //usage: "\n (after all -c CNT packets are sent)" | ||
84 | //usage: "\n -w SEC Seconds until ping exits (default:infinite)" | ||
85 | //usage: "\n (can exit earlier with -c CNT)" | ||
86 | //usage: "\n -q Quiet, only displays output at start" | ||
87 | //usage: "\n and when finished" | ||
88 | //usage: | ||
89 | //usage:# define ping6_trivial_usage | ||
90 | //usage: "[OPTIONS] HOST" | ||
91 | //usage:# define ping6_full_usage "\n\n" | ||
92 | //usage: "Send ICMP ECHO_REQUEST packets to network hosts\n" | ||
93 | //usage: "\nOptions:" | ||
94 | //usage: "\n -c CNT Send only CNT pings" | ||
95 | //usage: "\n -s SIZE Send SIZE data bytes in packets (default:56)" | ||
96 | //usage: "\n -I IFACE/IP Use interface or IP address as source" | ||
97 | //usage: "\n -q Quiet, only displays output at start" | ||
98 | //usage: "\n and when finished" | ||
99 | //usage: | ||
100 | //usage:#endif | ||
101 | //usage: | ||
102 | //usage:#define ping_example_usage | ||
103 | //usage: "$ ping localhost\n" | ||
104 | //usage: "PING slag (127.0.0.1): 56 data bytes\n" | ||
105 | //usage: "64 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=20.1 ms\n" | ||
106 | //usage: "\n" | ||
107 | //usage: "--- debian ping statistics ---\n" | ||
108 | //usage: "1 packets transmitted, 1 packets received, 0% packet loss\n" | ||
109 | //usage: "round-trip min/avg/max = 20.1/20.1/20.1 ms\n" | ||
110 | //usage:#define ping6_example_usage | ||
111 | //usage: "$ ping6 ip6-localhost\n" | ||
112 | //usage: "PING ip6-localhost (::1): 56 data bytes\n" | ||
113 | //usage: "64 bytes from ::1: icmp6_seq=0 ttl=64 time=20.1 ms\n" | ||
114 | //usage: "\n" | ||
115 | //usage: "--- ip6-localhost ping statistics ---\n" | ||
116 | //usage: "1 packets transmitted, 1 packets received, 0% packet loss\n" | ||
117 | //usage: "round-trip min/avg/max = 20.1/20.1/20.1 ms\n" | ||
118 | |||
32 | #if ENABLE_PING6 | 119 | #if ENABLE_PING6 |
33 | # include <netinet/icmp6.h> | 120 | # include <netinet/icmp6.h> |
34 | /* I see RENUMBERED constants in bits/in.h - !!? | 121 | /* I see RENUMBERED constants in bits/in.h - !!? |
@@ -223,17 +310,18 @@ static int common_ping_main(sa_family_t af, char **argv) | |||
223 | 310 | ||
224 | /* Full(er) version */ | 311 | /* Full(er) version */ |
225 | 312 | ||
226 | #define OPT_STRING ("qvc:s:w:W:I:4" IF_PING6("6")) | 313 | #define OPT_STRING ("qvc:s:t:w:W:I:4" IF_PING6("6")) |
227 | enum { | 314 | enum { |
228 | OPT_QUIET = 1 << 0, | 315 | OPT_QUIET = 1 << 0, |
229 | OPT_VERBOSE = 1 << 1, | 316 | OPT_VERBOSE = 1 << 1, |
230 | OPT_c = 1 << 2, | 317 | OPT_c = 1 << 2, |
231 | OPT_s = 1 << 3, | 318 | OPT_s = 1 << 3, |
232 | OPT_w = 1 << 4, | 319 | OPT_t = 1 << 4, |
233 | OPT_W = 1 << 5, | 320 | OPT_w = 1 << 5, |
234 | OPT_I = 1 << 6, | 321 | OPT_W = 1 << 6, |
235 | OPT_IPV4 = 1 << 7, | 322 | OPT_I = 1 << 7, |
236 | OPT_IPV6 = (1 << 8) * ENABLE_PING6, | 323 | OPT_IPV4 = 1 << 8, |
324 | OPT_IPV6 = (1 << 9) * ENABLE_PING6, | ||
237 | }; | 325 | }; |
238 | 326 | ||
239 | 327 | ||
@@ -244,6 +332,7 @@ struct globals { | |||
244 | len_and_sockaddr *source_lsa; | 332 | len_and_sockaddr *source_lsa; |
245 | unsigned datalen; | 333 | unsigned datalen; |
246 | unsigned pingcount; /* must be int-sized */ | 334 | unsigned pingcount; /* must be int-sized */ |
335 | unsigned opt_ttl; | ||
247 | unsigned long ntransmitted, nreceived, nrepeats; | 336 | unsigned long ntransmitted, nreceived, nrepeats; |
248 | uint16_t myid; | 337 | uint16_t myid; |
249 | unsigned tmin, tmax; /* in us */ | 338 | unsigned tmin, tmax; /* in us */ |
@@ -275,6 +364,7 @@ struct globals { | |||
275 | #define nreceived (G.nreceived ) | 364 | #define nreceived (G.nreceived ) |
276 | #define nrepeats (G.nrepeats ) | 365 | #define nrepeats (G.nrepeats ) |
277 | #define pingcount (G.pingcount ) | 366 | #define pingcount (G.pingcount ) |
367 | #define opt_ttl (G.opt_ttl ) | ||
278 | #define myid (G.myid ) | 368 | #define myid (G.myid ) |
279 | #define tmin (G.tmin ) | 369 | #define tmin (G.tmin ) |
280 | #define tmax (G.tmax ) | 370 | #define tmax (G.tmax ) |
@@ -586,6 +676,12 @@ static void ping4(len_and_sockaddr *lsa) | |||
586 | sockopt = (datalen * 2) + 7 * 1024; /* giving it a bit of extra room */ | 676 | sockopt = (datalen * 2) + 7 * 1024; /* giving it a bit of extra room */ |
587 | setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt)); | 677 | setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt)); |
588 | 678 | ||
679 | if (opt_ttl != 0) { | ||
680 | setsockopt(pingsock, IPPROTO_IP, IP_TTL, &opt_ttl, sizeof(opt_ttl)); | ||
681 | /* above doesnt affect packets sent to bcast IP, so... */ | ||
682 | setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, &opt_ttl, sizeof(opt_ttl)); | ||
683 | } | ||
684 | |||
589 | signal(SIGINT, print_stats_and_exit); | 685 | signal(SIGINT, print_stats_and_exit); |
590 | 686 | ||
591 | /* start the ping's going ... */ | 687 | /* start the ping's going ... */ |
@@ -735,9 +831,9 @@ static int common_ping_main(int opt, char **argv) | |||
735 | 831 | ||
736 | INIT_G(); | 832 | INIT_G(); |
737 | 833 | ||
738 | /* exactly one argument needed; -v and -q don't mix; -c NUM, -w NUM, -W NUM */ | 834 | /* exactly one argument needed; -v and -q don't mix; -c NUM, -t NUM, -w NUM, -W NUM */ |
739 | opt_complementary = "=1:q--v:v--q:c+:w+:W+"; | 835 | opt_complementary = "=1:q--v:v--q:c+:t+:w+:W+"; |
740 | opt |= getopt32(argv, OPT_STRING, &pingcount, &str_s, &deadline, &timeout, &str_I); | 836 | opt |= getopt32(argv, OPT_STRING, &pingcount, &str_s, &opt_ttl, &deadline, &timeout, &str_I); |
741 | if (opt & OPT_s) | 837 | if (opt & OPT_s) |
742 | datalen = xatou16(str_s); // -s | 838 | datalen = xatou16(str_s); // -s |
743 | if (opt & OPT_I) { // -I | 839 | if (opt & OPT_I) { // -I |
diff --git a/networking/slattach.c b/networking/slattach.c index 921ec552d..71edd2f27 100644 --- a/networking/slattach.c +++ b/networking/slattach.c | |||
@@ -134,9 +134,9 @@ int slattach_main(int argc UNUSED_PARAM, char **argv) | |||
134 | int i, encap, opt; | 134 | int i, encap, opt; |
135 | struct termios state; | 135 | struct termios state; |
136 | const char *proto = "cslip"; | 136 | const char *proto = "cslip"; |
137 | const char *extcmd; /* Command to execute after hangup */ | 137 | const char *extcmd; /* Command to execute after hangup */ |
138 | const char *baud_str; | 138 | const char *baud_str; |
139 | int baud_code = -1; /* Line baud rate (system code) */ | 139 | int baud_code = -1; /* Line baud rate (system code) */ |
140 | 140 | ||
141 | enum { | 141 | enum { |
142 | OPT_p_proto = 1 << 0, | 142 | OPT_p_proto = 1 << 0, |
diff --git a/networking/tc.c b/networking/tc.c index 9242741e4..2e2473a70 100644 --- a/networking/tc.c +++ b/networking/tc.c | |||
@@ -1,7 +1,5 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * "tc" utility frontend. | ||
4 | * | ||
5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 3 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
6 | * | 4 | * |
7 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | 5 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
diff --git a/networking/telnet.c b/networking/telnet.c index 12d1970fa..f6fad684c 100644 --- a/networking/telnet.c +++ b/networking/telnet.c | |||
@@ -42,11 +42,13 @@ enum { | |||
42 | UF_ECHO = 0x01, | 42 | UF_ECHO = 0x01, |
43 | UF_SGA = 0x02, | 43 | UF_SGA = 0x02, |
44 | 44 | ||
45 | TS_0 = 1, | 45 | TS_NORMAL = 0, |
46 | TS_COPY = 1, | ||
46 | TS_IAC = 2, | 47 | TS_IAC = 2, |
47 | TS_OPT = 3, | 48 | TS_OPT = 3, |
48 | TS_SUB1 = 4, | 49 | TS_SUB1 = 4, |
49 | TS_SUB2 = 5, | 50 | TS_SUB2 = 5, |
51 | TS_CR = 6, | ||
50 | }; | 52 | }; |
51 | 53 | ||
52 | typedef unsigned char byte; | 54 | typedef unsigned char byte; |
@@ -83,13 +85,13 @@ struct globals { | |||
83 | }; \ | 85 | }; \ |
84 | } while (0) | 86 | } while (0) |
85 | 87 | ||
86 | /* Function prototypes */ | 88 | |
87 | static void rawmode(void); | 89 | static void rawmode(void); |
88 | static void cookmode(void); | 90 | static void cookmode(void); |
89 | static void do_linemode(void); | 91 | static void do_linemode(void); |
90 | static void will_charmode(void); | 92 | static void will_charmode(void); |
91 | static void telopt(byte c); | 93 | static void telopt(byte c); |
92 | static int subneg(byte c); | 94 | static void subneg(byte c); |
93 | 95 | ||
94 | static void iac_flush(void) | 96 | static void iac_flush(void) |
95 | { | 97 | { |
@@ -170,24 +172,24 @@ static void handle_net_output(int len) | |||
170 | * So I implemented it. It's really useful for me. I hope that | 172 | * So I implemented it. It's really useful for me. I hope that |
171 | * other people will find it interesting too. | 173 | * other people will find it interesting too. |
172 | */ | 174 | */ |
173 | 175 | byte outbuf[2 * DATABUFSIZE]; | |
174 | int i, j; | ||
175 | byte *p = (byte*)G.buf; | 176 | byte *p = (byte*)G.buf; |
176 | byte outbuf[4*DATABUFSIZE]; | 177 | int j = 0; |
177 | 178 | ||
178 | for (i = len, j = 0; i > 0; i--, p++) { | 179 | for (; len > 0; len--, p++) { |
179 | if (*p == 0x1d) { | 180 | byte c = *p; |
181 | if (c == 0x1d) { | ||
180 | con_escape(); | 182 | con_escape(); |
181 | return; | 183 | return; |
182 | } | 184 | } |
183 | outbuf[j++] = *p; | 185 | outbuf[j++] = c; |
184 | if (*p == 0xff) | 186 | if (c == IAC) |
185 | outbuf[j++] = 0xff; | 187 | outbuf[j++] = c; /* IAC -> IAC IAC */ |
186 | else if (*p == 0x0d) | 188 | else if (c == '\r') |
187 | outbuf[j++] = 0x00; | 189 | outbuf[j++] = '\0'; /* CR -> CR NUL */ |
188 | } | 190 | } |
189 | if (j > 0) | 191 | if (j > 0) |
190 | write(netfd, outbuf, j); | 192 | full_write(netfd, outbuf, j); |
191 | } | 193 | } |
192 | 194 | ||
193 | static void handle_net_input(int len) | 195 | static void handle_net_input(int len) |
@@ -198,25 +200,44 @@ static void handle_net_input(int len) | |||
198 | for (i = 0; i < len; i++) { | 200 | for (i = 0; i < len; i++) { |
199 | byte c = G.buf[i]; | 201 | byte c = G.buf[i]; |
200 | 202 | ||
201 | if (G.telstate == 0) { /* most of the time state == 0 */ | 203 | if (G.telstate == TS_NORMAL) { /* most typical state */ |
202 | if (c == IAC) { | 204 | if (c == IAC) { |
203 | cstart = i; | 205 | cstart = i; |
204 | G.telstate = TS_IAC; | 206 | G.telstate = TS_IAC; |
205 | } | 207 | } |
208 | else if (c == '\r') { | ||
209 | cstart = i + 1; | ||
210 | G.telstate = TS_CR; | ||
211 | } | ||
212 | /* No IACs were seen so far, no need to copy | ||
213 | * bytes within G.buf: */ | ||
206 | continue; | 214 | continue; |
207 | } | 215 | } |
216 | |||
208 | switch (G.telstate) { | 217 | switch (G.telstate) { |
209 | case TS_0: | 218 | case TS_CR: |
219 | /* Prev char was CR. If cur one is NUL, ignore it. | ||
220 | * See RFC 1123 section 3.3.1 for discussion of telnet EOL handling. | ||
221 | */ | ||
222 | G.telstate = TS_COPY; | ||
223 | if (c == '\0') | ||
224 | break; | ||
225 | /* else: fall through - need to handle CR IAC ... properly */ | ||
226 | |||
227 | case TS_COPY: /* Prev char was ordinary */ | ||
228 | /* Similar to NORMAL, but in TS_COPY we need to copy bytes */ | ||
210 | if (c == IAC) | 229 | if (c == IAC) |
211 | G.telstate = TS_IAC; | 230 | G.telstate = TS_IAC; |
212 | else | 231 | else |
213 | G.buf[cstart++] = c; | 232 | G.buf[cstart++] = c; |
233 | if (c == '\r') | ||
234 | G.telstate = TS_CR; | ||
214 | break; | 235 | break; |
215 | 236 | ||
216 | case TS_IAC: | 237 | case TS_IAC: /* Prev char was IAC */ |
217 | if (c == IAC) { /* IAC IAC -> 0xFF */ | 238 | if (c == IAC) { /* IAC IAC -> one IAC */ |
218 | G.buf[cstart++] = c; | 239 | G.buf[cstart++] = c; |
219 | G.telstate = TS_0; | 240 | G.telstate = TS_COPY; |
220 | break; | 241 | break; |
221 | } | 242 | } |
222 | /* else */ | 243 | /* else */ |
@@ -228,34 +249,38 @@ static void handle_net_input(int len) | |||
228 | case DONT: | 249 | case DONT: |
229 | case WILL: | 250 | case WILL: |
230 | case WONT: | 251 | case WONT: |
231 | G.telwish = c; | 252 | G.telwish = c; |
232 | G.telstate = TS_OPT; | 253 | G.telstate = TS_OPT; |
233 | break; | 254 | break; |
255 | /* DATA MARK must be added later */ | ||
234 | default: | 256 | default: |
235 | G.telstate = TS_0; /* DATA MARK must be added later */ | 257 | G.telstate = TS_COPY; |
236 | } | 258 | } |
237 | break; | 259 | break; |
238 | case TS_OPT: /* WILL, WONT, DO, DONT */ | 260 | |
261 | case TS_OPT: /* Prev chars were IAC WILL/WONT/DO/DONT */ | ||
239 | telopt(c); | 262 | telopt(c); |
240 | G.telstate = TS_0; | 263 | G.telstate = TS_COPY; |
241 | break; | 264 | break; |
265 | |||
242 | case TS_SUB1: /* Subnegotiation */ | 266 | case TS_SUB1: /* Subnegotiation */ |
243 | case TS_SUB2: /* Subnegotiation */ | 267 | case TS_SUB2: /* Subnegotiation */ |
244 | if (subneg(c)) | 268 | subneg(c); /* can change G.telstate */ |
245 | G.telstate = TS_0; | ||
246 | break; | 269 | break; |
247 | } | 270 | } |
248 | } | 271 | } |
249 | if (G.telstate) { | 272 | |
273 | if (G.telstate != TS_NORMAL) { | ||
274 | /* We had some IACs, or CR */ | ||
250 | if (G.iaclen) | 275 | if (G.iaclen) |
251 | iac_flush(); | 276 | iac_flush(); |
252 | if (G.telstate == TS_0) | 277 | if (G.telstate == TS_COPY) /* we aren't in the middle of IAC */ |
253 | G.telstate = 0; | 278 | G.telstate = TS_NORMAL; |
254 | len = cstart; | 279 | len = cstart; |
255 | } | 280 | } |
256 | 281 | ||
257 | if (len) | 282 | if (len) |
258 | write(STDOUT_FILENO, G.buf, len); | 283 | full_write(STDOUT_FILENO, G.buf, len); |
259 | } | 284 | } |
260 | 285 | ||
261 | static void put_iac(int c) | 286 | static void put_iac(int c) |
@@ -495,7 +520,7 @@ static void telopt(byte c) | |||
495 | } | 520 | } |
496 | 521 | ||
497 | /* subnegotiation -- ignore all (except TTYPE,NAWS) */ | 522 | /* subnegotiation -- ignore all (except TTYPE,NAWS) */ |
498 | static int subneg(byte c) | 523 | static void subneg(byte c) |
499 | { | 524 | { |
500 | switch (G.telstate) { | 525 | switch (G.telstate) { |
501 | case TS_SUB1: | 526 | case TS_SUB1: |
@@ -513,12 +538,13 @@ static int subneg(byte c) | |||
513 | #endif | 538 | #endif |
514 | break; | 539 | break; |
515 | case TS_SUB2: | 540 | case TS_SUB2: |
516 | if (c == SE) | 541 | if (c == SE) { |
517 | return TRUE; | 542 | G.telstate = TS_COPY; |
543 | return; | ||
544 | } | ||
518 | G.telstate = TS_SUB1; | 545 | G.telstate = TS_SUB1; |
519 | /* break; */ | 546 | break; |
520 | } | 547 | } |
521 | return FALSE; | ||
522 | } | 548 | } |
523 | 549 | ||
524 | static void rawmode(void) | 550 | static void rawmode(void) |
@@ -533,21 +559,13 @@ static void cookmode(void) | |||
533 | tcsetattr(0, TCSADRAIN, &G.termios_def); | 559 | tcsetattr(0, TCSADRAIN, &G.termios_def); |
534 | } | 560 | } |
535 | 561 | ||
536 | /* poll gives smaller (-70 bytes) code */ | ||
537 | #define USE_POLL 1 | ||
538 | |||
539 | int telnet_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 562 | int telnet_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
540 | int telnet_main(int argc UNUSED_PARAM, char **argv) | 563 | int telnet_main(int argc UNUSED_PARAM, char **argv) |
541 | { | 564 | { |
542 | char *host; | 565 | char *host; |
543 | int port; | 566 | int port; |
544 | int len; | 567 | int len; |
545 | #ifdef USE_POLL | ||
546 | struct pollfd ufds[2]; | 568 | struct pollfd ufds[2]; |
547 | #else | ||
548 | fd_set readfds; | ||
549 | int maxfd; | ||
550 | #endif | ||
551 | 569 | ||
552 | INIT_G(); | 570 | INIT_G(); |
553 | 571 | ||
@@ -585,63 +603,39 @@ int telnet_main(int argc UNUSED_PARAM, char **argv) | |||
585 | 603 | ||
586 | signal(SIGINT, record_signo); | 604 | signal(SIGINT, record_signo); |
587 | 605 | ||
588 | #ifdef USE_POLL | 606 | ufds[0].fd = STDIN_FILENO; |
589 | ufds[0].fd = 0; ufds[1].fd = netfd; | 607 | ufds[0].events = POLLIN; |
590 | ufds[0].events = ufds[1].events = POLLIN; | 608 | ufds[1].fd = netfd; |
591 | #else | 609 | ufds[1].events = POLLIN; |
592 | FD_ZERO(&readfds); | ||
593 | FD_SET(STDIN_FILENO, &readfds); | ||
594 | FD_SET(netfd, &readfds); | ||
595 | maxfd = netfd + 1; | ||
596 | #endif | ||
597 | 610 | ||
598 | while (1) { | 611 | while (1) { |
599 | #ifndef USE_POLL | 612 | if (poll(ufds, 2, -1) < 0) { |
600 | fd_set rfds = readfds; | ||
601 | |||
602 | switch (select(maxfd, &rfds, NULL, NULL, NULL)) | ||
603 | #else | ||
604 | switch (poll(ufds, 2, -1)) | ||
605 | #endif | ||
606 | { | ||
607 | case 0: | ||
608 | /* timeout */ | ||
609 | case -1: | ||
610 | /* error, ignore and/or log something, bay go to loop */ | 613 | /* error, ignore and/or log something, bay go to loop */ |
611 | if (bb_got_signal) | 614 | if (bb_got_signal) |
612 | con_escape(); | 615 | con_escape(); |
613 | else | 616 | else |
614 | sleep(1); | 617 | sleep(1); |
615 | break; | 618 | continue; |
616 | default: | 619 | } |
617 | 620 | ||
618 | #ifdef USE_POLL | 621 | // FIXME: reads can block. Need full bidirectional buffering. |
619 | if (ufds[0].revents) | ||
620 | #else | ||
621 | if (FD_ISSET(STDIN_FILENO, &rfds)) | ||
622 | #endif | ||
623 | { | ||
624 | len = safe_read(STDIN_FILENO, G.buf, DATABUFSIZE); | ||
625 | if (len <= 0) | ||
626 | doexit(EXIT_SUCCESS); | ||
627 | TRACE(0, ("Read con: %d\n", len)); | ||
628 | handle_net_output(len); | ||
629 | } | ||
630 | 622 | ||
631 | #ifdef USE_POLL | 623 | if (ufds[0].revents) { |
632 | if (ufds[1].revents) | 624 | len = safe_read(STDIN_FILENO, G.buf, DATABUFSIZE); |
633 | #else | 625 | if (len <= 0) |
634 | if (FD_ISSET(netfd, &rfds)) | 626 | doexit(EXIT_SUCCESS); |
635 | #endif | 627 | TRACE(0, ("Read con: %d\n", len)); |
636 | { | 628 | handle_net_output(len); |
637 | len = safe_read(netfd, G.buf, DATABUFSIZE); | 629 | } |
638 | if (len <= 0) { | 630 | |
639 | full_write1_str("Connection closed by foreign host\r\n"); | 631 | if (ufds[1].revents) { |
640 | doexit(EXIT_FAILURE); | 632 | len = safe_read(netfd, G.buf, DATABUFSIZE); |
641 | } | 633 | if (len <= 0) { |
642 | TRACE(0, ("Read netfd (%d): %d\n", netfd, len)); | 634 | full_write1_str("Connection closed by foreign host\r\n"); |
643 | handle_net_input(len); | 635 | doexit(EXIT_FAILURE); |
644 | } | 636 | } |
637 | TRACE(0, ("Read netfd (%d): %d\n", netfd, len)); | ||
638 | handle_net_input(len); | ||
645 | } | 639 | } |
646 | } /* while (1) */ | 640 | } /* while (1) */ |
647 | } | 641 | } |
diff --git a/networking/telnetd.c b/networking/telnetd.c index 5c011e15d..07c6a6a73 100644 --- a/networking/telnetd.c +++ b/networking/telnetd.c | |||
@@ -141,7 +141,7 @@ remove_iacs(struct tsession *ts, int *pnum_totty) | |||
141 | if (ptr[1] == SB && ptr[2] == TELOPT_NAWS) { | 141 | if (ptr[1] == SB && ptr[2] == TELOPT_NAWS) { |
142 | struct winsize ws; | 142 | struct winsize ws; |
143 | if ((ptr+8) >= end) | 143 | if ((ptr+8) >= end) |
144 | break; /* incomplete, can't process */ | 144 | break; /* incomplete, can't process */ |
145 | ws.ws_col = (ptr[3] << 8) | ptr[4]; | 145 | ws.ws_col = (ptr[3] << 8) | ptr[4]; |
146 | ws.ws_row = (ptr[5] << 8) | ptr[6]; | 146 | ws.ws_row = (ptr[5] << 8) | ptr[6]; |
147 | ioctl(ts->ptyfd, TIOCSWINSZ, (char *)&ws); | 147 | ioctl(ts->ptyfd, TIOCSWINSZ, (char *)&ws); |
@@ -273,8 +273,8 @@ make_new_session( | |||
273 | static const char iacs_to_send[] ALIGN1 = { | 273 | static const char iacs_to_send[] ALIGN1 = { |
274 | IAC, DO, TELOPT_ECHO, | 274 | IAC, DO, TELOPT_ECHO, |
275 | IAC, DO, TELOPT_NAWS, | 275 | IAC, DO, TELOPT_NAWS, |
276 | /* This requires telnetd.ctrlSQ.patch (incomplete) */ | 276 | /* This requires telnetd.ctrlSQ.patch (incomplete) */ |
277 | /* IAC, DO, TELOPT_LFLOW, */ | 277 | /*IAC, DO, TELOPT_LFLOW,*/ |
278 | IAC, WILL, TELOPT_ECHO, | 278 | IAC, WILL, TELOPT_ECHO, |
279 | IAC, WILL, TELOPT_SGA | 279 | IAC, WILL, TELOPT_SGA |
280 | }; | 280 | }; |
@@ -314,6 +314,8 @@ make_new_session( | |||
314 | /* Restore default signal handling ASAP */ | 314 | /* Restore default signal handling ASAP */ |
315 | bb_signals((1 << SIGCHLD) + (1 << SIGPIPE), SIG_DFL); | 315 | bb_signals((1 << SIGCHLD) + (1 << SIGPIPE), SIG_DFL); |
316 | 316 | ||
317 | pid = getpid(); | ||
318 | |||
317 | if (ENABLE_FEATURE_UTMP) { | 319 | if (ENABLE_FEATURE_UTMP) { |
318 | len_and_sockaddr *lsa = get_peer_lsa(sock); | 320 | len_and_sockaddr *lsa = get_peer_lsa(sock); |
319 | char *hostname = NULL; | 321 | char *hostname = NULL; |
@@ -335,7 +337,6 @@ make_new_session( | |||
335 | xopen(tty_name, O_RDWR); /* becomes our ctty */ | 337 | xopen(tty_name, O_RDWR); /* becomes our ctty */ |
336 | xdup2(0, 1); | 338 | xdup2(0, 1); |
337 | xdup2(0, 2); | 339 | xdup2(0, 2); |
338 | pid = getpid(); | ||
339 | tcsetpgrp(0, pid); /* switch this tty's process group to us */ | 340 | tcsetpgrp(0, pid); /* switch this tty's process group to us */ |
340 | 341 | ||
341 | /* The pseudo-terminal allocated to the client is configured to operate | 342 | /* The pseudo-terminal allocated to the client is configured to operate |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 78aabedf2..7e5ab61fd 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -926,6 +926,10 @@ static void client_background(void) | |||
926 | //usage: "\n -v Verbose" | 926 | //usage: "\n -v Verbose" |
927 | //usage: ) | 927 | //usage: ) |
928 | //usage: ) | 928 | //usage: ) |
929 | //usage: "\nSignals:" | ||
930 | //usage: "\n USR1 Renew current lease" | ||
931 | //usage: "\n USR2 Release current lease" | ||
932 | |||
929 | 933 | ||
930 | int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 934 | int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
931 | int udhcpc_main(int argc UNUSED_PARAM, char **argv) | 935 | int udhcpc_main(int argc UNUSED_PARAM, char **argv) |
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index a015cf038..6fb48a19a 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
@@ -133,7 +133,10 @@ static uint32_t select_lease_time(struct dhcp_packet *packet) | |||
133 | 133 | ||
134 | /* We got a DHCP DISCOVER. Send an OFFER. */ | 134 | /* We got a DHCP DISCOVER. Send an OFFER. */ |
135 | /* NOINLINE: limit stack usage in caller */ | 135 | /* NOINLINE: limit stack usage in caller */ |
136 | static NOINLINE void send_offer(struct dhcp_packet *oldpacket, uint32_t static_lease_nip, struct dyn_lease *lease) | 136 | static NOINLINE void send_offer(struct dhcp_packet *oldpacket, |
137 | uint32_t static_lease_nip, | ||
138 | struct dyn_lease *lease, | ||
139 | uint8_t *requested_ip_opt) | ||
137 | { | 140 | { |
138 | struct dhcp_packet packet; | 141 | struct dhcp_packet packet; |
139 | uint32_t lease_time_sec; | 142 | uint32_t lease_time_sec; |
@@ -147,7 +150,6 @@ static NOINLINE void send_offer(struct dhcp_packet *oldpacket, uint32_t static_l | |||
147 | if (!static_lease_nip) { | 150 | if (!static_lease_nip) { |
148 | /* We have no static lease for client's chaddr */ | 151 | /* We have no static lease for client's chaddr */ |
149 | uint32_t req_nip; | 152 | uint32_t req_nip; |
150 | uint8_t *req_ip_opt; | ||
151 | const char *p_host_name; | 153 | const char *p_host_name; |
152 | 154 | ||
153 | if (lease) { | 155 | if (lease) { |
@@ -158,9 +160,9 @@ static NOINLINE void send_offer(struct dhcp_packet *oldpacket, uint32_t static_l | |||
158 | packet.yiaddr = lease->lease_nip; | 160 | packet.yiaddr = lease->lease_nip; |
159 | } | 161 | } |
160 | /* Or: if client has requested an IP */ | 162 | /* Or: if client has requested an IP */ |
161 | else if ((req_ip_opt = udhcp_get_option(oldpacket, DHCP_REQUESTED_IP)) != NULL | 163 | else if (requested_ip_opt != NULL |
162 | /* (read IP) */ | 164 | /* (read IP) */ |
163 | && (move_from_unaligned32(req_nip, req_ip_opt), 1) | 165 | && (move_from_unaligned32(req_nip, requested_ip_opt), 1) |
164 | /* and the IP is in the lease range */ | 166 | /* and the IP is in the lease range */ |
165 | && ntohl(req_nip) >= server_config.start_ip | 167 | && ntohl(req_nip) >= server_config.start_ip |
166 | && ntohl(req_nip) <= server_config.end_ip | 168 | && ntohl(req_nip) <= server_config.end_ip |
@@ -283,16 +285,12 @@ struct dyn_lease *g_leases; | |||
283 | int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 285 | int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
284 | int udhcpd_main(int argc UNUSED_PARAM, char **argv) | 286 | int udhcpd_main(int argc UNUSED_PARAM, char **argv) |
285 | { | 287 | { |
286 | fd_set rfds; | ||
287 | int server_socket = -1, retval, max_sock; | 288 | int server_socket = -1, retval, max_sock; |
288 | struct dhcp_packet packet; | ||
289 | uint8_t *state; | 289 | uint8_t *state; |
290 | uint32_t static_lease_nip; | ||
291 | unsigned timeout_end; | 290 | unsigned timeout_end; |
292 | unsigned num_ips; | 291 | unsigned num_ips; |
293 | unsigned opt; | 292 | unsigned opt; |
294 | struct option_set *option; | 293 | struct option_set *option; |
295 | struct dyn_lease *lease, fake_lease; | ||
296 | IF_FEATURE_UDHCP_PORT(char *str_P;) | 294 | IF_FEATURE_UDHCP_PORT(char *str_P;) |
297 | 295 | ||
298 | #if ENABLE_FEATURE_UDHCP_PORT | 296 | #if ENABLE_FEATURE_UDHCP_PORT |
@@ -372,11 +370,15 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
372 | 370 | ||
373 | timeout_end = monotonic_sec() + server_config.auto_time; | 371 | timeout_end = monotonic_sec() + server_config.auto_time; |
374 | while (1) { /* loop until universe collapses */ | 372 | while (1) { /* loop until universe collapses */ |
373 | fd_set rfds; | ||
374 | struct dhcp_packet packet; | ||
375 | int bytes; | 375 | int bytes; |
376 | struct timeval tv; | 376 | struct timeval tv; |
377 | uint8_t *server_id_opt; | 377 | uint8_t *server_id_opt; |
378 | uint8_t *requested_opt; | 378 | uint8_t *requested_ip_opt; |
379 | uint32_t requested_nip = requested_nip; /* for compiler */ | 379 | uint32_t requested_nip = requested_nip; /* for compiler */ |
380 | uint32_t static_lease_nip; | ||
381 | struct dyn_lease *lease, fake_lease; | ||
380 | 382 | ||
381 | if (server_socket < 0) { | 383 | if (server_socket < 0) { |
382 | server_socket = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT, | 384 | server_socket = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT, |
@@ -443,6 +445,18 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
443 | continue; | 445 | continue; |
444 | } | 446 | } |
445 | 447 | ||
448 | /* Get SERVER_ID if present */ | ||
449 | server_id_opt = udhcp_get_option(&packet, DHCP_SERVER_ID); | ||
450 | if (server_id_opt) { | ||
451 | uint32_t server_id_network_order; | ||
452 | move_from_unaligned32(server_id_network_order, server_id_opt); | ||
453 | if (server_id_network_order != server_config.server_nip) { | ||
454 | /* client talks to somebody else */ | ||
455 | log1("server ID doesn't match, ignoring"); | ||
456 | continue; | ||
457 | } | ||
458 | } | ||
459 | |||
446 | /* Look for a static/dynamic lease */ | 460 | /* Look for a static/dynamic lease */ |
447 | static_lease_nip = get_static_nip_by_mac(server_config.static_leases, &packet.chaddr); | 461 | static_lease_nip = get_static_nip_by_mac(server_config.static_leases, &packet.chaddr); |
448 | if (static_lease_nip) { | 462 | if (static_lease_nip) { |
@@ -455,20 +469,10 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
455 | lease = find_lease_by_mac(packet.chaddr); | 469 | lease = find_lease_by_mac(packet.chaddr); |
456 | } | 470 | } |
457 | 471 | ||
458 | /* Get REQUESTED_IP and SERVER_ID if present */ | 472 | /* Get REQUESTED_IP if present */ |
459 | server_id_opt = udhcp_get_option(&packet, DHCP_SERVER_ID); | 473 | requested_ip_opt = udhcp_get_option(&packet, DHCP_REQUESTED_IP); |
460 | if (server_id_opt) { | 474 | if (requested_ip_opt) { |
461 | uint32_t server_id_net; | 475 | move_from_unaligned32(requested_nip, requested_ip_opt); |
462 | move_from_unaligned32(server_id_net, server_id_opt); | ||
463 | if (server_id_net != server_config.server_nip) { | ||
464 | /* client talks to somebody else */ | ||
465 | log1("server ID doesn't match, ignoring"); | ||
466 | continue; | ||
467 | } | ||
468 | } | ||
469 | requested_opt = udhcp_get_option(&packet, DHCP_REQUESTED_IP); | ||
470 | if (requested_opt) { | ||
471 | move_from_unaligned32(requested_nip, requested_opt); | ||
472 | } | 476 | } |
473 | 477 | ||
474 | switch (state[0]) { | 478 | switch (state[0]) { |
@@ -476,7 +480,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
476 | case DHCPDISCOVER: | 480 | case DHCPDISCOVER: |
477 | log1("Received DISCOVER"); | 481 | log1("Received DISCOVER"); |
478 | 482 | ||
479 | send_offer(&packet, static_lease_nip, lease); | 483 | send_offer(&packet, static_lease_nip, lease, requested_ip_opt); |
480 | break; | 484 | break; |
481 | 485 | ||
482 | case DHCPREQUEST: | 486 | case DHCPREQUEST: |
@@ -567,7 +571,7 @@ o DHCPREQUEST generated during REBINDING state: | |||
567 | A DHCP server MAY extend a client's lease only if it has local | 571 | A DHCP server MAY extend a client's lease only if it has local |
568 | administrative authority to do so. | 572 | administrative authority to do so. |
569 | */ | 573 | */ |
570 | if (!requested_opt) { | 574 | if (!requested_ip_opt) { |
571 | requested_nip = packet.ciaddr; | 575 | requested_nip = packet.ciaddr; |
572 | if (requested_nip == 0) { | 576 | if (requested_nip == 0) { |
573 | log1("no requested IP and no ciaddr, ignoring"); | 577 | log1("no requested IP and no ciaddr, ignoring"); |
@@ -580,11 +584,15 @@ o DHCPREQUEST generated during REBINDING state: | |||
580 | send_ACK(&packet, lease->lease_nip); | 584 | send_ACK(&packet, lease->lease_nip); |
581 | break; | 585 | break; |
582 | } | 586 | } |
583 | if (server_id_opt) { | 587 | /* No lease for this MAC, or lease IP != requested IP */ |
584 | /* client was talking specifically to us. | 588 | |
585 | * "No, we don't have this IP for you". */ | 589 | if (server_id_opt /* client is in SELECTING state */ |
590 | || requested_ip_opt /* client is in INIT-REBOOT state */ | ||
591 | ) { | ||
592 | /* "No, we don't have this IP for you" */ | ||
586 | send_NAK(&packet); | 593 | send_NAK(&packet); |
587 | } | 594 | } /* else: client is in RENEWING or REBINDING, do not answer */ |
595 | |||
588 | break; | 596 | break; |
589 | 597 | ||
590 | case DHCPDECLINE: | 598 | case DHCPDECLINE: |
@@ -603,7 +611,7 @@ o DHCPREQUEST generated during REBINDING state: | |||
603 | */ | 611 | */ |
604 | log1("Received DECLINE"); | 612 | log1("Received DECLINE"); |
605 | if (server_id_opt | 613 | if (server_id_opt |
606 | && requested_opt | 614 | && requested_ip_opt |
607 | && lease /* chaddr matches this lease */ | 615 | && lease /* chaddr matches this lease */ |
608 | && requested_nip == lease->lease_nip | 616 | && requested_nip == lease->lease_nip |
609 | ) { | 617 | ) { |
diff --git a/networking/vconfig.c b/networking/vconfig.c index 1f574d2ad..13c65ad78 100644 --- a/networking/vconfig.c +++ b/networking/vconfig.c | |||
@@ -47,8 +47,8 @@ struct vlan_ioctl_args { | |||
47 | short vlan_qos; | 47 | short vlan_qos; |
48 | }; | 48 | }; |
49 | 49 | ||
50 | #define VLAN_GROUP_ARRAY_LEN 4096 | 50 | #define VLAN_GROUP_ARRAY_LEN 4096 |
51 | #define SIOCSIFVLAN 0x8983 /* Set 802.1Q VLAN options */ | 51 | #define SIOCSIFVLAN 0x8983 /* Set 802.1Q VLAN options */ |
52 | 52 | ||
53 | /* On entry, table points to the length of the current string | 53 | /* On entry, table points to the length of the current string |
54 | * plus NUL terminator plus data length for the subsequent entry. | 54 | * plus NUL terminator plus data length for the subsequent entry. |
diff --git a/networking/wget.c b/networking/wget.c index 5b0907e11..16594c9bf 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Licensed under GPLv2, see file LICENSE in this source tree. | 6 | * Licensed under GPLv2, see file LICENSE in this source tree. |
7 | * | 7 | * |
8 | * Copyright (C) 2010 Bradley M. Kuhn <bkuhn@ebb.org> | 8 | * Copyright (C) 2010 Bradley M. Kuhn <bkuhn@ebb.org> |
9 | * Kuhn's copyrights are licensed GPLv2-or-later. File as a whole remains GPLv2. | 9 | * Kuhn's copyrights are licensed GPLv2-or-later. File as a whole remains GPLv2. |
10 | */ | 10 | */ |
11 | #include "libbb.h" | 11 | #include "libbb.h" |
12 | 12 | ||
@@ -48,7 +48,7 @@ struct BUG_G_too_big { | |||
48 | /* Must match option string! */ | 48 | /* Must match option string! */ |
49 | enum { | 49 | enum { |
50 | WGET_OPT_CONTINUE = (1 << 0), | 50 | WGET_OPT_CONTINUE = (1 << 0), |
51 | WGET_OPT_SPIDER = (1 << 1), | 51 | WGET_OPT_SPIDER = (1 << 1), |
52 | WGET_OPT_QUIET = (1 << 2), | 52 | WGET_OPT_QUIET = (1 << 2), |
53 | WGET_OPT_OUTNAME = (1 << 3), | 53 | WGET_OPT_OUTNAME = (1 << 3), |
54 | WGET_OPT_PREFIX = (1 << 4), | 54 | WGET_OPT_PREFIX = (1 << 4), |
@@ -786,7 +786,7 @@ However, in real world it was observed that some web servers | |||
786 | */ | 786 | */ |
787 | case 204: | 787 | case 204: |
788 | break; | 788 | break; |
789 | case 300: /* redirection */ | 789 | case 300: /* redirection */ |
790 | case 301: | 790 | case 301: |
791 | case 302: | 791 | case 302: |
792 | case 303: | 792 | case 303: |
diff --git a/procps/Config.src b/procps/Config.src index 1ff6dfd30..cf664eeb2 100644 --- a/procps/Config.src +++ b/procps/Config.src | |||
@@ -46,12 +46,6 @@ config KILLALL5 | |||
46 | default y | 46 | default y |
47 | depends on KILL | 47 | depends on KILL |
48 | 48 | ||
49 | config NMETER | ||
50 | bool "nmeter" | ||
51 | default y | ||
52 | help | ||
53 | Prints selected system stats continuously, one line per update. | ||
54 | |||
55 | config PGREP | 49 | config PGREP |
56 | bool "pgrep" | 50 | bool "pgrep" |
57 | default y | 51 | default y |
@@ -192,11 +186,12 @@ config FEATURE_TOPMEM | |||
192 | Enable 's' in top (gives lots of memory info). | 186 | Enable 's' in top (gives lots of memory info). |
193 | 187 | ||
194 | config FEATURE_SHOW_THREADS | 188 | config FEATURE_SHOW_THREADS |
195 | bool "Support for showing threads in ps/top" | 189 | bool "Support for showing threads in ps/pstree/top" |
196 | default y | 190 | default y |
197 | depends on PS || TOP | 191 | depends on PS || TOP || PSTREE |
198 | help | 192 | help |
199 | Enables ps -T option and 'h' command in top | 193 | Enables the ps -T option, showing of threads in pstree, |
194 | and 'h' command in top. | ||
200 | 195 | ||
201 | config UPTIME | 196 | config UPTIME |
202 | bool "uptime" | 197 | bool "uptime" |
diff --git a/procps/Kbuild.src b/procps/Kbuild.src index 791d65670..89b1cc094 100644 --- a/procps/Kbuild.src +++ b/procps/Kbuild.src | |||
@@ -11,7 +11,6 @@ lib-$(CONFIG_FREE) += free.o | |||
11 | lib-$(CONFIG_FUSER) += fuser.o | 11 | lib-$(CONFIG_FUSER) += fuser.o |
12 | lib-$(CONFIG_KILL) += kill.o | 12 | lib-$(CONFIG_KILL) += kill.o |
13 | lib-$(CONFIG_ASH) += kill.o # used for built-in kill by ash | 13 | lib-$(CONFIG_ASH) += kill.o # used for built-in kill by ash |
14 | lib-$(CONFIG_NMETER) += nmeter.o | ||
15 | lib-$(CONFIG_PGREP) += pgrep.o | 14 | lib-$(CONFIG_PGREP) += pgrep.o |
16 | lib-$(CONFIG_PKILL) += pgrep.o | 15 | lib-$(CONFIG_PKILL) += pgrep.o |
17 | lib-$(CONFIG_PIDOF) += pidof.o | 16 | lib-$(CONFIG_PIDOF) += pidof.o |
diff --git a/procps/iostat.c b/procps/iostat.c index 5d829861e..a9ff13a05 100644 --- a/procps/iostat.c +++ b/procps/iostat.c | |||
@@ -18,14 +18,14 @@ | |||
18 | //config: Report CPU and I/O statistics | 18 | //config: Report CPU and I/O statistics |
19 | 19 | ||
20 | #include "libbb.h" | 20 | #include "libbb.h" |
21 | #include <sys/utsname.h> /* Need struct utsname */ | 21 | #include <sys/utsname.h> /* Need struct utsname */ |
22 | 22 | ||
23 | //#define debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__) | 23 | //#define debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__) |
24 | #define debug(fmt, ...) ((void)0) | 24 | #define debug(fmt, ...) ((void)0) |
25 | 25 | ||
26 | #define MAX_DEVICE_NAME 12 | 26 | #define MAX_DEVICE_NAME 12 |
27 | #define CURRENT 0 | 27 | #define CURRENT 0 |
28 | #define LAST 1 | 28 | #define LAST 1 |
29 | 29 | ||
30 | #if 1 | 30 | #if 1 |
31 | typedef unsigned long long cputime_t; | 31 | typedef unsigned long long cputime_t; |
@@ -327,7 +327,7 @@ static void do_disk_statistics(cputime_t itv) | |||
327 | int i = 0; | 327 | int i = 0; |
328 | char buf[128]; | 328 | char buf[128]; |
329 | unsigned major, minor; | 329 | unsigned major, minor; |
330 | unsigned long wr_ops, dummy; /* %*lu for suppres the conversion wouldn't work */ | 330 | unsigned long wr_ops, dummy; /* %*lu for suppress the conversion wouldn't work */ |
331 | unsigned long long rd_sec_or_wr_ops; | 331 | unsigned long long rd_sec_or_wr_ops; |
332 | unsigned long long rd_sec_or_dummy, wr_sec_or_dummy, wr_sec; | 332 | unsigned long long rd_sec_or_dummy, wr_sec_or_dummy, wr_sec; |
333 | struct stats_dev sd; | 333 | struct stats_dev sd; |
diff --git a/procps/mpstat.c b/procps/mpstat.c index f1a0b00b8..25efedf62 100644 --- a/procps/mpstat.c +++ b/procps/mpstat.c | |||
@@ -18,7 +18,7 @@ | |||
18 | //config: Per-processor statistics | 18 | //config: Per-processor statistics |
19 | 19 | ||
20 | #include "libbb.h" | 20 | #include "libbb.h" |
21 | #include <sys/utsname.h> /* struct utsname */ | 21 | #include <sys/utsname.h> /* struct utsname */ |
22 | 22 | ||
23 | //#define debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__) | 23 | //#define debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__) |
24 | #define debug(fmt, ...) ((void)0) | 24 | #define debug(fmt, ...) ((void)0) |
@@ -634,7 +634,7 @@ static void get_irqs_from_interrupts(const char *fname, | |||
634 | while (irq < irqs_per_cpu) { | 634 | while (irq < irqs_per_cpu) { |
635 | /* Number of interrupts per CPU has changed */ | 635 | /* Number of interrupts per CPU has changed */ |
636 | ic = &per_cpu_stats[current][irq]; | 636 | ic = &per_cpu_stats[current][irq]; |
637 | ic->irq_name[0] = '\0'; /* False interrupt */ | 637 | ic->irq_name[0] = '\0'; /* False interrupt */ |
638 | irq++; | 638 | irq++; |
639 | } | 639 | } |
640 | } | 640 | } |
@@ -820,7 +820,7 @@ static int get_irqcpu_nr(const char *f, int max_irqs) | |||
820 | unsigned irq; | 820 | unsigned irq; |
821 | 821 | ||
822 | fp = fopen_for_read(f); | 822 | fp = fopen_for_read(f); |
823 | if (!fp) /* No interrupts file */ | 823 | if (!fp) /* No interrupts file */ |
824 | return 0; | 824 | return 0; |
825 | 825 | ||
826 | linelen = INTERRUPTS_LINE + 16 * G.cpu_nr; | 826 | linelen = INTERRUPTS_LINE + 16 * G.cpu_nr; |
@@ -858,10 +858,10 @@ int mpstat_main(int UNUSED_PARAM argc, char **argv) | |||
858 | char *opt_set_cpu; | 858 | char *opt_set_cpu; |
859 | int i, opt; | 859 | int i, opt; |
860 | enum { | 860 | enum { |
861 | OPT_ALL = 1 << 0, /* -A */ | 861 | OPT_ALL = 1 << 0, /* -A */ |
862 | OPT_INTS = 1 << 1, /* -I */ | 862 | OPT_INTS = 1 << 1, /* -I */ |
863 | OPT_SETCPU = 1 << 2, /* -P */ | 863 | OPT_SETCPU = 1 << 2, /* -P */ |
864 | OPT_UTIL = 1 << 3, /* -u */ | 864 | OPT_UTIL = 1 << 3, /* -u */ |
865 | }; | 865 | }; |
866 | 866 | ||
867 | /* Dont buffer data if redirected to a pipe */ | 867 | /* Dont buffer data if redirected to a pipe */ |
diff --git a/procps/nmeter.c b/procps/nmeter.c index 7836a90d5..ac019eb53 100644 --- a/procps/nmeter.c +++ b/procps/nmeter.c | |||
@@ -6,6 +6,40 @@ | |||
6 | * Contact me: vda.linux@googlemail.com | 6 | * Contact me: vda.linux@googlemail.com |
7 | */ | 7 | */ |
8 | 8 | ||
9 | //config:config NMETER | ||
10 | //config: bool "nmeter" | ||
11 | //config: default y | ||
12 | //config: help | ||
13 | //config: Prints selected system stats continuously, one line per update. | ||
14 | |||
15 | //applet:IF_NMETER(APPLET(nmeter, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | ||
16 | |||
17 | //kbuild:lib-$(CONFIG_NMETER) += nmeter.o | ||
18 | |||
19 | //usage:#define nmeter_trivial_usage | ||
20 | //usage: "[-d MSEC] FORMAT_STRING" | ||
21 | //usage:#define nmeter_full_usage "\n\n" | ||
22 | //usage: "Monitor system in real time" | ||
23 | //usage: "\n" | ||
24 | //usage: "\n -d MSEC Milliseconds between updates (default:1000)" | ||
25 | //usage: "\n" | ||
26 | //usage: "\nFormat specifiers:" | ||
27 | //usage: "\n %Nc or %[cN] Monitor CPU. N - bar size (default:10)" | ||
28 | //usage: "\n (displays: S:system U:user N:niced D:iowait I:irq i:softirq)" | ||
29 | //usage: "\n %[niface] Monitor network interface 'iface'" | ||
30 | //usage: "\n %m Monitor allocated memory" | ||
31 | //usage: "\n %[mf] Monitor free memory" | ||
32 | //usage: "\n %[mt] Monitor total memory" | ||
33 | //usage: "\n %s Monitor allocated swap" | ||
34 | //usage: "\n %f Monitor number of used file descriptors" | ||
35 | //usage: "\n %Ni Monitor total/specific IRQ rate" | ||
36 | //usage: "\n %x Monitor context switch rate" | ||
37 | //usage: "\n %p Monitor forks" | ||
38 | //usage: "\n %[pn] Monitor # of processes" | ||
39 | //usage: "\n %b Monitor block io" | ||
40 | //usage: "\n %Nt Show time (with N decimal points)" | ||
41 | //usage: "\n %r Print <cr> instead of <lf> at EOL" | ||
42 | |||
9 | //TODO: | 43 | //TODO: |
10 | // simplify code | 44 | // simplify code |
11 | // /proc/locks | 45 | // /proc/locks |
@@ -769,6 +803,7 @@ static void FAST_FUNC collect_info(s_stat *s) | |||
769 | 803 | ||
770 | typedef s_stat* init_func(const char *param); | 804 | typedef s_stat* init_func(const char *param); |
771 | 805 | ||
806 | // Deprecated %NNNd is to be removed, -d MSEC supersedes it | ||
772 | static const char options[] ALIGN1 = "ncmsfixptbdr"; | 807 | static const char options[] ALIGN1 = "ncmsfixptbdr"; |
773 | static init_func *const init_functions[] = { | 808 | static init_func *const init_functions[] = { |
774 | init_if, | 809 | init_if, |
@@ -792,23 +827,28 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv) | |||
792 | s_stat *first = NULL; | 827 | s_stat *first = NULL; |
793 | s_stat *last = NULL; | 828 | s_stat *last = NULL; |
794 | s_stat *s; | 829 | s_stat *s; |
830 | char *opt_d; | ||
795 | char *cur, *prev; | 831 | char *cur, *prev; |
796 | 832 | ||
797 | INIT_G(); | 833 | INIT_G(); |
798 | 834 | ||
799 | xchdir("/proc"); | 835 | xchdir("/proc"); |
800 | 836 | ||
801 | if (!argv[1]) | ||
802 | bb_show_usage(); | ||
803 | |||
804 | if (open_read_close("version", buf, sizeof(buf)-1) > 0) { | 837 | if (open_read_close("version", buf, sizeof(buf)-1) > 0) { |
805 | buf[sizeof(buf)-1] = '\0'; | 838 | buf[sizeof(buf)-1] = '\0'; |
806 | is26 = (strstr(buf, " 2.4.") == NULL); | 839 | is26 = (strstr(buf, " 2.4.") == NULL); |
807 | } | 840 | } |
808 | 841 | ||
809 | // Can use argv[1] directly, but this will mess up | 842 | if (getopt32(argv, "d:", &opt_d)) |
843 | init_delay(opt_d); | ||
844 | argv += optind; | ||
845 | |||
846 | if (!argv[0]) | ||
847 | bb_show_usage(); | ||
848 | |||
849 | // Can use argv[0] directly, but this will mess up | ||
810 | // parameters as seen by e.g. ps. Making a copy... | 850 | // parameters as seen by e.g. ps. Making a copy... |
811 | cur = xstrdup(argv[1]); | 851 | cur = xstrdup(argv[0]); |
812 | while (1) { | 852 | while (1) { |
813 | char *param, *p; | 853 | char *param, *p; |
814 | prev = cur; | 854 | prev = cur; |
diff --git a/procps/powertop.c b/procps/powertop.c index 250da817b..2f977a03b 100644 --- a/procps/powertop.c +++ b/procps/powertop.c | |||
@@ -169,7 +169,7 @@ static void read_cstate_counts(ullong *usage, ullong *duration) | |||
169 | if (len < 3 || len > BIG_SYSNAME_LEN) | 169 | if (len < 3 || len > BIG_SYSNAME_LEN) |
170 | continue; | 170 | continue; |
171 | 171 | ||
172 | sprintf(buf, "/proc/acpi/processor/%s/power", d->d_name); | 172 | sprintf(buf, "%s/%s/power", "/proc/acpi/processor", d->d_name); |
173 | fp = fopen_for_read(buf); | 173 | fp = fopen_for_read(buf); |
174 | if (!fp) | 174 | if (!fp) |
175 | continue; | 175 | continue; |
@@ -321,31 +321,18 @@ static void process_irq_counts(void) | |||
321 | /* 0: 143646045 153901007 IO-APIC-edge timer | 321 | /* 0: 143646045 153901007 IO-APIC-edge timer |
322 | * ^ | 322 | * ^ |
323 | */ | 323 | */ |
324 | *p = '\0'; | ||
324 | /* Deal with non-maskable interrupts -- make up fake numbers */ | 325 | /* Deal with non-maskable interrupts -- make up fake numbers */ |
325 | nr = -1; | 326 | nr = index_in_strings("NMI\0RES\0CAL\0TLB\0TRM\0THR\0SPU\0", buf); |
326 | if (buf[0] != ' ' && !isdigit(buf[0])) { | 327 | if (nr >= 0) { |
327 | //TODO: optimize | 328 | nr += 20000; |
328 | if (strncmp(buf, "NMI:", 4) == 0) | ||
329 | nr = 20000; | ||
330 | if (strncmp(buf, "RES:", 4) == 0) | ||
331 | nr = 20001; | ||
332 | if (strncmp(buf, "CAL:", 4) == 0) | ||
333 | nr = 20002; | ||
334 | if (strncmp(buf, "TLB:", 4) == 0) | ||
335 | nr = 20003; | ||
336 | if (strncmp(buf, "TRM:", 4) == 0) | ||
337 | nr = 20004; | ||
338 | if (strncmp(buf, "THR:", 4) == 0) | ||
339 | nr = 20005; | ||
340 | if (strncmp(buf, "SPU:", 4) == 0) | ||
341 | nr = 20006; | ||
342 | } else { | 329 | } else { |
343 | /* bb_strtou doesn't eat leading spaces, using strtoul */ | 330 | /* bb_strtou doesn't eat leading spaces, using strtoul */ |
331 | errno = 0; | ||
344 | nr = strtoul(buf, NULL, 10); | 332 | nr = strtoul(buf, NULL, 10); |
333 | if (errno) | ||
334 | continue; | ||
345 | } | 335 | } |
346 | if (nr == -1) | ||
347 | continue; | ||
348 | |||
349 | p++; | 336 | p++; |
350 | /* 0: 143646045 153901007 IO-APIC-edge timer | 337 | /* 0: 143646045 153901007 IO-APIC-edge timer |
351 | * ^ | 338 | * ^ |
@@ -412,6 +399,7 @@ static NOINLINE int process_timer_stats(void) | |||
412 | buf[0] = '\0'; | 399 | buf[0] = '\0'; |
413 | totalticks = 0; | 400 | totalticks = 0; |
414 | 401 | ||
402 | n = 0; | ||
415 | fp = NULL; | 403 | fp = NULL; |
416 | if (!G.cant_enable_timer_stats) | 404 | if (!G.cant_enable_timer_stats) |
417 | fp = fopen_for_read("/proc/timer_stats"); | 405 | fp = fopen_for_read("/proc/timer_stats"); |
@@ -430,33 +418,41 @@ static NOINLINE int process_timer_stats(void) | |||
430 | while (fgets(buf, sizeof(buf), fp)) { | 418 | while (fgets(buf, sizeof(buf), fp)) { |
431 | const char *count, *process, *func; | 419 | const char *count, *process, *func; |
432 | char *p; | 420 | char *p; |
433 | int cnt; | 421 | int idx; |
422 | unsigned cnt; | ||
434 | 423 | ||
435 | count = skip_whitespace(buf); | 424 | count = skip_whitespace(buf); |
436 | p = strchr(count, ','); | 425 | p = strchr(count, ','); |
437 | if (!p) | 426 | if (!p) |
438 | continue; | 427 | continue; |
439 | *p++ = '\0'; | 428 | *p++ = '\0'; |
440 | if (strcmp(strchrnul(count, ' '), " total events") == 0) | 429 | cnt = bb_strtou(count, NULL, 10); |
430 | if (strcmp(skip_non_whitespace(count), " total events") == 0) { | ||
431 | #if ENABLE_FEATURE_POWERTOP_PROCIRQ | ||
432 | n = cnt / G.total_cpus; | ||
433 | if (n > 0 && n < G.interrupt_0) { | ||
434 | sprintf(line, " <interrupt> : %s", "extra timer interrupt"); | ||
435 | save_line(line, G.interrupt_0 - n); | ||
436 | } | ||
437 | #endif | ||
441 | break; | 438 | break; |
442 | p = skip_whitespace(p); /* points to pid */ | 439 | } |
443 | 440 | if (strchr(count, 'D')) | |
444 | /* Find char ' ', then eat remaining spaces */ | 441 | continue; /* deferred */ |
445 | #define ADVANCE(p) do { \ | 442 | p = skip_whitespace(p); /* points to pid now */ |
446 | (p) = strchr((p), ' '); \ | 443 | process = NULL; |
447 | if (!(p)) \ | 444 | get_func_name: |
448 | continue; \ | 445 | p = strchr(p, ' '); |
449 | *(p) = '\0'; \ | 446 | if (!p) |
450 | (p)++; \ | 447 | continue; |
451 | (p) = skip_whitespace(p); \ | 448 | *p++ = '\0'; |
452 | } while (0) | 449 | p = skip_whitespace(p); |
453 | /* Get process name */ | 450 | if (process == NULL) { |
454 | ADVANCE(p); | 451 | process = p; |
455 | process = p; | 452 | goto get_func_name; |
456 | /* Get function */ | 453 | } |
457 | ADVANCE(p); | ||
458 | func = p; | 454 | func = p; |
459 | #undef ADVANCE | 455 | |
460 | //if (strcmp(process, "swapper") == 0 | 456 | //if (strcmp(process, "swapper") == 0 |
461 | // && strcmp(func, "hrtimer_start_range_ns (tick_sched_timer)\n") == 0 | 457 | // && strcmp(func, "hrtimer_start_range_ns (tick_sched_timer)\n") == 0 |
462 | //) { | 458 | //) { |
@@ -471,45 +467,26 @@ static NOINLINE int process_timer_stats(void) | |||
471 | //if (strcmp(process, "powertop") == 0) | 467 | //if (strcmp(process, "powertop") == 0) |
472 | // continue; | 468 | // continue; |
473 | 469 | ||
474 | if (strcmp(process, "insmod") == 0) | 470 | idx = index_in_strings("insmod\0modprobe\0swapper\0", process); |
475 | process = "[kernel module]"; | 471 | if (idx != -1) { |
476 | if (strcmp(process, "modprobe") == 0) | 472 | process = idx < 2 ? "[kernel module]" : "<kernel core>"; |
477 | process = "[kernel module]"; | 473 | } |
478 | if (strcmp(process, "swapper") == 0) | ||
479 | process = "<kernel core>"; | ||
480 | 474 | ||
481 | strchrnul(p, '\n')[0] = '\0'; | 475 | strchrnul(p, '\n')[0] = '\0'; |
482 | 476 | ||
483 | { | 477 | // 46D\01136\0kondemand/1\0do_dbs_timer (delayed_work_timer_fn) |
484 | char *tmp; | 478 | // ^ ^ ^ |
485 | cnt = bb_strtoull(count, &tmp, 10); | 479 | // count process func |
486 | p = tmp; | ||
487 | } | ||
488 | while (*p != '\0') { | ||
489 | if (*p++ == 'D') /* deferred */ | ||
490 | goto skip; | ||
491 | } | ||
492 | 480 | ||
493 | //if (strchr(process, '[')) | 481 | //if (strchr(process, '[')) |
494 | sprintf(line, "%15.15s : %s", process, func); | 482 | sprintf(line, "%15.15s : %s", process, func); |
495 | //else | 483 | //else |
496 | // sprintf(line, "%s", process); | 484 | // sprintf(line, "%s", process); |
497 | save_line(line, cnt); | 485 | save_line(line, cnt); |
498 | skip: ; | ||
499 | } | 486 | } |
500 | fclose(fp); | 487 | fclose(fp); |
501 | } | 488 | } |
502 | 489 | ||
503 | n = 0; | ||
504 | #if ENABLE_FEATURE_POWERTOP_PROCIRQ | ||
505 | if (strstr(buf, "total events")) { | ||
506 | n = bb_strtoull(buf, NULL, 10) / G.total_cpus; | ||
507 | if (n > 0 && n < G.interrupt_0) { | ||
508 | sprintf(line, " <interrupt> : %s", "extra timer interrupt"); | ||
509 | save_line(line, G.interrupt_0 - n); | ||
510 | } | ||
511 | } | ||
512 | #endif | ||
513 | return n; | 490 | return n; |
514 | } | 491 | } |
515 | 492 | ||
@@ -566,7 +543,7 @@ static NOINLINE void print_intel_cstates(void) | |||
566 | if (!isdigit(d->d_name[3])) | 543 | if (!isdigit(d->d_name[3])) |
567 | continue; | 544 | continue; |
568 | 545 | ||
569 | len = sprintf(fname, "/sys/devices/system/cpu/%s/cpuidle", d->d_name); | 546 | len = sprintf(fname, "%s/%s/cpuidle", "/sys/devices/system/cpu", d->d_name); |
570 | dir = opendir(fname); | 547 | dir = opendir(fname); |
571 | if (!dir) | 548 | if (!dir) |
572 | continue; | 549 | continue; |
@@ -635,7 +612,7 @@ static NOINLINE void print_intel_cstates(void) | |||
635 | bb_putchar('\n'); | 612 | bb_putchar('\n'); |
636 | } | 613 | } |
637 | #else | 614 | #else |
638 | # define print_intel_cstates(void) ((void)0) | 615 | # define print_intel_cstates() ((void)0) |
639 | #endif | 616 | #endif |
640 | 617 | ||
641 | static void show_timerstats(void) | 618 | static void show_timerstats(void) |
diff --git a/procps/pstree.c b/procps/pstree.c new file mode 100644 index 000000000..180d0939a --- /dev/null +++ b/procps/pstree.c | |||
@@ -0,0 +1,406 @@ | |||
1 | /* | ||
2 | * pstree.c - display process tree | ||
3 | * | ||
4 | * Copyright (C) 1993-2002 Werner Almesberger | ||
5 | * Copyright (C) 2002-2009 Craig Small | ||
6 | * Copyright (C) 2010 Lauri Kasanen | ||
7 | * | ||
8 | * Based on pstree (PSmisc) 22.13. | ||
9 | * | ||
10 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
11 | */ | ||
12 | |||
13 | //config:config PSTREE | ||
14 | //config: bool "pstree" | ||
15 | //config: default y | ||
16 | //config: help | ||
17 | //config: Display a tree of processes. | ||
18 | |||
19 | //applet:IF_PSTREE(APPLET(pstree, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | ||
20 | |||
21 | //kbuild:lib-$(CONFIG_PSTREE) += pstree.o | ||
22 | |||
23 | //usage:#define pstree_trivial_usage | ||
24 | //usage: "[-p] [PID|USER]" | ||
25 | //usage:#define pstree_full_usage "\n\n" | ||
26 | //usage: "Display process tree, optionally start from USER or PID\n" | ||
27 | //usage: "\nOptions:" | ||
28 | //usage: "\n -p Show pids" | ||
29 | |||
30 | #include "libbb.h" | ||
31 | |||
32 | #define PROC_BASE "/proc" | ||
33 | |||
34 | #define OPT_PID (1 << 0) | ||
35 | |||
36 | struct child; | ||
37 | |||
38 | typedef struct proc { | ||
39 | char comm[COMM_LEN + 1]; | ||
40 | // char flags; - unused, delete? | ||
41 | pid_t pid; | ||
42 | uid_t uid; | ||
43 | struct child *children; | ||
44 | struct proc *parent; | ||
45 | struct proc *next; | ||
46 | } PROC; | ||
47 | |||
48 | /* For flags above */ | ||
49 | //#define PFLAG_THREAD 0x01 | ||
50 | |||
51 | typedef struct child { | ||
52 | PROC *child; | ||
53 | struct child *next; | ||
54 | } CHILD; | ||
55 | |||
56 | #define empty_2 " " | ||
57 | #define branch_2 "|-" | ||
58 | #define vert_2 "| " | ||
59 | #define last_2 "`-" | ||
60 | #define single_3 "---" | ||
61 | #define first_3 "-+-" | ||
62 | |||
63 | struct globals { | ||
64 | /* 0-based. IOW: the number of chars we printed on current line */ | ||
65 | unsigned cur_x; | ||
66 | unsigned output_width; | ||
67 | |||
68 | /* The buffers will be dynamically increased in size as needed */ | ||
69 | unsigned capacity; | ||
70 | unsigned *width; | ||
71 | uint8_t *more; | ||
72 | |||
73 | PROC *list; | ||
74 | |||
75 | smallint dumped; /* used by dump_by_user */ | ||
76 | }; | ||
77 | #define G (*ptr_to_globals) | ||
78 | #define INIT_G() do { \ | ||
79 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | ||
80 | } while (0) | ||
81 | |||
82 | |||
83 | /* | ||
84 | * Allocates additional buffer space for width and more as needed. | ||
85 | * The first call will allocate the first buffer. | ||
86 | * | ||
87 | * bufindex the index that will be used after the call to this function. | ||
88 | */ | ||
89 | static void ensure_buffer_capacity(int bufindex) | ||
90 | { | ||
91 | if (bufindex >= G.capacity) { | ||
92 | G.capacity += 0x100; | ||
93 | G.width = xrealloc(G.width, G.capacity * sizeof(G.width[0])); | ||
94 | G.more = xrealloc(G.more, G.capacity * sizeof(G.more[0])); | ||
95 | } | ||
96 | } | ||
97 | |||
98 | /* NB: this function is never called with "bad" chars | ||
99 | * (control chars or chars >= 0x7f) | ||
100 | */ | ||
101 | static void out_char(char c) | ||
102 | { | ||
103 | G.cur_x++; | ||
104 | if (G.cur_x > G.output_width) | ||
105 | return; | ||
106 | if (G.cur_x == G.output_width) | ||
107 | c = '+'; | ||
108 | putchar(c); | ||
109 | } | ||
110 | |||
111 | /* NB: this function is never called with "bad" chars | ||
112 | * (control chars or chars >= 0x7f) | ||
113 | */ | ||
114 | static void out_string(const char *str) | ||
115 | { | ||
116 | while (*str) | ||
117 | out_char(*str++); | ||
118 | } | ||
119 | |||
120 | static void out_newline(void) | ||
121 | { | ||
122 | putchar('\n'); | ||
123 | G.cur_x = 0; | ||
124 | } | ||
125 | |||
126 | static PROC *find_proc(pid_t pid) | ||
127 | { | ||
128 | PROC *walk; | ||
129 | |||
130 | for (walk = G.list; walk; walk = walk->next) | ||
131 | if (walk->pid == pid) | ||
132 | break; | ||
133 | |||
134 | return walk; | ||
135 | } | ||
136 | |||
137 | static PROC *new_proc(const char *comm, pid_t pid, uid_t uid) | ||
138 | { | ||
139 | PROC *new = xzalloc(sizeof(*new)); | ||
140 | |||
141 | strcpy(new->comm, comm); | ||
142 | new->pid = pid; | ||
143 | new->uid = uid; | ||
144 | new->next = G.list; | ||
145 | |||
146 | G.list = new; | ||
147 | return G.list; | ||
148 | } | ||
149 | |||
150 | static void add_child(PROC *parent, PROC *child) | ||
151 | { | ||
152 | CHILD *new, **walk; | ||
153 | int cmp; | ||
154 | |||
155 | new = xmalloc(sizeof(*new)); | ||
156 | |||
157 | new->child = child; | ||
158 | for (walk = &parent->children; *walk; walk = &(*walk)->next) { | ||
159 | cmp = strcmp((*walk)->child->comm, child->comm); | ||
160 | if (cmp > 0) | ||
161 | break; | ||
162 | if (cmp == 0 && (*walk)->child->uid > child->uid) | ||
163 | break; | ||
164 | } | ||
165 | new->next = *walk; | ||
166 | *walk = new; | ||
167 | } | ||
168 | |||
169 | static void add_proc(const char *comm, pid_t pid, pid_t ppid, | ||
170 | uid_t uid /*, char isthread*/) | ||
171 | { | ||
172 | PROC *this, *parent; | ||
173 | |||
174 | this = find_proc(pid); | ||
175 | if (!this) | ||
176 | this = new_proc(comm, pid, uid); | ||
177 | else { | ||
178 | strcpy(this->comm, comm); | ||
179 | this->uid = uid; | ||
180 | } | ||
181 | |||
182 | if (pid == ppid) | ||
183 | ppid = 0; | ||
184 | // if (isthread) | ||
185 | // this->flags |= PFLAG_THREAD; | ||
186 | |||
187 | parent = find_proc(ppid); | ||
188 | if (!parent) | ||
189 | parent = new_proc("?", ppid, 0); | ||
190 | |||
191 | add_child(parent, this); | ||
192 | this->parent = parent; | ||
193 | } | ||
194 | |||
195 | static int tree_equal(const PROC *a, const PROC *b) | ||
196 | { | ||
197 | const CHILD *walk_a, *walk_b; | ||
198 | |||
199 | if (strcmp(a->comm, b->comm) != 0) | ||
200 | return 0; | ||
201 | if ((option_mask32 /*& OPT_PID*/) && a->pid != b->pid) | ||
202 | return 0; | ||
203 | |||
204 | for (walk_a = a->children, walk_b = b->children; | ||
205 | walk_a && walk_b; | ||
206 | walk_a = walk_a->next, walk_b = walk_b->next | ||
207 | ) { | ||
208 | if (!tree_equal(walk_a->child, walk_b->child)) | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | return !(walk_a || walk_b); | ||
213 | } | ||
214 | |||
215 | static int out_args(const char *mystr) | ||
216 | { | ||
217 | const char *here; | ||
218 | int strcount = 0; | ||
219 | char tmpstr[5]; | ||
220 | |||
221 | for (here = mystr; *here; here++) { | ||
222 | if (*here == '\\') { | ||
223 | out_string("\\\\"); | ||
224 | strcount += 2; | ||
225 | } else if (*here >= ' ' && *here < 0x7f) { | ||
226 | out_char(*here); | ||
227 | strcount++; | ||
228 | } else { | ||
229 | sprintf(tmpstr, "\\%03o", (unsigned char) *here); | ||
230 | out_string(tmpstr); | ||
231 | strcount += 4; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | return strcount; | ||
236 | } | ||
237 | |||
238 | static void | ||
239 | dump_tree(PROC *current, int level, int rep, int leaf, int last, int closing) | ||
240 | { | ||
241 | CHILD *walk, *next, **scan; | ||
242 | int lvl, i, add, offset, count, comm_len, first; | ||
243 | char tmp[sizeof(int)*3 + 4]; | ||
244 | |||
245 | if (!current) | ||
246 | return; | ||
247 | |||
248 | if (!leaf) { | ||
249 | for (lvl = 0; lvl < level; lvl++) { | ||
250 | i = G.width[lvl] + 1; | ||
251 | while (--i >= 0) | ||
252 | out_char(' '); | ||
253 | |||
254 | if (lvl == level - 1) { | ||
255 | if (last) { | ||
256 | out_string(last_2); | ||
257 | } else { | ||
258 | out_string(branch_2); | ||
259 | } | ||
260 | } else { | ||
261 | if (G.more[lvl + 1]) { | ||
262 | out_string(vert_2); | ||
263 | } else { | ||
264 | out_string(empty_2); | ||
265 | } | ||
266 | } | ||
267 | } | ||
268 | } | ||
269 | |||
270 | add = 0; | ||
271 | if (rep > 1) { | ||
272 | add += sprintf(tmp, "%d*[", rep); | ||
273 | out_string(tmp); | ||
274 | } | ||
275 | comm_len = out_args(current->comm); | ||
276 | if (option_mask32 /*& OPT_PID*/) { | ||
277 | comm_len += sprintf(tmp, "(%d)", (int)current->pid); | ||
278 | out_string(tmp); | ||
279 | } | ||
280 | offset = G.cur_x; | ||
281 | |||
282 | if (!current->children) { | ||
283 | while (closing--) | ||
284 | out_char(']'); | ||
285 | out_newline(); | ||
286 | } | ||
287 | ensure_buffer_capacity(level); | ||
288 | G.more[level] = !last; | ||
289 | |||
290 | G.width[level] = comm_len + G.cur_x - offset + add; | ||
291 | if (G.cur_x >= G.output_width) { | ||
292 | //out_string(first_3); - why? it won't print anything | ||
293 | //out_char('+'); | ||
294 | out_newline(); | ||
295 | return; | ||
296 | } | ||
297 | |||
298 | first = 1; | ||
299 | for (walk = current->children; walk; walk = next) { | ||
300 | count = 0; | ||
301 | next = walk->next; | ||
302 | scan = &walk->next; | ||
303 | while (*scan) { | ||
304 | if (!tree_equal(walk->child, (*scan)->child)) | ||
305 | scan = &(*scan)->next; | ||
306 | else { | ||
307 | if (next == *scan) | ||
308 | next = (*scan)->next; | ||
309 | count++; | ||
310 | *scan = (*scan)->next; | ||
311 | } | ||
312 | } | ||
313 | if (first) { | ||
314 | out_string(next ? first_3 : single_3); | ||
315 | first = 0; | ||
316 | } | ||
317 | |||
318 | dump_tree(walk->child, level + 1, count + 1, | ||
319 | walk == current->children, !next, | ||
320 | closing + (count ? 1 : 0)); | ||
321 | } | ||
322 | } | ||
323 | |||
324 | static void dump_by_user(PROC *current, uid_t uid) | ||
325 | { | ||
326 | const CHILD *walk; | ||
327 | |||
328 | if (!current) | ||
329 | return; | ||
330 | |||
331 | if (current->uid == uid) { | ||
332 | if (G.dumped) | ||
333 | putchar('\n'); | ||
334 | dump_tree(current, 0, 1, 1, 1, 0); | ||
335 | G.dumped = 1; | ||
336 | return; | ||
337 | } | ||
338 | for (walk = current->children; walk; walk = walk->next) | ||
339 | dump_by_user(walk->child, uid); | ||
340 | } | ||
341 | |||
342 | static void handle_thread(const char *comm, pid_t pid, pid_t ppid, uid_t uid) | ||
343 | { | ||
344 | char threadname[COMM_LEN + 2]; | ||
345 | sprintf(threadname, "{%.*s}", COMM_LEN - 2, comm); | ||
346 | add_proc(threadname, pid, ppid, uid/*, 1*/); | ||
347 | } | ||
348 | |||
349 | static void mread_proc(void) | ||
350 | { | ||
351 | procps_status_t *p = NULL; | ||
352 | pid_t parent = 0; | ||
353 | int flags = PSSCAN_COMM | PSSCAN_PID | PSSCAN_PPID | PSSCAN_UIDGID | PSSCAN_TASKS; | ||
354 | |||
355 | while ((p = procps_scan(p, flags)) != NULL) { | ||
356 | #if ENABLE_FEATURE_SHOW_THREADS | ||
357 | if (p->pid != p->main_thread_pid) | ||
358 | handle_thread(p->comm, p->pid, parent, p->uid); | ||
359 | else | ||
360 | #endif | ||
361 | { | ||
362 | add_proc(p->comm, p->pid, p->ppid, p->uid/*, 0*/); | ||
363 | parent = p->pid; | ||
364 | } | ||
365 | } | ||
366 | } | ||
367 | |||
368 | int pstree_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
369 | int pstree_main(int argc UNUSED_PARAM, char **argv) | ||
370 | { | ||
371 | pid_t pid = 1; | ||
372 | long uid = 0; | ||
373 | |||
374 | INIT_G(); | ||
375 | |||
376 | get_terminal_width_height(0, &G.output_width, NULL); | ||
377 | |||
378 | opt_complementary = "?1"; | ||
379 | getopt32(argv, "p"); | ||
380 | argv += optind; | ||
381 | |||
382 | if (argv[0]) { | ||
383 | if (argv[0][0] >= '0' && argv[0][0] <= '9') { | ||
384 | pid = xatoi(argv[0]); | ||
385 | } else { | ||
386 | uid = xuname2uid(argv[0]); | ||
387 | } | ||
388 | } | ||
389 | |||
390 | mread_proc(); | ||
391 | |||
392 | if (!uid) | ||
393 | dump_tree(find_proc(pid), 0, 1, 1, 1, 0); | ||
394 | else { | ||
395 | dump_by_user(find_proc(1), uid); | ||
396 | if (!G.dumped) { | ||
397 | bb_error_msg_and_die("no processes found"); | ||
398 | } | ||
399 | } | ||
400 | |||
401 | if (ENABLE_FEATURE_CLEAN_UP) { | ||
402 | free(G.width); | ||
403 | free(G.more); | ||
404 | } | ||
405 | return 0; | ||
406 | } | ||
diff --git a/procps/smemcap.c b/procps/smemcap.c index 196c91f54..200df6795 100644 --- a/procps/smemcap.c +++ b/procps/smemcap.c | |||
@@ -20,7 +20,7 @@ | |||
20 | //config: a memory usage statistic tool. | 20 | //config: a memory usage statistic tool. |
21 | 21 | ||
22 | #include "libbb.h" | 22 | #include "libbb.h" |
23 | #include "unarchive.h" | 23 | #include "archive.h" |
24 | 24 | ||
25 | struct fileblock { | 25 | struct fileblock { |
26 | struct fileblock *next; | 26 | struct fileblock *next; |
diff --git a/procps/sysctl.c b/procps/sysctl.c index 20b372c54..aba966e7f 100644 --- a/procps/sysctl.c +++ b/procps/sysctl.c | |||
@@ -91,7 +91,7 @@ static int sysctl_act_on_setting(char *setting) | |||
91 | retval = EXIT_FAILURE; | 91 | retval = EXIT_FAILURE; |
92 | goto end; | 92 | goto end; |
93 | } | 93 | } |
94 | value = cptr + 1; /* point to the value in name=value */ | 94 | value = cptr + 1; /* point to the value in name=value */ |
95 | if (setting == cptr || !*value) { | 95 | if (setting == cptr || !*value) { |
96 | bb_error_msg("error: malformed setting '%s'", outname); | 96 | bb_error_msg("error: malformed setting '%s'", outname); |
97 | retval = EXIT_FAILURE; | 97 | retval = EXIT_FAILURE; |
diff --git a/runit/runsvdir.c b/runit/runsvdir.c index e77eeff04..166664237 100644 --- a/runit/runsvdir.c +++ b/runit/runsvdir.c | |||
@@ -312,8 +312,11 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) | |||
312 | last_mtime = s.st_mtime; | 312 | last_mtime = s.st_mtime; |
313 | last_dev = s.st_dev; | 313 | last_dev = s.st_dev; |
314 | last_ino = s.st_ino; | 314 | last_ino = s.st_ino; |
315 | //if (now <= mtime) | 315 | /* if the svdir changed this very second, wait until the |
316 | // sleep(1); | 316 | * next second, because we won't be able to detect more |
317 | * changes within this second */ | ||
318 | while (time(NULL) == last_mtime) | ||
319 | usleep(100000); | ||
317 | need_rescan = do_rescan(); | 320 | need_rescan = do_rescan(); |
318 | while (fchdir(curdir) == -1) { | 321 | while (fchdir(curdir) == -1) { |
319 | warn2_cannot("change directory, pausing", ""); | 322 | warn2_cannot("change directory, pausing", ""); |
diff --git a/scripts/Makefile.IMA b/scripts/Makefile.IMA index 11ae39eae..a62618ae0 100644 --- a/scripts/Makefile.IMA +++ b/scripts/Makefile.IMA | |||
@@ -85,8 +85,8 @@ lib-y:= | |||
85 | include archival/Kbuild | 85 | include archival/Kbuild |
86 | lib-all-y += $(patsubst %,archival/%,$(sort $(lib-y))) | 86 | lib-all-y += $(patsubst %,archival/%,$(sort $(lib-y))) |
87 | lib-y:= | 87 | lib-y:= |
88 | include archival/libunarchive/Kbuild | 88 | include archival/libarchive/Kbuild |
89 | lib-all-y += $(patsubst %,archival/libunarchive/%,$(sort $(lib-y))) | 89 | lib-all-y += $(patsubst %,archival/libarchive/%,$(sort $(lib-y))) |
90 | lib-y:= | 90 | lib-y:= |
91 | include applets/Kbuild | 91 | include applets/Kbuild |
92 | lib-all-y += $(patsubst %,applets/%,$(sort $(lib-y))) | 92 | lib-all-y += $(patsubst %,applets/%,$(sort $(lib-y))) |
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c index 1a5b10f84..f27a17984 100644 --- a/scripts/basic/fixdep.c +++ b/scripts/basic/fixdep.c | |||
@@ -329,7 +329,7 @@ void parse_dep_file(void *map, size_t len) | |||
329 | clear_config(); | 329 | clear_config(); |
330 | 330 | ||
331 | while (m < end) { | 331 | while (m < end) { |
332 | while (m < end && (*m == ' ' || *m == '\\' || *m == '\n')) | 332 | while (m < end && (*m == ' ' || *m == '\\' || *m == '\n' || *m == '\r')) |
333 | m++; | 333 | m++; |
334 | p = m; | 334 | p = m; |
335 | while (p < end && *p != ' ') p++; | 335 | while (p < end && *p != ' ') p++; |
diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter index 95cbbe6b8..91374c1ca 100755 --- a/scripts/bloat-o-meter +++ b/scripts/bloat-o-meter | |||
@@ -63,7 +63,7 @@ def getsizes(file): | |||
63 | else: | 63 | else: |
64 | sym[name] = {"addr" : value, "size": size} | 64 | sym[name] = {"addr" : value, "size": size} |
65 | lut[(value, size)] = 0 | 65 | lut[(value, size)] = 0 |
66 | for addr, sz in alias.iterkeys(): | 66 | for addr, sz in iter(alias.keys()): |
67 | # If the non-GLOBAL sym has an implementation elsewhere then | 67 | # If the non-GLOBAL sym has an implementation elsewhere then |
68 | # it's an alias, disregard it. | 68 | # it's an alias, disregard it. |
69 | if not (addr, sz) in lut: | 69 | if not (addr, sz) in lut: |
@@ -92,7 +92,7 @@ if flag_timing: | |||
92 | grow, shrink, add, remove, up, down = 0, 0, 0, 0, 0, 0 | 92 | grow, shrink, add, remove, up, down = 0, 0, 0, 0, 0, 0 |
93 | delta, common = [], {} | 93 | delta, common = [], {} |
94 | 94 | ||
95 | for name in old.iterkeys(): | 95 | for name in iter(old.keys()): |
96 | if name in new: | 96 | if name in new: |
97 | common[name] = 1 | 97 | common[name] = 1 |
98 | 98 | ||
diff --git a/scripts/cleanup_printf2puts b/scripts/cleanup_printf2puts index 446152e12..00193a842 100755 --- a/scripts/cleanup_printf2puts +++ b/scripts/cleanup_printf2puts | |||
@@ -3,7 +3,7 @@ | |||
3 | # Processes current directory recursively: | 3 | # Processes current directory recursively: |
4 | # printf("abc\n") -> puts("abc"). Beware of fprintf etc... | 4 | # printf("abc\n") -> puts("abc"). Beware of fprintf etc... |
5 | 5 | ||
6 | # BTW, gcc 4.1.2 already does tha same! Can't believe it... | 6 | # BTW, gcc 4.1.2 already does the same! Can't believe it... |
7 | 7 | ||
8 | grep -lr 'printf\([^%%]*\\n"\)' . | grep '.[ch]$' | xargs -n1 \ | 8 | grep -lr 'printf\([^%%]*\\n"\)' . | grep '.[ch]$' | xargs -n1 \ |
9 | sed -e 's/\([^A-Za-z0-9_]\)printf(\( *"[^%]*\)\\n")/\1puts(\2")/' -i | 9 | sed -e 's/\([^A-Za-z0-9_]\)printf(\( *"[^%]*\)\\n")/\1puts(\2")/' -i |
diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh index 09a95b507..03831f501 100755 --- a/scripts/gen_build_files.sh +++ b/scripts/gen_build_files.sh | |||
@@ -9,43 +9,58 @@ mkdir include 2>/dev/null | |||
9 | 9 | ||
10 | srctree="$1" | 10 | srctree="$1" |
11 | 11 | ||
12 | status() { printf ' %-8s%s\n' "$1" "$2"; } | ||
13 | gen() { status "GEN" "$@"; } | ||
14 | chk() { status "CHK" "$@"; } | ||
15 | |||
16 | generate() | ||
17 | { | ||
18 | local src="$1" dst="$2" header="$3" insert="$4" | ||
19 | #chk "${dst}" | ||
20 | ( | ||
21 | # Need to use printf: different shells have inconsistent | ||
22 | # rules re handling of "\n" in echo params, | ||
23 | # and ${insert} definitely contains "\n". | ||
24 | # Therefore, echo "${header}" would not work: | ||
25 | printf "%s\n" "${header}" | ||
26 | if grep -qs '^INSERT$' "${src}"; then | ||
27 | sed -n '1,/^INSERT$/p' "${src}" | ||
28 | printf "%s\n" "${insert}" | ||
29 | sed -n '/^INSERT$/,$p' "${src}" | ||
30 | else | ||
31 | if [ -n "${insert}" ]; then | ||
32 | printf "%s\n" "ERROR: INSERT line missing in: ${src}" 1>&2 | ||
33 | fi | ||
34 | cat "${src}" | ||
35 | fi | ||
36 | ) | sed '/^INSERT$/d' > "${dst}.tmp" | ||
37 | if ! cmp -s "${dst}" "${dst}.tmp"; then | ||
38 | gen "${dst}" | ||
39 | mv "${dst}.tmp" "${dst}" | ||
40 | else | ||
41 | rm -f "${dst}.tmp" | ||
42 | fi | ||
43 | } | ||
44 | |||
12 | # (Re)generate include/applets.h | 45 | # (Re)generate include/applets.h |
13 | src="$srctree/include/applets.src.h" | ||
14 | dst="include/applets.h" | ||
15 | s=`sed -n 's@^//applet:@@p' -- "$srctree"/*/*.c "$srctree"/*/*/*.c` | 46 | s=`sed -n 's@^//applet:@@p' -- "$srctree"/*/*.c "$srctree"/*/*/*.c` |
16 | old=`cat "$dst" 2>/dev/null` | 47 | generate \ |
17 | # Why "IFS='' read -r REPLY"?? | 48 | "$srctree/include/applets.src.h" \ |
18 | # This atrocity is needed to read lines without mangling. | 49 | "include/applets.h" \ |
19 | # IFS='' prevents whitespace trimming, | 50 | "/* DO NOT EDIT. This file is generated from applets.src.h */" \ |
20 | # -r suppresses backslash handling. | 51 | "${s}" |
21 | new=`echo "/* DO NOT EDIT. This file is generated from applets.src.h */" | ||
22 | while IFS='' read -r REPLY; do | ||
23 | test x"$REPLY" = x"INSERT" && REPLY="$s" | ||
24 | printf "%s\n" "$REPLY" | ||
25 | done <"$src"` | ||
26 | if test x"$new" != x"$old"; then | ||
27 | echo " GEN $dst" | ||
28 | printf "%s\n" "$new" >"$dst" | ||
29 | fi | ||
30 | 52 | ||
31 | # (Re)generate include/usage.h | 53 | # (Re)generate include/usage.h |
32 | src="$srctree/include/usage.src.h" | ||
33 | dst="include/usage.h" | ||
34 | # We add line continuation backslash after each line, | 54 | # We add line continuation backslash after each line, |
35 | # and insert empty line before each line which doesn't start | 55 | # and insert empty line before each line which doesn't start |
36 | # with space or tab | 56 | # with space or tab |
37 | # (note: we need to use \\\\ because of ``) | 57 | # (note: we need to use \\\\ because of ``) |
38 | s=`sed -n -e 's@^//usage:\([ \t].*\)$@\1 \\\\@p' -e 's@^//usage:\([^ \t].*\)$@\n\1 \\\\@p' -- "$srctree"/*/*.c "$srctree"/*/*/*.c` | 58 | s=`sed -n -e 's@^//usage:\([ \t].*\)$@\1 \\\\@p' -e 's@^//usage:\([^ \t].*\)$@\n\1 \\\\@p' -- "$srctree"/*/*.c "$srctree"/*/*/*.c` |
39 | old=`cat "$dst" 2>/dev/null` | 59 | generate \ |
40 | new=`echo "/* DO NOT EDIT. This file is generated from usage.src.h */" | 60 | "$srctree/include/usage.src.h" \ |
41 | while IFS='' read -r REPLY; do | 61 | "include/usage.h" \ |
42 | test x"$REPLY" = x"INSERT" && REPLY="$s" | 62 | "/* DO NOT EDIT. This file is generated from usage.src.h */" \ |
43 | printf "%s\n" "$REPLY" | 63 | "${s}" |
44 | done <"$src"` | ||
45 | if test x"$new" != x"$old"; then | ||
46 | echo " GEN $dst" | ||
47 | printf "%s\n" "$new" >"$dst" | ||
48 | fi | ||
49 | 64 | ||
50 | # (Re)generate */Kbuild and */Config.in | 65 | # (Re)generate */Kbuild and */Config.in |
51 | { cd -- "$srctree" && find . -type d; } | while read -r d; do | 66 | { cd -- "$srctree" && find . -type d; } | while read -r d; do |
@@ -55,40 +70,24 @@ fi | |||
55 | dst="$d/Kbuild" | 70 | dst="$d/Kbuild" |
56 | if test -f "$src"; then | 71 | if test -f "$src"; then |
57 | mkdir -p -- "$d" 2>/dev/null | 72 | mkdir -p -- "$d" 2>/dev/null |
58 | #echo " CHK $dst" | ||
59 | 73 | ||
60 | s=`sed -n 's@^//kbuild:@@p' -- "$srctree/$d"/*.c` | 74 | s=`sed -n 's@^//kbuild:@@p' -- "$srctree/$d"/*.c` |
61 | 75 | generate \ | |
62 | old=`cat "$dst" 2>/dev/null` | 76 | "${src}" "${dst}" \ |
63 | new=`echo "# DO NOT EDIT. This file is generated from Kbuild.src" | 77 | "# DO NOT EDIT. This file is generated from Kbuild.src" \ |
64 | while IFS='' read -r REPLY; do | 78 | "${s}" |
65 | test x"$REPLY" = x"INSERT" && REPLY="$s" | ||
66 | printf "%s\n" "$REPLY" | ||
67 | done <"$src"` | ||
68 | if test x"$new" != x"$old"; then | ||
69 | echo " GEN $dst" | ||
70 | printf "%s\n" "$new" >"$dst" | ||
71 | fi | ||
72 | fi | 79 | fi |
73 | 80 | ||
74 | src="$srctree/$d/Config.src" | 81 | src="$srctree/$d/Config.src" |
75 | dst="$d/Config.in" | 82 | dst="$d/Config.in" |
76 | if test -f "$src"; then | 83 | if test -f "$src"; then |
77 | mkdir -p -- "$d" 2>/dev/null | 84 | mkdir -p -- "$d" 2>/dev/null |
78 | #echo " CHK $dst" | ||
79 | 85 | ||
80 | s=`sed -n 's@^//config:@@p' -- "$srctree/$d"/*.c` | 86 | s=`sed -n 's@^//config:@@p' -- "$srctree/$d"/*.c` |
81 | 87 | generate \ | |
82 | old=`cat "$dst" 2>/dev/null` | 88 | "${src}" "${dst}" \ |
83 | new=`echo "# DO NOT EDIT. This file is generated from Config.src" | 89 | "# DO NOT EDIT. This file is generated from Config.src" \ |
84 | while IFS='' read -r REPLY; do | 90 | "${s}" |
85 | test x"$REPLY" = x"INSERT" && REPLY="$s" | ||
86 | printf "%s\n" "$REPLY" | ||
87 | done <"$src"` | ||
88 | if test x"$new" != x"$old"; then | ||
89 | echo " GEN $dst" | ||
90 | printf "%s\n" "$new" >"$dst" | ||
91 | fi | ||
92 | fi | 91 | fi |
93 | done | 92 | done |
94 | 93 | ||
diff --git a/scripts/individual b/scripts/individual deleted file mode 100755 index e93ca5552..000000000 --- a/scripts/individual +++ /dev/null | |||
@@ -1,129 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | # Compile individual versions of each busybox applet. | ||
4 | |||
5 | if [ $# -eq 0 ] | ||
6 | then | ||
7 | |||
8 | # Clear out the build directory. (Make clean should do this instead of here.) | ||
9 | |||
10 | rm -rf build | ||
11 | mkdir build | ||
12 | |||
13 | # Make our prerequisites. | ||
14 | |||
15 | make busybox.links include/bb_config.h $(pwd)/{libbb/libbb.a,archival/libunarchive/libunarchive.a,coreutils/libcoreutils/libcoreutils.a,networking/libiproute/libiproute.a} | ||
16 | |||
17 | else | ||
18 | # Could very well be that we want to build an individual applet but have no | ||
19 | # 'build' dir yet.. | ||
20 | |||
21 | test -d ./build || mkdir build | ||
22 | |||
23 | fi | ||
24 | |||
25 | # About 3/5 of the applets build from one .c file (with the same name as the | ||
26 | # corresponding applet), and all it needs to link against. However, to build | ||
27 | # them all we need more than that. | ||
28 | |||
29 | # Figure out which applets need extra libraries added to their command line. | ||
30 | |||
31 | function substithing() | ||
32 | { | ||
33 | if [ "${1/ $3 //}" != "$1" ] | ||
34 | then | ||
35 | echo $2 | ||
36 | fi | ||
37 | } | ||
38 | |||
39 | function extra_libraries() | ||
40 | { | ||
41 | # gzip needs gunzip.c (when gunzip is enabled, anyway). | ||
42 | substithing " gzip " "archival/gunzip.c archival/uncompress.c" "$1" | ||
43 | |||
44 | # init needs init_shared.c | ||
45 | substithing " init " "init/init_shared.c" "$1" | ||
46 | |||
47 | # ifconfig needs interface.c | ||
48 | substithing " ifconfig " "networking/interface.c" "$1" | ||
49 | |||
50 | # Applets that need libunarchive.a | ||
51 | substithing " ar bunzip2 unlzma cpio dpkg gunzip rpm2cpio rpm tar uncompress unzip dpkg_deb gzip " "archival/libunarchive/libunarchive.a" "$1" | ||
52 | |||
53 | # Applets that need libcoreutils.a | ||
54 | substithing " cp mv " "coreutils/libcoreutils/libcoreutils.a" "$1" | ||
55 | |||
56 | # Applets that need libiproute.a | ||
57 | substithing " ip " "networking/libiproute/libiproute.a" "$1" | ||
58 | |||
59 | # What needs -libm? | ||
60 | substithing " awk dc " "-lm" "$1" | ||
61 | |||
62 | # What needs -lcrypt? | ||
63 | substithing " httpd vlock " "-lcrypt" "$1" | ||
64 | } | ||
65 | |||
66 | # Query applets.h to figure out which applets need special treatment | ||
67 | |||
68 | strange_names=`sed -rn -e 's/\#.*//' -e 's/.*APPLET_NOUSAGE\(([^,]*),([^,]*),.*/\1 \2/p' -e 's/.*APPLET_ODDNAME\(([^,]*),([^,]*),.*, *([^)]*).*/\1 \2@\3/p' include/applets.h` | ||
69 | |||
70 | function bonkname() | ||
71 | { | ||
72 | while [ $# -gt 0 ] | ||
73 | do | ||
74 | if [ "$APPLET" == "$1" ] | ||
75 | then | ||
76 | APPFILT="${2/@*/}" | ||
77 | if [ "${APPFILT}" == "$2" ] | ||
78 | then | ||
79 | HELPNAME='"nousage\n"' # These should be _fixed_. | ||
80 | else | ||
81 | HELPNAME="${2/*@/}"_full_usage | ||
82 | fi | ||
83 | break | ||
84 | fi | ||
85 | shift 2 | ||
86 | done | ||
87 | #echo APPLET=${APPLET} APPFILT=${APPFILT} HELPNAME=${HELPNAME} 2=${2} | ||
88 | } | ||
89 | |||
90 | # Iterate through every name in busybox.links | ||
91 | |||
92 | function buildit () | ||
93 | { | ||
94 | export APPLET="$1" | ||
95 | export APPFILT=${APPLET} | ||
96 | export HELPNAME=${APPLET}_full_usage | ||
97 | |||
98 | bonkname $strange_names | ||
99 | |||
100 | j=`find archival console-tools coreutils debianutils editors findutils init loginutils miscutils modutils networking procps shell sysklogd util-linux -name "${APPFILT}.c"` | ||
101 | if [ -z "$j" ] | ||
102 | then | ||
103 | echo no file for $APPLET | ||
104 | else | ||
105 | echo "Building $APPLET" | ||
106 | gcc -Os -o build/$APPLET applets/individual.c $j \ | ||
107 | `extra_libraries $APPFILT` libbb/libbb.a -Iinclude \ | ||
108 | -DBUILD_INDIVIDUAL \ | ||
109 | '-Drun_applet_and_exit(...)' '-Dfind_applet_by_name(...)=0' \ | ||
110 | -DAPPLET_main=${APPFILT}_main -DAPPLET_full_usage=${HELPNAME} | ||
111 | if [ $? -ne 0 ]; | ||
112 | then | ||
113 | echo "Failed $APPLET" | ||
114 | fi | ||
115 | fi | ||
116 | } | ||
117 | |||
118 | if [ $# -eq 0 ] | ||
119 | then | ||
120 | for APPLET in `sed 's .*/ ' busybox.links` | ||
121 | do | ||
122 | buildit "$APPLET" | ||
123 | done | ||
124 | else | ||
125 | buildit "$1" | ||
126 | fi | ||
127 | |||
128 | |||
129 | strip build/* | ||
diff --git a/scripts/mkdiff_obj b/scripts/mkdiff_obj index a6ec5e602..307474874 100755 --- a/scripts/mkdiff_obj +++ b/scripts/mkdiff_obj | |||
@@ -1,28 +1,35 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | ||
3 | usage() { | ||
4 | echo "Usage: ${0##*/} DIR1 DIR2" | ||
5 | echo | ||
6 | echo "Compares all object files recursivelty found in DIR1 and DIR2." | ||
7 | echo "Prints diff of their disassembly." | ||
8 | echo | ||
9 | exit $1 | ||
10 | } | ||
11 | |||
3 | filter() { | 12 | filter() { |
4 | # sed removes " address: " prefixes which mess up diff | 13 | # sed removes " address: " prefixes which mess up diff |
5 | sed $'s/^\\(\t*\\)[ ]*[0-9a-f][0-9a-f]*:[ \t]*/\\1/' \ | 14 | sed $'s/^\\(\t*\\)[ ]*[0-9a-f][0-9a-f]*:[ \t]*/\\1/' \ |
6 | | sed 's/__GI_//g' | 15 | | sed 's/__GI_//g' |
7 | } | 16 | } |
8 | 17 | ||
9 | test -d "$1" || exit 1 | 18 | test -d "$1" || usage 1 |
10 | test -d "$2" || exit 1 | 19 | test -d "$2" || usage 1 |
11 | 20 | ||
12 | { | 21 | { |
13 | ( | 22 | ( |
14 | cd "$1" || exit 1 | 23 | cd "$1" || exit 1 |
15 | find -name '*.o' -o -name '*.os' # -o -name '*.so' | 24 | find -name '*.o' # -o -name '*.os' # -o -name '*.so' |
16 | ) | 25 | ) |
17 | ( | 26 | ( |
18 | cd "$2" || exit 1 | 27 | cd "$2" || exit 1 |
19 | find -name '*.o' -o -name '*.os' # -o -name '*.so' | 28 | find -name '*.o' # -o -name '*.os' # -o -name '*.so' |
20 | ) | 29 | ) |
21 | } | sed 's:^\./::' | sort | uniq | \ | 30 | } | sed 's:^\./::' | sort | uniq | \ |
22 | tee LST | \ | ||
23 | ( | 31 | ( |
24 | IFS='' | 32 | while IFS='' read -r oname; do |
25 | while read -r oname; do | ||
26 | if ! test -f "$1/$oname"; then | 33 | if ! test -f "$1/$oname"; then |
27 | echo "Only $2/$oname" | 34 | echo "Only $2/$oname" |
28 | continue | 35 | continue |
@@ -32,8 +39,8 @@ while read -r oname; do | |||
32 | continue | 39 | continue |
33 | fi | 40 | fi |
34 | diff -q -- "$1/$oname" "$2/$oname" >/dev/null && continue | 41 | diff -q -- "$1/$oname" "$2/$oname" >/dev/null && continue |
35 | (cd "$1"; objdump -dr "$oname" | filter >"$oname.disasm") | 42 | (cd "$1" && { size "$oname"; objdump -dr "$oname" | filter; } >"$oname.disasm") |
36 | (cd "$2"; objdump -dr "$oname" | filter >"$oname.disasm") | 43 | (cd "$2" && { size "$oname"; objdump -dr "$oname" | filter; } >"$oname.disasm") |
37 | diff -u "$1/$oname.disasm" "$2/$oname.disasm" | 44 | diff -u -- "$1/$oname.disasm" "$2/$oname.disasm" |
38 | done | 45 | done |
39 | ) | 46 | ) |
diff --git a/scripts/randomtest.loop b/scripts/randomtest.loop index 311536df8..2c8a9bd35 100755 --- a/scripts/randomtest.loop +++ b/scripts/randomtest.loop | |||
@@ -4,7 +4,7 @@ test -d "$1" || { echo "'$1' is not a directory"; exit 1; } | |||
4 | test -x "$1/scripts/randomtest" || { echo "No scripts/randomtest in '$1'"; exit 1; } | 4 | test -x "$1/scripts/randomtest" || { echo "No scripts/randomtest in '$1'"; exit 1; } |
5 | 5 | ||
6 | export LIBC="uclibc" | 6 | export LIBC="uclibc" |
7 | export CROSS_COMPILER_PREFIX="i486-linux-uclibc-" | 7 | export CROSS_COMPILER_PREFIX="i686-" |
8 | export MAKEOPTS="-j9" | 8 | export MAKEOPTS="-j9" |
9 | 9 | ||
10 | cnt=0 | 10 | cnt=0 |
diff --git a/selinux/runcon.c b/selinux/runcon.c index b70a5e396..54349b25c 100644 --- a/selinux/runcon.c +++ b/selinux/runcon.c | |||
@@ -132,6 +132,5 @@ int runcon_main(int argc UNUSED_PARAM, char **argv) | |||
132 | bb_error_msg_and_die("can't set up security context '%s'", | 132 | bb_error_msg_and_die("can't set up security context '%s'", |
133 | context_str(con)); | 133 | context_str(con)); |
134 | 134 | ||
135 | execvp(argv[0], argv); | 135 | BB_EXECVP_or_die(argv); |
136 | bb_perror_msg_and_die("can't execute '%s'", argv[0]); | ||
137 | } | 136 | } |
diff --git a/selinux/sestatus.c b/selinux/sestatus.c index 7fb2b470b..aa12e806c 100644 --- a/selinux/sestatus.c +++ b/selinux/sestatus.c | |||
@@ -12,10 +12,10 @@ | |||
12 | 12 | ||
13 | extern char *selinux_mnt; | 13 | extern char *selinux_mnt; |
14 | 14 | ||
15 | #define OPT_VERBOSE (1 << 0) | 15 | #define OPT_VERBOSE (1 << 0) |
16 | #define OPT_BOOLEAN (1 << 1) | 16 | #define OPT_BOOLEAN (1 << 1) |
17 | 17 | ||
18 | #define COL_FMT "%-31s " | 18 | #define COL_FMT "%-31s " |
19 | 19 | ||
20 | static void display_boolean(void) | 20 | static void display_boolean(void) |
21 | { | 21 | { |
@@ -151,7 +151,7 @@ int sestatus_main(int argc UNUSED_PARAM, char **argv) | |||
151 | const char *pol_path; | 151 | const char *pol_path; |
152 | int rc; | 152 | int rc; |
153 | 153 | ||
154 | opt_complementary = "?0"; /* no arguments are required. */ | 154 | opt_complementary = "?0"; /* no arguments are required. */ |
155 | opts = getopt32(argv, "vb"); | 155 | opts = getopt32(argv, "vb"); |
156 | 156 | ||
157 | /* SELinux status: line */ | 157 | /* SELinux status: line */ |
diff --git a/shell/ash.c b/shell/ash.c index ccf4288a9..f7baf2b3b 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -57,7 +57,9 @@ | |||
57 | #include <sys/times.h> | 57 | #include <sys/times.h> |
58 | 58 | ||
59 | #include "shell_common.h" | 59 | #include "shell_common.h" |
60 | #include "math.h" | 60 | #if ENABLE_SH_MATH_SUPPORT |
61 | # include "math.h" | ||
62 | #endif | ||
61 | #if ENABLE_ASH_RANDOM_SUPPORT | 63 | #if ENABLE_ASH_RANDOM_SUPPORT |
62 | # include "random.h" | 64 | # include "random.h" |
63 | #else | 65 | #else |
@@ -5834,6 +5836,11 @@ static struct arglist exparg; | |||
5834 | /* | 5836 | /* |
5835 | * Our own itoa(). | 5837 | * Our own itoa(). |
5836 | */ | 5838 | */ |
5839 | #if !ENABLE_SH_MATH_SUPPORT | ||
5840 | /* cvtnum() is used even if math support is off (to prepare $? values and such) */ | ||
5841 | typedef long arith_t; | ||
5842 | # define ARITH_FMT "%ld" | ||
5843 | #endif | ||
5837 | static int | 5844 | static int |
5838 | cvtnum(arith_t num) | 5845 | cvtnum(arith_t num) |
5839 | { | 5846 | { |
@@ -13648,7 +13655,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
13648 | } | 13655 | } |
13649 | } | 13656 | } |
13650 | #endif | 13657 | #endif |
13651 | if (/* argv[0] && */ argv[0][0] == '-') | 13658 | if (argv[0] && argv[0][0] == '-') |
13652 | isloginsh = 1; | 13659 | isloginsh = 1; |
13653 | if (isloginsh) { | 13660 | if (isloginsh) { |
13654 | state = 1; | 13661 | state = 1; |
diff --git a/shell/ash_test/recho.c b/shell/ash_test/recho.c index fb48d9c48..42a5feafd 100644 --- a/shell/ash_test/recho.c +++ b/shell/ash_test/recho.c | |||
@@ -29,12 +29,9 @@ | |||
29 | 29 | ||
30 | void strprint(); | 30 | void strprint(); |
31 | 31 | ||
32 | int | 32 | int main(int argc, char **argv) |
33 | main(argc, argv) | ||
34 | int argc; | ||
35 | char **argv; | ||
36 | { | 33 | { |
37 | register int i; | 34 | int i; |
38 | 35 | ||
39 | for (i = 1; i < argc; i++) { | 36 | for (i = 1; i < argc; i++) { |
40 | printf("argv[%d] = <", i); | 37 | printf("argv[%d] = <", i); |
@@ -44,11 +41,9 @@ char **argv; | |||
44 | exit(EXIT_SUCCESS); | 41 | exit(EXIT_SUCCESS); |
45 | } | 42 | } |
46 | 43 | ||
47 | void | 44 | void strprint(char *str) |
48 | strprint(str) | ||
49 | char *str; | ||
50 | { | 45 | { |
51 | register unsigned char *s; | 46 | unsigned char *s; |
52 | 47 | ||
53 | for (s = (unsigned char *)str; s && *s; s++) { | 48 | for (s = (unsigned char *)str; s && *s; s++) { |
54 | if (*s < ' ') { | 49 | if (*s < ' ') { |
diff --git a/shell/ash_test/zecho.c b/shell/ash_test/zecho.c index bf876f641..cbaa59b81 100644 --- a/shell/ash_test/zecho.c +++ b/shell/ash_test/zecho.c | |||
@@ -21,10 +21,7 @@ | |||
21 | #include <stdio.h> | 21 | #include <stdio.h> |
22 | #include <stdlib.h> | 22 | #include <stdlib.h> |
23 | 23 | ||
24 | int | 24 | int main(int argc, char **argv) |
25 | main(argc, argv) | ||
26 | int argc; | ||
27 | char **argv; | ||
28 | { | 25 | { |
29 | argv++; | 26 | argv++; |
30 | 27 | ||
diff --git a/shell/hush.c b/shell/hush.c index 9dd30c436..a771e9cd9 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -82,7 +82,11 @@ | |||
82 | * aaa | 82 | * aaa |
83 | */ | 83 | */ |
84 | #include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */ | 84 | #include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */ |
85 | #include <malloc.h> /* for malloc_trim */ | 85 | #if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ |
86 | || defined(__APPLE__) \ | ||
87 | ) | ||
88 | # include <malloc.h> /* for malloc_trim */ | ||
89 | #endif | ||
86 | #include <glob.h> | 90 | #include <glob.h> |
87 | /* #include <dmalloc.h> */ | 91 | /* #include <dmalloc.h> */ |
88 | #if ENABLE_HUSH_CASE | 92 | #if ENABLE_HUSH_CASE |
@@ -245,9 +249,15 @@ | |||
245 | //config: msh is deprecated and will be removed, please migrate to hush. | 249 | //config: msh is deprecated and will be removed, please migrate to hush. |
246 | //config: | 250 | //config: |
247 | 251 | ||
248 | //usage:#define hush_trivial_usage NOUSAGE_STR | 252 | /* -i (interactive) and -s (read stdin) are also accepted, |
253 | * but currently do nothing, therefore aren't shown in help. | ||
254 | * NOMMU-specific options are not meant to be used by users, | ||
255 | * therefore we don't show them either. | ||
256 | */ | ||
257 | //usage:#define hush_trivial_usage | ||
258 | //usage: "[-nx] [-c SCRIPT]" | ||
249 | //usage:#define hush_full_usage "" | 259 | //usage:#define hush_full_usage "" |
250 | //usage:#define msh_trivial_usage NOUSAGE_STR | 260 | //usage:#define msh_trivial_usage hush_trivial_usage |
251 | //usage:#define msh_full_usage "" | 261 | //usage:#define msh_full_usage "" |
252 | //usage:#define sh_trivial_usage NOUSAGE_STR | 262 | //usage:#define sh_trivial_usage NOUSAGE_STR |
253 | //usage:#define sh_full_usage "" | 263 | //usage:#define sh_full_usage "" |
@@ -507,6 +517,7 @@ struct command { | |||
507 | # define CMD_FUNCDEF 3 | 517 | # define CMD_FUNCDEF 3 |
508 | #endif | 518 | #endif |
509 | 519 | ||
520 | smalluint cmd_exitcode; | ||
510 | /* if non-NULL, this "command" is { list }, ( list ), or a compound statement */ | 521 | /* if non-NULL, this "command" is { list }, ( list ), or a compound statement */ |
511 | struct pipe *group; | 522 | struct pipe *group; |
512 | #if !BB_MMU | 523 | #if !BB_MMU |
@@ -542,7 +553,6 @@ struct command { | |||
542 | #define IS_NULL_CMD(cmd) \ | 553 | #define IS_NULL_CMD(cmd) \ |
543 | (!(cmd)->group && !(cmd)->argv && !(cmd)->redirects) | 554 | (!(cmd)->group && !(cmd)->argv && !(cmd)->redirects) |
544 | 555 | ||
545 | |||
546 | struct pipe { | 556 | struct pipe { |
547 | struct pipe *next; | 557 | struct pipe *next; |
548 | int num_cmds; /* total number of commands in pipe */ | 558 | int num_cmds; /* total number of commands in pipe */ |
@@ -637,6 +647,53 @@ struct function { | |||
637 | #endif | 647 | #endif |
638 | 648 | ||
639 | 649 | ||
650 | /* set -/+o OPT support. (TODO: make it optional) | ||
651 | * bash supports the following opts: | ||
652 | * allexport off | ||
653 | * braceexpand on | ||
654 | * emacs on | ||
655 | * errexit off | ||
656 | * errtrace off | ||
657 | * functrace off | ||
658 | * hashall on | ||
659 | * histexpand off | ||
660 | * history on | ||
661 | * ignoreeof off | ||
662 | * interactive-comments on | ||
663 | * keyword off | ||
664 | * monitor on | ||
665 | * noclobber off | ||
666 | * noexec off | ||
667 | * noglob off | ||
668 | * nolog off | ||
669 | * notify off | ||
670 | * nounset off | ||
671 | * onecmd off | ||
672 | * physical off | ||
673 | * pipefail off | ||
674 | * posix off | ||
675 | * privileged off | ||
676 | * verbose off | ||
677 | * vi off | ||
678 | * xtrace off | ||
679 | */ | ||
680 | static const char o_opt_strings[] ALIGN1 = | ||
681 | "pipefail\0" | ||
682 | "noexec\0" | ||
683 | #if ENABLE_HUSH_MODE_X | ||
684 | "xtrace\0" | ||
685 | #endif | ||
686 | ; | ||
687 | enum { | ||
688 | OPT_O_PIPEFAIL, | ||
689 | OPT_O_NOEXEC, | ||
690 | #if ENABLE_HUSH_MODE_X | ||
691 | OPT_O_XTRACE, | ||
692 | #endif | ||
693 | NUM_OPT_O | ||
694 | }; | ||
695 | |||
696 | |||
640 | /* "Globals" within this file */ | 697 | /* "Globals" within this file */ |
641 | /* Sorted roughly by size (smaller offsets == smaller code) */ | 698 | /* Sorted roughly by size (smaller offsets == smaller code) */ |
642 | struct globals { | 699 | struct globals { |
@@ -679,6 +736,12 @@ struct globals { | |||
679 | #else | 736 | #else |
680 | # define G_saved_tty_pgrp 0 | 737 | # define G_saved_tty_pgrp 0 |
681 | #endif | 738 | #endif |
739 | char o_opt[NUM_OPT_O]; | ||
740 | #if ENABLE_HUSH_MODE_X | ||
741 | # define G_x_mode (G.o_opt[OPT_O_XTRACE]) | ||
742 | #else | ||
743 | # define G_x_mode 0 | ||
744 | #endif | ||
682 | smallint flag_SIGINT; | 745 | smallint flag_SIGINT; |
683 | #if ENABLE_HUSH_LOOPS | 746 | #if ENABLE_HUSH_LOOPS |
684 | smallint flag_break_continue; | 747 | smallint flag_break_continue; |
@@ -690,13 +753,6 @@ struct globals { | |||
690 | */ | 753 | */ |
691 | smallint flag_return_in_progress; | 754 | smallint flag_return_in_progress; |
692 | #endif | 755 | #endif |
693 | smallint n_mode; | ||
694 | #if ENABLE_HUSH_MODE_X | ||
695 | smallint x_mode; | ||
696 | # define G_x_mode (G.x_mode) | ||
697 | #else | ||
698 | # define G_x_mode 0 | ||
699 | #endif | ||
700 | smallint exiting; /* used to prevent EXIT trap recursion */ | 756 | smallint exiting; /* used to prevent EXIT trap recursion */ |
701 | /* These four support $?, $#, and $1 */ | 757 | /* These four support $?, $#, and $1 */ |
702 | smalluint last_exitcode; | 758 | smalluint last_exitcode; |
@@ -875,7 +931,7 @@ static const struct built_in_command bltins2[] = { | |||
875 | */ | 931 | */ |
876 | #if HUSH_DEBUG | 932 | #if HUSH_DEBUG |
877 | /* prevent disasters with G.debug_indent < 0 */ | 933 | /* prevent disasters with G.debug_indent < 0 */ |
878 | # define indent() fprintf(stderr, "%*s", (G.debug_indent * 2) & 0xff, "") | 934 | # define indent() fdprintf(2, "%*s", (G.debug_indent * 2) & 0xff, "") |
879 | # define debug_enter() (G.debug_indent++) | 935 | # define debug_enter() (G.debug_indent++) |
880 | # define debug_leave() (G.debug_indent--) | 936 | # define debug_leave() (G.debug_indent--) |
881 | #else | 937 | #else |
@@ -885,56 +941,56 @@ static const struct built_in_command bltins2[] = { | |||
885 | #endif | 941 | #endif |
886 | 942 | ||
887 | #ifndef debug_printf | 943 | #ifndef debug_printf |
888 | # define debug_printf(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 944 | # define debug_printf(...) (indent(), fdprintf(2, __VA_ARGS__)) |
889 | #endif | 945 | #endif |
890 | 946 | ||
891 | #ifndef debug_printf_parse | 947 | #ifndef debug_printf_parse |
892 | # define debug_printf_parse(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 948 | # define debug_printf_parse(...) (indent(), fdprintf(2, __VA_ARGS__)) |
893 | #endif | 949 | #endif |
894 | 950 | ||
895 | #ifndef debug_printf_exec | 951 | #ifndef debug_printf_exec |
896 | #define debug_printf_exec(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 952 | #define debug_printf_exec(...) (indent(), fdprintf(2, __VA_ARGS__)) |
897 | #endif | 953 | #endif |
898 | 954 | ||
899 | #ifndef debug_printf_env | 955 | #ifndef debug_printf_env |
900 | # define debug_printf_env(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 956 | # define debug_printf_env(...) (indent(), fdprintf(2, __VA_ARGS__)) |
901 | #endif | 957 | #endif |
902 | 958 | ||
903 | #ifndef debug_printf_jobs | 959 | #ifndef debug_printf_jobs |
904 | # define debug_printf_jobs(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 960 | # define debug_printf_jobs(...) (indent(), fdprintf(2, __VA_ARGS__)) |
905 | # define DEBUG_JOBS 1 | 961 | # define DEBUG_JOBS 1 |
906 | #else | 962 | #else |
907 | # define DEBUG_JOBS 0 | 963 | # define DEBUG_JOBS 0 |
908 | #endif | 964 | #endif |
909 | 965 | ||
910 | #ifndef debug_printf_expand | 966 | #ifndef debug_printf_expand |
911 | # define debug_printf_expand(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 967 | # define debug_printf_expand(...) (indent(), fdprintf(2, __VA_ARGS__)) |
912 | # define DEBUG_EXPAND 1 | 968 | # define DEBUG_EXPAND 1 |
913 | #else | 969 | #else |
914 | # define DEBUG_EXPAND 0 | 970 | # define DEBUG_EXPAND 0 |
915 | #endif | 971 | #endif |
916 | 972 | ||
917 | #ifndef debug_printf_varexp | 973 | #ifndef debug_printf_varexp |
918 | # define debug_printf_varexp(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 974 | # define debug_printf_varexp(...) (indent(), fdprintf(2, __VA_ARGS__)) |
919 | #endif | 975 | #endif |
920 | 976 | ||
921 | #ifndef debug_printf_glob | 977 | #ifndef debug_printf_glob |
922 | # define debug_printf_glob(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 978 | # define debug_printf_glob(...) (indent(), fdprintf(2, __VA_ARGS__)) |
923 | # define DEBUG_GLOB 1 | 979 | # define DEBUG_GLOB 1 |
924 | #else | 980 | #else |
925 | # define DEBUG_GLOB 0 | 981 | # define DEBUG_GLOB 0 |
926 | #endif | 982 | #endif |
927 | 983 | ||
928 | #ifndef debug_printf_list | 984 | #ifndef debug_printf_list |
929 | # define debug_printf_list(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 985 | # define debug_printf_list(...) (indent(), fdprintf(2, __VA_ARGS__)) |
930 | #endif | 986 | #endif |
931 | 987 | ||
932 | #ifndef debug_printf_subst | 988 | #ifndef debug_printf_subst |
933 | # define debug_printf_subst(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 989 | # define debug_printf_subst(...) (indent(), fdprintf(2, __VA_ARGS__)) |
934 | #endif | 990 | #endif |
935 | 991 | ||
936 | #ifndef debug_printf_clean | 992 | #ifndef debug_printf_clean |
937 | # define debug_printf_clean(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 993 | # define debug_printf_clean(...) (indent(), fdprintf(2, __VA_ARGS__)) |
938 | # define DEBUG_CLEAN 1 | 994 | # define DEBUG_CLEAN 1 |
939 | #else | 995 | #else |
940 | # define DEBUG_CLEAN 0 | 996 | # define DEBUG_CLEAN 0 |
@@ -944,9 +1000,9 @@ static const struct built_in_command bltins2[] = { | |||
944 | static void debug_print_strings(const char *prefix, char **vv) | 1000 | static void debug_print_strings(const char *prefix, char **vv) |
945 | { | 1001 | { |
946 | indent(); | 1002 | indent(); |
947 | fprintf(stderr, "%s:\n", prefix); | 1003 | fdprintf(2, "%s:\n", prefix); |
948 | while (*vv) | 1004 | while (*vv) |
949 | fprintf(stderr, " '%s'\n", *vv++); | 1005 | fdprintf(2, " '%s'\n", *vv++); |
950 | } | 1006 | } |
951 | #else | 1007 | #else |
952 | # define debug_print_strings(prefix, vv) ((void)0) | 1008 | # define debug_print_strings(prefix, vv) ((void)0) |
@@ -1378,6 +1434,22 @@ static void hush_exit(int exitcode) | |||
1378 | builtin_eval(argv); | 1434 | builtin_eval(argv); |
1379 | } | 1435 | } |
1380 | 1436 | ||
1437 | #if ENABLE_FEATURE_CLEAN_UP | ||
1438 | { | ||
1439 | struct variable *cur_var; | ||
1440 | if (G.cwd != bb_msg_unknown) | ||
1441 | free((char*)G.cwd); | ||
1442 | cur_var = G.top_var; | ||
1443 | while (cur_var) { | ||
1444 | struct variable *tmp = cur_var; | ||
1445 | if (!cur_var->max_len) | ||
1446 | free(cur_var->varstr); | ||
1447 | cur_var = cur_var->next; | ||
1448 | free(tmp); | ||
1449 | } | ||
1450 | } | ||
1451 | #endif | ||
1452 | |||
1381 | #if ENABLE_HUSH_JOB | 1453 | #if ENABLE_HUSH_JOB |
1382 | fflush_all(); | 1454 | fflush_all(); |
1383 | sigexit(- (exitcode & 0xff)); | 1455 | sigexit(- (exitcode & 0xff)); |
@@ -2120,22 +2192,22 @@ static void debug_print_list(const char *prefix, o_string *o, int n) | |||
2120 | int i = 0; | 2192 | int i = 0; |
2121 | 2193 | ||
2122 | indent(); | 2194 | indent(); |
2123 | fprintf(stderr, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d glob:%d quoted:%d escape:%d\n", | 2195 | fdprintf(2, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d glob:%d quoted:%d escape:%d\n", |
2124 | prefix, list, n, string_start, o->length, o->maxlen, | 2196 | prefix, list, n, string_start, o->length, o->maxlen, |
2125 | !!(o->o_expflags & EXP_FLAG_GLOB), | 2197 | !!(o->o_expflags & EXP_FLAG_GLOB), |
2126 | o->has_quoted_part, | 2198 | o->has_quoted_part, |
2127 | !!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); | 2199 | !!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); |
2128 | while (i < n) { | 2200 | while (i < n) { |
2129 | indent(); | 2201 | indent(); |
2130 | fprintf(stderr, " list[%d]=%d '%s' %p\n", i, (int)list[i], | 2202 | fdprintf(2, " list[%d]=%d '%s' %p\n", i, (int)(uintptr_t)list[i], |
2131 | o->data + (int)list[i] + string_start, | 2203 | o->data + (int)(uintptr_t)list[i] + string_start, |
2132 | o->data + (int)list[i] + string_start); | 2204 | o->data + (int)(uintptr_t)list[i] + string_start); |
2133 | i++; | 2205 | i++; |
2134 | } | 2206 | } |
2135 | if (n) { | 2207 | if (n) { |
2136 | const char *p = o->data + (int)list[n - 1] + string_start; | 2208 | const char *p = o->data + (int)(uintptr_t)list[n - 1] + string_start; |
2137 | indent(); | 2209 | indent(); |
2138 | fprintf(stderr, " total_sz:%ld\n", (long)((p + strlen(p) + 1) - o->data)); | 2210 | fdprintf(2, " total_sz:%ld\n", (long)((p + strlen(p) + 1) - o->data)); |
2139 | } | 2211 | } |
2140 | } | 2212 | } |
2141 | #else | 2213 | #else |
@@ -2583,6 +2655,94 @@ static void free_pipe_list(struct pipe *pi) | |||
2583 | 2655 | ||
2584 | /*** Parsing routines ***/ | 2656 | /*** Parsing routines ***/ |
2585 | 2657 | ||
2658 | #ifndef debug_print_tree | ||
2659 | static void debug_print_tree(struct pipe *pi, int lvl) | ||
2660 | { | ||
2661 | static const char *const PIPE[] = { | ||
2662 | [PIPE_SEQ] = "SEQ", | ||
2663 | [PIPE_AND] = "AND", | ||
2664 | [PIPE_OR ] = "OR" , | ||
2665 | [PIPE_BG ] = "BG" , | ||
2666 | }; | ||
2667 | static const char *RES[] = { | ||
2668 | [RES_NONE ] = "NONE" , | ||
2669 | # if ENABLE_HUSH_IF | ||
2670 | [RES_IF ] = "IF" , | ||
2671 | [RES_THEN ] = "THEN" , | ||
2672 | [RES_ELIF ] = "ELIF" , | ||
2673 | [RES_ELSE ] = "ELSE" , | ||
2674 | [RES_FI ] = "FI" , | ||
2675 | # endif | ||
2676 | # if ENABLE_HUSH_LOOPS | ||
2677 | [RES_FOR ] = "FOR" , | ||
2678 | [RES_WHILE] = "WHILE", | ||
2679 | [RES_UNTIL] = "UNTIL", | ||
2680 | [RES_DO ] = "DO" , | ||
2681 | [RES_DONE ] = "DONE" , | ||
2682 | # endif | ||
2683 | # if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE | ||
2684 | [RES_IN ] = "IN" , | ||
2685 | # endif | ||
2686 | # if ENABLE_HUSH_CASE | ||
2687 | [RES_CASE ] = "CASE" , | ||
2688 | [RES_CASE_IN ] = "CASE_IN" , | ||
2689 | [RES_MATCH] = "MATCH", | ||
2690 | [RES_CASE_BODY] = "CASE_BODY", | ||
2691 | [RES_ESAC ] = "ESAC" , | ||
2692 | # endif | ||
2693 | [RES_XXXX ] = "XXXX" , | ||
2694 | [RES_SNTX ] = "SNTX" , | ||
2695 | }; | ||
2696 | static const char *const CMDTYPE[] = { | ||
2697 | "{}", | ||
2698 | "()", | ||
2699 | "[noglob]", | ||
2700 | # if ENABLE_HUSH_FUNCTIONS | ||
2701 | "func()", | ||
2702 | # endif | ||
2703 | }; | ||
2704 | |||
2705 | int pin, prn; | ||
2706 | |||
2707 | pin = 0; | ||
2708 | while (pi) { | ||
2709 | fdprintf(2, "%*spipe %d res_word=%s followup=%d %s\n", lvl*2, "", | ||
2710 | pin, RES[pi->res_word], pi->followup, PIPE[pi->followup]); | ||
2711 | prn = 0; | ||
2712 | while (prn < pi->num_cmds) { | ||
2713 | struct command *command = &pi->cmds[prn]; | ||
2714 | char **argv = command->argv; | ||
2715 | |||
2716 | fdprintf(2, "%*s cmd %d assignment_cnt:%d", | ||
2717 | lvl*2, "", prn, | ||
2718 | command->assignment_cnt); | ||
2719 | if (command->group) { | ||
2720 | fdprintf(2, " group %s: (argv=%p)%s%s\n", | ||
2721 | CMDTYPE[command->cmd_type], | ||
2722 | argv | ||
2723 | # if !BB_MMU | ||
2724 | , " group_as_string:", command->group_as_string | ||
2725 | # else | ||
2726 | , "", "" | ||
2727 | # endif | ||
2728 | ); | ||
2729 | debug_print_tree(command->group, lvl+1); | ||
2730 | prn++; | ||
2731 | continue; | ||
2732 | } | ||
2733 | if (argv) while (*argv) { | ||
2734 | fdprintf(2, " '%s'", *argv); | ||
2735 | argv++; | ||
2736 | } | ||
2737 | fdprintf(2, "\n"); | ||
2738 | prn++; | ||
2739 | } | ||
2740 | pi = pi->next; | ||
2741 | pin++; | ||
2742 | } | ||
2743 | } | ||
2744 | #endif /* debug_print_tree */ | ||
2745 | |||
2586 | static struct pipe *new_pipe(void) | 2746 | static struct pipe *new_pipe(void) |
2587 | { | 2747 | { |
2588 | struct pipe *pi; | 2748 | struct pipe *pi; |
@@ -3972,15 +4132,16 @@ static struct pipe *parse_stream(char **pstring, | |||
3972 | goto parse_error; | 4132 | goto parse_error; |
3973 | } | 4133 | } |
3974 | if (ch == '\n') { | 4134 | if (ch == '\n') { |
3975 | #if ENABLE_HUSH_CASE | 4135 | /* Is this a case when newline is simply ignored? |
3976 | /* "case ... in <newline> word) ..." - | 4136 | * Some examples: |
3977 | * newlines are ignored (but ';' wouldn't be) */ | 4137 | * "cmd | <newline> cmd ..." |
3978 | if (ctx.command->argv == NULL | 4138 | * "case ... in <newline> word) ..." |
3979 | && ctx.ctx_res_w == RES_MATCH | 4139 | */ |
4140 | if (IS_NULL_CMD(ctx.command) | ||
4141 | && dest.length == 0 && !dest.has_quoted_part | ||
3980 | ) { | 4142 | ) { |
3981 | continue; | 4143 | continue; |
3982 | } | 4144 | } |
3983 | #endif | ||
3984 | /* Treat newline as a command separator. */ | 4145 | /* Treat newline as a command separator. */ |
3985 | done_pipe(&ctx, PIPE_SEQ); | 4146 | done_pipe(&ctx, PIPE_SEQ); |
3986 | debug_printf_parse("heredoc_cnt:%d\n", heredoc_cnt); | 4147 | debug_printf_parse("heredoc_cnt:%d\n", heredoc_cnt); |
@@ -4112,6 +4273,31 @@ static struct pipe *parse_stream(char **pstring, | |||
4112 | if (parse_redirect(&ctx, redir_fd, redir_style, input)) | 4273 | if (parse_redirect(&ctx, redir_fd, redir_style, input)) |
4113 | goto parse_error; | 4274 | goto parse_error; |
4114 | continue; /* back to top of while (1) */ | 4275 | continue; /* back to top of while (1) */ |
4276 | case '#': | ||
4277 | if (dest.length == 0 && !dest.has_quoted_part) { | ||
4278 | /* skip "#comment" */ | ||
4279 | while (1) { | ||
4280 | ch = i_peek(input); | ||
4281 | if (ch == EOF || ch == '\n') | ||
4282 | break; | ||
4283 | i_getch(input); | ||
4284 | /* note: we do not add it to &ctx.as_string */ | ||
4285 | } | ||
4286 | nommu_addchr(&ctx.as_string, '\n'); | ||
4287 | continue; /* back to top of while (1) */ | ||
4288 | } | ||
4289 | break; | ||
4290 | case '\\': | ||
4291 | if (next == '\n') { | ||
4292 | /* It's "\<newline>" */ | ||
4293 | #if !BB_MMU | ||
4294 | /* Remove trailing '\' from ctx.as_string */ | ||
4295 | ctx.as_string.data[--ctx.as_string.length] = '\0'; | ||
4296 | #endif | ||
4297 | ch = i_getch(input); /* eat it */ | ||
4298 | continue; /* back to top of while (1) */ | ||
4299 | } | ||
4300 | break; | ||
4115 | } | 4301 | } |
4116 | 4302 | ||
4117 | if (dest.o_assignment == MAYBE_ASSIGNMENT | 4303 | if (dest.o_assignment == MAYBE_ASSIGNMENT |
@@ -4126,19 +4312,8 @@ static struct pipe *parse_stream(char **pstring, | |||
4126 | /* Note: nommu_addchr(&ctx.as_string, ch) is already done */ | 4312 | /* Note: nommu_addchr(&ctx.as_string, ch) is already done */ |
4127 | 4313 | ||
4128 | switch (ch) { | 4314 | switch (ch) { |
4129 | case '#': | 4315 | case '#': /* non-comment #: "echo a#b" etc */ |
4130 | if (dest.length == 0) { | 4316 | o_addQchr(&dest, ch); |
4131 | while (1) { | ||
4132 | ch = i_peek(input); | ||
4133 | if (ch == EOF || ch == '\n') | ||
4134 | break; | ||
4135 | i_getch(input); | ||
4136 | /* note: we do not add it to &ctx.as_string */ | ||
4137 | } | ||
4138 | nommu_addchr(&ctx.as_string, '\n'); | ||
4139 | } else { | ||
4140 | o_addQchr(&dest, ch); | ||
4141 | } | ||
4142 | break; | 4317 | break; |
4143 | case '\\': | 4318 | case '\\': |
4144 | if (next == EOF) { | 4319 | if (next == EOF) { |
@@ -4146,21 +4321,14 @@ static struct pipe *parse_stream(char **pstring, | |||
4146 | xfunc_die(); | 4321 | xfunc_die(); |
4147 | } | 4322 | } |
4148 | ch = i_getch(input); | 4323 | ch = i_getch(input); |
4149 | if (ch != '\n') { | 4324 | /* note: ch != '\n' (that case does not reach this place) */ |
4150 | o_addchr(&dest, '\\'); | 4325 | o_addchr(&dest, '\\'); |
4151 | /*nommu_addchr(&ctx.as_string, '\\'); - already done */ | 4326 | /*nommu_addchr(&ctx.as_string, '\\'); - already done */ |
4152 | o_addchr(&dest, ch); | 4327 | o_addchr(&dest, ch); |
4153 | nommu_addchr(&ctx.as_string, ch); | 4328 | nommu_addchr(&ctx.as_string, ch); |
4154 | /* Example: echo Hello \2>file | 4329 | /* Example: echo Hello \2>file |
4155 | * we need to know that word 2 is quoted */ | 4330 | * we need to know that word 2 is quoted */ |
4156 | dest.has_quoted_part = 1; | 4331 | dest.has_quoted_part = 1; |
4157 | } | ||
4158 | #if !BB_MMU | ||
4159 | else { | ||
4160 | /* It's "\<newline>". Remove trailing '\' from ctx.as_string */ | ||
4161 | ctx.as_string.data[--ctx.as_string.length] = '\0'; | ||
4162 | } | ||
4163 | #endif | ||
4164 | break; | 4332 | break; |
4165 | case '$': | 4333 | case '$': |
4166 | if (parse_dollar(&ctx.as_string, &dest, input, /*quote_mask:*/ 0) != 0) { | 4334 | if (parse_dollar(&ctx.as_string, &dest, input, /*quote_mask:*/ 0) != 0) { |
@@ -4366,7 +4534,9 @@ static struct pipe *parse_stream(char **pstring, | |||
4366 | expand_string_to_string(str) | 4534 | expand_string_to_string(str) |
4367 | #endif | 4535 | #endif |
4368 | static char *expand_string_to_string(const char *str, int do_unbackslash); | 4536 | static char *expand_string_to_string(const char *str, int do_unbackslash); |
4537 | #if ENABLE_HUSH_TICK | ||
4369 | static int process_command_subs(o_string *dest, const char *s); | 4538 | static int process_command_subs(o_string *dest, const char *s); |
4539 | #endif | ||
4370 | 4540 | ||
4371 | /* expand_strvec_to_strvec() takes a list of strings, expands | 4541 | /* expand_strvec_to_strvec() takes a list of strings, expands |
4372 | * all variable references within and returns a pointer to | 4542 | * all variable references within and returns a pointer to |
@@ -6309,48 +6479,57 @@ static int checkjobs(struct pipe *fg_pipe) | |||
6309 | #endif | 6479 | #endif |
6310 | /* Were we asked to wait for fg pipe? */ | 6480 | /* Were we asked to wait for fg pipe? */ |
6311 | if (fg_pipe) { | 6481 | if (fg_pipe) { |
6312 | for (i = 0; i < fg_pipe->num_cmds; i++) { | 6482 | i = fg_pipe->num_cmds; |
6483 | while (--i >= 0) { | ||
6313 | debug_printf_jobs("check pid %d\n", fg_pipe->cmds[i].pid); | 6484 | debug_printf_jobs("check pid %d\n", fg_pipe->cmds[i].pid); |
6314 | if (fg_pipe->cmds[i].pid != childpid) | 6485 | if (fg_pipe->cmds[i].pid != childpid) |
6315 | continue; | 6486 | continue; |
6316 | if (dead) { | 6487 | if (dead) { |
6488 | int ex; | ||
6317 | fg_pipe->cmds[i].pid = 0; | 6489 | fg_pipe->cmds[i].pid = 0; |
6318 | fg_pipe->alive_cmds--; | 6490 | fg_pipe->alive_cmds--; |
6319 | if (i == fg_pipe->num_cmds - 1) { | 6491 | ex = WEXITSTATUS(status); |
6320 | /* last process gives overall exitstatus */ | 6492 | /* bash prints killer signal's name for *last* |
6321 | rcode = WEXITSTATUS(status); | 6493 | * process in pipe (prints just newline for SIGINT). |
6322 | /* bash prints killer signal's name for *last* | 6494 | * Mimic this. Example: "sleep 5" + (^\ or kill -QUIT) |
6323 | * process in pipe (prints just newline for SIGINT). | 6495 | */ |
6324 | * Mimic this. Example: "sleep 5" + (^\ or kill -QUIT) | 6496 | if (WIFSIGNALED(status)) { |
6325 | */ | 6497 | int sig = WTERMSIG(status); |
6326 | if (WIFSIGNALED(status)) { | 6498 | if (i == fg_pipe->num_cmds-1) |
6327 | int sig = WTERMSIG(status); | ||
6328 | printf("%s\n", sig == SIGINT ? "" : get_signame(sig)); | 6499 | printf("%s\n", sig == SIGINT ? "" : get_signame(sig)); |
6329 | /* TODO: MIPS has 128 sigs (1..128), what if sig==128 here? | 6500 | /* TODO: MIPS has 128 sigs (1..128), what if sig==128 here? |
6330 | * Maybe we need to use sig | 128? */ | 6501 | * Maybe we need to use sig | 128? */ |
6331 | rcode = sig + 128; | 6502 | ex = sig + 128; |
6332 | } | ||
6333 | IF_HAS_KEYWORDS(if (fg_pipe->pi_inverted) rcode = !rcode;) | ||
6334 | } | 6503 | } |
6504 | fg_pipe->cmds[i].cmd_exitcode = ex; | ||
6335 | } else { | 6505 | } else { |
6336 | fg_pipe->cmds[i].is_stopped = 1; | 6506 | fg_pipe->cmds[i].is_stopped = 1; |
6337 | fg_pipe->stopped_cmds++; | 6507 | fg_pipe->stopped_cmds++; |
6338 | } | 6508 | } |
6339 | debug_printf_jobs("fg_pipe: alive_cmds %d stopped_cmds %d\n", | 6509 | debug_printf_jobs("fg_pipe: alive_cmds %d stopped_cmds %d\n", |
6340 | fg_pipe->alive_cmds, fg_pipe->stopped_cmds); | 6510 | fg_pipe->alive_cmds, fg_pipe->stopped_cmds); |
6341 | if (fg_pipe->alive_cmds - fg_pipe->stopped_cmds <= 0) { | 6511 | if (fg_pipe->alive_cmds == fg_pipe->stopped_cmds) { |
6342 | /* All processes in fg pipe have exited or stopped */ | 6512 | /* All processes in fg pipe have exited or stopped */ |
6513 | i = fg_pipe->num_cmds; | ||
6514 | while (--i >= 0) { | ||
6515 | rcode = fg_pipe->cmds[i].cmd_exitcode; | ||
6516 | /* usually last process gives overall exitstatus, | ||
6517 | * but with "set -o pipefail", last *failed* process does */ | ||
6518 | if (G.o_opt[OPT_O_PIPEFAIL] == 0 || rcode != 0) | ||
6519 | break; | ||
6520 | } | ||
6521 | IF_HAS_KEYWORDS(if (fg_pipe->pi_inverted) rcode = !rcode;) | ||
6343 | /* Note: *non-interactive* bash does not continue if all processes in fg pipe | 6522 | /* Note: *non-interactive* bash does not continue if all processes in fg pipe |
6344 | * are stopped. Testcase: "cat | cat" in a script (not on command line!) | 6523 | * are stopped. Testcase: "cat | cat" in a script (not on command line!) |
6345 | * and "killall -STOP cat" */ | 6524 | * and "killall -STOP cat" */ |
6346 | if (G_interactive_fd) { | 6525 | if (G_interactive_fd) { |
6347 | #if ENABLE_HUSH_JOB | 6526 | #if ENABLE_HUSH_JOB |
6348 | if (fg_pipe->alive_cmds) | 6527 | if (fg_pipe->alive_cmds != 0) |
6349 | insert_bg_job(fg_pipe); | 6528 | insert_bg_job(fg_pipe); |
6350 | #endif | 6529 | #endif |
6351 | return rcode; | 6530 | return rcode; |
6352 | } | 6531 | } |
6353 | if (!fg_pipe->alive_cmds) | 6532 | if (fg_pipe->alive_cmds == 0) |
6354 | return rcode; | 6533 | return rcode; |
6355 | } | 6534 | } |
6356 | /* There are still running processes in the fg pipe */ | 6535 | /* There are still running processes in the fg pipe */ |
@@ -6436,7 +6615,7 @@ static int checkjobs_and_fg_shell(struct pipe *fg_pipe) | |||
6436 | * subshell: ( list ) [&] | 6615 | * subshell: ( list ) [&] |
6437 | */ | 6616 | */ |
6438 | #if !ENABLE_HUSH_MODE_X | 6617 | #if !ENABLE_HUSH_MODE_X |
6439 | #define redirect_and_varexp_helper(new_env_p, old_vars_p, command, squirrel, char argv_expanded) \ | 6618 | #define redirect_and_varexp_helper(new_env_p, old_vars_p, command, squirrel, argv_expanded) \ |
6440 | redirect_and_varexp_helper(new_env_p, old_vars_p, command, squirrel) | 6619 | redirect_and_varexp_helper(new_env_p, old_vars_p, command, squirrel) |
6441 | #endif | 6620 | #endif |
6442 | static int redirect_and_varexp_helper(char ***new_env_p, | 6621 | static int redirect_and_varexp_helper(char ***new_env_p, |
@@ -6821,94 +7000,6 @@ static NOINLINE int run_pipe(struct pipe *pi) | |||
6821 | return -1; | 7000 | return -1; |
6822 | } | 7001 | } |
6823 | 7002 | ||
6824 | #ifndef debug_print_tree | ||
6825 | static void debug_print_tree(struct pipe *pi, int lvl) | ||
6826 | { | ||
6827 | static const char *const PIPE[] = { | ||
6828 | [PIPE_SEQ] = "SEQ", | ||
6829 | [PIPE_AND] = "AND", | ||
6830 | [PIPE_OR ] = "OR" , | ||
6831 | [PIPE_BG ] = "BG" , | ||
6832 | }; | ||
6833 | static const char *RES[] = { | ||
6834 | [RES_NONE ] = "NONE" , | ||
6835 | # if ENABLE_HUSH_IF | ||
6836 | [RES_IF ] = "IF" , | ||
6837 | [RES_THEN ] = "THEN" , | ||
6838 | [RES_ELIF ] = "ELIF" , | ||
6839 | [RES_ELSE ] = "ELSE" , | ||
6840 | [RES_FI ] = "FI" , | ||
6841 | # endif | ||
6842 | # if ENABLE_HUSH_LOOPS | ||
6843 | [RES_FOR ] = "FOR" , | ||
6844 | [RES_WHILE] = "WHILE", | ||
6845 | [RES_UNTIL] = "UNTIL", | ||
6846 | [RES_DO ] = "DO" , | ||
6847 | [RES_DONE ] = "DONE" , | ||
6848 | # endif | ||
6849 | # if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE | ||
6850 | [RES_IN ] = "IN" , | ||
6851 | # endif | ||
6852 | # if ENABLE_HUSH_CASE | ||
6853 | [RES_CASE ] = "CASE" , | ||
6854 | [RES_CASE_IN ] = "CASE_IN" , | ||
6855 | [RES_MATCH] = "MATCH", | ||
6856 | [RES_CASE_BODY] = "CASE_BODY", | ||
6857 | [RES_ESAC ] = "ESAC" , | ||
6858 | # endif | ||
6859 | [RES_XXXX ] = "XXXX" , | ||
6860 | [RES_SNTX ] = "SNTX" , | ||
6861 | }; | ||
6862 | static const char *const CMDTYPE[] = { | ||
6863 | "{}", | ||
6864 | "()", | ||
6865 | "[noglob]", | ||
6866 | # if ENABLE_HUSH_FUNCTIONS | ||
6867 | "func()", | ||
6868 | # endif | ||
6869 | }; | ||
6870 | |||
6871 | int pin, prn; | ||
6872 | |||
6873 | pin = 0; | ||
6874 | while (pi) { | ||
6875 | fprintf(stderr, "%*spipe %d res_word=%s followup=%d %s\n", lvl*2, "", | ||
6876 | pin, RES[pi->res_word], pi->followup, PIPE[pi->followup]); | ||
6877 | prn = 0; | ||
6878 | while (prn < pi->num_cmds) { | ||
6879 | struct command *command = &pi->cmds[prn]; | ||
6880 | char **argv = command->argv; | ||
6881 | |||
6882 | fprintf(stderr, "%*s cmd %d assignment_cnt:%d", | ||
6883 | lvl*2, "", prn, | ||
6884 | command->assignment_cnt); | ||
6885 | if (command->group) { | ||
6886 | fprintf(stderr, " group %s: (argv=%p)%s%s\n", | ||
6887 | CMDTYPE[command->cmd_type], | ||
6888 | argv | ||
6889 | # if !BB_MMU | ||
6890 | , " group_as_string:", command->group_as_string | ||
6891 | # else | ||
6892 | , "", "" | ||
6893 | # endif | ||
6894 | ); | ||
6895 | debug_print_tree(command->group, lvl+1); | ||
6896 | prn++; | ||
6897 | continue; | ||
6898 | } | ||
6899 | if (argv) while (*argv) { | ||
6900 | fprintf(stderr, " '%s'", *argv); | ||
6901 | argv++; | ||
6902 | } | ||
6903 | fprintf(stderr, "\n"); | ||
6904 | prn++; | ||
6905 | } | ||
6906 | pi = pi->next; | ||
6907 | pin++; | ||
6908 | } | ||
6909 | } | ||
6910 | #endif /* debug_print_tree */ | ||
6911 | |||
6912 | /* NB: called by pseudo_exec, and therefore must not modify any | 7003 | /* NB: called by pseudo_exec, and therefore must not modify any |
6913 | * global data until exec/_exit (we can be a child after vfork!) */ | 7004 | * global data until exec/_exit (we can be a child after vfork!) */ |
6914 | static int run_list(struct pipe *pi) | 7005 | static int run_list(struct pipe *pi) |
@@ -6938,27 +7029,30 @@ static int run_list(struct pipe *pi) | |||
6938 | 7029 | ||
6939 | #if ENABLE_HUSH_LOOPS | 7030 | #if ENABLE_HUSH_LOOPS |
6940 | /* Check syntax for "for" */ | 7031 | /* Check syntax for "for" */ |
6941 | for (struct pipe *cpipe = pi; cpipe; cpipe = cpipe->next) { | 7032 | { |
6942 | if (cpipe->res_word != RES_FOR && cpipe->res_word != RES_IN) | 7033 | struct pipe *cpipe; |
6943 | continue; | 7034 | for (cpipe = pi; cpipe; cpipe = cpipe->next) { |
6944 | /* current word is FOR or IN (BOLD in comments below) */ | 7035 | if (cpipe->res_word != RES_FOR && cpipe->res_word != RES_IN) |
6945 | if (cpipe->next == NULL) { | 7036 | continue; |
6946 | syntax_error("malformed for"); | 7037 | /* current word is FOR or IN (BOLD in comments below) */ |
6947 | debug_leave(); | 7038 | if (cpipe->next == NULL) { |
6948 | debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level); | 7039 | syntax_error("malformed for"); |
6949 | return 1; | 7040 | debug_leave(); |
6950 | } | 7041 | debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level); |
6951 | /* "FOR v; do ..." and "for v IN a b; do..." are ok */ | 7042 | return 1; |
6952 | if (cpipe->next->res_word == RES_DO) | 7043 | } |
6953 | continue; | 7044 | /* "FOR v; do ..." and "for v IN a b; do..." are ok */ |
6954 | /* next word is not "do". It must be "in" then ("FOR v in ...") */ | 7045 | if (cpipe->next->res_word == RES_DO) |
6955 | if (cpipe->res_word == RES_IN /* "for v IN a b; not_do..."? */ | 7046 | continue; |
6956 | || cpipe->next->res_word != RES_IN /* FOR v not_do_and_not_in..."? */ | 7047 | /* next word is not "do". It must be "in" then ("FOR v in ...") */ |
6957 | ) { | 7048 | if (cpipe->res_word == RES_IN /* "for v IN a b; not_do..."? */ |
6958 | syntax_error("malformed for"); | 7049 | || cpipe->next->res_word != RES_IN /* FOR v not_do_and_not_in..."? */ |
6959 | debug_leave(); | 7050 | ) { |
6960 | debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level); | 7051 | syntax_error("malformed for"); |
6961 | return 1; | 7052 | debug_leave(); |
7053 | debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level); | ||
7054 | return 1; | ||
7055 | } | ||
6962 | } | 7056 | } |
6963 | } | 7057 | } |
6964 | #endif | 7058 | #endif |
@@ -7241,7 +7335,7 @@ static int run_and_free_list(struct pipe *pi) | |||
7241 | { | 7335 | { |
7242 | int rcode = 0; | 7336 | int rcode = 0; |
7243 | debug_printf_exec("run_and_free_list entered\n"); | 7337 | debug_printf_exec("run_and_free_list entered\n"); |
7244 | if (!G.n_mode) { | 7338 | if (!G.o_opt[OPT_O_NOEXEC]) { |
7245 | debug_printf_exec(": run_list: 1st pipe with %d cmds\n", pi->num_cmds); | 7339 | debug_printf_exec(": run_list: 1st pipe with %d cmds\n", pi->num_cmds); |
7246 | rcode = run_list(pi); | 7340 | rcode = run_list(pi); |
7247 | } | 7341 | } |
@@ -7339,13 +7433,41 @@ static void set_fatal_handlers(void) | |||
7339 | } | 7433 | } |
7340 | #endif | 7434 | #endif |
7341 | 7435 | ||
7342 | static int set_mode(const char cstate, const char mode) | 7436 | static int set_mode(int state, char mode, const char *o_opt) |
7343 | { | 7437 | { |
7344 | int state = (cstate == '-' ? 1 : 0); | 7438 | int idx; |
7345 | switch (mode) { | 7439 | switch (mode) { |
7346 | case 'n': G.n_mode = state; break; | 7440 | case 'n': |
7347 | case 'x': IF_HUSH_MODE_X(G_x_mode = state;) break; | 7441 | G.o_opt[OPT_O_NOEXEC] = state; |
7348 | default: return EXIT_FAILURE; | 7442 | break; |
7443 | case 'x': | ||
7444 | IF_HUSH_MODE_X(G_x_mode = state;) | ||
7445 | break; | ||
7446 | case 'o': | ||
7447 | if (!o_opt) { | ||
7448 | /* "set -+o" without parameter. | ||
7449 | * in bash, set -o produces this output: | ||
7450 | * pipefail off | ||
7451 | * and set +o: | ||
7452 | * set +o pipefail | ||
7453 | * We always use the second form. | ||
7454 | */ | ||
7455 | const char *p = o_opt_strings; | ||
7456 | idx = 0; | ||
7457 | while (*p) { | ||
7458 | printf("set %co %s\n", (G.o_opt[idx] ? '-' : '+'), p); | ||
7459 | idx++; | ||
7460 | p += strlen(p) + 1; | ||
7461 | } | ||
7462 | break; | ||
7463 | } | ||
7464 | idx = index_in_strings(o_opt_strings, o_opt); | ||
7465 | if (idx >= 0) { | ||
7466 | G.o_opt[idx] = state; | ||
7467 | break; | ||
7468 | } | ||
7469 | default: | ||
7470 | return EXIT_FAILURE; | ||
7349 | } | 7471 | } |
7350 | return EXIT_SUCCESS; | 7472 | return EXIT_SUCCESS; |
7351 | } | 7473 | } |
@@ -7357,7 +7479,7 @@ int hush_main(int argc, char **argv) | |||
7357 | unsigned builtin_argc; | 7479 | unsigned builtin_argc; |
7358 | char **e; | 7480 | char **e; |
7359 | struct variable *cur_var; | 7481 | struct variable *cur_var; |
7360 | struct variable shell_ver; | 7482 | struct variable *shell_ver; |
7361 | 7483 | ||
7362 | INIT_G(); | 7484 | INIT_G(); |
7363 | if (EXIT_SUCCESS) /* if EXIT_SUCCESS == 0, it is already done */ | 7485 | if (EXIT_SUCCESS) /* if EXIT_SUCCESS == 0, it is already done */ |
@@ -7366,17 +7488,17 @@ int hush_main(int argc, char **argv) | |||
7366 | G.argv0_for_re_execing = argv[0]; | 7488 | G.argv0_for_re_execing = argv[0]; |
7367 | #endif | 7489 | #endif |
7368 | /* Deal with HUSH_VERSION */ | 7490 | /* Deal with HUSH_VERSION */ |
7369 | memset(&shell_ver, 0, sizeof(shell_ver)); | 7491 | shell_ver = xzalloc(sizeof(*shell_ver)); |
7370 | shell_ver.flg_export = 1; | 7492 | shell_ver->flg_export = 1; |
7371 | shell_ver.flg_read_only = 1; | 7493 | shell_ver->flg_read_only = 1; |
7372 | /* Code which handles ${var<op>...} needs writable values for all variables, | 7494 | /* Code which handles ${var<op>...} needs writable values for all variables, |
7373 | * therefore we xstrdup: */ | 7495 | * therefore we xstrdup: */ |
7374 | shell_ver.varstr = xstrdup(hush_version_str), | 7496 | shell_ver->varstr = xstrdup(hush_version_str); |
7375 | G.top_var = &shell_ver; | ||
7376 | /* Create shell local variables from the values | 7497 | /* Create shell local variables from the values |
7377 | * currently living in the environment */ | 7498 | * currently living in the environment */ |
7378 | debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); | 7499 | debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); |
7379 | unsetenv("HUSH_VERSION"); /* in case it exists in initial env */ | 7500 | unsetenv("HUSH_VERSION"); /* in case it exists in initial env */ |
7501 | G.top_var = shell_ver; | ||
7380 | cur_var = G.top_var; | 7502 | cur_var = G.top_var; |
7381 | e = environ; | 7503 | e = environ; |
7382 | if (e) while (*e) { | 7504 | if (e) while (*e) { |
@@ -7391,8 +7513,8 @@ int hush_main(int argc, char **argv) | |||
7391 | e++; | 7513 | e++; |
7392 | } | 7514 | } |
7393 | /* (Re)insert HUSH_VERSION into env (AFTER we scanned the env!) */ | 7515 | /* (Re)insert HUSH_VERSION into env (AFTER we scanned the env!) */ |
7394 | debug_printf_env("putenv '%s'\n", shell_ver.varstr); | 7516 | debug_printf_env("putenv '%s'\n", shell_ver->varstr); |
7395 | putenv(shell_ver.varstr); | 7517 | putenv(shell_ver->varstr); |
7396 | 7518 | ||
7397 | /* Export PWD */ | 7519 | /* Export PWD */ |
7398 | set_pwd_var(/*exp:*/ 1); | 7520 | set_pwd_var(/*exp:*/ 1); |
@@ -7585,7 +7707,7 @@ int hush_main(int argc, char **argv) | |||
7585 | #endif | 7707 | #endif |
7586 | case 'n': | 7708 | case 'n': |
7587 | case 'x': | 7709 | case 'x': |
7588 | if (set_mode('-', opt) == 0) /* no error */ | 7710 | if (set_mode(1, opt, NULL) == 0) /* no error */ |
7589 | break; | 7711 | break; |
7590 | default: | 7712 | default: |
7591 | #ifndef BB_VER | 7713 | #ifndef BB_VER |
@@ -7752,18 +7874,6 @@ int hush_main(int argc, char **argv) | |||
7752 | parse_and_run_file(stdin); | 7874 | parse_and_run_file(stdin); |
7753 | 7875 | ||
7754 | final_return: | 7876 | final_return: |
7755 | #if ENABLE_FEATURE_CLEAN_UP | ||
7756 | if (G.cwd != bb_msg_unknown) | ||
7757 | free((char*)G.cwd); | ||
7758 | cur_var = G.top_var->next; | ||
7759 | while (cur_var) { | ||
7760 | struct variable *tmp = cur_var; | ||
7761 | if (!cur_var->max_len) | ||
7762 | free(cur_var->varstr); | ||
7763 | cur_var = cur_var->next; | ||
7764 | free(tmp); | ||
7765 | } | ||
7766 | #endif | ||
7767 | hush_exit(G.last_exitcode); | 7877 | hush_exit(G.last_exitcode); |
7768 | } | 7878 | } |
7769 | 7879 | ||
@@ -8375,15 +8485,18 @@ static int FAST_FUNC builtin_set(char **argv) | |||
8375 | } | 8485 | } |
8376 | 8486 | ||
8377 | do { | 8487 | do { |
8378 | if (!strcmp(arg, "--")) { | 8488 | if (strcmp(arg, "--") == 0) { |
8379 | ++argv; | 8489 | ++argv; |
8380 | goto set_argv; | 8490 | goto set_argv; |
8381 | } | 8491 | } |
8382 | if (arg[0] != '+' && arg[0] != '-') | 8492 | if (arg[0] != '+' && arg[0] != '-') |
8383 | break; | 8493 | break; |
8384 | for (n = 1; arg[n]; ++n) | 8494 | for (n = 1; arg[n]; ++n) { |
8385 | if (set_mode(arg[0], arg[n])) | 8495 | if (set_mode((arg[0] == '-'), arg[n], argv[1])) |
8386 | goto error; | 8496 | goto error; |
8497 | if (arg[n] == 'o' && argv[1]) | ||
8498 | argv++; | ||
8499 | } | ||
8387 | } while ((arg = *++argv) != NULL); | 8500 | } while ((arg = *++argv) != NULL); |
8388 | /* Now argv[0] is 1st argument */ | 8501 | /* Now argv[0] is 1st argument */ |
8389 | 8502 | ||
diff --git a/shell/hush_test/hush-misc/assignment3.right b/shell/hush_test/hush-misc/assignment3.right new file mode 100644 index 000000000..0f02d7cbc --- /dev/null +++ b/shell/hush_test/hush-misc/assignment3.right | |||
@@ -0,0 +1,2 @@ | |||
1 | Done:0 | ||
2 | abc=123 | ||
diff --git a/shell/hush_test/hush-misc/assignment3.tests b/shell/hush_test/hush-misc/assignment3.tests new file mode 100755 index 000000000..790129be1 --- /dev/null +++ b/shell/hush_test/hush-misc/assignment3.tests | |||
@@ -0,0 +1,5 @@ | |||
1 | # This must be interpreted as assignments | ||
2 | a=1 b\ | ||
3 | =2 c=3 | ||
4 | echo Done:$? | ||
5 | echo abc=$a$b$c | ||
diff --git a/shell/hush_test/hush-misc/pipefail.right b/shell/hush_test/hush-misc/pipefail.right new file mode 100644 index 000000000..5845d8939 --- /dev/null +++ b/shell/hush_test/hush-misc/pipefail.right | |||
@@ -0,0 +1,40 @@ | |||
1 | Default: | ||
2 | true | true: | ||
3 | 0 | ||
4 | 1 | ||
5 | true | false: | ||
6 | 1 | ||
7 | 0 | ||
8 | false | true: | ||
9 | 0 | ||
10 | 1 | ||
11 | exit 2 | exit 3 | exit 4: | ||
12 | 4 | ||
13 | 0 | ||
14 | Pipefail on: | ||
15 | true | true: | ||
16 | 0 | ||
17 | 1 | ||
18 | true | false: | ||
19 | 1 | ||
20 | 0 | ||
21 | false | true: | ||
22 | 1 | ||
23 | 0 | ||
24 | exit 2 | exit 3 | exit 4: | ||
25 | 4 | ||
26 | 0 | ||
27 | Pipefail off: | ||
28 | true | true: | ||
29 | 0 | ||
30 | 1 | ||
31 | true | false: | ||
32 | 1 | ||
33 | 0 | ||
34 | false | true: | ||
35 | 0 | ||
36 | 1 | ||
37 | exit 2 | exit 3 | exit 4: | ||
38 | 4 | ||
39 | 0 | ||
40 | Done | ||
diff --git a/shell/hush_test/hush-misc/pipefail.tests b/shell/hush_test/hush-misc/pipefail.tests new file mode 100755 index 000000000..9df841861 --- /dev/null +++ b/shell/hush_test/hush-misc/pipefail.tests | |||
@@ -0,0 +1,45 @@ | |||
1 | echo Default: | ||
2 | echo "true | true:" | ||
3 | true | true; echo $? | ||
4 | ! true | true; echo $? | ||
5 | echo "true | false:" | ||
6 | true | false; echo $? | ||
7 | ! true | false; echo $? | ||
8 | echo "false | true:" | ||
9 | false | true; echo $? | ||
10 | ! false | true; echo $? | ||
11 | echo "exit 2 | exit 3 | exit 4:" | ||
12 | exit 2 | exit 3 | exit 4; echo $? | ||
13 | ! exit 2 | exit 3 | exit 4; echo $? | ||
14 | |||
15 | echo Pipefail on: | ||
16 | set -o pipefail | ||
17 | echo "true | true:" | ||
18 | true | true; echo $? | ||
19 | ! true | true; echo $? | ||
20 | echo "true | false:" | ||
21 | true | false; echo $? | ||
22 | ! true | false; echo $? | ||
23 | echo "false | true:" | ||
24 | false | true; echo $? | ||
25 | ! false | true; echo $? | ||
26 | echo "exit 2 | exit 3 | exit 4:" | ||
27 | exit 2 | exit 3 | exit 4; echo $? | ||
28 | ! exit 2 | exit 3 | exit 4; echo $? | ||
29 | |||
30 | echo Pipefail off: | ||
31 | set +o pipefail | ||
32 | echo "true | true:" | ||
33 | true | true; echo $? | ||
34 | ! true | true; echo $? | ||
35 | echo "true | false:" | ||
36 | true | false; echo $? | ||
37 | ! true | false; echo $? | ||
38 | echo "false | true:" | ||
39 | false | true; echo $? | ||
40 | ! false | true; echo $? | ||
41 | echo "exit 2 | exit 3 | exit 4:" | ||
42 | exit 2 | exit 3 | exit 4; echo $? | ||
43 | ! exit 2 | exit 3 | exit 4; echo $? | ||
44 | |||
45 | echo Done | ||
diff --git a/shell/hush_test/hush-parsing/comment1.right b/shell/hush_test/hush-parsing/comment1.right new file mode 100644 index 000000000..a102b1d4e --- /dev/null +++ b/shell/hush_test/hush-parsing/comment1.right | |||
@@ -0,0 +1,2 @@ | |||
1 | Nothing: | ||
2 | String: #should-be-echoed | ||
diff --git a/shell/hush_test/hush-parsing/comment1.tests b/shell/hush_test/hush-parsing/comment1.tests new file mode 100755 index 000000000..d268860ff --- /dev/null +++ b/shell/hush_test/hush-parsing/comment1.tests | |||
@@ -0,0 +1,2 @@ | |||
1 | echo Nothing: #should-not-be-echoed | ||
2 | echo String: ""#should-be-echoed | ||
diff --git a/shell/hush_test/hush-parsing/eol1.right b/shell/hush_test/hush-parsing/eol1.right new file mode 100644 index 000000000..31c896f62 --- /dev/null +++ b/shell/hush_test/hush-parsing/eol1.right | |||
@@ -0,0 +1 @@ | |||
Done:0 | |||
diff --git a/shell/hush_test/hush-parsing/eol1.tests b/shell/hush_test/hush-parsing/eol1.tests new file mode 100755 index 000000000..f1b55e8b8 --- /dev/null +++ b/shell/hush_test/hush-parsing/eol1.tests | |||
@@ -0,0 +1,18 @@ | |||
1 | # bug was that we treated <newline> as ';' in this line: | ||
2 | true || echo foo | | ||
3 | echo BAD1 | cat | ||
4 | |||
5 | # variation on the same theme | ||
6 | true || echo foo | | ||
7 | # comment | ||
8 | echo BAD2 | cat | ||
9 | |||
10 | # variation on the same theme | ||
11 | true || echo foo | | ||
12 | |||
13 | echo BAD3 | cat | ||
14 | |||
15 | # this should error out, but currently works in hush: | ||
16 | #true || echo foo |; | ||
17 | |||
18 | echo Done:$? | ||
diff --git a/testsuite/bunzip2.tests b/testsuite/bunzip2.tests index 827aee867..fcfce1a31 100755 --- a/testsuite/bunzip2.tests +++ b/testsuite/bunzip2.tests | |||
@@ -463,6 +463,24 @@ $ECHO -ne "\x40\xa0\x00\x8b\x12\xe8\xfb\xb7\x27\xaa\xd3\x36\x0c\xfc\xe1\x40" | |||
463 | $ECHO -ne "\x01\xff\x8b\xb9\x22\x9c\x28\x48\x5f\xa5\xca\xf3\x80" | 463 | $ECHO -ne "\x01\xff\x8b\xb9\x22\x9c\x28\x48\x5f\xa5\xca\xf3\x80" |
464 | } | 464 | } |
465 | 465 | ||
466 | pbzip_4m_zeros() { | ||
467 | $ECHO -ne "\x42\x5a\x68\x31\x31\x41\x59\x26\x53\x59\x63\xe3\xec\xa2\x00\x06" | ||
468 | $ECHO -ne "\xe4\xc1\x00\xc0\x00\x02\x00\x00\x08\x20\x00\x30\xcc\x09\xaa\x69" | ||
469 | $ECHO -ne "\x94\xa1\x36\xa9\x28\x4f\x17\x72\x45\x38\x50\x90\x63\xe3\xec\xa2" | ||
470 | $ECHO -ne "\x42\x5a\x68\x31\x31\x41\x59\x26\x53\x59\x63\xe3\xec\xa2\x00\x06" | ||
471 | $ECHO -ne "\xe4\xc1\x00\xc0\x00\x02\x00\x00\x08\x20\x00\x30\xcc\x09\xaa\x69" | ||
472 | $ECHO -ne "\x94\xa1\x36\xa9\x28\x4f\x17\x72\x45\x38\x50\x90\x63\xe3\xec\xa2" | ||
473 | $ECHO -ne "\x42\x5a\x68\x31\x31\x41\x59\x26\x53\x59\x63\xe3\xec\xa2\x00\x06" | ||
474 | $ECHO -ne "\xe4\xc1\x00\xc0\x00\x02\x00\x00\x08\x20\x00\x30\xcc\x09\xaa\x69" | ||
475 | $ECHO -ne "\x94\xa1\x36\xa9\x28\x4f\x17\x72\x45\x38\x50\x90\x63\xe3\xec\xa2" | ||
476 | $ECHO -ne "\x42\x5a\x68\x31\x31\x41\x59\x26\x53\x59\x63\xe3\xec\xa2\x00\x06" | ||
477 | $ECHO -ne "\xe4\xc1\x00\xc0\x00\x02\x00\x00\x08\x20\x00\x30\xcc\x09\xaa\x69" | ||
478 | $ECHO -ne "\x94\xa1\x36\xa9\x28\x4f\x17\x72\x45\x38\x50\x90\x63\xe3\xec\xa2" | ||
479 | $ECHO -ne "\x42\x5a\x68\x31\x31\x41\x59\x26\x53\x59\xc9\xb5\x21\xef\x00\x04" | ||
480 | $ECHO -ne "\x8d\x40\x20\xc0\x00\x01\x00\x00\x08\x20\x00\x30\xcc\x05\x29\xa6" | ||
481 | $ECHO -ne "\x4a\x11\xb1\x4a\x11\xe2\xee\x48\xa7\x0a\x12\x19\x36\xa4\x3d\xe0" | ||
482 | } | ||
483 | |||
466 | prep() { | 484 | prep() { |
467 | rm -f t* | 485 | rm -f t* |
468 | hello_$ext >t1.$ext | 486 | hello_$ext >t1.$ext |
@@ -520,9 +538,18 @@ if test "${0##*/}" = "bunzip2.tests"; then | |||
520 | if test1_bz2 | ${bb}bunzip2 >/dev/null \ | 538 | if test1_bz2 | ${bb}bunzip2 >/dev/null \ |
521 | && test "`test1_bz2 | ${bb}bunzip2 | md5sum`" = "61bbeee4be9c6f110a71447f584fda7b -" | 539 | && test "`test1_bz2 | ${bb}bunzip2 | md5sum`" = "61bbeee4be9c6f110a71447f584fda7b -" |
522 | then | 540 | then |
523 | echo "PASS: $unpack: test bz2 file" | 541 | echo "PASS: $unpack: test_bz2 file" |
542 | else | ||
543 | echo "FAIL: $unpack: test_bz2 file" | ||
544 | FAILCOUNT=$((FAILCOUNT + 1)) | ||
545 | fi | ||
546 | |||
547 | if pbzip_4m_zeros | ${bb}bunzip2 >/dev/null \ | ||
548 | && test "`pbzip_4m_zeros | ${bb}bunzip2 | md5sum`" = "b5cfa9d6c8febd618f91ac2843d50a1c -" | ||
549 | then | ||
550 | echo "PASS: $unpack: pbzip_4m_zeros file" | ||
524 | else | 551 | else |
525 | echo "FAIL: $unpack: test bz2 file" | 552 | echo "FAIL: $unpack: pbzip_4m_zeros file" |
526 | FAILCOUNT=$((FAILCOUNT + 1)) | 553 | FAILCOUNT=$((FAILCOUNT + 1)) |
527 | fi | 554 | fi |
528 | fi | 555 | fi |
diff --git a/testsuite/date/date-@-works b/testsuite/date/date-@-works new file mode 100644 index 000000000..03b4c7f03 --- /dev/null +++ b/testsuite/date/date-@-works | |||
@@ -0,0 +1,13 @@ | |||
1 | # Tests for time_t value (unix time format) | ||
2 | |||
3 | # Just before DST switched off | ||
4 | test x"Sun Oct 31 03:59:59 EEST 2010" = x"`TZ=EET-2EEST,M3.5.0/3,M10.5.0/4 busybox date -d @1288486799`" | ||
5 | |||
6 | # Just after DST switched off | ||
7 | test x"Sun Oct 31 03:00:01 EET 2010" = x"`TZ=EET-2EEST,M3.5.0/3,M10.5.0/4 busybox date -d @1288486801`" | ||
8 | |||
9 | # Just before DST switched on | ||
10 | test x"Sun Mar 28 02:59:59 EET 2010" = x"`TZ=EET-2EEST,M3.5.0/3,M10.5.0/4 busybox date -d @1269737999`" | ||
11 | |||
12 | # Just after DST switched on | ||
13 | test x"Sun Mar 28 04:00:01 EEST 2010" = x"`TZ=EET-2EEST,M3.5.0/3,M10.5.0/4 busybox date -d @1269738001`" | ||
diff --git a/testsuite/du/du-h-works b/testsuite/du/du-h-works index c18433c29..1c77b6552 100644 --- a/testsuite/du/du-h-works +++ b/testsuite/du/du-h-works | |||
@@ -1,4 +1,4 @@ | |||
1 | # FEATURE: CONFIG_FEATURE_HUMAN_READABLE | 1 | # FEATURE: CONFIG_FEATURE_HUMAN_READABLE |
2 | 2 | ||
3 | dd if=/dev/zero of=file bs=1M count=1 2>/dev/null | 3 | dd if=/dev/zero of=file bs=1M count=1 2>/dev/null |
4 | test x"`busybox du -h .`" = x"1.0M ." | 4 | test x"`busybox du -h file`" = x"1.0M file" |
diff --git a/testsuite/md5sum.tests b/testsuite/md5sum.tests index 35ec67cb4..1068b083f 100755 --- a/testsuite/md5sum.tests +++ b/testsuite/md5sum.tests | |||
@@ -18,6 +18,11 @@ fi | |||
18 | sum="$1" | 18 | sum="$1" |
19 | expected="$2" | 19 | expected="$2" |
20 | 20 | ||
21 | test -f "$bindir/.config" && . "$bindir/.config" | ||
22 | |||
23 | test x"$CONFIG_FEATURE_FANCY_HEAD" != x"y" \ | ||
24 | && { echo "SKIPPED: $sum"; exit 0; } | ||
25 | |||
21 | text="The quick brown fox jumps over the lazy dog" | 26 | text="The quick brown fox jumps over the lazy dog" |
22 | text=`yes "$text" | head -c 9999` | 27 | text=`yes "$text" | head -c 9999` |
23 | 28 | ||
diff --git a/testsuite/patch.tests b/testsuite/patch.tests index e482304f6..c604b9c1d 100755 --- a/testsuite/patch.tests +++ b/testsuite/patch.tests | |||
@@ -75,7 +75,7 @@ zxc | |||
75 | testing "patch detects already applied hunk" \ | 75 | testing "patch detects already applied hunk" \ |
76 | 'patch 2>&1; echo $?; cat input' \ | 76 | 'patch 2>&1; echo $?; cat input' \ |
77 | "\ | 77 | "\ |
78 | Possibly reversed hunk 1 at 2 | 78 | Possibly reversed hunk 1 at 4 |
79 | Hunk 1 FAILED 1/1. | 79 | Hunk 1 FAILED 1/1. |
80 | abc | 80 | abc |
81 | +def | 81 | +def |
@@ -103,7 +103,7 @@ def | |||
103 | testing "patch detects already applied hunk at the EOF" \ | 103 | testing "patch detects already applied hunk at the EOF" \ |
104 | 'patch 2>&1; echo $?; cat input' \ | 104 | 'patch 2>&1; echo $?; cat input' \ |
105 | "\ | 105 | "\ |
106 | Possibly reversed hunk 1 at 3 | 106 | Possibly reversed hunk 1 at 4 |
107 | Hunk 1 FAILED 1/1. | 107 | Hunk 1 FAILED 1/1. |
108 | abc | 108 | abc |
109 | 123 | 109 | 123 |
@@ -175,6 +175,43 @@ abc | |||
175 | 123 | 175 | 123 |
176 | " \ | 176 | " \ |
177 | 177 | ||
178 | # testing "test name" "command(s)" "expected result" "file input" "stdin" | ||
179 | testing "patch at the beginning" \ | ||
180 | 'patch 2>&1; cat input' \ | ||
181 | "\ | ||
182 | patching file input | ||
183 | 111changed | ||
184 | 444 | ||
185 | 555 | ||
186 | 666 | ||
187 | 777 | ||
188 | 888 | ||
189 | 999 | ||
190 | " \ | ||
191 | "\ | ||
192 | 111 | ||
193 | 222 | ||
194 | 333 | ||
195 | 444 | ||
196 | 555 | ||
197 | 666 | ||
198 | 777 | ||
199 | 888 | ||
200 | 999 | ||
201 | " \ | ||
202 | "\ | ||
203 | --- input | ||
204 | +++ input | ||
205 | @@ -1,6 +1,4 @@ | ||
206 | -111 | ||
207 | -222 | ||
208 | -333 | ||
209 | +111changed | ||
210 | 444 | ||
211 | 555 | ||
212 | 666 | ||
213 | " \ | ||
214 | |||
178 | rm input.orig 2>/dev/null | 215 | rm input.orig 2>/dev/null |
179 | 216 | ||
180 | exit $FAILCOUNT | 217 | exit $FAILCOUNT |
diff --git a/testsuite/testing.sh b/testsuite/testing.sh index c7c9ca6af..e7e64e58b 100644 --- a/testsuite/testing.sh +++ b/testsuite/testing.sh | |||
@@ -87,6 +87,7 @@ testing() | |||
87 | 87 | ||
88 | $ECHO -ne "$3" > expected | 88 | $ECHO -ne "$3" > expected |
89 | $ECHO -ne "$4" > input | 89 | $ECHO -ne "$4" > input |
90 | [ -z "$VERBOSE" ] || echo ====================== | ||
90 | [ -z "$VERBOSE" ] || echo "echo -ne '$4' >input" | 91 | [ -z "$VERBOSE" ] || echo "echo -ne '$4' >input" |
91 | [ -z "$VERBOSE" ] || echo "echo -ne '$5' | $2" | 92 | [ -z "$VERBOSE" ] || echo "echo -ne '$5' | $2" |
92 | $ECHO -ne "$5" | eval "$2" > actual | 93 | $ECHO -ne "$5" | eval "$2" > actual |
diff --git a/util-linux/Config.src b/util-linux/Config.src index c71b4de38..dbf2b0d85 100644 --- a/util-linux/Config.src +++ b/util-linux/Config.src | |||
@@ -40,6 +40,13 @@ config BLKID | |||
40 | WARNING: | 40 | WARNING: |
41 | With all submodules selected, it will add ~8k to busybox. | 41 | With all submodules selected, it will add ~8k to busybox. |
42 | 42 | ||
43 | config FEATURE_BLKID_TYPE | ||
44 | bool "Print filesystem type" | ||
45 | default n | ||
46 | depends on BLKID | ||
47 | help | ||
48 | Show TYPE="filesystem type" | ||
49 | |||
43 | config DMESG | 50 | config DMESG |
44 | bool "dmesg" | 51 | bool "dmesg" |
45 | default y | 52 | default y |
diff --git a/util-linux/acpid.c b/util-linux/acpid.c index 0b227a8ae..ce4c98ebe 100644 --- a/util-linux/acpid.c +++ b/util-linux/acpid.c | |||
@@ -16,9 +16,9 @@ enum { | |||
16 | OPT_e = (1 << 2), | 16 | OPT_e = (1 << 2), |
17 | OPT_f = (1 << 3), | 17 | OPT_f = (1 << 3), |
18 | OPT_l = (1 << 4), | 18 | OPT_l = (1 << 4), |
19 | OPT_p = (1 << 5) * ENABLE_FEATURE_PIDFILE, | 19 | OPT_a = (1 << 5), |
20 | OPT_a = (1 << 6), | 20 | OPT_M = (1 << 6), |
21 | OPT_M = (1 << 7), | 21 | OPT_p = (1 << 7) * ENABLE_FEATURE_PIDFILE, |
22 | }; | 22 | }; |
23 | 23 | ||
24 | struct acpi_event { | 24 | struct acpi_event { |
@@ -199,8 +199,9 @@ int acpid_main(int argc UNUSED_PARAM, char **argv) | |||
199 | INIT_G(); | 199 | INIT_G(); |
200 | 200 | ||
201 | opt_complementary = "df:e--e"; | 201 | opt_complementary = "df:e--e"; |
202 | opts = getopt32(argv, "c:de:fl:p:a:M:" IF_FEATURE_ACPID_COMPAT("g:m:s:S:v"), | 202 | opts = getopt32(argv, "c:de:fl:a:M:" IF_FEATURE_PIDFILE("p:") IF_FEATURE_ACPID_COMPAT("g:m:s:S:v"), |
203 | &opt_dir, &opt_input, &opt_logfile, &opt_pidfile, &opt_action, &opt_map | 203 | &opt_dir, &opt_input, &opt_logfile, &opt_action, &opt_map |
204 | IF_FEATURE_PIDFILE(, &opt_pidfile) | ||
204 | IF_FEATURE_ACPID_COMPAT(, NULL, NULL, NULL, NULL) | 205 | IF_FEATURE_ACPID_COMPAT(, NULL, NULL, NULL, NULL) |
205 | ); | 206 | ); |
206 | 207 | ||
diff --git a/util-linux/blkid.c b/util-linux/blkid.c index 4ce44b144..fe88fb31d 100644 --- a/util-linux/blkid.c +++ b/util-linux/blkid.c | |||
@@ -10,9 +10,16 @@ | |||
10 | #include "libbb.h" | 10 | #include "libbb.h" |
11 | #include "volume_id.h" | 11 | #include "volume_id.h" |
12 | 12 | ||
13 | //TODO: extend to take BLOCKDEV args, and show TYPE="fstype" | ||
14 | |||
13 | int blkid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 15 | int blkid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
14 | int blkid_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | 16 | int blkid_main(int argc UNUSED_PARAM, char **argv) |
15 | { | 17 | { |
18 | while (*++argv) { | ||
19 | /* Note: bogus device names don't cause any error messages */ | ||
20 | add_to_uuid_cache(*argv); | ||
21 | } | ||
22 | |||
16 | display_uuid_cache(); | 23 | display_uuid_cache(); |
17 | return 0; | 24 | return 0; |
18 | } | 25 | } |
diff --git a/util-linux/fbset.c b/util-linux/fbset.c index 07c8f55d1..77cc1fc12 100644 --- a/util-linux/fbset.c +++ b/util-linux/fbset.c | |||
@@ -26,7 +26,7 @@ enum { | |||
26 | 26 | ||
27 | struct fb_bitfield { | 27 | struct fb_bitfield { |
28 | uint32_t offset; /* beginning of bitfield */ | 28 | uint32_t offset; /* beginning of bitfield */ |
29 | uint32_t length; /* length of bitfield */ | 29 | uint32_t length; /* length of bitfield */ |
30 | uint32_t msb_right; /* !=0: Most significant bit is right */ | 30 | uint32_t msb_right; /* !=0: Most significant bit is right */ |
31 | }; | 31 | }; |
32 | struct fb_var_screeninfo { | 32 | struct fb_var_screeninfo { |
@@ -52,7 +52,7 @@ struct fb_var_screeninfo { | |||
52 | uint32_t height; /* height of picture in mm */ | 52 | uint32_t height; /* height of picture in mm */ |
53 | uint32_t width; /* width of picture in mm */ | 53 | uint32_t width; /* width of picture in mm */ |
54 | 54 | ||
55 | uint32_t accel_flags; /* acceleration flags (hints) */ | 55 | uint32_t accel_flags; /* acceleration flags (hints) */ |
56 | 56 | ||
57 | /* Timing: All values in pixclocks, except pixclock (of course) */ | 57 | /* Timing: All values in pixclocks, except pixclock (of course) */ |
58 | uint32_t pixclock; /* pixel clock in ps (pico seconds) */ | 58 | uint32_t pixclock; /* pixel clock in ps (pico seconds) */ |
@@ -317,7 +317,7 @@ static int read_mode_db(struct fb_var_screeninfo *base, const char *fn, | |||
317 | } | 317 | } |
318 | case 4: | 318 | case 4: |
319 | case 5: | 319 | case 5: |
320 | case 6: { | 320 | case 6: { |
321 | static const uint32_t syncs[] = {FB_SYNC_VERT_HIGH_ACT, FB_SYNC_HOR_HIGH_ACT, FB_SYNC_COMP_HIGH_ACT}; | 321 | static const uint32_t syncs[] = {FB_SYNC_VERT_HIGH_ACT, FB_SYNC_HOR_HIGH_ACT, FB_SYNC_COMP_HIGH_ACT}; |
322 | ss(&base->sync, syncs[i-4], p, "low"); | 322 | ss(&base->sync, syncs[i-4], p, "low"); |
323 | //bb_info_msg("SYNC[%s]", p); | 323 | //bb_info_msg("SYNC[%s]", p); |
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c index 3f2e0d3ae..02785ab85 100644 --- a/util-linux/fdisk.c +++ b/util-linux/fdisk.c | |||
@@ -662,6 +662,7 @@ STATIC_OSF void bsd_select(void); | |||
662 | STATIC_OSF void xbsd_print_disklabel(int); | 662 | STATIC_OSF void xbsd_print_disklabel(int); |
663 | #include "fdisk_osf.c" | 663 | #include "fdisk_osf.c" |
664 | 664 | ||
665 | STATIC_GPT void gpt_list_table(int xtra); | ||
665 | #include "fdisk_gpt.c" | 666 | #include "fdisk_gpt.c" |
666 | 667 | ||
667 | #if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL | 668 | #if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL |
diff --git a/util-linux/hexdump.c b/util-linux/hexdump.c index 8c4d521ab..a38fe05e7 100644 --- a/util-linux/hexdump.c +++ b/util-linux/hexdump.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Based on code from util-linux v 2.11l | 4 | * Based on code from util-linux v 2.11l |
5 | * | 5 | * |
6 | * Copyright (c) 1989 | 6 | * Copyright (c) 1989 |
7 | * The Regents of the University of California. All rights reserved. | 7 | * The Regents of the University of California. All rights reserved. |
8 | * | 8 | * |
9 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 9 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
10 | */ | 10 | */ |
@@ -32,11 +32,11 @@ static void bb_dump_addfile(dumper_t *dumper, char *name) | |||
32 | } | 32 | } |
33 | 33 | ||
34 | static const char *const add_strings[] = { | 34 | static const char *const add_strings[] = { |
35 | "\"%07.7_ax \" 16/1 \"%03o \" \"\\n\"", /* b */ | 35 | "\"%07.7_ax \" 16/1 \"%03o \" \"\\n\"", /* b */ |
36 | "\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\"", /* c */ | 36 | "\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\"", /* c */ |
37 | "\"%07.7_ax \" 8/2 \" %05u \" \"\\n\"", /* d */ | 37 | "\"%07.7_ax \" 8/2 \" %05u \" \"\\n\"", /* d */ |
38 | "\"%07.7_ax \" 8/2 \" %06o \" \"\\n\"", /* o */ | 38 | "\"%07.7_ax \" 8/2 \" %06o \" \"\\n\"", /* o */ |
39 | "\"%07.7_ax \" 8/2 \" %04x \" \"\\n\"", /* x */ | 39 | "\"%07.7_ax \" 8/2 \" %04x \" \"\\n\"", /* x */ |
40 | }; | 40 | }; |
41 | 41 | ||
42 | static const char add_first[] ALIGN1 = "\"%07.7_Ax\n\""; | 42 | static const char add_first[] ALIGN1 = "\"%07.7_Ax\n\""; |
diff --git a/util-linux/ipcrm.c b/util-linux/ipcrm.c index 731216c06..e597ed637 100644 --- a/util-linux/ipcrm.c +++ b/util-linux/ipcrm.c | |||
@@ -40,7 +40,7 @@ typedef enum type_id { | |||
40 | MSG | 40 | MSG |
41 | } type_id; | 41 | } type_id; |
42 | 42 | ||
43 | static int remove_ids(type_id type, int argc, char **argv) | 43 | static int remove_ids(type_id type, char **argv) |
44 | { | 44 | { |
45 | unsigned long id; | 45 | unsigned long id; |
46 | int nb_errors = 0; | 46 | int nb_errors = 0; |
@@ -48,7 +48,7 @@ static int remove_ids(type_id type, int argc, char **argv) | |||
48 | 48 | ||
49 | arg.val = 0; | 49 | arg.val = 0; |
50 | 50 | ||
51 | while (argc) { | 51 | while (argv[0]) { |
52 | id = bb_strtoul(argv[0], NULL, 10); | 52 | id = bb_strtoul(argv[0], NULL, 10); |
53 | if (errno || id > INT_MAX) { | 53 | if (errno || id > INT_MAX) { |
54 | bb_error_msg("invalid id: %s", argv[0]); | 54 | bb_error_msg("invalid id: %s", argv[0]); |
@@ -67,7 +67,6 @@ static int remove_ids(type_id type, int argc, char **argv) | |||
67 | nb_errors++; | 67 | nb_errors++; |
68 | } | 68 | } |
69 | } | 69 | } |
70 | argc--; | ||
71 | argv++; | 70 | argv++; |
72 | } | 71 | } |
73 | 72 | ||
@@ -109,7 +108,7 @@ int ipcrm_main(int argc, char **argv) | |||
109 | else if (w == 'e') | 108 | else if (w == 'e') |
110 | what = SEM; | 109 | what = SEM; |
111 | 110 | ||
112 | if (remove_ids(what, argc-2, &argv[2])) | 111 | if (remove_ids(what, &argv[2])) |
113 | fflush_stdout_and_exit(EXIT_FAILURE); | 112 | fflush_stdout_and_exit(EXIT_FAILURE); |
114 | printf("resource(s) deleted\n"); | 113 | printf("resource(s) deleted\n"); |
115 | return 0; | 114 | return 0; |
diff --git a/util-linux/more.c b/util-linux/more.c index 1fd6f9ee8..c424a0e4b 100644 --- a/util-linux/more.c +++ b/util-linux/more.c | |||
@@ -29,16 +29,20 @@ struct globals { | |||
29 | #define new_settings (G.new_settings ) | 29 | #define new_settings (G.new_settings ) |
30 | #define cin_fileno (G.cin_fileno ) | 30 | #define cin_fileno (G.cin_fileno ) |
31 | 31 | ||
32 | #define setTermSettings(fd, argp) do { \ | 32 | #define setTermSettings(fd, argp) \ |
33 | if (ENABLE_FEATURE_USE_TERMIOS) tcsetattr(fd, TCSANOW, argp); \ | 33 | do { \ |
34 | } while (0) | 34 | if (ENABLE_FEATURE_USE_TERMIOS) \ |
35 | tcsetattr(fd, TCSANOW, argp); \ | ||
36 | } while (0) | ||
35 | #define getTermSettings(fd, argp) tcgetattr(fd, argp) | 37 | #define getTermSettings(fd, argp) tcgetattr(fd, argp) |
36 | 38 | ||
37 | static void gotsig(int sig UNUSED_PARAM) | 39 | static void gotsig(int sig UNUSED_PARAM) |
38 | { | 40 | { |
39 | bb_putchar('\n'); | 41 | /* bb_putchar_stderr doesn't use stdio buffering, |
42 | * therefore it is safe in signal handler */ | ||
43 | bb_putchar_stderr('\n'); | ||
40 | setTermSettings(cin_fileno, &initial_settings); | 44 | setTermSettings(cin_fileno, &initial_settings); |
41 | exit(EXIT_FAILURE); | 45 | _exit(EXIT_FAILURE); |
42 | } | 46 | } |
43 | 47 | ||
44 | #define CONVERTED_TAB_SIZE 8 | 48 | #define CONVERTED_TAB_SIZE 8 |
@@ -187,6 +191,7 @@ int more_main(int argc UNUSED_PARAM, char **argv) | |||
187 | } | 191 | } |
188 | /* My small mind cannot fathom backspaces and UTF-8 */ | 192 | /* My small mind cannot fathom backspaces and UTF-8 */ |
189 | putchar(c); | 193 | putchar(c); |
194 | die_if_ferror_stdout(); /* if tty was destroyed (closed xterm, etc) */ | ||
190 | } | 195 | } |
191 | fclose(file); | 196 | fclose(file); |
192 | fflush_all(); | 197 | fflush_all(); |
diff --git a/util-linux/umount.c b/util-linux/umount.c index 78c603856..5597d9eba 100644 --- a/util-linux/umount.c +++ b/util-linux/umount.c | |||
@@ -9,39 +9,10 @@ | |||
9 | */ | 9 | */ |
10 | #include <mntent.h> | 10 | #include <mntent.h> |
11 | #include <sys/mount.h> | 11 | #include <sys/mount.h> |
12 | /* Make sure we have all the new mount flags we actually try to use. */ | ||
13 | #ifndef MS_BIND | ||
14 | # define MS_BIND (1 << 12) | ||
15 | #endif | ||
16 | #ifndef MS_MOVE | ||
17 | # define MS_MOVE (1 << 13) | ||
18 | #endif | ||
19 | #ifndef MS_RECURSIVE | ||
20 | # define MS_RECURSIVE (1 << 14) | ||
21 | #endif | ||
22 | #ifndef MS_SILENT | ||
23 | # define MS_SILENT (1 << 15) | ||
24 | #endif | ||
25 | /* The shared subtree stuff, which went in around 2.6.15. */ | ||
26 | #ifndef MS_UNBINDABLE | ||
27 | # define MS_UNBINDABLE (1 << 17) | ||
28 | #endif | ||
29 | #ifndef MS_PRIVATE | ||
30 | # define MS_PRIVATE (1 << 18) | ||
31 | #endif | ||
32 | #ifndef MS_SLAVE | ||
33 | # define MS_SLAVE (1 << 19) | ||
34 | #endif | ||
35 | #ifndef MS_SHARED | ||
36 | # define MS_SHARED (1 << 20) | ||
37 | #endif | ||
38 | #ifndef MS_RELATIME | ||
39 | # define MS_RELATIME (1 << 21) | ||
40 | #endif | ||
41 | #include "libbb.h" | 12 | #include "libbb.h" |
42 | 13 | ||
43 | |||
44 | #if defined(__dietlibc__) | 14 | #if defined(__dietlibc__) |
15 | // TODO: This does not belong here. | ||
45 | /* 16.12.2006, Sampo Kellomaki (sampo@iki.fi) | 16 | /* 16.12.2006, Sampo Kellomaki (sampo@iki.fi) |
46 | * dietlibc-0.30 does not have implementation of getmntent_r() */ | 17 | * dietlibc-0.30 does not have implementation of getmntent_r() */ |
47 | static struct mntent *getmntent_r(FILE* stream, struct mntent* result, | 18 | static struct mntent *getmntent_r(FILE* stream, struct mntent* result, |
@@ -54,23 +25,17 @@ static struct mntent *getmntent_r(FILE* stream, struct mntent* result, | |||
54 | 25 | ||
55 | /* ignored: -v -d -t -i */ | 26 | /* ignored: -v -d -t -i */ |
56 | #define OPTION_STRING "fldnra" "vdt:i" | 27 | #define OPTION_STRING "fldnra" "vdt:i" |
57 | #define OPT_FORCE (1 << 0) | 28 | #define OPT_FORCE (1 << 0) // Same as MNT_FORCE |
58 | #define OPT_LAZY (1 << 1) | 29 | #define OPT_LAZY (1 << 1) // Same as MNT_DETACH |
59 | #define OPT_FREELOOP (1 << 2) | 30 | #define OPT_FREELOOP (1 << 2) |
60 | #define OPT_NO_MTAB (1 << 3) | 31 | #define OPT_NO_MTAB (1 << 3) |
61 | #define OPT_REMOUNT (1 << 4) | 32 | #define OPT_REMOUNT (1 << 4) |
62 | #define OPT_ALL (ENABLE_FEATURE_UMOUNT_ALL ? (1 << 5) : 0) | 33 | #define OPT_ALL (ENABLE_FEATURE_UMOUNT_ALL ? (1 << 5) : 0) |
63 | 34 | ||
64 | // These constants from linux/fs.h must match OPT_FORCE and OPT_LAZY, | ||
65 | // otherwise "doForce" trick below won't work! | ||
66 | //#define MNT_FORCE 0x00000001 /* Attempt to forcibly umount */ | ||
67 | //#define MNT_DETACH 0x00000002 /* Just detach from the tree */ | ||
68 | |||
69 | int umount_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 35 | int umount_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
70 | int umount_main(int argc UNUSED_PARAM, char **argv) | 36 | int umount_main(int argc UNUSED_PARAM, char **argv) |
71 | { | 37 | { |
72 | int doForce; | 38 | int doForce; |
73 | char *const buf = xmalloc(4096); /* reducing stack usage */ | ||
74 | struct mntent me; | 39 | struct mntent me; |
75 | FILE *fp; | 40 | FILE *fp; |
76 | char *fstype = NULL; | 41 | char *fstype = NULL; |
@@ -85,6 +50,9 @@ int umount_main(int argc UNUSED_PARAM, char **argv) | |||
85 | opt = getopt32(argv, OPTION_STRING, &fstype); | 50 | opt = getopt32(argv, OPTION_STRING, &fstype); |
86 | //argc -= optind; | 51 | //argc -= optind; |
87 | argv += optind; | 52 | argv += optind; |
53 | |||
54 | // MNT_FORCE and MNT_DETACH (from linux/fs.h) must match | ||
55 | // OPT_FORCE and OPT_LAZY, otherwise this trick won't work: | ||
88 | doForce = MAX((opt & OPT_FORCE), (opt & OPT_LAZY)); | 56 | doForce = MAX((opt & OPT_FORCE), (opt & OPT_LAZY)); |
89 | 57 | ||
90 | /* Get a list of mount points from mtab. We read them all in now mostly | 58 | /* Get a list of mount points from mtab. We read them all in now mostly |
@@ -101,7 +69,7 @@ int umount_main(int argc UNUSED_PARAM, char **argv) | |||
101 | if (opt & OPT_ALL) | 69 | if (opt & OPT_ALL) |
102 | bb_error_msg_and_die("can't open '%s'", bb_path_mtab_file); | 70 | bb_error_msg_and_die("can't open '%s'", bb_path_mtab_file); |
103 | } else { | 71 | } else { |
104 | while (getmntent_r(fp, &me, buf, 4096)) { | 72 | while (getmntent_r(fp, &me, bb_common_bufsiz1, sizeof(bb_common_bufsiz1))) { |
105 | /* Match fstype if passed */ | 73 | /* Match fstype if passed */ |
106 | if (!match_fstype(&me, fstype)) | 74 | if (!match_fstype(&me, fstype)) |
107 | continue; | 75 | continue; |
@@ -203,7 +171,6 @@ int umount_main(int argc UNUSED_PARAM, char **argv) | |||
203 | free(mtl); | 171 | free(mtl); |
204 | mtl = m; | 172 | mtl = m; |
205 | } | 173 | } |
206 | free(buf); | ||
207 | } | 174 | } |
208 | 175 | ||
209 | return status; | 176 | return status; |
diff --git a/util-linux/volume_id/cramfs.c b/util-linux/volume_id/cramfs.c index b84a6f0b2..28e997043 100644 --- a/util-linux/volume_id/cramfs.c +++ b/util-linux/volume_id/cramfs.c | |||
@@ -51,7 +51,7 @@ int FAST_FUNC volume_id_probe_cramfs(struct volume_id *id /*,uint64_t off*/) | |||
51 | volume_id_set_label_string(id, cs->name, 16); | 51 | volume_id_set_label_string(id, cs->name, 16); |
52 | 52 | ||
53 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); | 53 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); |
54 | // id->type = "cramfs"; | 54 | IF_FEATURE_BLKID_TYPE(id->type = "cramfs";) |
55 | return 0; | 55 | return 0; |
56 | } | 56 | } |
57 | 57 | ||
diff --git a/util-linux/volume_id/ext.c b/util-linux/volume_id/ext.c index 80c217f98..b5194a7b5 100644 --- a/util-linux/volume_id/ext.c +++ b/util-linux/volume_id/ext.c | |||
@@ -65,10 +65,12 @@ int FAST_FUNC volume_id_probe_ext(struct volume_id *id /*,uint64_t off*/) | |||
65 | volume_id_set_uuid(id, es->uuid, UUID_DCE); | 65 | volume_id_set_uuid(id, es->uuid, UUID_DCE); |
66 | dbg("ext: label '%s' uuid '%s'", id->label, id->uuid); | 66 | dbg("ext: label '%s' uuid '%s'", id->label, id->uuid); |
67 | 67 | ||
68 | // if ((le32_to_cpu(es->feature_compat) & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0) | 68 | #if ENABLE_FEATURE_BLKID_TYPE |
69 | // id->type = "ext3"; | 69 | if ((le32_to_cpu(es->feature_compat) & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0) |
70 | // else | 70 | id->type = "ext3"; |
71 | // id->type = "ext2"; | 71 | else |
72 | id->type = "ext2"; | ||
73 | #endif | ||
72 | 74 | ||
73 | return 0; | 75 | return 0; |
74 | } | 76 | } |
diff --git a/util-linux/volume_id/fat.c b/util-linux/volume_id/fat.c index b0f427c74..904fbb201 100644 --- a/util-linux/volume_id/fat.c +++ b/util-linux/volume_id/fat.c | |||
@@ -332,7 +332,7 @@ int FAST_FUNC volume_id_probe_vfat(struct volume_id *id /*,uint64_t fat_partitio | |||
332 | 332 | ||
333 | ret: | 333 | ret: |
334 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); | 334 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); |
335 | // id->type = "vfat"; | 335 | IF_FEATURE_BLKID_TYPE(id->type = "vfat";) |
336 | 336 | ||
337 | return 0; | 337 | return 0; |
338 | } | 338 | } |
diff --git a/util-linux/volume_id/get_devname.c b/util-linux/volume_id/get_devname.c index bf32e6a8c..7c9930543 100644 --- a/util-linux/volume_id/get_devname.c +++ b/util-linux/volume_id/get_devname.c | |||
@@ -19,14 +19,22 @@ static struct uuidCache_s { | |||
19 | char *device; | 19 | char *device; |
20 | char *label; | 20 | char *label; |
21 | char *uc_uuid; /* prefix makes it easier to grep for */ | 21 | char *uc_uuid; /* prefix makes it easier to grep for */ |
22 | IF_FEATURE_BLKID_TYPE(const char *type;) | ||
22 | } *uuidCache; | 23 | } *uuidCache; |
23 | 24 | ||
25 | #if !ENABLE_FEATURE_BLKID_TYPE | ||
26 | #define get_label_uuid(fd, label, uuid, type) \ | ||
27 | get_label_uuid(fd, label, uuid) | ||
28 | #define uuidcache_addentry(device, label, uuid, type) \ | ||
29 | uuidcache_addentry(device, label, uuid) | ||
30 | #endif | ||
31 | |||
24 | /* Returns !0 on error. | 32 | /* Returns !0 on error. |
25 | * Otherwise, returns malloc'ed strings for label and uuid | 33 | * Otherwise, returns malloc'ed strings for label and uuid |
26 | * (and they can't be NULL, although they can be ""). | 34 | * (and they can't be NULL, although they can be ""). |
27 | * NB: closes fd. */ | 35 | * NB: closes fd. */ |
28 | static int | 36 | static int |
29 | get_label_uuid(int fd, char **label, char **uuid) | 37 | get_label_uuid(int fd, char **label, char **uuid, const char **type) |
30 | { | 38 | { |
31 | int rv = 1; | 39 | int rv = 1; |
32 | uint64_t size; | 40 | uint64_t size; |
@@ -44,7 +52,12 @@ get_label_uuid(int fd, char **label, char **uuid) | |||
44 | if (vid->label[0] != '\0' || vid->uuid[0] != '\0') { | 52 | if (vid->label[0] != '\0' || vid->uuid[0] != '\0') { |
45 | *label = xstrndup(vid->label, sizeof(vid->label)); | 53 | *label = xstrndup(vid->label, sizeof(vid->label)); |
46 | *uuid = xstrndup(vid->uuid, sizeof(vid->uuid)); | 54 | *uuid = xstrndup(vid->uuid, sizeof(vid->uuid)); |
55 | #if ENABLE_FEATURE_BLKID_TYPE | ||
56 | *type = vid->type; | ||
57 | dbg("found label '%s', uuid '%s', type '%s'", *label, *uuid, *type); | ||
58 | #else | ||
47 | dbg("found label '%s', uuid '%s'", *label, *uuid); | 59 | dbg("found label '%s', uuid '%s'", *label, *uuid); |
60 | #endif | ||
48 | rv = 0; | 61 | rv = 0; |
49 | } | 62 | } |
50 | ret: | 63 | ret: |
@@ -54,7 +67,7 @@ get_label_uuid(int fd, char **label, char **uuid) | |||
54 | 67 | ||
55 | /* NB: we take ownership of (malloc'ed) label and uuid */ | 68 | /* NB: we take ownership of (malloc'ed) label and uuid */ |
56 | static void | 69 | static void |
57 | uuidcache_addentry(char *device, /*int major, int minor,*/ char *label, char *uuid) | 70 | uuidcache_addentry(char *device, /*int major, int minor,*/ char *label, char *uuid, const char *type) |
58 | { | 71 | { |
59 | struct uuidCache_s *last; | 72 | struct uuidCache_s *last; |
60 | 73 | ||
@@ -72,6 +85,7 @@ uuidcache_addentry(char *device, /*int major, int minor,*/ char *label, char *uu | |||
72 | last->device = device; | 85 | last->device = device; |
73 | last->label = label; | 86 | last->label = label; |
74 | last->uc_uuid = uuid; | 87 | last->uc_uuid = uuid; |
88 | IF_FEATURE_BLKID_TYPE(last->type = type;) | ||
75 | } | 89 | } |
76 | 90 | ||
77 | /* If get_label_uuid() on device_name returns success, | 91 | /* If get_label_uuid() on device_name returns success, |
@@ -83,10 +97,6 @@ uuidcache_check_device(const char *device, | |||
83 | void *userData UNUSED_PARAM, | 97 | void *userData UNUSED_PARAM, |
84 | int depth UNUSED_PARAM) | 98 | int depth UNUSED_PARAM) |
85 | { | 99 | { |
86 | char *uuid = uuid; /* for compiler */ | ||
87 | char *label = label; | ||
88 | int fd; | ||
89 | |||
90 | /* note: this check rejects links to devices, among other nodes */ | 100 | /* note: this check rejects links to devices, among other nodes */ |
91 | if (!S_ISBLK(statbuf->st_mode)) | 101 | if (!S_ISBLK(statbuf->st_mode)) |
92 | return TRUE; | 102 | return TRUE; |
@@ -99,21 +109,15 @@ uuidcache_check_device(const char *device, | |||
99 | if (major(statbuf->st_rdev) == 2) | 109 | if (major(statbuf->st_rdev) == 2) |
100 | return TRUE; | 110 | return TRUE; |
101 | 111 | ||
102 | fd = open(device, O_RDONLY); | 112 | add_to_uuid_cache(device); |
103 | if (fd < 0) | ||
104 | return TRUE; | ||
105 | 113 | ||
106 | /* get_label_uuid() closes fd in all cases (success & failure) */ | ||
107 | if (get_label_uuid(fd, &label, &uuid) == 0) { | ||
108 | /* uuidcache_addentry() takes ownership of all three params */ | ||
109 | uuidcache_addentry(xstrdup(device), /*ma, mi,*/ label, uuid); | ||
110 | } | ||
111 | return TRUE; | 114 | return TRUE; |
112 | } | 115 | } |
113 | 116 | ||
114 | static void | 117 | static void |
115 | uuidcache_init(void) | 118 | uuidcache_init(void) |
116 | { | 119 | { |
120 | dbg("DBG: uuidCache=%x, uuidCache"); | ||
117 | if (uuidCache) | 121 | if (uuidCache) |
118 | return; | 122 | return; |
119 | 123 | ||
@@ -223,11 +227,38 @@ void display_uuid_cache(void) | |||
223 | printf(" LABEL=\"%s\"", u->label); | 227 | printf(" LABEL=\"%s\"", u->label); |
224 | if (u->uc_uuid[0]) | 228 | if (u->uc_uuid[0]) |
225 | printf(" UUID=\"%s\"", u->uc_uuid); | 229 | printf(" UUID=\"%s\"", u->uc_uuid); |
230 | #if ENABLE_FEATURE_BLKID_TYPE | ||
231 | if (u->type) | ||
232 | printf(" TYPE=\"%s\"", u->type); | ||
233 | #endif | ||
226 | bb_putchar('\n'); | 234 | bb_putchar('\n'); |
227 | u = u->next; | 235 | u = u->next; |
228 | } | 236 | } |
229 | } | 237 | } |
230 | 238 | ||
239 | int add_to_uuid_cache(const char *device) | ||
240 | { | ||
241 | char *uuid = uuid; /* for compiler */ | ||
242 | char *label = label; | ||
243 | #if ENABLE_FEATURE_BLKID_TYPE | ||
244 | const char *type = type; | ||
245 | #endif | ||
246 | int fd; | ||
247 | |||
248 | fd = open(device, O_RDONLY); | ||
249 | if (fd < 0) | ||
250 | return 0; | ||
251 | |||
252 | /* get_label_uuid() closes fd in all cases (success & failure) */ | ||
253 | if (get_label_uuid(fd, &label, &uuid, &type) == 0) { | ||
254 | /* uuidcache_addentry() takes ownership of all four params */ | ||
255 | uuidcache_addentry(xstrdup(device), /*ma, mi,*/ label, uuid, type); | ||
256 | return 1; | ||
257 | } | ||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | |||
231 | /* Used by mount and findfs */ | 262 | /* Used by mount and findfs */ |
232 | 263 | ||
233 | char *get_devname_from_label(const char *spec) | 264 | char *get_devname_from_label(const char *spec) |
diff --git a/util-linux/volume_id/hfs.c b/util-linux/volume_id/hfs.c index cf7585138..f3f19dba7 100644 --- a/util-linux/volume_id/hfs.c +++ b/util-linux/volume_id/hfs.c | |||
@@ -195,7 +195,7 @@ int FAST_FUNC volume_id_probe_hfs_hfsplus(struct volume_id *id /*,uint64_t off*/ | |||
195 | 195 | ||
196 | volume_id_set_uuid(id, hfs->finder_info.id, UUID_HFS); | 196 | volume_id_set_uuid(id, hfs->finder_info.id, UUID_HFS); |
197 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); | 197 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); |
198 | // id->type = "hfs"; | 198 | IF_FEATURE_BLKID_TYPE(id->type = "hfs";) |
199 | 199 | ||
200 | return 0; | 200 | return 0; |
201 | 201 | ||
diff --git a/util-linux/volume_id/iso9660.c b/util-linux/volume_id/iso9660.c index 1519de496..1d7693a9c 100644 --- a/util-linux/volume_id/iso9660.c +++ b/util-linux/volume_id/iso9660.c | |||
@@ -114,7 +114,7 @@ int FAST_FUNC volume_id_probe_iso9660(struct volume_id *id /*,uint64_t off*/) | |||
114 | 114 | ||
115 | found: | 115 | found: |
116 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); | 116 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); |
117 | // id->type = "iso9660"; | 117 | IF_FEATURE_BLKID_TYPE(id->type = "iso9660";) |
118 | 118 | ||
119 | return 0; | 119 | return 0; |
120 | } | 120 | } |
diff --git a/util-linux/volume_id/jfs.c b/util-linux/volume_id/jfs.c index eb7a44872..5333af2c3 100644 --- a/util-linux/volume_id/jfs.c +++ b/util-linux/volume_id/jfs.c | |||
@@ -54,7 +54,7 @@ int FAST_FUNC volume_id_probe_jfs(struct volume_id *id /*,uint64_t off*/) | |||
54 | volume_id_set_uuid(id, js->uuid, UUID_DCE); | 54 | volume_id_set_uuid(id, js->uuid, UUID_DCE); |
55 | 55 | ||
56 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); | 56 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); |
57 | // id->type = "jfs"; | 57 | IF_FEATURE_BLKID_TYPE(id->type = "jfs";) |
58 | 58 | ||
59 | return 0; | 59 | return 0; |
60 | } | 60 | } |
diff --git a/util-linux/volume_id/linux_raid.c b/util-linux/volume_id/linux_raid.c index e1c86369d..761e54f9f 100644 --- a/util-linux/volume_id/linux_raid.c +++ b/util-linux/volume_id/linux_raid.c | |||
@@ -75,7 +75,7 @@ int FAST_FUNC volume_id_probe_linux_raid(struct volume_id *id /*,uint64_t off*/, | |||
75 | 75 | ||
76 | dbg("found raid signature"); | 76 | dbg("found raid signature"); |
77 | // volume_id_set_usage(id, VOLUME_ID_RAID); | 77 | // volume_id_set_usage(id, VOLUME_ID_RAID); |
78 | // id->type = "linux_raid_member"; | 78 | IF_FEATURE_BLKID_TYPE(id->type = "linux_raid_member";) |
79 | 79 | ||
80 | return 0; | 80 | return 0; |
81 | } | 81 | } |
diff --git a/util-linux/volume_id/linux_swap.c b/util-linux/volume_id/linux_swap.c index 574354611..62d588522 100644 --- a/util-linux/volume_id/linux_swap.c +++ b/util-linux/volume_id/linux_swap.c | |||
@@ -55,6 +55,7 @@ int FAST_FUNC volume_id_probe_linux_swap(struct volume_id *id /*,uint64_t off*/) | |||
55 | if (memcmp(buf, "SWAPSPACE2", 10) == 0 | 55 | if (memcmp(buf, "SWAPSPACE2", 10) == 0 |
56 | || memcmp(buf, "S1SUSPEND", 9) == 0 | 56 | || memcmp(buf, "S1SUSPEND", 9) == 0 |
57 | || memcmp(buf, "S2SUSPEND", 9) == 0 | 57 | || memcmp(buf, "S2SUSPEND", 9) == 0 |
58 | || memcmp(buf, "LINHIB0001", 10) == 0 | ||
58 | || memcmp(buf, "ULSUSPEND", 9) == 0 | 59 | || memcmp(buf, "ULSUSPEND", 9) == 0 |
59 | ) { | 60 | ) { |
60 | sw = volume_id_get_buffer(id, off, sizeof(struct swap_header_v1_2)); | 61 | sw = volume_id_get_buffer(id, off, sizeof(struct swap_header_v1_2)); |
@@ -72,7 +73,7 @@ int FAST_FUNC volume_id_probe_linux_swap(struct volume_id *id /*,uint64_t off*/) | |||
72 | 73 | ||
73 | found: | 74 | found: |
74 | // volume_id_set_usage(id, VOLUME_ID_OTHER); | 75 | // volume_id_set_usage(id, VOLUME_ID_OTHER); |
75 | // id->type = "swap"; | 76 | IF_FEATURE_BLKID_TYPE(id->type = "swap";) |
76 | 77 | ||
77 | return 0; | 78 | return 0; |
78 | } | 79 | } |
diff --git a/util-linux/volume_id/luks.c b/util-linux/volume_id/luks.c index 8ab09e381..f9b376672 100644 --- a/util-linux/volume_id/luks.c +++ b/util-linux/volume_id/luks.c | |||
@@ -94,7 +94,7 @@ int FAST_FUNC volume_id_probe_luks(struct volume_id *id /*,uint64_t off*/) | |||
94 | 94 | ||
95 | // volume_id_set_usage(id, VOLUME_ID_CRYPTO); | 95 | // volume_id_set_usage(id, VOLUME_ID_CRYPTO); |
96 | volume_id_set_uuid(id, header->uuid, UUID_DCE_STRING); | 96 | volume_id_set_uuid(id, header->uuid, UUID_DCE_STRING); |
97 | // id->type = "crypto_LUKS"; | 97 | IF_FEATURE_BLKID_TYPE(id->type = "crypto_LUKS";) |
98 | 98 | ||
99 | return 0; | 99 | return 0; |
100 | } | 100 | } |
diff --git a/util-linux/volume_id/ntfs.c b/util-linux/volume_id/ntfs.c index 17b1fe8b3..547f141c9 100644 --- a/util-linux/volume_id/ntfs.c +++ b/util-linux/volume_id/ntfs.c | |||
@@ -188,7 +188,7 @@ int FAST_FUNC volume_id_probe_ntfs(struct volume_id *id /*,uint64_t off*/) | |||
188 | 188 | ||
189 | found: | 189 | found: |
190 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); | 190 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); |
191 | // id->type = "ntfs"; | 191 | IF_FEATURE_BLKID_TYPE(id->type = "ntfs";) |
192 | 192 | ||
193 | return 0; | 193 | return 0; |
194 | } | 194 | } |
diff --git a/util-linux/volume_id/ocfs2.c b/util-linux/volume_id/ocfs2.c index e6c455965..fcdb15192 100644 --- a/util-linux/volume_id/ocfs2.c +++ b/util-linux/volume_id/ocfs2.c | |||
@@ -101,6 +101,6 @@ int FAST_FUNC volume_id_probe_ocfs2(struct volume_id *id /*,uint64_t off*/) | |||
101 | volume_id_set_label_string(id, os->s_label, OCFS2_MAX_VOL_LABEL_LEN < VOLUME_ID_LABEL_SIZE ? | 101 | volume_id_set_label_string(id, os->s_label, OCFS2_MAX_VOL_LABEL_LEN < VOLUME_ID_LABEL_SIZE ? |
102 | OCFS2_MAX_VOL_LABEL_LEN : VOLUME_ID_LABEL_SIZE); | 102 | OCFS2_MAX_VOL_LABEL_LEN : VOLUME_ID_LABEL_SIZE); |
103 | volume_id_set_uuid(id, os->s_uuid, UUID_DCE); | 103 | volume_id_set_uuid(id, os->s_uuid, UUID_DCE); |
104 | // id->type = "ocfs2"; | 104 | IF_FEATURE_BLKID_TYPE(id->type = "ocfs2";) |
105 | return 0; | 105 | return 0; |
106 | } | 106 | } |
diff --git a/util-linux/volume_id/reiserfs.c b/util-linux/volume_id/reiserfs.c index 3120b29a0..67b4a1877 100644 --- a/util-linux/volume_id/reiserfs.c +++ b/util-linux/volume_id/reiserfs.c | |||
@@ -107,7 +107,7 @@ int FAST_FUNC volume_id_probe_reiserfs(struct volume_id *id /*,uint64_t off*/) | |||
107 | 107 | ||
108 | found: | 108 | found: |
109 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); | 109 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); |
110 | // id->type = "reiserfs"; | 110 | IF_FEATURE_BLKID_TYPE(id->type = "reiserfs";) |
111 | 111 | ||
112 | return 0; | 112 | return 0; |
113 | } | 113 | } |
diff --git a/util-linux/volume_id/romfs.c b/util-linux/volume_id/romfs.c index 228e77a41..15653bedf 100644 --- a/util-linux/volume_id/romfs.c +++ b/util-linux/volume_id/romfs.c | |||
@@ -47,7 +47,7 @@ int FAST_FUNC volume_id_probe_romfs(struct volume_id *id /*,uint64_t off*/) | |||
47 | } | 47 | } |
48 | 48 | ||
49 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); | 49 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); |
50 | // id->type = "romfs"; | 50 | IF_FEATURE_BLKID_TYPE(id->type = "romfs";) |
51 | return 0; | 51 | return 0; |
52 | } | 52 | } |
53 | 53 | ||
diff --git a/util-linux/volume_id/sysv.c b/util-linux/volume_id/sysv.c index e0fa20a8c..6eb96464d 100644 --- a/util-linux/volume_id/sysv.c +++ b/util-linux/volume_id/sysv.c | |||
@@ -99,7 +99,7 @@ int FAST_FUNC volume_id_probe_sysv(struct volume_id *id /*,uint64_t off*/) | |||
99 | if (vs->s_magic == cpu_to_le32(SYSV_MAGIC) || vs->s_magic == cpu_to_be32(SYSV_MAGIC)) { | 99 | if (vs->s_magic == cpu_to_le32(SYSV_MAGIC) || vs->s_magic == cpu_to_be32(SYSV_MAGIC)) { |
100 | // volume_id_set_label_raw(id, vs->s_fname, 6); | 100 | // volume_id_set_label_raw(id, vs->s_fname, 6); |
101 | volume_id_set_label_string(id, vs->s_fname, 6); | 101 | volume_id_set_label_string(id, vs->s_fname, 6); |
102 | // id->type = "sysv"; | 102 | IF_FEATURE_BLKID_TYPE(id->type = "sysv"); |
103 | goto found; | 103 | goto found; |
104 | } | 104 | } |
105 | } | 105 | } |
@@ -112,7 +112,7 @@ int FAST_FUNC volume_id_probe_sysv(struct volume_id *id /*,uint64_t off*/) | |||
112 | if (xs->s_magic == cpu_to_le32(XENIX_MAGIC) || xs->s_magic == cpu_to_be32(XENIX_MAGIC)) { | 112 | if (xs->s_magic == cpu_to_le32(XENIX_MAGIC) || xs->s_magic == cpu_to_be32(XENIX_MAGIC)) { |
113 | // volume_id_set_label_raw(id, xs->s_fname, 6); | 113 | // volume_id_set_label_raw(id, xs->s_fname, 6); |
114 | volume_id_set_label_string(id, xs->s_fname, 6); | 114 | volume_id_set_label_string(id, xs->s_fname, 6); |
115 | // id->type = "xenix"; | 115 | IF_FEATURE_BLKID_TYPE(id->type = "xenix";) |
116 | goto found; | 116 | goto found; |
117 | } | 117 | } |
118 | } | 118 | } |
diff --git a/util-linux/volume_id/udf.c b/util-linux/volume_id/udf.c index dd2573171..cd63c8d8a 100644 --- a/util-linux/volume_id/udf.c +++ b/util-linux/volume_id/udf.c | |||
@@ -167,7 +167,6 @@ anchor: | |||
167 | 167 | ||
168 | found: | 168 | found: |
169 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); | 169 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); |
170 | // id->type = "udf"; | 170 | IF_FEATURE_BLKID_TYPE(id->type = "udf";) |
171 | |||
172 | return 0; | 171 | return 0; |
173 | } | 172 | } |
diff --git a/util-linux/volume_id/volume_id_internal.h b/util-linux/volume_id/volume_id_internal.h index 9b808ff6b..1c64046e5 100644 --- a/util-linux/volume_id/volume_id_internal.h +++ b/util-linux/volume_id/volume_id_internal.h | |||
@@ -80,7 +80,9 @@ struct volume_id { | |||
80 | // char type_version[VOLUME_ID_FORMAT_SIZE]; | 80 | // char type_version[VOLUME_ID_FORMAT_SIZE]; |
81 | // smallint usage_id; | 81 | // smallint usage_id; |
82 | // const char *usage; | 82 | // const char *usage; |
83 | // const char *type; | 83 | #if ENABLE_FEATURE_BLKID_TYPE |
84 | const char *type; | ||
85 | #endif | ||
84 | }; | 86 | }; |
85 | 87 | ||
86 | struct volume_id* FAST_FUNC volume_id_open_node(int fd); | 88 | struct volume_id* FAST_FUNC volume_id_open_node(int fd); |
diff --git a/util-linux/volume_id/xfs.c b/util-linux/volume_id/xfs.c index 1017d077b..84746020e 100644 --- a/util-linux/volume_id/xfs.c +++ b/util-linux/volume_id/xfs.c | |||
@@ -54,7 +54,7 @@ int FAST_FUNC volume_id_probe_xfs(struct volume_id *id /*,uint64_t off*/) | |||
54 | volume_id_set_uuid(id, xs->uuid, UUID_DCE); | 54 | volume_id_set_uuid(id, xs->uuid, UUID_DCE); |
55 | 55 | ||
56 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); | 56 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); |
57 | // id->type = "xfs"; | 57 | IF_FEATURE_BLKID_TYPE(id->type = "xfs";) |
58 | 58 | ||
59 | return 0; | 59 | return 0; |
60 | } | 60 | } |