diff options
author | Ron Yorston <rmy@pobox.com> | 2021-01-14 13:28:49 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-01-14 13:28:49 +0000 |
commit | 89963b524d211e1aec12b72b3725be05ee95c8cf (patch) | |
tree | 48590aef62b7ee7686b7898256f29def8d9c50b9 | |
parent | 9aa5a829070392c2ac6494d0c4e674c0c2bc7dab (diff) | |
parent | 2b7c1aa92c68524559a2067609d09309d5c09adc (diff) | |
download | busybox-w32-89963b524d211e1aec12b72b3725be05ee95c8cf.tar.gz busybox-w32-89963b524d211e1aec12b72b3725be05ee95c8cf.tar.bz2 busybox-w32-89963b524d211e1aec12b72b3725be05ee95c8cf.zip |
Merge branch 'busybox' into merge
227 files changed, 3296 insertions, 2214 deletions
@@ -649,6 +649,14 @@ config STACK_OPTIMIZATION_386 | |||
649 | do not work with it (they use SSE instructions without | 649 | do not work with it (they use SSE instructions without |
650 | ensuring stack alignment). | 650 | ensuring stack alignment). |
651 | 651 | ||
652 | config STATIC_LIBGCC | ||
653 | bool "Use -static-libgcc" | ||
654 | default y | ||
655 | help | ||
656 | This option instructs gcc to link in a static version of its | ||
657 | support library, libgcc. This means that the binary will require | ||
658 | one fewer dynamic library at run time. | ||
659 | |||
652 | comment 'Installation Options ("make install" behavior)' | 660 | comment 'Installation Options ("make install" behavior)' |
653 | 661 | ||
654 | choice | 662 | choice |
@@ -1,5 +1,5 @@ | |||
1 | VERSION = 1 | 1 | VERSION = 1 |
2 | PATCHLEVEL = 33 | 2 | PATCHLEVEL = 34 |
3 | SUBLEVEL = 0 | 3 | SUBLEVEL = 0 |
4 | EXTRAVERSION = .git | 4 | EXTRAVERSION = .git |
5 | NAME = Unnamed | 5 | NAME = Unnamed |
diff --git a/Makefile.flags b/Makefile.flags index fdaf5cc79..94ed4e40e 100644 --- a/Makefile.flags +++ b/Makefile.flags | |||
@@ -59,7 +59,8 @@ CFLAGS += $(call cc-option,-fno-builtin-strlen -fomit-frame-pointer -ffunction-s | |||
59 | CFLAGS += $(call cc-option,-fno-guess-branch-probability,) | 59 | CFLAGS += $(call cc-option,-fno-guess-branch-probability,) |
60 | CFLAGS += $(call cc-option,-funsigned-char,) | 60 | CFLAGS += $(call cc-option,-funsigned-char,) |
61 | 61 | ||
62 | ifneq ($(CC),clang) | 62 | ifeq ($(CONFIG_STATIC_LIBGCC),y) |
63 | # Disable it, for example, if you get | ||
63 | # "clang-9: warning: argument unused during compilation: '-static-libgcc'" | 64 | # "clang-9: warning: argument unused during compilation: '-static-libgcc'" |
64 | CFLAGS += $(call cc-option,-static-libgcc,) | 65 | CFLAGS += $(call cc-option,-static-libgcc,) |
65 | endif | 66 | endif |
@@ -189,8 +190,10 @@ LDLIBS += $(if $(SELINUX_LIBS),$(SELINUX_LIBS:-l%=%),$(SELINUX_PC_MODULES:lib%=% | |||
189 | endif | 190 | endif |
190 | 191 | ||
191 | ifeq ($(CONFIG_FEATURE_NSLOOKUP_BIG),y) | 192 | ifeq ($(CONFIG_FEATURE_NSLOOKUP_BIG),y) |
193 | ifeq ($(CONFIG_UNAME_OSNAME),Linux) | ||
192 | LDLIBS += resolv | 194 | LDLIBS += resolv |
193 | endif | 195 | endif |
196 | endif | ||
194 | 197 | ||
195 | ifeq ($(CONFIG_EFENCE),y) | 198 | ifeq ($(CONFIG_EFENCE),y) |
196 | LDLIBS += efence | 199 | LDLIBS += efence |
diff --git a/applets/applet_tables.c b/applets/applet_tables.c index ce2037440..7ba929b12 100644 --- a/applets/applet_tables.c +++ b/applets/applet_tables.c | |||
@@ -20,6 +20,10 @@ | |||
20 | #undef ARRAY_SIZE | 20 | #undef ARRAY_SIZE |
21 | #define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0]))) | 21 | #define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0]))) |
22 | 22 | ||
23 | #ifndef PATH_MAX | ||
24 | #define PATH_MAX 1024 | ||
25 | #endif | ||
26 | |||
23 | #include "../include/autoconf.h" | 27 | #include "../include/autoconf.h" |
24 | #include "../include/applet_metadata.h" | 28 | #include "../include/applet_metadata.h" |
25 | 29 | ||
diff --git a/arch/i386/Makefile b/arch/i386/Makefile index 425361fd9..2fa008fa7 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile | |||
@@ -11,3 +11,11 @@ ifeq ($(CONFIG_STACK_OPTIMIZATION_386),y) | |||
11 | # from aligning stack to 16 bytes. (Which is gcc's way of supporting SSE). | 11 | # from aligning stack to 16 bytes. (Which is gcc's way of supporting SSE). |
12 | CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2,) | 12 | CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2,) |
13 | endif | 13 | endif |
14 | |||
15 | # "Control how GCC aligns variables. | ||
16 | # Supported values for type are compat uses increased alignment value | ||
17 | # compatible uses GCC 4.8 and earlier, abi uses alignment value as specified by the psABI, | ||
18 | # and cacheline uses increased alignment value to match the cache line size. | ||
19 | # compat is the default." | ||
20 | # "abi" seems to be somewhat successful in preventing oversealous data alignment. | ||
21 | CFLAGS += $(call cc-option,-malign-data=abi,) | ||
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile new file mode 100644 index 000000000..16576fb81 --- /dev/null +++ b/arch/x86_64/Makefile | |||
@@ -0,0 +1,11 @@ | |||
1 | # ========================================================================== | ||
2 | # Build system | ||
3 | # ========================================================================== | ||
4 | |||
5 | # "Control how GCC aligns variables. | ||
6 | # Supported values for type are compat uses increased alignment value | ||
7 | # compatible uses GCC 4.8 and earlier, abi uses alignment value as specified by the psABI, | ||
8 | # and cacheline uses increased alignment value to match the cache line size. | ||
9 | # compat is the default." | ||
10 | # "abi" seems to be somewhat successful in preventing oversealous data alignment. | ||
11 | CFLAGS += $(call cc-option,-malign-data=abi,) | ||
diff --git a/archival/ar.c b/archival/ar.c index 66930f0b8..eb734a685 100644 --- a/archival/ar.c +++ b/archival/ar.c | |||
@@ -48,19 +48,9 @@ | |||
48 | 48 | ||
49 | //kbuild:lib-$(CONFIG_AR) += ar.o | 49 | //kbuild:lib-$(CONFIG_AR) += ar.o |
50 | 50 | ||
51 | //usage:#define ar_trivial_usage | ||
52 | //usage: "[-o] [-v] [-p] [-t] [-x] ARCHIVE FILES" | ||
53 | //usage:#define ar_full_usage "\n\n" | ||
54 | //usage: "Extract or list FILES from an ar archive\n" | ||
55 | //usage: "\n -o Preserve original dates" | ||
56 | //usage: "\n -p Extract to stdout" | ||
57 | //usage: "\n -t List" | ||
58 | //usage: "\n -x Extract" | ||
59 | //usage: "\n -v Verbose" | ||
60 | |||
61 | #include "libbb.h" | 51 | #include "libbb.h" |
62 | #include "bb_archive.h" | 52 | #include "bb_archive.h" |
63 | #include "ar.h" | 53 | #include "ar_.h" |
64 | 54 | ||
65 | #if ENABLE_FEATURE_AR_CREATE | 55 | #if ENABLE_FEATURE_AR_CREATE |
66 | /* filter out entries with same names as specified on the command line */ | 56 | /* filter out entries with same names as specified on the command line */ |
@@ -236,23 +226,36 @@ static void FAST_FUNC header_verbose_list_ar(const file_header_t *file_header) | |||
236 | ); | 226 | ); |
237 | } | 227 | } |
238 | 228 | ||
239 | #define AR_OPT_VERBOSE (1 << 0) | 229 | //usage:#define ar_trivial_usage |
240 | #define AR_OPT_PRESERVE_DATE (1 << 1) | 230 | //usage: "x|p|t"IF_FEATURE_AR_CREATE("|r")" [-ov] ARCHIVE [FILE]..." |
241 | /* "ar r" implies create, but warns about it. c suppresses warning. | 231 | //usage:#define ar_full_usage "\n\n" |
242 | * bbox accepts but ignores it: */ | 232 | //usage: "Extract or list FILEs from an ar archive"IF_FEATURE_AR_CREATE(", or create it")"\n" |
243 | #define AR_OPT_CREATE (1 << 2) | 233 | //usage: "\n x Extract" |
244 | 234 | //usage: "\n p Extract to stdout" | |
245 | #define AR_CMD_PRINT (1 << 3) | 235 | //usage: "\n t List" |
246 | #define FIRST_CMD AR_CMD_PRINT | 236 | //usage: IF_FEATURE_AR_CREATE( |
247 | #define AR_CMD_LIST (1 << 4) | 237 | //usage: "\n r Create" |
248 | #define AR_CMD_EXTRACT (1 << 5) | 238 | //usage: ) |
249 | #define AR_CMD_INSERT (1 << 6) | 239 | //usage: "\n -o Restore mtime" |
240 | //usage: "\n -v Verbose" | ||
250 | 241 | ||
251 | int ar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 242 | int ar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
252 | int ar_main(int argc UNUSED_PARAM, char **argv) | 243 | int ar_main(int argc UNUSED_PARAM, char **argv) |
253 | { | 244 | { |
254 | archive_handle_t *archive_handle; | 245 | archive_handle_t *archive_handle; |
255 | unsigned opt, t; | 246 | unsigned opt, t; |
247 | enum { | ||
248 | OPT_VERBOSE = (1 << 0), | ||
249 | OPT_PRESERVE_DATE = (1 << 1), | ||
250 | /* "ar r" implies create, but warns about it. c suppresses warning. | ||
251 | * bbox accepts but ignores it: */ | ||
252 | OPT_CREATE = (1 << 2), | ||
253 | CMD_PRINT = (1 << 3), | ||
254 | FIRST_CMD = CMD_PRINT, | ||
255 | CMD_LIST = (1 << 4), | ||
256 | CMD_EXTRACT = (1 << 5), | ||
257 | CMD_INSERT = ((1 << 6) * ENABLE_FEATURE_AR_CREATE), | ||
258 | }; | ||
256 | 259 | ||
257 | archive_handle = init_handle(); | 260 | archive_handle = init_handle(); |
258 | 261 | ||
@@ -272,26 +275,26 @@ int ar_main(int argc UNUSED_PARAM, char **argv) | |||
272 | if (t & (t-1)) /* more than one of p,t,x[,r] are specified */ | 275 | if (t & (t-1)) /* more than one of p,t,x[,r] are specified */ |
273 | bb_show_usage(); | 276 | bb_show_usage(); |
274 | 277 | ||
275 | if (opt & AR_CMD_PRINT) { | 278 | if (opt & CMD_PRINT) { |
276 | archive_handle->action_data = data_extract_to_stdout; | 279 | archive_handle->action_data = data_extract_to_stdout; |
277 | } | 280 | } |
278 | if (opt & AR_CMD_LIST) { | 281 | if (opt & CMD_LIST) { |
279 | archive_handle->action_header = header_list; | 282 | archive_handle->action_header = header_list; |
280 | } | 283 | } |
281 | if (opt & AR_CMD_EXTRACT) { | 284 | if (opt & CMD_EXTRACT) { |
282 | archive_handle->action_data = data_extract_all; | 285 | archive_handle->action_data = data_extract_all; |
283 | } | 286 | } |
284 | if (opt & AR_OPT_PRESERVE_DATE) { | 287 | if (opt & OPT_PRESERVE_DATE) { |
285 | archive_handle->ah_flags |= ARCHIVE_RESTORE_DATE; | 288 | archive_handle->ah_flags |= ARCHIVE_RESTORE_DATE; |
286 | } | 289 | } |
287 | if (opt & AR_OPT_VERBOSE) { | 290 | if (opt & OPT_VERBOSE) { |
288 | archive_handle->action_header = header_verbose_list_ar; | 291 | archive_handle->action_header = header_verbose_list_ar; |
289 | } | 292 | } |
290 | #if ENABLE_FEATURE_AR_CREATE | 293 | #if ENABLE_FEATURE_AR_CREATE |
291 | archive_handle->ar__name = *argv; | 294 | archive_handle->ar__name = *argv; |
292 | #endif | 295 | #endif |
293 | archive_handle->src_fd = xopen(*argv++, | 296 | archive_handle->src_fd = xopen(*argv++, |
294 | (opt & AR_CMD_INSERT) | 297 | (opt & CMD_INSERT) |
295 | ? O_RDWR | O_CREAT | 298 | ? O_RDWR | O_CREAT |
296 | : O_RDONLY | 299 | : O_RDONLY |
297 | ); | 300 | ); |
@@ -303,7 +306,7 @@ int ar_main(int argc UNUSED_PARAM, char **argv) | |||
303 | } | 306 | } |
304 | 307 | ||
305 | #if ENABLE_FEATURE_AR_CREATE | 308 | #if ENABLE_FEATURE_AR_CREATE |
306 | if (opt & AR_CMD_INSERT) | 309 | if (opt & CMD_INSERT) |
307 | return write_ar_archive(archive_handle); | 310 | return write_ar_archive(archive_handle); |
308 | #endif | 311 | #endif |
309 | 312 | ||
diff --git a/archival/bbunzip.c b/archival/bbunzip.c index 320fe4fd1..2beb92763 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c | |||
@@ -221,7 +221,7 @@ char* FAST_FUNC make_new_name_generic(char *filename, const char *expected_ext) | |||
221 | //usage:#define uncompress_trivial_usage | 221 | //usage:#define uncompress_trivial_usage |
222 | //usage: "[-cf] [FILE]..." | 222 | //usage: "[-cf] [FILE]..." |
223 | //usage:#define uncompress_full_usage "\n\n" | 223 | //usage:#define uncompress_full_usage "\n\n" |
224 | //usage: "Decompress .Z file[s]\n" | 224 | //usage: "Decompress FILEs (or stdin)\n" |
225 | //usage: "\n -c Write to stdout" | 225 | //usage: "\n -c Write to stdout" |
226 | //usage: "\n -f Overwrite" | 226 | //usage: "\n -f Overwrite" |
227 | 227 | ||
@@ -463,7 +463,7 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) | |||
463 | //usage:#define unlzma_trivial_usage | 463 | //usage:#define unlzma_trivial_usage |
464 | //usage: "[-cfk] [FILE]..." | 464 | //usage: "[-cfk] [FILE]..." |
465 | //usage:#define unlzma_full_usage "\n\n" | 465 | //usage:#define unlzma_full_usage "\n\n" |
466 | //usage: "Decompress FILE (or stdin)\n" | 466 | //usage: "Decompress FILEs (or stdin)\n" |
467 | //usage: "\n -c Write to stdout" | 467 | //usage: "\n -c Write to stdout" |
468 | //usage: "\n -f Force" | 468 | //usage: "\n -f Force" |
469 | //usage: "\n -k Keep input files" | 469 | //usage: "\n -k Keep input files" |
@@ -471,7 +471,7 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) | |||
471 | //usage:#define lzma_trivial_usage | 471 | //usage:#define lzma_trivial_usage |
472 | //usage: "-d [-cfk] [FILE]..." | 472 | //usage: "-d [-cfk] [FILE]..." |
473 | //usage:#define lzma_full_usage "\n\n" | 473 | //usage:#define lzma_full_usage "\n\n" |
474 | //usage: "Decompress FILE (or stdin)\n" | 474 | //usage: "Decompress FILEs (or stdin)\n" |
475 | //usage: "\n -d Decompress" | 475 | //usage: "\n -d Decompress" |
476 | //usage: "\n -c Write to stdout" | 476 | //usage: "\n -c Write to stdout" |
477 | //usage: "\n -f Force" | 477 | //usage: "\n -f Force" |
@@ -534,7 +534,7 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv) | |||
534 | //usage:#define unxz_trivial_usage | 534 | //usage:#define unxz_trivial_usage |
535 | //usage: "[-cfk] [FILE]..." | 535 | //usage: "[-cfk] [FILE]..." |
536 | //usage:#define unxz_full_usage "\n\n" | 536 | //usage:#define unxz_full_usage "\n\n" |
537 | //usage: "Decompress FILE (or stdin)\n" | 537 | //usage: "Decompress FILEs (or stdin)\n" |
538 | //usage: "\n -c Write to stdout" | 538 | //usage: "\n -c Write to stdout" |
539 | //usage: "\n -f Force" | 539 | //usage: "\n -f Force" |
540 | //usage: "\n -k Keep input files" | 540 | //usage: "\n -k Keep input files" |
@@ -543,7 +543,7 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv) | |||
543 | //usage:#define xz_trivial_usage | 543 | //usage:#define xz_trivial_usage |
544 | //usage: "-d [-cfk] [FILE]..." | 544 | //usage: "-d [-cfk] [FILE]..." |
545 | //usage:#define xz_full_usage "\n\n" | 545 | //usage:#define xz_full_usage "\n\n" |
546 | //usage: "Decompress FILE (or stdin)\n" | 546 | //usage: "Decompress FILEs (or stdin)\n" |
547 | //usage: "\n -d Decompress" | 547 | //usage: "\n -d Decompress" |
548 | //usage: "\n -c Write to stdout" | 548 | //usage: "\n -c Write to stdout" |
549 | //usage: "\n -f Force" | 549 | //usage: "\n -f Force" |
diff --git a/archival/bzip2.c b/archival/bzip2.c index d0390a92a..ac5db0880 100644 --- a/archival/bzip2.c +++ b/archival/bzip2.c | |||
@@ -50,7 +50,7 @@ | |||
50 | //kbuild:lib-$(CONFIG_BZIP2) += bzip2.o | 50 | //kbuild:lib-$(CONFIG_BZIP2) += bzip2.o |
51 | 51 | ||
52 | //usage:#define bzip2_trivial_usage | 52 | //usage:#define bzip2_trivial_usage |
53 | //usage: "[OPTIONS] [FILE]..." | 53 | //usage: "[-cfk" IF_FEATURE_BZIP2_DECOMPRESS("dt") "123456789] [FILE]..." |
54 | //usage:#define bzip2_full_usage "\n\n" | 54 | //usage:#define bzip2_full_usage "\n\n" |
55 | //usage: "Compress FILEs (or stdin) with bzip2 algorithm\n" | 55 | //usage: "Compress FILEs (or stdin) with bzip2 algorithm\n" |
56 | //usage: "\n -1..9 Compression level" | 56 | //usage: "\n -1..9 Compression level" |
diff --git a/archival/cpio.c b/archival/cpio.c index 94b4b8174..94303389e 100644 --- a/archival/cpio.c +++ b/archival/cpio.c | |||
@@ -68,7 +68,7 @@ | |||
68 | //usage: "\n -H newc Archive format" | 68 | //usage: "\n -H newc Archive format" |
69 | //usage: ) | 69 | //usage: ) |
70 | //usage: "\n -d Make leading directories" | 70 | //usage: "\n -d Make leading directories" |
71 | //usage: "\n -m Preserve mtime" | 71 | //usage: "\n -m Restore mtime" |
72 | //usage: "\n -v Verbose" | 72 | //usage: "\n -v Verbose" |
73 | //usage: "\n -u Overwrite" | 73 | //usage: "\n -u Overwrite" |
74 | //usage: "\n -F FILE Input (-t,-i,-p) or output (-o) file" | 74 | //usage: "\n -F FILE Input (-t,-i,-p) or output (-o) file" |
diff --git a/archival/dpkg.c b/archival/dpkg.c index 61631bd4d..8e1f9431d 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c | |||
@@ -1309,7 +1309,7 @@ postrm abort-install <old_version> | |||
1309 | postrm abort-upgrade <old_version> | 1309 | postrm abort-upgrade <old_version> |
1310 | postrm disappear <overwriter> <version> | 1310 | postrm disappear <overwriter> <version> |
1311 | */ | 1311 | */ |
1312 | static const char *const all_control_files[] = { | 1312 | static const char *const all_control_files[] ALIGN_PTR = { |
1313 | "preinst", "postinst", "prerm", "postrm", | 1313 | "preinst", "postinst", "prerm", "postrm", |
1314 | "list", "md5sums", "shlibs", "conffiles", | 1314 | "list", "md5sums", "shlibs", "conffiles", |
1315 | "config", "templates" | 1315 | "config", "templates" |
diff --git a/archival/dpkg_deb.c b/archival/dpkg_deb.c index c2c4cbbcc..a5a80439d 100644 --- a/archival/dpkg_deb.c +++ b/archival/dpkg_deb.c | |||
@@ -28,7 +28,7 @@ | |||
28 | //usage: "\n -f Print control fields" | 28 | //usage: "\n -f Print control fields" |
29 | //usage: "\n -e Extract control files to DIR (default: ./DEBIAN)" | 29 | //usage: "\n -e Extract control files to DIR (default: ./DEBIAN)" |
30 | //usage: "\n -x Extract files to DIR (no default)" | 30 | //usage: "\n -x Extract files to DIR (no default)" |
31 | //usage: "\n -X Verbose -x" | 31 | //usage: "\n -X Verbose extract" |
32 | //usage: | 32 | //usage: |
33 | //usage:#define dpkg_deb_example_usage | 33 | //usage:#define dpkg_deb_example_usage |
34 | //usage: "$ dpkg-deb -X ./busybox_0.48-1_i386.deb /tmp\n" | 34 | //usage: "$ dpkg-deb -X ./busybox_0.48-1_i386.deb /tmp\n" |
diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index 92d6d8251..062fd0f54 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c | |||
@@ -459,7 +459,7 @@ int mainGtU(EState* state, | |||
459 | * usually small, typically <= 20. | 459 | * usually small, typically <= 20. |
460 | */ | 460 | */ |
461 | static | 461 | static |
462 | const uint32_t incs[14] = { | 462 | const uint32_t incs[14] ALIGN4 = { |
463 | 1, 4, 13, 40, 121, 364, 1093, 3280, | 463 | 1, 4, 13, 40, 121, 364, 1093, 3280, |
464 | 9841, 29524, 88573, 265720, | 464 | 9841, 29524, 88573, 265720, |
465 | 797161, 2391484 | 465 | 797161, 2391484 |
diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c index 3142405a3..049c2c156 100644 --- a/archival/libarchive/data_extract_all.c +++ b/archival/libarchive/data_extract_all.c | |||
@@ -159,6 +159,10 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |||
159 | break; | 159 | break; |
160 | } | 160 | } |
161 | case S_IFDIR: | 161 | case S_IFDIR: |
162 | //TODO: this causes problems if tarball contains a r-xr-xr-x directory: | ||
163 | // we create this directory, and then fail to create files inside it | ||
164 | // (if tar xf isn't run as root). | ||
165 | // GNU tar works around this by chmod-ing directories *after* all files are extracted. | ||
162 | res = mkdir(dst_name, file_header->mode); | 166 | res = mkdir(dst_name, file_header->mode); |
163 | if ((res != 0) | 167 | if ((res != 0) |
164 | && (errno != EISDIR) /* btw, Linux doesn't return this */ | 168 | && (errno != EISDIR) /* btw, Linux doesn't return this */ |
diff --git a/archival/libarchive/data_extract_to_command.c b/archival/libarchive/data_extract_to_command.c index 0fcabb4a9..f8b2ff8d2 100644 --- a/archival/libarchive/data_extract_to_command.c +++ b/archival/libarchive/data_extract_to_command.c | |||
@@ -20,7 +20,7 @@ enum { | |||
20 | TAR_MAX, | 20 | TAR_MAX, |
21 | }; | 21 | }; |
22 | 22 | ||
23 | static const char *const tar_var[] = { | 23 | static const char *const tar_var[] ALIGN_PTR = { |
24 | // "FILETYPE", | 24 | // "FILETYPE", |
25 | "MODE", | 25 | "MODE", |
26 | "FILENAME", | 26 | "FILENAME", |
diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c index c0332d414..b2a3eb1c2 100644 --- a/archival/libarchive/decompress_gunzip.c +++ b/archival/libarchive/decompress_gunzip.c | |||
@@ -194,14 +194,14 @@ struct cp_ext { | |||
194 | }; | 194 | }; |
195 | /* Copy lengths and extra bits for literal codes 257..285 */ | 195 | /* Copy lengths and extra bits for literal codes 257..285 */ |
196 | /* note: see note #13 above about the 258 in this list. */ | 196 | /* note: see note #13 above about the 258 in this list. */ |
197 | static const struct cp_ext lit = { | 197 | static const struct cp_ext lit ALIGN2 = { |
198 | /*257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 */ | 198 | /*257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 */ |
199 | /*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 */ | 199 | /*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 */ |
200 | { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 }, | 200 | { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 }, |
201 | { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99 } /* 99 == invalid */ | 201 | { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99 } /* 99 == invalid */ |
202 | }; | 202 | }; |
203 | /* Copy offsets and extra bits for distance codes 0..29 */ | 203 | /* Copy offsets and extra bits for distance codes 0..29 */ |
204 | static const struct cp_ext dist = { | 204 | static const struct cp_ext dist ALIGN2 = { |
205 | /*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 */ | 205 | /*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 */ |
206 | { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 }, | 206 | { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 }, |
207 | { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 } | 207 | { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 } |
diff --git a/archival/libarchive/get_header_ar.c b/archival/libarchive/get_header_ar.c index b6ecd596c..3a19d6ff7 100644 --- a/archival/libarchive/get_header_ar.c +++ b/archival/libarchive/get_header_ar.c | |||
@@ -6,7 +6,7 @@ | |||
6 | */ | 6 | */ |
7 | #include "libbb.h" | 7 | #include "libbb.h" |
8 | #include "bb_archive.h" | 8 | #include "bb_archive.h" |
9 | #include "ar.h" | 9 | #include "ar_.h" |
10 | 10 | ||
11 | /* WARNING: Clobbers str[len], so fields must be read in reverse order! */ | 11 | /* WARNING: Clobbers str[len], so fields must be read in reverse order! */ |
12 | static unsigned read_num(char *str, int base, int len) | 12 | static unsigned read_num(char *str, int base, int len) |
diff --git a/archival/libarchive/unpack_ar_archive.c b/archival/libarchive/unpack_ar_archive.c index 584c18ce8..125d424c9 100644 --- a/archival/libarchive/unpack_ar_archive.c +++ b/archival/libarchive/unpack_ar_archive.c | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | #include "libbb.h" | 5 | #include "libbb.h" |
6 | #include "bb_archive.h" | 6 | #include "bb_archive.h" |
7 | #include "ar.h" | 7 | #include "ar_.h" |
8 | 8 | ||
9 | void FAST_FUNC unpack_ar_archive(archive_handle_t *ar_archive) | 9 | void FAST_FUNC unpack_ar_archive(archive_handle_t *ar_archive) |
10 | { | 10 | { |
diff --git a/archival/rpm.c b/archival/rpm.c index 0d8f641b9..63d13d0e1 100644 --- a/archival/rpm.c +++ b/archival/rpm.c | |||
@@ -83,7 +83,9 @@ struct globals { | |||
83 | void *map; | 83 | void *map; |
84 | rpm_index *mytags; | 84 | rpm_index *mytags; |
85 | int tagcount; | 85 | int tagcount; |
86 | unsigned mapsize, pagesize; | 86 | unsigned mapsize; |
87 | IF_VARIABLE_ARCH_PAGESIZE(unsigned pagesize;) | ||
88 | #define G_pagesize cached_pagesize(G.pagesize) | ||
87 | } FIX_ALIASING; | 89 | } FIX_ALIASING; |
88 | #define G (*(struct globals*)bb_common_bufsiz1) | 90 | #define G (*(struct globals*)bb_common_bufsiz1) |
89 | #define INIT_G() do { setup_common_bufsiz(); } while (0) | 91 | #define INIT_G() do { setup_common_bufsiz(); } while (0) |
@@ -142,11 +144,11 @@ static int rpm_gettags(const char *filename) | |||
142 | 144 | ||
143 | #if !ENABLE_PLATFORM_MINGW32 | 145 | #if !ENABLE_PLATFORM_MINGW32 |
144 | /* Map the store */ | 146 | /* Map the store */ |
145 | storepos = (storepos + G.pagesize) & -(int)G.pagesize; | 147 | storepos = (storepos + G_pagesize) & -(int)G_pagesize; |
146 | /* remember size for munmap */ | 148 | /* remember size for munmap */ |
147 | G.mapsize = storepos; | 149 | G.mapsize = storepos; |
148 | /* some NOMMU systems prefer MAP_PRIVATE over MAP_SHARED */ | 150 | /* some NOMMU systems prefer MAP_PRIVATE over MAP_SHARED */ |
149 | G.map = mmap(0, storepos, PROT_READ, MAP_PRIVATE, fd, 0); | 151 | G.map = mmap_read(fd, storepos); |
150 | if (G.map == MAP_FAILED) | 152 | if (G.map == MAP_FAILED) |
151 | bb_perror_msg_and_die("mmap '%s'", filename); | 153 | bb_perror_msg_and_die("mmap '%s'", filename); |
152 | #else | 154 | #else |
@@ -368,7 +370,7 @@ int rpm_main(int argc, char **argv) | |||
368 | int opt, func = 0; | 370 | int opt, func = 0; |
369 | 371 | ||
370 | INIT_G(); | 372 | INIT_G(); |
371 | G.pagesize = getpagesize(); | 373 | INIT_PAGESIZE(G.pagesize); |
372 | 374 | ||
373 | while ((opt = getopt(argc, argv, "iqpldc")) != -1) { | 375 | while ((opt = getopt(argc, argv, "iqpldc")) != -1) { |
374 | switch (opt) { | 376 | switch (opt) { |
@@ -535,7 +537,7 @@ int rpm2cpio_main(int argc UNUSED_PARAM, char **argv) | |||
535 | int rpm_fd; | 537 | int rpm_fd; |
536 | 538 | ||
537 | INIT_G(); | 539 | INIT_G(); |
538 | G.pagesize = getpagesize(); | 540 | INIT_PAGESIZE(G.pagesize); |
539 | 541 | ||
540 | rpm_fd = rpm_gettags(argv[1]); | 542 | rpm_fd = rpm_gettags(argv[1]); |
541 | 543 | ||
diff --git a/archival/tar.c b/archival/tar.c index 1796d4c60..6c1591bdc 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -794,7 +794,7 @@ static llist_t *append_file_list_to_list(llist_t *list) | |||
794 | //usage: IF_FEATURE_TAR_NOPRESERVE_TIME("m") | 794 | //usage: IF_FEATURE_TAR_NOPRESERVE_TIME("m") |
795 | //usage: "vokO] " | 795 | //usage: "vokO] " |
796 | //usage: "[-f TARFILE] [-C DIR] " | 796 | //usage: "[-f TARFILE] [-C DIR] " |
797 | //usage: IF_FEATURE_TAR_FROM("[-T FILE] [-X FILE] "IF_FEATURE_TAR_LONG_OPTIONS("[--exclude PATTERN]... ")) | 797 | //usage: IF_FEATURE_TAR_FROM("[-T FILE] [-X FILE] "IF_FEATURE_TAR_LONG_OPTIONS("[OPTION]... ")) |
798 | //usage: "[FILE]..." | 798 | //usage: "[FILE]..." |
799 | //usage:#define tar_full_usage "\n\n" | 799 | //usage:#define tar_full_usage "\n\n" |
800 | //usage: IF_FEATURE_TAR_CREATE("Create, extract, ") | 800 | //usage: IF_FEATURE_TAR_CREATE("Create, extract, ") |
@@ -828,6 +828,11 @@ static llist_t *append_file_list_to_list(llist_t *list) | |||
828 | //usage: IF_FEATURE_SEAMLESS_BZ2( | 828 | //usage: IF_FEATURE_SEAMLESS_BZ2( |
829 | //usage: "\n -j (De)compress using bzip2" | 829 | //usage: "\n -j (De)compress using bzip2" |
830 | //usage: ) | 830 | //usage: ) |
831 | //usage: IF_FEATURE_SEAMLESS_LZMA( | ||
832 | //usage: IF_FEATURE_TAR_LONG_OPTIONS( | ||
833 | //usage: "\n --lzma (De)compress using lzma" | ||
834 | //usage: ) | ||
835 | //usage: ) | ||
831 | //usage: "\n -a (De)compress based on extension" | 836 | //usage: "\n -a (De)compress based on extension" |
832 | //usage: IF_FEATURE_TAR_CREATE( | 837 | //usage: IF_FEATURE_TAR_CREATE( |
833 | //usage: "\n -h Follow symlinks" | 838 | //usage: "\n -h Follow symlinks" |
@@ -839,21 +844,21 @@ static llist_t *append_file_list_to_list(llist_t *list) | |||
839 | //usage: "\n --exclude PATTERN Glob pattern to exclude" | 844 | //usage: "\n --exclude PATTERN Glob pattern to exclude" |
840 | //usage: ) | 845 | //usage: ) |
841 | //usage: ) | 846 | //usage: ) |
847 | //usage: IF_FEATURE_TAR_LONG_OPTIONS( | ||
848 | //usage: "\n --overwrite Replace existing files" | ||
849 | //usage: "\n --strip-components NUM NUM of leading components to strip" | ||
850 | //usage: "\n --no-recursion Don't descend in directories" | ||
851 | //usage: "\n --numeric-owner Use numeric user:group" | ||
852 | //usage: "\n --no-same-permissions Don't restore access permissions" | ||
853 | //usage: IF_FEATURE_TAR_TO_COMMAND( | ||
854 | //usage: "\n --to-command COMMAND Pipe files to COMMAND" | ||
855 | //usage: ) | ||
856 | //usage: ) | ||
842 | //usage: | 857 | //usage: |
843 | //usage:#define tar_example_usage | 858 | //usage:#define tar_example_usage |
844 | //usage: "$ zcat /tmp/tarball.tar.gz | tar -xf -\n" | 859 | //usage: "$ zcat /tmp/tarball.tar.gz | tar -xf -\n" |
845 | //usage: "$ tar -cf /tmp/tarball.tar /usr/local\n" | 860 | //usage: "$ tar -cf /tmp/tarball.tar /usr/local\n" |
846 | 861 | ||
847 | // Supported but aren't in --help: | ||
848 | // lzma | ||
849 | // no-recursion | ||
850 | // numeric-owner | ||
851 | // no-same-permissions | ||
852 | // overwrite | ||
853 | //IF_FEATURE_TAR_TO_COMMAND( | ||
854 | // to-command | ||
855 | //) | ||
856 | |||
857 | enum { | 862 | enum { |
858 | OPTBIT_KEEP_OLD = 8, | 863 | OPTBIT_KEEP_OLD = 8, |
859 | IF_FEATURE_TAR_CREATE( OPTBIT_CREATE ,) | 864 | IF_FEATURE_TAR_CREATE( OPTBIT_CREATE ,) |
diff --git a/configs/mingw32_defconfig b/configs/mingw32_defconfig index d3a974706..f95f71607 100644 --- a/configs/mingw32_defconfig +++ b/configs/mingw32_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Busybox version: 1.33.0.git | 3 | # Busybox version: 1.34.0.git |
4 | # Thu Nov 12 08:15:02 2020 | 4 | # Thu Jan 14 12:07:38 2021 |
5 | # | 5 | # |
6 | CONFIG_HAVE_DOT_CONFIG=y | 6 | CONFIG_HAVE_DOT_CONFIG=y |
7 | # CONFIG_PLATFORM_POSIX is not set | 7 | # CONFIG_PLATFORM_POSIX is not set |
@@ -72,6 +72,7 @@ CONFIG_EXTRA_LDFLAGS="" | |||
72 | CONFIG_EXTRA_LDLIBS="" | 72 | CONFIG_EXTRA_LDLIBS="" |
73 | CONFIG_USE_PORTABLE_CODE=y | 73 | CONFIG_USE_PORTABLE_CODE=y |
74 | CONFIG_STACK_OPTIMIZATION_386=y | 74 | CONFIG_STACK_OPTIMIZATION_386=y |
75 | CONFIG_STATIC_LIBGCC=y | ||
75 | 76 | ||
76 | # | 77 | # |
77 | # Installation Options ("make install" behavior) | 78 | # Installation Options ("make install" behavior) |
@@ -348,6 +349,7 @@ CONFIG_UNIQ=y | |||
348 | CONFIG_UNLINK=y | 349 | CONFIG_UNLINK=y |
349 | CONFIG_USLEEP=y | 350 | CONFIG_USLEEP=y |
350 | CONFIG_UUDECODE=y | 351 | CONFIG_UUDECODE=y |
352 | CONFIG_BASE32=y | ||
351 | CONFIG_BASE64=y | 353 | CONFIG_BASE64=y |
352 | CONFIG_UUENCODE=y | 354 | CONFIG_UUENCODE=y |
353 | CONFIG_WC=y | 355 | CONFIG_WC=y |
@@ -720,6 +722,7 @@ CONFIG_REV=y | |||
720 | # CONFIG_FEATURE_VOLUMEID_BCACHE is not set | 722 | # CONFIG_FEATURE_VOLUMEID_BCACHE is not set |
721 | # CONFIG_FEATURE_VOLUMEID_BTRFS is not set | 723 | # CONFIG_FEATURE_VOLUMEID_BTRFS is not set |
722 | # CONFIG_FEATURE_VOLUMEID_CRAMFS is not set | 724 | # CONFIG_FEATURE_VOLUMEID_CRAMFS is not set |
725 | # CONFIG_FEATURE_VOLUMEID_EROFS is not set | ||
723 | # CONFIG_FEATURE_VOLUMEID_EXFAT is not set | 726 | # CONFIG_FEATURE_VOLUMEID_EXFAT is not set |
724 | # CONFIG_FEATURE_VOLUMEID_EXT is not set | 727 | # CONFIG_FEATURE_VOLUMEID_EXT is not set |
725 | # CONFIG_FEATURE_VOLUMEID_F2FS is not set | 728 | # CONFIG_FEATURE_VOLUMEID_F2FS is not set |
@@ -1002,6 +1005,7 @@ CONFIG_UDHCPC_DEFAULT_SCRIPT="" | |||
1002 | # CONFIG_FEATURE_UDHCPC6_RFC4704 is not set | 1005 | # CONFIG_FEATURE_UDHCPC6_RFC4704 is not set |
1003 | # CONFIG_FEATURE_UDHCPC6_RFC4833 is not set | 1006 | # CONFIG_FEATURE_UDHCPC6_RFC4833 is not set |
1004 | # CONFIG_FEATURE_UDHCPC6_RFC5970 is not set | 1007 | # CONFIG_FEATURE_UDHCPC6_RFC5970 is not set |
1008 | CONFIG_UDHCPC_DEFAULT_INTERFACE="" | ||
1005 | # CONFIG_FEATURE_UDHCP_PORT is not set | 1009 | # CONFIG_FEATURE_UDHCP_PORT is not set |
1006 | CONFIG_UDHCP_DEBUG=0 | 1010 | CONFIG_UDHCP_DEBUG=0 |
1007 | CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=0 | 1011 | CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=0 |
diff --git a/configs/mingw64_defconfig b/configs/mingw64_defconfig index da2419c62..cf0e3ec8e 100644 --- a/configs/mingw64_defconfig +++ b/configs/mingw64_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Busybox version: 1.33.0.git | 3 | # Busybox version: 1.34.0.git |
4 | # Thu Nov 12 08:15:02 2020 | 4 | # Thu Jan 14 12:07:38 2021 |
5 | # | 5 | # |
6 | CONFIG_HAVE_DOT_CONFIG=y | 6 | CONFIG_HAVE_DOT_CONFIG=y |
7 | # CONFIG_PLATFORM_POSIX is not set | 7 | # CONFIG_PLATFORM_POSIX is not set |
@@ -72,6 +72,7 @@ CONFIG_EXTRA_LDFLAGS="" | |||
72 | CONFIG_EXTRA_LDLIBS="" | 72 | CONFIG_EXTRA_LDLIBS="" |
73 | CONFIG_USE_PORTABLE_CODE=y | 73 | CONFIG_USE_PORTABLE_CODE=y |
74 | CONFIG_STACK_OPTIMIZATION_386=y | 74 | CONFIG_STACK_OPTIMIZATION_386=y |
75 | CONFIG_STATIC_LIBGCC=y | ||
75 | 76 | ||
76 | # | 77 | # |
77 | # Installation Options ("make install" behavior) | 78 | # Installation Options ("make install" behavior) |
@@ -348,6 +349,7 @@ CONFIG_UNIQ=y | |||
348 | CONFIG_UNLINK=y | 349 | CONFIG_UNLINK=y |
349 | CONFIG_USLEEP=y | 350 | CONFIG_USLEEP=y |
350 | CONFIG_UUDECODE=y | 351 | CONFIG_UUDECODE=y |
352 | CONFIG_BASE32=y | ||
351 | CONFIG_BASE64=y | 353 | CONFIG_BASE64=y |
352 | CONFIG_UUENCODE=y | 354 | CONFIG_UUENCODE=y |
353 | CONFIG_WC=y | 355 | CONFIG_WC=y |
@@ -720,6 +722,7 @@ CONFIG_REV=y | |||
720 | # CONFIG_FEATURE_VOLUMEID_BCACHE is not set | 722 | # CONFIG_FEATURE_VOLUMEID_BCACHE is not set |
721 | # CONFIG_FEATURE_VOLUMEID_BTRFS is not set | 723 | # CONFIG_FEATURE_VOLUMEID_BTRFS is not set |
722 | # CONFIG_FEATURE_VOLUMEID_CRAMFS is not set | 724 | # CONFIG_FEATURE_VOLUMEID_CRAMFS is not set |
725 | # CONFIG_FEATURE_VOLUMEID_EROFS is not set | ||
723 | # CONFIG_FEATURE_VOLUMEID_EXFAT is not set | 726 | # CONFIG_FEATURE_VOLUMEID_EXFAT is not set |
724 | # CONFIG_FEATURE_VOLUMEID_EXT is not set | 727 | # CONFIG_FEATURE_VOLUMEID_EXT is not set |
725 | # CONFIG_FEATURE_VOLUMEID_F2FS is not set | 728 | # CONFIG_FEATURE_VOLUMEID_F2FS is not set |
@@ -1002,6 +1005,7 @@ CONFIG_UDHCPC_DEFAULT_SCRIPT="" | |||
1002 | # CONFIG_FEATURE_UDHCPC6_RFC4704 is not set | 1005 | # CONFIG_FEATURE_UDHCPC6_RFC4704 is not set |
1003 | # CONFIG_FEATURE_UDHCPC6_RFC4833 is not set | 1006 | # CONFIG_FEATURE_UDHCPC6_RFC4833 is not set |
1004 | # CONFIG_FEATURE_UDHCPC6_RFC5970 is not set | 1007 | # CONFIG_FEATURE_UDHCPC6_RFC5970 is not set |
1008 | CONFIG_UDHCPC_DEFAULT_INTERFACE="" | ||
1005 | # CONFIG_FEATURE_UDHCP_PORT is not set | 1009 | # CONFIG_FEATURE_UDHCP_PORT is not set |
1006 | CONFIG_UDHCP_DEBUG=0 | 1010 | CONFIG_UDHCP_DEBUG=0 |
1007 | CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=0 | 1011 | CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=0 |
diff --git a/coreutils/cp.c b/coreutils/cp.c index cfeb19fc4..9b9b8f7bf 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c | |||
@@ -38,7 +38,7 @@ | |||
38 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/cp.html */ | 38 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/cp.html */ |
39 | 39 | ||
40 | //usage:#define cp_trivial_usage | 40 | //usage:#define cp_trivial_usage |
41 | //usage: "[OPTIONS] SOURCE... DEST" | 41 | //usage: "[-arPLHpfilsTu] SOURCE... DEST" |
42 | //usage:#define cp_full_usage "\n\n" | 42 | //usage:#define cp_full_usage "\n\n" |
43 | //usage: "Copy SOURCE(s) to DEST\n" | 43 | //usage: "Copy SOURCE(s) to DEST\n" |
44 | //usage: "\n -a Same as -dpR" | 44 | //usage: "\n -a Same as -dpR" |
diff --git a/coreutils/date.c b/coreutils/date.c index 1a3ae506c..d64ff94b9 100644 --- a/coreutils/date.c +++ b/coreutils/date.c | |||
@@ -93,40 +93,27 @@ | |||
93 | */ | 93 | */ |
94 | 94 | ||
95 | //usage:#define date_trivial_usage | 95 | //usage:#define date_trivial_usage |
96 | //usage: "[OPTIONS] [+FMT] [TIME]" | 96 | //usage: "[OPTIONS] [+FMT] [[-s] TIME]" |
97 | //usage:#define date_full_usage "\n\n" | 97 | //usage:#define date_full_usage "\n\n" |
98 | //usage: "Display time (using +FMT), or set time\n" | 98 | //usage: "Display time (using +FMT), or set time\n" |
99 | //usage: IF_NOT_LONG_OPTS( | ||
100 | //usage: IF_NOT_PLATFORM_MINGW32( | ||
101 | //usage: "\n [-s] TIME Set time to TIME" | ||
102 | //usage: ) | ||
103 | //usage: "\n -u Work in UTC (don't convert to local time)" | 99 | //usage: "\n -u Work in UTC (don't convert to local time)" |
104 | //usage: "\n -R Output RFC-2822 compliant date string" | 100 | //usage: IF_NOT_PLATFORM_MINGW32( |
105 | //usage: ) IF_LONG_OPTS( | 101 | //usage: "\n [-s] TIME Set time to TIME" |
106 | //usage: IF_NOT_PLATFORM_MINGW32( | ||
107 | //usage: "\n [-s,--set] TIME Set time to TIME" | ||
108 | //usage: ) | ||
109 | //usage: "\n -u,--utc Work in UTC (don't convert to local time)" | ||
110 | //usage: "\n -R,--rfc-2822 Output RFC-2822 compliant date string" | ||
111 | //usage: ) | 102 | //usage: ) |
103 | //usage: "\n -d TIME Display TIME, not 'now'" | ||
112 | //usage: IF_FEATURE_DATE_ISOFMT( | 104 | //usage: IF_FEATURE_DATE_ISOFMT( |
113 | //usage: "\n -I[SPEC] Output ISO-8601 compliant date string" | 105 | //usage: "\n -D FMT FMT (strptime format) for -s/-d TIME conversion" |
114 | //usage: "\n SPEC='date' (default) for date only," | 106 | ////////^^^^^^^^^^^^^^^^^^^^^^ busybox invention, not compat |
115 | //usage: "\n 'hours', 'minutes', or 'seconds' for date and" | ||
116 | //usage: "\n time to the indicated precision" | ||
117 | //usage: ) | 107 | //usage: ) |
118 | //usage: IF_NOT_LONG_OPTS( | ||
119 | //usage: "\n -r FILE Display last modification time of FILE" | 108 | //usage: "\n -r FILE Display last modification time of FILE" |
120 | //usage: "\n -d TIME Display TIME, not 'now'" | 109 | //usage: "\n -R Output RFC-2822 date" |
121 | //usage: ) IF_LONG_OPTS( | ||
122 | //usage: "\n -r,--reference FILE Display last modification time of FILE" | ||
123 | //usage: "\n -d,--date TIME Display TIME, not 'now'" | ||
124 | //usage: ) | ||
125 | //usage: IF_FEATURE_DATE_ISOFMT( | 110 | //usage: IF_FEATURE_DATE_ISOFMT( |
126 | //usage: "\n -D FMT Use FMT (strptime format) for -d TIME conversion" | 111 | //usage: "\n -I[SPEC] Output ISO-8601 date" |
112 | //usage: "\n SPEC=date (default), hours, minutes, seconds or ns" | ||
127 | //usage: ) | 113 | //usage: ) |
128 | //usage: "\n" | 114 | //usage: "\n" |
129 | //usage: "\nRecognized TIME formats:" | 115 | //usage: "\nRecognized TIME formats:" |
116 | //usage: "\n @seconds_since_1970" | ||
130 | //usage: "\n hh:mm[:ss]" | 117 | //usage: "\n hh:mm[:ss]" |
131 | //usage: "\n [YYYY.]MM.DD-hh:mm[:ss]" | 118 | //usage: "\n [YYYY.]MM.DD-hh:mm[:ss]" |
132 | //usage: "\n YYYY-MM-DD hh:mm[:ss]" | 119 | //usage: "\n YYYY-MM-DD hh:mm[:ss]" |
@@ -152,15 +139,15 @@ enum { | |||
152 | OPT_UTC = (1 << 2), /* u */ | 139 | OPT_UTC = (1 << 2), /* u */ |
153 | OPT_DATE = (1 << 3), /* d */ | 140 | OPT_DATE = (1 << 3), /* d */ |
154 | OPT_REFERENCE = (1 << 4), /* r */ | 141 | OPT_REFERENCE = (1 << 4), /* r */ |
155 | OPT_TIMESPEC = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* I */ | 142 | OPT_ISO8601 = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* I */ |
156 | OPT_HINT = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* D */ | 143 | OPT_STR2DT = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* D */ |
157 | #else | 144 | #else |
158 | OPT_SET = (0), /* s */ | 145 | OPT_SET = (0), /* s */ |
159 | OPT_UTC = (1 << 1), /* u */ | 146 | OPT_UTC = (1 << 1), /* u */ |
160 | OPT_DATE = (1 << 2), /* d */ | 147 | OPT_DATE = (1 << 2), /* d */ |
161 | OPT_REFERENCE = (1 << 3), /* r */ | 148 | OPT_REFERENCE = (1 << 3), /* r */ |
162 | OPT_TIMESPEC = (1 << 4) * ENABLE_FEATURE_DATE_ISOFMT, /* I */ | 149 | OPT_ISO8601 = (1 << 4) * ENABLE_FEATURE_DATE_ISOFMT, /* I */ |
163 | OPT_HINT = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* D */ | 150 | OPT_STR2DT = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* D */ |
164 | #endif | 151 | #endif |
165 | }; | 152 | }; |
166 | 153 | ||
@@ -185,12 +172,6 @@ static const char date_longopts[] ALIGN1 = | |||
185 | * - after xasprintf we use other xfuncs | 172 | * - after xasprintf we use other xfuncs |
186 | */ | 173 | */ |
187 | 174 | ||
188 | static void maybe_set_utc(int opt) | ||
189 | { | ||
190 | if (opt & OPT_UTC) | ||
191 | putenv((char*)"TZ=UTC0"); | ||
192 | } | ||
193 | |||
194 | int date_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 175 | int date_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
195 | int date_main(int argc UNUSED_PARAM, char **argv) | 176 | int date_main(int argc UNUSED_PARAM, char **argv) |
196 | { | 177 | { |
@@ -198,7 +179,7 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
198 | struct tm tm_time; | 179 | struct tm tm_time; |
199 | char buf_fmt_dt2str[64]; | 180 | char buf_fmt_dt2str[64]; |
200 | unsigned opt; | 181 | unsigned opt; |
201 | int ifmt = -1; | 182 | int isofmt = -1; |
202 | char *date_str; | 183 | char *date_str; |
203 | char *fmt_dt2str; | 184 | char *fmt_dt2str; |
204 | char *fmt_str2dt; | 185 | char *fmt_str2dt; |
@@ -229,15 +210,16 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
229 | ); | 210 | ); |
230 | argv += optind; | 211 | argv += optind; |
231 | 212 | ||
232 | maybe_set_utc(opt); | 213 | if (opt & OPT_UTC) |
214 | putenv((char*)"TZ=UTC0"); | ||
233 | 215 | ||
234 | if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_TIMESPEC)) { | 216 | if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_ISO8601)) { |
235 | ifmt = 0; /* default is date */ | 217 | isofmt = 0; /* default is date */ |
236 | if (isofmt_arg) { | 218 | if (isofmt_arg) { |
237 | static const char isoformats[] ALIGN1 = | 219 | static const char isoformats[] ALIGN1 = |
238 | "date\0""hours\0""minutes\0""seconds\0"; /* ns? */ | 220 | "date\0""hours\0""minutes\0""seconds\0ns\0"; |
239 | ifmt = index_in_substrings(isoformats, isofmt_arg); | 221 | isofmt = index_in_substrings(isoformats, isofmt_arg); |
240 | if (ifmt < 0) | 222 | if (isofmt < 0) |
241 | bb_show_usage(); | 223 | bb_show_usage(); |
242 | } | 224 | } |
243 | } | 225 | } |
@@ -247,7 +229,7 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
247 | fmt_dt2str = &argv[0][1]; /* skip over the '+' */ | 229 | fmt_dt2str = &argv[0][1]; /* skip over the '+' */ |
248 | argv++; | 230 | argv++; |
249 | } | 231 | } |
250 | if (!(opt & (OPT_SET | OPT_DATE))) { | 232 | if (!(opt & (OPT_SET | OPT_DATE))) { /* neither -s TIME nor -d TIME? */ |
251 | opt |= OPT_SET; | 233 | opt |= OPT_SET; |
252 | date_str = argv[0]; /* can be NULL */ | 234 | date_str = argv[0]; /* can be NULL */ |
253 | if (date_str) { | 235 | if (date_str) { |
@@ -315,7 +297,7 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
315 | tm_time.tm_hour = 0; | 297 | tm_time.tm_hour = 0; |
316 | 298 | ||
317 | /* Process any date input to UNIX time since 1 Jan 1970 */ | 299 | /* Process any date input to UNIX time since 1 Jan 1970 */ |
318 | if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_HINT)) { | 300 | if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_STR2DT)) { |
319 | if (strptime(date_str, fmt_str2dt, &tm_time) == NULL) | 301 | if (strptime(date_str, fmt_str2dt, &tm_time) == NULL) |
320 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); | 302 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); |
321 | } else { | 303 | } else { |
@@ -341,24 +323,34 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
341 | if (fmt_dt2str == NULL) { | 323 | if (fmt_dt2str == NULL) { |
342 | int i; | 324 | int i; |
343 | fmt_dt2str = buf_fmt_dt2str; | 325 | fmt_dt2str = buf_fmt_dt2str; |
344 | if (ENABLE_FEATURE_DATE_ISOFMT && ifmt >= 0) { | 326 | if (ENABLE_FEATURE_DATE_ISOFMT && isofmt >= 0) { |
345 | /* -I[SPEC]: 0:date 1:hours 2:minutes 3:seconds */ | 327 | /* -I[SPEC]: 0:date 1:hours 2:minutes 3:seconds 4:ns*/ |
346 | strcpy(fmt_dt2str, "%Y-%m-%dT%H:%M:%S"); | 328 | strcpy(fmt_dt2str, "%Y-%m-%dT%H:%M:%S"); |
347 | i = 8 + 3 * ifmt; | 329 | i = 8 + 3 * isofmt; |
348 | if (ifmt != 0) { | 330 | if (isofmt != 0) { |
349 | /* TODO: if (ifmt==4) i += sprintf(&fmt_dt2str[i], ",%09u", nanoseconds); */ | 331 | int n; |
350 | format_utc: | 332 | if (isofmt == 4) { |
351 | fmt_dt2str[i++] = '%'; | 333 | i -= 3; |
352 | fmt_dt2str[i++] = (opt & OPT_UTC) ? 'Z' : 'z'; | 334 | i += sprintf(&fmt_dt2str[i], ",%09u", (unsigned)ts.tv_nsec); |
335 | } | ||
336 | /* %z prints "+hhmm" timezone, but coreutils-8.30 prints "+hh:mm"! */ | ||
337 | /* ...therefore this atrocity: */ | ||
338 | n = strftime(&fmt_dt2str[i], 8, "%z", &tm_time); | ||
339 | i += n; | ||
340 | if (n == 5 && (fmt_dt2str[i-5] == '+' || fmt_dt2str[i-5] == '-')) { | ||
341 | /* "mm" -> ":mm" */ | ||
342 | fmt_dt2str[i ] = fmt_dt2str[i - 1]; | ||
343 | fmt_dt2str[i - 1] = fmt_dt2str[i - 2]; | ||
344 | fmt_dt2str[i - 2] = ':'; | ||
345 | i++; | ||
346 | } | ||
353 | } | 347 | } |
354 | fmt_dt2str[i] = '\0'; | 348 | fmt_dt2str[i] = '\0'; |
355 | } else if (opt & OPT_RFC2822) { | 349 | } else if (opt & OPT_RFC2822) { |
356 | /* -R. undo busybox.c setlocale */ | 350 | /* -R. undo busybox.c setlocale */ |
357 | if (ENABLE_LOCALE_SUPPORT) | 351 | if (ENABLE_LOCALE_SUPPORT) |
358 | setlocale(LC_TIME, "C"); | 352 | setlocale(LC_TIME, "C"); |
359 | strcpy(fmt_dt2str, "%a, %d %b %Y %H:%M:%S "); | 353 | fmt_dt2str = (char*)"%a, %d %b %Y %H:%M:%S %z"; |
360 | i = sizeof("%a, %d %b %Y %H:%M:%S ")-1; | ||
361 | goto format_utc; | ||
362 | } else { /* default case */ | 354 | } else { /* default case */ |
363 | fmt_dt2str = (char*)"%a %b %e %H:%M:%S %Z %Y"; | 355 | fmt_dt2str = (char*)"%a %b %e %H:%M:%S %Z %Y"; |
364 | } | 356 | } |
@@ -410,10 +402,6 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
410 | /* With no format string, just print a blank line */ | 402 | /* With no format string, just print a blank line */ |
411 | date_buf[0] = '\0'; | 403 | date_buf[0] = '\0'; |
412 | } else { | 404 | } else { |
413 | /* Handle special conversions */ | ||
414 | if (is_prefixed_with(fmt_dt2str, "%f")) { | ||
415 | fmt_dt2str = (char*)"%Y.%m.%d-%H:%M:%S"; | ||
416 | } | ||
417 | /* Generate output string */ | 405 | /* Generate output string */ |
418 | strftime(date_buf, COMMON_BUFSIZE, fmt_dt2str, &tm_time); | 406 | strftime(date_buf, COMMON_BUFSIZE, fmt_dt2str, &tm_time); |
419 | } | 407 | } |
diff --git a/coreutils/dd.c b/coreutils/dd.c index 042355e24..c150ef5bc 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c | |||
@@ -59,7 +59,7 @@ | |||
59 | //usage: "[if=FILE] [of=FILE] [" IF_FEATURE_DD_IBS_OBS("ibs=N obs=N/") "bs=N] [count=N] [skip=N] [seek=N]\n" | 59 | //usage: "[if=FILE] [of=FILE] [" IF_FEATURE_DD_IBS_OBS("ibs=N obs=N/") "bs=N] [count=N] [skip=N] [seek=N]\n" |
60 | //usage: IF_FEATURE_DD_IBS_OBS( | 60 | //usage: IF_FEATURE_DD_IBS_OBS( |
61 | //usage: " [conv=notrunc|noerror|sync|fsync]\n" | 61 | //usage: " [conv=notrunc|noerror|sync|fsync]\n" |
62 | //usage: " [iflag=skip_bytes|fullblock] [oflag=seek_bytes|append]" | 62 | //usage: " [iflag=skip_bytes|fullblock|direct] [oflag=seek_bytes|append|direct]" |
63 | //usage: ) | 63 | //usage: ) |
64 | //usage:#define dd_full_usage "\n\n" | 64 | //usage:#define dd_full_usage "\n\n" |
65 | //usage: "Copy a file with converting and formatting\n" | 65 | //usage: "Copy a file with converting and formatting\n" |
@@ -82,9 +82,11 @@ | |||
82 | //usage: "\n conv=fsync Physically write data out before finishing" | 82 | //usage: "\n conv=fsync Physically write data out before finishing" |
83 | //usage: "\n conv=swab Swap every pair of bytes" | 83 | //usage: "\n conv=swab Swap every pair of bytes" |
84 | //usage: "\n iflag=skip_bytes skip=N is in bytes" | 84 | //usage: "\n iflag=skip_bytes skip=N is in bytes" |
85 | //usage: "\n iflag=fullblock Read full blocks" | ||
86 | //usage: "\n oflag=seek_bytes seek=N is in bytes" | 85 | //usage: "\n oflag=seek_bytes seek=N is in bytes" |
87 | //usage: "\n oflag=append Open output file in append mode" | 86 | //usage: "\n iflag=direct O_DIRECT input" |
87 | //usage: "\n oflag=direct O_DIRECT output" | ||
88 | //usage: "\n iflag=fullblock Read full blocks" | ||
89 | //usage: "\n oflag=append Open output in append mode" | ||
88 | //usage: ) | 90 | //usage: ) |
89 | //usage: IF_FEATURE_DD_STATUS( | 91 | //usage: IF_FEATURE_DD_STATUS( |
90 | //usage: "\n status=noxfer Suppress rate output" | 92 | //usage: "\n status=noxfer Suppress rate output" |
@@ -140,16 +142,18 @@ enum { | |||
140 | FLAG_IFLAG_SHIFT = 5, | 142 | FLAG_IFLAG_SHIFT = 5, |
141 | FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, | 143 | FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, |
142 | FLAG_FULLBLOCK = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS, | 144 | FLAG_FULLBLOCK = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS, |
145 | FLAG_IDIRECT = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS, | ||
143 | /* end of input flags */ | 146 | /* end of input flags */ |
144 | /* start of output flags */ | 147 | /* start of output flags */ |
145 | FLAG_OFLAG_SHIFT = 7, | 148 | FLAG_OFLAG_SHIFT = 8, |
146 | FLAG_SEEK_BYTES = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS, | 149 | FLAG_SEEK_BYTES = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS, |
147 | FLAG_APPEND = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS, | 150 | FLAG_APPEND = (1 << 9) * ENABLE_FEATURE_DD_IBS_OBS, |
151 | FLAG_ODIRECT = (1 << 10) * ENABLE_FEATURE_DD_IBS_OBS, | ||
148 | /* end of output flags */ | 152 | /* end of output flags */ |
149 | FLAG_TWOBUFS = (1 << 9) * ENABLE_FEATURE_DD_IBS_OBS, | 153 | FLAG_TWOBUFS = (1 << 11) * ENABLE_FEATURE_DD_IBS_OBS, |
150 | FLAG_COUNT = 1 << 10, | 154 | FLAG_COUNT = 1 << 12, |
151 | FLAG_STATUS_NONE = 1 << 11, | 155 | FLAG_STATUS_NONE = 1 << 13, |
152 | FLAG_STATUS_NOXFER = 1 << 12, | 156 | FLAG_STATUS_NOXFER = 1 << 14, |
153 | }; | 157 | }; |
154 | 158 | ||
155 | static void dd_output_status(int UNUSED_PARAM cur_signal) | 159 | static void dd_output_status(int UNUSED_PARAM cur_signal) |
@@ -195,12 +199,50 @@ static void dd_output_status(int UNUSED_PARAM cur_signal) | |||
195 | #endif | 199 | #endif |
196 | } | 200 | } |
197 | 201 | ||
202 | #if ENABLE_FEATURE_DD_IBS_OBS | ||
203 | static int clear_O_DIRECT(int fd) | ||
204 | { | ||
205 | if (errno == EINVAL) { | ||
206 | int fl = fcntl(fd, F_GETFL); | ||
207 | if (fl & O_DIRECT) { | ||
208 | fcntl(fd, F_SETFL, fl & ~O_DIRECT); | ||
209 | return 1; | ||
210 | } | ||
211 | } | ||
212 | return 0; | ||
213 | } | ||
214 | #endif | ||
215 | |||
216 | static ssize_t dd_read(void *ibuf, size_t ibs) | ||
217 | { | ||
218 | ssize_t n; | ||
219 | |||
220 | #if ENABLE_FEATURE_DD_IBS_OBS | ||
221 | read_again: | ||
222 | if (G.flags & FLAG_FULLBLOCK) | ||
223 | n = full_read(ifd, ibuf, ibs); | ||
224 | else | ||
225 | #endif | ||
226 | n = safe_read(ifd, ibuf, ibs); | ||
227 | #if ENABLE_FEATURE_DD_IBS_OBS | ||
228 | if (n < 0 && (G.flags & FLAG_IDIRECT) && clear_O_DIRECT(ifd)) | ||
229 | goto read_again; | ||
230 | #endif | ||
231 | return n; | ||
232 | } | ||
233 | |||
198 | static bool write_and_stats(const void *buf, size_t len, size_t obs, | 234 | static bool write_and_stats(const void *buf, size_t len, size_t obs, |
199 | const char *filename) | 235 | const char *filename) |
200 | { | 236 | { |
201 | ssize_t n; | 237 | ssize_t n; |
202 | 238 | ||
239 | IF_FEATURE_DD_IBS_OBS(write_again:) | ||
203 | n = full_write(ofd, buf, len); | 240 | n = full_write(ofd, buf, len); |
241 | #if ENABLE_FEATURE_DD_IBS_OBS | ||
242 | if (n < 0 && (G.flags & FLAG_ODIRECT) && clear_O_DIRECT(ofd)) | ||
243 | goto write_again; | ||
244 | #endif | ||
245 | |||
204 | #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE | 246 | #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE |
205 | if (n > 0) | 247 | if (n > 0) |
206 | G.total_bytes += n; | 248 | G.total_bytes += n; |
@@ -257,6 +299,16 @@ static int parse_comma_flags(char *val, const char *words, const char *error_in) | |||
257 | } | 299 | } |
258 | #endif | 300 | #endif |
259 | 301 | ||
302 | static void *alloc_buf(size_t size) | ||
303 | { | ||
304 | #if !ENABLE_PLATFORM_MINGW32 | ||
305 | /* Important for "{i,o}flag=direct" - buffers must be page aligned */ | ||
306 | if (size >= bb_getpagesize()) | ||
307 | return xmmap_anon(size); | ||
308 | #endif | ||
309 | return xmalloc(size); | ||
310 | } | ||
311 | |||
260 | int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 312 | int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
261 | int dd_main(int argc UNUSED_PARAM, char **argv) | 313 | int dd_main(int argc UNUSED_PARAM, char **argv) |
262 | { | 314 | { |
@@ -270,9 +322,9 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
270 | static const char conv_words[] ALIGN1 = | 322 | static const char conv_words[] ALIGN1 = |
271 | "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; | 323 | "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; |
272 | static const char iflag_words[] ALIGN1 = | 324 | static const char iflag_words[] ALIGN1 = |
273 | "skip_bytes\0""fullblock\0"; | 325 | "skip_bytes\0""fullblock\0""direct\0"; |
274 | static const char oflag_words[] ALIGN1 = | 326 | static const char oflag_words[] ALIGN1 = |
275 | "seek_bytes\0append\0"; | 327 | "seek_bytes\0append\0""direct\0"; |
276 | #endif | 328 | #endif |
277 | #if ENABLE_FEATURE_DD_STATUS | 329 | #if ENABLE_FEATURE_DD_STATUS |
278 | static const char status_words[] ALIGN1 = | 330 | static const char status_words[] ALIGN1 = |
@@ -313,7 +365,9 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
313 | //swab swap every pair of input bytes: will abort on non-even reads | 365 | //swab swap every pair of input bytes: will abort on non-even reads |
314 | OP_iflag_skip_bytes, | 366 | OP_iflag_skip_bytes, |
315 | OP_iflag_fullblock, | 367 | OP_iflag_fullblock, |
368 | OP_iflag_direct, | ||
316 | OP_oflag_seek_bytes, | 369 | OP_oflag_seek_bytes, |
370 | OP_oflag_direct, | ||
317 | #endif | 371 | #endif |
318 | }; | 372 | }; |
319 | smallint exitcode = EXIT_FAILURE; | 373 | smallint exitcode = EXIT_FAILURE; |
@@ -429,13 +483,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
429 | #endif | 483 | #endif |
430 | } /* end of "for (argv[i])" */ | 484 | } /* end of "for (argv[i])" */ |
431 | 485 | ||
432 | //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever | 486 | ibuf = alloc_buf(ibs); |
433 | ibuf = xmalloc(ibs); | ||
434 | obuf = ibuf; | 487 | obuf = ibuf; |
435 | #if ENABLE_FEATURE_DD_IBS_OBS | 488 | #if ENABLE_FEATURE_DD_IBS_OBS |
436 | if (ibs != obs) { | 489 | if (ibs != obs) { |
437 | G.flags |= FLAG_TWOBUFS; | 490 | G.flags |= FLAG_TWOBUFS; |
438 | obuf = xmalloc(obs); | 491 | obuf = alloc_buf(obs); |
439 | } | 492 | } |
440 | #endif | 493 | #endif |
441 | 494 | ||
@@ -447,10 +500,15 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
447 | #endif | 500 | #endif |
448 | 501 | ||
449 | if (infile) { | 502 | if (infile) { |
503 | int iflag = O_RDONLY; | ||
504 | #if ENABLE_FEATURE_DD_IBS_OBS | ||
505 | if (G.flags & FLAG_IDIRECT) | ||
506 | iflag |= O_DIRECT; | ||
507 | #endif | ||
450 | #if !ENABLE_PLATFORM_MINGW32 | 508 | #if !ENABLE_PLATFORM_MINGW32 |
451 | xmove_fd(xopen(infile, O_RDONLY), ifd); | 509 | xmove_fd(xopen(infile, iflag), ifd); |
452 | #else | 510 | #else |
453 | xmove_fd(mingw_xopen(infile, O_RDONLY), ifd); | 511 | xmove_fd(mingw_xopen(infile, iflag), ifd); |
454 | update_dev_fd(get_dev_type(infile), ifd); | 512 | update_dev_fd(get_dev_type(infile), ifd); |
455 | #endif | 513 | #endif |
456 | } else { | 514 | } else { |
@@ -463,7 +521,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
463 | oflag |= O_TRUNC; | 521 | oflag |= O_TRUNC; |
464 | if (G.flags & FLAG_APPEND) | 522 | if (G.flags & FLAG_APPEND) |
465 | oflag |= O_APPEND; | 523 | oflag |= O_APPEND; |
466 | 524 | #if ENABLE_FEATURE_DD_IBS_OBS | |
525 | if (G.flags & FLAG_ODIRECT) | ||
526 | oflag |= O_DIRECT; | ||
527 | #endif | ||
467 | xmove_fd(xopen(outfile, oflag), ofd); | 528 | xmove_fd(xopen(outfile, oflag), ofd); |
468 | 529 | ||
469 | #if ENABLE_PLATFORM_MINGW32 | 530 | #if ENABLE_PLATFORM_MINGW32 |
@@ -508,13 +569,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
508 | size_t blocksz = (G.flags & FLAG_SKIP_BYTES) ? 1 : ibs; | 569 | size_t blocksz = (G.flags & FLAG_SKIP_BYTES) ? 1 : ibs; |
509 | if (lseek(ifd, skip * blocksz, SEEK_CUR) < 0) { | 570 | if (lseek(ifd, skip * blocksz, SEEK_CUR) < 0) { |
510 | do { | 571 | do { |
511 | ssize_t n; | 572 | ssize_t n = dd_read(ibuf, blocksz); |
512 | #if ENABLE_FEATURE_DD_IBS_OBS | ||
513 | if (G.flags & FLAG_FULLBLOCK) | ||
514 | n = full_read(ifd, ibuf, blocksz); | ||
515 | else | ||
516 | #endif | ||
517 | n = safe_read(ifd, ibuf, blocksz); | ||
518 | if (n < 0) | 573 | if (n < 0) |
519 | goto die_infile; | 574 | goto die_infile; |
520 | if (n == 0) | 575 | if (n == 0) |
@@ -529,14 +584,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
529 | } | 584 | } |
530 | 585 | ||
531 | while (!(G.flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { | 586 | while (!(G.flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { |
532 | ssize_t n; | 587 | ssize_t n = dd_read(ibuf, ibs); |
533 | |||
534 | #if ENABLE_FEATURE_DD_IBS_OBS | ||
535 | if (G.flags & FLAG_FULLBLOCK) | ||
536 | n = full_read(ifd, ibuf, ibs); | ||
537 | else | ||
538 | #endif | ||
539 | n = safe_read(ifd, ibuf, ibs); | ||
540 | if (n == 0) | 588 | if (n == 0) |
541 | break; | 589 | break; |
542 | if (n < 0) { | 590 | if (n < 0) { |
@@ -631,11 +679,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
631 | if (!ENABLE_FEATURE_DD_STATUS || !(G.flags & FLAG_STATUS_NONE)) | 679 | if (!ENABLE_FEATURE_DD_STATUS || !(G.flags & FLAG_STATUS_NONE)) |
632 | dd_output_status(0); | 680 | dd_output_status(0); |
633 | 681 | ||
682 | #if 0 /* can't just free(), they can be mmap()ed */ | ||
634 | if (ENABLE_FEATURE_CLEAN_UP) { | 683 | if (ENABLE_FEATURE_CLEAN_UP) { |
635 | free(obuf); | 684 | free(obuf); |
636 | if (G.flags & FLAG_TWOBUFS) | 685 | if (G.flags & FLAG_TWOBUFS) |
637 | free(ibuf); | 686 | free(ibuf); |
638 | } | 687 | } |
688 | #endif | ||
639 | 689 | ||
640 | return exitcode; | 690 | return exitcode; |
641 | } | 691 | } |
diff --git a/coreutils/factor.c b/coreutils/factor.c index 47fe179dc..a7a5a5030 100644 --- a/coreutils/factor.c +++ b/coreutils/factor.c | |||
@@ -19,6 +19,7 @@ | |||
19 | //usage: "Print prime factors" | 19 | //usage: "Print prime factors" |
20 | 20 | ||
21 | #include "libbb.h" | 21 | #include "libbb.h" |
22 | #include "common_bufsiz.h" | ||
22 | 23 | ||
23 | #if 0 | 24 | #if 0 |
24 | # define dbg(...) bb_error_msg(__VA_ARGS__) | 25 | # define dbg(...) bb_error_msg(__VA_ARGS__) |
@@ -42,9 +43,116 @@ typedef unsigned long half_t; | |||
42 | #error Cant find an integer type which is half as wide as ullong | 43 | #error Cant find an integer type which is half as wide as ullong |
43 | #endif | 44 | #endif |
44 | 45 | ||
46 | /* The trial divisor increment wheel. Use it to skip over divisors that | ||
47 | * are composites of 2, 3, 5, 7, or 11. | ||
48 | * Larger wheels improve sieving only slightly, but quickly grow in size | ||
49 | * (adding just one prime, 13, results in 5766 element sieve). | ||
50 | */ | ||
51 | #define R(a,b,c,d,e,f,g,h,i,j,A,B,C,D,E,F,G,H,I,J) \ | ||
52 | (((uint64_t)(a<<0) | (b<<3) | (c<<6) | (d<<9) | (e<<12) | (f<<15) | (g<<18) | (h<<21) | (i<<24) | (j<<27)) << 1) | \ | ||
53 | (((uint64_t)(A<<0) | (B<<3) | (C<<6) | (D<<9) | (E<<12) | (F<<15) | (G<<18) | (H<<21) | (I<<24) | (J<<27)) << 31) | ||
54 | #define P(a,b,c,d,e,f,g,h,i,j,A,B,C,D,E,F,G,H,I,J) \ | ||
55 | R( (a/2),(b/2),(c/2),(d/2),(e/2),(f/2),(g/2),(h/2),(i/2),(j/2), \ | ||
56 | (A/2),(B/2),(C/2),(D/2),(E/2),(F/2),(G/2),(H/2),(I/2),(J/2) ) | ||
57 | static const uint64_t packed_wheel[] = { | ||
58 | /*1, 2, 2, 4, 2,*/ | ||
59 | P( 4, 2, 4, 6, 2, 6, 4, 2, 4, 6, 6, 2, 6, 4, 2, 6, 4, 6, 8, 4), //01 | ||
60 | P( 2, 4, 2, 4,14, 4, 6, 2,10, 2, 6, 6, 4, 2, 4, 6, 2,10, 2, 4), //02 | ||
61 | P( 2,12,10, 2, 4, 2, 4, 6, 2, 6, 4, 6, 6, 6, 2, 6, 4, 2, 6, 4), //03 | ||
62 | P( 6, 8, 4, 2, 4, 6, 8, 6,10, 2, 4, 6, 2, 6, 6, 4, 2, 4, 6, 2), //04 | ||
63 | P( 6, 4, 2, 6,10, 2,10, 2, 4, 2, 4, 6, 8, 4, 2, 4,12, 2, 6, 4), //05 | ||
64 | P( 2, 6, 4, 6,12, 2, 4, 2, 4, 8, 6, 4, 6, 2, 4, 6, 2, 6,10, 2), //06 | ||
65 | P( 4, 6, 2, 6, 4, 2, 4, 2,10, 2,10, 2, 4, 6, 6, 2, 6, 6, 4, 6), //07 | ||
66 | P( 6, 2, 6, 4, 2, 6, 4, 6, 8, 4, 2, 6, 4, 8, 6, 4, 6, 2, 4, 6), //08 | ||
67 | P( 8, 6, 4, 2,10, 2, 6, 4, 2, 4, 2,10, 2,10, 2, 4, 2, 4, 8, 6), //09 | ||
68 | P( 4, 2, 4, 6, 6, 2, 6, 4, 8, 4, 6, 8, 4, 2, 4, 2, 4, 8, 6, 4), //10 | ||
69 | P( 6, 6, 6, 2, 6, 6, 4, 2, 4, 6, 2, 6, 4, 2, 4, 2,10, 2,10, 2), //11 | ||
70 | P( 6, 4, 6, 2, 6, 4, 2, 4, 6, 6, 8, 4, 2, 6,10, 8, 4, 2, 4, 2), //12 | ||
71 | P( 4, 8,10, 6, 2, 4, 8, 6, 6, 4, 2, 4, 6, 2, 6, 4, 6, 2,10, 2), //13 | ||
72 | P(10, 2, 4, 2, 4, 6, 2, 6, 4, 2, 4, 6, 6, 2, 6, 6, 6, 4, 6, 8), //14 | ||
73 | P( 4, 2, 4, 2, 4, 8, 6, 4, 8, 4, 6, 2, 6, 6, 4, 2, 4, 6, 8, 4), //15 | ||
74 | P( 2, 4, 2,10, 2,10, 2, 4, 2, 4, 6, 2,10, 2, 4, 6, 8, 6, 4, 2), //16 | ||
75 | P( 6, 4, 6, 8, 4, 6, 2, 4, 8, 6, 4, 6, 2, 4, 6, 2, 6, 6, 4, 6), //17 | ||
76 | P( 6, 2, 6, 6, 4, 2,10, 2,10, 2, 4, 2, 4, 6, 2, 6, 4, 2,10, 6), //18 | ||
77 | P( 2, 6, 4, 2, 6, 4, 6, 8, 4, 2, 4, 2,12, 6, 4, 6, 2, 4, 6, 2), //19 | ||
78 | P(12, 4, 2, 4, 8, 6, 4, 2, 4, 2,10, 2,10, 6, 2, 4, 6, 2, 6, 4), //20 | ||
79 | P( 2, 4, 6, 6, 2, 6, 4, 2,10, 6, 8, 6, 4, 2, 4, 8, 6, 4, 6, 2), //21 | ||
80 | P( 4, 6, 2, 6, 6, 6, 4, 6, 2, 6, 4, 2, 4, 2,10,12, 2, 4, 2,10), //22 | ||
81 | P( 2, 6, 4, 2, 4, 6, 6, 2,10, 2, 6, 4,14, 4, 2, 4, 2, 4, 8, 6), //23 | ||
82 | P( 4, 6, 2, 4, 6, 2, 6, 6, 4, 2, 4, 6, 2, 6, 4, 2, 4,12, 2,12), //24 | ||
83 | }; | ||
84 | #undef P | ||
85 | #undef R | ||
86 | #define WHEEL_START 5 | ||
87 | #define WHEEL_SIZE (5 + 24 * 20) | ||
88 | #define square_count (((uint8_t*)&bb_common_bufsiz1)[0]) | ||
89 | #define wheel_tab (((uint8_t*)&bb_common_bufsiz1) + 1) | ||
90 | /* | ||
91 | * Why, you ask? | ||
92 | * plain byte array: | ||
93 | * function old new delta | ||
94 | * wheel_tab - 485 +485 | ||
95 | * 3-bit-packed insanity: | ||
96 | * packed_wheel - 192 +192 | ||
97 | * factor_main 108 171 +63 | ||
98 | */ | ||
99 | static void unpack_wheel(void) | ||
100 | { | ||
101 | int i; | ||
102 | uint8_t *p; | ||
103 | |||
104 | setup_common_bufsiz(); | ||
105 | wheel_tab[0] = 1; | ||
106 | wheel_tab[1] = 2; | ||
107 | wheel_tab[2] = 2; | ||
108 | wheel_tab[3] = 4; | ||
109 | wheel_tab[4] = 2; | ||
110 | p = &wheel_tab[5]; | ||
111 | for (i = 0; i < ARRAY_SIZE(packed_wheel); i++) { | ||
112 | uint64_t v = packed_wheel[i]; | ||
113 | while ((v & 0xe) != 0) { | ||
114 | *p = v & 0xe; | ||
115 | //printf("%2u,", *p); | ||
116 | p++; | ||
117 | v >>= 3; | ||
118 | } | ||
119 | //printf("\n"); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | /* Prevent inlining, factorize() needs all help it can get with reducing register pressure */ | ||
124 | static NOINLINE void print_w(wide_t n) | ||
125 | { | ||
126 | unsigned rep = square_count; | ||
127 | do | ||
128 | printf(" %"LL_FMT"u", n); | ||
129 | while (--rep != 0); | ||
130 | } | ||
131 | static NOINLINE void print_h(half_t n) | ||
132 | { | ||
133 | print_w(n); | ||
134 | } | ||
135 | |||
136 | static void factorize(wide_t N); | ||
137 | |||
45 | static half_t isqrt_odd(wide_t N) | 138 | static half_t isqrt_odd(wide_t N) |
46 | { | 139 | { |
47 | half_t s = isqrt(N); | 140 | half_t s = isqrt(N); |
141 | /* s^2 is <= N, (s+1)^2 > N */ | ||
142 | |||
143 | /* If s^2 in fact is EQUAL to N, it's very lucky. | ||
144 | * Examples: | ||
145 | * factor 18446743988964486098 = 2 * 3037000493 * 3037000493 | ||
146 | * factor 18446743902517389507 = 3 * 2479700513 * 2479700513 | ||
147 | */ | ||
148 | if ((wide_t)s * s == N) { | ||
149 | /* factorize sqrt(N), printing each factor twice */ | ||
150 | square_count *= 2; | ||
151 | factorize(s); | ||
152 | /* Let caller know we recursed */ | ||
153 | return 0; | ||
154 | } | ||
155 | |||
48 | /* Subtract 1 from even s, odd s won't change: */ | 156 | /* Subtract 1 from even s, odd s won't change: */ |
49 | /* (doesnt work for zero, but we know that s != 0 here) */ | 157 | /* (doesnt work for zero, but we know that s != 0 here) */ |
50 | s = (s - 1) | 1; | 158 | s = (s - 1) | 1; |
@@ -53,43 +161,20 @@ static half_t isqrt_odd(wide_t N) | |||
53 | 161 | ||
54 | static NOINLINE void factorize(wide_t N) | 162 | static NOINLINE void factorize(wide_t N) |
55 | { | 163 | { |
164 | unsigned w; | ||
56 | half_t factor; | 165 | half_t factor; |
57 | half_t max_factor; | 166 | half_t max_factor; |
58 | // unsigned count3; | ||
59 | // unsigned count5; | ||
60 | // unsigned count7; | ||
61 | // ^^^^^^^^^^^^^^^ commented-out simple sieving code (easier to grasp). | ||
62 | // Faster sieving, using one word for potentially up to 6 counters: | ||
63 | // count upwards in each mask, counter "triggers" when it sets its mask to "100[0]..." | ||
64 | // 10987654321098765432109876543210 - bits 31-0 in 32-bit word | ||
65 | // 17777713333311111777775555333 - bit masks for counters for primes 3,5,7,11,13,17 | ||
66 | // 100000100001000010001001 - value for adding 1 to each mask | ||
67 | // 10000010000010000100001000100 - value for checking that any mask reached msb | ||
68 | enum { | ||
69 | SHIFT_3 = 1 << 0, | ||
70 | SHIFT_5 = 1 << 3, | ||
71 | SHIFT_7 = 1 << 7, | ||
72 | INCREMENT_EACH = SHIFT_3 | SHIFT_5 | SHIFT_7, | ||
73 | MULTIPLE_OF_3 = 1 << 2, | ||
74 | MULTIPLE_OF_5 = 1 << 6, | ||
75 | MULTIPLE_OF_7 = 1 << 11, | ||
76 | MULTIPLE_DETECTED = MULTIPLE_OF_3 | MULTIPLE_OF_5 | MULTIPLE_OF_7, | ||
77 | }; | ||
78 | unsigned sieve_word; | ||
79 | 167 | ||
80 | if (N < 4) | 168 | if (N < 4) |
81 | goto end; | 169 | goto end; |
82 | 170 | ||
83 | while (!(N & 1)) { | ||
84 | printf(" 2"); | ||
85 | N >>= 1; | ||
86 | } | ||
87 | |||
88 | /* The code needs to be optimized for the case where | 171 | /* The code needs to be optimized for the case where |
89 | * there are large prime factors. For example, | 172 | * there are large prime factors. For example, |
90 | * this is not hard: | 173 | * this is not hard: |
91 | * 8262075252869367027 = 3 7 17 23 47 101 113 127 131 137 823 | 174 | * 8262075252869367027 = 3 7 17 23 47 101 113 127 131 137 823 |
92 | * (the largest factor to test is only ~sqrt(823) = 28) | 175 | * (the largest divisor to test for largest factor 823 |
176 | * is only ~sqrt(823) = 28, the entire factorization needs | ||
177 | * only ~33 trial divisions) | ||
93 | * but this is: | 178 | * but this is: |
94 | * 18446744073709551601 = 53 348051774975651917 | 179 | * 18446744073709551601 = 53 348051774975651917 |
95 | * the last factor requires testing up to | 180 | * the last factor requires testing up to |
@@ -98,70 +183,37 @@ static NOINLINE void factorize(wide_t N) | |||
98 | * factor 18446744073709551557 (0xffffffffffffffc5). | 183 | * factor 18446744073709551557 (0xffffffffffffffc5). |
99 | */ | 184 | */ |
100 | max_factor = isqrt_odd(N); | 185 | max_factor = isqrt_odd(N); |
101 | // count3 = 3; | 186 | if (!max_factor) |
102 | // count5 = 6; | 187 | return; /* square was detected and recursively factored */ |
103 | // count7 = 9; | 188 | factor = 2; |
104 | sieve_word = 0 | 189 | w = 0; |
105 | /* initial count for SHIFT_n is (n-1)/2*3: */ | ||
106 | + (MULTIPLE_OF_3 - 3 * SHIFT_3) | ||
107 | + (MULTIPLE_OF_5 - 6 * SHIFT_5) | ||
108 | + (MULTIPLE_OF_7 - 9 * SHIFT_7) | ||
109 | //+ (MULTIPLE_OF_11 - 15 * SHIFT_11) | ||
110 | //+ (MULTIPLE_OF_13 - 18 * SHIFT_13) | ||
111 | //+ (MULTIPLE_OF_17 - 24 * SHIFT_17) | ||
112 | ; | ||
113 | factor = 3; | ||
114 | for (;;) { | 190 | for (;;) { |
191 | half_t fw; | ||
192 | |||
115 | /* The division is the most costly part of the loop. | 193 | /* The division is the most costly part of the loop. |
116 | * On 64bit CPUs, takes at best 12 cycles, often ~20. | 194 | * On 64bit CPUs, takes at best 12 cycles, often ~20. |
117 | */ | 195 | */ |
118 | while ((N % factor) == 0) { /* not likely */ | 196 | while ((N % factor) == 0) { /* not likely */ |
119 | N = N / factor; | 197 | N = N / factor; |
120 | printf(" %"HALF_FMT"u", factor); | 198 | print_h(factor); |
121 | max_factor = isqrt_odd(N); | 199 | max_factor = isqrt_odd(N); |
200 | if (!max_factor) | ||
201 | return; /* square was detected */ | ||
122 | } | 202 | } |
123 | next_factor: | ||
124 | if (factor >= max_factor) | 203 | if (factor >= max_factor) |
125 | break; | 204 | break; |
126 | factor += 2; | 205 | fw = factor + wheel_tab[w]; |
127 | /* Rudimentary wheel sieving: skip multiples of 3, 5 and 7: | 206 | if (fw < factor) |
128 | * Every third odd number is divisible by three and thus isn't a prime: | 207 | break; /* overflow */ |
129 | * 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47... | 208 | factor = fw; |
130 | * ^ ^ ^ ^ ^ ^ ^ _ ^ ^ _ ^ ^ ^ ^ | 209 | w++; |
131 | * (^ = primes, _ = would-be-primes-if-not-divisible-by-5) | 210 | if (w < WHEEL_SIZE) |
132 | * The numbers with space under them are excluded by sieve 3. | ||
133 | */ | ||
134 | // count7--; | ||
135 | // count5--; | ||
136 | // count3--; | ||
137 | // if (count3 && count5 && count7) | ||
138 | // continue; | ||
139 | sieve_word += INCREMENT_EACH; | ||
140 | if (!(sieve_word & MULTIPLE_DETECTED)) | ||
141 | continue; | 211 | continue; |
142 | /* | 212 | w = WHEEL_START; |
143 | * "factor" is multiple of 3 33% of the time (count3 reached 0), | ||
144 | * else, multiple of 5 13% of the time, | ||
145 | * else, multiple of 7 7.6% of the time. | ||
146 | * Cumulatively, with 3,5,7 sieving we are here 54.3% of the time. | ||
147 | */ | ||
148 | // if (count3 == 0) | ||
149 | // count3 = 3; | ||
150 | if (sieve_word & MULTIPLE_OF_3) | ||
151 | sieve_word -= SHIFT_3 * 3; | ||
152 | // if (count5 == 0) | ||
153 | // count5 = 5; | ||
154 | if (sieve_word & MULTIPLE_OF_5) | ||
155 | sieve_word -= SHIFT_5 * 5; | ||
156 | // if (count7 == 0) | ||
157 | // count7 = 7; | ||
158 | if (sieve_word & MULTIPLE_OF_7) | ||
159 | sieve_word -= SHIFT_7 * 7; | ||
160 | goto next_factor; | ||
161 | } | 213 | } |
162 | end: | 214 | end: |
163 | if (N > 1) | 215 | if (N > 1) |
164 | printf(" %"LL_FMT"u", N); | 216 | print_w(N); |
165 | bb_putchar('\n'); | 217 | bb_putchar('\n'); |
166 | } | 218 | } |
167 | 219 | ||
@@ -176,12 +228,15 @@ static void factorize_numstr(const char *numstr) | |||
176 | if (errno) | 228 | if (errno) |
177 | bb_show_usage(); | 229 | bb_show_usage(); |
178 | printf("%"LL_FMT"u:", N); | 230 | printf("%"LL_FMT"u:", N); |
231 | square_count = 1; | ||
179 | factorize(N); | 232 | factorize(N); |
180 | } | 233 | } |
181 | 234 | ||
182 | int factor_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 235 | int factor_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
183 | int factor_main(int argc UNUSED_PARAM, char **argv) | 236 | int factor_main(int argc UNUSED_PARAM, char **argv) |
184 | { | 237 | { |
238 | unpack_wheel(); | ||
239 | |||
185 | //// coreutils has undocumented option ---debug (three dashes) | 240 | //// coreutils has undocumented option ---debug (three dashes) |
186 | //getopt32(argv, ""); | 241 | //getopt32(argv, ""); |
187 | //argv += optind; | 242 | //argv += optind; |
diff --git a/coreutils/id.c b/coreutils/id.c index f20cd7d09..78d5f2a50 100644 --- a/coreutils/id.c +++ b/coreutils/id.c | |||
@@ -33,7 +33,7 @@ | |||
33 | /* BB_AUDIT SUSv3 compliant. */ | 33 | /* BB_AUDIT SUSv3 compliant. */ |
34 | 34 | ||
35 | //usage:#define id_trivial_usage | 35 | //usage:#define id_trivial_usage |
36 | //usage: "[OPTIONS] [USER]" | 36 | //usage: "[-ugGnr"IF_SELINUX("Z")"] [USER]" |
37 | //usage:#define id_full_usage "\n\n" | 37 | //usage:#define id_full_usage "\n\n" |
38 | //usage: "Print information about USER or the current user\n" | 38 | //usage: "Print information about USER or the current user\n" |
39 | //usage: IF_SELINUX( | 39 | //usage: IF_SELINUX( |
diff --git a/coreutils/ln.c b/coreutils/ln.c index 5591e8335..2dcf79c07 100644 --- a/coreutils/ln.c +++ b/coreutils/ln.c | |||
@@ -21,14 +21,14 @@ | |||
21 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/ln.html */ | 21 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/ln.html */ |
22 | 22 | ||
23 | //usage:#define ln_trivial_usage | 23 | //usage:#define ln_trivial_usage |
24 | //usage: "[OPTIONS] TARGET... LINK|DIR" | 24 | //usage: "[-sfnbtv] [-S SUF] TARGET... LINK|DIR" |
25 | //usage:#define ln_full_usage "\n\n" | 25 | //usage:#define ln_full_usage "\n\n" |
26 | //usage: "Create a link LINK or DIR/TARGET to the specified TARGET(s)\n" | 26 | //usage: "Create a link LINK or DIR/TARGET to the specified TARGET(s)\n" |
27 | //usage: "\n -s Make symlinks instead of hardlinks" | 27 | //usage: "\n -s Make symlinks instead of hardlinks" |
28 | //usage: "\n -f Remove existing destinations" | 28 | //usage: "\n -f Remove existing destinations" |
29 | //usage: "\n -n Don't dereference symlinks - treat like normal file" | 29 | //usage: "\n -n Don't dereference symlinks - treat like normal file" |
30 | //usage: "\n -b Make a backup of the target (if exists) before link operation" | 30 | //usage: "\n -b Make a backup of the target (if exists) before link operation" |
31 | //usage: "\n -S suf Use suffix instead of ~ when making backup files" | 31 | //usage: "\n -S SUF Use suffix instead of ~ when making backup files" |
32 | //usage: "\n -T Treat LINK as a file, not DIR" | 32 | //usage: "\n -T Treat LINK as a file, not DIR" |
33 | //usage: "\n -v Verbose" | 33 | //usage: "\n -v Verbose" |
34 | //usage: | 34 | //usage: |
diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c index ba26c985a..4efa23061 100644 --- a/coreutils/md5_sha1_sum.c +++ b/coreutils/md5_sha1_sum.c | |||
@@ -117,8 +117,8 @@ | |||
117 | //usage: "\n -c Check sums against list in FILEs" | 117 | //usage: "\n -c Check sums against list in FILEs" |
118 | //usage: "\n -s Don't output anything, status code shows success" | 118 | //usage: "\n -s Don't output anything, status code shows success" |
119 | //usage: "\n -w Warn about improperly formatted checksum lines" | 119 | //usage: "\n -w Warn about improperly formatted checksum lines" |
120 | //usage: "\n -a BITS 224 (default), 256, 384, 512" | ||
121 | //usage: ) | 120 | //usage: ) |
121 | //usage: "\n -a BITS 224 (default), 256, 384, 512" | ||
122 | 122 | ||
123 | //FIXME: GNU coreutils 8.25 has no -s option, it has only these two long opts: | 123 | //FIXME: GNU coreutils 8.25 has no -s option, it has only these two long opts: |
124 | // --quiet don't print OK for each successfully verified file | 124 | // --quiet don't print OK for each successfully verified file |
diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c index 0ee1d1f72..d5e0f512b 100644 --- a/coreutils/mkdir.c +++ b/coreutils/mkdir.c | |||
@@ -27,7 +27,7 @@ | |||
27 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/mkdir.html */ | 27 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/mkdir.html */ |
28 | 28 | ||
29 | //usage:#define mkdir_trivial_usage | 29 | //usage:#define mkdir_trivial_usage |
30 | //usage: "[OPTIONS] DIRECTORY..." | 30 | //usage: "[-m MODE] [-p] DIRECTORY..." |
31 | //usage:#define mkdir_full_usage "\n\n" | 31 | //usage:#define mkdir_full_usage "\n\n" |
32 | //usage: "Create DIRECTORY\n" | 32 | //usage: "Create DIRECTORY\n" |
33 | //usage: "\n -m MODE Mode" | 33 | //usage: "\n -m MODE Mode" |
diff --git a/coreutils/mknod.c b/coreutils/mknod.c index eee0ac71d..b10fe4fc3 100644 --- a/coreutils/mknod.c +++ b/coreutils/mknod.c | |||
@@ -36,7 +36,9 @@ | |||
36 | //usage: "$ mknod /dev/fd0 b 2 0\n" | 36 | //usage: "$ mknod /dev/fd0 b 2 0\n" |
37 | //usage: "$ mknod -m 644 /tmp/pipe p\n" | 37 | //usage: "$ mknod -m 644 /tmp/pipe p\n" |
38 | 38 | ||
39 | #include <sys/sysmacros.h> // For makedev | 39 | #ifdef __linux__ |
40 | # include <sys/sysmacros.h> // For makedev | ||
41 | #endif | ||
40 | 42 | ||
41 | #include "libbb.h" | 43 | #include "libbb.h" |
42 | #include "libcoreutils/coreutils.h" | 44 | #include "libcoreutils/coreutils.h" |
diff --git a/coreutils/nl.c b/coreutils/nl.c index aea019c56..800b73c26 100644 --- a/coreutils/nl.c +++ b/coreutils/nl.c | |||
@@ -19,7 +19,7 @@ | |||
19 | //usage:#define nl_full_usage "\n\n" | 19 | //usage:#define nl_full_usage "\n\n" |
20 | //usage: "Write FILEs to standard output with line numbers added\n" | 20 | //usage: "Write FILEs to standard output with line numbers added\n" |
21 | //usage: "\n -b STYLE Which lines to number - a: all, t: nonempty, n: none" | 21 | //usage: "\n -b STYLE Which lines to number - a: all, t: nonempty, n: none" |
22 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^TODO: support "pBRE": number only lines thatmatch regexp BRE" | 22 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^TODO: support "pBRE": number only lines that match regexp BRE" |
23 | ////usage: "\n -f STYLE footer lines" | 23 | ////usage: "\n -f STYLE footer lines" |
24 | ////usage: "\n -h STYLE header lines" | 24 | ////usage: "\n -h STYLE header lines" |
25 | ////usage: "\n -d CC use CC for separating logical pages" | 25 | ////usage: "\n -d CC use CC for separating logical pages" |
diff --git a/coreutils/od_bloaty.c b/coreutils/od_bloaty.c index ea1ab9de8..76ee5137a 100644 --- a/coreutils/od_bloaty.c +++ b/coreutils/od_bloaty.c | |||
@@ -634,7 +634,7 @@ decode_one_format(const char *s_orig, const char *s, struct tspec *tspec) | |||
634 | bytes_to_unsigned_dec_digits, | 634 | bytes_to_unsigned_dec_digits, |
635 | bytes_to_hex_digits, | 635 | bytes_to_hex_digits, |
636 | }; | 636 | }; |
637 | static const char doux_fmtstring[][sizeof(" %%0%u%s")] = { | 637 | static const char doux_fmtstring[][sizeof(" %%0%u%s")] ALIGN1 = { |
638 | " %%%u%s", | 638 | " %%%u%s", |
639 | " %%0%u%s", | 639 | " %%0%u%s", |
640 | " %%%u%s", | 640 | " %%%u%s", |
@@ -1155,7 +1155,7 @@ dump_strings(off_t address, off_t end_offset) | |||
1155 | static int | 1155 | static int |
1156 | parse_old_offset(const char *s, off_t *offset) | 1156 | parse_old_offset(const char *s, off_t *offset) |
1157 | { | 1157 | { |
1158 | static const struct suffix_mult Bb[] = { | 1158 | static const struct suffix_mult Bb[] ALIGN_SUFFIX = { |
1159 | { "B", 1024 }, | 1159 | { "B", 1024 }, |
1160 | { "b", 512 }, | 1160 | { "b", 512 }, |
1161 | { "", 0 } | 1161 | { "", 0 } |
diff --git a/coreutils/paste.c b/coreutils/paste.c index 11743297a..fd2aa5027 100644 --- a/coreutils/paste.c +++ b/coreutils/paste.c | |||
@@ -18,7 +18,7 @@ | |||
18 | //kbuild:lib-$(CONFIG_PASTE) += paste.o | 18 | //kbuild:lib-$(CONFIG_PASTE) += paste.o |
19 | 19 | ||
20 | //usage:#define paste_trivial_usage | 20 | //usage:#define paste_trivial_usage |
21 | //usage: "[OPTIONS] [FILE]..." | 21 | //usage: "[-d LIST] [-s] [FILE]..." |
22 | //usage:#define paste_full_usage "\n\n" | 22 | //usage:#define paste_full_usage "\n\n" |
23 | //usage: "Paste lines from each input file, separated with tab\n" | 23 | //usage: "Paste lines from each input file, separated with tab\n" |
24 | //usage: "\n -d LIST Use delimiters from LIST, not tab" | 24 | //usage: "\n -d LIST Use delimiters from LIST, not tab" |
diff --git a/coreutils/rmdir.c b/coreutils/rmdir.c index 5092a5dfc..addf41188 100644 --- a/coreutils/rmdir.c +++ b/coreutils/rmdir.c | |||
@@ -20,7 +20,7 @@ | |||
20 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/rmdir.html */ | 20 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/rmdir.html */ |
21 | 21 | ||
22 | //usage:#define rmdir_trivial_usage | 22 | //usage:#define rmdir_trivial_usage |
23 | //usage: "[OPTIONS] DIRECTORY..." | 23 | //usage: "[-p] DIRECTORY..." |
24 | //usage:#define rmdir_full_usage "\n\n" | 24 | //usage:#define rmdir_full_usage "\n\n" |
25 | //usage: "Remove DIRECTORY if it is empty\n" | 25 | //usage: "Remove DIRECTORY if it is empty\n" |
26 | //usage: "\n -p Include parents" | 26 | //usage: "\n -p Include parents" |
diff --git a/coreutils/sort.c b/coreutils/sort.c index 07c327645..b194847d1 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c | |||
@@ -43,7 +43,7 @@ | |||
43 | 43 | ||
44 | //usage:#define sort_trivial_usage | 44 | //usage:#define sort_trivial_usage |
45 | //usage: "[-nru" | 45 | //usage: "[-nru" |
46 | //usage: IF_FEATURE_SORT_BIG("gMcszbdfiokt] [-o FILE] [-k start[.offset][opts][,end[.offset][opts]] [-t CHAR") | 46 | //usage: IF_FEATURE_SORT_BIG("gMcszbdfiokt] [-o FILE] [-k START[.OFS][OPTS][,END[.OFS][OPTS]] [-t CHAR") |
47 | //usage: "] [FILE]..." | 47 | //usage: "] [FILE]..." |
48 | //usage:#define sort_full_usage "\n\n" | 48 | //usage:#define sort_full_usage "\n\n" |
49 | //usage: "Sort lines of text\n" | 49 | //usage: "Sort lines of text\n" |
diff --git a/coreutils/split.c b/coreutils/split.c index ecbc9d2d8..3fcfd95f2 100644 --- a/coreutils/split.c +++ b/coreutils/split.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #include "common_bufsiz.h" | 44 | #include "common_bufsiz.h" |
45 | 45 | ||
46 | #if ENABLE_FEATURE_SPLIT_FANCY | 46 | #if ENABLE_FEATURE_SPLIT_FANCY |
47 | static const struct suffix_mult split_suffixes[] = { | 47 | static const struct suffix_mult split_suffixes[] ALIGN_SUFFIX = { |
48 | { "b", 512 }, | 48 | { "b", 512 }, |
49 | { "k", 1024 }, | 49 | { "k", 1024 }, |
50 | { "m", 1024*1024 }, | 50 | { "m", 1024*1024 }, |
diff --git a/coreutils/stat.c b/coreutils/stat.c index c332e5dc8..0a3f251f3 100644 --- a/coreutils/stat.c +++ b/coreutils/stat.c | |||
@@ -40,7 +40,7 @@ | |||
40 | //kbuild:lib-$(CONFIG_STAT) += stat.o | 40 | //kbuild:lib-$(CONFIG_STAT) += stat.o |
41 | 41 | ||
42 | //usage:#define stat_trivial_usage | 42 | //usage:#define stat_trivial_usage |
43 | //usage: "[OPTIONS] FILE..." | 43 | //usage: "[-lt"IF_FEATURE_STAT_FILESYSTEM("f")"] "IF_FEATURE_STAT_FORMAT("[-c FMT] ")"FILE..." |
44 | //usage:#define stat_full_usage "\n\n" | 44 | //usage:#define stat_full_usage "\n\n" |
45 | //usage: "Display file" | 45 | //usage: "Display file" |
46 | //usage: IF_FEATURE_STAT_FILESYSTEM(" (default) or filesystem") | 46 | //usage: IF_FEATURE_STAT_FILESYSTEM(" (default) or filesystem") |
@@ -209,7 +209,7 @@ FS_TYPE(0x62656572, "sysfs") | |||
209 | static const char *human_fstype(uint32_t f_type) | 209 | static const char *human_fstype(uint32_t f_type) |
210 | { | 210 | { |
211 | # define FS_TYPE(type, name) type, | 211 | # define FS_TYPE(type, name) type, |
212 | static const uint32_t fstype[] = { | 212 | static const uint32_t fstype[] ALIGN4 = { |
213 | FS_TYPE_LIST | 213 | FS_TYPE_LIST |
214 | }; | 214 | }; |
215 | # undef FS_TYPE | 215 | # undef FS_TYPE |
diff --git a/coreutils/stty.c b/coreutils/stty.c index 40e812799..19253964c 100644 --- a/coreutils/stty.c +++ b/coreutils/stty.c | |||
@@ -487,7 +487,7 @@ static const char mode_name[] ALIGN1 = | |||
487 | #undef MI_ENTRY | 487 | #undef MI_ENTRY |
488 | #define MI_ENTRY(N,T,F,B,M) { T, F, M, B }, | 488 | #define MI_ENTRY(N,T,F,B,M) { T, F, M, B }, |
489 | 489 | ||
490 | static const struct mode_info mode_info[] = { | 490 | static const struct mode_info mode_info[] ALIGN4 = { |
491 | /* This should be verbatim cut-n-paste copy of the above MI_ENTRYs */ | 491 | /* This should be verbatim cut-n-paste copy of the above MI_ENTRYs */ |
492 | MI_ENTRY("evenp", combination, REV | OMIT, 0, 0 ) | 492 | MI_ENTRY("evenp", combination, REV | OMIT, 0, 0 ) |
493 | MI_ENTRY("parity", combination, REV | OMIT, 0, 0 ) | 493 | MI_ENTRY("parity", combination, REV | OMIT, 0, 0 ) |
@@ -905,7 +905,7 @@ static void display_window_size(int fancy) | |||
905 | } | 905 | } |
906 | } | 906 | } |
907 | 907 | ||
908 | static const struct suffix_mult stty_suffixes[] = { | 908 | static const struct suffix_mult stty_suffixes[] ALIGN_SUFFIX = { |
909 | { "b", 512 }, | 909 | { "b", 512 }, |
910 | { "k", 1024 }, | 910 | { "k", 1024 }, |
911 | { "B", 1024 }, | 911 | { "B", 1024 }, |
diff --git a/coreutils/test.c b/coreutils/test.c index ac7b546a3..7c6574334 100644 --- a/coreutils/test.c +++ b/coreutils/test.c | |||
@@ -306,7 +306,7 @@ struct operator_t { | |||
306 | unsigned char op_num, op_type; | 306 | unsigned char op_num, op_type; |
307 | }; | 307 | }; |
308 | 308 | ||
309 | static const struct operator_t ops_table[] = { | 309 | static const struct operator_t ops_table[] ALIGN2 = { |
310 | { /* "-r" */ FILRD , UNOP }, | 310 | { /* "-r" */ FILRD , UNOP }, |
311 | { /* "-w" */ FILWR , UNOP }, | 311 | { /* "-w" */ FILWR , UNOP }, |
312 | { /* "-x" */ FILEX , UNOP }, | 312 | { /* "-x" */ FILEX , UNOP }, |
diff --git a/coreutils/timeout.c b/coreutils/timeout.c index 06c134a37..204a7ab92 100644 --- a/coreutils/timeout.c +++ b/coreutils/timeout.c | |||
@@ -41,7 +41,7 @@ | |||
41 | //usage:#define timeout_trivial_usage | 41 | //usage:#define timeout_trivial_usage |
42 | //usage: "[-s SIG] SECS PROG ARGS" | 42 | //usage: "[-s SIG] SECS PROG ARGS" |
43 | //usage:#define timeout_full_usage "\n\n" | 43 | //usage:#define timeout_full_usage "\n\n" |
44 | //usage: "Runs PROG. Sends SIG to it if it is not gone in SECS seconds.\n" | 44 | //usage: "Run PROG. Send SIG to it if it is not gone in SECS seconds.\n" |
45 | //usage: "Default SIG: TERM." | 45 | //usage: "Default SIG: TERM." |
46 | 46 | ||
47 | #include "libbb.h" | 47 | #include "libbb.h" |
@@ -130,7 +130,7 @@ int timeout_main(int argc UNUSED_PARAM, char **argv) | |||
130 | grandchild: | 130 | grandchild: |
131 | /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ | 131 | /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ |
132 | while (1) { | 132 | while (1) { |
133 | sleep(1); | 133 | sleep1(); |
134 | if (--timeout <= 0) | 134 | if (--timeout <= 0) |
135 | break; | 135 | break; |
136 | if (kill(parent, 0)) { | 136 | if (kill(parent, 0)) { |
diff --git a/coreutils/uniq.c b/coreutils/uniq.c index 317f45531..e1594286f 100644 --- a/coreutils/uniq.c +++ b/coreutils/uniq.c | |||
@@ -20,7 +20,7 @@ | |||
20 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/uniq.html */ | 20 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/uniq.html */ |
21 | 21 | ||
22 | //usage:#define uniq_trivial_usage | 22 | //usage:#define uniq_trivial_usage |
23 | //usage: "[-cdu][-f,s,w N] [INPUT [OUTPUT]]" | 23 | //usage: "[-cdui] [-f,s,w N] [INPUT [OUTPUT]]" |
24 | //usage:#define uniq_full_usage "\n\n" | 24 | //usage:#define uniq_full_usage "\n\n" |
25 | //usage: "Discard duplicate lines\n" | 25 | //usage: "Discard duplicate lines\n" |
26 | //usage: "\n -c Prefix lines by the number of occurrences" | 26 | //usage: "\n -c Prefix lines by the number of occurrences" |
diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c index 5b2edd649..164b208ea 100644 --- a/coreutils/uudecode.c +++ b/coreutils/uudecode.c | |||
@@ -168,9 +168,11 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv) | |||
168 | } | 168 | } |
169 | #endif | 169 | #endif |
170 | 170 | ||
171 | //applet:IF_BASE64(APPLET(base64, BB_DIR_BIN, BB_SUID_DROP)) | 171 | //config:config BASE32 |
172 | 172 | //config: bool "base32 (4.9 kb)" | |
173 | //kbuild:lib-$(CONFIG_BASE64) += uudecode.o | 173 | //config: default y |
174 | //config: help | ||
175 | //config: Base32 encode and decode | ||
174 | 176 | ||
175 | //config:config BASE64 | 177 | //config:config BASE64 |
176 | //config: bool "base64 (4.9 kb)" | 178 | //config: bool "base64 (4.9 kb)" |
@@ -178,49 +180,165 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv) | |||
178 | //config: help | 180 | //config: help |
179 | //config: Base64 encode and decode | 181 | //config: Base64 encode and decode |
180 | 182 | ||
183 | //usage:#define base32_trivial_usage | ||
184 | //usage: "[-d] [-w COL] [FILE]" | ||
185 | //usage:#define base32_full_usage "\n\n" | ||
186 | //usage: "Base32 encode or decode FILE to standard output" | ||
187 | //usage: "\n -d Decode data" | ||
188 | //usage: "\n -w COL Wrap lines at COL (default 76, 0 disables)" | ||
189 | ////usage: "\n -i When decoding, ignore non-alphabet characters" | ||
190 | |||
181 | //usage:#define base64_trivial_usage | 191 | //usage:#define base64_trivial_usage |
182 | //usage: "[-d] [FILE]" | 192 | //usage: "[-d] [-w COL] [FILE]" |
183 | //usage:#define base64_full_usage "\n\n" | 193 | //usage:#define base64_full_usage "\n\n" |
184 | //usage: "Base64 encode or decode FILE to standard output" | 194 | //usage: "Base64 encode or decode FILE to standard output" |
185 | //usage: "\n -d Decode data" | 195 | //usage: "\n -d Decode data" |
186 | ////usage: "\n -w COL Wrap lines at COL (default 76, 0 disables)" | 196 | //usage: "\n -w COL Wrap lines at COL (default 76, 0 disables)" |
187 | ////usage: "\n -i When decoding, ignore non-alphabet characters" | 197 | ////usage: "\n -i When decoding, ignore non-alphabet characters" |
188 | 198 | ||
189 | #if ENABLE_BASE64 | 199 | // APPLET_ODDNAME:name main location suid_type help |
190 | int base64_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 200 | //applet:IF_BASE32(APPLET_ODDNAME(base32, baseNUM, BB_DIR_BIN, BB_SUID_DROP, base32)) |
191 | int base64_main(int argc UNUSED_PARAM, char **argv) | 201 | //applet:IF_BASE64(APPLET_ODDNAME(base64, baseNUM, BB_DIR_BIN, BB_SUID_DROP, base64)) |
202 | |||
203 | //kbuild:lib-$(CONFIG_BASE64) += uudecode.o | ||
204 | //kbuild:lib-$(CONFIG_BASE32) += uudecode.o | ||
205 | |||
206 | #if ENABLE_BASE32 || ENABLE_BASE64 | ||
207 | |||
208 | # if ENABLE_BASE32 | ||
209 | static void bb_b32encode(char *p, const void *src, int length) | ||
210 | { | ||
211 | #define tbl bb_uuenc_tbl_base32 | ||
212 | const unsigned char *s = src; | ||
213 | |||
214 | /* Transform 5x8 bits to 8x5 bits */ | ||
215 | while (length > 0) { | ||
216 | unsigned cur, next; | ||
217 | |||
218 | length--; | ||
219 | cur = *s++; | ||
220 | *p++ = tbl[cur >> 3]; // xxxxx--- -------- -------- -------- -------- | ||
221 | cur &= 7; | ||
222 | |||
223 | next = 0; | ||
224 | if (--length >= 0) | ||
225 | next = *s++; | ||
226 | *p++ = tbl[(cur << 2) + (next >> 6)]; // -----xxx xx------ -------- -------- -------- | ||
227 | cur = next & 0x3f; | ||
228 | |||
229 | *p++ = tbl[cur >> 1]; // -------- --xxxxx- -------- -------- -------- | ||
230 | cur &= 1; | ||
231 | |||
232 | next = 0; | ||
233 | if (--length >= 0) | ||
234 | next = *s++; | ||
235 | *p++ = tbl[(cur << 4) + (next >> 4)]; // -------- -------x xxxx---- -------- -------- | ||
236 | cur = next & 0xf; | ||
237 | |||
238 | next = 0; | ||
239 | if (--length >= 0) | ||
240 | next = *s++; | ||
241 | *p++ = tbl[(cur << 1) + (next >> 7)]; // -------- -------- ----xxxx x------- -------- | ||
242 | cur = next & 0x7f; | ||
243 | |||
244 | *p++ = tbl[cur >> 2]; // -------- -------- -------- -xxxxx-- -------- | ||
245 | cur &= 3; | ||
246 | |||
247 | next = 0; | ||
248 | if (--length >= 0) | ||
249 | next = *s++; | ||
250 | *p++ = tbl[(cur << 3) + (next >> 5)]; // -------- -------- -------- ------xx xxx----- | ||
251 | cur = next & 0x1f; | ||
252 | |||
253 | *p++ = tbl[cur]; // -------- -------- -------- -------- ---xxxxx | ||
254 | } | ||
255 | #undef tbl | ||
256 | /* Zero-terminate */ | ||
257 | *p = '\0'; | ||
258 | /* Pad as necessary */ | ||
259 | length = ((-length) * 3) >> 1; /* -4 => 6 pad chars, -3 => 4, -2 => 3, -1 => 1 */ | ||
260 | while (length--) { | ||
261 | *--p = '='; | ||
262 | } | ||
263 | } | ||
264 | # else | ||
265 | void bb_b32encode(char *p, const void *src, int length); /* undefined */ | ||
266 | # endif | ||
267 | |||
268 | int baseNUM_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
269 | int baseNUM_main(int argc UNUSED_PARAM, char **argv) | ||
192 | { | 270 | { |
193 | FILE *src_stream; | 271 | FILE *src_stream; |
194 | unsigned opts; | 272 | unsigned opts; |
273 | unsigned col = 76; | ||
195 | 274 | ||
196 | opts = getopt32(argv, "^" "d" "\0" "?1"/* 1 arg max*/); | 275 | opts = getopt32(argv, "^" "dw:+" "\0" "?1"/* 1 arg max*/, &col); |
197 | argv += optind; | 276 | argv += optind; |
198 | 277 | ||
199 | if (!argv[0]) | 278 | if (!argv[0]) |
200 | *--argv = (char*)"-"; | 279 | *--argv = (char*)"-"; |
201 | src_stream = xfopen_stdin(argv[0]); | 280 | src_stream = xfopen_stdin(argv[0]); |
202 | if (opts) { | 281 | if (opts & 1) { |
203 | read_base64(src_stream, stdout, /*flags:*/ (unsigned char)EOF); | 282 | /* -d: decode */ |
283 | int flags = (unsigned char)EOF; | ||
284 | if (ENABLE_BASE32 && (!ENABLE_BASE64 || applet_name[4] == '3')) | ||
285 | flags = ((unsigned char)EOF) | BASE64_32; | ||
286 | read_base64(src_stream, stdout, flags); | ||
204 | } else { | 287 | } else { |
205 | enum { | 288 | enum { |
206 | SRC_BUF_SIZE = 76 / 4 * 3, /* this *MUST* be a multiple of 3 */ | 289 | SRC_BUF_SIZE = 3 * 5 * 32, /* this *MUST* be a multiple of 3 and 5 */ |
207 | DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3), | 290 | DST_BUF_SIZE = 8 * ((SRC_BUF_SIZE + 4) / 5), /* max growth on encode (base32 case) */ |
208 | }; | 291 | }; |
209 | char src_buf[SRC_BUF_SIZE]; | 292 | /* Use one buffer for both input and output: |
210 | char dst_buf[DST_BUF_SIZE + 1]; | 293 | * encoding reads input "left-to-right", |
211 | int src_fd = fileno(src_stream); | 294 | * it's safe to place source at the end of the buffer and |
295 | * overwrite it while encoding, just be careful to have a gap. | ||
296 | */ | ||
297 | char dst_buf[((DST_BUF_SIZE + /*gap:*/ 16) /*round up to 16:*/ | 0xf) + 1]; | ||
298 | #define src_buf (dst_buf + sizeof(dst_buf) - SRC_BUF_SIZE) | ||
299 | int src_fd, rem; | ||
300 | |||
301 | src_fd = fileno(src_stream); | ||
302 | rem = 0; | ||
212 | while (1) { | 303 | while (1) { |
213 | size_t size = full_read(src_fd, src_buf, SRC_BUF_SIZE); | 304 | size_t size = full_read(src_fd, src_buf, SRC_BUF_SIZE); |
214 | if (!size) | ||
215 | break; | ||
216 | if ((ssize_t)size < 0) | 305 | if ((ssize_t)size < 0) |
217 | bb_simple_perror_msg_and_die(bb_msg_read_error); | 306 | bb_simple_perror_msg_and_die(bb_msg_read_error); |
307 | if (size == 0) { | ||
308 | if (rem != 0) bb_putchar('\n'); | ||
309 | break; | ||
310 | } | ||
311 | |||
218 | /* Encode the buffer we just read in */ | 312 | /* Encode the buffer we just read in */ |
219 | bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64); | 313 | if (ENABLE_BASE32 && (!ENABLE_BASE64 || applet_name[4] == '3')) { |
220 | xwrite(STDOUT_FILENO, dst_buf, 4 * ((size + 2) / 3)); | 314 | bb_b32encode(dst_buf, src_buf, size); |
221 | bb_putchar('\n'); | 315 | size = 8 * ((size + 4) / 5); |
222 | fflush(stdout); | 316 | } else { |
317 | bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64); | ||
318 | size = 4 * ((size + 2) / 3); | ||
319 | } | ||
320 | |||
321 | if (col == 0) { | ||
322 | fputs(dst_buf, stdout); | ||
323 | } else { | ||
324 | char *result = dst_buf; | ||
325 | if (rem == 0) | ||
326 | rem = col; | ||
327 | while (1) { | ||
328 | int out = size < rem ? size : rem; | ||
329 | rem -= out; | ||
330 | printf(rem != 0 ? "%.*s" : "%.*s\n", out, result); | ||
331 | if (rem != 0) | ||
332 | break; | ||
333 | size -= out; | ||
334 | if (size == 0) | ||
335 | break; | ||
336 | result += out; | ||
337 | rem = col; | ||
338 | } | ||
339 | } | ||
223 | } | 340 | } |
341 | #undef src_buf | ||
224 | } | 342 | } |
225 | 343 | ||
226 | fflush_stdout_and_exit(EXIT_SUCCESS); | 344 | fflush_stdout_and_exit(EXIT_SUCCESS); |
diff --git a/debianutils/which.c b/debianutils/which.c index 1d23786b8..f5ea17198 100644 --- a/debianutils/which.c +++ b/debianutils/which.c | |||
@@ -17,9 +17,9 @@ | |||
17 | //kbuild:lib-$(CONFIG_WHICH) += which.o | 17 | //kbuild:lib-$(CONFIG_WHICH) += which.o |
18 | 18 | ||
19 | //usage:#define which_trivial_usage | 19 | //usage:#define which_trivial_usage |
20 | //usage: "[COMMAND]..." | 20 | //usage: "COMMAND..." |
21 | //usage:#define which_full_usage "\n\n" | 21 | //usage:#define which_full_usage "\n\n" |
22 | //usage: "Locate a COMMAND" | 22 | //usage: "Locate COMMAND" |
23 | //usage: | 23 | //usage: |
24 | //usage:#define which_example_usage | 24 | //usage:#define which_example_usage |
25 | //usage: "$ which login\n" | 25 | //usage: "$ which login\n" |
diff --git a/e2fsprogs/e2fs_lib.c b/e2fsprogs/e2fs_lib.c index 3b776bc97..d0cacf14c 100644 --- a/e2fsprogs/e2fs_lib.c +++ b/e2fsprogs/e2fs_lib.c | |||
@@ -159,7 +159,7 @@ int fgetsetflags(const char *name, unsigned long *get_flags, unsigned long set_f | |||
159 | 159 | ||
160 | #if !ENABLE_PLATFORM_MINGW32 | 160 | #if !ENABLE_PLATFORM_MINGW32 |
161 | /* Print file attributes on an ext2 file system */ | 161 | /* Print file attributes on an ext2 file system */ |
162 | const uint32_t e2attr_flags_value[] = { | 162 | const uint32_t e2attr_flags_value[] ALIGN4 = { |
163 | #ifdef ENABLE_COMPRESSION | 163 | #ifdef ENABLE_COMPRESSION |
164 | EXT2_COMPRBLK_FL, | 164 | EXT2_COMPRBLK_FL, |
165 | EXT2_DIRTY_FL, | 165 | EXT2_DIRTY_FL, |
diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c index fc53a9043..96c1e51e0 100644 --- a/e2fsprogs/fsck.c +++ b/e2fsprogs/fsck.c | |||
@@ -480,7 +480,7 @@ static int wait_one(int flags) | |||
480 | * time to set up the signal handler | 480 | * time to set up the signal handler |
481 | */ | 481 | */ |
482 | if (inst2->start_time >= time(NULL) - 1) | 482 | if (inst2->start_time >= time(NULL) - 1) |
483 | sleep(1); | 483 | sleep1(); |
484 | kill(inst2->pid, SIGUSR1); | 484 | kill(inst2->pid, SIGUSR1); |
485 | inst2->flags |= FLAG_PROGRESS; | 485 | inst2->flags |= FLAG_PROGRESS; |
486 | break; | 486 | break; |
diff --git a/editors/awk.c b/editors/awk.c index 509f4ddd8..4799091ec 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -405,7 +405,7 @@ static const char tokenlist[] ALIGN1 = | |||
405 | 405 | ||
406 | #define OC_B OC_BUILTIN | 406 | #define OC_B OC_BUILTIN |
407 | 407 | ||
408 | static const uint32_t tokeninfo[] = { | 408 | static const uint32_t tokeninfo[] ALIGN4 = { |
409 | 0, | 409 | 0, |
410 | 0, | 410 | 0, |
411 | OC_REGEXP, | 411 | OC_REGEXP, |
@@ -1767,12 +1767,34 @@ static void fsrealloc(int size) | |||
1767 | nfields = size; | 1767 | nfields = size; |
1768 | } | 1768 | } |
1769 | 1769 | ||
1770 | static int regexec1_nonempty(const regex_t *preg, const char *s, regmatch_t pmatch[]) | ||
1771 | { | ||
1772 | int r = regexec(preg, s, 1, pmatch, 0); | ||
1773 | if (r == 0 && pmatch[0].rm_eo == 0) { | ||
1774 | /* For example, happens when FS can match | ||
1775 | * an empty string (awk -F ' *'). Logically, | ||
1776 | * this should split into one-char fields. | ||
1777 | * However, gawk 5.0.1 searches for first | ||
1778 | * _non-empty_ separator string match: | ||
1779 | */ | ||
1780 | size_t ofs = 0; | ||
1781 | do { | ||
1782 | ofs++; | ||
1783 | if (!s[ofs]) | ||
1784 | return REG_NOMATCH; | ||
1785 | regexec(preg, s + ofs, 1, pmatch, 0); | ||
1786 | } while (pmatch[0].rm_eo == 0); | ||
1787 | pmatch[0].rm_so += ofs; | ||
1788 | pmatch[0].rm_eo += ofs; | ||
1789 | } | ||
1790 | return r; | ||
1791 | } | ||
1792 | |||
1770 | static int awk_split(const char *s, node *spl, char **slist) | 1793 | static int awk_split(const char *s, node *spl, char **slist) |
1771 | { | 1794 | { |
1772 | int l, n; | 1795 | int n; |
1773 | char c[4]; | 1796 | char c[4]; |
1774 | char *s1; | 1797 | char *s1; |
1775 | regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough... | ||
1776 | 1798 | ||
1777 | /* in worst case, each char would be a separate field */ | 1799 | /* in worst case, each char would be a separate field */ |
1778 | *slist = s1 = xzalloc(strlen(s) * 2 + 3); | 1800 | *slist = s1 = xzalloc(strlen(s) * 2 + 3); |
@@ -1789,29 +1811,31 @@ static int awk_split(const char *s, node *spl, char **slist) | |||
1789 | return n; /* "": zero fields */ | 1811 | return n; /* "": zero fields */ |
1790 | n++; /* at least one field will be there */ | 1812 | n++; /* at least one field will be there */ |
1791 | do { | 1813 | do { |
1814 | int l; | ||
1815 | regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough... | ||
1816 | |||
1792 | l = strcspn(s, c+2); /* len till next NUL or \n */ | 1817 | l = strcspn(s, c+2); /* len till next NUL or \n */ |
1793 | if (regexec(icase ? spl->r.ire : spl->l.re, s, 1, pmatch, 0) == 0 | 1818 | if (regexec1_nonempty(icase ? spl->r.ire : spl->l.re, s, pmatch) == 0 |
1794 | && pmatch[0].rm_so <= l | 1819 | && pmatch[0].rm_so <= l |
1795 | ) { | 1820 | ) { |
1821 | /* if (pmatch[0].rm_eo == 0) ... - impossible */ | ||
1796 | l = pmatch[0].rm_so; | 1822 | l = pmatch[0].rm_so; |
1797 | if (pmatch[0].rm_eo == 0) { | ||
1798 | l++; | ||
1799 | pmatch[0].rm_eo++; | ||
1800 | } | ||
1801 | n++; /* we saw yet another delimiter */ | 1823 | n++; /* we saw yet another delimiter */ |
1802 | } else { | 1824 | } else { |
1803 | pmatch[0].rm_eo = l; | 1825 | pmatch[0].rm_eo = l; |
1804 | if (s[l]) | 1826 | if (s[l]) |
1805 | pmatch[0].rm_eo++; | 1827 | pmatch[0].rm_eo++; |
1806 | } | 1828 | } |
1807 | memcpy(s1, s, l); | 1829 | s1 = mempcpy(s1, s, l); |
1808 | /* make sure we remove *all* of the separator chars */ | 1830 | *s1++ = '\0'; |
1809 | do { | ||
1810 | s1[l] = '\0'; | ||
1811 | } while (++l < pmatch[0].rm_eo); | ||
1812 | nextword(&s1); | ||
1813 | s += pmatch[0].rm_eo; | 1831 | s += pmatch[0].rm_eo; |
1814 | } while (*s); | 1832 | } while (*s); |
1833 | |||
1834 | /* echo a-- | awk -F-- '{ print NF, length($NF), $NF }' | ||
1835 | * should print "2 0 ": | ||
1836 | */ | ||
1837 | *s1 = '\0'; | ||
1838 | |||
1815 | return n; | 1839 | return n; |
1816 | } | 1840 | } |
1817 | if (c[0] == '\0') { /* null split */ | 1841 | if (c[0] == '\0') { /* null split */ |
@@ -2030,7 +2054,7 @@ static ssize_t FAST_FUNC safe_read_strip_cr(int fd, void *buf, size_t count) | |||
2030 | static int awk_getline(rstream *rsm, var *v) | 2054 | static int awk_getline(rstream *rsm, var *v) |
2031 | { | 2055 | { |
2032 | char *b; | 2056 | char *b; |
2033 | regmatch_t pmatch[2]; | 2057 | regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough... |
2034 | int size, a, p, pp = 0; | 2058 | int size, a, p, pp = 0; |
2035 | int fd, so, eo, r, rp; | 2059 | int fd, so, eo, r, rp; |
2036 | char c, *m, *s; | 2060 | char c, *m, *s; |
diff --git a/editors/patch.c b/editors/patch.c index aaa253591..110176630 100644 --- a/editors/patch.c +++ b/editors/patch.c | |||
@@ -31,7 +31,7 @@ | |||
31 | //kbuild:lib-$(CONFIG_PATCH) += patch.o | 31 | //kbuild:lib-$(CONFIG_PATCH) += patch.o |
32 | 32 | ||
33 | //usage:#define patch_trivial_usage | 33 | //usage:#define patch_trivial_usage |
34 | //usage: "[OPTIONS] [ORIGFILE [PATCHFILE]]" | 34 | //usage: "[-RNE] [-p N] [-i DIFF] [ORIGFILE [PATCHFILE]]" |
35 | //usage:#define patch_full_usage "\n\n" | 35 | //usage:#define patch_full_usage "\n\n" |
36 | //usage: " -p N Strip N leading components from file names" | 36 | //usage: " -p N Strip N leading components from file names" |
37 | //usage: "\n -i DIFF Read DIFF instead of stdin" | 37 | //usage: "\n -i DIFF Read DIFF instead of stdin" |
diff --git a/editors/vi.c b/editors/vi.c index 131c018a2..bfe05d613 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -166,7 +166,7 @@ | |||
166 | //kbuild:lib-$(CONFIG_VI) += vi.o | 166 | //kbuild:lib-$(CONFIG_VI) += vi.o |
167 | 167 | ||
168 | //usage:#define vi_trivial_usage | 168 | //usage:#define vi_trivial_usage |
169 | //usage: "[OPTIONS] [FILE]..." | 169 | //usage: IF_FEATURE_VI_COLON("[-c CMD] ")IF_FEATURE_VI_READONLY("[-R] ")"[FILE]..." |
170 | //usage:#define vi_full_usage "\n\n" | 170 | //usage:#define vi_full_usage "\n\n" |
171 | //usage: "Edit FILE\n" | 171 | //usage: "Edit FILE\n" |
172 | //usage: IF_FEATURE_VI_COLON( | 172 | //usage: IF_FEATURE_VI_COLON( |
diff --git a/examples/inetd.conf b/examples/inetd.conf index ca7e3d8e1..78b10e3ac 100644 --- a/examples/inetd.conf +++ b/examples/inetd.conf | |||
@@ -31,7 +31,7 @@ time dgram udp wait root internal | |||
31 | #ftp stream tcp nowait root /usr/sbin/tcpd in.ftpd | 31 | #ftp stream tcp nowait root /usr/sbin/tcpd in.ftpd |
32 | #telnet stream tcp nowait root /sbin/telnetd /sbin/telnetd | 32 | #telnet stream tcp nowait root /sbin/telnetd /sbin/telnetd |
33 | #nntp stream tcp nowait root tcpd in.nntpd | 33 | #nntp stream tcp nowait root tcpd in.nntpd |
34 | #smtp stream tcp nowait root tcpd sendmail -v | 34 | #smtp stream tcp nowait root tcpd sendmail -v |
35 | # | 35 | # |
36 | # Shell, login, exec and talk are BSD protocols. | 36 | # Shell, login, exec and talk are BSD protocols. |
37 | # | 37 | # |
diff --git a/examples/udhcp/sample.bound b/examples/udhcp/sample.bound index efd98cf15..15a7775e9 100755 --- a/examples/udhcp/sample.bound +++ b/examples/udhcp/sample.bound | |||
@@ -6,12 +6,12 @@ RESOLV_CONF="/etc/udhcpc/resolv.conf" | |||
6 | [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" | 6 | [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" |
7 | [ -n "$subnet" ] && NETMASK="netmask $subnet" | 7 | [ -n "$subnet" ] && NETMASK="netmask $subnet" |
8 | 8 | ||
9 | /sbin/ifconfig $interface $ip $BROADCAST $NETMASK | 9 | ifconfig $interface $ip $BROADCAST $NETMASK |
10 | 10 | ||
11 | if [ -n "$router" ] | 11 | if [ -n "$router" ] |
12 | then | 12 | then |
13 | echo "deleting routers" | 13 | echo "deleting routers" |
14 | while /sbin/route del default gw 0.0.0.0 dev $interface | 14 | while route del default gw 0.0.0.0 dev $interface |
15 | do : | 15 | do : |
16 | done | 16 | done |
17 | 17 | ||
@@ -23,9 +23,9 @@ then | |||
23 | # /32 instructs kernel to always use routing for all outgoing packets | 23 | # /32 instructs kernel to always use routing for all outgoing packets |
24 | # (they can never be sent to local subnet - there is no local subnet for /32). | 24 | # (they can never be sent to local subnet - there is no local subnet for /32). |
25 | # Used in datacenters, avoids the need for private ip-addresses between two hops. | 25 | # Used in datacenters, avoids the need for private ip-addresses between two hops. |
26 | /sbin/ip route add $i dev $interface | 26 | ip route add $i dev $interface |
27 | fi | 27 | fi |
28 | /sbin/route add default gw $i dev $interface metric $((metric++)) | 28 | route add default gw $i dev $interface metric $((metric++)) |
29 | done | 29 | done |
30 | fi | 30 | fi |
31 | 31 | ||
diff --git a/examples/udhcp/sample.deconfig b/examples/udhcp/sample.deconfig index b221bcf12..a893de83f 100755 --- a/examples/udhcp/sample.deconfig +++ b/examples/udhcp/sample.deconfig | |||
@@ -1,4 +1,4 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | # Sample udhcpc deconfig script | 2 | # Sample udhcpc deconfig script |
3 | 3 | ||
4 | /sbin/ifconfig $interface 0.0.0.0 | 4 | ifconfig $interface 0.0.0.0 |
diff --git a/examples/udhcp/sample.renew b/examples/udhcp/sample.renew index efd98cf15..15a7775e9 100755 --- a/examples/udhcp/sample.renew +++ b/examples/udhcp/sample.renew | |||
@@ -6,12 +6,12 @@ RESOLV_CONF="/etc/udhcpc/resolv.conf" | |||
6 | [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" | 6 | [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" |
7 | [ -n "$subnet" ] && NETMASK="netmask $subnet" | 7 | [ -n "$subnet" ] && NETMASK="netmask $subnet" |
8 | 8 | ||
9 | /sbin/ifconfig $interface $ip $BROADCAST $NETMASK | 9 | ifconfig $interface $ip $BROADCAST $NETMASK |
10 | 10 | ||
11 | if [ -n "$router" ] | 11 | if [ -n "$router" ] |
12 | then | 12 | then |
13 | echo "deleting routers" | 13 | echo "deleting routers" |
14 | while /sbin/route del default gw 0.0.0.0 dev $interface | 14 | while route del default gw 0.0.0.0 dev $interface |
15 | do : | 15 | do : |
16 | done | 16 | done |
17 | 17 | ||
@@ -23,9 +23,9 @@ then | |||
23 | # /32 instructs kernel to always use routing for all outgoing packets | 23 | # /32 instructs kernel to always use routing for all outgoing packets |
24 | # (they can never be sent to local subnet - there is no local subnet for /32). | 24 | # (they can never be sent to local subnet - there is no local subnet for /32). |
25 | # Used in datacenters, avoids the need for private ip-addresses between two hops. | 25 | # Used in datacenters, avoids the need for private ip-addresses between two hops. |
26 | /sbin/ip route add $i dev $interface | 26 | ip route add $i dev $interface |
27 | fi | 27 | fi |
28 | /sbin/route add default gw $i dev $interface metric $((metric++)) | 28 | route add default gw $i dev $interface metric $((metric++)) |
29 | done | 29 | done |
30 | fi | 30 | fi |
31 | 31 | ||
diff --git a/findutils/find.c b/findutils/find.c index f26c01c1e..188865e05 100644 --- a/findutils/find.c +++ b/findutils/find.c | |||
@@ -1445,7 +1445,7 @@ static action*** parse_params(char **argv) | |||
1445 | #else | 1445 | #else |
1446 | #define XATOU_SFX xatoul_sfx | 1446 | #define XATOU_SFX xatoul_sfx |
1447 | #endif | 1447 | #endif |
1448 | static const struct suffix_mult find_suffixes[] = { | 1448 | static const struct suffix_mult find_suffixes[] ALIGN_SUFFIX = { |
1449 | { "c", 1 }, | 1449 | { "c", 1 }, |
1450 | { "w", 2 }, | 1450 | { "w", 2 }, |
1451 | { "", 512 }, | 1451 | { "", 512 }, |
@@ -1526,7 +1526,7 @@ int find_main(int argc UNUSED_PARAM, char **argv) | |||
1526 | } | 1526 | } |
1527 | *past_HLP = NULL; | 1527 | *past_HLP = NULL; |
1528 | /* "+": stop on first non-option */ | 1528 | /* "+": stop on first non-option */ |
1529 | i = getopt32(argv, "+HLP"); | 1529 | i = getopt32(argv, "+""HLP"); |
1530 | if (i & (1<<0)) | 1530 | if (i & (1<<0)) |
1531 | G.recurse_flags |= ACTION_FOLLOWLINKS_L0 | ACTION_DANGLING_OK; | 1531 | G.recurse_flags |= ACTION_FOLLOWLINKS_L0 | ACTION_DANGLING_OK; |
1532 | if (i & (1<<1)) | 1532 | if (i & (1<<1)) |
diff --git a/include/ar.h b/include/ar_.h index 386fe0456..386fe0456 100644 --- a/include/ar.h +++ b/include/ar_.h | |||
diff --git a/include/libbb.h b/include/libbb.h index eb8b63895..3d6a6a0cf 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -106,7 +106,11 @@ | |||
106 | # define updwtmpx updwtmp | 106 | # define updwtmpx updwtmp |
107 | # define _PATH_UTMPX _PATH_UTMP | 107 | # define _PATH_UTMPX _PATH_UTMP |
108 | # else | 108 | # else |
109 | # include <utmp.h> | 109 | # if !defined(__FreeBSD__) |
110 | # include <utmp.h> | ||
111 | # else | ||
112 | # define _PATH_UTMPX "/var/run/utx.active" | ||
113 | # endif | ||
110 | # include <utmpx.h> | 114 | # include <utmpx.h> |
111 | # if defined _PATH_UTMP && !defined _PATH_UTMPX | 115 | # if defined _PATH_UTMP && !defined _PATH_UTMPX |
112 | # define _PATH_UTMPX _PATH_UTMP | 116 | # define _PATH_UTMPX _PATH_UTMP |
@@ -405,6 +409,32 @@ void* xrealloc_vector_helper(void *vector, unsigned sizeof_and_shift, int idx) F | |||
405 | char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC; | 409 | char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC; |
406 | char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC; | 410 | char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC; |
407 | void *xmemdup(const void *s, int n) FAST_FUNC RETURNS_MALLOC; | 411 | void *xmemdup(const void *s, int n) FAST_FUNC RETURNS_MALLOC; |
412 | void *mmap_read(int fd, size_t size) FAST_FUNC; | ||
413 | void *mmap_anon(size_t size) FAST_FUNC; | ||
414 | void *xmmap_anon(size_t size) FAST_FUNC; | ||
415 | |||
416 | #if defined(__x86_64__) || defined(i386) | ||
417 | # define BB_ARCH_FIXED_PAGESIZE 4096 | ||
418 | #elif defined(__arm__) /* only 32bit, 64bit ARM has variable page size */ | ||
419 | # define BB_ARCH_FIXED_PAGESIZE 4096 | ||
420 | #else /* if defined(ARCH) */ | ||
421 | /* add you favorite arch today! */ | ||
422 | //From Linux kernel inspection: | ||
423 | //xtenza,s390[x],riscv,nios2,csky,sparc32: fixed 4k pages | ||
424 | //sparc64,alpha,openrisc: fixed 8k pages | ||
425 | #endif | ||
426 | |||
427 | #if defined BB_ARCH_FIXED_PAGESIZE | ||
428 | # define IF_VARIABLE_ARCH_PAGESIZE(...) /*nothing*/ | ||
429 | # define bb_getpagesize() BB_ARCH_FIXED_PAGESIZE | ||
430 | # define INIT_PAGESIZE(var) ((void)0) | ||
431 | # define cached_pagesize(var) BB_ARCH_FIXED_PAGESIZE | ||
432 | #else | ||
433 | # define IF_VARIABLE_ARCH_PAGESIZE(...) __VA_ARGS__ | ||
434 | # define bb_getpagesize() getpagesize() | ||
435 | # define INIT_PAGESIZE(var) ((var) = getpagesize()) | ||
436 | # define cached_pagesize(var) (var) | ||
437 | #endif | ||
408 | 438 | ||
409 | 439 | ||
410 | //TODO: supply a pointer to char[11] buffer (avoid statics)? | 440 | //TODO: supply a pointer to char[11] buffer (avoid statics)? |
@@ -670,6 +700,9 @@ void parse_datestr(const char *date_str, struct tm *ptm) FAST_FUNC; | |||
670 | time_t validate_tm_time(const char *date_str, struct tm *ptm) FAST_FUNC; | 700 | time_t validate_tm_time(const char *date_str, struct tm *ptm) FAST_FUNC; |
671 | char *strftime_HHMMSS(char *buf, unsigned len, time_t *tp) FAST_FUNC; | 701 | char *strftime_HHMMSS(char *buf, unsigned len, time_t *tp) FAST_FUNC; |
672 | char *strftime_YYYYMMDDHHMMSS(char *buf, unsigned len, time_t *tp) FAST_FUNC; | 702 | char *strftime_YYYYMMDDHHMMSS(char *buf, unsigned len, time_t *tp) FAST_FUNC; |
703 | void xgettimeofday(struct timeval *tv) FAST_FUNC; | ||
704 | void xsettimeofday(const struct timeval *tv) FAST_FUNC; | ||
705 | |||
673 | 706 | ||
674 | int xsocket(int domain, int type, int protocol) FAST_FUNC; | 707 | int xsocket(int domain, int type, int protocol) FAST_FUNC; |
675 | void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen) FAST_FUNC; | 708 | void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen) FAST_FUNC; |
@@ -1065,8 +1098,9 @@ void generate_uuid(uint8_t *buf) FAST_FUNC; | |||
1065 | /* Last element is marked by mult == 0 */ | 1098 | /* Last element is marked by mult == 0 */ |
1066 | struct suffix_mult { | 1099 | struct suffix_mult { |
1067 | char suffix[4]; | 1100 | char suffix[4]; |
1068 | unsigned mult; | 1101 | uint32_t mult; |
1069 | }; | 1102 | }; |
1103 | #define ALIGN_SUFFIX ALIGN4 | ||
1070 | extern const struct suffix_mult bkm_suffixes[]; | 1104 | extern const struct suffix_mult bkm_suffixes[]; |
1071 | #define km_suffixes (bkm_suffixes + 1) | 1105 | #define km_suffixes (bkm_suffixes + 1) |
1072 | extern const struct suffix_mult cwbkMG_suffixes[]; | 1106 | extern const struct suffix_mult cwbkMG_suffixes[]; |
@@ -1178,7 +1212,6 @@ int BB_EXECVP(const char *file, char *const argv[]) FAST_FUNC; | |||
1178 | #define BB_EXECLP(prog,cmd,...) execlp(prog,cmd,__VA_ARGS__) | 1212 | #define BB_EXECLP(prog,cmd,...) execlp(prog,cmd,__VA_ARGS__) |
1179 | #endif | 1213 | #endif |
1180 | void BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC; | 1214 | void BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC; |
1181 | void exec_prog_or_SHELL(char **argv) NORETURN FAST_FUNC; | ||
1182 | 1215 | ||
1183 | /* xvfork() can't be a _function_, return after vfork in child mangles stack | 1216 | /* xvfork() can't be a _function_, return after vfork in child mangles stack |
1184 | * in the parent. It must be a macro. */ | 1217 | * in the parent. It must be a macro. */ |
@@ -1644,12 +1677,14 @@ char *bb_simplify_path(const char *path) FAST_FUNC; | |||
1644 | /* Returns ptr to NUL */ | 1677 | /* Returns ptr to NUL */ |
1645 | char *bb_simplify_abs_path_inplace(char *path) FAST_FUNC; | 1678 | char *bb_simplify_abs_path_inplace(char *path) FAST_FUNC; |
1646 | 1679 | ||
1647 | #ifndef LOGIN_FAIL_DELAY | 1680 | void pause_after_failed_login(void) FAST_FUNC; |
1648 | #define LOGIN_FAIL_DELAY 3 | 1681 | void bb_do_delay(unsigned seconds) FAST_FUNC; |
1649 | #endif | 1682 | void msleep(unsigned ms) FAST_FUNC; |
1650 | extern void bb_do_delay(int seconds) FAST_FUNC; | 1683 | void sleep1(void) FAST_FUNC; |
1651 | extern void change_identity(const struct passwd *pw) FAST_FUNC; | 1684 | void change_identity(const struct passwd *pw) FAST_FUNC; |
1652 | extern void run_shell(const char *shell, int loginshell, const char **args) NORETURN FAST_FUNC; | 1685 | void exec_shell(const char *shell, int loginshell, const char **args) NORETURN FAST_FUNC; |
1686 | void exec_login_shell(const char *shell) NORETURN FAST_FUNC; | ||
1687 | void exec_prog_or_SHELL(char **argv) NORETURN FAST_FUNC; | ||
1653 | 1688 | ||
1654 | /* Returns $SHELL, getpwuid(getuid())->pw_shell, or DEFAULT_SHELL. | 1689 | /* Returns $SHELL, getpwuid(getuid())->pw_shell, or DEFAULT_SHELL. |
1655 | * Note that getpwuid result might need xstrdup'ing | 1690 | * Note that getpwuid result might need xstrdup'ing |
@@ -1884,14 +1919,20 @@ typedef const char *get_exe_name_t(int i) FAST_FUNC; | |||
1884 | typedef struct line_input_t { | 1919 | typedef struct line_input_t { |
1885 | int flags; | 1920 | int flags; |
1886 | int timeout; | 1921 | int timeout; |
1922 | # if ENABLE_FEATURE_TAB_COMPLETION | ||
1923 | # if ENABLE_SHELL_ASH | ||
1887 | const char *path_lookup; | 1924 | const char *path_lookup; |
1888 | # if ENABLE_FEATURE_TAB_COMPLETION \ | 1925 | # define EDITING_HAS_path_lookup 1 |
1889 | && (ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH \ | 1926 | # else |
1890 | || ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH \ | 1927 | # define EDITING_HAS_path_lookup 0 |
1891 | ) | 1928 | # endif |
1929 | # if ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH | ||
1892 | /* function to fetch additional application-specific names to match */ | 1930 | /* function to fetch additional application-specific names to match */ |
1893 | get_exe_name_t *get_exe_name; | 1931 | get_exe_name_t *get_exe_name; |
1894 | # define EDITING_HAS_get_exe_name 1 | 1932 | # define EDITING_HAS_get_exe_name 1 |
1933 | # else | ||
1934 | # define EDITING_HAS_get_exe_name 0 | ||
1935 | # endif | ||
1895 | # endif | 1936 | # endif |
1896 | # if MAX_HISTORY | 1937 | # if MAX_HISTORY |
1897 | int cnt_history; | 1938 | int cnt_history; |
@@ -1919,7 +1960,11 @@ enum { | |||
1919 | FOR_SHELL = DO_HISTORY | TAB_COMPLETION | USERNAME_COMPLETION, | 1960 | FOR_SHELL = DO_HISTORY | TAB_COMPLETION | USERNAME_COMPLETION, |
1920 | }; | 1961 | }; |
1921 | line_input_t *new_line_input_t(int flags) FAST_FUNC; | 1962 | line_input_t *new_line_input_t(int flags) FAST_FUNC; |
1963 | #if ENABLE_FEATURE_EDITING_SAVEHISTORY | ||
1922 | void free_line_input_t(line_input_t *n) FAST_FUNC; | 1964 | void free_line_input_t(line_input_t *n) FAST_FUNC; |
1965 | #else | ||
1966 | # define free_line_input_t(n) free(n) | ||
1967 | #endif | ||
1923 | /* | 1968 | /* |
1924 | * maxsize must be >= 2. | 1969 | * maxsize must be >= 2. |
1925 | * Returns: | 1970 | * Returns: |
@@ -2079,14 +2124,17 @@ char *percent_decode_in_place(char *str, int strict) FAST_FUNC; | |||
2079 | 2124 | ||
2080 | 2125 | ||
2081 | extern const char bb_uuenc_tbl_base64[] ALIGN1; | 2126 | extern const char bb_uuenc_tbl_base64[] ALIGN1; |
2127 | extern const char bb_uuenc_tbl_base32[] ALIGN1; | ||
2082 | extern const char bb_uuenc_tbl_std[] ALIGN1; | 2128 | extern const char bb_uuenc_tbl_std[] ALIGN1; |
2083 | void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC; | 2129 | void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC; |
2084 | enum { | 2130 | enum { |
2085 | BASE64_FLAG_UU_STOP = 0x100, | 2131 | BASE64_FLAG_UU_STOP = 0x100, |
2132 | BASE64_32 = 0x200, /* base32 */ | ||
2086 | /* Sign-extends to a value which never matches fgetc result: */ | 2133 | /* Sign-extends to a value which never matches fgetc result: */ |
2087 | BASE64_FLAG_NO_STOP_CHAR = 0x80, | 2134 | BASE64_FLAG_NO_STOP_CHAR = 0x80, |
2088 | }; | 2135 | }; |
2089 | const char *decode_base64(char **pp_dst, const char *src) FAST_FUNC; | 2136 | char *decode_base64(char *dst, const char **pp_src) FAST_FUNC; |
2137 | char *decode_base32(char *dst, const char **pp_src) FAST_FUNC; | ||
2090 | void read_base64(FILE *src_stream, FILE *dst_stream, int flags) FAST_FUNC; | 2138 | void read_base64(FILE *src_stream, FILE *dst_stream, int flags) FAST_FUNC; |
2091 | 2139 | ||
2092 | typedef struct md5_ctx_t { | 2140 | typedef struct md5_ctx_t { |
diff --git a/include/mingw.h b/include/mingw.h index 8af2e3938..d1e638231 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -31,6 +31,7 @@ int inet_pton(int af, const char *src, void *dst); | |||
31 | #define O_NONBLOCK 0 | 31 | #define O_NONBLOCK 0 |
32 | #define O_NOFOLLOW 0 | 32 | #define O_NOFOLLOW 0 |
33 | #define O_NOCTTY 0 | 33 | #define O_NOCTTY 0 |
34 | #define O_DIRECT 0 | ||
34 | #define O_SPECIAL 0x800000 | 35 | #define O_SPECIAL 0x800000 |
35 | 36 | ||
36 | /* | 37 | /* |
diff --git a/include/platform.h b/include/platform.h index f1c09c4d2..ea97d2682 100644 --- a/include/platform.h +++ b/include/platform.h | |||
@@ -335,7 +335,7 @@ typedef unsigned smalluint; | |||
335 | #endif | 335 | #endif |
336 | 336 | ||
337 | /* Define bb_setpgrp */ | 337 | /* Define bb_setpgrp */ |
338 | #if defined(__digital__) && defined(__unix__) | 338 | #if (defined(__digital__) && defined(__unix__)) || defined(__FreeBSD__) |
339 | /* use legacy setpgrp(pid_t, pid_t) for now. move to platform.c */ | 339 | /* use legacy setpgrp(pid_t, pid_t) for now. move to platform.c */ |
340 | # define bb_setpgrp() do { pid_t __me = getpid(); setpgrp(__me, __me); } while (0) | 340 | # define bb_setpgrp() do { pid_t __me = getpid(); setpgrp(__me, __me); } while (0) |
341 | #else | 341 | #else |
@@ -358,6 +358,8 @@ typedef unsigned smalluint; | |||
358 | # define ALIGN2 | 358 | # define ALIGN2 |
359 | # define ALIGN4 | 359 | # define ALIGN4 |
360 | #endif | 360 | #endif |
361 | #define ALIGN8 __attribute__((aligned(8))) | ||
362 | #define ALIGN_PTR __attribute__((aligned(sizeof(void*)))) | ||
361 | 363 | ||
362 | /* | 364 | /* |
363 | * For 0.9.29 and svn, __ARCH_USE_MMU__ indicates no-mmu reliably. | 365 | * For 0.9.29 and svn, __ARCH_USE_MMU__ indicates no-mmu reliably. |
diff --git a/include/rtc_.h b/include/rtc_.h index 750fc20ec..24ff5363f 100644 --- a/include/rtc_.h +++ b/include/rtc_.h | |||
@@ -11,6 +11,12 @@ | |||
11 | 11 | ||
12 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | 12 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN |
13 | 13 | ||
14 | #if ENABLE_FEATURE_HWCLOCK_ADJTIME_FHS | ||
15 | # define ADJTIME_PATH "/var/lib/hwclock/adjtime" | ||
16 | #else | ||
17 | # define ADJTIME_PATH "/etc/adjtime" | ||
18 | #endif | ||
19 | |||
14 | int rtc_adjtime_is_utc(void) FAST_FUNC; | 20 | int rtc_adjtime_is_utc(void) FAST_FUNC; |
15 | int rtc_xopen(const char **default_rtc, int flags) FAST_FUNC; | 21 | int rtc_xopen(const char **default_rtc, int flags) FAST_FUNC; |
16 | void rtc_read_tm(struct tm *ptm, int fd) FAST_FUNC; | 22 | void rtc_read_tm(struct tm *ptm, int fd) FAST_FUNC; |
diff --git a/include/usage.src.h b/include/usage.src.h index d22efd3ba..1ac252d1b 100644 --- a/include/usage.src.h +++ b/include/usage.src.h | |||
@@ -25,6 +25,12 @@ | |||
25 | " (default "CONFIG_FEATURE_DEFAULT_PASSWD_ALGO")" | 25 | " (default "CONFIG_FEATURE_DEFAULT_PASSWD_ALGO")" |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | #if ENABLE_FEATURE_HWCLOCK_ADJTIME_FHS | ||
29 | # define ADJTIME_PATH "/var/lib/hwclock/adjtime" | ||
30 | #else | ||
31 | # define ADJTIME_PATH "/etc/adjtime" | ||
32 | #endif | ||
33 | |||
28 | INSERT | 34 | INSERT |
29 | 35 | ||
30 | #define busybox_notes_usage \ | 36 | #define busybox_notes_usage \ |
diff --git a/init/bootchartd.c b/init/bootchartd.c index 750f67356..ae1ee9d9a 100644 --- a/init/bootchartd.c +++ b/init/bootchartd.c | |||
@@ -218,10 +218,10 @@ static char *make_tempdir(void) | |||
218 | 218 | ||
219 | static void do_logging(unsigned sample_period_us, int process_accounting) | 219 | static void do_logging(unsigned sample_period_us, int process_accounting) |
220 | { | 220 | { |
221 | FILE *proc_stat = xfopen("proc_stat.log", "w"); | 221 | FILE *proc_stat = xfopen_for_write("proc_stat.log"); |
222 | FILE *proc_diskstats = xfopen("proc_diskstats.log", "w"); | 222 | FILE *proc_diskstats = xfopen_for_write("proc_diskstats.log"); |
223 | //FILE *proc_netdev = xfopen("proc_netdev.log", "w"); | 223 | //FILE *proc_netdev = xfopen_for_write("proc_netdev.log"); |
224 | FILE *proc_ps = xfopen("proc_ps.log", "w"); | 224 | FILE *proc_ps = xfopen_for_write("proc_ps.log"); |
225 | int look_for_login_process = (getppid() == 1); | 225 | int look_for_login_process = (getppid() == 1); |
226 | unsigned count = 60*1000*1000 / sample_period_us; /* ~1 minute */ | 226 | unsigned count = 60*1000*1000 / sample_period_us; /* ~1 minute */ |
227 | 227 | ||
@@ -268,7 +268,7 @@ static void finalize(char *tempdir, const char *prog, int process_accounting) | |||
268 | //local pacct= | 268 | //local pacct= |
269 | //[ -e kernel_pacct ] && pacct=kernel_pacct | 269 | //[ -e kernel_pacct ] && pacct=kernel_pacct |
270 | 270 | ||
271 | FILE *header_fp = xfopen("header", "w"); | 271 | FILE *header_fp = xfopen_for_write("header"); |
272 | 272 | ||
273 | if (process_accounting) | 273 | if (process_accounting) |
274 | acct(NULL); | 274 | acct(NULL); |
diff --git a/init/halt.c b/init/halt.c index 785c38130..fe3cb9e75 100644 --- a/init/halt.c +++ b/init/halt.c | |||
@@ -65,7 +65,7 @@ | |||
65 | //kbuild:lib-$(CONFIG_REBOOT) += halt.o | 65 | //kbuild:lib-$(CONFIG_REBOOT) += halt.o |
66 | 66 | ||
67 | //usage:#define halt_trivial_usage | 67 | //usage:#define halt_trivial_usage |
68 | //usage: "[-d DELAY] [-n] [-f]" IF_FEATURE_WTMP(" [-w]") | 68 | //usage: "[-d DELAY] [-nf"IF_FEATURE_WTMP("w")"]" |
69 | //usage:#define halt_full_usage "\n\n" | 69 | //usage:#define halt_full_usage "\n\n" |
70 | //usage: "Halt the system\n" | 70 | //usage: "Halt the system\n" |
71 | //usage: "\n -d SEC Delay interval" | 71 | //usage: "\n -d SEC Delay interval" |
@@ -76,7 +76,7 @@ | |||
76 | //usage: ) | 76 | //usage: ) |
77 | //usage: | 77 | //usage: |
78 | //usage:#define poweroff_trivial_usage | 78 | //usage:#define poweroff_trivial_usage |
79 | //usage: "[-d DELAY] [-n] [-f]" | 79 | //usage: "[-d DELAY] [-nf]" |
80 | //usage:#define poweroff_full_usage "\n\n" | 80 | //usage:#define poweroff_full_usage "\n\n" |
81 | //usage: "Halt and shut off power\n" | 81 | //usage: "Halt and shut off power\n" |
82 | //usage: "\n -d SEC Delay interval" | 82 | //usage: "\n -d SEC Delay interval" |
@@ -84,7 +84,7 @@ | |||
84 | //usage: "\n -f Force (don't go through init)" | 84 | //usage: "\n -f Force (don't go through init)" |
85 | //usage: | 85 | //usage: |
86 | //usage:#define reboot_trivial_usage | 86 | //usage:#define reboot_trivial_usage |
87 | //usage: "[-d DELAY] [-n] [-f]" | 87 | //usage: "[-d DELAY] [-nf]" |
88 | //usage:#define reboot_full_usage "\n\n" | 88 | //usage:#define reboot_full_usage "\n\n" |
89 | //usage: "Reboot the system\n" | 89 | //usage: "Reboot the system\n" |
90 | //usage: "\n -d SEC Delay interval" | 90 | //usage: "\n -d SEC Delay interval" |
@@ -144,14 +144,14 @@ static int init_was_not_there(void) | |||
144 | */ | 144 | */ |
145 | #if 0 | 145 | #if 0 |
146 | while (kill(1, 0) != 0 && --cnt >= 0) | 146 | while (kill(1, 0) != 0 && --cnt >= 0) |
147 | sleep(1); | 147 | sleep1(); |
148 | #endif | 148 | #endif |
149 | /* ... so let's wait for some evidence a usual startup event, | 149 | /* ... so let's wait for some evidence a usual startup event, |
150 | * mounting of /proc, happened. By that time init should be ready | 150 | * mounting of /proc, happened. By that time init should be ready |
151 | * for signals. | 151 | * for signals. |
152 | */ | 152 | */ |
153 | while (access("/proc/meminfo", F_OK) != 0 && --cnt >= 0) | 153 | while (access("/proc/meminfo", F_OK) != 0 && --cnt >= 0) |
154 | sleep(1); | 154 | sleep1(); |
155 | 155 | ||
156 | /* Does it look like init wasn't there? */ | 156 | /* Does it look like init wasn't there? */ |
157 | return (cnt != initial - 1); | 157 | return (cnt != initial - 1); |
diff --git a/init/init.c b/init/init.c index 28775a65c..efab5dcb4 100644 --- a/init/init.c +++ b/init/init.c | |||
@@ -736,7 +736,7 @@ static void pause_and_low_level_reboot(unsigned magic) | |||
736 | pid_t pid; | 736 | pid_t pid; |
737 | 737 | ||
738 | /* Allow time for last message to reach serial console, etc */ | 738 | /* Allow time for last message to reach serial console, etc */ |
739 | sleep(1); | 739 | sleep1(); |
740 | 740 | ||
741 | /* We have to fork here, since the kernel calls do_exit(EXIT_SUCCESS) | 741 | /* We have to fork here, since the kernel calls do_exit(EXIT_SUCCESS) |
742 | * in linux/kernel/sys.c, which can cause the machine to panic when | 742 | * in linux/kernel/sys.c, which can cause the machine to panic when |
@@ -751,7 +751,7 @@ static void pause_and_low_level_reboot(unsigned magic) | |||
751 | * we would eternally sleep here - not what we want. | 751 | * we would eternally sleep here - not what we want. |
752 | */ | 752 | */ |
753 | waitpid(pid, NULL, 0); | 753 | waitpid(pid, NULL, 0); |
754 | sleep(1); /* paranoia */ | 754 | sleep1(); /* paranoia */ |
755 | _exit(EXIT_SUCCESS); | 755 | _exit(EXIT_SUCCESS); |
756 | } | 756 | } |
757 | 757 | ||
@@ -768,12 +768,12 @@ static void run_shutdown_and_kill_processes(void) | |||
768 | kill(-1, SIGTERM); | 768 | kill(-1, SIGTERM); |
769 | message(L_CONSOLE, "Sent SIG%s to all processes", "TERM"); | 769 | message(L_CONSOLE, "Sent SIG%s to all processes", "TERM"); |
770 | sync(); | 770 | sync(); |
771 | sleep(1); | 771 | sleep1(); |
772 | 772 | ||
773 | kill(-1, SIGKILL); | 773 | kill(-1, SIGKILL); |
774 | message(L_CONSOLE, "Sent SIG%s to all processes", "KILL"); | 774 | message(L_CONSOLE, "Sent SIG%s to all processes", "KILL"); |
775 | sync(); | 775 | sync(); |
776 | /*sleep(1); - callers take care about making a pause */ | 776 | /*sleep1(); - callers take care about making a pause */ |
777 | } | 777 | } |
778 | 778 | ||
779 | /* Signal handling by init: | 779 | /* Signal handling by init: |
@@ -904,7 +904,7 @@ static void stop_handler(int sig UNUSED_PARAM) | |||
904 | wpid = wait_any_nohang(NULL); | 904 | wpid = wait_any_nohang(NULL); |
905 | mark_terminated(wpid); | 905 | mark_terminated(wpid); |
906 | if (wpid <= 0) /* no processes exited? sleep a bit */ | 906 | if (wpid <= 0) /* no processes exited? sleep a bit */ |
907 | sleep(1); | 907 | sleep1(); |
908 | } | 908 | } |
909 | 909 | ||
910 | signal(SIGCONT, SIG_DFL); | 910 | signal(SIGCONT, SIG_DFL); |
@@ -1209,7 +1209,7 @@ int init_main(int argc UNUSED_PARAM, char **argv) | |||
1209 | } | 1209 | } |
1210 | 1210 | ||
1211 | /* Don't consume all CPU time - sleep a bit */ | 1211 | /* Don't consume all CPU time - sleep a bit */ |
1212 | sleep(1); | 1212 | sleep1(); |
1213 | } /* while (1) */ | 1213 | } /* while (1) */ |
1214 | } | 1214 | } |
1215 | 1215 | ||
diff --git a/klibc-utils/nuke.c b/klibc-utils/nuke.c index d7c16f5cf..8c20c5e11 100644 --- a/klibc-utils/nuke.c +++ b/klibc-utils/nuke.c | |||
@@ -5,7 +5,7 @@ | |||
5 | */ | 5 | */ |
6 | //config:config NUKE | 6 | //config:config NUKE |
7 | //config: bool "nuke (2.9 kb)" | 7 | //config: bool "nuke (2.9 kb)" |
8 | //config: default y | 8 | //config: default n # off by default: too "accidentally destructive" |
9 | //config: help | 9 | //config: help |
10 | //config: Alias to "rm -rf". | 10 | //config: Alias to "rm -rf". |
11 | 11 | ||
diff --git a/libbb/bb_do_delay.c b/libbb/bb_do_delay.c index 65541704b..9a84fa24b 100644 --- a/libbb/bb_do_delay.c +++ b/libbb/bb_do_delay.c | |||
@@ -8,13 +8,60 @@ | |||
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | 10 | ||
11 | void FAST_FUNC bb_do_delay(int seconds) | 11 | /* void FAST_FUNC bb_do_delay(unsigned seconds) { ... } - no users yet */ |
12 | |||
13 | #ifndef LOGIN_FAIL_DELAY | ||
14 | #define LOGIN_FAIL_DELAY 3 | ||
15 | #endif | ||
16 | void FAST_FUNC pause_after_failed_login(void) | ||
12 | { | 17 | { |
13 | time_t start, now; | 18 | #if 0 /* over-engineered madness */ |
19 | time_t end, diff; | ||
14 | 20 | ||
15 | start = time(NULL); | 21 | end = time(NULL) + LOGIN_FAIL_DELAY; |
22 | diff = LOGIN_FAIL_DELAY; | ||
16 | do { | 23 | do { |
17 | sleep(seconds); | 24 | sleep(diff); |
18 | now = time(NULL); | 25 | diff = end - time(NULL); |
19 | } while ((now - start) < seconds); | 26 | } while (diff > 0); |
27 | #else | ||
28 | sleep(LOGIN_FAIL_DELAY); | ||
29 | #endif | ||
30 | } | ||
31 | |||
32 | void FAST_FUNC sleep1(void) | ||
33 | { | ||
34 | sleep(1); | ||
35 | } | ||
36 | |||
37 | void FAST_FUNC msleep(unsigned ms) | ||
38 | { | ||
39 | #if 0 | ||
40 | /* 1. usleep(n) is not guaranteed by standards to accept n >= 1000000 | ||
41 | * 2. multiplication in usleep(ms * 1000) can overflow if ms > 4294967 | ||
42 | * (sleep of ~71.5 minutes) | ||
43 | * Let's play safe and loop: | ||
44 | */ | ||
45 | while (ms > 500) { | ||
46 | usleep(500000); | ||
47 | ms -= 500; | ||
48 | } | ||
49 | usleep(ms * 1000); | ||
50 | #else | ||
51 | //usleep is often implemented as a call to nanosleep. | ||
52 | //Simply do the same to implement msleep. | ||
53 | //it's marginally larger, but wakes your CPU less often: | ||
54 | //function old new delta | ||
55 | //msleep 45 52 +7 | ||
56 | struct timespec ts; | ||
57 | ts.tv_sec = ms / 1000; | ||
58 | ts.tv_nsec = (ms % 1000) * 1000000; | ||
59 | /* | ||
60 | * If a signal has non-default handler, nanosleep returns early. | ||
61 | * Our version of msleep doesn't return early | ||
62 | * if interrupted by such signals: | ||
63 | */ | ||
64 | while (nanosleep(&ts, &ts) != 0) | ||
65 | continue; | ||
66 | #endif | ||
20 | } | 67 | } |
diff --git a/libbb/capability.c b/libbb/capability.c index 23afd8eb9..e3c252a5a 100644 --- a/libbb/capability.c +++ b/libbb/capability.c | |||
@@ -17,7 +17,7 @@ extern int capget(cap_user_header_t header, const cap_user_data_t data); | |||
17 | // This way, libcap needs not be installed in build environment. | 17 | // This way, libcap needs not be installed in build environment. |
18 | #include "libbb.h" | 18 | #include "libbb.h" |
19 | 19 | ||
20 | static const char *const capabilities[] = { | 20 | static const char *const capabilities[] ALIGN_PTR = { |
21 | "chown", | 21 | "chown", |
22 | "dac_override", | 22 | "dac_override", |
23 | "dac_read_search", | 23 | "dac_read_search", |
diff --git a/libbb/copyfd.c b/libbb/copyfd.c index d41fd10f0..7f9d92ea9 100644 --- a/libbb/copyfd.c +++ b/libbb/copyfd.c | |||
@@ -75,10 +75,7 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size) | |||
75 | goto use_small_buf; | 75 | goto use_small_buf; |
76 | /* We want page-aligned buffer, just in case kernel is clever | 76 | /* We want page-aligned buffer, just in case kernel is clever |
77 | * and can do page-aligned io more efficiently */ | 77 | * and can do page-aligned io more efficiently */ |
78 | buffer = mmap(NULL, CONFIG_FEATURE_COPYBUF_KB * 1024, | 78 | buffer = mmap_anon(CONFIG_FEATURE_COPYBUF_KB * 1024); |
79 | PROT_READ | PROT_WRITE, | ||
80 | MAP_PRIVATE | MAP_ANON, | ||
81 | /* ignored: */ -1, 0); | ||
82 | buffer_size = CONFIG_FEATURE_COPYBUF_KB * 1024; | 79 | buffer_size = CONFIG_FEATURE_COPYBUF_KB * 1024; |
83 | if (buffer == MAP_FAILED) { | 80 | if (buffer == MAP_FAILED) { |
84 | use_small_buf: | 81 | use_small_buf: |
diff --git a/libbb/die_if_bad_username.c b/libbb/die_if_bad_username.c index e5e1160c4..d05dc74c5 100644 --- a/libbb/die_if_bad_username.c +++ b/libbb/die_if_bad_username.c | |||
@@ -8,6 +8,10 @@ | |||
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | 10 | ||
11 | #ifndef LOGIN_NAME_MAX | ||
12 | #define LOGIN_NAME_MAX 256 | ||
13 | #endif | ||
14 | |||
11 | /* To avoid problems, the username should consist only of | 15 | /* To avoid problems, the username should consist only of |
12 | * letters, digits, underscores, periods, at signs and dashes, | 16 | * letters, digits, underscores, periods, at signs and dashes, |
13 | * and not start with a dash (as defined by IEEE Std 1003.1-2001). | 17 | * and not start with a dash (as defined by IEEE Std 1003.1-2001). |
diff --git a/libbb/duration.c b/libbb/duration.c index 22b209f4d..086da15fb 100644 --- a/libbb/duration.c +++ b/libbb/duration.c | |||
@@ -21,7 +21,7 @@ | |||
21 | 21 | ||
22 | #include "libbb.h" | 22 | #include "libbb.h" |
23 | 23 | ||
24 | static const struct suffix_mult duration_suffixes[] = { | 24 | static const struct suffix_mult duration_suffixes[] ALIGN_SUFFIX = { |
25 | { "s", 1 }, | 25 | { "s", 1 }, |
26 | { "m", 60 }, | 26 | { "m", 60 }, |
27 | { "h", 60*60 }, | 27 | { "h", 60*60 }, |
diff --git a/libbb/executable.c b/libbb/executable.c index f549a7aae..bd3022b13 100644 --- a/libbb/executable.c +++ b/libbb/executable.c | |||
@@ -100,12 +100,3 @@ void FAST_FUNC BB_EXECVP_or_die(char **argv) | |||
100 | xfunc_error_retval = (errno == ENOENT) ? 127 : 126; | 100 | xfunc_error_retval = (errno == ENOENT) ? 127 : 126; |
101 | bb_perror_msg_and_die("can't execute '%s'", argv[0]); | 101 | bb_perror_msg_and_die("can't execute '%s'", argv[0]); |
102 | } | 102 | } |
103 | |||
104 | /* Typical idiom for applets which exec *optional* PROG [ARGS] */ | ||
105 | void FAST_FUNC exec_prog_or_SHELL(char **argv) | ||
106 | { | ||
107 | if (argv[0]) { | ||
108 | BB_EXECVP_or_die(argv); | ||
109 | } | ||
110 | run_shell(getenv("SHELL"), /*login:*/ 1, NULL); | ||
111 | } | ||
diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c index d8f210173..e0db8ce67 100644 --- a/libbb/hash_md5_sha.c +++ b/libbb/hash_md5_sha.c | |||
@@ -111,7 +111,7 @@ static void FAST_FUNC md5_process_block64(md5_ctx_t *ctx) | |||
111 | They are defined in RFC 1321 as | 111 | They are defined in RFC 1321 as |
112 | T[i] = (int)(2^32 * fabs(sin(i))), i=1..64 | 112 | T[i] = (int)(2^32 * fabs(sin(i))), i=1..64 |
113 | */ | 113 | */ |
114 | static const uint32_t C_array[] = { | 114 | static const uint32_t C_array[] ALIGN4 = { |
115 | /* round 1 */ | 115 | /* round 1 */ |
116 | 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, | 116 | 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, |
117 | 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, | 117 | 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, |
@@ -492,7 +492,7 @@ unsigned FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf) | |||
492 | 492 | ||
493 | static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx) | 493 | static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx) |
494 | { | 494 | { |
495 | static const uint32_t rconsts[] = { | 495 | static const uint32_t rconsts[] ALIGN4 = { |
496 | 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 | 496 | 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 |
497 | }; | 497 | }; |
498 | int i, j; | 498 | int i, j; |
@@ -567,7 +567,7 @@ typedef uint64_t sha_K_int; | |||
567 | typedef uint32_t sha_K_int; | 567 | typedef uint32_t sha_K_int; |
568 | # define K(v) (uint32_t)(v >> 32) | 568 | # define K(v) (uint32_t)(v >> 32) |
569 | #endif | 569 | #endif |
570 | static const sha_K_int sha_K[] = { | 570 | static const sha_K_int sha_K[] ALIGN8 = { |
571 | K(0x428a2f98d728ae22ULL), K(0x7137449123ef65cdULL), | 571 | K(0x428a2f98d728ae22ULL), K(0x7137449123ef65cdULL), |
572 | K(0xb5c0fbcfec4d3b2fULL), K(0xe9b5dba58189dbbcULL), | 572 | K(0xb5c0fbcfec4d3b2fULL), K(0xe9b5dba58189dbbcULL), |
573 | K(0x3956c25bf348b538ULL), K(0x59f111f1b605d019ULL), | 573 | K(0x3956c25bf348b538ULL), K(0x59f111f1b605d019ULL), |
@@ -760,7 +760,7 @@ void FAST_FUNC sha1_begin(sha1_ctx_t *ctx) | |||
760 | ctx->process_block = sha1_process_block64; | 760 | ctx->process_block = sha1_process_block64; |
761 | } | 761 | } |
762 | 762 | ||
763 | static const uint32_t init256[] = { | 763 | static const uint32_t init256[] ALIGN4 = { |
764 | 0, | 764 | 0, |
765 | 0, | 765 | 0, |
766 | 0x6a09e667, | 766 | 0x6a09e667, |
@@ -773,7 +773,7 @@ static const uint32_t init256[] = { | |||
773 | 0x5be0cd19, | 773 | 0x5be0cd19, |
774 | }; | 774 | }; |
775 | #if NEED_SHA512 | 775 | #if NEED_SHA512 |
776 | static const uint32_t init512_lo[] = { | 776 | static const uint32_t init512_lo[] ALIGN4 = { |
777 | 0, | 777 | 0, |
778 | 0, | 778 | 0, |
779 | 0xf3bcc908, | 779 | 0xf3bcc908, |
@@ -1009,7 +1009,7 @@ static void sha3_process_block72(uint64_t *state) | |||
1009 | 1009 | ||
1010 | #if OPTIMIZE_SHA3_FOR_32 | 1010 | #if OPTIMIZE_SHA3_FOR_32 |
1011 | /* | 1011 | /* |
1012 | static const uint32_t IOTA_CONST_0[NROUNDS] = { | 1012 | static const uint32_t IOTA_CONST_0[NROUNDS] ALIGN4 = { |
1013 | 0x00000001UL, | 1013 | 0x00000001UL, |
1014 | 0x00000000UL, | 1014 | 0x00000000UL, |
1015 | 0x00000000UL, | 1015 | 0x00000000UL, |
@@ -1038,7 +1038,7 @@ static void sha3_process_block72(uint64_t *state) | |||
1038 | ** bits are in lsb: 0101 0000 1111 0100 1111 0001 | 1038 | ** bits are in lsb: 0101 0000 1111 0100 1111 0001 |
1039 | */ | 1039 | */ |
1040 | uint32_t IOTA_CONST_0bits = (uint32_t)(0x0050f4f1); | 1040 | uint32_t IOTA_CONST_0bits = (uint32_t)(0x0050f4f1); |
1041 | static const uint32_t IOTA_CONST_1[NROUNDS] = { | 1041 | static const uint32_t IOTA_CONST_1[NROUNDS] ALIGN4 = { |
1042 | 0x00000000UL, | 1042 | 0x00000000UL, |
1043 | 0x00000089UL, | 1043 | 0x00000089UL, |
1044 | 0x8000008bUL, | 1044 | 0x8000008bUL, |
@@ -1174,7 +1174,7 @@ static void sha3_process_block72(uint64_t *state) | |||
1174 | combine_halves(state); | 1174 | combine_halves(state); |
1175 | #else | 1175 | #else |
1176 | /* Native 64-bit algorithm */ | 1176 | /* Native 64-bit algorithm */ |
1177 | static const uint16_t IOTA_CONST[NROUNDS] = { | 1177 | static const uint16_t IOTA_CONST[NROUNDS] ALIGN2 = { |
1178 | /* Elements should be 64-bit, but top half is always zero | 1178 | /* Elements should be 64-bit, but top half is always zero |
1179 | * or 0x80000000. We encode 63rd bits in a separate word below. | 1179 | * or 0x80000000. We encode 63rd bits in a separate word below. |
1180 | * Same is true for 31th bits, which lets us use 16-bit table | 1180 | * Same is true for 31th bits, which lets us use 16-bit table |
@@ -1210,15 +1210,15 @@ static void sha3_process_block72(uint64_t *state) | |||
1210 | /* bit for CONST[0] is in msb: 0001 0110 0011 1000 0001 1011 */ | 1210 | /* bit for CONST[0] is in msb: 0001 0110 0011 1000 0001 1011 */ |
1211 | const uint32_t IOTA_CONST_bit31 = (uint32_t)(0x16381b00); | 1211 | const uint32_t IOTA_CONST_bit31 = (uint32_t)(0x16381b00); |
1212 | 1212 | ||
1213 | static const uint8_t ROT_CONST[24] = { | 1213 | static const uint8_t ROT_CONST[24] ALIGN1 = { |
1214 | 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, | 1214 | 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, |
1215 | 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44, | 1215 | 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44, |
1216 | }; | 1216 | }; |
1217 | static const uint8_t PI_LANE[24] = { | 1217 | static const uint8_t PI_LANE[24] ALIGN1 = { |
1218 | 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, | 1218 | 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, |
1219 | 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1, | 1219 | 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1, |
1220 | }; | 1220 | }; |
1221 | /*static const uint8_t MOD5[10] = { 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, };*/ | 1221 | /*static const uint8_t MOD5[10] ALIGN1 = { 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, };*/ |
1222 | 1222 | ||
1223 | unsigned x; | 1223 | unsigned x; |
1224 | unsigned round; | 1224 | unsigned round; |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index b35da1874..f3cbc512c 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -57,12 +57,23 @@ | |||
57 | #if ENABLE_FEATURE_EDITING | 57 | #if ENABLE_FEATURE_EDITING |
58 | 58 | ||
59 | 59 | ||
60 | #if !ENABLE_SHELL_ASH && !ENABLE_SHELL_HUSH | ||
61 | /* so far only shells use these features */ | ||
62 | # undef ENABLE_FEATURE_EDITING_FANCY_PROMPT | ||
63 | # undef ENABLE_FEATURE_TAB_COMPLETION | ||
64 | # undef ENABLE_FEATURE_USERNAME_COMPLETION | ||
65 | # define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0 | ||
66 | # define ENABLE_FEATURE_TAB_COMPLETION 0 | ||
67 | # define ENABLE_FEATURE_USERNAME_COMPLETION 0 | ||
68 | #endif | ||
69 | |||
70 | |||
60 | #define ENABLE_USERNAME_OR_HOMEDIR \ | 71 | #define ENABLE_USERNAME_OR_HOMEDIR \ |
61 | (ENABLE_FEATURE_USERNAME_COMPLETION || ENABLE_FEATURE_EDITING_FANCY_PROMPT) | 72 | (ENABLE_FEATURE_USERNAME_COMPLETION || ENABLE_FEATURE_EDITING_FANCY_PROMPT) |
62 | #define IF_USERNAME_OR_HOMEDIR(...) | ||
63 | #if ENABLE_USERNAME_OR_HOMEDIR | 73 | #if ENABLE_USERNAME_OR_HOMEDIR |
64 | # undef IF_USERNAME_OR_HOMEDIR | ||
65 | # define IF_USERNAME_OR_HOMEDIR(...) __VA_ARGS__ | 74 | # define IF_USERNAME_OR_HOMEDIR(...) __VA_ARGS__ |
75 | #else | ||
76 | # define IF_USERNAME_OR_HOMEDIR(...) /*nothing*/ | ||
66 | #endif | 77 | #endif |
67 | 78 | ||
68 | 79 | ||
@@ -205,9 +216,6 @@ extern struct lineedit_statics *const lineedit_ptr_to_statics; | |||
205 | #define INIT_S() do { \ | 216 | #define INIT_S() do { \ |
206 | (*(struct lineedit_statics**)not_const_pp(&lineedit_ptr_to_statics)) = xzalloc(sizeof(S)); \ | 217 | (*(struct lineedit_statics**)not_const_pp(&lineedit_ptr_to_statics)) = xzalloc(sizeof(S)); \ |
207 | barrier(); \ | 218 | barrier(); \ |
208 | cmdedit_termw = 80; \ | ||
209 | IF_USERNAME_OR_HOMEDIR(home_pwd_buf = (char*)null_str;) \ | ||
210 | IF_FEATURE_EDITING_VI(delptr = delbuf;) \ | ||
211 | } while (0) | 219 | } while (0) |
212 | 220 | ||
213 | static void deinit_S(void) | 221 | static void deinit_S(void) |
@@ -796,16 +804,18 @@ enum { | |||
796 | FIND_FILE_ONLY = 2, | 804 | FIND_FILE_ONLY = 2, |
797 | }; | 805 | }; |
798 | 806 | ||
799 | static int path_parse(char ***p) | 807 | static unsigned path_parse(char ***p) |
800 | { | 808 | { |
801 | int npth; | 809 | unsigned npth; |
802 | const char *pth; | 810 | const char *pth; |
803 | char *tmp; | 811 | char *tmp; |
804 | char **res; | 812 | char **res; |
805 | 813 | ||
814 | # if EDITING_HAS_path_lookup | ||
806 | if (state->flags & WITH_PATH_LOOKUP) | 815 | if (state->flags & WITH_PATH_LOOKUP) |
807 | pth = state->path_lookup; | 816 | pth = state->path_lookup; |
808 | else | 817 | else |
818 | # endif | ||
809 | pth = getenv("PATH"); | 819 | pth = getenv("PATH"); |
810 | 820 | ||
811 | /* PATH="" or PATH=":"? */ | 821 | /* PATH="" or PATH=":"? */ |
@@ -824,7 +834,7 @@ static int path_parse(char ***p) | |||
824 | npth++; | 834 | npth++; |
825 | } | 835 | } |
826 | 836 | ||
827 | *p = res = xmalloc(npth * sizeof(res[0])); | 837 | *p = res = xzalloc((npth + 1) * sizeof(res[0])); |
828 | res[0] = tmp = xstrdup(pth); | 838 | res[0] = tmp = xstrdup(pth); |
829 | npth = 1; | 839 | npth = 1; |
830 | while (1) { | 840 | while (1) { |
@@ -836,6 +846,8 @@ static int path_parse(char ***p) | |||
836 | break; /* :<empty> */ | 846 | break; /* :<empty> */ |
837 | res[npth++] = tmp; | 847 | res[npth++] = tmp; |
838 | } | 848 | } |
849 | /* special case: "match subdirectories of the current directory" */ | ||
850 | /*res[npth++] = NULL; - filled by xzalloc() */ | ||
839 | return npth; | 851 | return npth; |
840 | } | 852 | } |
841 | 853 | ||
@@ -846,49 +858,49 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
846 | { | 858 | { |
847 | char *path1[1]; | 859 | char *path1[1]; |
848 | char **paths = path1; | 860 | char **paths = path1; |
849 | int npaths; | 861 | unsigned npaths; |
850 | int i; | 862 | unsigned i; |
851 | unsigned pf_len; | 863 | unsigned baselen; |
852 | const char *pfind; | 864 | const char *basecmd; |
853 | char *dirbuf = NULL; | 865 | char *dirbuf = NULL; |
854 | 866 | ||
855 | npaths = 1; | 867 | npaths = 1; |
856 | path1[0] = (char*)"."; | 868 | path1[0] = (char*)"."; |
857 | 869 | ||
858 | pfind = strrchr(command, '/'); | 870 | basecmd = strrchr(command, '/'); |
859 | #if ENABLE_PLATFORM_MINGW32 | 871 | #if ENABLE_PLATFORM_MINGW32 |
860 | if (!pfind && has_dos_drive_prefix(command) && command[2] != '\0') { | 872 | if (!basecmd && has_dos_drive_prefix(command) && command[2] != '\0') { |
861 | char buffer[PATH_MAX]; | 873 | char buffer[PATH_MAX]; |
862 | 874 | ||
863 | /* path is of form c:path with no '/' */ | 875 | /* path is of form c:path with no '/' */ |
864 | if (get_drive_cwd(command, buffer, PATH_MAX)) { | 876 | if (get_drive_cwd(command, buffer, PATH_MAX)) { |
865 | pfind = command + 2; | 877 | basecmd = command + 2; |
866 | path1[0] = dirbuf = xstrdup(buffer); | 878 | path1[0] = dirbuf = xstrdup(buffer); |
867 | } | 879 | } |
868 | } else | 880 | } else |
869 | #endif | 881 | #endif |
870 | if (!pfind) { | 882 | if (!basecmd) { |
871 | if (type == FIND_EXE_ONLY) | 883 | if (type == FIND_EXE_ONLY) |
872 | npaths = path_parse(&paths); | 884 | npaths = path_parse(&paths); |
873 | pfind = command; | 885 | basecmd = command; |
874 | } else { | 886 | } else { |
875 | /* point to 'l' in "..../last_component" */ | 887 | /* point to 'l' in "..../last_component" */ |
876 | pfind++; | 888 | basecmd++; |
877 | /* dirbuf = ".../.../.../" */ | 889 | /* dirbuf = ".../.../.../" */ |
878 | dirbuf = xstrndup(command, pfind - command); | 890 | dirbuf = xstrndup(command, basecmd - command); |
879 | # if ENABLE_FEATURE_USERNAME_COMPLETION | 891 | # if ENABLE_FEATURE_USERNAME_COMPLETION |
880 | if (dirbuf[0] == '~') /* ~/... or ~user/... */ | 892 | if (dirbuf[0] == '~') /* ~/... or ~user/... */ |
881 | dirbuf = username_path_completion(dirbuf); | 893 | dirbuf = username_path_completion(dirbuf); |
882 | # endif | 894 | # endif |
883 | path1[0] = dirbuf; | 895 | path1[0] = dirbuf; |
884 | } | 896 | } |
885 | pf_len = strlen(pfind); | 897 | baselen = strlen(basecmd); |
886 | 898 | ||
887 | if (type == FIND_EXE_ONLY && !dirbuf) { | 899 | if (type == FIND_EXE_ONLY && !dirbuf) { |
888 | # if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1 | 900 | # if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1 |
889 | const char *p = applet_names; | 901 | const char *p = applet_names; |
890 | while (*p) { | 902 | while (*p) { |
891 | if (strncmp(pfind, p, pf_len) == 0) | 903 | if (strncmp(basecmd, p, baselen) == 0) |
892 | add_match(xstrdup(p)); | 904 | add_match(xstrdup(p)); |
893 | while (*p++ != '\0') | 905 | while (*p++ != '\0') |
894 | continue; | 906 | continue; |
@@ -901,7 +913,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
901 | const char *b = state->get_exe_name(i++); | 913 | const char *b = state->get_exe_name(i++); |
902 | if (!b) | 914 | if (!b) |
903 | break; | 915 | break; |
904 | if (strncmp(pfind, b, pf_len) == 0) | 916 | if (strncmp(basecmd, b, baselen) == 0) |
905 | add_match(xstrdup(b)); | 917 | add_match(xstrdup(b)); |
906 | } | 918 | } |
907 | } | 919 | } |
@@ -913,9 +925,20 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
913 | struct dirent *next; | 925 | struct dirent *next; |
914 | struct stat st; | 926 | struct stat st; |
915 | char *found; | 927 | char *found; |
928 | #if ENABLE_PLATFORM_MINGW32 | ||
929 | char *lpath; | ||
930 | #endif | ||
931 | |||
932 | if (paths[i] == NULL) { /* path_parse()'s last component? */ | ||
933 | /* in PATH completion, current dir's subdir names | ||
934 | * can be completions (but only subdirs, not files). | ||
935 | */ | ||
936 | type = FIND_DIR_ONLY; | ||
937 | paths[i] = (char *)"."; | ||
938 | } | ||
916 | 939 | ||
917 | #if ENABLE_PLATFORM_MINGW32 | 940 | #if ENABLE_PLATFORM_MINGW32 |
918 | char *lpath = auto_string(alloc_system_drive(paths[i])); | 941 | lpath = auto_string(alloc_system_drive(paths[i])); |
919 | dir = opendir(lpath); | 942 | dir = opendir(lpath); |
920 | #else | 943 | #else |
921 | dir = opendir(paths[i]); | 944 | dir = opendir(paths[i]); |
@@ -928,10 +951,10 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
928 | const char *name_found = next->d_name; | 951 | const char *name_found = next->d_name; |
929 | 952 | ||
930 | /* .../<tab>: bash 3.2.0 shows dotfiles, but not . and .. */ | 953 | /* .../<tab>: bash 3.2.0 shows dotfiles, but not . and .. */ |
931 | if (!pfind[0] && DOT_OR_DOTDOT(name_found)) | 954 | if (!basecmd[0] && DOT_OR_DOTDOT(name_found)) |
932 | continue; | 955 | continue; |
933 | /* match? */ | 956 | /* match? */ |
934 | if (!is_prefixed_with(name_found, pfind)) | 957 | if (strncmp(basecmd, name_found, baselen) != 0) |
935 | continue; /* no */ | 958 | continue; /* no */ |
936 | 959 | ||
937 | #if ENABLE_PLATFORM_MINGW32 | 960 | #if ENABLE_PLATFORM_MINGW32 |
@@ -957,6 +980,9 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
957 | strcpy(found, name_found); | 980 | strcpy(found, name_found); |
958 | 981 | ||
959 | if (S_ISDIR(st.st_mode)) { | 982 | if (S_ISDIR(st.st_mode)) { |
983 | /* skip directories if searching PATH */ | ||
984 | if (type == FIND_EXE_ONLY && !dirbuf) | ||
985 | goto cont; | ||
960 | /* name is a directory, add slash */ | 986 | /* name is a directory, add slash */ |
961 | found[len] = '/'; | 987 | found[len] = '/'; |
962 | found[len + 1] = '\0'; | 988 | found[len + 1] = '\0'; |
@@ -980,7 +1006,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
980 | } | 1006 | } |
981 | free(dirbuf); | 1007 | free(dirbuf); |
982 | 1008 | ||
983 | return pf_len; | 1009 | return baselen; |
984 | } | 1010 | } |
985 | 1011 | ||
986 | /* build_match_prefix: | 1012 | /* build_match_prefix: |
@@ -1492,15 +1518,19 @@ void FAST_FUNC show_history(const line_input_t *st) | |||
1492 | printf("%4d %s\n", i, st->history[i]); | 1518 | printf("%4d %s\n", i, st->history[i]); |
1493 | } | 1519 | } |
1494 | 1520 | ||
1521 | # if ENABLE_FEATURE_EDITING_SAVEHISTORY | ||
1495 | void FAST_FUNC free_line_input_t(line_input_t *n) | 1522 | void FAST_FUNC free_line_input_t(line_input_t *n) |
1496 | { | 1523 | { |
1497 | # if ENABLE_FEATURE_EDITING_SAVEHISTORY | 1524 | if (n) { |
1498 | int i = n->cnt_history; | 1525 | int i = n->cnt_history; |
1499 | while (i > 0) | 1526 | while (i > 0) |
1500 | free(n->history[--i]); | 1527 | free(n->history[--i]); |
1501 | #endif | 1528 | free(n); |
1502 | free(n); | 1529 | } |
1503 | } | 1530 | } |
1531 | # else | ||
1532 | /* #defined to free() in libbb.h */ | ||
1533 | # endif | ||
1504 | 1534 | ||
1505 | # if ENABLE_FEATURE_EDITING_SAVEHISTORY | 1535 | # if ENABLE_FEATURE_EDITING_SAVEHISTORY |
1506 | /* We try to ensure that concurrent additions to the history | 1536 | /* We try to ensure that concurrent additions to the history |
@@ -1581,7 +1611,7 @@ void save_history(line_input_t *st) | |||
1581 | { | 1611 | { |
1582 | FILE *fp; | 1612 | FILE *fp; |
1583 | 1613 | ||
1584 | if (!st->hist_file) | 1614 | if (!st || !st->hist_file) |
1585 | return; | 1615 | return; |
1586 | if (st->cnt_history <= st->cnt_history_in_file) | 1616 | if (st->cnt_history <= st->cnt_history_in_file) |
1587 | return; | 1617 | return; |
@@ -1971,9 +2001,7 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
1971 | { | 2001 | { |
1972 | int prmt_size = 0; | 2002 | int prmt_size = 0; |
1973 | char *prmt_mem_ptr = xzalloc(1); | 2003 | char *prmt_mem_ptr = xzalloc(1); |
1974 | # if ENABLE_USERNAME_OR_HOMEDIR | ||
1975 | char *cwd_buf = NULL; | 2004 | char *cwd_buf = NULL; |
1976 | # endif | ||
1977 | char flg_not_length = '['; | 2005 | char flg_not_length = '['; |
1978 | char cbuf[2]; | 2006 | char cbuf[2]; |
1979 | 2007 | ||
@@ -2040,11 +2068,9 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2040 | c = *prmt_ptr++; | 2068 | c = *prmt_ptr++; |
2041 | 2069 | ||
2042 | switch (c) { | 2070 | switch (c) { |
2043 | # if ENABLE_USERNAME_OR_HOMEDIR | ||
2044 | case 'u': | 2071 | case 'u': |
2045 | pbuf = user_buf ? user_buf : (char*)""; | 2072 | pbuf = user_buf ? user_buf : (char*)""; |
2046 | break; | 2073 | break; |
2047 | # endif | ||
2048 | case 'H': | 2074 | case 'H': |
2049 | case 'h': | 2075 | case 'h': |
2050 | pbuf = free_me = safe_gethostname(); | 2076 | pbuf = free_me = safe_gethostname(); |
@@ -2062,7 +2088,6 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2062 | strftime_HHMMSS(timebuf, sizeof(timebuf), NULL)[-3] = '\0'; | 2088 | strftime_HHMMSS(timebuf, sizeof(timebuf), NULL)[-3] = '\0'; |
2063 | pbuf = timebuf; | 2089 | pbuf = timebuf; |
2064 | break; | 2090 | break; |
2065 | # if ENABLE_USERNAME_OR_HOMEDIR | ||
2066 | case 'w': /* current dir */ | 2091 | case 'w': /* current dir */ |
2067 | case 'W': /* basename of cur dir */ | 2092 | case 'W': /* basename of cur dir */ |
2068 | if (!cwd_buf) { | 2093 | if (!cwd_buf) { |
@@ -2089,7 +2114,6 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2089 | if (cp) | 2114 | if (cp) |
2090 | pbuf = (char*)cp + 1; | 2115 | pbuf = (char*)cp + 1; |
2091 | break; | 2116 | break; |
2092 | # endif | ||
2093 | // bb_process_escape_sequence does this now: | 2117 | // bb_process_escape_sequence does this now: |
2094 | // case 'e': case 'E': /* \e \E = \033 */ | 2118 | // case 'e': case 'E': /* \e \E = \033 */ |
2095 | // c = '\033'; | 2119 | // c = '\033'; |
@@ -2130,10 +2154,17 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2130 | if (c == '\n') | 2154 | if (c == '\n') |
2131 | cmdedit_prmt_len = 0; | 2155 | cmdedit_prmt_len = 0; |
2132 | else if (flg_not_length != ']') { | 2156 | else if (flg_not_length != ']') { |
2133 | #if 0 /*ENABLE_UNICODE_SUPPORT*/ | 2157 | #if ENABLE_UNICODE_SUPPORT |
2134 | /* Won't work, pbuf is one BYTE string here instead of an one Unicode char string. */ | 2158 | if (n == 1) { |
2135 | /* FIXME */ | 2159 | /* Only count single-byte characters and the first of multi-byte characters */ |
2136 | cmdedit_prmt_len += unicode_strwidth(pbuf); | 2160 | if ((unsigned char)*pbuf < 0x80 /* single byte character */ |
2161 | || (unsigned char)*pbuf >= 0xc0 /* first of multi-byte characters */ | ||
2162 | ) { | ||
2163 | cmdedit_prmt_len += n; | ||
2164 | } | ||
2165 | } else { | ||
2166 | cmdedit_prmt_len += unicode_strwidth(pbuf); | ||
2167 | } | ||
2137 | #else | 2168 | #else |
2138 | cmdedit_prmt_len += n; | 2169 | cmdedit_prmt_len += n; |
2139 | #endif | 2170 | #endif |
@@ -2143,10 +2174,8 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2143 | free(free_me); | 2174 | free(free_me); |
2144 | } /* while */ | 2175 | } /* while */ |
2145 | 2176 | ||
2146 | # if ENABLE_USERNAME_OR_HOMEDIR | ||
2147 | if (cwd_buf != (char *)bb_msg_unknown) | 2177 | if (cwd_buf != (char *)bb_msg_unknown) |
2148 | free(cwd_buf); | 2178 | free(cwd_buf); |
2149 | # endif | ||
2150 | /* see comment (above this function) about multiline prompt redrawing */ | 2179 | /* see comment (above this function) about multiline prompt redrawing */ |
2151 | cmdedit_prompt = prompt_last_line = prmt_mem_ptr; | 2180 | cmdedit_prompt = prompt_last_line = prmt_mem_ptr; |
2152 | prmt_ptr = strrchr(cmdedit_prompt, '\n'); | 2181 | prmt_ptr = strrchr(cmdedit_prompt, '\n'); |
@@ -2154,7 +2183,7 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2154 | prompt_last_line = prmt_ptr + 1; | 2183 | prompt_last_line = prmt_ptr + 1; |
2155 | put_prompt(); | 2184 | put_prompt(); |
2156 | } | 2185 | } |
2157 | #endif | 2186 | #endif /* FEATURE_EDITING_FANCY_PROMPT */ |
2158 | 2187 | ||
2159 | #if ENABLE_FEATURE_EDITING_WINCH | 2188 | #if ENABLE_FEATURE_EDITING_WINCH |
2160 | static void cmdedit_setwidth(void) | 2189 | static void cmdedit_setwidth(void) |
@@ -2467,6 +2496,11 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2467 | char read_key_buffer[KEYCODE_BUFFER_SIZE]; | 2496 | char read_key_buffer[KEYCODE_BUFFER_SIZE]; |
2468 | 2497 | ||
2469 | INIT_S(); | 2498 | INIT_S(); |
2499 | //command_len = 0; - done by INIT_S() | ||
2500 | //cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */ | ||
2501 | cmdedit_termw = 80; | ||
2502 | IF_USERNAME_OR_HOMEDIR(home_pwd_buf = (char*)null_str;) | ||
2503 | IF_FEATURE_EDITING_VI(delptr = delbuf;) | ||
2470 | 2504 | ||
2471 | #if !ENABLE_PLATFORM_MINGW32 | 2505 | #if !ENABLE_PLATFORM_MINGW32 |
2472 | n = get_termios_and_make_raw(STDIN_FILENO, &new_settings, &initial_settings, 0 | 2506 | n = get_termios_and_make_raw(STDIN_FILENO, &new_settings, &initial_settings, 0 |
@@ -2521,8 +2555,6 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2521 | #endif | 2555 | #endif |
2522 | 2556 | ||
2523 | /* prepare before init handlers */ | 2557 | /* prepare before init handlers */ |
2524 | cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */ | ||
2525 | command_len = 0; | ||
2526 | #if ENABLE_UNICODE_SUPPORT | 2558 | #if ENABLE_UNICODE_SUPPORT |
2527 | command_ps = xzalloc(maxsize * sizeof(command_ps[0])); | 2559 | command_ps = xzalloc(maxsize * sizeof(command_ps[0])); |
2528 | #else | 2560 | #else |
@@ -3005,6 +3037,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
3005 | * before it comes in. UGLY! | 3037 | * before it comes in. UGLY! |
3006 | */ | 3038 | */ |
3007 | usleep(20*1000); | 3039 | usleep(20*1000); |
3040 | // MAYBE? tcflush(STDIN_FILENO, TCIFLUSH); /* flushes data received but not read */ | ||
3008 | } | 3041 | } |
3009 | #endif | 3042 | #endif |
3010 | 3043 | ||
diff --git a/libbb/loop.c b/libbb/loop.c index 85b2724e5..cb8fa2442 100644 --- a/libbb/loop.c +++ b/libbb/loop.c | |||
@@ -98,9 +98,7 @@ int FAST_FUNC get_free_loop(void) | |||
98 | 98 | ||
99 | /* Returns opened fd to the loop device, <0 on error. | 99 | /* Returns opened fd to the loop device, <0 on error. |
100 | * *device is loop device to use, or if *device==NULL finds a loop device to | 100 | * *device is loop device to use, or if *device==NULL finds a loop device to |
101 | * mount it on and sets *device to a strdup of that loop device name. This | 101 | * mount it on and sets *device to a strdup of that loop device name. |
102 | * search will re-use an existing loop device already bound to that | ||
103 | * file/offset if it finds one. | ||
104 | */ | 102 | */ |
105 | int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offset, | 103 | int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offset, |
106 | unsigned long long sizelimit, unsigned flags) | 104 | unsigned long long sizelimit, unsigned flags) |
@@ -109,9 +107,7 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse | |||
109 | char *try; | 107 | char *try; |
110 | bb_loop_info loopinfo; | 108 | bb_loop_info loopinfo; |
111 | struct stat statbuf; | 109 | struct stat statbuf; |
112 | int i, dfd, ffd, mode, rc; | 110 | int i, lfd, ffd, mode, rc; |
113 | |||
114 | rc = dfd = -1; | ||
115 | 111 | ||
116 | /* Open the file. Barf if this doesn't work. */ | 112 | /* Open the file. Barf if this doesn't work. */ |
117 | mode = (flags & BB_LO_FLAGS_READ_ONLY) ? O_RDONLY : O_RDWR; | 113 | mode = (flags & BB_LO_FLAGS_READ_ONLY) ? O_RDONLY : O_RDWR; |
@@ -127,24 +123,23 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse | |||
127 | 123 | ||
128 | try = *device; | 124 | try = *device; |
129 | if (!try) { | 125 | if (!try) { |
126 | get_free_loopN: | ||
130 | i = get_free_loop(); | 127 | i = get_free_loop(); |
131 | if (i == -2) { /* no /dev/loop-control */ | ||
132 | i = 0; | ||
133 | try = dev; | ||
134 | goto old_style; | ||
135 | } | ||
136 | if (i == -1) { | 128 | if (i == -1) { |
137 | close(ffd); | 129 | close(ffd); |
138 | return -1; /* no free loop devices */ | 130 | return -1; /* no free loop devices */ |
139 | } | 131 | } |
140 | try = *device = xasprintf(LOOP_FORMAT, i); | 132 | if (i >= 0) { |
141 | goto try_to_open; | 133 | try = xasprintf(LOOP_FORMAT, i); |
134 | goto open_lfd; | ||
135 | } | ||
136 | /* i == -2: no /dev/loop-control. Do an old-style search for a free device */ | ||
137 | try = dev; | ||
142 | } | 138 | } |
143 | 139 | ||
144 | old_style: | 140 | /* Find a loop device */ |
145 | /* Find a loop device. */ | 141 | /* 0xfffff is a max possible minor number in Linux circa 2010 */ |
146 | /* 1048575 (0xfffff) is a max possible minor number in Linux circa 2010 */ | 142 | for (i = 0; i <= 0xfffff; i++) { |
147 | for (i = 0; rc && i < 1048576; i++) { | ||
148 | sprintf(dev, LOOP_FORMAT, i); | 143 | sprintf(dev, LOOP_FORMAT, i); |
149 | 144 | ||
150 | IF_FEATURE_MOUNT_LOOP_CREATE(errno = 0;) | 145 | IF_FEATURE_MOUNT_LOOP_CREATE(errno = 0;) |
@@ -153,72 +148,86 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse | |||
153 | && errno == ENOENT | 148 | && errno == ENOENT |
154 | && try == dev | 149 | && try == dev |
155 | ) { | 150 | ) { |
156 | /* Node doesn't exist, try to create it. */ | 151 | /* Node doesn't exist, try to create it */ |
157 | if (mknod(dev, S_IFBLK|0644, makedev(7, i)) == 0) | 152 | if (mknod(dev, S_IFBLK|0644, makedev(7, i)) == 0) |
158 | goto try_to_open; | 153 | goto open_lfd; |
159 | } | 154 | } |
160 | /* Ran out of block devices, return failure. */ | 155 | /* Ran out of block devices, return failure */ |
161 | rc = -1; | 156 | rc = -1; |
162 | break; | 157 | break; |
163 | } | 158 | } |
164 | try_to_open: | 159 | open_lfd: |
165 | /* Open the sucker and check its loopiness. */ | 160 | /* Open the sucker and check its loopiness */ |
166 | dfd = open(try, mode); | 161 | lfd = rc = open(try, mode); |
167 | if (dfd < 0 && errno == EROFS) { | 162 | if (lfd < 0 && errno == EROFS) { |
168 | mode = O_RDONLY; | 163 | mode = O_RDONLY; |
169 | dfd = open(try, mode); | 164 | lfd = rc = open(try, mode); |
170 | } | 165 | } |
171 | if (dfd < 0) { | 166 | if (lfd < 0) { |
172 | if (errno == ENXIO) { | 167 | if (errno == ENXIO) { |
173 | /* Happens if loop module is not loaded */ | 168 | /* Happens if loop module is not loaded */ |
174 | rc = -1; | 169 | /* rc is -1; */ |
175 | break; | 170 | break; |
176 | } | 171 | } |
177 | goto try_again; | 172 | goto try_next_loopN; |
178 | } | 173 | } |
179 | 174 | ||
180 | rc = ioctl(dfd, BB_LOOP_GET_STATUS, &loopinfo); | 175 | rc = ioctl(lfd, BB_LOOP_GET_STATUS, &loopinfo); |
181 | 176 | ||
182 | /* If device is free, claim it. */ | 177 | /* If device is free, try to claim it */ |
183 | if (rc && errno == ENXIO) { | 178 | if (rc && errno == ENXIO) { |
184 | /* Associate free loop device with file. */ | 179 | /* Associate free loop device with file */ |
185 | if (ioctl(dfd, LOOP_SET_FD, ffd) == 0) { | 180 | if (ioctl(lfd, LOOP_SET_FD, ffd)) { |
186 | memset(&loopinfo, 0, sizeof(loopinfo)); | 181 | /* Ouch. Are we racing with other mount? */ |
187 | safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE); | 182 | if (!*device /* yes */ |
188 | loopinfo.lo_offset = offset; | 183 | && try != dev /* tried a _kernel-offered_ loopN? */ |
189 | loopinfo.lo_sizelimit = sizelimit; | 184 | ) { |
190 | /* | 185 | free(try); |
191 | * Used by mount to set LO_FLAGS_AUTOCLEAR. | 186 | close(lfd); |
192 | * LO_FLAGS_READ_ONLY is not set because RO is controlled by open type of the file. | 187 | //TODO: add "if (--failcount != 0) ..."? |
193 | * Note that closing LO_FLAGS_AUTOCLEARed dfd before mount | 188 | goto get_free_loopN; |
194 | * is wrong (would free the loop device!) | ||
195 | */ | ||
196 | loopinfo.lo_flags = (flags & ~BB_LO_FLAGS_READ_ONLY); | ||
197 | rc = ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo); | ||
198 | if (rc != 0 && (loopinfo.lo_flags & BB_LO_FLAGS_AUTOCLEAR)) { | ||
199 | /* Old kernel, does not support LO_FLAGS_AUTOCLEAR? */ | ||
200 | /* (this code path is not tested) */ | ||
201 | loopinfo.lo_flags -= BB_LO_FLAGS_AUTOCLEAR; | ||
202 | rc = ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo); | ||
203 | } | ||
204 | if (rc != 0) { | ||
205 | ioctl(dfd, LOOP_CLR_FD, 0); // actually, 0 param is unnecessary | ||
206 | } | 189 | } |
190 | goto close_and_try_next_loopN; | ||
207 | } | 191 | } |
208 | } else { | 192 | memset(&loopinfo, 0, sizeof(loopinfo)); |
209 | rc = -1; | 193 | safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE); |
210 | } | 194 | loopinfo.lo_offset = offset; |
211 | if (rc != 0) { | 195 | loopinfo.lo_sizelimit = sizelimit; |
212 | close(dfd); | 196 | /* |
197 | * Used by mount to set LO_FLAGS_AUTOCLEAR. | ||
198 | * LO_FLAGS_READ_ONLY is not set because RO is controlled by open type of the file. | ||
199 | * Note that closing LO_FLAGS_AUTOCLEARed lfd before mount | ||
200 | * is wrong (would free the loop device!) | ||
201 | */ | ||
202 | loopinfo.lo_flags = (flags & ~BB_LO_FLAGS_READ_ONLY); | ||
203 | rc = ioctl(lfd, BB_LOOP_SET_STATUS, &loopinfo); | ||
204 | if (rc != 0 && (loopinfo.lo_flags & BB_LO_FLAGS_AUTOCLEAR)) { | ||
205 | /* Old kernel, does not support LO_FLAGS_AUTOCLEAR? */ | ||
206 | /* (this code path is not tested) */ | ||
207 | loopinfo.lo_flags -= BB_LO_FLAGS_AUTOCLEAR; | ||
208 | rc = ioctl(lfd, BB_LOOP_SET_STATUS, &loopinfo); | ||
209 | } | ||
210 | if (rc == 0) { | ||
211 | /* SUCCESS! */ | ||
212 | if (try != dev) /* tried a kernel-offered free loopN? */ | ||
213 | *device = try; /* malloced */ | ||
214 | if (!*device) /* was looping in search of free "/dev/loopN"? */ | ||
215 | *device = xstrdup(dev); | ||
216 | rc = lfd; /* return this */ | ||
217 | break; | ||
218 | } | ||
219 | /* failure, undo LOOP_SET_FD */ | ||
220 | ioctl(lfd, LOOP_CLR_FD, 0); // actually, 0 param is unnecessary | ||
213 | } | 221 | } |
214 | try_again: | 222 | /* else: device is not free (rc == 0) or error other than ENXIO */ |
215 | if (*device) break; | 223 | close_and_try_next_loopN: |
216 | } | 224 | close(lfd); |
225 | try_next_loopN: | ||
226 | rc = -1; | ||
227 | if (*device) /* was looking for a particular "/dev/loopN"? */ | ||
228 | break; /* yes, do not try other names */ | ||
229 | } /* for() */ | ||
230 | |||
217 | close(ffd); | 231 | close(ffd); |
218 | if (rc == 0) { | ||
219 | if (!*device) | ||
220 | *device = xstrdup(dev); | ||
221 | return dfd; | ||
222 | } | ||
223 | return rc; | 232 | return rc; |
224 | } | 233 | } |
diff --git a/libbb/mode_string.c b/libbb/mode_string.c index 6c5c08acd..dc3f9f88c 100644 --- a/libbb/mode_string.c +++ b/libbb/mode_string.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #define mode_t unsigned short | 27 | #define mode_t unsigned short |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | static const mode_t mode_flags[] = { | 30 | static const mode_t mode_flags[] ALIGN4 = { |
31 | S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID, | 31 | S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID, |
32 | S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID, | 32 | S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID, |
33 | S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX | 33 | S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX |
diff --git a/libbb/platform.c b/libbb/platform.c index 03bbb798b..329b0237e 100644 --- a/libbb/platform.c +++ b/libbb/platform.c | |||
@@ -27,7 +27,6 @@ int FAST_FUNC usleep(unsigned usec) | |||
27 | * If a signal has non-default handler, nanosleep returns early. | 27 | * If a signal has non-default handler, nanosleep returns early. |
28 | * Our version of usleep doesn't return early | 28 | * Our version of usleep doesn't return early |
29 | * if interrupted by such signals: | 29 | * if interrupted by such signals: |
30 | * | ||
31 | */ | 30 | */ |
32 | while (nanosleep(&ts, &ts) != 0) | 31 | while (nanosleep(&ts, &ts) != 0) |
33 | continue; | 32 | continue; |
@@ -107,7 +106,8 @@ void* FAST_FUNC memrchr(const void *s, int c, size_t n) | |||
107 | /* This is now actually part of POSIX.1, but was only added in 2008 */ | 106 | /* This is now actually part of POSIX.1, but was only added in 2008 */ |
108 | char* FAST_FUNC mkdtemp(char *template) | 107 | char* FAST_FUNC mkdtemp(char *template) |
109 | { | 108 | { |
110 | if (mktemp(template) == NULL || mkdir(template, 0700) != 0) | 109 | /* NB: on error, mktemp returns an empty string, not NULL */ |
110 | if (mktemp(template)[0] == '\0' || mkdir(template, 0700) != 0) | ||
111 | return NULL; | 111 | return NULL; |
112 | return template; | 112 | return template; |
113 | } | 113 | } |
diff --git a/libbb/procps.c b/libbb/procps.c index 4f9705bc1..8c9cac125 100644 --- a/libbb/procps.c +++ b/libbb/procps.c | |||
@@ -21,40 +21,29 @@ typedef struct cache_t { | |||
21 | int size; | 21 | int size; |
22 | } cache_t; | 22 | } cache_t; |
23 | 23 | ||
24 | static cache_t username, groupname; | 24 | static cache_t *cache_user_group; |
25 | 25 | ||
26 | static void clear_cache(cache_t *cp) | ||
27 | { | ||
28 | free(cp->cache); | ||
29 | cp->cache = NULL; | ||
30 | cp->size = 0; | ||
31 | } | ||
32 | void FAST_FUNC clear_username_cache(void) | 26 | void FAST_FUNC clear_username_cache(void) |
33 | { | 27 | { |
34 | clear_cache(&username); | 28 | if (cache_user_group) { |
35 | clear_cache(&groupname); | 29 | free(cache_user_group[0].cache); |
36 | } | 30 | free(cache_user_group[1].cache); |
37 | 31 | free(cache_user_group); | |
38 | #if 0 /* more generic, but we don't need that yet */ | 32 | cache_user_group = NULL; |
39 | /* Returns -N-1 if not found. */ | 33 | } |
40 | /* cp->cache[N] is allocated and must be filled in this case */ | ||
41 | static int get_cached(cache_t *cp, uid_t id) | ||
42 | { | ||
43 | int i; | ||
44 | for (i = 0; i < cp->size; i++) | ||
45 | if (cp->cache[i].id == id) | ||
46 | return i; | ||
47 | i = cp->size++; | ||
48 | cp->cache = xrealloc_vector(cp->cache, 2, i); | ||
49 | cp->cache[i++].id = id; | ||
50 | return -i; | ||
51 | } | 34 | } |
52 | #endif | ||
53 | 35 | ||
54 | static char* get_cached(cache_t *cp, uid_t id, | 36 | static char* get_cached(int user_group, uid_t id, |
55 | char* FAST_FUNC x2x_utoa(uid_t id)) | 37 | char* FAST_FUNC x2x_utoa(uid_t id)) |
56 | { | 38 | { |
39 | cache_t *cp; | ||
57 | int i; | 40 | int i; |
41 | |||
42 | if (!cache_user_group) | ||
43 | cache_user_group = xzalloc(sizeof(cache_user_group[0]) * 2); | ||
44 | |||
45 | cp = &cache_user_group[user_group]; | ||
46 | |||
58 | for (i = 0; i < cp->size; i++) | 47 | for (i = 0; i < cp->size; i++) |
59 | if (cp->cache[i].id == id) | 48 | if (cp->cache[i].id == id) |
60 | return cp->cache[i].name; | 49 | return cp->cache[i].name; |
@@ -67,11 +56,11 @@ static char* get_cached(cache_t *cp, uid_t id, | |||
67 | } | 56 | } |
68 | const char* FAST_FUNC get_cached_username(uid_t uid) | 57 | const char* FAST_FUNC get_cached_username(uid_t uid) |
69 | { | 58 | { |
70 | return get_cached(&username, uid, uid2uname_utoa); | 59 | return get_cached(0, uid, uid2uname_utoa); |
71 | } | 60 | } |
72 | const char* FAST_FUNC get_cached_groupname(gid_t gid) | 61 | const char* FAST_FUNC get_cached_groupname(gid_t gid) |
73 | { | 62 | { |
74 | return get_cached(&groupname, gid, gid2group_utoa); | 63 | return get_cached(1, gid, gid2group_utoa); |
75 | } | 64 | } |
76 | 65 | ||
77 | #if !ENABLE_PLATFORM_MINGW32 | 66 | #if !ENABLE_PLATFORM_MINGW32 |
@@ -95,15 +84,15 @@ static int read_to_buf(const char *filename, void *buf) | |||
95 | 84 | ||
96 | static procps_status_t* FAST_FUNC alloc_procps_scan(void) | 85 | static procps_status_t* FAST_FUNC alloc_procps_scan(void) |
97 | { | 86 | { |
98 | unsigned n = getpagesize(); | ||
99 | procps_status_t* sp = xzalloc(sizeof(procps_status_t)); | 87 | procps_status_t* sp = xzalloc(sizeof(procps_status_t)); |
100 | sp->dir = xopendir("/proc"); | 88 | unsigned n = bb_getpagesize(); |
101 | while (1) { | 89 | while (1) { |
102 | n >>= 1; | 90 | n >>= 1; |
103 | if (!n) break; | 91 | if (!n) break; |
104 | sp->shift_pages_to_bytes++; | 92 | sp->shift_pages_to_bytes++; |
105 | } | 93 | } |
106 | sp->shift_pages_to_kb = sp->shift_pages_to_bytes - 10; | 94 | sp->shift_pages_to_kb = sp->shift_pages_to_bytes - 10; |
95 | sp->dir = xopendir("/proc"); | ||
107 | return sp; | 96 | return sp; |
108 | } | 97 | } |
109 | 98 | ||
@@ -178,6 +167,7 @@ static char *skip_fields(char *str, int count) | |||
178 | } | 167 | } |
179 | #endif | 168 | #endif |
180 | 169 | ||
170 | #if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP | ||
181 | static char* skip_whitespace_if_prefixed_with(char *buf, const char *prefix) | 171 | static char* skip_whitespace_if_prefixed_with(char *buf, const char *prefix) |
182 | { | 172 | { |
183 | char *tp = is_prefixed_with(buf, prefix); | 173 | char *tp = is_prefixed_with(buf, prefix); |
@@ -187,7 +177,6 @@ static char* skip_whitespace_if_prefixed_with(char *buf, const char *prefix) | |||
187 | return tp; | 177 | return tp; |
188 | } | 178 | } |
189 | 179 | ||
190 | #if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP | ||
191 | int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total, | 180 | int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total, |
192 | void (*cb)(struct smaprec *, void *), void *data) | 181 | void (*cb)(struct smaprec *, void *), void *data) |
193 | { | 182 | { |
diff --git a/libbb/pw_encrypt.c b/libbb/pw_encrypt.c index 47c20690f..3463fd95b 100644 --- a/libbb/pw_encrypt.c +++ b/libbb/pw_encrypt.c | |||
@@ -7,7 +7,9 @@ | |||
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 | #if !ENABLE_USE_BB_CRYPT | 9 | #if !ENABLE_USE_BB_CRYPT |
10 | #include <crypt.h> | 10 | # if !defined(__FreeBSD__) |
11 | # include <crypt.h> | ||
12 | # endif | ||
11 | #endif | 13 | #endif |
12 | #include "libbb.h" | 14 | #include "libbb.h" |
13 | 15 | ||
@@ -120,6 +122,7 @@ static char *my_crypt(const char *key, const char *salt) | |||
120 | if (!des_cctx) | 122 | if (!des_cctx) |
121 | des_cctx = const_des_init(); | 123 | des_cctx = const_des_init(); |
122 | des_ctx = des_init(des_ctx, des_cctx); | 124 | des_ctx = des_init(des_ctx, des_cctx); |
125 | /* Can return NULL if salt is bad ("" or "<one_char>") */ | ||
123 | return des_crypt(des_ctx, xzalloc(DES_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt); | 126 | return des_crypt(des_ctx, xzalloc(DES_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt); |
124 | } | 127 | } |
125 | 128 | ||
@@ -137,6 +140,8 @@ char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup) | |||
137 | char *encrypted; | 140 | char *encrypted; |
138 | 141 | ||
139 | encrypted = my_crypt(clear, salt); | 142 | encrypted = my_crypt(clear, salt); |
143 | if (!encrypted) | ||
144 | bb_simple_error_msg_and_die("bad salt"); | ||
140 | 145 | ||
141 | if (cleanup) | 146 | if (cleanup) |
142 | my_crypt_cleanup(); | 147 | my_crypt_cleanup(); |
@@ -148,14 +153,16 @@ char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup) | |||
148 | 153 | ||
149 | char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup) | 154 | char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup) |
150 | { | 155 | { |
151 | char *s; | 156 | char *encrypted; |
152 | 157 | ||
153 | s = crypt(clear, salt); | 158 | encrypted = crypt(clear, salt); |
154 | /* | 159 | /* |
155 | * glibc used to return "" on malformed salts (for example, ""), | 160 | * glibc used to return "" on malformed salts (for example, ""), |
156 | * but since 2.17 it returns NULL. | 161 | * but since 2.17 it returns NULL. |
157 | */ | 162 | */ |
158 | return xstrdup(s ? s : ""); | 163 | if (!encrypted || !encrypted[0]) |
164 | bb_simple_error_msg_and_die("bad salt"); | ||
165 | return xstrdup(encrypted); | ||
159 | } | 166 | } |
160 | 167 | ||
161 | #endif | 168 | #endif |
diff --git a/libbb/pw_encrypt_des.c b/libbb/pw_encrypt_des.c index 19a9ab15b..dcd3521e2 100644 --- a/libbb/pw_encrypt_des.c +++ b/libbb/pw_encrypt_des.c | |||
@@ -65,25 +65,25 @@ | |||
65 | 65 | ||
66 | 66 | ||
67 | /* A pile of data */ | 67 | /* A pile of data */ |
68 | static const uint8_t IP[64] = { | 68 | static const uint8_t IP[64] ALIGN1 = { |
69 | 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, | 69 | 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, |
70 | 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, | 70 | 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, |
71 | 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, | 71 | 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, |
72 | 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 | 72 | 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 |
73 | }; | 73 | }; |
74 | 74 | ||
75 | static const uint8_t key_perm[56] = { | 75 | static const uint8_t key_perm[56] ALIGN1 = { |
76 | 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, | 76 | 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, |
77 | 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, | 77 | 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, |
78 | 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, | 78 | 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, |
79 | 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 | 79 | 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 |
80 | }; | 80 | }; |
81 | 81 | ||
82 | static const uint8_t key_shifts[16] = { | 82 | static const uint8_t key_shifts[16] ALIGN1 = { |
83 | 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 | 83 | 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 |
84 | }; | 84 | }; |
85 | 85 | ||
86 | static const uint8_t comp_perm[48] = { | 86 | static const uint8_t comp_perm[48] ALIGN1 = { |
87 | 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, | 87 | 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, |
88 | 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, | 88 | 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, |
89 | 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, | 89 | 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, |
@@ -181,13 +181,12 @@ static const uint8_t u_sbox[8][32] = { | |||
181 | }; | 181 | }; |
182 | #endif | 182 | #endif |
183 | 183 | ||
184 | static const uint8_t pbox[32] = { | 184 | static const uint8_t pbox[32] ALIGN1 = { |
185 | 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, | 185 | 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, |
186 | 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 | 186 | 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 |
187 | }; | 187 | }; |
188 | 188 | ||
189 | static const uint32_t bits32[32] = | 189 | static const uint32_t bits32[32] ALIGN4 = { |
190 | { | ||
191 | 0x80000000, 0x40000000, 0x20000000, 0x10000000, | 190 | 0x80000000, 0x40000000, 0x20000000, 0x10000000, |
192 | 0x08000000, 0x04000000, 0x02000000, 0x01000000, | 191 | 0x08000000, 0x04000000, 0x02000000, 0x01000000, |
193 | 0x00800000, 0x00400000, 0x00200000, 0x00100000, | 192 | 0x00800000, 0x00400000, 0x00200000, 0x00100000, |
@@ -198,7 +197,7 @@ static const uint32_t bits32[32] = | |||
198 | 0x00000008, 0x00000004, 0x00000002, 0x00000001 | 197 | 0x00000008, 0x00000004, 0x00000002, 0x00000001 |
199 | }; | 198 | }; |
200 | 199 | ||
201 | static const uint8_t bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; | 200 | static const uint8_t bits8[8] ALIGN1 = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; |
202 | 201 | ||
203 | 202 | ||
204 | static int | 203 | static int |
@@ -714,11 +713,15 @@ to64_msb_first(char *s, unsigned v) | |||
714 | static char * | 713 | static char * |
715 | NOINLINE | 714 | NOINLINE |
716 | des_crypt(struct des_ctx *ctx, char output[DES_OUT_BUFSIZE], | 715 | des_crypt(struct des_ctx *ctx, char output[DES_OUT_BUFSIZE], |
717 | const unsigned char *key, const unsigned char *setting) | 716 | const unsigned char *key, const unsigned char *salt_str) |
718 | { | 717 | { |
719 | uint32_t salt, r0, r1, keybuf[2]; | 718 | uint32_t salt, r0, r1, keybuf[2]; |
720 | uint8_t *q; | 719 | uint8_t *q; |
721 | 720 | ||
721 | /* Bad salt? Mimic crypt() API - return NULL */ | ||
722 | if (!salt_str[0] || !salt_str[1]) | ||
723 | return NULL; | ||
724 | |||
722 | /* | 725 | /* |
723 | * Copy the key, shifting each character up by one bit | 726 | * Copy the key, shifting each character up by one bit |
724 | * and padding with zeros. | 727 | * and padding with zeros. |
@@ -733,22 +736,15 @@ des_crypt(struct des_ctx *ctx, char output[DES_OUT_BUFSIZE], | |||
733 | des_setkey(ctx, (char *)keybuf); | 736 | des_setkey(ctx, (char *)keybuf); |
734 | 737 | ||
735 | /* | 738 | /* |
736 | * setting - 2 bytes of salt | 739 | * salt_str - 2 bytes of salt |
737 | * key - up to 8 characters | 740 | * key - up to 8 characters |
738 | */ | 741 | */ |
739 | salt = (ascii_to_bin(setting[1]) << 6) | 742 | output[0] = salt_str[0]; |
740 | | ascii_to_bin(setting[0]); | 743 | output[1] = salt_str[1]; |
741 | 744 | salt = (ascii_to_bin(salt_str[1]) << 6) | |
742 | output[0] = setting[0]; | 745 | | ascii_to_bin(salt_str[0]); |
743 | /* | ||
744 | * If the encrypted password that the salt was extracted from | ||
745 | * is only 1 character long, the salt will be corrupted. We | ||
746 | * need to ensure that the output string doesn't have an extra | ||
747 | * NUL in it! | ||
748 | */ | ||
749 | output[1] = setting[1] ? setting[1] : output[0]; | ||
750 | |||
751 | setup_salt(ctx, salt); | 746 | setup_salt(ctx, salt); |
747 | |||
752 | /* Do it. */ | 748 | /* Do it. */ |
753 | do_des(ctx, /*0, 0,*/ &r0, &r1, 25 /* count */); | 749 | do_des(ctx, /*0, 0,*/ &r0, &r1, 25 /* count */); |
754 | 750 | ||
diff --git a/libbb/rtc.c b/libbb/rtc.c index c4117ba34..54b52f23a 100644 --- a/libbb/rtc.c +++ b/libbb/rtc.c | |||
@@ -7,12 +7,6 @@ | |||
7 | #include "libbb.h" | 7 | #include "libbb.h" |
8 | #include "rtc_.h" | 8 | #include "rtc_.h" |
9 | 9 | ||
10 | #if ENABLE_FEATURE_HWCLOCK_ADJTIME_FHS | ||
11 | # define ADJTIME_PATH "/var/lib/hwclock/adjtime" | ||
12 | #else | ||
13 | # define ADJTIME_PATH "/etc/adjtime" | ||
14 | #endif | ||
15 | |||
16 | int FAST_FUNC rtc_adjtime_is_utc(void) | 10 | int FAST_FUNC rtc_adjtime_is_utc(void) |
17 | { | 11 | { |
18 | int utc = 0; | 12 | int utc = 0; |
diff --git a/libbb/run_shell.c b/libbb/run_shell.c index a0420d982..c22bba87b 100644 --- a/libbb/run_shell.c +++ b/libbb/run_shell.c | |||
@@ -48,10 +48,10 @@ void FAST_FUNC set_current_security_context(security_context_t sid) | |||
48 | 48 | ||
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | /* Run SHELL, or DEFAULT_SHELL if SHELL is "" or NULL. | 51 | /* Exec SHELL, or DEFAULT_SHELL if SHELL is "" or NULL. |
52 | * If ADDITIONAL_ARGS is not NULL, pass them to the shell. | 52 | * If ADDITIONAL_ARGS is not NULL, pass them to the shell. |
53 | */ | 53 | */ |
54 | void FAST_FUNC run_shell(const char *shell, int loginshell, const char **additional_args) | 54 | void FAST_FUNC exec_shell(const char *shell, int loginshell, const char **additional_args) |
55 | { | 55 | { |
56 | const char **args; | 56 | const char **args; |
57 | 57 | ||
@@ -59,7 +59,7 @@ void FAST_FUNC run_shell(const char *shell, int loginshell, const char **additio | |||
59 | while (args && *args) | 59 | while (args && *args) |
60 | args++; | 60 | args++; |
61 | 61 | ||
62 | args = xmalloc(sizeof(char*) * (2 + (args - additional_args))); | 62 | args = xzalloc(sizeof(args[0]) * (2 + (args - additional_args))); |
63 | 63 | ||
64 | if (!shell || !shell[0]) | 64 | if (!shell || !shell[0]) |
65 | shell = DEFAULT_SHELL; | 65 | shell = DEFAULT_SHELL; |
@@ -67,12 +67,11 @@ void FAST_FUNC run_shell(const char *shell, int loginshell, const char **additio | |||
67 | args[0] = bb_get_last_path_component_nostrip(shell); | 67 | args[0] = bb_get_last_path_component_nostrip(shell); |
68 | if (loginshell) | 68 | if (loginshell) |
69 | args[0] = xasprintf("-%s", args[0]); | 69 | args[0] = xasprintf("-%s", args[0]); |
70 | args[1] = NULL; | 70 | /*args[1] = NULL; - already is */ |
71 | if (additional_args) { | 71 | if (additional_args) { |
72 | int cnt = 1; | 72 | int cnt = 0; |
73 | for (;;) | 73 | while (*additional_args) |
74 | if ((args[cnt++] = *additional_args++) == NULL) | 74 | args[++cnt] = *additional_args++; |
75 | break; | ||
76 | } | 75 | } |
77 | 76 | ||
78 | #if ENABLE_SELINUX | 77 | #if ENABLE_SELINUX |
@@ -84,3 +83,20 @@ void FAST_FUNC run_shell(const char *shell, int loginshell, const char **additio | |||
84 | execv(shell, (char **) args); | 83 | execv(shell, (char **) args); |
85 | bb_perror_msg_and_die("can't execute '%s'", shell); | 84 | bb_perror_msg_and_die("can't execute '%s'", shell); |
86 | } | 85 | } |
86 | |||
87 | void FAST_FUNC exec_login_shell(const char *shell) | ||
88 | { | ||
89 | exec_shell(shell, 1, NULL); | ||
90 | } | ||
91 | |||
92 | /* Typical idiom for applets which exec *optional* PROG [ARGS] */ | ||
93 | void FAST_FUNC exec_prog_or_SHELL(char **argv) | ||
94 | { | ||
95 | if (argv[0]) { | ||
96 | BB_EXECVP_or_die(argv); | ||
97 | } | ||
98 | /* Both users (nsenter and unshare) do indeed exec | ||
99 | * a _login_ shell (with dash in argv[0])! | ||
100 | */ | ||
101 | exec_login_shell(getenv("SHELL")); | ||
102 | } | ||
diff --git a/libbb/speed_table.c b/libbb/speed_table.c index 967cf8de8..cf7101e64 100644 --- a/libbb/speed_table.c +++ b/libbb/speed_table.c | |||
@@ -28,7 +28,7 @@ struct speed_map { | |||
28 | }; | 28 | }; |
29 | 29 | ||
30 | /* On Linux, Bxx constants are 0..15 (up to B38400) and 0x1001..0x100f */ | 30 | /* On Linux, Bxx constants are 0..15 (up to B38400) and 0x1001..0x100f */ |
31 | static const struct speed_map speeds[] = { | 31 | static const struct speed_map speeds[] ALIGN4 = { |
32 | {B0, 0}, | 32 | {B0, 0}, |
33 | {B50, 50}, | 33 | {B50, 50}, |
34 | {B75, 75}, | 34 | {B75, 75}, |
diff --git a/libbb/time.c b/libbb/time.c index e66a9cba8..cf5f2e5c8 100644 --- a/libbb/time.c +++ b/libbb/time.c | |||
@@ -90,7 +90,11 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm) | |||
90 | ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ | 90 | ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ |
91 | } else | 91 | } else |
92 | if (date_str[0] == '@') { | 92 | if (date_str[0] == '@') { |
93 | time_t t = bb_strtol(date_str + 1, NULL, 10); | 93 | time_t t; |
94 | if (sizeof(t) <= sizeof(long)) | ||
95 | t = bb_strtol(date_str + 1, NULL, 10); | ||
96 | else /* time_t is 64 bits but longs are smaller */ | ||
97 | t = bb_strtoll(date_str + 1, NULL, 10); | ||
94 | if (!errno) { | 98 | if (!errno) { |
95 | struct tm *lt = localtime(&t); | 99 | struct tm *lt = localtime(&t); |
96 | if (lt) { | 100 | if (lt) { |
@@ -246,7 +250,6 @@ char* FAST_FUNC strftime_YYYYMMDDHHMMSS(char *buf, unsigned len, time_t *tp) | |||
246 | 250 | ||
247 | #if ENABLE_MONOTONIC_SYSCALL | 251 | #if ENABLE_MONOTONIC_SYSCALL |
248 | 252 | ||
249 | #include <sys/syscall.h> | ||
250 | /* Old glibc (< 2.3.4) does not provide this constant. We use syscall | 253 | /* Old glibc (< 2.3.4) does not provide this constant. We use syscall |
251 | * directly so this definition is safe. */ | 254 | * directly so this definition is safe. */ |
252 | #ifndef CLOCK_MONOTONIC | 255 | #ifndef CLOCK_MONOTONIC |
@@ -288,19 +291,19 @@ unsigned FAST_FUNC monotonic_sec(void) | |||
288 | unsigned long long FAST_FUNC monotonic_ns(void) | 291 | unsigned long long FAST_FUNC monotonic_ns(void) |
289 | { | 292 | { |
290 | struct timeval tv; | 293 | struct timeval tv; |
291 | gettimeofday(&tv, NULL); | 294 | xgettimeofday(&tv); |
292 | return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000; | 295 | return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000; |
293 | } | 296 | } |
294 | unsigned long long FAST_FUNC monotonic_us(void) | 297 | unsigned long long FAST_FUNC monotonic_us(void) |
295 | { | 298 | { |
296 | struct timeval tv; | 299 | struct timeval tv; |
297 | gettimeofday(&tv, NULL); | 300 | xgettimeofday(&tv); |
298 | return tv.tv_sec * 1000000ULL + tv.tv_usec; | 301 | return tv.tv_sec * 1000000ULL + tv.tv_usec; |
299 | } | 302 | } |
300 | unsigned long long FAST_FUNC monotonic_ms(void) | 303 | unsigned long long FAST_FUNC monotonic_ms(void) |
301 | { | 304 | { |
302 | struct timeval tv; | 305 | struct timeval tv; |
303 | gettimeofday(&tv, NULL); | 306 | xgettimeofday(&tv); |
304 | return tv.tv_sec * 1000ULL + tv.tv_usec / 1000; | 307 | return tv.tv_sec * 1000ULL + tv.tv_usec / 1000; |
305 | } | 308 | } |
306 | unsigned FAST_FUNC monotonic_sec(void) | 309 | unsigned FAST_FUNC monotonic_sec(void) |
diff --git a/libbb/unicode.c b/libbb/unicode.c index 79481f159..e98cbbf35 100644 --- a/libbb/unicode.c +++ b/libbb/unicode.c | |||
@@ -25,7 +25,7 @@ uint8_t unicode_status; | |||
25 | 25 | ||
26 | void FAST_FUNC reinit_unicode(const char *LANG) | 26 | void FAST_FUNC reinit_unicode(const char *LANG) |
27 | { | 27 | { |
28 | static const char unicode_0x394[] = { 0xce, 0x94, 0 }; | 28 | static const char unicode_0x394[] ALIGN1 = { 0xce, 0x94, 0 }; |
29 | size_t width; | 29 | size_t width; |
30 | 30 | ||
31 | /* We pass "" instead of "C" because some libc's have | 31 | /* We pass "" instead of "C" because some libc's have |
@@ -306,8 +306,10 @@ static int in_uint16_table(unsigned ucs, const uint16_t *table, unsigned max) | |||
306 | unsigned first, last; | 306 | unsigned first, last; |
307 | 307 | ||
308 | first = table[0] >> 2; | 308 | first = table[0] >> 2; |
309 | last = first + (table[0] & 3); | 309 | if (ucs < first) |
310 | if (ucs < first || ucs > last) | 310 | return 0; |
311 | last = (table[max] >> 2) + (table[max] & 3); | ||
312 | if (ucs > last) | ||
311 | return 0; | 313 | return 0; |
312 | 314 | ||
313 | min = 0; | 315 | min = 0; |
@@ -587,12 +589,12 @@ int FAST_FUNC wcwidth(unsigned ucs) | |||
587 | BIG_(0xFE20, 0xFE23) \ | 589 | BIG_(0xFE20, 0xFE23) \ |
588 | BIG_(0xFEFF, 0xFEFF) \ | 590 | BIG_(0xFEFF, 0xFEFF) \ |
589 | BIG_(0xFFF9, 0xFFFB) | 591 | BIG_(0xFFF9, 0xFFFB) |
590 | static const struct interval combining[] = { ARRAY }; | 592 | static const struct interval combining[] ALIGN4 = { ARRAY }; |
591 | # undef BIG_ | 593 | # undef BIG_ |
592 | # undef PAIR | 594 | # undef PAIR |
593 | # define BIG_(a,b) | 595 | # define BIG_(a,b) |
594 | # define PAIR(a,b) (a << 2) | (b-a), | 596 | # define PAIR(a,b) (a << 2) | (b-a), |
595 | static const uint16_t combining1[] = { ARRAY }; | 597 | static const uint16_t combining1[] ALIGN2 = { ARRAY }; |
596 | # undef BIG_ | 598 | # undef BIG_ |
597 | # undef PAIR | 599 | # undef PAIR |
598 | # define BIG_(a,b) char big_##a[b < 0x4000 && b-a <= 3 ? -1 : 1]; | 600 | # define BIG_(a,b) char big_##a[b < 0x4000 && b-a <= 3 ? -1 : 1]; |
@@ -646,7 +648,7 @@ int FAST_FUNC wcwidth(unsigned ucs) | |||
646 | # if CONFIG_LAST_SUPPORTED_WCHAR >= 0x10000 | 648 | # if CONFIG_LAST_SUPPORTED_WCHAR >= 0x10000 |
647 | if (ucs >= 0x10000) { | 649 | if (ucs >= 0x10000) { |
648 | /* Combining chars in Supplementary Multilingual Plane 0x1xxxx */ | 650 | /* Combining chars in Supplementary Multilingual Plane 0x1xxxx */ |
649 | static const struct interval combining0x10000[] = { | 651 | static const struct interval combining0x10000[] ALIGN4 = { |
650 | { 0x0A01, 0x0A03 }, { 0x0A05, 0x0A06 }, { 0x0A0C, 0x0A0F }, | 652 | { 0x0A01, 0x0A03 }, { 0x0A05, 0x0A06 }, { 0x0A0C, 0x0A0F }, |
651 | { 0x0A38, 0x0A3A }, { 0x0A3F, 0x0A3F }, { 0xD167, 0xD169 }, | 653 | { 0x0A38, 0x0A3A }, { 0x0A3F, 0x0A3F }, { 0xD167, 0xD169 }, |
652 | { 0xD173, 0xD182 }, { 0xD185, 0xD18B }, { 0xD1AA, 0xD1AD }, | 654 | { 0xD173, 0xD182 }, { 0xD185, 0xD18B }, { 0xD1AA, 0xD1AD }, |
@@ -757,12 +759,12 @@ int FAST_FUNC unicode_bidi_isrtl(wint_t wc) | |||
757 | {0x10E7F, 0x10FFF}, | 759 | {0x10E7F, 0x10FFF}, |
758 | {0x1E800, 0x1EFFF} | 760 | {0x1E800, 0x1EFFF} |
759 | */ | 761 | */ |
760 | static const struct interval rtl_b[] = { ARRAY }; | 762 | static const struct interval rtl_b[] ALIGN4 = { ARRAY }; |
761 | # undef BIG_ | 763 | # undef BIG_ |
762 | # undef PAIR | 764 | # undef PAIR |
763 | # define BIG_(a,b) | 765 | # define BIG_(a,b) |
764 | # define PAIR(a,b) (a << 2) | (b-a), | 766 | # define PAIR(a,b) (a << 2) | (b-a), |
765 | static const uint16_t rtl_p[] = { ARRAY }; | 767 | static const uint16_t rtl_p[] ALIGN2 = { ARRAY }; |
766 | # undef BIG_ | 768 | # undef BIG_ |
767 | # undef PAIR | 769 | # undef PAIR |
768 | # define BIG_(a,b) char big_##a[b < 0x4000 && b-a <= 3 ? -1 : 1]; | 770 | # define BIG_(a,b) char big_##a[b < 0x4000 && b-a <= 3 ? -1 : 1]; |
@@ -961,12 +963,12 @@ int FAST_FUNC unicode_bidi_is_neutral_wchar(wint_t wc) | |||
961 | {0x1F030, 0x1F093}, | 963 | {0x1F030, 0x1F093}, |
962 | {0x1F100, 0x1F10A} | 964 | {0x1F100, 0x1F10A} |
963 | */ | 965 | */ |
964 | static const struct interval neutral_b[] = { ARRAY }; | 966 | static const struct interval neutral_b[] ALIGN4 = { ARRAY }; |
965 | # undef BIG_ | 967 | # undef BIG_ |
966 | # undef PAIR | 968 | # undef PAIR |
967 | # define BIG_(a,b) | 969 | # define BIG_(a,b) |
968 | # define PAIR(a,b) (a << 2) | (b-a), | 970 | # define PAIR(a,b) (a << 2) | (b-a), |
969 | static const uint16_t neutral_p[] = { ARRAY }; | 971 | static const uint16_t neutral_p[] ALIGN2 = { ARRAY }; |
970 | # undef BIG_ | 972 | # undef BIG_ |
971 | # undef PAIR | 973 | # undef PAIR |
972 | # define BIG_(a,b) char big_##a[b < 0x4000 && b-a <= 3 ? -1 : 1]; | 974 | # define BIG_(a,b) char big_##a[b < 0x4000 && b-a <= 3 ? -1 : 1]; |
diff --git a/libbb/uuencode.c b/libbb/uuencode.c index d36b34f63..21af7a8c9 100644 --- a/libbb/uuencode.c +++ b/libbb/uuencode.c | |||
@@ -8,8 +8,18 @@ | |||
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | 10 | ||
11 | /* Conversion table. for base 64 */ | 11 | /* Conversion tables */ |
12 | const char bb_uuenc_tbl_base64[65 + 1] ALIGN1 = { | 12 | #if ENABLE_BASE32 |
13 | const char bb_uuenc_tbl_base32[] ALIGN1 = { | ||
14 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', | ||
15 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', | ||
16 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', | ||
17 | 'Y', 'Z', '2', '3', '4', '5', '6', '7', | ||
18 | /* unused: '=', */ | ||
19 | }; | ||
20 | #endif | ||
21 | /* for base 64 */ | ||
22 | const char bb_uuenc_tbl_base64[] ALIGN1 = { | ||
13 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', | 23 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', |
14 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', | 24 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', |
15 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', | 25 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', |
@@ -18,11 +28,9 @@ const char bb_uuenc_tbl_base64[65 + 1] ALIGN1 = { | |||
18 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', | 28 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', |
19 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', | 29 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', |
20 | '4', '5', '6', '7', '8', '9', '+', '/', | 30 | '4', '5', '6', '7', '8', '9', '+', '/', |
21 | '=' /* termination character */, | 31 | '=' /* termination character */ |
22 | '\0' /* needed for uudecode.c only */ | ||
23 | }; | 32 | }; |
24 | 33 | const char bb_uuenc_tbl_std[] ALIGN1 = { | |
25 | const char bb_uuenc_tbl_std[65] ALIGN1 = { | ||
26 | '`', '!', '"', '#', '$', '%', '&', '\'', | 34 | '`', '!', '"', '#', '$', '%', '&', '\'', |
27 | '(', ')', '*', '+', ',', '-', '.', '/', | 35 | '(', ')', '*', '+', ',', '-', '.', '/', |
28 | '0', '1', '2', '3', '4', '5', '6', '7', | 36 | '0', '1', '2', '3', '4', '5', '6', '7', |
@@ -30,7 +38,7 @@ const char bb_uuenc_tbl_std[65] ALIGN1 = { | |||
30 | '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', | 38 | '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', |
31 | 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', | 39 | 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', |
32 | 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', | 40 | 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', |
33 | 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', | 41 | 'X', 'Y', 'Z', '[', '\\',']', '^', '_', |
34 | '`' /* termination character */ | 42 | '`' /* termination character */ |
35 | }; | 43 | }; |
36 | 44 | ||
@@ -72,86 +80,124 @@ void FAST_FUNC bb_uuencode(char *p, const void *src, int length, const char *tbl | |||
72 | } | 80 | } |
73 | 81 | ||
74 | /* | 82 | /* |
75 | * Decode base64 encoded string. Stops on '\0'. | 83 | * Decode base64 encoded string. |
76 | * | 84 | * |
77 | * Returns: pointer to the undecoded part of source. | 85 | * Returns: pointer past the last written output byte, |
86 | * the result is not NUL-terminated. | ||
87 | * (*pp_src) is advanced past the last read byte. | ||
78 | * If points to '\0', then the source was fully decoded. | 88 | * If points to '\0', then the source was fully decoded. |
79 | * (*pp_dst): advanced past the last written byte. | ||
80 | */ | 89 | */ |
81 | const char* FAST_FUNC decode_base64(char **pp_dst, const char *src) | 90 | char* FAST_FUNC decode_base64(char *dst, const char **pp_src) |
82 | { | 91 | { |
83 | char *dst = *pp_dst; | 92 | const char *src = pp_src ? *pp_src : dst; /* for httpd.c, support NULL 2nd param */ |
84 | const char *src_tail; | 93 | unsigned ch = 0; |
94 | unsigned t; | ||
95 | int i = 0; | ||
85 | 96 | ||
86 | while (1) { | 97 | while ((t = (unsigned char)*src) != '\0') { |
87 | unsigned char six_bit[4]; | 98 | src++; |
88 | int count = 0; | ||
89 | |||
90 | /* Fetch up to four 6-bit values */ | ||
91 | src_tail = src; | ||
92 | while (count < 4) { | ||
93 | char *table_ptr; | ||
94 | int ch; | ||
95 | |||
96 | /* Get next _valid_ character. | ||
97 | * bb_uuenc_tbl_base64[] contains this string: | ||
98 | * 0 1 2 3 4 5 6 | ||
99 | * 01234567890123456789012345678901234567890123456789012345678901234 | ||
100 | * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" | ||
101 | */ | ||
102 | do { | ||
103 | ch = *src; | ||
104 | if (ch == '\0') { | ||
105 | if (count == 0) { | ||
106 | /* Example: | ||
107 | * If we decode "QUJD <NUL>", we want | ||
108 | * to return ptr to NUL, not to ' ', | ||
109 | * because we did fully decode | ||
110 | * the string (to "ABC"). | ||
111 | */ | ||
112 | src_tail = src; | ||
113 | } | ||
114 | goto ret; | ||
115 | } | ||
116 | src++; | ||
117 | table_ptr = strchr(bb_uuenc_tbl_base64, ch); | ||
118 | //TODO: add BASE64_FLAG_foo to die on bad char? | ||
119 | } while (!table_ptr); | ||
120 | 99 | ||
121 | /* Convert encoded character to decimal */ | 100 | /* "if" forest is faster than strchr(bb_uuenc_tbl_base64, t) */ |
122 | ch = table_ptr - bb_uuenc_tbl_base64; | 101 | if (t >= '0' && t <= '9') |
102 | t = t - '0' + 52; | ||
103 | else if (t >= 'A' && t <= 'Z') | ||
104 | t = t - 'A'; | ||
105 | else if (t >= 'a' && t <= 'z') | ||
106 | t = t - 'a' + 26; | ||
107 | else if (t == '+') | ||
108 | t = 62; | ||
109 | else if (t == '/') | ||
110 | t = 63; | ||
111 | else if (t == '=' && (i == 3 || (i == 2 && *src == '='))) | ||
112 | /* the above disallows "==AA", "A===", "AA=A" etc */ | ||
113 | t = 0x1000000; | ||
114 | else | ||
115 | //TODO: add BASE64_FLAG_foo to die on bad char? | ||
116 | continue; | ||
123 | 117 | ||
124 | /* ch is 64 if char was '=', otherwise 0..63 */ | 118 | ch = (ch << 6) | t; |
125 | if (ch == 64) | 119 | i = (i + 1) & 3; |
120 | if (i == 0) { | ||
121 | *dst++ = (char) (ch >> 16); | ||
122 | *dst++ = (char) (ch >> 8); | ||
123 | *dst++ = (char) ch; | ||
124 | if (ch & 0x1000000) { /* was last input char '='? */ | ||
125 | dst--; | ||
126 | if (ch & (0x1000000 << 6)) /* was it "=="? */ | ||
127 | dst--; | ||
126 | break; | 128 | break; |
127 | six_bit[count] = ch; | 129 | } |
128 | count++; | 130 | ch = 0; |
131 | } | ||
132 | } | ||
133 | /* i is zero here if full 4-char block was decoded */ | ||
134 | if (pp_src) | ||
135 | *pp_src = src - i; /* -i signals truncation: e.g. "MQ" and "MQ=" (correct encoding is "MQ==" -> "1") */ | ||
136 | return dst; | ||
137 | } | ||
138 | |||
139 | #if ENABLE_BASE32 | ||
140 | char* FAST_FUNC decode_base32(char *dst, const char **pp_src) | ||
141 | { | ||
142 | const char *src = *pp_src; | ||
143 | uint64_t ch = 0; | ||
144 | unsigned t; | ||
145 | int i = 0; | ||
146 | |||
147 | while ((t = (unsigned char)*src) != '\0') { | ||
148 | src++; | ||
149 | |||
150 | /* "if" forest is faster than strchr(bb_uuenc_tbl_base32, t) */ | ||
151 | if (t >= '2' && t <= '7') | ||
152 | t = t - '2' + 26; | ||
153 | else if (t == '=' && i > 1) | ||
154 | t = 0; | ||
155 | else { | ||
156 | t = (t | 0x20) - 'a'; | ||
157 | if (t > 25) | ||
158 | //TODO: add BASE64_FLAG_foo to die on bad char? | ||
159 | continue; | ||
129 | } | 160 | } |
130 | 161 | ||
131 | /* Transform 6-bit values to 8-bit ones. | 162 | ch = (ch << 5) | t; |
132 | * count can be < 4 when we decode the tail: | 163 | i = (i + 1) & 7; |
133 | * "eQ==" -> "y", not "y NUL NUL". | 164 | if (i == 0) { |
134 | * Note that (count > 1) is always true, | 165 | *dst++ = (char) (ch >> 32); |
135 | * "x===" encoding is not valid: | 166 | if (src[-1] == '=') /* was last input char '='? */ |
136 | * even a single zero byte encodes as "AA==". | 167 | goto tail; |
137 | * However, with current logic we come here with count == 1 | 168 | *dst++ = (char) (ch >> 24); |
138 | * when we decode "==" tail. | 169 | *dst++ = (char) (ch >> 16); |
139 | */ | 170 | *dst++ = (char) (ch >> 8); |
140 | if (count > 1) | 171 | *dst++ = (char) ch; |
141 | *dst++ = six_bit[0] << 2 | six_bit[1] >> 4; | 172 | } |
142 | if (count > 2) | 173 | } |
143 | *dst++ = six_bit[1] << 4 | six_bit[2] >> 2; | 174 | /* i is zero here if full 8-char block was decoded */ |
144 | if (count > 3) | 175 | *pp_src = src - i; |
145 | *dst++ = six_bit[2] << 6 | six_bit[3]; | 176 | return dst; |
146 | /* Note that if we decode "AA==" and ate first '=', | 177 | tail: |
147 | * we just decoded one char (count == 2) and now we'll | 178 | { |
148 | * do the loop once more to decode second '='. | 179 | const char *s = src; |
180 | while (*--s == '=') | ||
181 | i++; | ||
182 | /* Why duplicate the below code? Testcase: | ||
183 | * echo ' 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18' | base32 | base32 -d | ||
184 | * IOW, decoding of | ||
185 | * EAYSAMRAGMQDIIBVEA3CANZAHAQDSIBRGAQDCMJAGEZCAMJTEAYTIIBRGUQDCNRAGE3SAMJYBI== | ||
186 | * ==== | ||
187 | * must correctly stitch together the tail, must not overwrite | ||
188 | * the tail before it is analyzed! (we can be decoding in-place) | ||
189 | * Else testcase fails, prints trailing extra NUL bytes. | ||
149 | */ | 190 | */ |
150 | } /* while (1) */ | 191 | *dst++ = (char) (ch >> 24); |
151 | ret: | 192 | *dst++ = (char) (ch >> 16); |
152 | *pp_dst = dst; | 193 | *dst++ = (char) (ch >> 8); |
153 | return src_tail; | 194 | *dst++ = (char) ch; |
195 | dst -= (i+1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */ | ||
196 | } | ||
197 | *pp_src = src; | ||
198 | return dst; | ||
154 | } | 199 | } |
200 | #endif | ||
155 | 201 | ||
156 | /* | 202 | /* |
157 | * Decode base64 encoded stream. | 203 | * Decode base64 encoded stream. |
@@ -163,20 +209,22 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) | |||
163 | /* Note that EOF _can_ be passed as exit_char too */ | 209 | /* Note that EOF _can_ be passed as exit_char too */ |
164 | #define exit_char ((int)(signed char)flags) | 210 | #define exit_char ((int)(signed char)flags) |
165 | #define uu_style_end (flags & BASE64_FLAG_UU_STOP) | 211 | #define uu_style_end (flags & BASE64_FLAG_UU_STOP) |
212 | #define base32 (flags & BASE64_32) | ||
166 | 213 | ||
167 | /* uuencoded files have 61 byte lines. Use 64 byte buffer | 214 | /* uuencoded files have 61 byte lines. |
168 | * to process line at a time. | 215 | * base32/64 have 76 byte lines by default. |
216 | * Use 80 byte buffer to process one line at a time. | ||
169 | */ | 217 | */ |
170 | enum { BUFFER_SIZE = 64 }; | 218 | enum { BUFFER_SIZE = 80 }; |
171 | 219 | /* decoded data is shorter than input, can use single buffer for both */ | |
172 | char in_buf[BUFFER_SIZE + 2]; | 220 | char buf[BUFFER_SIZE + 2]; |
173 | char out_buf[BUFFER_SIZE / 4 * 3 + 2]; | ||
174 | char *out_tail; | ||
175 | const char *in_tail; | ||
176 | int term_seen = 0; | 221 | int term_seen = 0; |
177 | int in_count = 0; | 222 | int in_count = 0; |
178 | 223 | ||
179 | while (1) { | 224 | while (1) { |
225 | char *out_tail; | ||
226 | const char *in_tail; | ||
227 | |||
180 | while (in_count < BUFFER_SIZE) { | 228 | while (in_count < BUFFER_SIZE) { |
181 | int ch = fgetc(src_stream); | 229 | int ch = fgetc(src_stream); |
182 | if (ch == exit_char) { | 230 | if (ch == exit_char) { |
@@ -195,29 +243,34 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) | |||
195 | */ | 243 | */ |
196 | if (ch <= ' ') | 244 | if (ch <= ' ') |
197 | break; | 245 | break; |
198 | in_buf[in_count++] = ch; | 246 | buf[in_count++] = ch; |
199 | } | 247 | } |
200 | in_buf[in_count] = '\0'; | 248 | buf[in_count] = '\0'; |
201 | 249 | ||
202 | /* Did we encounter "====" line? */ | 250 | /* Did we encounter "====" line? */ |
203 | if (uu_style_end && strcmp(in_buf, "====") == 0) | 251 | if (uu_style_end && strcmp(buf, "====") == 0) |
204 | return; | 252 | return; |
205 | 253 | ||
206 | out_tail = out_buf; | 254 | in_tail = buf; |
207 | in_tail = decode_base64(&out_tail, in_buf); | 255 | #if ENABLE_BASE32 |
256 | if (base32) | ||
257 | out_tail = decode_base32(buf, &in_tail); | ||
258 | else | ||
259 | #endif | ||
260 | out_tail = decode_base64(buf, &in_tail); | ||
208 | 261 | ||
209 | fwrite(out_buf, (out_tail - out_buf), 1, dst_stream); | 262 | fwrite(buf, (out_tail - buf), 1, dst_stream); |
210 | 263 | ||
211 | if (term_seen) { | 264 | if (term_seen) { |
212 | /* Did we consume ALL characters? */ | 265 | /* Did we consume ALL characters? */ |
213 | if (*in_tail == '\0') | 266 | if (*in_tail == '\0') |
214 | return; | 267 | return; |
215 | /* No */ | 268 | /* No */ |
216 | bb_simple_error_msg_and_die("truncated base64 input"); | 269 | bb_simple_error_msg_and_die("truncated input"); |
217 | } | 270 | } |
218 | 271 | ||
219 | /* It was partial decode */ | 272 | /* It was partial decode */ |
220 | in_count = strlen(in_tail); | 273 | in_count = strlen(in_tail); |
221 | memmove(in_buf, in_tail, in_count); | 274 | memmove(buf, in_tail, in_count); |
222 | } | 275 | } |
223 | } | 276 | } |
diff --git a/libbb/xatonum.c b/libbb/xatonum.c index 7639a62aa..36b06c849 100644 --- a/libbb/xatonum.c +++ b/libbb/xatonum.c | |||
@@ -68,14 +68,14 @@ uint16_t FAST_FUNC xatou16(const char *numstr) | |||
68 | return xatou_range(numstr, 0, 0xffff); | 68 | return xatou_range(numstr, 0, 0xffff); |
69 | } | 69 | } |
70 | 70 | ||
71 | const struct suffix_mult bkm_suffixes[] = { | 71 | const struct suffix_mult bkm_suffixes[] ALIGN_SUFFIX = { |
72 | { "b", 512 }, | 72 | { "b", 512 }, |
73 | { "k", 1024 }, | 73 | { "k", 1024 }, |
74 | { "m", 1024*1024 }, | 74 | { "m", 1024*1024 }, |
75 | { "", 0 } | 75 | { "", 0 } |
76 | }; | 76 | }; |
77 | 77 | ||
78 | const struct suffix_mult cwbkMG_suffixes[] = { | 78 | const struct suffix_mult cwbkMG_suffixes[] ALIGN_SUFFIX = { |
79 | { "c", 1 }, | 79 | { "c", 1 }, |
80 | { "w", 2 }, | 80 | { "w", 2 }, |
81 | { "b", 512 }, | 81 | { "b", 512 }, |
@@ -96,7 +96,7 @@ const struct suffix_mult cwbkMG_suffixes[] = { | |||
96 | { "", 0 } | 96 | { "", 0 } |
97 | }; | 97 | }; |
98 | 98 | ||
99 | const struct suffix_mult kmg_i_suffixes[] = { | 99 | const struct suffix_mult kmg_i_suffixes[] ALIGN_SUFFIX = { |
100 | { "KiB", 1024 }, | 100 | { "KiB", 1024 }, |
101 | { "kiB", 1024 }, | 101 | { "kiB", 1024 }, |
102 | { "K", 1024 }, | 102 | { "K", 1024 }, |
diff --git a/libbb/xconnect.c b/libbb/xconnect.c index 38faef38e..f5c514b2c 100644 --- a/libbb/xconnect.c +++ b/libbb/xconnect.c | |||
@@ -428,17 +428,14 @@ int FAST_FUNC create_and_bind_to_netlink(int proto, int grp, unsigned rcvbuf) | |||
428 | struct sockaddr_nl sa; | 428 | struct sockaddr_nl sa; |
429 | int fd; | 429 | int fd; |
430 | 430 | ||
431 | memset(&sa, 0, sizeof(sa)); | ||
432 | sa.nl_family = AF_NETLINK; | ||
433 | sa.nl_pid = getpid(); | ||
434 | sa.nl_groups = grp; | ||
435 | fd = xsocket(AF_NETLINK, SOCK_DGRAM, proto); | 431 | fd = xsocket(AF_NETLINK, SOCK_DGRAM, proto); |
436 | xbind(fd, (struct sockaddr *) &sa, sizeof(sa)); | ||
437 | close_on_exec_on(fd); | ||
438 | 432 | ||
433 | /* Set receive buffer size before binding the socket | ||
434 | * We want to have enough space before we start receiving messages. | ||
435 | */ | ||
439 | if (rcvbuf != 0) { | 436 | if (rcvbuf != 0) { |
440 | // SO_RCVBUFFORCE (root only) can go above net.core.rmem_max sysctl | 437 | setsockopt_SOL_SOCKET_int(fd, SO_RCVBUF, rcvbuf); |
441 | setsockopt_SOL_SOCKET_int(fd, SO_RCVBUF, rcvbuf); | 438 | /* SO_RCVBUFFORCE (root only) can go above net.core.rmem_max */ |
442 | setsockopt_SOL_SOCKET_int(fd, SO_RCVBUFFORCE, rcvbuf); | 439 | setsockopt_SOL_SOCKET_int(fd, SO_RCVBUFFORCE, rcvbuf); |
443 | # if 0 | 440 | # if 0 |
444 | { | 441 | { |
@@ -450,6 +447,13 @@ int FAST_FUNC create_and_bind_to_netlink(int proto, int grp, unsigned rcvbuf) | |||
450 | # endif | 447 | # endif |
451 | } | 448 | } |
452 | 449 | ||
450 | memset(&sa, 0, sizeof(sa)); | ||
451 | sa.nl_family = AF_NETLINK; | ||
452 | sa.nl_pid = getpid(); | ||
453 | sa.nl_groups = grp; | ||
454 | xbind(fd, (struct sockaddr *) &sa, sizeof(sa)); | ||
455 | close_on_exec_on(fd); | ||
456 | |||
453 | return fd; | 457 | return fd; |
454 | } | 458 | } |
455 | #endif | 459 | #endif |
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index c92436683..ef990118e 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c | |||
@@ -421,15 +421,3 @@ int FAST_FUNC wait4pid(pid_t pid) | |||
421 | return WTERMSIG(status) + 0x180; | 421 | return WTERMSIG(status) + 0x180; |
422 | return 0; | 422 | return 0; |
423 | } | 423 | } |
424 | |||
425 | // Useful when we do know that pid is valid, and we just want to wait | ||
426 | // for it to exit. Not existing pid is fatal. waitpid() status is not returned. | ||
427 | int FAST_FUNC wait_for_exitstatus(pid_t pid) | ||
428 | { | ||
429 | int exit_status, n; | ||
430 | |||
431 | n = safe_waitpid(pid, &exit_status, 0); | ||
432 | if (n < 0) | ||
433 | bb_simple_perror_msg_and_die("waitpid"); | ||
434 | return exit_status; | ||
435 | } | ||
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index 6fdc0f6a4..4bd19d471 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c | |||
@@ -111,6 +111,29 @@ void* FAST_FUNC xmemdup(const void *s, int n) | |||
111 | return memcpy(xmalloc(n), s, n); | 111 | return memcpy(xmalloc(n), s, n); |
112 | } | 112 | } |
113 | 113 | ||
114 | #if !ENABLE_PLATFORM_MINGW32 | ||
115 | void* FAST_FUNC mmap_read(int fd, size_t size) | ||
116 | { | ||
117 | return mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); | ||
118 | } | ||
119 | |||
120 | void* FAST_FUNC mmap_anon(size_t size) | ||
121 | { | ||
122 | return mmap(NULL, size, | ||
123 | PROT_READ | PROT_WRITE, | ||
124 | MAP_PRIVATE | MAP_ANONYMOUS, | ||
125 | /* ignored: */ -1, 0); | ||
126 | } | ||
127 | |||
128 | void* FAST_FUNC xmmap_anon(size_t size) | ||
129 | { | ||
130 | void *p = mmap_anon(size); | ||
131 | if (p == MAP_FAILED) | ||
132 | bb_die_memory_exhausted(); | ||
133 | return p; | ||
134 | } | ||
135 | #endif | ||
136 | |||
114 | // Die if we can't open a file and return a FILE* to it. | 137 | // Die if we can't open a file and return a FILE* to it. |
115 | // Notice we haven't got xfread(), This is for use with fscanf() and friends. | 138 | // Notice we haven't got xfread(), This is for use with fscanf() and friends. |
116 | FILE* FAST_FUNC xfopen(const char *path, const char *mode) | 139 | FILE* FAST_FUNC xfopen(const char *path, const char *mode) |
@@ -502,22 +525,22 @@ void FAST_FUNC xfstat(int fd, struct stat *stat_buf, const char *errmsg) | |||
502 | bb_simple_perror_msg_and_die(errmsg); | 525 | bb_simple_perror_msg_and_die(errmsg); |
503 | } | 526 | } |
504 | 527 | ||
505 | #if !ENABLE_PLATFORM_MINGW32 | 528 | #if ENABLE_SELINUX |
506 | // selinux_or_die() - die if SELinux is disabled. | 529 | // selinux_or_die() - die if SELinux is disabled. |
507 | void FAST_FUNC selinux_or_die(void) | 530 | void FAST_FUNC selinux_or_die(void) |
508 | { | 531 | { |
509 | #if ENABLE_SELINUX | ||
510 | int rc = is_selinux_enabled(); | 532 | int rc = is_selinux_enabled(); |
511 | if (rc == 0) { | 533 | if (rc == 0) { |
512 | bb_simple_error_msg_and_die("SELinux is disabled"); | 534 | bb_simple_error_msg_and_die("SELinux is disabled"); |
513 | } else if (rc < 0) { | 535 | } else if (rc < 0) { |
514 | bb_simple_error_msg_and_die("is_selinux_enabled() failed"); | 536 | bb_simple_error_msg_and_die("is_selinux_enabled() failed"); |
515 | } | 537 | } |
538 | } | ||
516 | #else | 539 | #else |
517 | bb_simple_error_msg_and_die("SELinux support is disabled"); | 540 | /* not defined, other code must have no calls to it */ |
518 | #endif | 541 | #endif |
519 | } | ||
520 | 542 | ||
543 | #if !ENABLE_PLATFORM_MINGW32 | ||
521 | int FAST_FUNC ioctl_or_perror_and_die(int fd, unsigned request, void *argp, const char *fmt,...) | 544 | int FAST_FUNC ioctl_or_perror_and_die(int fd, unsigned request, void *argp, const char *fmt,...) |
522 | { | 545 | { |
523 | int ret; | 546 | int ret; |
@@ -634,14 +657,11 @@ void FAST_FUNC generate_uuid(uint8_t *buf) | |||
634 | pid_t pid; | 657 | pid_t pid; |
635 | int i; | 658 | int i; |
636 | 659 | ||
637 | i = open("/dev/urandom", O_RDONLY); | 660 | open_read_close("/dev/urandom", buf, 16); |
638 | if (i >= 0) { | ||
639 | read(i, buf, 16); | ||
640 | close(i); | ||
641 | } | ||
642 | /* Paranoia. /dev/urandom may be missing. | 661 | /* Paranoia. /dev/urandom may be missing. |
643 | * rand() is guaranteed to generate at least [0, 2^15) range, | 662 | * rand() is guaranteed to generate at least [0, 2^15) range, |
644 | * but lowest bits in some libc are not so "random". */ | 663 | * but lowest bits in some libc are not so "random". |
664 | */ | ||
645 | srand(monotonic_us()); /* pulls in printf */ | 665 | srand(monotonic_us()); /* pulls in printf */ |
646 | pid = getpid(); | 666 | pid = getpid(); |
647 | while (1) { | 667 | while (1) { |
@@ -686,3 +706,34 @@ void FAST_FUNC xvfork_parent_waits_and_exits(void) | |||
686 | /* Child continues */ | 706 | /* Child continues */ |
687 | } | 707 | } |
688 | #endif /* !ENABLE_PLATFORM_MINGW32 */ | 708 | #endif /* !ENABLE_PLATFORM_MINGW32 */ |
709 | |||
710 | // Useful when we do know that pid is valid, and we just want to wait | ||
711 | // for it to exit. Not existing pid is fatal. waitpid() status is not returned. | ||
712 | int FAST_FUNC wait_for_exitstatus(pid_t pid) | ||
713 | { | ||
714 | int exit_status, n; | ||
715 | |||
716 | n = safe_waitpid(pid, &exit_status, 0); | ||
717 | if (n < 0) | ||
718 | bb_simple_perror_msg_and_die("waitpid"); | ||
719 | return exit_status; | ||
720 | } | ||
721 | |||
722 | #if !ENABLE_PLATFORM_MINGW32 | ||
723 | void FAST_FUNC xsettimeofday(const struct timeval *tv) | ||
724 | { | ||
725 | if (settimeofday(tv, NULL)) | ||
726 | bb_simple_perror_msg_and_die("settimeofday"); | ||
727 | } | ||
728 | #endif | ||
729 | |||
730 | void FAST_FUNC xgettimeofday(struct timeval *tv) | ||
731 | { | ||
732 | #if 0 | ||
733 | if (gettimeofday(tv, NULL)) | ||
734 | bb_simple_perror_msg_and_die("gettimeofday"); | ||
735 | #else | ||
736 | /* Never fails on Linux */ | ||
737 | gettimeofday(tv, NULL); | ||
738 | #endif | ||
739 | } | ||
diff --git a/loginutils/chpasswd.c b/loginutils/chpasswd.c index 4e70b2557..a032abbed 100644 --- a/loginutils/chpasswd.c +++ b/loginutils/chpasswd.c | |||
@@ -24,21 +24,13 @@ | |||
24 | //kbuild:lib-$(CONFIG_CHPASSWD) += chpasswd.o | 24 | //kbuild:lib-$(CONFIG_CHPASSWD) += chpasswd.o |
25 | 25 | ||
26 | //usage:#define chpasswd_trivial_usage | 26 | //usage:#define chpasswd_trivial_usage |
27 | //usage: IF_LONG_OPTS("[--md5|--encrypted|--crypt-method|--root]") IF_NOT_LONG_OPTS("[-m|-e|-c|-R]") | 27 | //usage: "[-me] [-c ALG] [-R DIR]" |
28 | //usage:#define chpasswd_full_usage "\n\n" | 28 | //usage:#define chpasswd_full_usage "\n\n" |
29 | //usage: "Read user:password from stdin and update /etc/passwd\n" | 29 | //usage: "Read user:password from stdin and update /etc/passwd\n" |
30 | //usage: IF_LONG_OPTS( | ||
31 | //usage: "\n -e,--encrypted Supplied passwords are in encrypted form" | ||
32 | //usage: "\n -m,--md5 Encrypt using md5, not des" | ||
33 | //usage: "\n -c,--crypt-method ALG "CRYPT_METHODS_HELP_STR | ||
34 | //usage: "\n -R,--root DIR Directory to chroot into" | ||
35 | //usage: ) | ||
36 | //usage: IF_NOT_LONG_OPTS( | ||
37 | //usage: "\n -e Supplied passwords are in encrypted form" | 30 | //usage: "\n -e Supplied passwords are in encrypted form" |
38 | //usage: "\n -m Encrypt using md5, not des" | 31 | //usage: "\n -m Encrypt using md5, not des" |
39 | //usage: "\n -c ALG "CRYPT_METHODS_HELP_STR | 32 | //usage: "\n -c ALG "CRYPT_METHODS_HELP_STR |
40 | //usage: "\n -R DIR Directory to chroot into" | 33 | //usage: "\n -R DIR Directory to chroot into" |
41 | //usage: ) | ||
42 | 34 | ||
43 | #include "libbb.h" | 35 | #include "libbb.h" |
44 | 36 | ||
diff --git a/loginutils/cryptpw.c b/loginutils/cryptpw.c index fbb7f0515..645f1bb09 100644 --- a/loginutils/cryptpw.c +++ b/loginutils/cryptpw.c | |||
@@ -32,22 +32,14 @@ | |||
32 | //kbuild:lib-$(CONFIG_MKPASSWD) += cryptpw.o | 32 | //kbuild:lib-$(CONFIG_MKPASSWD) += cryptpw.o |
33 | 33 | ||
34 | //usage:#define cryptpw_trivial_usage | 34 | //usage:#define cryptpw_trivial_usage |
35 | //usage: "[OPTIONS] [PASSWORD] [SALT]" | 35 | //usage: "[-s] [-p N] [-m TYPE] [-S SALT] [PASSWORD] [SALT]" |
36 | /* We do support -s, we just don't mention it */ | 36 | /* We do support -s, we just don't mention it */ |
37 | //usage:#define cryptpw_full_usage "\n\n" | 37 | //usage:#define cryptpw_full_usage "\n\n" |
38 | //usage: "Print crypt(3) hashed PASSWORD\n" | 38 | //usage: "Print crypt(3) hashed PASSWORD\n" |
39 | //usage: IF_LONG_OPTS( | ||
40 | //usage: "\n -P,--password-fd N Read password from fd N" | ||
41 | /* //usage: "\n -s,--stdin Use stdin; like -P0" */ | ||
42 | //usage: "\n -m,--method TYPE "CRYPT_METHODS_HELP_STR | ||
43 | //usage: "\n -S,--salt SALT" | ||
44 | //usage: ) | ||
45 | //usage: IF_NOT_LONG_OPTS( | ||
46 | //usage: "\n -P N Read password from fd N" | 39 | //usage: "\n -P N Read password from fd N" |
47 | /* //usage: "\n -s Use stdin; like -P0" */ | 40 | /* //usage: "\n -s Use stdin; like -P0" */ |
48 | //usage: "\n -m TYPE "CRYPT_METHODS_HELP_STR | 41 | //usage: "\n -m TYPE "CRYPT_METHODS_HELP_STR |
49 | //usage: "\n -S SALT" | 42 | //usage: "\n -S SALT" |
50 | //usage: ) | ||
51 | 43 | ||
52 | #include "libbb.h" | 44 | #include "libbb.h" |
53 | 45 | ||
diff --git a/loginutils/getty.c b/loginutils/getty.c index 7393a3d1c..6c6d409f4 100644 --- a/loginutils/getty.c +++ b/loginutils/getty.c | |||
@@ -404,7 +404,7 @@ static void finalize_tty_attrs(void) | |||
404 | set_tty_attrs(); | 404 | set_tty_attrs(); |
405 | 405 | ||
406 | /* Now the newline character should be properly written */ | 406 | /* Now the newline character should be properly written */ |
407 | full_write(STDOUT_FILENO, "\n", 1); | 407 | full_write1_str("\n"); |
408 | } | 408 | } |
409 | 409 | ||
410 | /* extract baud rate from modem status message */ | 410 | /* extract baud rate from modem status message */ |
@@ -434,7 +434,7 @@ static void auto_baud(void) | |||
434 | * Wait for a while, then read everything the modem has said so far and | 434 | * Wait for a while, then read everything the modem has said so far and |
435 | * try to extract the speed of the dial-in call. | 435 | * try to extract the speed of the dial-in call. |
436 | */ | 436 | */ |
437 | sleep(1); | 437 | sleep1(); |
438 | nread = safe_read(STDIN_FILENO, G.line_buf, sizeof(G.line_buf) - 1); | 438 | nread = safe_read(STDIN_FILENO, G.line_buf, sizeof(G.line_buf) - 1); |
439 | if (nread > 0) { | 439 | if (nread > 0) { |
440 | int speed; | 440 | int speed; |
@@ -498,13 +498,13 @@ static char *get_logname(void) | |||
498 | case 0x7f: | 498 | case 0x7f: |
499 | G.tty_attrs.c_cc[VERASE] = c; | 499 | G.tty_attrs.c_cc[VERASE] = c; |
500 | if (bp > G.line_buf) { | 500 | if (bp > G.line_buf) { |
501 | full_write(STDOUT_FILENO, "\010 \010", 3); | 501 | full_write1_str("\010 \010"); |
502 | bp--; | 502 | bp--; |
503 | } | 503 | } |
504 | break; | 504 | break; |
505 | case CTL('U'): | 505 | case CTL('U'): |
506 | while (bp > G.line_buf) { | 506 | while (bp > G.line_buf) { |
507 | full_write(STDOUT_FILENO, "\010 \010", 3); | 507 | full_write1_str("\010 \010"); |
508 | bp--; | 508 | bp--; |
509 | } | 509 | } |
510 | break; | 510 | break; |
diff --git a/loginutils/login.c b/loginutils/login.c index 4e65b3a19..21c32fc25 100644 --- a/loginutils/login.c +++ b/loginutils/login.c | |||
@@ -341,6 +341,7 @@ int login_main(int argc UNUSED_PARAM, char **argv) | |||
341 | #if ENABLE_LOGIN_SESSION_AS_CHILD | 341 | #if ENABLE_LOGIN_SESSION_AS_CHILD |
342 | pid_t child_pid; | 342 | pid_t child_pid; |
343 | #endif | 343 | #endif |
344 | IF_FEATURE_UTMP(pid_t my_pid;) | ||
344 | 345 | ||
345 | INIT_G(); | 346 | INIT_G(); |
346 | 347 | ||
@@ -504,16 +505,14 @@ int login_main(int argc UNUSED_PARAM, char **argv) | |||
504 | #endif /* ENABLE_PAM */ | 505 | #endif /* ENABLE_PAM */ |
505 | auth_failed: | 506 | auth_failed: |
506 | opt &= ~LOGIN_OPT_f; | 507 | opt &= ~LOGIN_OPT_f; |
507 | bb_do_delay(LOGIN_FAIL_DELAY); | 508 | pause_after_failed_login(); |
508 | /* TODO: doesn't sound like correct English phrase to me */ | 509 | /* TODO: doesn't sound like correct English phrase to me */ |
509 | puts("Login incorrect"); | 510 | puts("Login incorrect"); |
511 | syslog(LOG_WARNING, "invalid password for '%s'%s", | ||
512 | username, fromhost); | ||
510 | if (++count == 3) { | 513 | if (++count == 3) { |
511 | syslog(LOG_WARNING, "invalid password for '%s'%s", | ||
512 | username, fromhost); | ||
513 | |||
514 | if (ENABLE_FEATURE_CLEAN_UP) | 514 | if (ENABLE_FEATURE_CLEAN_UP) |
515 | free(fromhost); | 515 | free(fromhost); |
516 | |||
517 | return EXIT_FAILURE; | 516 | return EXIT_FAILURE; |
518 | } | 517 | } |
519 | username[0] = '\0'; | 518 | username[0] = '\0'; |
@@ -525,6 +524,9 @@ int login_main(int argc UNUSED_PARAM, char **argv) | |||
525 | if (pw->pw_uid != 0) | 524 | if (pw->pw_uid != 0) |
526 | die_if_nologin(); | 525 | die_if_nologin(); |
527 | 526 | ||
527 | IF_FEATURE_UTMP(my_pid = getpid();) | ||
528 | update_utmp(my_pid, USER_PROCESS, short_tty, username, run_by_root ? opt_host : NULL); | ||
529 | |||
528 | #if ENABLE_LOGIN_SESSION_AS_CHILD | 530 | #if ENABLE_LOGIN_SESSION_AS_CHILD |
529 | child_pid = vfork(); | 531 | child_pid = vfork(); |
530 | if (child_pid != 0) { | 532 | if (child_pid != 0) { |
@@ -532,8 +534,8 @@ int login_main(int argc UNUSED_PARAM, char **argv) | |||
532 | bb_simple_perror_msg("vfork"); | 534 | bb_simple_perror_msg("vfork"); |
533 | else { | 535 | else { |
534 | wait_for_exitstatus(child_pid); | 536 | wait_for_exitstatus(child_pid); |
535 | update_utmp_DEAD_PROCESS(child_pid); | ||
536 | } | 537 | } |
538 | update_utmp_DEAD_PROCESS(my_pid); | ||
537 | login_pam_end(pamh); | 539 | login_pam_end(pamh); |
538 | return 0; | 540 | return 0; |
539 | } | 541 | } |
@@ -546,8 +548,6 @@ int login_main(int argc UNUSED_PARAM, char **argv) | |||
546 | fchown(0, pw->pw_uid, pw->pw_gid); | 548 | fchown(0, pw->pw_uid, pw->pw_gid); |
547 | fchmod(0, 0600); | 549 | fchmod(0, 0600); |
548 | 550 | ||
549 | update_utmp(getpid(), USER_PROCESS, short_tty, username, run_by_root ? opt_host : NULL); | ||
550 | |||
551 | /* We trust environment only if we run by root */ | 551 | /* We trust environment only if we run by root */ |
552 | if (ENABLE_LOGIN_SCRIPTS && run_by_root) | 552 | if (ENABLE_LOGIN_SCRIPTS && run_by_root) |
553 | run_login_script(pw, full_tty); | 553 | run_login_script(pw, full_tty); |
@@ -602,7 +602,7 @@ int login_main(int argc UNUSED_PARAM, char **argv) | |||
602 | signal(SIGINT, SIG_DFL); | 602 | signal(SIGINT, SIG_DFL); |
603 | 603 | ||
604 | /* Exec login shell with no additional parameters */ | 604 | /* Exec login shell with no additional parameters */ |
605 | run_shell(pw->pw_shell, 1, NULL); | 605 | exec_login_shell(pw->pw_shell); |
606 | 606 | ||
607 | /* return EXIT_FAILURE; - not reached */ | 607 | /* return EXIT_FAILURE; - not reached */ |
608 | } | 608 | } |
diff --git a/loginutils/passwd.c b/loginutils/passwd.c index 6c643d3d0..acc942275 100644 --- a/loginutils/passwd.c +++ b/loginutils/passwd.c | |||
@@ -28,7 +28,7 @@ | |||
28 | //kbuild:lib-$(CONFIG_PASSWD) += passwd.o | 28 | //kbuild:lib-$(CONFIG_PASSWD) += passwd.o |
29 | 29 | ||
30 | //usage:#define passwd_trivial_usage | 30 | //usage:#define passwd_trivial_usage |
31 | //usage: "[OPTIONS] [USER]" | 31 | //usage: "[-a ALG] [-dlu] [USER]" |
32 | //usage:#define passwd_full_usage "\n\n" | 32 | //usage:#define passwd_full_usage "\n\n" |
33 | //usage: "Change USER's password (default: current user)" | 33 | //usage: "Change USER's password (default: current user)" |
34 | //usage: "\n" | 34 | //usage: "\n" |
@@ -57,7 +57,7 @@ static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo | |||
57 | encrypted = pw_encrypt(orig, pw->pw_passwd, 1); /* returns malloced str */ | 57 | encrypted = pw_encrypt(orig, pw->pw_passwd, 1); /* returns malloced str */ |
58 | if (strcmp(encrypted, pw->pw_passwd) != 0) { | 58 | if (strcmp(encrypted, pw->pw_passwd) != 0) { |
59 | syslog(LOG_WARNING, "incorrect password for %s", pw->pw_name); | 59 | syslog(LOG_WARNING, "incorrect password for %s", pw->pw_name); |
60 | bb_do_delay(LOGIN_FAIL_DELAY); | 60 | pause_after_failed_login(); |
61 | puts("Incorrect password"); | 61 | puts("Incorrect password"); |
62 | goto err_ret; | 62 | goto err_ret; |
63 | } | 63 | } |
diff --git a/loginutils/su.c b/loginutils/su.c index 79edbc44a..e46bbf78b 100644 --- a/loginutils/su.c +++ b/loginutils/su.c | |||
@@ -147,7 +147,7 @@ int su_main(int argc UNUSED_PARAM, char **argv) | |||
147 | if (ENABLE_FEATURE_SU_SYSLOG) | 147 | if (ENABLE_FEATURE_SU_SYSLOG) |
148 | syslog(LOG_NOTICE, "%c %s %s:%s", | 148 | syslog(LOG_NOTICE, "%c %s %s:%s", |
149 | '-', tty, old_user, opt_username); | 149 | '-', tty, old_user, opt_username); |
150 | bb_do_delay(LOGIN_FAIL_DELAY); | 150 | pause_after_failed_login(); |
151 | bb_simple_error_msg_and_die("incorrect password"); | 151 | bb_simple_error_msg_and_die("incorrect password"); |
152 | } | 152 | } |
153 | 153 | ||
@@ -205,7 +205,7 @@ int su_main(int argc UNUSED_PARAM, char **argv) | |||
205 | */ | 205 | */ |
206 | 206 | ||
207 | /* Never returns */ | 207 | /* Never returns */ |
208 | run_shell(opt_shell, flags & SU_OPT_l, (const char**)argv); | 208 | exec_shell(opt_shell, flags & SU_OPT_l, (const char**)argv); |
209 | 209 | ||
210 | /* return EXIT_FAILURE; - not reached */ | 210 | /* return EXIT_FAILURE; - not reached */ |
211 | } | 211 | } |
diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c index 099085340..69d8b5ec7 100644 --- a/loginutils/sulogin.c +++ b/loginutils/sulogin.c | |||
@@ -74,7 +74,7 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv) | |||
74 | if (r > 0) { | 74 | if (r > 0) { |
75 | break; | 75 | break; |
76 | } | 76 | } |
77 | bb_do_delay(LOGIN_FAIL_DELAY); | 77 | pause_after_failed_login(); |
78 | bb_simple_info_msg("Login incorrect"); | 78 | bb_simple_info_msg("Login incorrect"); |
79 | } | 79 | } |
80 | 80 | ||
@@ -89,5 +89,5 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv) | |||
89 | shell = pwd->pw_shell; | 89 | shell = pwd->pw_shell; |
90 | 90 | ||
91 | /* Exec login shell with no additional parameters. Never returns. */ | 91 | /* Exec login shell with no additional parameters. Never returns. */ |
92 | run_shell(shell, 1, NULL); | 92 | exec_login_shell(shell); |
93 | } | 93 | } |
diff --git a/loginutils/vlock.c b/loginutils/vlock.c index 9e319fe61..334b7d2ad 100644 --- a/loginutils/vlock.c +++ b/loginutils/vlock.c | |||
@@ -120,7 +120,7 @@ int vlock_main(int argc UNUSED_PARAM, char **argv) | |||
120 | if (ask_and_check_password(pw) > 0) { | 120 | if (ask_and_check_password(pw) > 0) { |
121 | break; | 121 | break; |
122 | } | 122 | } |
123 | bb_do_delay(LOGIN_FAIL_DELAY); | 123 | pause_after_failed_login(); |
124 | puts("Incorrect password"); | 124 | puts("Incorrect password"); |
125 | } | 125 | } |
126 | 126 | ||
diff --git a/mailutils/mail.c b/mailutils/mail.c index 3a1fd6949..f48b41bab 100644 --- a/mailutils/mail.c +++ b/mailutils/mail.c | |||
@@ -6,39 +6,45 @@ | |||
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 | #include <sys/prctl.h> | 9 | #if defined(__linux__) |
10 | # include <sys/prctl.h> | ||
11 | # define PRCTL | ||
12 | #elif defined(__FreeBSD__) | ||
13 | # include <sys/procctl.h> | ||
14 | # define PROCCTL | ||
15 | #endif | ||
10 | #include "libbb.h" | 16 | #include "libbb.h" |
11 | #include "mail.h" | 17 | #include "mail.h" |
12 | 18 | ||
13 | // generic signal handler | 19 | // common signal handler |
14 | static void signal_handler(int signo) | 20 | static void signal_handler(int signo) |
15 | { | 21 | { |
16 | #define err signo | ||
17 | if (SIGALRM == signo) { | 22 | if (SIGALRM == signo) { |
18 | bb_simple_error_msg_and_die("timed out"); | 23 | bb_simple_error_msg_and_die("timed out"); |
19 | } | 24 | } |
20 | 25 | ||
21 | // SIGCHLD. reap zombies | 26 | // SIGCHLD. reap the zombie if we expect one |
22 | if (safe_waitpid(G.helper_pid, &err, WNOHANG) > 0) { | 27 | if (G.helper_pid == 0) |
23 | if (WIFSIGNALED(err)) | 28 | return; |
24 | bb_error_msg_and_die("helper killed by signal %u", WTERMSIG(err)); | 29 | #define status signo |
25 | if (WIFEXITED(err)) { | 30 | if (safe_waitpid(G.helper_pid, &status, WNOHANG) > 0) { |
26 | G.helper_pid = 0; | 31 | G.helper_pid = 0; |
27 | if (WEXITSTATUS(err)) | 32 | if (WIFSIGNALED(status)) |
28 | bb_error_msg_and_die("helper exited (%u)", WEXITSTATUS(err)); | 33 | bb_error_msg_and_die("helper killed by signal %u", WTERMSIG(status)); |
29 | } | 34 | if (WIFEXITED(status) && WEXITSTATUS(status) != 0) |
35 | bb_error_msg_and_die("helper exited (%u)", WEXITSTATUS(status)); | ||
30 | } | 36 | } |
31 | #undef err | 37 | #undef status |
32 | } | 38 | } |
33 | 39 | ||
34 | void FAST_FUNC launch_helper(const char **argv) | 40 | void FAST_FUNC launch_helper(const char **argv) |
35 | { | 41 | { |
36 | // setup vanilla unidirectional pipes interchange | 42 | pid_t pid; |
37 | int i; | 43 | struct fd_pair child_out; |
38 | int pipes[4]; | 44 | struct fd_pair child_in; |
39 | 45 | ||
40 | xpipe(pipes); | 46 | xpiped_pair(child_out); |
41 | xpipe(pipes + 2); | 47 | xpiped_pair(child_in); |
42 | 48 | ||
43 | // NB: handler must be installed before vfork | 49 | // NB: handler must be installed before vfork |
44 | bb_signals(0 | 50 | bb_signals(0 |
@@ -46,40 +52,52 @@ void FAST_FUNC launch_helper(const char **argv) | |||
46 | + (1 << SIGALRM) | 52 | + (1 << SIGALRM) |
47 | , signal_handler); | 53 | , signal_handler); |
48 | 54 | ||
49 | G.helper_pid = xvfork(); | 55 | fflush_all(); |
50 | 56 | pid = xvfork(); | |
51 | i = (!G.helper_pid) * 2; // for parent:0, for child:2 | 57 | if (pid == 0) { |
52 | close(pipes[i + 1]); // 1 or 3 - closing one write end | ||
53 | close(pipes[2 - i]); // 2 or 0 - closing one read end | ||
54 | xmove_fd(pipes[i], STDIN_FILENO); // 0 or 2 - using other read end | ||
55 | xmove_fd(pipes[3 - i], STDOUT_FILENO); // 3 or 1 - using other write end | ||
56 | // End result: | ||
57 | // parent stdout [3] -> child stdin [2] | ||
58 | // child stdout [1] -> parent stdin [0] | ||
59 | |||
60 | if (!G.helper_pid) { | ||
61 | // child | 58 | // child |
59 | close(child_in.wr); | ||
60 | close(child_out.rd); | ||
61 | xmove_fd(child_in.rd, STDIN_FILENO); | ||
62 | xmove_fd(child_out.wr, STDOUT_FILENO); | ||
62 | // if parent dies, get SIGTERM | 63 | // if parent dies, get SIGTERM |
64 | #if defined(PRCTL) | ||
63 | prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0); | 65 | prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0); |
66 | #elif defined(PROCCTL) | ||
67 | { | ||
68 | int signum = SIGTERM; | ||
69 | procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum); | ||
70 | } | ||
71 | #endif | ||
64 | // try to execute connection helper | 72 | // try to execute connection helper |
65 | // NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec | 73 | // NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec |
66 | BB_EXECVP_or_die((char**)argv); | 74 | BB_EXECVP_or_die((char**)argv); |
67 | } | 75 | } |
76 | G.helper_pid = pid; | ||
77 | close(child_out.wr); | ||
78 | close(child_in.rd); | ||
79 | xmove_fd(child_out.rd, STDIN_FILENO); | ||
80 | xmove_fd(child_in.wr, STDOUT_FILENO); | ||
68 | 81 | ||
69 | // parent goes on | 82 | // parent goes on |
70 | } | 83 | } |
71 | 84 | ||
85 | void FAST_FUNC send_r_n(const char *s) | ||
86 | { | ||
87 | if (G.verbose) | ||
88 | bb_error_msg("send:'%s'", s); | ||
89 | printf("%s\r\n", s); | ||
90 | } | ||
91 | |||
72 | char* FAST_FUNC send_mail_command(const char *fmt, const char *param) | 92 | char* FAST_FUNC send_mail_command(const char *fmt, const char *param) |
73 | { | 93 | { |
74 | char *msg; | 94 | char *msg; |
75 | if (timeout) | 95 | if (G.timeout) |
76 | alarm(timeout); | 96 | alarm(G.timeout); |
77 | msg = (char*)fmt; | 97 | msg = (char*)fmt; |
78 | if (fmt) { | 98 | if (fmt) { |
79 | msg = xasprintf(fmt, param); | 99 | msg = xasprintf(fmt, param); |
80 | if (verbose) | 100 | send_r_n(msg); |
81 | bb_error_msg("send:'%s'", msg); | ||
82 | printf("%s\r\n", msg); | ||
83 | } | 101 | } |
84 | fflush_all(); | 102 | fflush_all(); |
85 | return msg; | 103 | return msg; |
diff --git a/mailutils/mail.h b/mailutils/mail.h index b14228a4a..a07d535cf 100644 --- a/mailutils/mail.h +++ b/mailutils/mail.h | |||
@@ -11,7 +11,6 @@ struct globals { | |||
11 | pid_t helper_pid; | 11 | pid_t helper_pid; |
12 | unsigned timeout; | 12 | unsigned timeout; |
13 | unsigned verbose; | 13 | unsigned verbose; |
14 | unsigned opts; | ||
15 | char *user; | 14 | char *user; |
16 | char *pass; | 15 | char *pass; |
17 | FILE *fp0; // initial stdin | 16 | FILE *fp0; // initial stdin |
@@ -19,9 +18,6 @@ struct globals { | |||
19 | }; | 18 | }; |
20 | 19 | ||
21 | #define G (*ptr_to_globals) | 20 | #define G (*ptr_to_globals) |
22 | #define timeout (G.timeout ) | ||
23 | #define verbose (G.verbose ) | ||
24 | #define opts (G.opts ) | ||
25 | #define INIT_G() do { \ | 21 | #define INIT_G() do { \ |
26 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | 22 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
27 | G.opt_charset = (char *)CONFIG_FEATURE_MIME_CHARSET; \ | 23 | G.opt_charset = (char *)CONFIG_FEATURE_MIME_CHARSET; \ |
@@ -32,6 +28,7 @@ struct globals { | |||
32 | void launch_helper(const char **argv) FAST_FUNC; | 28 | void launch_helper(const char **argv) FAST_FUNC; |
33 | void get_cred_or_die(int fd) FAST_FUNC; | 29 | void get_cred_or_die(int fd) FAST_FUNC; |
34 | 30 | ||
31 | void send_r_n(const char *s) FAST_FUNC; | ||
35 | char *send_mail_command(const char *fmt, const char *param) FAST_FUNC; | 32 | char *send_mail_command(const char *fmt, const char *param) FAST_FUNC; |
36 | 33 | ||
37 | void printbuf_base64(const char *buf, unsigned len) FAST_FUNC; | 34 | void printbuf_base64(const char *buf, unsigned len) FAST_FUNC; |
diff --git a/mailutils/makemime.c b/mailutils/makemime.c index 53a1820f1..1ff2012d5 100644 --- a/mailutils/makemime.c +++ b/mailutils/makemime.c | |||
@@ -173,6 +173,7 @@ Content-Transfer-Encoding: 7bit | |||
173 | int makemime_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 173 | int makemime_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
174 | int makemime_main(int argc UNUSED_PARAM, char **argv) | 174 | int makemime_main(int argc UNUSED_PARAM, char **argv) |
175 | { | 175 | { |
176 | unsigned opts; | ||
176 | llist_t *opt_headers = NULL, *l; | 177 | llist_t *opt_headers = NULL, *l; |
177 | const char *opt_output; | 178 | const char *opt_output; |
178 | const char *content_type = "application/octet-stream"; | 179 | const char *content_type = "application/octet-stream"; |
diff --git a/mailutils/popmaildir.c b/mailutils/popmaildir.c index c5522f1b7..1f2db2892 100644 --- a/mailutils/popmaildir.c +++ b/mailutils/popmaildir.c | |||
@@ -68,10 +68,11 @@ | |||
68 | static void pop3_checkr(const char *fmt, const char *param, char **ret) | 68 | static void pop3_checkr(const char *fmt, const char *param, char **ret) |
69 | { | 69 | { |
70 | char *msg = send_mail_command(fmt, param); | 70 | char *msg = send_mail_command(fmt, param); |
71 | //FIXME: limit max len!!! | ||
71 | char *answer = xmalloc_fgetline(stdin); | 72 | char *answer = xmalloc_fgetline(stdin); |
72 | if (answer && '+' == answer[0]) { | 73 | if (answer && '+' == answer[0]) { |
73 | free(msg); | 74 | free(msg); |
74 | if (timeout) | 75 | if (G.timeout) |
75 | alarm(0); | 76 | alarm(0); |
76 | if (ret) { | 77 | if (ret) { |
77 | // skip "+OK " | 78 | // skip "+OK " |
@@ -92,6 +93,7 @@ static void pop3_check(const char *fmt, const char *param) | |||
92 | int popmaildir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 93 | int popmaildir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
93 | int popmaildir_main(int argc UNUSED_PARAM, char **argv) | 94 | int popmaildir_main(int argc UNUSED_PARAM, char **argv) |
94 | { | 95 | { |
96 | unsigned opts; | ||
95 | char *buf; | 97 | char *buf; |
96 | unsigned nmsg; | 98 | unsigned nmsg; |
97 | char *hostname; | 99 | char *hostname; |
@@ -128,7 +130,7 @@ int popmaildir_main(int argc UNUSED_PARAM, char **argv) | |||
128 | opts = getopt32(argv, "^" | 130 | opts = getopt32(argv, "^" |
129 | "bdmVcasTkt:+" "R:+Z:L:+H:+" IF_FEATURE_POPMAILDIR_DELIVERY("M:F:") | 131 | "bdmVcasTkt:+" "R:+Z:L:+H:+" IF_FEATURE_POPMAILDIR_DELIVERY("M:F:") |
130 | "\0" "-1:dd", | 132 | "\0" "-1:dd", |
131 | &timeout, NULL, NULL, NULL, &opt_nlines | 133 | &G.timeout, NULL, NULL, NULL, &opt_nlines |
132 | IF_FEATURE_POPMAILDIR_DELIVERY(, &delivery, &delivery) // we treat -M and -F the same | 134 | IF_FEATURE_POPMAILDIR_DELIVERY(, &delivery, &delivery) // we treat -M and -F the same |
133 | ); | 135 | ); |
134 | //argc -= optind; | 136 | //argc -= optind; |
diff --git a/mailutils/reformime.c b/mailutils/reformime.c index 307656a15..a1d3f4e8b 100644 --- a/mailutils/reformime.c +++ b/mailutils/reformime.c | |||
@@ -166,7 +166,7 @@ static int parse(const char *boundary, char **argv) | |||
166 | else | 166 | else |
167 | filename = bb_get_last_path_component_strip(xstrdup(filename)); | 167 | filename = bb_get_last_path_component_strip(xstrdup(filename)); |
168 | 168 | ||
169 | if (opts & OPT_X) { | 169 | if (option_mask32 & OPT_X) { |
170 | int fd[2]; | 170 | int fd[2]; |
171 | 171 | ||
172 | /* start external helper */ | 172 | /* start external helper */ |
@@ -219,7 +219,7 @@ static int parse(const char *boundary, char **argv) | |||
219 | fclose(fp); | 219 | fclose(fp); |
220 | 220 | ||
221 | /* Wait for child */ | 221 | /* Wait for child */ |
222 | if (opts & OPT_X) { | 222 | if (option_mask32 & OPT_X) { |
223 | int rc; | 223 | int rc; |
224 | signal(SIGPIPE, SIG_DFL); | 224 | signal(SIGPIPE, SIG_DFL); |
225 | rc = (wait4pid(pid) & 0xff); | 225 | rc = (wait4pid(pid) & 0xff); |
@@ -275,6 +275,7 @@ Usage: reformime [options] | |||
275 | int reformime_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 275 | int reformime_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
276 | int reformime_main(int argc UNUSED_PARAM, char **argv) | 276 | int reformime_main(int argc UNUSED_PARAM, char **argv) |
277 | { | 277 | { |
278 | unsigned opts; | ||
278 | const char *opt_prefix = ""; | 279 | const char *opt_prefix = ""; |
279 | 280 | ||
280 | INIT_G(); | 281 | INIT_G(); |
diff --git a/mailutils/sendmail.c b/mailutils/sendmail.c index 1bdc1c300..1a01b7110 100644 --- a/mailutils/sendmail.c +++ b/mailutils/sendmail.c | |||
@@ -102,13 +102,6 @@ | |||
102 | // set to 0 to not limit | 102 | // set to 0 to not limit |
103 | #define MAX_HEADERS 256 | 103 | #define MAX_HEADERS 256 |
104 | 104 | ||
105 | static void send_r_n(const char *s) | ||
106 | { | ||
107 | if (verbose) | ||
108 | bb_error_msg("send:'%s'", s); | ||
109 | printf("%s\r\n", s); | ||
110 | } | ||
111 | |||
112 | static int smtp_checkp(const char *fmt, const char *param, int code) | 105 | static int smtp_checkp(const char *fmt, const char *param, int code) |
113 | { | 106 | { |
114 | char *answer; | 107 | char *answer; |
@@ -119,8 +112,9 @@ static int smtp_checkp(const char *fmt, const char *param, int code) | |||
119 | // if code = -1 then just return this number | 112 | // if code = -1 then just return this number |
120 | // if code != -1 then checks whether the number equals the code | 113 | // if code != -1 then checks whether the number equals the code |
121 | // if not equal -> die saying msg | 114 | // if not equal -> die saying msg |
115 | //FIXME: limit max len!!! | ||
122 | while ((answer = xmalloc_fgetline(stdin)) != NULL) { | 116 | while ((answer = xmalloc_fgetline(stdin)) != NULL) { |
123 | if (verbose) | 117 | if (G.verbose) |
124 | bb_error_msg("recv:'%.*s'", (int)(strchrnul(answer, '\r') - answer), answer); | 118 | bb_error_msg("recv:'%.*s'", (int)(strchrnul(answer, '\r') - answer), answer); |
125 | if (strlen(answer) <= 3 || '-' != answer[3]) | 119 | if (strlen(answer) <= 3 || '-' != answer[3]) |
126 | break; | 120 | break; |
@@ -128,7 +122,7 @@ static int smtp_checkp(const char *fmt, const char *param, int code) | |||
128 | } | 122 | } |
129 | if (answer) { | 123 | if (answer) { |
130 | int n = atoi(answer); | 124 | int n = atoi(answer); |
131 | if (timeout) | 125 | if (G.timeout) |
132 | alarm(0); | 126 | alarm(0); |
133 | free(answer); | 127 | free(answer); |
134 | if (-1 == code || n == code) { | 128 | if (-1 == code || n == code) { |
@@ -223,6 +217,7 @@ static void rcptto_list(const char *list) | |||
223 | int sendmail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 217 | int sendmail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
224 | int sendmail_main(int argc UNUSED_PARAM, char **argv) | 218 | int sendmail_main(int argc UNUSED_PARAM, char **argv) |
225 | { | 219 | { |
220 | unsigned opts; | ||
226 | char *opt_connect; | 221 | char *opt_connect; |
227 | char *opt_from = NULL; | 222 | char *opt_from = NULL; |
228 | char *s; | 223 | char *s; |
@@ -276,7 +271,7 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv) | |||
276 | // -v is a counter, -H and -S are mutually exclusive, -a is a list | 271 | // -v is a counter, -H and -S are mutually exclusive, -a is a list |
277 | "vv:H--S:S--H", | 272 | "vv:H--S:S--H", |
278 | &opt_from, NULL, | 273 | &opt_from, NULL, |
279 | &timeout, &opt_connect, &opt_connect, &list, &verbose | 274 | &G.timeout, &opt_connect, &opt_connect, &list, &G.verbose |
280 | ); | 275 | ); |
281 | //argc -= optind; | 276 | //argc -= optind; |
282 | argv += optind; | 277 | argv += optind; |
@@ -425,6 +420,7 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv) | |||
425 | // this means we scan stdin for To:, Cc:, Bcc: lines until an empty line | 420 | // this means we scan stdin for To:, Cc:, Bcc: lines until an empty line |
426 | // and then use the rest of stdin as message body | 421 | // and then use the rest of stdin as message body |
427 | code = 0; // set "analyze headers" mode | 422 | code = 0; // set "analyze headers" mode |
423 | //FIXME: limit max len!!! | ||
428 | while ((s = xmalloc_fgetline(G.fp0)) != NULL) { | 424 | while ((s = xmalloc_fgetline(G.fp0)) != NULL) { |
429 | dump: | 425 | dump: |
430 | // put message lines doubling leading dots | 426 | // put message lines doubling leading dots |
diff --git a/miscutils/adjtimex.c b/miscutils/adjtimex.c index a9de0f9aa..209d1d560 100644 --- a/miscutils/adjtimex.c +++ b/miscutils/adjtimex.c | |||
@@ -22,7 +22,7 @@ | |||
22 | //kbuild:lib-$(CONFIG_ADJTIMEX) += adjtimex.o | 22 | //kbuild:lib-$(CONFIG_ADJTIMEX) += adjtimex.o |
23 | 23 | ||
24 | //usage:#define adjtimex_trivial_usage | 24 | //usage:#define adjtimex_trivial_usage |
25 | //usage: "[-q] [-o OFF] [-f FREQ] [-p TCONST] [-t TICK]" | 25 | //usage: "[-q] [-o OFS] [-f FREQ] [-p TCONST] [-t TICK]" |
26 | //usage:#define adjtimex_full_usage "\n\n" | 26 | //usage:#define adjtimex_full_usage "\n\n" |
27 | //usage: "Read or set kernel time variables. See adjtimex(2)\n" | 27 | //usage: "Read or set kernel time variables. See adjtimex(2)\n" |
28 | //usage: "\n -q Quiet" | 28 | //usage: "\n -q Quiet" |
diff --git a/miscutils/bc.c b/miscutils/bc.c index 4d987325e..53eb5c799 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
@@ -231,7 +231,7 @@ typedef struct BcNum { | |||
231 | #define BC_NUM_MAX_IBASE 36 | 231 | #define BC_NUM_MAX_IBASE 36 |
232 | // larger value might speed up BIGNUM calculations a bit: | 232 | // larger value might speed up BIGNUM calculations a bit: |
233 | #define BC_NUM_DEF_SIZE 16 | 233 | #define BC_NUM_DEF_SIZE 16 |
234 | #define BC_NUM_PRINT_WIDTH 69 | 234 | #define BC_NUM_PRINT_WIDTH 70 |
235 | 235 | ||
236 | #define BC_NUM_KARATSUBA_LEN 32 | 236 | #define BC_NUM_KARATSUBA_LEN 32 |
237 | 237 | ||
@@ -517,7 +517,7 @@ struct BcLexKeyword { | |||
517 | }; | 517 | }; |
518 | #define LEX_KW_ENTRY(a, b) \ | 518 | #define LEX_KW_ENTRY(a, b) \ |
519 | { .name8 = a /*, .posix = b */ } | 519 | { .name8 = a /*, .posix = b */ } |
520 | static const struct BcLexKeyword bc_lex_kws[20] = { | 520 | static const struct BcLexKeyword bc_lex_kws[20] ALIGN8 = { |
521 | LEX_KW_ENTRY("auto" , 1), // 0 | 521 | LEX_KW_ENTRY("auto" , 1), // 0 |
522 | LEX_KW_ENTRY("break" , 1), // 1 | 522 | LEX_KW_ENTRY("break" , 1), // 1 |
523 | LEX_KW_ENTRY("continue", 0), // 2 note: this one has no terminating NUL | 523 | LEX_KW_ENTRY("continue", 0), // 2 note: this one has no terminating NUL |
@@ -1827,7 +1827,7 @@ static FAST_FUNC BC_STATUS zbc_num_k(BcNum *restrict a, BcNum *restrict b, | |||
1827 | #define zbc_num_k(...) (zbc_num_k(__VA_ARGS__) COMMA_SUCCESS) | 1827 | #define zbc_num_k(...) (zbc_num_k(__VA_ARGS__) COMMA_SUCCESS) |
1828 | { | 1828 | { |
1829 | BcStatus s; | 1829 | BcStatus s; |
1830 | size_t max = BC_MAX(a->len, b->len), max2 = (max + 1) / 2; | 1830 | size_t max, max2; |
1831 | BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp; | 1831 | BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp; |
1832 | bool aone; | 1832 | bool aone; |
1833 | 1833 | ||
@@ -1841,9 +1841,9 @@ static FAST_FUNC BC_STATUS zbc_num_k(BcNum *restrict a, BcNum *restrict b, | |||
1841 | RETURN_STATUS(BC_STATUS_SUCCESS); | 1841 | RETURN_STATUS(BC_STATUS_SUCCESS); |
1842 | } | 1842 | } |
1843 | 1843 | ||
1844 | if (a->len + b->len < BC_NUM_KARATSUBA_LEN | 1844 | if (a->len < BC_NUM_KARATSUBA_LEN |
1845 | || a->len < BC_NUM_KARATSUBA_LEN | ||
1846 | || b->len < BC_NUM_KARATSUBA_LEN | 1845 | || b->len < BC_NUM_KARATSUBA_LEN |
1846 | /* || a->len + b->len < BC_NUM_KARATSUBA_LEN - redundant check */ | ||
1847 | ) { | 1847 | ) { |
1848 | size_t i, j, len; | 1848 | size_t i, j, len; |
1849 | 1849 | ||
@@ -1877,6 +1877,7 @@ static FAST_FUNC BC_STATUS zbc_num_k(BcNum *restrict a, BcNum *restrict b, | |||
1877 | RETURN_STATUS(BC_STATUS_SUCCESS); | 1877 | RETURN_STATUS(BC_STATUS_SUCCESS); |
1878 | } | 1878 | } |
1879 | 1879 | ||
1880 | max = BC_MAX(a->len, b->len); | ||
1880 | bc_num_init(&l1, max); | 1881 | bc_num_init(&l1, max); |
1881 | bc_num_init(&h1, max); | 1882 | bc_num_init(&h1, max); |
1882 | bc_num_init(&l2, max); | 1883 | bc_num_init(&l2, max); |
@@ -1888,6 +1889,7 @@ static FAST_FUNC BC_STATUS zbc_num_k(BcNum *restrict a, BcNum *restrict b, | |||
1888 | bc_num_init(&z2, max); | 1889 | bc_num_init(&z2, max); |
1889 | bc_num_init(&temp, max + max); | 1890 | bc_num_init(&temp, max + max); |
1890 | 1891 | ||
1892 | max2 = (max + 1) / 2; | ||
1891 | bc_num_split(a, max2, &l1, &h1); | 1893 | bc_num_split(a, max2, &l1, &h1); |
1892 | bc_num_split(b, max2, &l2, &h2); | 1894 | bc_num_split(b, max2, &l2, &h2); |
1893 | 1895 | ||
@@ -2201,8 +2203,8 @@ static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) | |||
2201 | BcStatus s; | 2203 | BcStatus s; |
2202 | BcNum num1, num2, half, f, fprime, *x0, *x1, *temp; | 2204 | BcNum num1, num2, half, f, fprime, *x0, *x1, *temp; |
2203 | BcDig half_digs[1]; | 2205 | BcDig half_digs[1]; |
2204 | size_t pow, len, digs, digs1, resrdx, req, times = 0; | 2206 | size_t pow, len, digs, digs1, resrdx, req, times; |
2205 | ssize_t cmp = 1, cmp1 = SSIZE_MAX, cmp2 = SSIZE_MAX; | 2207 | ssize_t cmp, cmp1, cmp2; |
2206 | 2208 | ||
2207 | req = BC_MAX(scale, a->rdx) + ((BC_NUM_INT(a) + 1) >> 1) + 1; | 2209 | req = BC_MAX(scale, a->rdx) + ((BC_NUM_INT(a) + 1) >> 1) + 1; |
2208 | bc_num_expand(b, req); | 2210 | bc_num_expand(b, req); |
@@ -2255,11 +2257,12 @@ static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) | |||
2255 | x0->rdx -= pow; | 2257 | x0->rdx -= pow; |
2256 | } | 2258 | } |
2257 | 2259 | ||
2258 | x0->rdx = digs = digs1 = 0; | 2260 | x0->rdx = digs = digs1 = times = 0; |
2259 | resrdx = scale + 2; | 2261 | resrdx = scale + 2; |
2260 | len = BC_NUM_INT(x0) + resrdx - 1; | 2262 | len = x0->len + resrdx - 1; |
2261 | 2263 | cmp = 1; | |
2262 | while (cmp != 0 || digs < len) { | 2264 | cmp1 = cmp2 = SSIZE_MAX; |
2265 | do { | ||
2263 | s = zbc_num_div(a, x0, &f, resrdx); | 2266 | s = zbc_num_div(a, x0, &f, resrdx); |
2264 | if (s) goto err; | 2267 | if (s) goto err; |
2265 | s = zbc_num_add(x0, &f, &fprime, resrdx); | 2268 | s = zbc_num_add(x0, &f, &fprime, resrdx); |
@@ -2284,11 +2287,12 @@ static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) | |||
2284 | temp = x0; | 2287 | temp = x0; |
2285 | x0 = x1; | 2288 | x0 = x1; |
2286 | x1 = temp; | 2289 | x1 = temp; |
2287 | } | 2290 | } while (cmp != 0 || digs < len); |
2288 | 2291 | ||
2289 | bc_num_copy(b, x0); | 2292 | bc_num_copy(b, x0); |
2290 | scale -= 1; | 2293 | scale -= 1; |
2291 | if (b->rdx > scale) bc_num_truncate(b, b->rdx - scale); | 2294 | if (b->rdx > scale) |
2295 | bc_num_truncate(b, b->rdx - scale); | ||
2292 | err: | 2296 | err: |
2293 | bc_num_free(&fprime); | 2297 | bc_num_free(&fprime); |
2294 | bc_num_free(&f); | 2298 | bc_num_free(&f); |
@@ -2522,9 +2526,6 @@ static void xc_read_line(BcVec *vec, FILE *fp) | |||
2522 | 2526 | ||
2523 | #if ENABLE_FEATURE_BC_INTERACTIVE | 2527 | #if ENABLE_FEATURE_BC_INTERACTIVE |
2524 | if (G_interrupt) { // ^C was pressed | 2528 | if (G_interrupt) { // ^C was pressed |
2525 | # if ENABLE_FEATURE_EDITING | ||
2526 | intr: | ||
2527 | # endif | ||
2528 | if (fp != stdin) { | 2529 | if (fp != stdin) { |
2529 | // ^C while running a script (bc SCRIPT): die. | 2530 | // ^C while running a script (bc SCRIPT): die. |
2530 | // We do not return to interactive prompt: | 2531 | // We do not return to interactive prompt: |
@@ -2535,22 +2536,25 @@ static void xc_read_line(BcVec *vec, FILE *fp) | |||
2535 | // the shell would be unexpected. | 2536 | // the shell would be unexpected. |
2536 | xfunc_die(); | 2537 | xfunc_die(); |
2537 | } | 2538 | } |
2538 | // ^C while interactive input | 2539 | // There was ^C while running calculations |
2539 | G_interrupt = 0; | 2540 | G_interrupt = 0; |
2540 | // GNU bc says "interrupted execution." | 2541 | // GNU bc says "interrupted execution." (to stdout, not stderr) |
2541 | // GNU dc says "Interrupt!" | 2542 | // GNU dc says "Interrupt!" |
2542 | fputs("\ninterrupted execution\n", stderr); | 2543 | puts("\ninterrupted execution"); |
2543 | } | 2544 | } |
2544 | 2545 | ||
2545 | # if ENABLE_FEATURE_EDITING | 2546 | # if ENABLE_FEATURE_EDITING |
2546 | if (G_ttyin && fp == stdin) { | 2547 | if (G_ttyin && fp == stdin) { |
2547 | int n, i; | 2548 | int n, i; |
2549 | if (!G.line_input_state) | ||
2550 | G.line_input_state = new_line_input_t(DO_HISTORY); | ||
2548 | # define line_buf bb_common_bufsiz1 | 2551 | # define line_buf bb_common_bufsiz1 |
2549 | n = read_line_input(G.line_input_state, "", line_buf, COMMON_BUFSIZE); | 2552 | n = read_line_input(G.line_input_state, "", line_buf, COMMON_BUFSIZE); |
2550 | if (n <= 0) { // read errors or EOF, or ^D, or ^C | 2553 | if (n <= 0) { // read errors or EOF, or ^D, or ^C |
2551 | if (n == 0) // ^C | 2554 | //GNU bc prints this on ^C: |
2552 | goto intr; | 2555 | //if (n == 0) // ^C |
2553 | bc_vec_pushZeroByte(vec); // ^D or EOF (or error) | 2556 | // puts("(interrupt) Exiting bc."); |
2557 | bc_vec_pushZeroByte(vec); | ||
2554 | return; | 2558 | return; |
2555 | } | 2559 | } |
2556 | i = 0; | 2560 | i = 0; |
@@ -6872,22 +6876,6 @@ static BC_STATUS zxc_program_exec(void) | |||
6872 | } | 6876 | } |
6873 | #define zxc_program_exec(...) (zxc_program_exec(__VA_ARGS__) COMMA_SUCCESS) | 6877 | #define zxc_program_exec(...) (zxc_program_exec(__VA_ARGS__) COMMA_SUCCESS) |
6874 | 6878 | ||
6875 | static unsigned xc_vm_envLen(const char *var) | ||
6876 | { | ||
6877 | char *lenv; | ||
6878 | unsigned len; | ||
6879 | |||
6880 | lenv = getenv(var); | ||
6881 | len = BC_NUM_PRINT_WIDTH; | ||
6882 | if (!lenv) return len; | ||
6883 | |||
6884 | len = bb_strtou(lenv, NULL, 10) - 1; | ||
6885 | if (errno || len < 2 || len >= INT_MAX) | ||
6886 | len = BC_NUM_PRINT_WIDTH; | ||
6887 | |||
6888 | return len; | ||
6889 | } | ||
6890 | |||
6891 | static BC_STATUS zxc_vm_process(const char *text) | 6879 | static BC_STATUS zxc_vm_process(const char *text) |
6892 | { | 6880 | { |
6893 | BcStatus s; | 6881 | BcStatus s; |
@@ -7377,12 +7365,43 @@ static void xc_program_init(void) | |||
7377 | bc_char_vec_init(&G.input_buffer); | 7365 | bc_char_vec_init(&G.input_buffer); |
7378 | } | 7366 | } |
7379 | 7367 | ||
7368 | static unsigned xc_vm_envLen(const char *var) | ||
7369 | { | ||
7370 | char *lenv; | ||
7371 | unsigned len; | ||
7372 | |||
7373 | lenv = getenv(var); | ||
7374 | len = BC_NUM_PRINT_WIDTH; | ||
7375 | if (lenv) { | ||
7376 | len = bb_strtou(lenv, NULL, 10); | ||
7377 | if (len == 0 || len > INT_MAX) | ||
7378 | len = INT_MAX; | ||
7379 | if (errno) | ||
7380 | len = BC_NUM_PRINT_WIDTH; | ||
7381 | } | ||
7382 | |||
7383 | // dc (GNU bc 1.07.1) 1.4.1 seems to use width | ||
7384 | // 1 char wider than bc from the same package. | ||
7385 | // Both default width, and xC_LINE_LENGTH=N are wider: | ||
7386 | // "DC_LINE_LENGTH=5 dc -e'123456 p'" prints: | ||
7387 | // |1234\ | | ||
7388 | // |56 | | ||
7389 | // "echo '123456' | BC_LINE_LENGTH=5 bc" prints: | ||
7390 | // |123\ | | ||
7391 | // |456 | | ||
7392 | // Do the same, but it might be a bug in GNU package | ||
7393 | if (IS_BC) | ||
7394 | len--; | ||
7395 | |||
7396 | if (len < 2) | ||
7397 | len = IS_BC ? BC_NUM_PRINT_WIDTH - 1 : BC_NUM_PRINT_WIDTH; | ||
7398 | |||
7399 | return len; | ||
7400 | } | ||
7401 | |||
7380 | static int xc_vm_init(const char *env_len) | 7402 | static int xc_vm_init(const char *env_len) |
7381 | { | 7403 | { |
7382 | G.prog.len = xc_vm_envLen(env_len); | 7404 | G.prog.len = xc_vm_envLen(env_len); |
7383 | #if ENABLE_FEATURE_EDITING | ||
7384 | G.line_input_state = new_line_input_t(DO_HISTORY); | ||
7385 | #endif | ||
7386 | bc_vec_init(&G.files, sizeof(char *), NULL); | 7405 | bc_vec_init(&G.files, sizeof(char *), NULL); |
7387 | 7406 | ||
7388 | xc_program_init(); | 7407 | xc_program_init(); |
@@ -7466,16 +7485,6 @@ int dc_main(int argc UNUSED_PARAM, char **argv) | |||
7466 | 7485 | ||
7467 | INIT_G(); | 7486 | INIT_G(); |
7468 | 7487 | ||
7469 | // TODO: dc (GNU bc 1.07.1) 1.4.1 seems to use width | ||
7470 | // 1 char wider than bc from the same package. | ||
7471 | // Both default width, and xC_LINE_LENGTH=N are wider: | ||
7472 | // "DC_LINE_LENGTH=5 dc -e'123456 p'" prints: | ||
7473 | // |1234\ | | ||
7474 | // |56 | | ||
7475 | // "echo '123456' | BC_LINE_LENGTH=5 bc" prints: | ||
7476 | // |123\ | | ||
7477 | // |456 | | ||
7478 | // Do the same, or it's a bug? | ||
7479 | xc_vm_init("DC_LINE_LENGTH"); | 7488 | xc_vm_init("DC_LINE_LENGTH"); |
7480 | 7489 | ||
7481 | // Run -e'SCRIPT' and -fFILE in order of appearance, then handle FILEs | 7490 | // Run -e'SCRIPT' and -fFILE in order of appearance, then handle FILEs |
diff --git a/miscutils/beep.c b/miscutils/beep.c index 1669332fd..7c60aed08 100644 --- a/miscutils/beep.c +++ b/miscutils/beep.c | |||
@@ -114,10 +114,10 @@ int beep_main(int argc, char **argv) | |||
114 | while (rep) { | 114 | while (rep) { |
115 | //bb_error_msg("rep[%d] freq=%d, length=%d, delay=%d", rep, freq, length, delay); | 115 | //bb_error_msg("rep[%d] freq=%d, length=%d, delay=%d", rep, freq, length, delay); |
116 | xioctl(speaker, KIOCSOUND, (void*)(uintptr_t)tickrate_div_freq); | 116 | xioctl(speaker, KIOCSOUND, (void*)(uintptr_t)tickrate_div_freq); |
117 | usleep(1000 * length); | 117 | msleep(length); |
118 | ioctl(speaker, KIOCSOUND, (void*)0); | 118 | ioctl(speaker, KIOCSOUND, (void*)0); |
119 | if (--rep) | 119 | if (--rep) |
120 | usleep(1000 * delay); | 120 | msleep(delay); |
121 | } | 121 | } |
122 | } | 122 | } |
123 | 123 | ||
diff --git a/miscutils/chat.c b/miscutils/chat.c index a04565063..86a114df6 100644 --- a/miscutils/chat.c +++ b/miscutils/chat.c | |||
@@ -379,7 +379,7 @@ int chat_main(int argc UNUSED_PARAM, char **argv) | |||
379 | // dump device input if ECHO ON | 379 | // dump device input if ECHO ON |
380 | if (echo) { | 380 | if (echo) { |
381 | // if (buf[buf_len] < ' ') { | 381 | // if (buf[buf_len] < ' ') { |
382 | // full_write(STDERR_FILENO, "^", 1); | 382 | // full_write2_str("^"); |
383 | // buf[buf_len] += '@'; | 383 | // buf[buf_len] += '@'; |
384 | // } | 384 | // } |
385 | full_write(STDERR_FILENO, buf+buf_len, 1); | 385 | full_write(STDERR_FILENO, buf+buf_len, 1); |
@@ -473,7 +473,7 @@ int chat_main(int argc UNUSED_PARAM, char **argv) | |||
473 | if ('\\' == c) { | 473 | if ('\\' == c) { |
474 | c = *++buf; | 474 | c = *++buf; |
475 | if ('d' == c) { | 475 | if ('d' == c) { |
476 | sleep(1); | 476 | sleep1(); |
477 | len--; | 477 | len--; |
478 | continue; | 478 | continue; |
479 | } | 479 | } |
@@ -509,7 +509,7 @@ int chat_main(int argc UNUSED_PARAM, char **argv) | |||
509 | #if ENABLE_FEATURE_CHAT_IMPLICIT_CR | 509 | #if ENABLE_FEATURE_CHAT_IMPLICIT_CR |
510 | // or terminate command with \r (if not inhibited) | 510 | // or terminate command with \r (if not inhibited) |
511 | else if (!nocr) | 511 | else if (!nocr) |
512 | xwrite(STDOUT_FILENO, "\r", 1); | 512 | xwrite_str(STDOUT_FILENO, "\r"); |
513 | #endif | 513 | #endif |
514 | // bail out unless we sent command successfully | 514 | // bail out unless we sent command successfully |
515 | if (exitcode) | 515 | if (exitcode) |
diff --git a/miscutils/crond.c b/miscutils/crond.c index 2e8ca8b68..b74427351 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c | |||
@@ -63,7 +63,7 @@ | |||
63 | //kbuild:lib-$(CONFIG_CROND) += crond.o | 63 | //kbuild:lib-$(CONFIG_CROND) += crond.o |
64 | 64 | ||
65 | //usage:#define crond_trivial_usage | 65 | //usage:#define crond_trivial_usage |
66 | //usage: "-fbS -l N " IF_FEATURE_CROND_D("-d N ") "-L LOGFILE -c DIR" | 66 | //usage: "[-fbS] [-l N] " IF_FEATURE_CROND_D("[-d N] ") "[-L LOGFILE] [-c DIR]" |
67 | //usage:#define crond_full_usage "\n\n" | 67 | //usage:#define crond_full_usage "\n\n" |
68 | //usage: " -f Foreground" | 68 | //usage: " -f Foreground" |
69 | //usage: "\n -b Background (default)" | 69 | //usage: "\n -b Background (default)" |
@@ -492,7 +492,7 @@ static void load_crontab(const char *fileName) | |||
492 | const char *name; | 492 | const char *name; |
493 | const char tokens[8]; | 493 | const char tokens[8]; |
494 | } SpecialEntry; | 494 | } SpecialEntry; |
495 | static const SpecialEntry SpecAry[] = { | 495 | static const SpecialEntry SpecAry[] ALIGN8 = { |
496 | /* hour day month weekday */ | 496 | /* hour day month weekday */ |
497 | { "yearly", "0\0" "1\0" "1\0" "*" }, | 497 | { "yearly", "0\0" "1\0" "1\0" "*" }, |
498 | { "annually", "0\0" "1\0" "1\0" "*" }, | 498 | { "annually", "0\0" "1\0" "1\0" "*" }, |
diff --git a/miscutils/dc.c b/miscutils/dc.c index b6c6795b6..918f2b5c8 100644 --- a/miscutils/dc.c +++ b/miscutils/dc.c | |||
@@ -100,7 +100,7 @@ static void mod(void) | |||
100 | * 0 | 100 | * 0 |
101 | */ | 101 | */ |
102 | if (d == 0) { | 102 | if (d == 0) { |
103 | bb_error_msg("remainder by zero"); | 103 | bb_simple_error_msg("remainder by zero"); |
104 | pop(); | 104 | pop(); |
105 | push(0); | 105 | push(0); |
106 | return; | 106 | return; |
@@ -195,7 +195,7 @@ struct op { | |||
195 | void (*function) (void); | 195 | void (*function) (void); |
196 | }; | 196 | }; |
197 | 197 | ||
198 | static const struct op operators[] = { | 198 | static const struct op operators[] ALIGN_PTR = { |
199 | #if ENABLE_FEATURE_DC_LIBM | 199 | #if ENABLE_FEATURE_DC_LIBM |
200 | {"^", power}, | 200 | {"^", power}, |
201 | // {"exp", power}, | 201 | // {"exp", power}, |
diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c index 17d8fb6b9..e5bb8a2d8 100644 --- a/miscutils/devfsd.c +++ b/miscutils/devfsd.c | |||
@@ -362,7 +362,7 @@ static const char bb_msg_variable_not_found[] ALIGN1 = "variable: %s not found"; | |||
362 | 362 | ||
363 | static void safe_memcpy(char *dest, const char *src, int len) | 363 | static void safe_memcpy(char *dest, const char *src, int len) |
364 | { | 364 | { |
365 | memcpy(dest , src, len); | 365 | memcpy(dest, src, len); |
366 | dest[len] = '\0'; | 366 | dest[len] = '\0'; |
367 | } | 367 | } |
368 | 368 | ||
@@ -1106,7 +1106,7 @@ static int copy_inode(const char *destpath, const struct stat *dest_stat, | |||
1106 | do_chown: | 1106 | do_chown: |
1107 | if (chown(destpath, source_stat->st_uid, source_stat->st_gid) == 0) | 1107 | if (chown(destpath, source_stat->st_uid, source_stat->st_gid) == 0) |
1108 | return TRUE; | 1108 | return TRUE; |
1109 | /*break;*/ | 1109 | /*break;*/ |
1110 | } | 1110 | } |
1111 | return FALSE; | 1111 | return FALSE; |
1112 | } /* End Function copy_inode */ | 1112 | } /* End Function copy_inode */ |
diff --git a/miscutils/devmem.c b/miscutils/devmem.c index e8dce5225..f9f0276bc 100644 --- a/miscutils/devmem.c +++ b/miscutils/devmem.c | |||
@@ -75,7 +75,7 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) | |||
75 | bb_show_usage(); /* one of bb_strtouXX failed */ | 75 | bb_show_usage(); /* one of bb_strtouXX failed */ |
76 | 76 | ||
77 | fd = xopen("/dev/mem", argv[3] ? (O_RDWR | O_SYNC) : (O_RDONLY | O_SYNC)); | 77 | fd = xopen("/dev/mem", argv[3] ? (O_RDWR | O_SYNC) : (O_RDONLY | O_SYNC)); |
78 | mapped_size = page_size = getpagesize(); | 78 | mapped_size = page_size = bb_getpagesize(); |
79 | offset_in_page = (unsigned)target & (page_size - 1); | 79 | offset_in_page = (unsigned)target & (page_size - 1); |
80 | if (offset_in_page + width > page_size) { | 80 | if (offset_in_page + width > page_size) { |
81 | /* This access spans pages. | 81 | /* This access spans pages. |
diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c index d25a2466e..01b4e8e2e 100644 --- a/miscutils/hdparm.c +++ b/miscutils/hdparm.c | |||
@@ -1366,7 +1366,7 @@ static NOINLINE void dump_identity(const struct hd_driveid *id) | |||
1366 | } | 1366 | } |
1367 | if (id->capability & 1) { | 1367 | if (id->capability & 1) { |
1368 | if (id->dma_1word | id->dma_mword) { | 1368 | if (id->dma_1word | id->dma_mword) { |
1369 | static const int dma_wmode_masks[] = { 0x100, 1, 0x200, 2, 0x400, 4, 0xf800, 0xf8 }; | 1369 | static const int dma_wmode_masks[] ALIGN4 = { 0x100, 1, 0x200, 2, 0x400, 4, 0xf800, 0xf8 }; |
1370 | printf("\n DMA modes: "); | 1370 | printf("\n DMA modes: "); |
1371 | print_flags_separated(dma_wmode_masks, | 1371 | print_flags_separated(dma_wmode_masks, |
1372 | "*\0""sdma0 \0""*\0""sdma1 \0""*\0""sdma2 \0""*\0""sdma? \0", | 1372 | "*\0""sdma0 \0""*\0""sdma1 \0""*\0""sdma2 \0""*\0""sdma? \0", |
@@ -1436,7 +1436,7 @@ static void flush_buffer_cache(/*int fd*/ void) | |||
1436 | fsync(fd); /* flush buffers */ | 1436 | fsync(fd); /* flush buffers */ |
1437 | ioctl_or_warn(fd, BLKFLSBUF, NULL); /* do it again, big time */ | 1437 | ioctl_or_warn(fd, BLKFLSBUF, NULL); /* do it again, big time */ |
1438 | #ifdef HDIO_DRIVE_CMD | 1438 | #ifdef HDIO_DRIVE_CMD |
1439 | sleep(1); | 1439 | sleep1(); |
1440 | if (ioctl(fd, HDIO_DRIVE_CMD, NULL) && errno != EINVAL) { /* await completion */ | 1440 | if (ioctl(fd, HDIO_DRIVE_CMD, NULL) && errno != EINVAL) { /* await completion */ |
1441 | if (ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn */ | 1441 | if (ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn */ |
1442 | bb_simple_perror_msg("HDIO_DRIVE_CMD"); | 1442 | bb_simple_perror_msg("HDIO_DRIVE_CMD"); |
@@ -1511,7 +1511,7 @@ static void do_time(int cache /*,int fd*/) | |||
1511 | * NB: *small* delay. User is expected to have a clue and to not run | 1511 | * NB: *small* delay. User is expected to have a clue and to not run |
1512 | * heavy io in parallel with measurements. */ | 1512 | * heavy io in parallel with measurements. */ |
1513 | sync(); | 1513 | sync(); |
1514 | sleep(1); | 1514 | sleep1(); |
1515 | if (cache) { /* Time cache */ | 1515 | if (cache) { /* Time cache */ |
1516 | seek_to_zero(); | 1516 | seek_to_zero(); |
1517 | read_big_block(buf); | 1517 | read_big_block(buf); |
diff --git a/miscutils/hexedit.c b/miscutils/hexedit.c index 898d77376..f8ff9b62b 100644 --- a/miscutils/hexedit.c +++ b/miscutils/hexedit.c | |||
@@ -31,7 +31,8 @@ struct globals { | |||
31 | int fd; | 31 | int fd; |
32 | unsigned height; | 32 | unsigned height; |
33 | unsigned row; | 33 | unsigned row; |
34 | unsigned pagesize; | 34 | IF_VARIABLE_ARCH_PAGESIZE(unsigned pagesize;) |
35 | #define G_pagesize cached_pagesize(G.pagesize) | ||
35 | uint8_t *baseaddr; | 36 | uint8_t *baseaddr; |
36 | uint8_t *current_byte; | 37 | uint8_t *current_byte; |
37 | uint8_t *eof_byte; | 38 | uint8_t *eof_byte; |
@@ -46,15 +47,6 @@ struct globals { | |||
46 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | 47 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
47 | } while (0) | 48 | } while (0) |
48 | 49 | ||
49 | //TODO: move to libbb | ||
50 | #if defined(__x86_64__) || defined(i386) | ||
51 | # define G_pagesize 4096 | ||
52 | # define INIT_PAGESIZE() ((void)0) | ||
53 | #else | ||
54 | # define G_pagesize (G.pagesize) | ||
55 | # define INIT_PAGESIZE() ((void)(G.pagesize = getpagesize())) | ||
56 | #endif | ||
57 | |||
58 | /* hopefully there aren't arches with PAGE_SIZE > 64k */ | 50 | /* hopefully there aren't arches with PAGE_SIZE > 64k */ |
59 | #define G_mapsize (64*1024) | 51 | #define G_mapsize (64*1024) |
60 | 52 | ||
@@ -262,7 +254,7 @@ int hexedit_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |||
262 | int hexedit_main(int argc UNUSED_PARAM, char **argv) | 254 | int hexedit_main(int argc UNUSED_PARAM, char **argv) |
263 | { | 255 | { |
264 | INIT_G(); | 256 | INIT_G(); |
265 | INIT_PAGESIZE(); | 257 | INIT_PAGESIZE(G.pagesize); |
266 | 258 | ||
267 | get_terminal_width_height(-1, NULL, &G.height); | 259 | get_terminal_width_height(-1, NULL, &G.height); |
268 | if (1) { | 260 | if (1) { |
diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index cc8b99a92..48135921d 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c | |||
@@ -273,7 +273,7 @@ static int i2c_bus_lookup(const char *bus_str) | |||
273 | return xstrtou_range(bus_str, 10, 0, 0xfffff); | 273 | return xstrtou_range(bus_str, 10, 0, 0xfffff); |
274 | } | 274 | } |
275 | 275 | ||
276 | #if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP || ENABLE_I2CTRANSFER | 276 | #if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP |
277 | static int i2c_parse_bus_addr(const char *addr_str) | 277 | static int i2c_parse_bus_addr(const char *addr_str) |
278 | { | 278 | { |
279 | /* Slave address must be in range 0x03 - 0x77. */ | 279 | /* Slave address must be in range 0x03 - 0x77. */ |
@@ -286,14 +286,16 @@ static void i2c_set_pec(int fd, int pec) | |||
286 | itoptr(pec ? 1 : 0), | 286 | itoptr(pec ? 1 : 0), |
287 | "can't set PEC"); | 287 | "can't set PEC"); |
288 | } | 288 | } |
289 | #endif | ||
289 | 290 | ||
291 | #if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP || ENABLE_I2CTRANSFER | ||
290 | static void i2c_set_slave_addr(int fd, int addr, int force) | 292 | static void i2c_set_slave_addr(int fd, int addr, int force) |
291 | { | 293 | { |
292 | ioctl_or_perror_and_die(fd, force ? I2C_SLAVE_FORCE : I2C_SLAVE, | 294 | ioctl_or_perror_and_die(fd, force ? I2C_SLAVE_FORCE : I2C_SLAVE, |
293 | itoptr(addr), | 295 | itoptr(addr), |
294 | "can't set address to 0x%02x", addr); | 296 | "can't set address to 0x%02x", addr); |
295 | } | 297 | } |
296 | #endif /* ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP */ | 298 | #endif |
297 | 299 | ||
298 | #if ENABLE_I2CGET || ENABLE_I2CSET | 300 | #if ENABLE_I2CGET || ENABLE_I2CSET |
299 | static int i2c_parse_data_addr(const char *data_addr) | 301 | static int i2c_parse_data_addr(const char *data_addr) |
@@ -1052,24 +1054,19 @@ struct adap_desc { | |||
1052 | const char *algo; | 1054 | const char *algo; |
1053 | }; | 1055 | }; |
1054 | 1056 | ||
1055 | static const struct adap_desc adap_descs[] = { | 1057 | static const struct adap_desc adap_descs[] ALIGN_PTR = { |
1056 | { .funcs = "dummy", | 1058 | { .funcs = "dummy", .algo = "Dummy bus", }, |
1057 | .algo = "Dummy bus", }, | 1059 | { .funcs = "isa", .algo = "ISA bus", }, |
1058 | { .funcs = "isa", | 1060 | { .funcs = "i2c", .algo = "I2C adapter", }, |
1059 | .algo = "ISA bus", }, | 1061 | { .funcs = "smbus", .algo = "SMBus adapter", }, |
1060 | { .funcs = "i2c", | ||
1061 | .algo = "I2C adapter", }, | ||
1062 | { .funcs = "smbus", | ||
1063 | .algo = "SMBus adapter", }, | ||
1064 | }; | 1062 | }; |
1065 | 1063 | ||
1066 | struct i2c_func | 1064 | struct i2c_func { |
1067 | { | ||
1068 | long value; | 1065 | long value; |
1069 | const char* name; | 1066 | const char* name; |
1070 | }; | 1067 | }; |
1071 | 1068 | ||
1072 | static const struct i2c_func i2c_funcs_tab[] = { | 1069 | static const struct i2c_func i2c_funcs_tab[] ALIGN_PTR = { |
1073 | { .value = I2C_FUNC_I2C, | 1070 | { .value = I2C_FUNC_I2C, |
1074 | .name = "I2C" }, | 1071 | .name = "I2C" }, |
1075 | { .value = I2C_FUNC_SMBUS_QUICK, | 1072 | { .value = I2C_FUNC_SMBUS_QUICK, |
@@ -1152,12 +1149,12 @@ static void NORETURN list_i2c_busses_and_exit(void) | |||
1152 | /* Simple version for ISA chips. */ | 1149 | /* Simple version for ISA chips. */ |
1153 | snprintf(path, NAME_MAX, "%s/%s/name", | 1150 | snprintf(path, NAME_MAX, "%s/%s/name", |
1154 | i2cdev_path, de->d_name); | 1151 | i2cdev_path, de->d_name); |
1155 | fp = fopen(path, "r"); | 1152 | fp = fopen_for_read(path); |
1156 | if (fp == NULL) { | 1153 | if (fp == NULL) { |
1157 | snprintf(path, NAME_MAX, | 1154 | snprintf(path, NAME_MAX, |
1158 | "%s/%s/device/name", | 1155 | "%s/%s/device/name", |
1159 | i2cdev_path, de->d_name); | 1156 | i2cdev_path, de->d_name); |
1160 | fp = fopen(path, "r"); | 1157 | fp = fopen_for_read(path); |
1161 | } | 1158 | } |
1162 | 1159 | ||
1163 | /* Non-ISA chips require the hard-way. */ | 1160 | /* Non-ISA chips require the hard-way. */ |
@@ -1178,7 +1175,7 @@ static void NORETURN list_i2c_busses_and_exit(void) | |||
1178 | "%s/%s/device/%s/name", | 1175 | "%s/%s/device/%s/name", |
1179 | i2cdev_path, de->d_name, | 1176 | i2cdev_path, de->d_name, |
1180 | subde->d_name); | 1177 | subde->d_name); |
1181 | fp = fopen(path, "r"); | 1178 | fp = fopen_for_read(path); |
1182 | break; | 1179 | break; |
1183 | } | 1180 | } |
1184 | } | 1181 | } |
diff --git a/miscutils/man.c b/miscutils/man.c index 6724b4b5d..052b50054 100644 --- a/miscutils/man.c +++ b/miscutils/man.c | |||
@@ -13,7 +13,7 @@ | |||
13 | //kbuild:lib-$(CONFIG_MAN) += man.o | 13 | //kbuild:lib-$(CONFIG_MAN) += man.o |
14 | 14 | ||
15 | //usage:#define man_trivial_usage | 15 | //usage:#define man_trivial_usage |
16 | //usage: "[-aw] MANPAGE..." | 16 | //usage: "[-aw] [SECTION] MANPAGE[.SECTION]..." |
17 | //usage:#define man_full_usage "\n\n" | 17 | //usage:#define man_full_usage "\n\n" |
18 | //usage: "Display manual page\n" | 18 | //usage: "Display manual page\n" |
19 | //usage: "\n -a Display all pages" | 19 | //usage: "\n -a Display all pages" |
@@ -239,10 +239,21 @@ static const char *if_redefined(const char *var, const char *key, const char *li | |||
239 | return xstrdup(skip_whitespace(line)); | 239 | return xstrdup(skip_whitespace(line)); |
240 | } | 240 | } |
241 | 241 | ||
242 | static int is_section_name(const char *sections, const char *str) | ||
243 | { | ||
244 | const char *s = strstr(sections, str); | ||
245 | if (s) { | ||
246 | int l = strlen(str); | ||
247 | return (s[l] == ':' || s[l] == '\0'); | ||
248 | } | ||
249 | return 0; | ||
250 | } | ||
251 | |||
242 | int man_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 252 | int man_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
243 | int man_main(int argc UNUSED_PARAM, char **argv) | 253 | int man_main(int argc UNUSED_PARAM, char **argv) |
244 | { | 254 | { |
245 | parser_t *parser; | 255 | parser_t *parser; |
256 | char *conf_sec_list; | ||
246 | char *sec_list; | 257 | char *sec_list; |
247 | char **man_path_list; | 258 | char **man_path_list; |
248 | int count_mp; | 259 | int count_mp; |
@@ -267,7 +278,7 @@ int man_main(int argc UNUSED_PARAM, char **argv) | |||
267 | chdir_system_drive(); | 278 | chdir_system_drive(); |
268 | #endif | 279 | #endif |
269 | 280 | ||
270 | sec_list = xstrdup("0p:1:1p:2:3:3p:4:5:6:7:8:9"); | 281 | conf_sec_list = xstrdup("0p:1:1p:2:3:3p:4:5:6:7:8:9"); |
271 | 282 | ||
272 | count_mp = 0; | 283 | count_mp = 0; |
273 | man_path_list = add_MANPATH(NULL, &count_mp, | 284 | man_path_list = add_MANPATH(NULL, &count_mp, |
@@ -297,8 +308,8 @@ int man_main(int argc UNUSED_PARAM, char **argv) | |||
297 | man_path_list = add_MANPATH(man_path_list, &count_mp, token[1]); | 308 | man_path_list = add_MANPATH(man_path_list, &count_mp, token[1]); |
298 | } | 309 | } |
299 | if (strcmp("MANSECT", token[0]) == 0) { | 310 | if (strcmp("MANSECT", token[0]) == 0) { |
300 | free(sec_list); | 311 | free(conf_sec_list); |
301 | sec_list = xstrdup(token[1]); | 312 | conf_sec_list = xstrdup(token[1]); |
302 | } | 313 | } |
303 | } | 314 | } |
304 | config_close(parser); | 315 | config_close(parser); |
@@ -337,6 +348,13 @@ int man_main(int argc UNUSED_PARAM, char **argv) | |||
337 | G.pager = xasprintf("%s -b -p -x", G.col); | 348 | G.pager = xasprintf("%s -b -p -x", G.col); |
338 | } | 349 | } |
339 | 350 | ||
351 | /* is 1st ARG a SECTION? */ | ||
352 | sec_list = conf_sec_list; | ||
353 | if (is_section_name(conf_sec_list, *argv)) { | ||
354 | /* yes */ | ||
355 | sec_list = *argv++; | ||
356 | } | ||
357 | |||
340 | not_found = 0; | 358 | not_found = 0; |
341 | do { /* for each argv[] */ | 359 | do { /* for each argv[] */ |
342 | const char *cur_path; | 360 | const char *cur_path; |
@@ -347,11 +365,20 @@ int man_main(int argc UNUSED_PARAM, char **argv) | |||
347 | found = show_manpage(*argv, /*man:*/ 1, 0); | 365 | found = show_manpage(*argv, /*man:*/ 1, 0); |
348 | goto check_found; | 366 | goto check_found; |
349 | } | 367 | } |
368 | |||
369 | /* for each MANPATH */ | ||
350 | cur_mp = 0; | 370 | cur_mp = 0; |
351 | while ((cur_path = man_path_list[cur_mp++]) != NULL) { | 371 | while ((cur_path = man_path_list[cur_mp++]) != NULL) { |
352 | /* for each MANPATH */ | ||
353 | const char *cur_sect = sec_list; | 372 | const char *cur_sect = sec_list; |
354 | do { /* for each section */ | 373 | |
374 | /* is MANPAGE of the form NAME.SECTION? */ | ||
375 | char *sect_ext = strrchr(*argv, '.'); | ||
376 | if (sect_ext && is_section_name(conf_sec_list, sect_ext + 1)) { | ||
377 | *sect_ext = '\0'; | ||
378 | cur_sect = sect_ext + 1; | ||
379 | } | ||
380 | |||
381 | do { /* for each SECTION in cur_sect */ | ||
355 | char *next_sect = strchrnul(cur_sect, ':'); | 382 | char *next_sect = strchrnul(cur_sect, ':'); |
356 | int sect_len = next_sect - cur_sect; | 383 | int sect_len = next_sect - cur_sect; |
357 | char *man_filename; | 384 | char *man_filename; |
@@ -378,6 +405,8 @@ int man_main(int argc UNUSED_PARAM, char **argv) | |||
378 | while (*cur_sect == ':') | 405 | while (*cur_sect == ':') |
379 | cur_sect++; | 406 | cur_sect++; |
380 | } while (*cur_sect); | 407 | } while (*cur_sect); |
408 | |||
409 | if (sect_ext) *sect_ext = '.'; | ||
381 | } | 410 | } |
382 | check_found: | 411 | check_found: |
383 | if (!found) { | 412 | if (!found) { |
diff --git a/miscutils/mt.c b/miscutils/mt.c index 9f1aecfca..1a4214664 100644 --- a/miscutils/mt.c +++ b/miscutils/mt.c | |||
@@ -15,7 +15,7 @@ | |||
15 | //kbuild:lib-$(CONFIG_MT) += mt.o | 15 | //kbuild:lib-$(CONFIG_MT) += mt.o |
16 | 16 | ||
17 | //usage:#define mt_trivial_usage | 17 | //usage:#define mt_trivial_usage |
18 | //usage: "[-f device] opcode value" | 18 | //usage: "[-f DEVICE] OPCODE VALUE" |
19 | //usage:#define mt_full_usage "\n\n" | 19 | //usage:#define mt_full_usage "\n\n" |
20 | //usage: "Control magnetic tape drive operation\n" | 20 | //usage: "Control magnetic tape drive operation\n" |
21 | //usage: "\n" | 21 | //usage: "\n" |
@@ -30,7 +30,7 @@ | |||
30 | #include <sys/mtio.h> | 30 | #include <sys/mtio.h> |
31 | 31 | ||
32 | /* missing: eod/seod, stoptions, stwrthreshold, densities */ | 32 | /* missing: eod/seod, stoptions, stwrthreshold, densities */ |
33 | static const short opcode_value[] = { | 33 | static const short opcode_value[] ALIGN2 = { |
34 | MTBSF, | 34 | MTBSF, |
35 | MTBSFM, | 35 | MTBSFM, |
36 | MTBSR, | 36 | MTBSR, |
diff --git a/miscutils/setserial.c b/miscutils/setserial.c index 1e75bf433..2006861e2 100644 --- a/miscutils/setserial.c +++ b/miscutils/setserial.c | |||
@@ -381,8 +381,7 @@ static bool cmd_needs_arg(int cmd) | |||
381 | # error "Unexpected flags size" | 381 | # error "Unexpected flags size" |
382 | #endif | 382 | #endif |
383 | 383 | ||
384 | static const uint16_t setbits[CMD_FLAG_LAST + 1] = | 384 | static const uint16_t setbits[CMD_FLAG_LAST + 1] ALIGN2 = { |
385 | { | ||
386 | 0, | 385 | 0, |
387 | ASYNC_SPD_HI, | 386 | ASYNC_SPD_HI, |
388 | ASYNC_SPD_VHI, | 387 | ASYNC_SPD_VHI, |
diff --git a/miscutils/time.c b/miscutils/time.c index dcc3a5b4c..12c540211 100644 --- a/miscutils/time.c +++ b/miscutils/time.c | |||
@@ -127,6 +127,10 @@ static void printargv(char *const *argv) | |||
127 | This is funky since the pagesize could be less than 1K. | 127 | This is funky since the pagesize could be less than 1K. |
128 | Note: Some machines express getrusage statistics in terms of K, | 128 | Note: Some machines express getrusage statistics in terms of K, |
129 | others in terms of pages. */ | 129 | others in terms of pages. */ |
130 | #ifdef BB_ARCH_FIXED_PAGESIZE | ||
131 | # define pagesize BB_ARCH_FIXED_PAGESIZE | ||
132 | # define ptok(pagesize, pages) ptok(pages) | ||
133 | #endif | ||
130 | static unsigned long ptok(const unsigned pagesize, const unsigned long pages) | 134 | static unsigned long ptok(const unsigned pagesize, const unsigned long pages) |
131 | { | 135 | { |
132 | unsigned long tmp; | 136 | unsigned long tmp; |
@@ -140,6 +144,7 @@ static unsigned long ptok(const unsigned pagesize, const unsigned long pages) | |||
140 | tmp = pages * pagesize; /* Larger first, */ | 144 | tmp = pages * pagesize; /* Larger first, */ |
141 | return tmp / 1024; /* then smaller. */ | 145 | return tmp / 1024; /* then smaller. */ |
142 | } | 146 | } |
147 | #undef pagesize | ||
143 | #endif | 148 | #endif |
144 | 149 | ||
145 | /* summarize: Report on the system use of a command. | 150 | /* summarize: Report on the system use of a command. |
@@ -199,7 +204,7 @@ static void summarize(const char *fmt, char **command, resource_t *resp) | |||
199 | #if !ENABLE_PLATFORM_MINGW32 | 204 | #if !ENABLE_PLATFORM_MINGW32 |
200 | unsigned vv_ms; /* Elapsed virtual (CPU) milliseconds */ | 205 | unsigned vv_ms; /* Elapsed virtual (CPU) milliseconds */ |
201 | unsigned cpu_ticks; /* Same, in "CPU ticks" */ | 206 | unsigned cpu_ticks; /* Same, in "CPU ticks" */ |
202 | unsigned pagesize = getpagesize(); | 207 | unsigned pagesize = bb_getpagesize(); |
203 | #endif | 208 | #endif |
204 | 209 | ||
205 | /* Impossible: we do not use WUNTRACED flag in wait()... | 210 | /* Impossible: we do not use WUNTRACED flag in wait()... |
diff --git a/miscutils/ts.c b/miscutils/ts.c index f769d663b..3eecb7464 100644 --- a/miscutils/ts.c +++ b/miscutils/ts.c | |||
@@ -50,13 +50,13 @@ int ts_main(int argc UNUSED_PARAM, char **argv) | |||
50 | 50 | ||
51 | #define date_buf bb_common_bufsiz1 | 51 | #define date_buf bb_common_bufsiz1 |
52 | setup_common_bufsiz(); | 52 | setup_common_bufsiz(); |
53 | gettimeofday(&base, NULL); | 53 | xgettimeofday(&base); |
54 | 54 | ||
55 | while ((line = xmalloc_fgets(stdin)) != NULL) { | 55 | while ((line = xmalloc_fgets(stdin)) != NULL) { |
56 | struct timeval ts; | 56 | struct timeval ts; |
57 | struct tm tm_time; | 57 | struct tm tm_time; |
58 | 58 | ||
59 | gettimeofday(&ts, NULL); | 59 | xgettimeofday(&ts); |
60 | if (opt) { | 60 | if (opt) { |
61 | /* -i and/or -s */ | 61 | /* -i and/or -s */ |
62 | struct timeval ts1 = ts1; | 62 | struct timeval ts1 = ts1; |
diff --git a/miscutils/ubi_tools.c b/miscutils/ubi_tools.c index 94a637eee..69ead7a13 100644 --- a/miscutils/ubi_tools.c +++ b/miscutils/ubi_tools.c | |||
@@ -97,7 +97,7 @@ static unsigned get_num_from_file(const char *path, unsigned max) | |||
97 | int ubi_tools_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 97 | int ubi_tools_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
98 | int ubi_tools_main(int argc UNUSED_PARAM, char **argv) | 98 | int ubi_tools_main(int argc UNUSED_PARAM, char **argv) |
99 | { | 99 | { |
100 | static const struct suffix_mult size_suffixes[] = { | 100 | static const struct suffix_mult size_suffixes[] ALIGN_SUFFIX = { |
101 | { "KiB", 1024 }, | 101 | { "KiB", 1024 }, |
102 | { "MiB", 1024*1024 }, | 102 | { "MiB", 1024*1024 }, |
103 | { "GiB", 1024*1024*1024 }, | 103 | { "GiB", 1024*1024*1024 }, |
diff --git a/miscutils/watchdog.c b/miscutils/watchdog.c index 8c8d7217f..0ed10bcf1 100644 --- a/miscutils/watchdog.c +++ b/miscutils/watchdog.c | |||
@@ -88,7 +88,7 @@ int watchdog_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |||
88 | int watchdog_main(int argc UNUSED_PARAM, char **argv) | 88 | int watchdog_main(int argc UNUSED_PARAM, char **argv) |
89 | { | 89 | { |
90 | static const int enable = WDIOS_ENABLECARD; | 90 | static const int enable = WDIOS_ENABLECARD; |
91 | static const struct suffix_mult suffixes[] = { | 91 | static const struct suffix_mult suffixes[] ALIGN_SUFFIX = { |
92 | { "ms", 1 }, | 92 | { "ms", 1 }, |
93 | { "", 1000 }, | 93 | { "", 1000 }, |
94 | { "", 0 } | 94 | { "", 0 } |
@@ -143,7 +143,7 @@ int watchdog_main(int argc UNUSED_PARAM, char **argv) | |||
143 | * as the counter value is undefined at this point -- PFM | 143 | * as the counter value is undefined at this point -- PFM |
144 | */ | 144 | */ |
145 | write(3, "", 1); /* write zero byte */ | 145 | write(3, "", 1); /* write zero byte */ |
146 | usleep(stimer_duration * 1000L); | 146 | msleep(stimer_duration); |
147 | } | 147 | } |
148 | return EXIT_SUCCESS; /* - not reached, but gcc 4.2.1 is too dumb! */ | 148 | return EXIT_SUCCESS; /* - not reached, but gcc 4.2.1 is too dumb! */ |
149 | } | 149 | } |
diff --git a/modutils/insmod.c b/modutils/insmod.c index bd79a0f26..8f7163e25 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c | |||
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | //usage:#if !ENABLE_MODPROBE_SMALL | 27 | //usage:#if !ENABLE_MODPROBE_SMALL |
28 | //usage:#define insmod_trivial_usage | 28 | //usage:#define insmod_trivial_usage |
29 | //usage: IF_FEATURE_2_4_MODULES("[OPTIONS] MODULE") | 29 | //usage: IF_FEATURE_2_4_MODULES("[-fkvqLx] MODULE") |
30 | //usage: IF_NOT_FEATURE_2_4_MODULES("FILE") | 30 | //usage: IF_NOT_FEATURE_2_4_MODULES("FILE") |
31 | //usage: IF_FEATURE_CMDLINE_MODULE_OPTIONS(" [SYMBOL=VALUE]...") | 31 | //usage: IF_FEATURE_CMDLINE_MODULE_OPTIONS(" [SYMBOL=VALUE]...") |
32 | //usage:#define insmod_full_usage "\n\n" | 32 | //usage:#define insmod_full_usage "\n\n" |
diff --git a/modutils/modinfo.c b/modutils/modinfo.c index c5cdc7980..d15772f0d 100644 --- a/modutils/modinfo.c +++ b/modutils/modinfo.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include "libbb.h" | 20 | #include "libbb.h" |
21 | #include "modutils.h" | 21 | #include "modutils.h" |
22 | 22 | ||
23 | static const char *const shortcuts[] = { | 23 | static const char *const shortcuts[] ALIGN_PTR = { |
24 | "filename", // -n | 24 | "filename", // -n |
25 | "author", // -a | 25 | "author", // -a |
26 | "description", // -d | 26 | "description", // -d |
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 18cfac481..db44a2ed0 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c | |||
@@ -377,11 +377,11 @@ static int parse_module(module_info *info, const char *pathname) | |||
377 | return info->open_read_failed; | 377 | return info->open_read_failed; |
378 | } | 378 | } |
379 | 379 | ||
380 | static FAST_FUNC int fileAction(const char *pathname, | 380 | static FAST_FUNC int fileAction(struct recursive_state *state, |
381 | struct stat *sb UNUSED_PARAM, | 381 | const char *pathname, |
382 | void *modname_to_match, | 382 | struct stat *sb UNUSED_PARAM) |
383 | int depth UNUSED_PARAM) | ||
384 | { | 383 | { |
384 | const char *modname_to_match = state->userData; | ||
385 | int cur; | 385 | int cur; |
386 | const char *fname; | 386 | const char *fname; |
387 | bool is_remove = (ENABLE_RMMOD && ONLY_APPLET) | 387 | bool is_remove = (ENABLE_RMMOD && ONLY_APPLET) |
diff --git a/modutils/modprobe.c b/modutils/modprobe.c index eeeff7609..c334186b8 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c | |||
@@ -663,6 +663,25 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
663 | load_modules_dep(); | 663 | load_modules_dep(); |
664 | } | 664 | } |
665 | 665 | ||
666 | /* Handle modprobe.blacklist=module1,module2,... */ | ||
667 | if (ENABLE_FEATURE_MODPROBE_BLACKLIST) { | ||
668 | char *options; | ||
669 | char *substr; | ||
670 | |||
671 | options = parse_and_add_kcmdline_module_options(NULL, "modprobe"); | ||
672 | while ((substr = strsep(&options, " ")) != NULL) { | ||
673 | char *fn = is_prefixed_with(substr, "blacklist="); | ||
674 | if (!fn) | ||
675 | continue; | ||
676 | while ((substr = strsep(&fn, ",")) != NULL) { | ||
677 | /* blacklist <modulename> */ | ||
678 | get_or_add_modentry(substr)->flags |= MODULE_FLAG_BLACKLISTED; | ||
679 | DBG("blacklist: %s", substr); | ||
680 | } | ||
681 | } | ||
682 | /*free(options); - WRONG, strsep may have advanced it */ | ||
683 | } | ||
684 | |||
666 | rc = 0; | 685 | rc = 0; |
667 | while ((me = llist_pop(&G.probes)) != NULL) { | 686 | while ((me = llist_pop(&G.probes)) != NULL) { |
668 | if (me->realnames == NULL) { | 687 | if (me->realnames == NULL) { |
diff --git a/modutils/modutils.c b/modutils/modutils.c index 6f7cd9721..f7ad5e805 100644 --- a/modutils/modutils.c +++ b/modutils/modutils.c | |||
@@ -169,7 +169,7 @@ void* FAST_FUNC try_to_mmap_module(const char *filename, size_t *image_size_p) | |||
169 | /* st.st_size is off_t, we can't just pass it to mmap */ | 169 | /* st.st_size is off_t, we can't just pass it to mmap */ |
170 | if (st.st_size <= *image_size_p) { | 170 | if (st.st_size <= *image_size_p) { |
171 | size_t image_size = st.st_size; | 171 | size_t image_size = st.st_size; |
172 | image = mmap(NULL, image_size, PROT_READ, MAP_PRIVATE, fd, 0); | 172 | image = mmap_read(fd, image_size); |
173 | if (image == MAP_FAILED) { | 173 | if (image == MAP_FAILED) { |
174 | image = NULL; | 174 | image = NULL; |
175 | } else if (*(uint32_t*)image != SWAP_BE32(0x7f454C46)) { | 175 | } else if (*(uint32_t*)image != SWAP_BE32(0x7f454C46)) { |
diff --git a/networking/ftpgetput.c b/networking/ftpgetput.c index 7b6b89057..f1d5ca571 100644 --- a/networking/ftpgetput.c +++ b/networking/ftpgetput.c | |||
@@ -43,7 +43,7 @@ | |||
43 | //usage: "\n -v Verbose" | 43 | //usage: "\n -v Verbose" |
44 | //usage: "\n -u USER Username" | 44 | //usage: "\n -u USER Username" |
45 | //usage: "\n -p PASS Password" | 45 | //usage: "\n -p PASS Password" |
46 | //usage: "\n -P NUM Port" | 46 | //usage: "\n -P PORT" |
47 | //usage: | 47 | //usage: |
48 | //usage:#define ftpput_trivial_usage | 48 | //usage:#define ftpput_trivial_usage |
49 | //usage: "[OPTIONS] HOST [REMOTE_FILE] LOCAL_FILE" | 49 | //usage: "[OPTIONS] HOST [REMOTE_FILE] LOCAL_FILE" |
@@ -52,7 +52,7 @@ | |||
52 | //usage: "\n -v Verbose" | 52 | //usage: "\n -v Verbose" |
53 | //usage: "\n -u USER Username" | 53 | //usage: "\n -u USER Username" |
54 | //usage: "\n -p PASS Password" | 54 | //usage: "\n -p PASS Password" |
55 | //usage: "\n -P NUM Port number" | 55 | //usage: "\n -P PORT" |
56 | 56 | ||
57 | #include "libbb.h" | 57 | #include "libbb.h" |
58 | #include "common_bufsiz.h" | 58 | #include "common_bufsiz.h" |
diff --git a/networking/hostname.c b/networking/hostname.c index f96daed95..549103485 100644 --- a/networking/hostname.c +++ b/networking/hostname.c | |||
@@ -29,9 +29,9 @@ | |||
29 | //kbuild: lib-$(CONFIG_DNSDOMAINNAME) += hostname.o | 29 | //kbuild: lib-$(CONFIG_DNSDOMAINNAME) += hostname.o |
30 | 30 | ||
31 | //usage:#define hostname_trivial_usage | 31 | //usage:#define hostname_trivial_usage |
32 | //usage: "[OPTIONS] [HOSTNAME | -F FILE]" | 32 | //usage: "[-sidf] [HOSTNAME | -F FILE]" |
33 | //usage:#define hostname_full_usage "\n\n" | 33 | //usage:#define hostname_full_usage "\n\n" |
34 | //usage: "Get or set hostname or DNS domain name\n" | 34 | //usage: "Show or set hostname or DNS domain name\n" |
35 | //usage: "\n -s Short" | 35 | //usage: "\n -s Short" |
36 | //usage: "\n -i Addresses for the hostname" | 36 | //usage: "\n -i Addresses for the hostname" |
37 | //usage: "\n -d DNS domain name" | 37 | //usage: "\n -d DNS domain name" |
diff --git a/networking/httpd.c b/networking/httpd.c index daa3ca1d0..02f544593 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -305,6 +305,11 @@ | |||
305 | # include <sys/sendfile.h> | 305 | # include <sys/sendfile.h> |
306 | #endif | 306 | #endif |
307 | 307 | ||
308 | /* see sys/netinet6/in6.h */ | ||
309 | #if defined(__FreeBSD__) | ||
310 | # define s6_addr32 __u6_addr.__u6_addr32 | ||
311 | #endif | ||
312 | |||
308 | #define DEBUG 0 | 313 | #define DEBUG 0 |
309 | 314 | ||
310 | #define IOBUF_SIZE 8192 | 315 | #define IOBUF_SIZE 8192 |
@@ -1036,48 +1041,9 @@ static char *encodeString(const char *string) | |||
1036 | * Parameter: a pointer to a base64 encoded string. | 1041 | * Parameter: a pointer to a base64 encoded string. |
1037 | * Decoded data is stored in-place. | 1042 | * Decoded data is stored in-place. |
1038 | */ | 1043 | */ |
1039 | static void decodeBase64(char *Data) | 1044 | static void decodeBase64(char *data) |
1040 | { | 1045 | { |
1041 | # if ENABLE_BASE64 || ENABLE_UUDECODE | 1046 | decode_base64(data, NULL)[0] = '\0'; |
1042 | /* Call decode_base64() from uuencode.c */ | ||
1043 | char *eptr = Data; | ||
1044 | decode_base64(&eptr, Data); | ||
1045 | *eptr = '\0'; | ||
1046 | # else | ||
1047 | const unsigned char *in = (const unsigned char *)Data; | ||
1048 | /* The decoded size will be at most 3/4 the size of the encoded */ | ||
1049 | unsigned ch = 0; | ||
1050 | int i = 0; | ||
1051 | |||
1052 | while (*in) { | ||
1053 | int t = *in++; | ||
1054 | |||
1055 | if (t >= '0' && t <= '9') | ||
1056 | t = t - '0' + 52; | ||
1057 | else if (t >= 'A' && t <= 'Z') | ||
1058 | t = t - 'A'; | ||
1059 | else if (t >= 'a' && t <= 'z') | ||
1060 | t = t - 'a' + 26; | ||
1061 | else if (t == '+') | ||
1062 | t = 62; | ||
1063 | else if (t == '/') | ||
1064 | t = 63; | ||
1065 | else if (t == '=') | ||
1066 | t = 0; | ||
1067 | else | ||
1068 | continue; | ||
1069 | |||
1070 | ch = (ch << 6) | t; | ||
1071 | i++; | ||
1072 | if (i == 4) { | ||
1073 | *Data++ = (char) (ch >> 16); | ||
1074 | *Data++ = (char) (ch >> 8); | ||
1075 | *Data++ = (char) ch; | ||
1076 | i = 0; | ||
1077 | } | ||
1078 | } | ||
1079 | *Data = '\0'; | ||
1080 | # endif | ||
1081 | } | 1047 | } |
1082 | #endif | 1048 | #endif |
1083 | 1049 | ||
@@ -1945,7 +1911,7 @@ static NOINLINE void send_file_and_exit(const char *url, int what) | |||
1945 | send_headers(HTTP_OK); | 1911 | send_headers(HTTP_OK); |
1946 | #if ENABLE_FEATURE_USE_SENDFILE | 1912 | #if ENABLE_FEATURE_USE_SENDFILE |
1947 | { | 1913 | { |
1948 | off_t offset = range_start; | 1914 | off_t offset = (range_start < 0) ? 0 : range_start; |
1949 | while (1) { | 1915 | while (1) { |
1950 | /* sz is rounded down to 64k */ | 1916 | /* sz is rounded down to 64k */ |
1951 | ssize_t sz = MAXINT(ssize_t) - 0xffff; | 1917 | ssize_t sz = MAXINT(ssize_t) - 0xffff; |
@@ -2590,8 +2556,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2590 | if (STRNCASECMP(iobuf, "Range:") == 0) { | 2556 | if (STRNCASECMP(iobuf, "Range:") == 0) { |
2591 | /* We know only bytes=NNN-[MMM] */ | 2557 | /* We know only bytes=NNN-[MMM] */ |
2592 | char *s = skip_whitespace(iobuf + sizeof("Range:")-1); | 2558 | char *s = skip_whitespace(iobuf + sizeof("Range:")-1); |
2593 | if (is_prefixed_with(s, "bytes=")) { | 2559 | s = is_prefixed_with(s, "bytes="); |
2594 | s += sizeof("bytes=")-1; | 2560 | if (s) { |
2595 | range_start = BB_STRTOOFF(s, &s, 10); | 2561 | range_start = BB_STRTOOFF(s, &s, 10); |
2596 | if (s[0] != '-' || range_start < 0) { | 2562 | if (s[0] != '-' || range_start < 0) { |
2597 | range_start = -1; | 2563 | range_start = -1; |
diff --git a/networking/ifconfig.c b/networking/ifconfig.c index 3c9a2dfb3..9ee232a66 100644 --- a/networking/ifconfig.c +++ b/networking/ifconfig.c | |||
@@ -76,7 +76,7 @@ | |||
76 | //kbuild:lib-$(CONFIG_IFCONFIG) += ifconfig.o interface.o | 76 | //kbuild:lib-$(CONFIG_IFCONFIG) += ifconfig.o interface.o |
77 | 77 | ||
78 | //usage:#define ifconfig_trivial_usage | 78 | //usage:#define ifconfig_trivial_usage |
79 | //usage: IF_FEATURE_IFCONFIG_STATUS("[-a]") " interface [address]" | 79 | //usage: IF_FEATURE_IFCONFIG_STATUS("[-a]") " [IFACE] [ADDRESS]" |
80 | //usage:#define ifconfig_full_usage "\n\n" | 80 | //usage:#define ifconfig_full_usage "\n\n" |
81 | //usage: "Configure a network interface\n" | 81 | //usage: "Configure a network interface\n" |
82 | //usage: "\n" | 82 | //usage: "\n" |
@@ -247,7 +247,7 @@ struct options { | |||
247 | * Set up the tables. Warning! They must have corresponding order! | 247 | * Set up the tables. Warning! They must have corresponding order! |
248 | */ | 248 | */ |
249 | 249 | ||
250 | static const struct arg1opt Arg1Opt[] = { | 250 | static const struct arg1opt Arg1Opt[] ALIGN_PTR = { |
251 | { "SIFMETRIC", SIOCSIFMETRIC, ifreq_offsetof(ifr_metric) }, | 251 | { "SIFMETRIC", SIOCSIFMETRIC, ifreq_offsetof(ifr_metric) }, |
252 | { "SIFMTU", SIOCSIFMTU, ifreq_offsetof(ifr_mtu) }, | 252 | { "SIFMTU", SIOCSIFMTU, ifreq_offsetof(ifr_mtu) }, |
253 | { "SIFTXQLEN", SIOCSIFTXQLEN, ifreq_offsetof(ifr_qlen) }, | 253 | { "SIFTXQLEN", SIOCSIFTXQLEN, ifreq_offsetof(ifr_qlen) }, |
@@ -277,7 +277,7 @@ static const struct arg1opt Arg1Opt[] = { | |||
277 | { "SIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr) }, | 277 | { "SIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr) }, |
278 | }; | 278 | }; |
279 | 279 | ||
280 | static const struct options OptArray[] = { | 280 | static const struct options OptArray[] ALIGN_PTR = { |
281 | { "metric", N_ARG, ARG_METRIC, 0 }, | 281 | { "metric", N_ARG, ARG_METRIC, 0 }, |
282 | { "mtu", N_ARG, ARG_MTU, 0 }, | 282 | { "mtu", N_ARG, ARG_MTU, 0 }, |
283 | { "txqueuelen", N_ARG, ARG_TXQUEUELEN, 0 }, | 283 | { "txqueuelen", N_ARG, ARG_TXQUEUELEN, 0 }, |
diff --git a/networking/ifplugd.c b/networking/ifplugd.c index 0d17b7d8c..18dcaff96 100644 --- a/networking/ifplugd.c +++ b/networking/ifplugd.c | |||
@@ -304,7 +304,7 @@ static const char api_modes[] ALIGN1 = "empwia"; | |||
304 | static const struct { | 304 | static const struct { |
305 | const char *name; | 305 | const char *name; |
306 | smallint (*func)(void); | 306 | smallint (*func)(void); |
307 | } method_table[] = { | 307 | } method_table[] ALIGN_PTR = { |
308 | { "SIOCETHTOOL" , &detect_link_ethtool }, | 308 | { "SIOCETHTOOL" , &detect_link_ethtool }, |
309 | { "SIOCGMIIPHY" , &detect_link_mii }, | 309 | { "SIOCGMIIPHY" , &detect_link_mii }, |
310 | { "SIOCDEVPRIVATE" , &detect_link_priv }, | 310 | { "SIOCDEVPRIVATE" , &detect_link_priv }, |
@@ -735,7 +735,7 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv) | |||
735 | delay_time += G.delay_down; | 735 | delay_time += G.delay_down; |
736 | #if 0 /* if you are back in 1970... */ | 736 | #if 0 /* if you are back in 1970... */ |
737 | if (delay_time == 0) { | 737 | if (delay_time == 0) { |
738 | sleep(1); | 738 | sleep1(); |
739 | delay_time = 1; | 739 | delay_time = 1; |
740 | } | 740 | } |
741 | #endif | 741 | #endif |
diff --git a/networking/ifupdown.c b/networking/ifupdown.c index 60ceb5a1f..737113dd4 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c | |||
@@ -113,30 +113,30 @@ | |||
113 | //kbuild:lib-$(CONFIG_IFDOWN) += ifupdown.o | 113 | //kbuild:lib-$(CONFIG_IFDOWN) += ifupdown.o |
114 | 114 | ||
115 | //usage:#define ifup_trivial_usage | 115 | //usage:#define ifup_trivial_usage |
116 | //usage: "[-an"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] [-i FILE] IFACE..." | 116 | //usage: "[-n"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] [-i FILE] -a | IFACE..." |
117 | //usage:#define ifup_full_usage "\n\n" | 117 | //usage:#define ifup_full_usage "\n\n" |
118 | //usage: " -a Configure all interfaces" | 118 | //usage: " -a Configure all interfaces" |
119 | //usage: "\n -i FILE Use FILE instead of /etc/network/interfaces" | 119 | //usage: "\n -i FILE Use FILE instead of /etc/network/interfaces" |
120 | //usage: "\n -n Print out what would happen, but don't do it" | 120 | //usage: "\n -n Dry run" |
121 | //usage: IF_FEATURE_IFUPDOWN_MAPPING( | 121 | //usage: IF_FEATURE_IFUPDOWN_MAPPING( |
122 | //usage: "\n (note: doesn't disable mappings)" | 122 | //usage: "\n (note: doesn't disable mappings)" |
123 | //usage: "\n -m Don't run any mappings" | 123 | //usage: "\n -m Don't run any mappings" |
124 | //usage: ) | 124 | //usage: ) |
125 | //usage: "\n -v Print out what would happen before doing it" | 125 | //usage: "\n -v Print out what would happen before doing it" |
126 | //usage: "\n -f Force configuration" | 126 | //usage: "\n -f Force" |
127 | //usage: | 127 | //usage: |
128 | //usage:#define ifdown_trivial_usage | 128 | //usage:#define ifdown_trivial_usage |
129 | //usage: "[-an"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] [-i FILE] IFACE..." | 129 | //usage: "[-n"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] [-i FILE] -a | IFACE..." |
130 | //usage:#define ifdown_full_usage "\n\n" | 130 | //usage:#define ifdown_full_usage "\n\n" |
131 | //usage: " -a Deconfigure all interfaces" | 131 | //usage: " -a Deconfigure all interfaces" |
132 | //usage: "\n -i FILE Use FILE for interface definitions" | 132 | //usage: "\n -i FILE Use FILE instead of /etc/network/interfaces" |
133 | //usage: "\n -n Print out what would happen, but don't do it" | 133 | //usage: "\n -n Dry run" |
134 | //usage: IF_FEATURE_IFUPDOWN_MAPPING( | 134 | //usage: IF_FEATURE_IFUPDOWN_MAPPING( |
135 | //usage: "\n (note: doesn't disable mappings)" | 135 | //usage: "\n (note: doesn't disable mappings)" |
136 | //usage: "\n -m Don't run any mappings" | 136 | //usage: "\n -m Don't run any mappings" |
137 | //usage: ) | 137 | //usage: ) |
138 | //usage: "\n -v Print out what would happen before doing it" | 138 | //usage: "\n -v Print out what would happen before doing it" |
139 | //usage: "\n -f Force deconfiguration" | 139 | //usage: "\n -f Force" |
140 | 140 | ||
141 | #include <net/if.h> | 141 | #include <net/if.h> |
142 | #include "libbb.h" | 142 | #include "libbb.h" |
@@ -1357,15 +1357,15 @@ static FILE *open_new_state_file(void) | |||
1357 | IFSTATE_FILE_PATH".new"); | 1357 | IFSTATE_FILE_PATH".new"); |
1358 | } | 1358 | } |
1359 | /* Someone else created the .new file */ | 1359 | /* Someone else created the .new file */ |
1360 | if (cnt > 30 * 1000) { | 1360 | if (cnt > 30) { |
1361 | /* Waited for 30*30/2 = 450 milliseconds, still EEXIST. | 1361 | /* Waited for 30*30/2 = 450 milliseconds, still EEXIST. |
1362 | * Assuming a stale file, rewriting it. | 1362 | * Assuming a stale file, rewriting it. |
1363 | */ | 1363 | */ |
1364 | flags = (O_WRONLY | O_CREAT | O_TRUNC); | 1364 | flags = (O_WRONLY | O_CREAT | O_TRUNC); |
1365 | continue; | 1365 | continue; |
1366 | } | 1366 | } |
1367 | usleep(cnt); | 1367 | msleep(cnt); |
1368 | cnt += 1000; | 1368 | cnt++; |
1369 | } | 1369 | } |
1370 | 1370 | ||
1371 | return xfdopen_for_write(fd); | 1371 | return xfdopen_for_write(fd); |
diff --git a/networking/inetd.c b/networking/inetd.c index 3cd2b11f0..febfb7b73 100644 --- a/networking/inetd.c +++ b/networking/inetd.c | |||
@@ -361,7 +361,7 @@ struct builtin { | |||
361 | void (*bi_dgram_fn)(int, servtab_t *) FAST_FUNC; | 361 | void (*bi_dgram_fn)(int, servtab_t *) FAST_FUNC; |
362 | }; | 362 | }; |
363 | 363 | ||
364 | static const struct builtin builtins[] = { | 364 | static const struct builtin builtins[] ALIGN_PTR = { |
365 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO | 365 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO |
366 | { "echo", 1, echo_stream, echo_dg }, | 366 | { "echo", 1, echo_stream, echo_dg }, |
367 | #endif | 367 | #endif |
@@ -1305,7 +1305,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv) | |||
1305 | if (ready_fd_cnt < 0) { | 1305 | if (ready_fd_cnt < 0) { |
1306 | if (errno != EINTR) { | 1306 | if (errno != EINTR) { |
1307 | bb_simple_perror_msg("select"); | 1307 | bb_simple_perror_msg("select"); |
1308 | sleep(1); | 1308 | sleep1(); |
1309 | } | 1309 | } |
1310 | continue; | 1310 | continue; |
1311 | } | 1311 | } |
@@ -1406,7 +1406,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv) | |||
1406 | 1406 | ||
1407 | if (pid < 0) { /* fork error */ | 1407 | if (pid < 0) { /* fork error */ |
1408 | bb_simple_perror_msg("vfork"+1); | 1408 | bb_simple_perror_msg("vfork"+1); |
1409 | sleep(1); | 1409 | sleep1(); |
1410 | restore_sigmask(&omask); | 1410 | restore_sigmask(&omask); |
1411 | maybe_close(new_udp_fd); | 1411 | maybe_close(new_udp_fd); |
1412 | maybe_close(accepted_fd); | 1412 | maybe_close(accepted_fd); |
@@ -1701,7 +1701,7 @@ static uint32_t machtime(void) | |||
1701 | { | 1701 | { |
1702 | struct timeval tv; | 1702 | struct timeval tv; |
1703 | 1703 | ||
1704 | gettimeofday(&tv, NULL); | 1704 | xgettimeofday(&tv); |
1705 | return htonl((uint32_t)(tv.tv_sec + 2208988800U)); | 1705 | return htonl((uint32_t)(tv.tv_sec + 2208988800U)); |
1706 | } | 1706 | } |
1707 | /* ARGSUSED */ | 1707 | /* ARGSUSED */ |
diff --git a/networking/interface.c b/networking/interface.c index e5e55d8d4..ea6a2c8a8 100644 --- a/networking/interface.c +++ b/networking/interface.c | |||
@@ -746,7 +746,7 @@ static const struct hwtype *const hwtypes[] = { | |||
746 | }; | 746 | }; |
747 | 747 | ||
748 | #ifdef IFF_PORTSEL | 748 | #ifdef IFF_PORTSEL |
749 | static const char *const if_port_text[] = { | 749 | static const char *const if_port_text[] ALIGN_PTR = { |
750 | /* Keep in step with <linux/netdevice.h> */ | 750 | /* Keep in step with <linux/netdevice.h> */ |
751 | "unknown", | 751 | "unknown", |
752 | "10base2", | 752 | "10base2", |
diff --git a/networking/ip.c b/networking/ip.c index 33bea5f49..85b1ba080 100644 --- a/networking/ip.c +++ b/networking/ip.c | |||
@@ -400,7 +400,7 @@ int ip_main(int argc UNUSED_PARAM, char **argv) | |||
400 | IF_FEATURE_IP_RULE("rule\0") | 400 | IF_FEATURE_IP_RULE("rule\0") |
401 | IF_FEATURE_IP_NEIGH("neigh\0") | 401 | IF_FEATURE_IP_NEIGH("neigh\0") |
402 | ; | 402 | ; |
403 | static const ip_func_ptr_t ip_func_ptrs[] = { | 403 | static const ip_func_ptr_t ip_func_ptrs[] ALIGN_PTR = { |
404 | ip_print_help, | 404 | ip_print_help, |
405 | IF_FEATURE_IP_ADDRESS(do_ipaddr,) | 405 | IF_FEATURE_IP_ADDRESS(do_ipaddr,) |
406 | IF_FEATURE_IP_ROUTE(do_iproute,) | 406 | IF_FEATURE_IP_ROUTE(do_iproute,) |
diff --git a/networking/ipcalc.c b/networking/ipcalc.c index 09b146872..e82e35dd5 100644 --- a/networking/ipcalc.c +++ b/networking/ipcalc.c | |||
@@ -36,7 +36,7 @@ | |||
36 | //kbuild:lib-$(CONFIG_IPCALC) += ipcalc.o | 36 | //kbuild:lib-$(CONFIG_IPCALC) += ipcalc.o |
37 | 37 | ||
38 | //usage:#define ipcalc_trivial_usage | 38 | //usage:#define ipcalc_trivial_usage |
39 | //usage: "[OPTIONS] ADDRESS" | 39 | //usage: "[-bnm"IF_FEATURE_IPCALC_FANCY("phs")"] ADDRESS" |
40 | //usage: IF_FEATURE_IPCALC_FANCY("[/PREFIX]") " [NETMASK]" | 40 | //usage: IF_FEATURE_IPCALC_FANCY("[/PREFIX]") " [NETMASK]" |
41 | //usage:#define ipcalc_full_usage "\n\n" | 41 | //usage:#define ipcalc_full_usage "\n\n" |
42 | //usage: "Calculate and display network settings from IP address\n" | 42 | //usage: "Calculate and display network settings from IP address\n" |
diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c index 71e8fb6a7..dfd84c000 100644 --- a/networking/libiproute/ipaddress.c +++ b/networking/libiproute/ipaddress.c | |||
@@ -21,6 +21,17 @@ | |||
21 | #define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ | 21 | #define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ |
22 | #endif | 22 | #endif |
23 | 23 | ||
24 | /* for old uclibc */ | ||
25 | #ifndef IFA_F_NOPREFIXROUTE | ||
26 | # define IFA_FLAGS 8 | ||
27 | # define IFA_F_NOPREFIXROUTE 0x200 | ||
28 | enum { /* can't do this with preporcessor, IFA_MAX is an (enum - 1), not preprocessor constant */ | ||
29 | REAL_IFA_MAX = (IFA_MAX >= IFA_FLAGS) ? IFA_MAX : IFA_FLAGS, | ||
30 | }; | ||
31 | # undef IFA_MAX | ||
32 | # define IFA_MAX REAL_IFA_MAX | ||
33 | #endif | ||
34 | |||
24 | struct filter_t { | 35 | struct filter_t { |
25 | char *label; | 36 | char *label; |
26 | /* Flush cmd buf. If !NULL, print_addrinfo() constructs flush commands in it */ | 37 | /* Flush cmd buf. If !NULL, print_addrinfo() constructs flush commands in it */ |
diff --git a/networking/libiproute/rt_names.c b/networking/libiproute/rt_names.c index 51f2e9bdb..3c2fad912 100644 --- a/networking/libiproute/rt_names.c +++ b/networking/libiproute/rt_names.c | |||
@@ -77,7 +77,7 @@ static rtnl_tab_t *rtnl_rtprot_tab; | |||
77 | 77 | ||
78 | static void rtnl_rtprot_initialize(void) | 78 | static void rtnl_rtprot_initialize(void) |
79 | { | 79 | { |
80 | static const char *const init_tab[] = { | 80 | static const char *const init_tab[] ALIGN_PTR = { |
81 | "none", | 81 | "none", |
82 | "redirect", | 82 | "redirect", |
83 | "kernel", | 83 | "kernel", |
diff --git a/networking/libiproute/rtm_map.c b/networking/libiproute/rtm_map.c index e94c99ab6..8b94c2f24 100644 --- a/networking/libiproute/rtm_map.c +++ b/networking/libiproute/rtm_map.c | |||
@@ -11,33 +11,55 @@ | |||
11 | #include "rt_names.h" | 11 | #include "rt_names.h" |
12 | #include "utils.h" | 12 | #include "utils.h" |
13 | 13 | ||
14 | static const char keywords[] ALIGN1 = | ||
15 | "local\0""nat\0""broadcast\0""brd\0""anycast\0" | ||
16 | "multicast\0""prohibit\0""unreachable\0""blackhole\0" | ||
17 | "xresolve\0""unicast\0""throw\0"; | ||
18 | enum { | ||
19 | ARG_local = 1, ARG_nat, ARG_broadcast, ARG_brd, ARG_anycast, | ||
20 | ARG_multicast, ARG_prohibit, ARG_unreachable, ARG_blackhole, | ||
21 | ARG_xresolve, ARG_unicast, ARG_throw | ||
22 | }; | ||
23 | #define str_local keywords | ||
24 | #define str_nat (str_local + sizeof("local")) | ||
25 | #define str_broadcast (str_nat + sizeof("nat")) | ||
26 | #define str_brd (str_broadcast + sizeof("broadcast")) | ||
27 | #define str_anycast (str_brd + sizeof("brd")) | ||
28 | #define str_multicast (str_anycast + sizeof("anycast")) | ||
29 | #define str_prohibit (str_multicast + sizeof("multicast")) | ||
30 | #define str_unreachable (str_prohibit + sizeof("prohibit")) | ||
31 | #define str_blackhole (str_unreachable + sizeof("unreachable")) | ||
32 | #define str_xresolve (str_blackhole + sizeof("blackhole")) | ||
33 | #define str_unicast (str_xresolve + sizeof("xresolve")) | ||
34 | #define str_throw (str_unicast + sizeof("unicast")) | ||
35 | |||
14 | const char* FAST_FUNC rtnl_rtntype_n2a(int id) | 36 | const char* FAST_FUNC rtnl_rtntype_n2a(int id) |
15 | { | 37 | { |
16 | switch (id) { | 38 | switch (id) { |
17 | case RTN_UNSPEC: | 39 | case RTN_UNSPEC: |
18 | return "none"; | 40 | return "none"; |
19 | case RTN_UNICAST: | 41 | case RTN_UNICAST: |
20 | return "unicast"; | 42 | return str_unicast; |
21 | case RTN_LOCAL: | 43 | case RTN_LOCAL: |
22 | return "local"; | 44 | return str_local; |
23 | case RTN_BROADCAST: | 45 | case RTN_BROADCAST: |
24 | return "broadcast"; | 46 | return str_broadcast; |
25 | case RTN_ANYCAST: | 47 | case RTN_ANYCAST: |
26 | return "anycast"; | 48 | return str_anycast; |
27 | case RTN_MULTICAST: | 49 | case RTN_MULTICAST: |
28 | return "multicast"; | 50 | return str_multicast; |
29 | case RTN_BLACKHOLE: | 51 | case RTN_BLACKHOLE: |
30 | return "blackhole"; | 52 | return str_blackhole; |
31 | case RTN_UNREACHABLE: | 53 | case RTN_UNREACHABLE: |
32 | return "unreachable"; | 54 | return str_unreachable; |
33 | case RTN_PROHIBIT: | 55 | case RTN_PROHIBIT: |
34 | return "prohibit"; | 56 | return str_prohibit; |
35 | case RTN_THROW: | 57 | case RTN_THROW: |
36 | return "throw"; | 58 | return str_throw; |
37 | case RTN_NAT: | 59 | case RTN_NAT: |
38 | return "nat"; | 60 | return str_nat; |
39 | case RTN_XRESOLVE: | 61 | case RTN_XRESOLVE: |
40 | return "xresolve"; | 62 | return str_xresolve; |
41 | default: | 63 | default: |
42 | return itoa(id); | 64 | return itoa(id); |
43 | } | 65 | } |
@@ -45,15 +67,6 @@ const char* FAST_FUNC rtnl_rtntype_n2a(int id) | |||
45 | 67 | ||
46 | int FAST_FUNC rtnl_rtntype_a2n(int *id, char *arg) | 68 | int FAST_FUNC rtnl_rtntype_a2n(int *id, char *arg) |
47 | { | 69 | { |
48 | static const char keywords[] ALIGN1 = | ||
49 | "local\0""nat\0""broadcast\0""brd\0""anycast\0" | ||
50 | "multicast\0""prohibit\0""unreachable\0""blackhole\0" | ||
51 | "xresolve\0""unicast\0""throw\0"; | ||
52 | enum { | ||
53 | ARG_local = 1, ARG_nat, ARG_broadcast, ARG_brd, ARG_anycast, | ||
54 | ARG_multicast, ARG_prohibit, ARG_unreachable, ARG_blackhole, | ||
55 | ARG_xresolve, ARG_unicast, ARG_throw | ||
56 | }; | ||
57 | const smalluint key = index_in_substrings(keywords, arg) + 1; | 70 | const smalluint key = index_in_substrings(keywords, arg) + 1; |
58 | char *end; | 71 | char *end; |
59 | unsigned long res; | 72 | unsigned long res; |
diff --git a/networking/nbd-client.c b/networking/nbd-client.c index 3db3b46f9..755b42ccd 100644 --- a/networking/nbd-client.c +++ b/networking/nbd-client.c | |||
@@ -270,7 +270,7 @@ int nbdclient_main(int argc, char **argv) | |||
270 | close(fd); | 270 | close(fd); |
271 | break; | 271 | break; |
272 | } | 272 | } |
273 | sleep(1); | 273 | sleep1(); |
274 | } | 274 | } |
275 | open(device, O_RDONLY); | 275 | open(device, O_RDONLY); |
276 | return 0; | 276 | return 0; |
diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c index 88eda6b28..25b95246f 100644 --- a/networking/nc_bloaty.c +++ b/networking/nc_bloaty.c | |||
@@ -196,7 +196,7 @@ enum { | |||
196 | /* Debug: squirt whatever message and sleep a bit so we can see it go by. */ | 196 | /* Debug: squirt whatever message and sleep a bit so we can see it go by. */ |
197 | /* Beware: writes to stdOUT... */ | 197 | /* Beware: writes to stdOUT... */ |
198 | #if 0 | 198 | #if 0 |
199 | #define Debug(...) do { printf(__VA_ARGS__); printf("\n"); fflush_all(); sleep(1); } while (0) | 199 | #define Debug(...) do { printf(__VA_ARGS__); printf("\n"); fflush_all(); sleep1(); } while (0) |
200 | #else | 200 | #else |
201 | #define Debug(...) do { } while (0) | 201 | #define Debug(...) do { } while (0) |
202 | #endif | 202 | #endif |
diff --git a/networking/netstat.c b/networking/netstat.c index 3ab7b0d21..807800a62 100644 --- a/networking/netstat.c +++ b/networking/netstat.c | |||
@@ -114,7 +114,7 @@ enum { | |||
114 | TCP_CLOSING, /* now a valid state */ | 114 | TCP_CLOSING, /* now a valid state */ |
115 | }; | 115 | }; |
116 | 116 | ||
117 | static const char *const tcp_state[] = { | 117 | static const char *const tcp_state[] ALIGN_PTR = { |
118 | "", | 118 | "", |
119 | "ESTABLISHED", | 119 | "ESTABLISHED", |
120 | "SYN_SENT", | 120 | "SYN_SENT", |
diff --git a/networking/nslookup.c b/networking/nslookup.c index 759de5c83..c43ad46f3 100644 --- a/networking/nslookup.c +++ b/networking/nslookup.c | |||
@@ -273,7 +273,7 @@ struct query { | |||
273 | static const struct { | 273 | static const struct { |
274 | unsigned char type; | 274 | unsigned char type; |
275 | char name[7]; | 275 | char name[7]; |
276 | } qtypes[] = { | 276 | } qtypes[] ALIGN1 = { |
277 | { ns_t_soa, "SOA" }, | 277 | { ns_t_soa, "SOA" }, |
278 | { ns_t_ns, "NS" }, | 278 | { ns_t_ns, "NS" }, |
279 | { ns_t_a, "A" }, | 279 | { ns_t_a, "A" }, |
@@ -288,7 +288,7 @@ static const struct { | |||
288 | { ns_t_any, "ANY" }, | 288 | { ns_t_any, "ANY" }, |
289 | }; | 289 | }; |
290 | 290 | ||
291 | static const char *const rcodes[] = { | 291 | static const char *const rcodes[] ALIGN_PTR = { |
292 | "NOERROR", // 0 | 292 | "NOERROR", // 0 |
293 | "FORMERR", // 1 | 293 | "FORMERR", // 1 |
294 | "SERVFAIL", // 2 | 294 | "SERVFAIL", // 2 |
@@ -349,6 +349,8 @@ static int parse_reply(const unsigned char *msg, size_t len) | |||
349 | header = (HEADER *)msg; | 349 | header = (HEADER *)msg; |
350 | if (!header->aa) | 350 | if (!header->aa) |
351 | printf("Non-authoritative answer:\n"); | 351 | printf("Non-authoritative answer:\n"); |
352 | else if (option_mask32 & OPT_debug) | ||
353 | printf("Non-authoritative answer:\n" + 4); | ||
352 | 354 | ||
353 | if (ns_initparse(msg, len, &handle) != 0) { | 355 | if (ns_initparse(msg, len, &handle) != 0) { |
354 | //printf("Unable to parse reply: %s\n", strerror(errno)); | 356 | //printf("Unable to parse reply: %s\n", strerror(errno)); |
@@ -381,7 +383,7 @@ static int parse_reply(const unsigned char *msg, size_t len) | |||
381 | return -1; | 383 | return -1; |
382 | } | 384 | } |
383 | inet_ntop(AF_INET6, ns_rr_rdata(rr), astr, sizeof(astr)); | 385 | inet_ntop(AF_INET6, ns_rr_rdata(rr), astr, sizeof(astr)); |
384 | /* bind-utils-9.11.3 uses the same format for A and AAAA answers */ | 386 | /* bind-utils 9.11.3 uses the same format for A and AAAA answers */ |
385 | printf("Name:\t%s\nAddress: %s\n", ns_rr_name(rr), astr); | 387 | printf("Name:\t%s\nAddress: %s\n", ns_rr_name(rr), astr); |
386 | break; | 388 | break; |
387 | #endif | 389 | #endif |
@@ -580,7 +582,7 @@ static int send_queries(struct ns *ns) | |||
580 | printf("Address:\t%s\n\n", | 582 | printf("Address:\t%s\n\n", |
581 | auto_string(xmalloc_sockaddr2dotted(&ns->lsa->u.sa)) | 583 | auto_string(xmalloc_sockaddr2dotted(&ns->lsa->u.sa)) |
582 | ); | 584 | ); |
583 | /* In "Address", bind-utils-9.11.3 show port after a hash: "1.2.3.4#53" */ | 585 | /* In "Address", bind-utils 9.11.3 show port after a hash: "1.2.3.4#53" */ |
584 | /* Should we do the same? */ | 586 | /* Should we do the same? */ |
585 | } | 587 | } |
586 | 588 | ||
@@ -640,12 +642,26 @@ static int send_queries(struct ns *ns) | |||
640 | printf("*** Can't find %s: Parse error\n", G.query[qn].name); | 642 | printf("*** Can't find %s: Parse error\n", G.query[qn].name); |
641 | G.exitcode = EXIT_FAILURE; | 643 | G.exitcode = EXIT_FAILURE; |
642 | break; | 644 | break; |
643 | 645 | /* bind-utils 9.11.25 just says nothing in this case */ | |
644 | case 0: | 646 | //case 0: |
645 | printf("*** Can't find %s: No answer\n", G.query[qn].name); | 647 | // break; |
646 | break; | ||
647 | } | 648 | } |
648 | } | 649 | } |
650 | /* NB: in case of authoritative, empty answer (NODATA), IOW: one with | ||
651 | * ns_msg_count() == 0, bind-utils 9.11.25 shows no trace of this answer | ||
652 | * (unless -debug, where it says: | ||
653 | * ------------ | ||
654 | * QUESTIONS: | ||
655 | * host.com, type = AAAA, class = IN | ||
656 | * ANSWERS: | ||
657 | * AUTHORITY RECORDS: | ||
658 | * ADDITIONAL RECORDS: | ||
659 | * ------------ | ||
660 | * ). Due to printing of below '\n', we do show an additional empty line. | ||
661 | * This is better than not showing any indication of this reply at all, | ||
662 | * yet maintains "compatibility". I wonder whether it's better to break compat | ||
663 | * and emit something more meaningful, e.g. print "Empty answer (NODATA)"? | ||
664 | */ | ||
649 | bb_putchar('\n'); | 665 | bb_putchar('\n'); |
650 | n_replies++; | 666 | n_replies++; |
651 | if (n_replies >= G.query_count) | 667 | if (n_replies >= G.query_count) |
@@ -697,7 +713,7 @@ static void parse_resolvconf(void) | |||
697 | { | 713 | { |
698 | FILE *resolv; | 714 | FILE *resolv; |
699 | 715 | ||
700 | resolv = fopen("/etc/resolv.conf", "r"); | 716 | resolv = fopen_for_read("/etc/resolv.conf"); |
701 | if (resolv) { | 717 | if (resolv) { |
702 | char line[512]; /* "search" is defined to be up to 256 chars */ | 718 | char line[512]; /* "search" is defined to be up to 256 chars */ |
703 | 719 | ||
diff --git a/networking/ntpd.c b/networking/ntpd.c index 44e711232..1f17b08ef 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c | |||
@@ -77,7 +77,7 @@ | |||
77 | //usage: IF_FEATURE_NTP_AUTH(" [-k KEYFILE] [-p [keyno:N:]PEER]...") | 77 | //usage: IF_FEATURE_NTP_AUTH(" [-k KEYFILE] [-p [keyno:N:]PEER]...") |
78 | //usage:#define ntpd_full_usage "\n\n" | 78 | //usage:#define ntpd_full_usage "\n\n" |
79 | //usage: "NTP client/server\n" | 79 | //usage: "NTP client/server\n" |
80 | //usage: "\n -d Verbose (may be repeated)" | 80 | //usage: "\n -d[d] Verbose" |
81 | //usage: "\n -n Do not daemonize" | 81 | //usage: "\n -n Do not daemonize" |
82 | //usage: "\n -q Quit after clock is set" | 82 | //usage: "\n -q Quit after clock is set" |
83 | //usage: "\n -N Run at high priority" | 83 | //usage: "\n -N Run at high priority" |
@@ -113,6 +113,13 @@ | |||
113 | # define IPTOS_DSCP_AF21 0x48 | 113 | # define IPTOS_DSCP_AF21 0x48 |
114 | #endif | 114 | #endif |
115 | 115 | ||
116 | #if defined(__FreeBSD__) | ||
117 | /* see sys/timex.h */ | ||
118 | # define adjtimex ntp_adjtime | ||
119 | # define ADJ_OFFSET MOD_OFFSET | ||
120 | # define ADJ_STATUS MOD_STATUS | ||
121 | # define ADJ_TIMECONST MOD_TIMECONST | ||
122 | #endif | ||
116 | 123 | ||
117 | /* Verbosity control (max level of -dddd options accepted). | 124 | /* Verbosity control (max level of -dddd options accepted). |
118 | * max 6 is very talkative (and bloated). 3 is non-bloated, | 125 | * max 6 is very talkative (and bloated). 3 is non-bloated, |
@@ -560,7 +567,7 @@ static double | |||
560 | gettime1900d(void) | 567 | gettime1900d(void) |
561 | { | 568 | { |
562 | struct timeval tv; | 569 | struct timeval tv; |
563 | gettimeofday(&tv, NULL); /* never fails */ | 570 | xgettimeofday(&tv); |
564 | G.cur_time = tv.tv_sec + (1.0e-6 * tv.tv_usec) + OFFSET_1900_1970; | 571 | G.cur_time = tv.tv_sec + (1.0e-6 * tv.tv_usec) + OFFSET_1900_1970; |
565 | return G.cur_time; | 572 | return G.cur_time; |
566 | } | 573 | } |
@@ -1144,11 +1151,10 @@ step_time(double offset) | |||
1144 | char buf[sizeof("yyyy-mm-dd hh:mm:ss") + /*paranoia:*/ 4]; | 1151 | char buf[sizeof("yyyy-mm-dd hh:mm:ss") + /*paranoia:*/ 4]; |
1145 | time_t tval; | 1152 | time_t tval; |
1146 | 1153 | ||
1147 | gettimeofday(&tvc, NULL); /* never fails */ | 1154 | xgettimeofday(&tvc); |
1148 | dtime = tvc.tv_sec + (1.0e-6 * tvc.tv_usec) + offset; | 1155 | dtime = tvc.tv_sec + (1.0e-6 * tvc.tv_usec) + offset; |
1149 | d_to_tv(dtime, &tvn); | 1156 | d_to_tv(dtime, &tvn); |
1150 | if (settimeofday(&tvn, NULL) == -1) | 1157 | xsettimeofday(&tvn); |
1151 | bb_simple_perror_msg_and_die("settimeofday"); | ||
1152 | 1158 | ||
1153 | VERB2 { | 1159 | VERB2 { |
1154 | tval = tvc.tv_sec; | 1160 | tval = tvc.tv_sec; |
@@ -2462,9 +2468,6 @@ static NOINLINE void ntp_init(char **argv) | |||
2462 | 2468 | ||
2463 | srand(getpid()); | 2469 | srand(getpid()); |
2464 | 2470 | ||
2465 | if (getuid()) | ||
2466 | bb_simple_error_msg_and_die(bb_msg_you_must_be_root); | ||
2467 | |||
2468 | /* Set some globals */ | 2471 | /* Set some globals */ |
2469 | G.discipline_jitter = G_precision_sec; | 2472 | G.discipline_jitter = G_precision_sec; |
2470 | G.stratum = MAXSTRAT; | 2473 | G.stratum = MAXSTRAT; |
diff --git a/networking/ping.c b/networking/ping.c index 5f7e5b9b5..86d8088de 100644 --- a/networking/ping.c +++ b/networking/ping.c | |||
@@ -58,16 +58,16 @@ | |||
58 | //usage:# define ping_trivial_usage | 58 | //usage:# define ping_trivial_usage |
59 | //usage: "HOST" | 59 | //usage: "HOST" |
60 | //usage:# define ping_full_usage "\n\n" | 60 | //usage:# define ping_full_usage "\n\n" |
61 | //usage: "Send ICMP ECHO_REQUEST packets to network hosts" | 61 | //usage: "Send ICMP ECHO_REQUESTs to HOST" |
62 | //usage:# define ping6_trivial_usage | 62 | //usage:# define ping6_trivial_usage |
63 | //usage: "HOST" | 63 | //usage: "HOST" |
64 | //usage:# define ping6_full_usage "\n\n" | 64 | //usage:# define ping6_full_usage "\n\n" |
65 | //usage: "Send ICMP ECHO_REQUEST packets to network hosts" | 65 | //usage: "Send ICMP ECHO_REQUESTs to HOST" |
66 | //usage:#else | 66 | //usage:#else |
67 | //usage:# define ping_trivial_usage | 67 | //usage:# define ping_trivial_usage |
68 | //usage: "[OPTIONS] HOST" | 68 | //usage: "[OPTIONS] HOST" |
69 | //usage:# define ping_full_usage "\n\n" | 69 | //usage:# define ping_full_usage "\n\n" |
70 | //usage: "Send ICMP ECHO_REQUEST packets to network hosts\n" | 70 | //usage: "Send ICMP ECHO_REQUESTs to HOST\n" |
71 | //usage: IF_PING6( | 71 | //usage: IF_PING6( |
72 | //usage: "\n -4,-6 Force IP or IPv6 name resolution" | 72 | //usage: "\n -4,-6 Force IP or IPv6 name resolution" |
73 | //usage: ) | 73 | //usage: ) |
@@ -81,22 +81,26 @@ | |||
81 | //usage: "\n (after all -c CNT packets are sent)" | 81 | //usage: "\n (after all -c CNT packets are sent)" |
82 | //usage: "\n -w SEC Seconds until ping exits (default:infinite)" | 82 | //usage: "\n -w SEC Seconds until ping exits (default:infinite)" |
83 | //usage: "\n (can exit earlier with -c CNT)" | 83 | //usage: "\n (can exit earlier with -c CNT)" |
84 | //usage: "\n -q Quiet, only display output at start" | 84 | //usage: "\n -q Quiet, only display output at start/finish" |
85 | //usage: "\n and when finished" | 85 | //usage: "\n -p HEXBYTE Payload pattern" |
86 | //usage: "\n -p HEXBYTE Pattern to use for payload" | ||
87 | //usage: | 86 | //usage: |
88 | //usage:# define ping6_trivial_usage | 87 | //usage:# define ping6_trivial_usage |
89 | //usage: "[OPTIONS] HOST" | 88 | //usage: "[OPTIONS] HOST" |
90 | //usage:# define ping6_full_usage "\n\n" | 89 | //usage:# define ping6_full_usage "\n\n" |
91 | //usage: "Send ICMP ECHO_REQUEST packets to network hosts\n" | 90 | //usage: "Send ICMP ECHO_REQUESTs to HOST\n" |
92 | //usage: "\n -c CNT Send only CNT pings" | 91 | //usage: "\n -c CNT Send only CNT pings" |
93 | //usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" | 92 | //usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" |
94 | //usage: "\n -i SECS Interval" | 93 | //usage: "\n -i SECS Interval" |
95 | //usage: "\n -A Ping as soon as reply is recevied" | 94 | //usage: "\n -A Ping as soon as reply is recevied" |
95 | ///////: "\n -t TTL Set TTL" | ||
96 | ///////^^^^^ -t not tested for IPv6, might be not working | ||
96 | //usage: "\n -I IFACE/IP Source interface or IP address" | 97 | //usage: "\n -I IFACE/IP Source interface or IP address" |
97 | //usage: "\n -q Quiet, only display output at start" | 98 | //usage: "\n -W SEC Seconds to wait for the first response (default 10)" |
98 | //usage: "\n and when finished" | 99 | //usage: "\n (after all -c CNT packets are sent)" |
99 | //usage: "\n -p HEXBYTE Pattern to use for payload" | 100 | //usage: "\n -w SEC Seconds until ping exits (default:infinite)" |
101 | //usage: "\n (can exit earlier with -c CNT)" | ||
102 | //usage: "\n -q Quiet, only display output at start/finish" | ||
103 | //usage: "\n -p HEXBYTE Payload pattern" | ||
100 | //usage: | 104 | //usage: |
101 | //usage:#endif | 105 | //usage:#endif |
102 | //usage: | 106 | //usage: |
@@ -118,6 +122,10 @@ | |||
118 | //usage: "round-trip min/avg/max = 20.1/20.1/20.1 ms\n" | 122 | //usage: "round-trip min/avg/max = 20.1/20.1/20.1 ms\n" |
119 | 123 | ||
120 | #include <net/if.h> | 124 | #include <net/if.h> |
125 | #if defined(__FreeBSD__) | ||
126 | # include <netinet/in.h> /* struct ip and friends */ | ||
127 | # include <netinet/ip.h> | ||
128 | #endif | ||
121 | #include <netinet/ip_icmp.h> | 129 | #include <netinet/ip_icmp.h> |
122 | #include "libbb.h" | 130 | #include "libbb.h" |
123 | #include "common_bufsiz.h" | 131 | #include "common_bufsiz.h" |
@@ -156,6 +164,40 @@ | |||
156 | # endif | 164 | # endif |
157 | #endif | 165 | #endif |
158 | 166 | ||
167 | #if defined(__FreeBSD__) | ||
168 | /** | ||
169 | * On BSD the IPv4 struct is called struct ip and instead of iXX | ||
170 | * the members are called ip_XX. One could change this code to use | ||
171 | * struct ip but that would require to define _BSD_SOURCE and that | ||
172 | * might have other complications. Instead make sure struct iphdr | ||
173 | * is present on FreeBSD. The below is taken from GLIBC. | ||
174 | * | ||
175 | * The GNU C Library is free software; you can redistribute it and/or | ||
176 | * modify it under the terms of the GNU Lesser General Public | ||
177 | * License as published by the Free Software Foundation; either | ||
178 | * version 2.1 of the License, or (at your option) any later version. | ||
179 | */ | ||
180 | struct iphdr { | ||
181 | # if BYTE_ORDER == LITTLE_ENDIAN | ||
182 | unsigned int ihl:4; | ||
183 | unsigned int version:4; | ||
184 | # elif BYTE_ORDER == BIG_ENDIAN | ||
185 | unsigned int version:4; | ||
186 | unsigned int ihl:4; | ||
187 | # endif | ||
188 | uint8_t tos; | ||
189 | uint16_t tot_len; | ||
190 | uint16_t id; | ||
191 | uint16_t frag_off; | ||
192 | uint8_t ttl; | ||
193 | uint8_t protocol; | ||
194 | uint16_t check; | ||
195 | uint32_t saddr; | ||
196 | uint32_t daddr; | ||
197 | /*The options start here. */ | ||
198 | }; | ||
199 | #endif | ||
200 | |||
159 | enum { | 201 | enum { |
160 | DEFDATALEN = 56, | 202 | DEFDATALEN = 56, |
161 | MAXIPLEN = 60, | 203 | MAXIPLEN = 60, |
@@ -332,6 +374,11 @@ static int common_ping_main(sa_family_t af, char **argv) | |||
332 | 374 | ||
333 | create_icmp_socket(lsa); | 375 | create_icmp_socket(lsa); |
334 | G.myid = (uint16_t) getpid(); | 376 | G.myid = (uint16_t) getpid(); |
377 | /* we can use native-endian ident, but other Unix ping/traceroute | ||
378 | * utils use *big-endian pid*, and e.g. traceroute on our machine may be | ||
379 | * *not* from busybox, idents may collide. Follow the convention: | ||
380 | */ | ||
381 | G.myid = htons(G.myid); | ||
335 | #if ENABLE_PING6 | 382 | #if ENABLE_PING6 |
336 | if (lsa->u.sa.sa_family == AF_INET6) | 383 | if (lsa->u.sa.sa_family == AF_INET6) |
337 | ping6(lsa); | 384 | ping6(lsa); |
@@ -466,17 +513,16 @@ static void sendping_tail(void (*sp)(int), int size_pkt) | |||
466 | { | 513 | { |
467 | int sz; | 514 | int sz; |
468 | 515 | ||
469 | CLR((uint16_t)G.ntransmitted % MAX_DUP_CHK); | ||
470 | G.ntransmitted++; | ||
471 | |||
472 | size_pkt += datalen; | ||
473 | |||
474 | if (G.deadline_us) { | 516 | if (G.deadline_us) { |
475 | unsigned n = G.cur_us - G.deadline_us; | 517 | unsigned n = G.cur_us - G.deadline_us; |
476 | if ((int)n >= 0) | 518 | if ((int)n >= 0) |
477 | print_stats_and_exit(0); | 519 | print_stats_and_exit(0); |
478 | } | 520 | } |
479 | 521 | ||
522 | CLR((uint16_t)G.ntransmitted % MAX_DUP_CHK); | ||
523 | G.ntransmitted++; | ||
524 | size_pkt += datalen; | ||
525 | |||
480 | /* sizeof(pingaddr) can be larger than real sa size, but I think | 526 | /* sizeof(pingaddr) can be larger than real sa size, but I think |
481 | * it doesn't matter */ | 527 | * it doesn't matter */ |
482 | sz = xsendto(pingsock, G.snd_packet, size_pkt, &pingaddr.sa, sizeof(pingaddr)); | 528 | sz = xsendto(pingsock, G.snd_packet, size_pkt, &pingaddr.sa, sizeof(pingaddr)); |
@@ -927,6 +973,11 @@ static int common_ping_main(int opt, char **argv) | |||
927 | G.interval_us = interval * 1000000; | 973 | G.interval_us = interval * 1000000; |
928 | 974 | ||
929 | myid = (uint16_t) getpid(); | 975 | myid = (uint16_t) getpid(); |
976 | /* we can use native-endian ident, but other Unix ping/traceroute | ||
977 | * utils use *big-endian pid*, and e.g. traceroute on our machine may be | ||
978 | * *not* from busybox, idents may collide. Follow the convention: | ||
979 | */ | ||
980 | myid = htons(myid); | ||
930 | hostname = argv[optind]; | 981 | hostname = argv[optind]; |
931 | #if ENABLE_PING6 | 982 | #if ENABLE_PING6 |
932 | { | 983 | { |
diff --git a/networking/pscan.c b/networking/pscan.c index 2715ef2df..816178bbc 100644 --- a/networking/pscan.c +++ b/networking/pscan.c | |||
@@ -18,13 +18,13 @@ | |||
18 | //usage:#define pscan_trivial_usage | 18 | //usage:#define pscan_trivial_usage |
19 | //usage: "[-cb] [-p MIN_PORT] [-P MAX_PORT] [-t TIMEOUT] [-T MIN_RTT] HOST" | 19 | //usage: "[-cb] [-p MIN_PORT] [-P MAX_PORT] [-t TIMEOUT] [-T MIN_RTT] HOST" |
20 | //usage:#define pscan_full_usage "\n\n" | 20 | //usage:#define pscan_full_usage "\n\n" |
21 | //usage: "Scan a host, print all open ports\n" | 21 | //usage: "Scan HOST, print all open ports\n" |
22 | //usage: "\n -c Show closed ports too" | 22 | //usage: "\n -c Show closed ports too" |
23 | //usage: "\n -b Show blocked ports too" | 23 | //usage: "\n -b Show blocked ports too" |
24 | //usage: "\n -p Scan from this port (default 1)" | 24 | //usage: "\n -p PORT Scan from this port (default 1)" |
25 | //usage: "\n -P Scan up to this port (default 1024)" | 25 | //usage: "\n -P PORT Scan up to this port (default 1024)" |
26 | //usage: "\n -t Timeout (default 5000 ms)" | 26 | //usage: "\n -t MS Timeout (default 5000 ms)" |
27 | //usage: "\n -T Minimum rtt (default 5 ms, increase for congested hosts)" | 27 | //usage: "\n -T MS Minimum rtt (default 5 ms)" |
28 | 28 | ||
29 | #include "libbb.h" | 29 | #include "libbb.h" |
30 | 30 | ||
@@ -139,7 +139,7 @@ int pscan_main(int argc UNUSED_PARAM, char **argv) | |||
139 | * We check rtt BEFORE we usleep, otherwise | 139 | * We check rtt BEFORE we usleep, otherwise |
140 | * on localhost we'll have no writes done (!) | 140 | * on localhost we'll have no writes done (!) |
141 | * before we exceed (rather small) rtt */ | 141 | * before we exceed (rather small) rtt */ |
142 | usleep(rtt_4/8); | 142 | usleep(rtt_4 / 8); |
143 | open: | 143 | open: |
144 | diff = MONOTONIC_US() - start; | 144 | diff = MONOTONIC_US() - start; |
145 | DMSG("write to port %u @%u", port, diff - start); | 145 | DMSG("write to port %u @%u", port, diff - start); |
diff --git a/networking/route.c b/networking/route.c index 4d9aad6cc..ff5daa8a7 100644 --- a/networking/route.c +++ b/networking/route.c | |||
@@ -34,14 +34,6 @@ | |||
34 | 34 | ||
35 | //kbuild:lib-$(CONFIG_ROUTE) += route.o | 35 | //kbuild:lib-$(CONFIG_ROUTE) += route.o |
36 | 36 | ||
37 | //usage:#define route_trivial_usage | ||
38 | //usage: "[{add|del|delete}]" | ||
39 | //usage:#define route_full_usage "\n\n" | ||
40 | //usage: "Edit kernel routing tables\n" | ||
41 | //usage: "\n -n Don't resolve names" | ||
42 | //usage: "\n -e Display other/more information" | ||
43 | //usage: "\n -A inet" IF_FEATURE_IPV6("{6}") " Select address family" | ||
44 | |||
45 | #include <net/route.h> | 37 | #include <net/route.h> |
46 | #include <net/if.h> | 38 | #include <net/if.h> |
47 | 39 | ||
@@ -83,17 +75,15 @@ | |||
83 | #define RTACTION_ADD 1 | 75 | #define RTACTION_ADD 1 |
84 | #define RTACTION_DEL 2 | 76 | #define RTACTION_DEL 2 |
85 | 77 | ||
86 | /* For the various tbl_*[] arrays, the 1st byte is the offset to | 78 | /* For the various tbl_*[] arrays, the 1st byte is return value. */ |
87 | * the next entry and the 2nd byte is return value. */ | ||
88 | 79 | ||
89 | #define NET_FLAG 1 | 80 | #define NET_FLAG 1 |
90 | #define HOST_FLAG 2 | 81 | #define HOST_FLAG 2 |
91 | 82 | ||
92 | /* We remap '-' to '#' to avoid problems with getopt. */ | 83 | /* We remap '-' to '#' to avoid problems with getopt. */ |
93 | static const char tbl_hash_net_host[] ALIGN1 = | 84 | static const char tbl_hash_net_host[] ALIGN1 = |
94 | "\007\001#net\0" | 85 | "\001#net\0" |
95 | /* "\010\002#host\0" */ | 86 | "\002#host\0" |
96 | "\007\002#host" /* Since last, we can save a byte. */ | ||
97 | ; | 87 | ; |
98 | 88 | ||
99 | #define KW_TAKES_ARG 020 | 89 | #define KW_TAKES_ARG 020 |
@@ -116,29 +106,28 @@ static const char tbl_hash_net_host[] ALIGN1 = | |||
116 | static const char tbl_ipvx[] ALIGN1 = | 106 | static const char tbl_ipvx[] ALIGN1 = |
117 | /* 020 is the "takes an arg" bit */ | 107 | /* 020 is the "takes an arg" bit */ |
118 | #if HAVE_NEW_ADDRT | 108 | #if HAVE_NEW_ADDRT |
119 | "\011\020metric\0" | 109 | "\020metric\0" |
120 | #endif | 110 | #endif |
121 | "\012\021netmask\0" | 111 | "\021netmask\0" |
122 | "\005\022gw\0" | 112 | "\022gw\0" |
123 | "\012\022gateway\0" | 113 | "\022gateway\0" |
124 | "\006\023mss\0" | 114 | "\023mss\0" |
125 | "\011\024window\0" | 115 | "\024window\0" |
126 | #ifdef RTF_IRTT | 116 | #ifdef RTF_IRTT |
127 | "\007\025irtt\0" | 117 | "\025irtt\0" |
128 | #endif | 118 | #endif |
129 | "\006\026dev\0" | 119 | "\026dev\0" |
130 | "\011\026device\0" | 120 | "\026device\0" |
131 | /* 040 is the "sets a flag" bit - MUST match flags_ipvx[] values below. */ | 121 | /* 040 is the "sets a flag" bit - MUST match flags_ipvx[] values below. */ |
132 | #ifdef RTF_REJECT | 122 | #ifdef RTF_REJECT |
133 | "\011\040reject\0" | 123 | "\040reject\0" |
134 | #endif | 124 | #endif |
135 | "\006\041mod\0" | 125 | "\041mod\0" |
136 | "\006\042dyn\0" | 126 | "\042dyn\0" |
137 | /* "\014\043reinstate\0" */ | 127 | "\043reinstate\0" |
138 | "\013\043reinstate" /* Since last, we can save a byte. */ | ||
139 | ; | 128 | ; |
140 | 129 | ||
141 | static const uint16_t flags_ipvx[] = { /* MUST match tbl_ipvx[] values above. */ | 130 | static const uint16_t flags_ipvx[] ALIGN2 = { /* MUST match tbl_ipvx[] values above. */ |
142 | #ifdef RTF_REJECT | 131 | #ifdef RTF_REJECT |
143 | RTF_REJECT, | 132 | RTF_REJECT, |
144 | #endif | 133 | #endif |
@@ -151,17 +140,17 @@ static int kw_lookup(const char *kwtbl, char ***pargs) | |||
151 | { | 140 | { |
152 | if (**pargs) { | 141 | if (**pargs) { |
153 | do { | 142 | do { |
154 | if (strcmp(kwtbl+2, **pargs) == 0) { /* Found a match. */ | 143 | if (strcmp(kwtbl + 1, **pargs) == 0) { /* Found a match. */ |
155 | *pargs += 1; | 144 | *pargs += 1; |
156 | if (kwtbl[1] & KW_TAKES_ARG) { | 145 | if (kwtbl[0] & KW_TAKES_ARG) { |
157 | if (!**pargs) { /* No more args! */ | 146 | if (!**pargs) { /* No more args! */ |
158 | bb_show_usage(); | 147 | bb_show_usage(); |
159 | } | 148 | } |
160 | *pargs += 1; /* Calling routine will use args[-1]. */ | 149 | *pargs += 1; /* Calling routine will use args[-1]. */ |
161 | } | 150 | } |
162 | return kwtbl[1]; | 151 | return kwtbl[0]; |
163 | } | 152 | } |
164 | kwtbl += *kwtbl; | 153 | kwtbl += strlen(kwtbl) + 1; |
165 | } while (*kwtbl); | 154 | } while (*kwtbl); |
166 | } | 155 | } |
167 | return 0; | 156 | return 0; |
@@ -208,7 +197,7 @@ static NOINLINE void INET_setroute(int action, char **args) | |||
208 | /* Default netmask. */ | 197 | /* Default netmask. */ |
209 | netmask = "default"; | 198 | netmask = "default"; |
210 | } | 199 | } |
211 | /* Prefer hostname lookup is -host flag (xflag==1) was given. */ | 200 | /* Prefer hostname lookup if -host flag (xflag==1) was given. */ |
212 | isnet = INET_resolve(target, (struct sockaddr_in *) &rt->rt_dst, | 201 | isnet = INET_resolve(target, (struct sockaddr_in *) &rt->rt_dst, |
213 | (xflag & HOST_FLAG)); | 202 | (xflag & HOST_FLAG)); |
214 | if (isnet < 0) { | 203 | if (isnet < 0) { |
@@ -460,9 +449,9 @@ static NOINLINE void INET6_setroute(int action, char **args) | |||
460 | #endif | 449 | #endif |
461 | 450 | ||
462 | static const | 451 | static const |
463 | IF_NOT_FEATURE_IPV6(uint16_t) | 452 | IF_NOT_FEATURE_IPV6(uint16_t flagvals[] ALIGN2 = ) |
464 | IF_FEATURE_IPV6(unsigned) | 453 | IF_FEATURE_IPV6(uint32_t flagvals[] ALIGN4 = ) |
465 | flagvals[] = { /* Must agree with flagchars[]. */ | 454 | { /* Must agree with flagchars[]. */ |
466 | RTF_UP, | 455 | RTF_UP, |
467 | RTF_GATEWAY, | 456 | RTF_GATEWAY, |
468 | RTF_HOST, | 457 | RTF_HOST, |
@@ -544,7 +533,6 @@ void FAST_FUNC bb_displayroutes(int noresolve, int netstatfmt) | |||
544 | flags[0] = '!'; | 533 | flags[0] = '!'; |
545 | } | 534 | } |
546 | #endif | 535 | #endif |
547 | |||
548 | memset(&s_addr, 0, sizeof(struct sockaddr_in)); | 536 | memset(&s_addr, 0, sizeof(struct sockaddr_in)); |
549 | s_addr.sin_family = AF_INET; | 537 | s_addr.sin_family = AF_INET; |
550 | s_addr.sin_addr.s_addr = d; | 538 | s_addr.sin_addr.s_addr = d; |
@@ -634,7 +622,6 @@ static void INET6_displayroutes(void) | |||
634 | naddr6 = INET6_rresolve((struct sockaddr_in6 *) &snaddr6, | 622 | naddr6 = INET6_rresolve((struct sockaddr_in6 *) &snaddr6, |
635 | 0x0fff /* Apparently, upstream never resolves. */ | 623 | 0x0fff /* Apparently, upstream never resolves. */ |
636 | ); | 624 | ); |
637 | |||
638 | if (!r) { /* 1st pass */ | 625 | if (!r) { /* 1st pass */ |
639 | snprintf(addr6, sizeof(addr6), "%s/%d", naddr6, prefix_len); | 626 | snprintf(addr6, sizeof(addr6), "%s/%d", naddr6, prefix_len); |
640 | r += 40; | 627 | r += 40; |
@@ -653,18 +640,27 @@ static void INET6_displayroutes(void) | |||
653 | 640 | ||
654 | #endif | 641 | #endif |
655 | 642 | ||
643 | //usage:#define route_trivial_usage | ||
644 | ///////: "[-ne]"IF_FEATURE_IPV6(" [-A inet[6]]")" [{add|del|delete} [-net|-host] TARGET [netmask MASK] [gw GATEWAY] [metric N] [mss BYTES] [window BYTES] [irtt MSEC] [reject] [mod] [dyn] [reinstate] [[dev] IFACE]]" | ||
645 | ///////too wordy | ||
646 | //usage: "[-ne]"IF_FEATURE_IPV6(" [-A inet[6]]")" [{add|del} [-net|-host] TARGET [netmask MASK]\n" | ||
647 | //usage: " [gw GATEWAY] [metric N] [mss BYTES] [window BYTES] [reject] [IFACE]]" | ||
648 | //usage:#define route_full_usage "\n\n" | ||
649 | //usage: "Show or edit kernel routing tables\n" | ||
650 | //usage: "\n -n Don't resolve names" | ||
651 | //usage: "\n -e Display other/more information" | ||
652 | //usage: "\n -A inet" IF_FEATURE_IPV6("[6]") " Select address family" | ||
653 | |||
656 | #define ROUTE_OPT_A 0x01 | 654 | #define ROUTE_OPT_A 0x01 |
657 | #define ROUTE_OPT_n 0x02 | 655 | #define ROUTE_OPT_n 0x02 |
658 | #define ROUTE_OPT_e 0x04 | 656 | #define ROUTE_OPT_e 0x04 |
659 | #define ROUTE_OPT_INET6 0x08 /* Not an actual option. See below. */ | 657 | #define ROUTE_OPT_INET6 0x08 /* Not an actual option. See below. */ |
660 | 658 | ||
661 | /* 1st byte is offset to next entry offset. 2nd byte is return value. */ | 659 | /* 1st byte is return value, matches RTACTION_* code */ |
662 | /* 2nd byte matches RTACTION_* code */ | ||
663 | static const char tbl_verb[] ALIGN1 = | 660 | static const char tbl_verb[] ALIGN1 = |
664 | "\006\001add\0" | 661 | "\001add\0" |
665 | "\006\002del\0" | 662 | "\002del\0" |
666 | /* "\011\002delete\0" */ | 663 | "\002delete\0" |
667 | "\010\002delete" /* Since it's last, we can save a byte. */ | ||
668 | ; | 664 | ; |
669 | 665 | ||
670 | int route_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 666 | int route_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
diff --git a/networking/slattach.c b/networking/slattach.c index 51fbc1f49..6d2a252fc 100644 --- a/networking/slattach.c +++ b/networking/slattach.c | |||
@@ -76,7 +76,7 @@ static void restore_state_and_exit(int exitcode) | |||
76 | cfsetispeed(&state, B0); | 76 | cfsetispeed(&state, B0); |
77 | cfsetospeed(&state, B0); | 77 | cfsetospeed(&state, B0); |
78 | exitcode |= tcsetattr_serial_or_warn(&state); | 78 | exitcode |= tcsetattr_serial_or_warn(&state); |
79 | sleep(1); | 79 | sleep1(); |
80 | 80 | ||
81 | /* Restore line status */ | 81 | /* Restore line status */ |
82 | if (tcsetattr_serial_or_warn(&G.saved_state)) | 82 | if (tcsetattr_serial_or_warn(&G.saved_state)) |
diff --git a/networking/telnet.c b/networking/telnet.c index 9fc85050b..7a0253525 100644 --- a/networking/telnet.c +++ b/networking/telnet.c | |||
@@ -368,12 +368,16 @@ static void put_iac2_msb_lsb(unsigned x_y) | |||
368 | } | 368 | } |
369 | #define put_iac2_x_y(x,y) put_iac2_msb_lsb(((x)<<8) + (y)) | 369 | #define put_iac2_x_y(x,y) put_iac2_msb_lsb(((x)<<8) + (y)) |
370 | 370 | ||
371 | #if ENABLE_FEATURE_TELNET_WIDTH \ | ||
372 | || ENABLE_FEATURE_TELNET_TTYPE \ | ||
373 | || ENABLE_FEATURE_TELNET_AUTOLOGIN | ||
371 | static void put_iac4_msb_lsb(unsigned x_y_z_t) | 374 | static void put_iac4_msb_lsb(unsigned x_y_z_t) |
372 | { | 375 | { |
373 | put_iac2_msb_lsb(x_y_z_t >> 16); | 376 | put_iac2_msb_lsb(x_y_z_t >> 16); |
374 | put_iac2_msb_lsb(x_y_z_t); /* "... & 0xffff" is implicit */ | 377 | put_iac2_msb_lsb(x_y_z_t); /* "... & 0xffff" is implicit */ |
375 | } | 378 | } |
376 | #define put_iac4_x_y_z_t(x,y,z,t) put_iac4_msb_lsb(((x)<<24) + ((y)<<16) + ((z)<<8) + (t)) | 379 | #define put_iac4_x_y_z_t(x,y,z,t) put_iac4_msb_lsb(((x)<<24) + ((y)<<16) + ((z)<<8) + (t)) |
380 | #endif | ||
377 | 381 | ||
378 | static void put_iac3_IAC_x_y_merged(unsigned wwdd_and_c) | 382 | static void put_iac3_IAC_x_y_merged(unsigned wwdd_and_c) |
379 | { | 383 | { |
@@ -673,7 +677,7 @@ int telnet_main(int argc UNUSED_PARAM, char **argv) | |||
673 | if (bb_got_signal) | 677 | if (bb_got_signal) |
674 | con_escape(); | 678 | con_escape(); |
675 | else | 679 | else |
676 | sleep(1); | 680 | sleep1(); |
677 | continue; | 681 | continue; |
678 | } | 682 | } |
679 | 683 | ||
diff --git a/networking/tftp.c b/networking/tftp.c index 60fdff232..4b86ed9de 100644 --- a/networking/tftp.c +++ b/networking/tftp.c | |||
@@ -104,7 +104,7 @@ | |||
104 | //usage: "\n -p Put file" | 104 | //usage: "\n -p Put file" |
105 | //usage: ) | 105 | //usage: ) |
106 | //usage: IF_FEATURE_TFTP_BLOCKSIZE( | 106 | //usage: IF_FEATURE_TFTP_BLOCKSIZE( |
107 | //usage: "\n -b SIZE Transfer blocks of SIZE octets" | 107 | //usage: "\n -b SIZE Transfer blocks in bytes" |
108 | //usage: ) | 108 | //usage: ) |
109 | ///////: "\n -m STR Accepted and ignored ('-m binary' compat with tftp-hpa 5.2)" | 109 | ///////: "\n -m STR Accepted and ignored ('-m binary' compat with tftp-hpa 5.2)" |
110 | //usage: | 110 | //usage: |
@@ -120,7 +120,7 @@ | |||
120 | //usage: " udpsvd -vE 0.0.0.0 69 tftpd /files/to/serve\n" | 120 | //usage: " udpsvd -vE 0.0.0.0 69 tftpd /files/to/serve\n" |
121 | //usage: "\n -r Prohibit upload" | 121 | //usage: "\n -r Prohibit upload" |
122 | //usage: "\n -c Allow file creation via upload" | 122 | //usage: "\n -c Allow file creation via upload" |
123 | //usage: "\n -u Access files as USER" | 123 | //usage: "\n -u USER Access files as USER" |
124 | //usage: "\n -l Log to syslog (inetd mode requires this)" | 124 | //usage: "\n -l Log to syslog (inetd mode requires this)" |
125 | 125 | ||
126 | #include "libbb.h" | 126 | #include "libbb.h" |
diff --git a/networking/tls.c b/networking/tls.c index c00ef5db0..869456a6a 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
@@ -1959,7 +1959,7 @@ static void send_client_key_exchange(tls_state_t *tls) | |||
1959 | premaster_size = sizeof(rsa_premaster); | 1959 | premaster_size = sizeof(rsa_premaster); |
1960 | } else { | 1960 | } else { |
1961 | /* ECDHE */ | 1961 | /* ECDHE */ |
1962 | static const uint8_t basepoint9[CURVE25519_KEYSIZE] = {9}; | 1962 | static const uint8_t basepoint9[CURVE25519_KEYSIZE] ALIGN1 = {9}; |
1963 | uint8_t privkey[CURVE25519_KEYSIZE]; //[32] | 1963 | uint8_t privkey[CURVE25519_KEYSIZE]; //[32] |
1964 | 1964 | ||
1965 | if (!(tls->flags & GOT_EC_KEY)) | 1965 | if (!(tls->flags & GOT_EC_KEY)) |
diff --git a/networking/tls_aes.c b/networking/tls_aes.c index 5400ad9b5..feb618fb7 100644 --- a/networking/tls_aes.c +++ b/networking/tls_aes.c | |||
@@ -313,15 +313,15 @@ static void InvMixColumns(unsigned astate[16]) | |||
313 | d = astate[i + 3]; | 313 | d = astate[i + 3]; |
314 | x = (a << 1) ^ (a << 2) ^ (a << 3) ^ b ^ (b << 1) ^ (b << 3) | 314 | x = (a << 1) ^ (a << 2) ^ (a << 3) ^ b ^ (b << 1) ^ (b << 3) |
315 | /***/ ^ c ^ (c << 2) ^ (c << 3) ^ d ^ (d << 3); | 315 | /***/ ^ c ^ (c << 2) ^ (c << 3) ^ d ^ (d << 3); |
316 | astate[i + 0] = Multiply(x); | ||
316 | y = a ^ (a << 3) ^ (b << 1) ^ (b << 2) ^ (b << 3) | 317 | y = a ^ (a << 3) ^ (b << 1) ^ (b << 2) ^ (b << 3) |
317 | /***/ ^ c ^ (c << 1) ^ (c << 3) ^ d ^ (d << 2) ^ (d << 3); | 318 | /***/ ^ c ^ (c << 1) ^ (c << 3) ^ d ^ (d << 2) ^ (d << 3); |
319 | astate[i + 1] = Multiply(y); | ||
318 | z = a ^ (a << 2) ^ (a << 3) ^ b ^ (b << 3) | 320 | z = a ^ (a << 2) ^ (a << 3) ^ b ^ (b << 3) |
319 | /***/ ^ (c << 1) ^ (c << 2) ^ (c << 3) ^ d ^ (d << 1) ^ (d << 3); | 321 | /***/ ^ (c << 1) ^ (c << 2) ^ (c << 3) ^ d ^ (d << 1) ^ (d << 3); |
322 | astate[i + 2] = Multiply(z); | ||
320 | t = a ^ (a << 1) ^ (a << 3) ^ b ^ (b << 2) ^ (b << 3) | 323 | t = a ^ (a << 1) ^ (a << 3) ^ b ^ (b << 2) ^ (b << 3) |
321 | /***/ ^ c ^ (c << 3) ^ (d << 1) ^ (d << 2) ^ (d << 3); | 324 | /***/ ^ c ^ (c << 3) ^ (d << 1) ^ (d << 2) ^ (d << 3); |
322 | astate[i + 0] = Multiply(x); | ||
323 | astate[i + 1] = Multiply(y); | ||
324 | astate[i + 2] = Multiply(z); | ||
325 | astate[i + 3] = Multiply(t); | 325 | astate[i + 3] = Multiply(t); |
326 | } | 326 | } |
327 | } | 327 | } |
diff --git a/networking/tls_fe.c b/networking/tls_fe.c index 10971bbff..f810e112a 100644 --- a/networking/tls_fe.c +++ b/networking/tls_fe.c | |||
@@ -383,12 +383,10 @@ static void fe_inv__distinct(byte *r, const byte *x) | |||
383 | * to avoid copying temporaries. | 383 | * to avoid copying temporaries. |
384 | */ | 384 | */ |
385 | 385 | ||
386 | /* 1 1 */ | 386 | lm_copy(r, x); |
387 | fe_mul__distinct(s, x, x); | ||
388 | fe_mul__distinct(r, s, x); | ||
389 | 387 | ||
390 | /* 1 x 248 */ | 388 | /* 1, 1 x 249 */ |
391 | for (i = 0; i < 248; i++) { | 389 | for (i = 0; i < 249; i++) { |
392 | fe_mul__distinct(s, r, r); | 390 | fe_mul__distinct(s, r, r); |
393 | fe_mul__distinct(r, s, x); | 391 | fe_mul__distinct(r, s, x); |
394 | } | 392 | } |
@@ -403,13 +401,11 @@ static void fe_inv__distinct(byte *r, const byte *x) | |||
403 | /* 0 */ | 401 | /* 0 */ |
404 | fe_mul__distinct(r, s, s); | 402 | fe_mul__distinct(r, s, s); |
405 | 403 | ||
406 | /* 1 */ | 404 | /* 1, 1 */ |
407 | fe_mul__distinct(s, r, r); | 405 | for (i = 0; i < 2; i++) { |
408 | fe_mul__distinct(r, s, x); | 406 | fe_mul__distinct(s, r, r); |
409 | 407 | fe_mul__distinct(r, s, x); | |
410 | /* 1 */ | 408 | } |
411 | fe_mul__distinct(s, r, r); | ||
412 | fe_mul__distinct(r, s, x); | ||
413 | } | 409 | } |
414 | 410 | ||
415 | #if 0 //UNUSED | 411 | #if 0 //UNUSED |
@@ -435,12 +431,10 @@ static void exp2523(byte *r, const byte *x, byte *s) | |||
435 | * 111111... 01 | 431 | * 111111... 01 |
436 | */ | 432 | */ |
437 | 433 | ||
438 | /* 1 1 */ | 434 | lm_copy(s, x); |
439 | fe_mul__distinct(r, x, x); | ||
440 | fe_mul__distinct(s, r, x); | ||
441 | 435 | ||
442 | /* 1 x 248 */ | 436 | /* 1, 1 x 249 */ |
443 | for (i = 0; i < 248; i++) { | 437 | for (i = 0; i < 249; i++) { |
444 | fe_mul__distinct(r, s, s); | 438 | fe_mul__distinct(r, s, s); |
445 | fe_mul__distinct(s, r, x); | 439 | fe_mul__distinct(s, r, x); |
446 | } | 440 | } |
diff --git a/networking/traceroute.c b/networking/traceroute.c index 1c4dc3e4a..8f5cd0bf2 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c | |||
@@ -243,7 +243,7 @@ | |||
243 | //kbuild:lib-$(CONFIG_TRACEROUTE6) += traceroute.o | 243 | //kbuild:lib-$(CONFIG_TRACEROUTE6) += traceroute.o |
244 | 244 | ||
245 | //usage:#define traceroute_trivial_usage | 245 | //usage:#define traceroute_trivial_usage |
246 | //usage: "[-"IF_TRACEROUTE6("46")"FIlnrv] [-f 1ST_TTL] [-m MAXTTL] [-q PROBES] [-p PORT]\n" | 246 | //usage: "[-"IF_TRACEROUTE6("46")IF_FEATURE_TRACEROUTE_USE_ICMP("I")"Flnrv] [-f 1ST_TTL] [-m MAXTTL] [-q PROBES] [-p PORT]\n" |
247 | //usage: " [-t TOS] [-w WAIT_SEC] [-s SRC_IP] [-i IFACE]\n" | 247 | //usage: " [-t TOS] [-w WAIT_SEC] [-s SRC_IP] [-i IFACE]\n" |
248 | //usage: " [-z PAUSE_MSEC] HOST [BYTES]" | 248 | //usage: " [-z PAUSE_MSEC] HOST [BYTES]" |
249 | //usage:#define traceroute_full_usage "\n\n" | 249 | //usage:#define traceroute_full_usage "\n\n" |
@@ -271,15 +271,20 @@ | |||
271 | //usage: "\n -s IP Source address" | 271 | //usage: "\n -s IP Source address" |
272 | //usage: "\n -i IFACE Source interface" | 272 | //usage: "\n -i IFACE Source interface" |
273 | //usage: "\n -t N Type-of-service in probe packets (default 0)" | 273 | //usage: "\n -t N Type-of-service in probe packets (default 0)" |
274 | //usage: "\n -w SEC Time to wait for a response (default 3)" | 274 | //usage: "\n -w SEC Wait for a response (default 3)" |
275 | //usage: "\n -g IP Loose source route gateway (8 max)" | 275 | //usage: "\n -z MSEC Wait before each send" |
276 | //usage: | 276 | //usage: |
277 | //usage:#define traceroute6_trivial_usage | 277 | //usage:#define traceroute6_trivial_usage |
278 | //usage: "[-nrv] [-m MAXTTL] [-q PROBES] [-p PORT]\n" | 278 | //usage: "[-"IF_FEATURE_TRACEROUTE_USE_ICMP("I")"nrv] [-f 1ST_TTL] [-m MAXTTL] [-q PROBES] [-p PORT]\n" |
279 | //usage: " [-t TOS] [-w WAIT_SEC] [-s SRC_IP] [-i IFACE]\n" | 279 | //usage: " [-t TOS] [-w WAIT_SEC] [-s SRC_IP] [-i IFACE]\n" |
280 | //usage: " HOST [BYTES]" | 280 | //usage: " [-z PAUSE_MSEC] HOST [BYTES]" |
281 | //usage:#define traceroute6_full_usage "\n\n" | 281 | //usage:#define traceroute6_full_usage "\n\n" |
282 | //usage: "Trace the route to HOST\n" | 282 | //usage: "Trace the route to HOST\n" |
283 | ////NOP? "\n -F Set don't fragment bit" | ||
284 | //usage: IF_FEATURE_TRACEROUTE_USE_ICMP( | ||
285 | //usage: "\n -I Use ICMP ECHO instead of UDP datagrams" | ||
286 | //usage: ) | ||
287 | ////NOP: "\n -l Display TTL value of the returned packet" | ||
283 | //Currently disabled (TRACEROUTE_SO_DEBUG==0) | 288 | //Currently disabled (TRACEROUTE_SO_DEBUG==0) |
284 | ////usage: "\n -d Set SO_DEBUG options to socket" | 289 | ////usage: "\n -d Set SO_DEBUG options to socket" |
285 | //usage: "\n -n Print numeric addresses" | 290 | //usage: "\n -n Print numeric addresses" |
@@ -287,6 +292,7 @@ | |||
287 | //usage: IF_FEATURE_TRACEROUTE_VERBOSE( | 292 | //usage: IF_FEATURE_TRACEROUTE_VERBOSE( |
288 | //usage: "\n -v Verbose" | 293 | //usage: "\n -v Verbose" |
289 | //usage: ) | 294 | //usage: ) |
295 | //usage: "\n -f N First number of hops (default 1)" | ||
290 | //usage: "\n -m N Max number of hops" | 296 | //usage: "\n -m N Max number of hops" |
291 | //usage: "\n -q N Number of probes per hop (default 3)" | 297 | //usage: "\n -q N Number of probes per hop (default 3)" |
292 | //usage: "\n -p N Base UDP port number used in probes" | 298 | //usage: "\n -p N Base UDP port number used in probes" |
@@ -294,7 +300,8 @@ | |||
294 | //usage: "\n -s IP Source address" | 300 | //usage: "\n -s IP Source address" |
295 | //usage: "\n -i IFACE Source interface" | 301 | //usage: "\n -i IFACE Source interface" |
296 | //usage: "\n -t N Type-of-service in probe packets (default 0)" | 302 | //usage: "\n -t N Type-of-service in probe packets (default 0)" |
297 | //usage: "\n -w SEC Time wait for a response (default 3)" | 303 | //usage: "\n -w SEC Wait for a response (default 3)" |
304 | //usage: "\n -z MSEC Wait before each send" | ||
298 | 305 | ||
299 | #define TRACEROUTE_SO_DEBUG 0 | 306 | #define TRACEROUTE_SO_DEBUG 0 |
300 | 307 | ||
@@ -324,7 +331,6 @@ | |||
324 | #ifndef IPPROTO_IP | 331 | #ifndef IPPROTO_IP |
325 | # define IPPROTO_IP 0 | 332 | # define IPPROTO_IP 0 |
326 | #endif | 333 | #endif |
327 | |||
328 | /* Some operating systems, like GNU/Hurd, don't define SOL_RAW, but do have | 334 | /* Some operating systems, like GNU/Hurd, don't define SOL_RAW, but do have |
329 | * IPPROTO_RAW. Since the IPPROTO definitions are also valid to use for | 335 | * IPPROTO_RAW. Since the IPPROTO definitions are also valid to use for |
330 | * setsockopt (and take the same value as their corresponding SOL definitions, | 336 | * setsockopt (and take the same value as their corresponding SOL definitions, |
@@ -335,7 +341,7 @@ | |||
335 | 341 | ||
336 | 342 | ||
337 | #define OPT_STRING \ | 343 | #define OPT_STRING \ |
338 | "FIlnrdvxt:i:m:p:q:s:w:z:f:" \ | 344 | "FIlnrdvt:i:m:p:q:s:w:z:f:" \ |
339 | "4" IF_TRACEROUTE6("6") | 345 | "4" IF_TRACEROUTE6("6") |
340 | enum { | 346 | enum { |
341 | OPT_DONT_FRAGMNT = (1 << 0), /* F */ | 347 | OPT_DONT_FRAGMNT = (1 << 0), /* F */ |
@@ -345,20 +351,23 @@ enum { | |||
345 | OPT_BYPASS_ROUTE = (1 << 4), /* r */ | 351 | OPT_BYPASS_ROUTE = (1 << 4), /* r */ |
346 | OPT_DEBUG = (1 << 5), /* d */ | 352 | OPT_DEBUG = (1 << 5), /* d */ |
347 | OPT_VERBOSE = (1 << 6) * ENABLE_FEATURE_TRACEROUTE_VERBOSE, /* v */ | 353 | OPT_VERBOSE = (1 << 6) * ENABLE_FEATURE_TRACEROUTE_VERBOSE, /* v */ |
348 | OPT_IP_CHKSUM = (1 << 7), /* x */ | 354 | OPT_TOS = (1 << 7), /* t */ |
349 | OPT_TOS = (1 << 8), /* t */ | 355 | OPT_DEVICE = (1 << 8), /* i */ |
350 | OPT_DEVICE = (1 << 9), /* i */ | 356 | OPT_MAX_TTL = (1 << 9), /* m */ |
351 | OPT_MAX_TTL = (1 << 10), /* m */ | 357 | OPT_PORT = (1 << 10), /* p */ |
352 | OPT_PORT = (1 << 11), /* p */ | 358 | OPT_NPROBES = (1 << 11), /* q */ |
353 | OPT_NPROBES = (1 << 12), /* q */ | 359 | OPT_SOURCE = (1 << 12), /* s */ |
354 | OPT_SOURCE = (1 << 13), /* s */ | 360 | OPT_WAITTIME = (1 << 13), /* w */ |
355 | OPT_WAITTIME = (1 << 14), /* w */ | 361 | OPT_PAUSE_MS = (1 << 14), /* z */ |
356 | OPT_PAUSE_MS = (1 << 15), /* z */ | 362 | OPT_FIRST_TTL = (1 << 15), /* f */ |
357 | OPT_FIRST_TTL = (1 << 16), /* f */ | 363 | OPT_IPV4 = (1 << 16), /* 4 */ |
358 | OPT_IPV4 = (1 << 17), /* 4 */ | 364 | OPT_IPV6 = (1 << 17) * ENABLE_TRACEROUTE6, /* 6 */ |
359 | OPT_IPV6 = (1 << 18) * ENABLE_TRACEROUTE6, /* 6 */ | ||
360 | }; | 365 | }; |
361 | #define verbose (option_mask32 & OPT_VERBOSE) | 366 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE |
367 | # define verbose (option_mask32 & OPT_VERBOSE) | ||
368 | #else | ||
369 | # define verbose 0 | ||
370 | #endif | ||
362 | 371 | ||
363 | enum { | 372 | enum { |
364 | SIZEOF_ICMP_HDR = 8, | 373 | SIZEOF_ICMP_HDR = 8, |
@@ -387,13 +396,26 @@ struct globals { | |||
387 | struct ip *outip; | 396 | struct ip *outip; |
388 | /* Pointer to ICMP or UDP payload (not header): */ | 397 | /* Pointer to ICMP or UDP payload (not header): */ |
389 | struct outdata_t *outdata; | 398 | struct outdata_t *outdata; |
390 | |||
391 | len_and_sockaddr *dest_lsa; | 399 | len_and_sockaddr *dest_lsa; |
400 | len_and_sockaddr *from_lsa; /* response came from this address */ | ||
401 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE | ||
402 | struct sockaddr *to; /* response came to this (local) address */ | ||
403 | #endif | ||
404 | uint32_t ident; | ||
405 | uint16_t port; /* start udp dest port # for probe packets */ | ||
406 | #if ENABLE_TRACEROUTE6 | ||
407 | smallint ipv6; | ||
408 | # define G_ipv6 G.ipv6 | ||
409 | #else | ||
410 | # define G_ipv6 0 | ||
411 | #endif | ||
392 | int packlen; /* total length of packet */ | 412 | int packlen; /* total length of packet */ |
393 | int pmtu; /* Path MTU Discovery (RFC1191) */ | 413 | int pmtu; /* Path MTU Discovery (RFC1191) */ |
394 | uint32_t ident; | 414 | int waittime; /* time to wait for response (in seconds) */ |
395 | uint16_t port; // 33434; /* start udp dest port # for probe packets */ | 415 | int first_ttl; |
396 | int waittime; // 5; /* time to wait for response (in seconds) */ | 416 | int nprobes; |
417 | int max_ttl; | ||
418 | unsigned pausemsecs; | ||
397 | unsigned char recv_pkt[512]; /* last inbound (icmp) packet */ | 419 | unsigned char recv_pkt[512]; /* last inbound (icmp) packet */ |
398 | }; | 420 | }; |
399 | 421 | ||
@@ -407,19 +429,39 @@ struct globals { | |||
407 | #define port (G.port ) | 429 | #define port (G.port ) |
408 | #define waittime (G.waittime ) | 430 | #define waittime (G.waittime ) |
409 | #define recv_pkt (G.recv_pkt ) | 431 | #define recv_pkt (G.recv_pkt ) |
410 | #define gwlist (G.gwlist ) | ||
411 | #define INIT_G() do { \ | 432 | #define INIT_G() do { \ |
412 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | 433 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
413 | port = 33434; \ | ||
414 | waittime = 5; \ | ||
415 | } while (0) | 434 | } while (0) |
416 | 435 | ||
417 | #define outicmp ((struct icmp *)(outip + 1)) | 436 | #define outudp ((struct udphdr *)(outip + 1)) |
418 | #define outudp ((struct udphdr *)(outip + 1)) | 437 | #define outudp6 ((struct udphdr *)(((struct ip6_hdr*)outip) + 1)) |
419 | 438 | #define outicmp ((struct icmp *)(outip + 1)) | |
439 | #define outicmp6 ((struct icmp *)(((struct ip6_hdr*)outip) + 1)) | ||
440 | /* NB: for icmp echo, IPv4 and IPv6 fields are the same size and offset: | ||
441 | * struct icmp: | ||
442 | * uint8_t icmp_type; | ||
443 | * uint8_t icmp_code; | ||
444 | * uint16_t icmp_cksum; | ||
445 | * uint16_t icmp_id; | ||
446 | * uint16_t icmp_seq; | ||
447 | * struct icmp6_hdr: | ||
448 | * uint8_t icmp6_type; | ||
449 | * uint8_t icmp6_code; | ||
450 | * uint16_t icmp6_cksum; | ||
451 | * uint16_t icmp6_id; | ||
452 | * uint16_t icmp6_seq; | ||
453 | * therefore both outicmp and outicmp6 are pointers to *IPv4* icmp struct. | ||
454 | * SIZEOF_ICMP_HDR == 8 is the same for both, as well. | ||
455 | * However, values of these pointers are not the same (since IPv6 IP header is larger), | ||
456 | * and icmp_type constants are not the same: | ||
457 | * #define ICMP_ECHO 8 | ||
458 | * #define ICMP_ECHOREPLY 0 | ||
459 | * #define ICMP6_ECHO_REQUEST 128 | ||
460 | * #define ICMP6_ECHO_REPLY 129 | ||
461 | */ | ||
420 | 462 | ||
421 | static int | 463 | static int |
422 | wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timestamp_us, int *left_ms) | 464 | wait_for_reply(unsigned *timestamp_us, int *left_ms) |
423 | { | 465 | { |
424 | struct pollfd pfd[1]; | 466 | struct pollfd pfd[1]; |
425 | int read_len = 0; | 467 | int read_len = 0; |
@@ -429,10 +471,19 @@ wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timest | |||
429 | if (*left_ms >= 0 && safe_poll(pfd, 1, *left_ms) > 0) { | 471 | if (*left_ms >= 0 && safe_poll(pfd, 1, *left_ms) > 0) { |
430 | unsigned t; | 472 | unsigned t; |
431 | 473 | ||
474 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE | ||
432 | read_len = recv_from_to(rcvsock, | 475 | read_len = recv_from_to(rcvsock, |
433 | recv_pkt, sizeof(recv_pkt), | 476 | recv_pkt, sizeof(recv_pkt), |
434 | /*flags:*/ MSG_DONTWAIT, | 477 | /*flags:*/ MSG_DONTWAIT, |
435 | &from_lsa->u.sa, to, from_lsa->len); | 478 | &G.from_lsa->u.sa, G.to, G.from_lsa->len); |
479 | #else | ||
480 | read_len = recvfrom(rcvsock, | ||
481 | recv_pkt, sizeof(recv_pkt), | ||
482 | /*flags:*/ MSG_DONTWAIT, | ||
483 | &G.from_lsa->u.sa, &G.from_lsa->len); | ||
484 | #endif | ||
485 | if (read_len < 0) | ||
486 | bb_simple_perror_msg_and_die("recv"); | ||
436 | t = monotonic_us(); | 487 | t = monotonic_us(); |
437 | *left_ms -= (t - *timestamp_us) / 1000; | 488 | *left_ms -= (t - *timestamp_us) / 1000; |
438 | *timestamp_us = t; | 489 | *timestamp_us = t; |
@@ -446,14 +497,16 @@ send_probe(int seq, int ttl) | |||
446 | { | 497 | { |
447 | int len, res; | 498 | int len, res; |
448 | void *out; | 499 | void *out; |
500 | struct icmp *icp; | ||
449 | 501 | ||
450 | /* Payload */ | 502 | /* Payload */ |
451 | #if ENABLE_TRACEROUTE6 | 503 | #if ENABLE_TRACEROUTE6 |
452 | if (dest_lsa->u.sa.sa_family == AF_INET6) { | 504 | if (G_ipv6) { |
453 | struct outdata6_t *pkt = (struct outdata6_t *) outdata; | 505 | struct outdata6_t *pkt = (void *) outdata; |
454 | pkt->ident6 = htonl(ident); | 506 | pkt->ident6 = ident; |
455 | pkt->seq6 = htonl(seq); | 507 | pkt->seq6 = htonl(seq); |
456 | /*gettimeofday(&pkt->tv, &tz);*/ | 508 | /*xgettimeofday(&pkt->tv);*/ |
509 | icp = outicmp6; | ||
457 | } else | 510 | } else |
458 | #endif | 511 | #endif |
459 | { | 512 | { |
@@ -461,19 +514,23 @@ send_probe(int seq, int ttl) | |||
461 | outdata->ttl = ttl; | 514 | outdata->ttl = ttl; |
462 | // UNUSED: was storing gettimeofday's result there, but never ever checked it | 515 | // UNUSED: was storing gettimeofday's result there, but never ever checked it |
463 | /*memcpy(&outdata->tv, tp, sizeof(outdata->tv));*/ | 516 | /*memcpy(&outdata->tv, tp, sizeof(outdata->tv));*/ |
464 | 517 | icp = outicmp; | |
465 | if (option_mask32 & OPT_USE_ICMP) { | 518 | } |
466 | outicmp->icmp_seq = htons(seq); | 519 | out = outdata; |
467 | 520 | if (option_mask32 & OPT_USE_ICMP) { | |
468 | /* Always calculate checksum for icmp packets */ | 521 | out = icp; |
469 | outicmp->icmp_cksum = 0; | 522 | /*icp->icmp_type = ICMP[6]_ECHO; - already set */ |
470 | outicmp->icmp_cksum = inet_cksum( | 523 | /*icp->icmp_code = 0; - already set */ |
471 | outicmp, | 524 | /*icp->icmp_id = ident; - already set */ |
472 | ((char*)outip + packlen) - (char*)outicmp | 525 | icp->icmp_seq = htons(seq); |
473 | ); | 526 | /* Always calculate checksum for icmp packets */ |
474 | if (outicmp->icmp_cksum == 0) | 527 | icp->icmp_cksum = 0; |
475 | outicmp->icmp_cksum = 0xffff; | 528 | icp->icmp_cksum = inet_cksum( |
476 | } | 529 | icp, |
530 | ((char*)outip + packlen) - (char*)icp | ||
531 | ); | ||
532 | if (icp->icmp_cksum == 0) | ||
533 | icp->icmp_cksum = 0xffff; | ||
477 | } | 534 | } |
478 | 535 | ||
479 | //BUG! verbose is (x & OPT_VERBOSE), not a counter! | 536 | //BUG! verbose is (x & OPT_VERBOSE), not a counter! |
@@ -502,9 +559,8 @@ send_probe(int seq, int ttl) | |||
502 | } | 559 | } |
503 | #endif | 560 | #endif |
504 | 561 | ||
505 | out = outdata; | ||
506 | #if ENABLE_TRACEROUTE6 | 562 | #if ENABLE_TRACEROUTE6 |
507 | if (dest_lsa->u.sa.sa_family == AF_INET6) { | 563 | if (G_ipv6) { |
508 | res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl); | 564 | res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl); |
509 | if (res != 0) | 565 | if (res != 0) |
510 | bb_perror_msg_and_die("setsockopt(%s) %d", "UNICAST_HOPS", ttl); | 566 | bb_perror_msg_and_die("setsockopt(%s) %d", "UNICAST_HOPS", ttl); |
@@ -516,8 +572,6 @@ send_probe(int seq, int ttl) | |||
516 | if (res != 0) | 572 | if (res != 0) |
517 | bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl); | 573 | bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl); |
518 | #endif | 574 | #endif |
519 | if (option_mask32 & OPT_USE_ICMP) | ||
520 | out = outicmp; | ||
521 | } | 575 | } |
522 | 576 | ||
523 | if (!(option_mask32 & OPT_USE_ICMP)) { | 577 | if (!(option_mask32 & OPT_USE_ICMP)) { |
@@ -530,13 +584,11 @@ send_probe(int seq, int ttl) | |||
530 | } | 584 | } |
531 | 585 | ||
532 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE | 586 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE |
533 | /* | 587 | /* Convert an ICMP "type" field to a printable string */ |
534 | * Convert an ICMP "type" field to a printable string. | ||
535 | */ | ||
536 | static const char * | 588 | static const char * |
537 | pr_type(unsigned char t) | 589 | pr_type(unsigned char t) |
538 | { | 590 | { |
539 | static const char *const ttab[] = { | 591 | static const char *const ttab[] ALIGN_PTR = { |
540 | "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable", | 592 | "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable", |
541 | "Source Quench", "Redirect", "ICMP 6", "ICMP 7", | 593 | "Source Quench", "Redirect", "ICMP 6", "ICMP 7", |
542 | "Echo", "Router Advert", "Router Solicit", "Time Exceeded", | 594 | "Echo", "Router Advert", "Router Solicit", "Time Exceeded", |
@@ -544,7 +596,7 @@ pr_type(unsigned char t) | |||
544 | "Info Reply", "Mask Request", "Mask Reply" | 596 | "Info Reply", "Mask Request", "Mask Reply" |
545 | }; | 597 | }; |
546 | # if ENABLE_TRACEROUTE6 | 598 | # if ENABLE_TRACEROUTE6 |
547 | static const char *const ttab6[] = { | 599 | static const char *const ttab6[] ALIGN_PTR = { |
548 | [0] = "Error", "Dest Unreachable", "Packet Too Big", "Time Exceeded", | 600 | [0] = "Error", "Dest Unreachable", "Packet Too Big", "Time Exceeded", |
549 | [4] = "Param Problem", | 601 | [4] = "Param Problem", |
550 | [8] = "Echo Request", "Echo Reply", "Membership Query", "Membership Report", | 602 | [8] = "Echo Request", "Echo Reply", "Membership Query", "Membership Report", |
@@ -552,7 +604,7 @@ pr_type(unsigned char t) | |||
552 | [16] = "Neighbor Advert", "Redirect", | 604 | [16] = "Neighbor Advert", "Redirect", |
553 | }; | 605 | }; |
554 | 606 | ||
555 | if (dest_lsa->u.sa.sa_family == AF_INET6) { | 607 | if (G_ipv6) { |
556 | if (t < 5) | 608 | if (t < 5) |
557 | return ttab6[t]; | 609 | return ttab6[t]; |
558 | if (t < 128 || t > ND_REDIRECT) | 610 | if (t < 128 || t > ND_REDIRECT) |
@@ -565,28 +617,54 @@ pr_type(unsigned char t) | |||
565 | 617 | ||
566 | return ttab[t]; | 618 | return ttab[t]; |
567 | } | 619 | } |
568 | #endif | 620 | static int |
621 | hexdump_if_verbose(const struct icmp *icp, int len) | ||
622 | { | ||
623 | const unsigned char *p; | ||
624 | int i; | ||
569 | 625 | ||
570 | #if !ENABLE_FEATURE_TRACEROUTE_VERBOSE | 626 | if (!verbose) |
571 | #define packet4_ok(read_len, from, seq) \ | 627 | return 0; |
572 | packet4_ok(read_len, seq) | 628 | |
629 | printf("\n%d bytes from %s to %s: icmp type %u (%s) code %u\n", | ||
630 | len, | ||
631 | auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)), | ||
632 | auto_string(xmalloc_sockaddr2dotted_noport(G.to)), | ||
633 | icp->icmp_type, pr_type(icp->icmp_type), | ||
634 | icp->icmp_code | ||
635 | ); | ||
636 | p = (const void *)icp; | ||
637 | for (i = 0; i < len; i++) { | ||
638 | if (!(i & 0xf)) | ||
639 | printf("\n%04x:" + (i==0), i); | ||
640 | printf(" %02x", p[i]); | ||
641 | } | ||
642 | bb_putchar('\n'); | ||
643 | return 0; | ||
644 | } | ||
645 | #else | ||
646 | # define hexdump_if_verbose(...) 0 | ||
573 | #endif | 647 | #endif |
648 | |||
574 | static int | 649 | static int |
575 | packet4_ok(int read_len, const struct sockaddr_in *from, int seq) | 650 | packet4_ok(int read_len, int seq) |
576 | { | 651 | { |
577 | const struct icmp *icp; | 652 | const struct icmp *icp; |
578 | unsigned char type, code; | 653 | unsigned char type, code; |
579 | int hlen; | 654 | int hlen; |
580 | const struct ip *ip; | 655 | const struct ip *ip; |
581 | 656 | ||
657 | /* NB: reads from (AF_INET, SOCK_RAW, IPPROTO_ICMP) socket | ||
658 | * return the entire IP packet (IOW: they do not strip IP header). | ||
659 | * This differs from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) sockets!? | ||
660 | */ | ||
582 | ip = (struct ip *) recv_pkt; | 661 | ip = (struct ip *) recv_pkt; |
662 | |||
583 | hlen = ip->ip_hl << 2; | 663 | hlen = ip->ip_hl << 2; |
584 | if (read_len < hlen + ICMP_MINLEN) { | 664 | if (read_len < hlen + ICMP_MINLEN) { |
585 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE | ||
586 | if (verbose) | 665 | if (verbose) |
587 | printf("packet too short (%d bytes) from %s\n", read_len, | 666 | printf("packet too short (%d bytes) from %s\n", read_len, |
588 | inet_ntoa(from->sin_addr)); | 667 | inet_ntoa(G.from_lsa->u.sin.sin_addr)); |
589 | #endif | ||
590 | return 0; | 668 | return 0; |
591 | } | 669 | } |
592 | read_len -= hlen; | 670 | read_len -= hlen; |
@@ -598,9 +676,22 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) | |||
598 | if (code == ICMP_UNREACH_NEEDFRAG) | 676 | if (code == ICMP_UNREACH_NEEDFRAG) |
599 | pmtu = ntohs(icp->icmp_nextmtu); | 677 | pmtu = ntohs(icp->icmp_nextmtu); |
600 | 678 | ||
679 | if ((option_mask32 & OPT_USE_ICMP) | ||
680 | && type == ICMP_ECHOREPLY | ||
681 | && icp->icmp_seq == htons(seq) | ||
682 | ) { | ||
683 | if (icp->icmp_id != ident) | ||
684 | /* reply to another ping/traceroute from this box? */ | ||
685 | return 0; /* ignore, silently */ | ||
686 | /* In UDP mode, when we reach the machine, we (usually) | ||
687 | * would get "port unreachable" - in ICMP we got "echo reply". | ||
688 | * Simulate "port unreachable" for caller: | ||
689 | */ | ||
690 | return ICMP_UNREACH_PORT+1; | ||
691 | } | ||
692 | |||
601 | if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) | 693 | if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) |
602 | || type == ICMP_UNREACH | 694 | || type == ICMP_UNREACH |
603 | || type == ICMP_ECHOREPLY | ||
604 | ) { | 695 | ) { |
605 | const struct ip *hip; | 696 | const struct ip *hip; |
606 | const struct udphdr *up; | 697 | const struct udphdr *up; |
@@ -610,18 +701,10 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) | |||
610 | if (option_mask32 & OPT_USE_ICMP) { | 701 | if (option_mask32 & OPT_USE_ICMP) { |
611 | struct icmp *hicmp; | 702 | struct icmp *hicmp; |
612 | 703 | ||
613 | /* XXX */ | ||
614 | if (type == ICMP_ECHOREPLY | ||
615 | && icp->icmp_id == htons(ident) | ||
616 | && icp->icmp_seq == htons(seq) | ||
617 | ) { | ||
618 | return ICMP_UNREACH_PORT+1; | ||
619 | } | ||
620 | |||
621 | hicmp = (struct icmp *)((unsigned char *)hip + hlen); | 704 | hicmp = (struct icmp *)((unsigned char *)hip + hlen); |
622 | if (hlen + SIZEOF_ICMP_HDR <= read_len | 705 | if (hlen + SIZEOF_ICMP_HDR <= read_len |
623 | && hip->ip_p == IPPROTO_ICMP | 706 | && hip->ip_p == IPPROTO_ICMP |
624 | && hicmp->icmp_id == htons(ident) | 707 | && hicmp->icmp_id == ident |
625 | && hicmp->icmp_seq == htons(seq) | 708 | && hicmp->icmp_seq == htons(seq) |
626 | ) { | 709 | ) { |
627 | return (type == ICMP_TIMXCEED ? -1 : code + 1); | 710 | return (type == ICMP_TIMXCEED ? -1 : code + 1); |
@@ -633,51 +716,54 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) | |||
633 | // Off: since we do not form the entire IP packet, | 716 | // Off: since we do not form the entire IP packet, |
634 | // but defer it to kernel, we can't set source port, | 717 | // but defer it to kernel, we can't set source port, |
635 | // and thus can't check it here in the reply | 718 | // and thus can't check it here in the reply |
636 | /* && up->source == htons(ident) */ | 719 | /* && up->uh_sport == ident */ |
637 | && up->dest == htons(port + seq) | 720 | && up->uh_dport == htons(port + seq) |
638 | ) { | 721 | ) { |
639 | return (type == ICMP_TIMXCEED ? -1 : code + 1); | 722 | return (type == ICMP_TIMXCEED ? -1 : code + 1); |
640 | } | 723 | } |
641 | } | 724 | } |
642 | } | 725 | } |
643 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE | 726 | /* testcase: traceroute -vI 127.0.0.1 (sees its own echo requests) */ |
644 | if (verbose) { | 727 | return hexdump_if_verbose(icp, read_len); |
645 | int i; | ||
646 | uint32_t *lp = (uint32_t *)&icp->icmp_ip; | ||
647 | |||
648 | printf("\n%d bytes from %s to " | ||
649 | "%s: icmp type %d (%s) code %d\n", | ||
650 | read_len, inet_ntoa(from->sin_addr), | ||
651 | inet_ntoa(ip->ip_dst), | ||
652 | type, pr_type(type), icp->icmp_code); | ||
653 | for (i = 4; i < read_len; i += sizeof(*lp)) | ||
654 | printf("%2d: x%8.8x\n", i, *lp++); | ||
655 | } | ||
656 | #endif | ||
657 | return 0; | ||
658 | } | 728 | } |
659 | 729 | ||
660 | #if ENABLE_TRACEROUTE6 | 730 | #if ENABLE_TRACEROUTE6 |
661 | # if !ENABLE_FEATURE_TRACEROUTE_VERBOSE | 731 | |
662 | #define packet_ok(read_len, from_lsa, to, seq) \ | ||
663 | packet_ok(read_len, from_lsa, seq) | ||
664 | # endif | ||
665 | static int | 732 | static int |
666 | packet_ok(int read_len, len_and_sockaddr *from_lsa, | 733 | packet6_ok(int read_len, int seq) |
667 | struct sockaddr *to, | ||
668 | int seq) | ||
669 | { | 734 | { |
670 | const struct icmp6_hdr *icp; | 735 | const struct icmp6_hdr *icp; |
671 | unsigned char type, code; | 736 | unsigned char type, code; |
672 | 737 | ||
673 | if (from_lsa->u.sa.sa_family == AF_INET) | 738 | /* NB: reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) socket |
674 | return packet4_ok(read_len, &from_lsa->u.sin, seq); | 739 | * return only ICMP packet (IOW: they strip IPv6 header). |
675 | 740 | * This differs from (AF_INET, SOCK_RAW, IPPROTO_ICMP) sockets!? | |
741 | */ | ||
742 | if (read_len < ICMP_MINLEN) { | ||
743 | if (verbose) | ||
744 | printf("packet too short (%d bytes) from %s\n", read_len, | ||
745 | auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa))); | ||
746 | return 0; | ||
747 | } | ||
676 | icp = (struct icmp6_hdr *) recv_pkt; | 748 | icp = (struct icmp6_hdr *) recv_pkt; |
677 | 749 | ||
678 | type = icp->icmp6_type; | 750 | type = icp->icmp6_type; |
679 | code = icp->icmp6_code; | 751 | code = icp->icmp6_code; |
680 | 752 | ||
753 | if ((option_mask32 & OPT_USE_ICMP) | ||
754 | && type == ICMP6_ECHO_REPLY | ||
755 | && icp->icmp6_seq == htons(seq) | ||
756 | ) { | ||
757 | if (icp->icmp6_id != ident) | ||
758 | /* reply to another ping/traceroute from this box? */ | ||
759 | return 0; /* ignore, silently */ | ||
760 | /* In UDP mode, when we reach the machine, we (usually) | ||
761 | * would get "port unreachable" - in ICMP we got "echo reply". | ||
762 | * Simulate "port unreachable" for caller: | ||
763 | */ | ||
764 | return (ICMP6_DST_UNREACH_NOPORT << 8) + 1; | ||
765 | } | ||
766 | |||
681 | if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) | 767 | if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) |
682 | || type == ICMP6_DST_UNREACH | 768 | || type == ICMP6_DST_UNREACH |
683 | ) { | 769 | ) { |
@@ -698,106 +784,75 @@ packet_ok(int read_len, len_and_sockaddr *from_lsa, | |||
698 | 784 | ||
699 | pkt = (struct outdata6_t *) (up + 1); | 785 | pkt = (struct outdata6_t *) (up + 1); |
700 | 786 | ||
701 | if (ntohl(pkt->ident6) == ident | 787 | if (pkt->ident6 == ident |
702 | && ntohl(pkt->seq6) == seq | 788 | && ntohl(pkt->seq6) == seq |
703 | ) { | 789 | ) { |
704 | return (type == ICMP6_TIME_EXCEEDED ? -1 : (code<<8)+1); | 790 | return (type == ICMP6_TIME_EXCEEDED ? -1 : (code<<8)+1); |
705 | } | 791 | } |
706 | } | 792 | } |
707 | } | 793 | } |
708 | 794 | /* cast is safe since the beginning of icmp4 and icmp6 layouts match */ | |
709 | # if ENABLE_FEATURE_TRACEROUTE_VERBOSE | 795 | return hexdump_if_verbose((const struct icmp *)icp, read_len); |
710 | if (verbose) { | ||
711 | # ifndef MAXHOSTNAMELEN | ||
712 | # define MAXHOSTNAMELEN 80 | ||
713 | # endif | ||
714 | unsigned char *p; | ||
715 | char pa1[MAXHOSTNAMELEN]; | ||
716 | char pa2[MAXHOSTNAMELEN]; | ||
717 | int i; | ||
718 | |||
719 | p = (unsigned char *) (icp + 1); | ||
720 | |||
721 | printf("\n%d bytes from %s to " | ||
722 | "%s: icmp type %d (%s) code %d\n", | ||
723 | read_len, | ||
724 | inet_ntop(AF_INET6, &from_lsa->u.sin6.sin6_addr, pa1, sizeof(pa1)), | ||
725 | inet_ntop(AF_INET6, &((struct sockaddr_in6*)to)->sin6_addr, pa2, sizeof(pa2)), | ||
726 | type, pr_type(type), icp->icmp6_code); | ||
727 | |||
728 | read_len -= sizeof(struct icmp6_hdr); | ||
729 | for (i = 0; i < read_len; i++) { | ||
730 | if (i % 16 == 0) | ||
731 | printf("%04x:", i); | ||
732 | if (i % 4 == 0) | ||
733 | bb_putchar(' '); | ||
734 | printf("%02x", p[i]); | ||
735 | if ((i % 16 == 15) && (i + 1 < read_len)) | ||
736 | bb_putchar('\n'); | ||
737 | } | ||
738 | bb_putchar('\n'); | ||
739 | } | ||
740 | # endif | ||
741 | |||
742 | return 0; | ||
743 | } | 796 | } |
744 | #else /* !ENABLE_TRACEROUTE6 */ | 797 | |
745 | static ALWAYS_INLINE int | 798 | static int |
746 | packet_ok(int read_len, | 799 | packet_ok(int read_len, int seq) |
747 | len_and_sockaddr *from_lsa IF_NOT_FEATURE_TRACEROUTE_VERBOSE(UNUSED_PARAM), | ||
748 | struct sockaddr *to UNUSED_PARAM, | ||
749 | int seq) | ||
750 | { | 800 | { |
751 | return packet4_ok(read_len, &from_lsa->u.sin, seq); | 801 | if (!G_ipv6) |
802 | return packet4_ok(read_len, seq); | ||
803 | return packet6_ok(read_len, seq); | ||
752 | } | 804 | } |
805 | |||
806 | #else /* !ENABLE_TRACEROUTE6 */ | ||
807 | |||
808 | # define packet_ok(read_len, seq) packet4_ok(read_len, seq) | ||
809 | |||
753 | #endif | 810 | #endif |
754 | 811 | ||
755 | /* | ||
756 | * Construct an Internet address representation. | ||
757 | * If the -n flag has been supplied, give | ||
758 | * numeric value, otherwise try for symbolic name. | ||
759 | */ | ||
760 | static void | 812 | static void |
761 | print_inetname(const struct sockaddr *from) | 813 | #if !ENABLE_FEATURE_TRACEROUTE_VERBOSE |
814 | print(void) | ||
815 | # define print(len) print() | ||
816 | #else | ||
817 | print(int read_len) | ||
818 | #endif | ||
762 | { | 819 | { |
763 | char *ina = xmalloc_sockaddr2dotted_noport(from); | 820 | char *ina = auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)); |
764 | 821 | ||
765 | if (option_mask32 & OPT_ADDR_NUM) { | 822 | if (option_mask32 & OPT_ADDR_NUM) { |
766 | printf(" %s", ina); | 823 | printf(" %s", ina); |
767 | } else { | 824 | } else { |
768 | char *n = NULL; | 825 | char *n = NULL; |
769 | 826 | if (G_ipv6 | |
770 | if (from->sa_family != AF_INET | 827 | || G.from_lsa->u.sin.sin_addr.s_addr != INADDR_ANY |
771 | || ((struct sockaddr_in*)from)->sin_addr.s_addr != INADDR_ANY | ||
772 | ) { | 828 | ) { |
773 | /* Try to reverse resolve if it is not 0.0.0.0 */ | 829 | /* Reverse resolve if IPV6 or not 0.0.0.0 */ |
774 | n = xmalloc_sockaddr2host_noport((struct sockaddr*)from); | 830 | n = auto_string(xmalloc_sockaddr2host_noport(&G.from_lsa->u.sa)); |
775 | } | 831 | } |
776 | printf(" %s (%s)", (n ? n : ina), ina); | 832 | printf(" %s (%s)", (n ? n : ina), ina); |
777 | free(n); | ||
778 | } | 833 | } |
779 | free(ina); | ||
780 | } | ||
781 | |||
782 | static void | ||
783 | print(int read_len, const struct sockaddr *from, const struct sockaddr *to) | ||
784 | { | ||
785 | print_inetname(from); | ||
786 | 834 | ||
835 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE | ||
787 | if (verbose) { | 836 | if (verbose) { |
788 | char *ina = xmalloc_sockaddr2dotted_noport(to); | 837 | # if ENABLE_TRACEROUTE6 |
789 | #if ENABLE_TRACEROUTE6 | 838 | /* NB: reads from (AF_INET, SOCK_RAW, IPPROTO_ICMP) socket |
790 | if (to->sa_family == AF_INET6) { | 839 | * return the entire IP packet (IOW: they do not strip IP header). |
791 | read_len -= sizeof(struct ip6_hdr); | 840 | * Reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) do strip IPv6 |
841 | * header and return only ICMP6 packet. Weird. | ||
842 | */ | ||
843 | if (G_ipv6) { | ||
844 | /* read_len -= sizeof(struct ip6_hdr); - WRONG! */ | ||
792 | } else | 845 | } else |
793 | #endif | 846 | # endif |
794 | { | 847 | { |
795 | struct ip *ip4packet = (struct ip*)recv_pkt; | 848 | struct ip *ip4packet = (struct ip*)recv_pkt; |
796 | read_len -= ip4packet->ip_hl << 2; | 849 | read_len -= ip4packet->ip_hl << 2; |
797 | } | 850 | } |
798 | printf(" %d bytes to %s", read_len, ina); | 851 | printf(" %d bytes to %s", read_len, |
799 | free(ina); | 852 | auto_string(xmalloc_sockaddr2dotted_noport(G.to)) |
853 | ); | ||
800 | } | 854 | } |
855 | #endif | ||
801 | } | 856 | } |
802 | 857 | ||
803 | static void | 858 | static void |
@@ -807,22 +862,12 @@ print_delta_ms(unsigned t1p, unsigned t2p) | |||
807 | printf(" %u.%03u ms", tt / 1000, tt % 1000); | 862 | printf(" %u.%03u ms", tt / 1000, tt % 1000); |
808 | } | 863 | } |
809 | 864 | ||
810 | /* | 865 | /* Keeping init code in a separate (not inlined!) function |
811 | * Usage: [-dFIlnrvx] [-g gateway] [-i iface] [-f first_ttl] | 866 | * for stack use reduction and better register allocation in main loop. |
812 | * [-m max_ttl] [ -p port] [-q nqueries] [-s src_addr] [-t tos] | ||
813 | * [-w waittime] [-z pausemsecs] host [packetlen]" | ||
814 | */ | 867 | */ |
815 | static int | 868 | static NOINLINE void |
816 | common_traceroute_main(int op, char **argv) | 869 | traceroute_init(int op, char **argv) |
817 | { | 870 | { |
818 | int minpacket; | ||
819 | #ifdef IP_TOS | ||
820 | int tos = 0; | ||
821 | #endif | ||
822 | int max_ttl = 30; | ||
823 | int nprobes = 3; | ||
824 | int first_ttl = 1; | ||
825 | unsigned pausemsecs = 0; | ||
826 | char *source; | 871 | char *source; |
827 | char *device; | 872 | char *device; |
828 | char *tos_str; | 873 | char *tos_str; |
@@ -838,13 +883,16 @@ common_traceroute_main(int op, char **argv) | |||
838 | #else | 883 | #else |
839 | enum { af = AF_INET }; | 884 | enum { af = AF_INET }; |
840 | #endif | 885 | #endif |
841 | int ttl; | 886 | |
842 | int seq; | 887 | /* Ensure the socket fds won't be 0, 1 or 2 */ |
843 | len_and_sockaddr *from_lsa; | 888 | bb_sanitize_stdio(); |
844 | struct sockaddr *lastaddr; | ||
845 | struct sockaddr *to; | ||
846 | 889 | ||
847 | INIT_G(); | 890 | INIT_G(); |
891 | port = 33434; | ||
892 | waittime = 5; | ||
893 | G.first_ttl = 1; | ||
894 | G.nprobes = 3; | ||
895 | G.max_ttl = 30; | ||
848 | 896 | ||
849 | op |= getopt32(argv, "^" | 897 | op |= getopt32(argv, "^" |
850 | OPT_STRING | 898 | OPT_STRING |
@@ -854,43 +902,29 @@ common_traceroute_main(int op, char **argv) | |||
854 | ); | 902 | ); |
855 | argv += optind; | 903 | argv += optind; |
856 | 904 | ||
857 | #if 0 /* IGNORED */ | ||
858 | if (op & OPT_IP_CHKSUM) | ||
859 | bb_error_msg("warning: ip checksums disabled"); | ||
860 | #endif | ||
861 | #ifdef IP_TOS | ||
862 | if (op & OPT_TOS) | ||
863 | tos = xatou_range(tos_str, 0, 255); | ||
864 | #endif | ||
865 | if (op & OPT_MAX_TTL) | 905 | if (op & OPT_MAX_TTL) |
866 | max_ttl = xatou_range(max_ttl_str, 1, 255); | 906 | G.max_ttl = xatou_range(max_ttl_str, 1, 255); |
867 | if (op & OPT_PORT) | 907 | if (op & OPT_PORT) |
868 | port = xatou16(port_str); | 908 | port = xatou16(port_str); |
869 | if (op & OPT_NPROBES) | 909 | if (op & OPT_NPROBES) |
870 | nprobes = xatou_range(nprobes_str, 1, INT_MAX); | 910 | G.nprobes = xatou_range(nprobes_str, 1, INT_MAX); |
871 | if (op & OPT_SOURCE) { | ||
872 | /* | ||
873 | * set the ip source address of the outbound | ||
874 | * probe (e.g., on a multi-homed host). | ||
875 | */ | ||
876 | if (getuid() != 0) | ||
877 | bb_simple_error_msg_and_die(bb_msg_you_must_be_root); | ||
878 | } | ||
879 | if (op & OPT_WAITTIME) | 911 | if (op & OPT_WAITTIME) |
880 | waittime = xatou_range(waittime_str, 1, 24 * 60 * 60); | 912 | waittime = xatou_range(waittime_str, 1, 24 * 60 * 60); |
881 | if (op & OPT_PAUSE_MS) | 913 | if (op & OPT_PAUSE_MS) |
882 | pausemsecs = xatou_range(pausemsecs_str, 0, 60 * 60 * 1000); | 914 | G.pausemsecs = xatou_range(pausemsecs_str, 0, 60 * 60 * 1000); |
883 | if (op & OPT_FIRST_TTL) | 915 | if (op & OPT_FIRST_TTL) |
884 | first_ttl = xatou_range(first_ttl_str, 1, max_ttl); | 916 | G.first_ttl = xatou_range(first_ttl_str, 1, G.max_ttl); |
885 | 917 | ||
886 | /* Process destination and optional packet size */ | 918 | /* Process destination and optional packet size */ |
887 | minpacket = sizeof(struct ip) | 919 | packlen = sizeof(struct ip) |
888 | + SIZEOF_ICMP_HDR | ||
889 | + sizeof(struct outdata_t); | ||
890 | if (!(op & OPT_USE_ICMP)) | ||
891 | minpacket = sizeof(struct ip) | ||
892 | + sizeof(struct udphdr) | 920 | + sizeof(struct udphdr) |
893 | + sizeof(struct outdata_t); | 921 | + sizeof(struct outdata_t); |
922 | if (op & OPT_USE_ICMP) { | ||
923 | packlen = sizeof(struct ip) | ||
924 | + SIZEOF_ICMP_HDR | ||
925 | + sizeof(struct outdata_t); | ||
926 | port = 0; /* on ICMP6 sockets, sendto(ipv6.nonzero_port) throws EINVAL! */ | ||
927 | } | ||
894 | #if ENABLE_TRACEROUTE6 | 928 | #if ENABLE_TRACEROUTE6 |
895 | af = AF_UNSPEC; | 929 | af = AF_UNSPEC; |
896 | if (op & OPT_IPV4) | 930 | if (op & OPT_IPV4) |
@@ -899,49 +933,73 @@ common_traceroute_main(int op, char **argv) | |||
899 | af = AF_INET6; | 933 | af = AF_INET6; |
900 | dest_lsa = xhost_and_af2sockaddr(argv[0], port, af); | 934 | dest_lsa = xhost_and_af2sockaddr(argv[0], port, af); |
901 | af = dest_lsa->u.sa.sa_family; | 935 | af = dest_lsa->u.sa.sa_family; |
902 | if (af == AF_INET6) | 936 | //TODO: make sure af == AF_INET[6]? (FEATURE_UNIX_LOCAL=y allows "local:/PATH" to be translated to AF_UNIX) |
903 | minpacket = sizeof(struct ip6_hdr) | 937 | if (af == AF_INET6) { |
904 | + sizeof(struct udphdr) | 938 | G_ipv6 = 1; |
905 | + sizeof(struct outdata6_t); | 939 | packlen = sizeof(struct ip6_hdr) |
940 | + sizeof(struct udphdr) | ||
941 | + sizeof(struct outdata6_t); | ||
942 | if (op & OPT_USE_ICMP) | ||
943 | packlen = sizeof(struct ip6_hdr) | ||
944 | + SIZEOF_ICMP_HDR | ||
945 | + sizeof(struct outdata6_t); | ||
946 | } | ||
906 | #else | 947 | #else |
907 | dest_lsa = xhost2sockaddr(argv[0], port); | 948 | /* accept only IPv4 addresses */ |
949 | dest_lsa = xhost_and_af2sockaddr(argv[0], port, AF_INET); | ||
950 | #endif | ||
951 | G.from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len); | ||
952 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE | ||
953 | G.to = xzalloc(dest_lsa->len); | ||
908 | #endif | 954 | #endif |
909 | packlen = minpacket; | ||
910 | if (argv[1]) | 955 | if (argv[1]) |
911 | packlen = xatoul_range(argv[1], minpacket, 32 * 1024); | 956 | packlen = xatoul_range(argv[1], packlen, 32 * 1024); |
912 | |||
913 | /* Ensure the socket fds won't be 0, 1 or 2 */ | ||
914 | bb_sanitize_stdio(); | ||
915 | 957 | ||
958 | if (af == AF_INET) { | ||
959 | xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), rcvsock); | ||
960 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE | ||
961 | /* want recvmsg to report target local address (for -v) */ | ||
962 | setsockopt_1(rcvsock, IPPROTO_IP, IP_PKTINFO); | ||
963 | #endif | ||
964 | } | ||
916 | #if ENABLE_TRACEROUTE6 | 965 | #if ENABLE_TRACEROUTE6 |
917 | if (af == AF_INET6) { | 966 | else { |
918 | xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock); | 967 | xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock); |
968 | # if ENABLE_FEATURE_TRACEROUTE_VERBOSE | ||
969 | /* want recvmsg to report target local address (for -v) */ | ||
919 | setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO); | 970 | setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO); |
920 | } else | 971 | # endif |
921 | #endif | ||
922 | { | ||
923 | xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), rcvsock); | ||
924 | } | 972 | } |
925 | 973 | #endif | |
926 | #if TRACEROUTE_SO_DEBUG | 974 | #if TRACEROUTE_SO_DEBUG |
927 | if (op & OPT_DEBUG) | 975 | if (op & OPT_DEBUG) |
928 | setsockopt_SOL_SOCKET_1(rcvsock, SO_DEBUG); | 976 | setsockopt_SOL_SOCKET_1(rcvsock, SO_DEBUG); |
929 | #endif | 977 | #endif |
930 | if (op & OPT_BYPASS_ROUTE) | ||
931 | setsockopt_SOL_SOCKET_1(rcvsock, SO_DONTROUTE); | ||
932 | 978 | ||
979 | { | ||
980 | int snd; | ||
981 | if (af == AF_INET) { | ||
982 | if (op & OPT_USE_ICMP) | ||
983 | snd = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP); | ||
984 | else | ||
985 | snd = xsocket(AF_INET, SOCK_DGRAM, 0); | ||
986 | } | ||
933 | #if ENABLE_TRACEROUTE6 | 987 | #if ENABLE_TRACEROUTE6 |
934 | if (af == AF_INET6) { | 988 | # if defined(__FreeBSD__) |
935 | if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0) | 989 | # define SOL_V6_OPTION SOL_IPV6 |
936 | bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM"); | 990 | # else |
937 | xmove_fd(xsocket(af, SOCK_DGRAM, 0), sndsock); | 991 | # define SOL_V6_OPTION SOL_RAW |
938 | } else | 992 | # endif |
993 | else { | ||
994 | if (setsockopt_int(rcvsock, SOL_V6_OPTION, IPV6_CHECKSUM, 2) != 0) | ||
995 | bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM"); | ||
996 | if (op & OPT_USE_ICMP) | ||
997 | snd = xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); | ||
998 | else | ||
999 | snd = xsocket(AF_INET6, SOCK_DGRAM, 0); | ||
1000 | } | ||
939 | #endif | 1001 | #endif |
940 | { | 1002 | xmove_fd(snd, sndsock); |
941 | if (op & OPT_USE_ICMP) | ||
942 | xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), sndsock); | ||
943 | else | ||
944 | xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sndsock); | ||
945 | } | 1003 | } |
946 | 1004 | ||
947 | #ifdef SO_SNDBUF | 1005 | #ifdef SO_SNDBUF |
@@ -950,8 +1008,10 @@ common_traceroute_main(int op, char **argv) | |||
950 | } | 1008 | } |
951 | #endif | 1009 | #endif |
952 | #ifdef IP_TOS | 1010 | #ifdef IP_TOS |
953 | if ((op & OPT_TOS) && setsockopt_int(sndsock, IPPROTO_IP, IP_TOS, tos) != 0) { | 1011 | if (op & OPT_TOS) { |
954 | bb_perror_msg_and_die("setsockopt(%s) %d", "TOS", tos); | 1012 | int tos = xatou_range(tos_str, 0, 255); |
1013 | if (setsockopt_int(sndsock, IPPROTO_IP, IP_TOS, tos) != 0) | ||
1014 | bb_perror_msg_and_die("setsockopt(%s,%d)", "TOS", tos); | ||
955 | } | 1015 | } |
956 | #endif | 1016 | #endif |
957 | #ifdef IP_DONTFRAG | 1017 | #ifdef IP_DONTFRAG |
@@ -968,23 +1028,30 @@ common_traceroute_main(int op, char **argv) | |||
968 | outip = xzalloc(packlen); | 1028 | outip = xzalloc(packlen); |
969 | 1029 | ||
970 | ident = getpid(); | 1030 | ident = getpid(); |
971 | 1031 | /* we can use native-endian ident, but other Unix ping/traceroute | |
972 | if (!ENABLE_TRACEROUTE6 || af == AF_INET) { | 1032 | * utils use *big-endian pid*, and e.g. ping on our machine may be |
1033 | * *not* from busybox, idents may collide. Follow the convention: | ||
1034 | */ | ||
1035 | ident = htons(ident); | ||
1036 | |||
1037 | outdata = (void*)(outudp + 1); | ||
1038 | if (af == AF_INET) { | ||
973 | if (op & OPT_USE_ICMP) { | 1039 | if (op & OPT_USE_ICMP) { |
974 | ident |= 0x8000; | ||
975 | outicmp->icmp_type = ICMP_ECHO; | 1040 | outicmp->icmp_type = ICMP_ECHO; |
976 | outicmp->icmp_id = htons(ident); | 1041 | /*outicmp->icmp_code = 0; - set by xzalloc */ |
977 | outdata = (struct outdata_t *)((char *)outicmp + SIZEOF_ICMP_HDR); | 1042 | outicmp->icmp_id = ident; |
978 | } else { | 1043 | outdata = (void*)((char *)outicmp + SIZEOF_ICMP_HDR); |
979 | outdata = (struct outdata_t *)(outudp + 1); | ||
980 | } | 1044 | } |
981 | } | 1045 | } |
982 | #if ENABLE_TRACEROUTE6 | 1046 | #if ENABLE_TRACEROUTE6 |
983 | if (af == AF_INET6) { | 1047 | else { |
984 | outdata = (void*)((char*)outip | 1048 | outdata = (void*)(outudp6 + 1); |
985 | + sizeof(struct ip6_hdr) | 1049 | if (op & OPT_USE_ICMP) { |
986 | + sizeof(struct udphdr) | 1050 | outicmp6->icmp_type = ICMP6_ECHO_REQUEST; |
987 | ); | 1051 | /*outicmp->icmp_code = 0; - set by xzalloc */ |
1052 | outicmp6->icmp_id = ident; | ||
1053 | outdata = (void*)((char *)outicmp6 + SIZEOF_ICMP_HDR); | ||
1054 | } | ||
988 | } | 1055 | } |
989 | #endif | 1056 | #endif |
990 | 1057 | ||
@@ -998,6 +1065,8 @@ common_traceroute_main(int op, char **argv) | |||
998 | #else | 1065 | #else |
999 | len_and_sockaddr *source_lsa = xdotted2sockaddr(source, 0); | 1066 | len_and_sockaddr *source_lsa = xdotted2sockaddr(source, 0); |
1000 | #endif | 1067 | #endif |
1068 | if (getuid() != 0) | ||
1069 | bb_simple_error_msg_and_die(bb_msg_you_must_be_root); | ||
1001 | /* Ping4 does this (why?) */ | 1070 | /* Ping4 does this (why?) */ |
1002 | if (af == AF_INET) | 1071 | if (af == AF_INET) |
1003 | if (setsockopt(sndsock, IPPROTO_IP, IP_MULTICAST_IF, | 1072 | if (setsockopt(sndsock, IPPROTO_IP, IP_MULTICAST_IF, |
@@ -1006,36 +1075,24 @@ common_traceroute_main(int op, char **argv) | |||
1006 | //TODO: we can query source port we bound to, | 1075 | //TODO: we can query source port we bound to, |
1007 | // and check it in replies... if we care enough | 1076 | // and check it in replies... if we care enough |
1008 | xbind(sndsock, &source_lsa->u.sa, source_lsa->len); | 1077 | xbind(sndsock, &source_lsa->u.sa, source_lsa->len); |
1009 | free(source_lsa); | 1078 | if (ENABLE_FEATURE_CLEAN_UP) |
1010 | } | 1079 | free(source_lsa); |
1011 | #if ENABLE_TRACEROUTE6 | 1080 | } else { |
1012 | else if (af == AF_INET6) { | ||
1013 | //TODO: why we don't do it for IPv4? | ||
1014 | len_and_sockaddr *source_lsa; | 1081 | len_and_sockaddr *source_lsa; |
1015 | 1082 | ||
1016 | int probe_fd = xsocket(af, SOCK_DGRAM, 0); | ||
1017 | if (op & OPT_DEVICE) | ||
1018 | setsockopt_bindtodevice(probe_fd, device); | ||
1019 | set_nport(&dest_lsa->u.sa, htons(1025)); | ||
1020 | /* dummy connect. makes kernel pick source IP (and port) */ | ||
1021 | xconnect(probe_fd, &dest_lsa->u.sa, dest_lsa->len); | ||
1022 | set_nport(&dest_lsa->u.sa, htons(port)); | 1083 | set_nport(&dest_lsa->u.sa, htons(port)); |
1023 | 1084 | /* Connect makes kernel pick source IP (and port if UDP) */ | |
1024 | /* read IP and port */ | 1085 | xconnect(sndsock, &dest_lsa->u.sa, dest_lsa->len); |
1025 | source_lsa = get_sock_lsa(probe_fd); | 1086 | /* Read IP and port */ |
1087 | source_lsa = get_sock_lsa(sndsock); | ||
1026 | if (source_lsa == NULL) | 1088 | if (source_lsa == NULL) |
1027 | bb_simple_error_msg_and_die("can't get probe addr"); | 1089 | bb_simple_perror_msg_and_die("getsockname"); |
1028 | 1090 | /* bind our recv ICMP socket to this IP (but not port, ICMP has no ports) */ | |
1029 | close(probe_fd); | 1091 | //set_nport(&source_lsa->u.sa, 0); - paranoia, seems to work without this for both ipv4 and ipv6 |
1030 | |||
1031 | /* bind our sockets to this IP (but not port) */ | ||
1032 | set_nport(&source_lsa->u.sa, 0); | ||
1033 | xbind(sndsock, &source_lsa->u.sa, source_lsa->len); | ||
1034 | xbind(rcvsock, &source_lsa->u.sa, source_lsa->len); | 1092 | xbind(rcvsock, &source_lsa->u.sa, source_lsa->len); |
1035 | 1093 | if (ENABLE_FEATURE_CLEAN_UP) | |
1036 | free(source_lsa); | 1094 | free(source_lsa); |
1037 | } | 1095 | } |
1038 | #endif | ||
1039 | 1096 | ||
1040 | /* Revert to non-privileged user after opening sockets */ | 1097 | /* Revert to non-privileged user after opening sockets */ |
1041 | xsetgid(getgid()); | 1098 | xsetgid(getgid()); |
@@ -1043,169 +1100,177 @@ common_traceroute_main(int op, char **argv) | |||
1043 | 1100 | ||
1044 | dest_str = xmalloc_sockaddr2dotted_noport(&dest_lsa->u.sa); | 1101 | dest_str = xmalloc_sockaddr2dotted_noport(&dest_lsa->u.sa); |
1045 | printf("traceroute to %s (%s)", argv[0], dest_str); | 1102 | printf("traceroute to %s (%s)", argv[0], dest_str); |
1046 | if (ENABLE_FEATURE_CLEAN_UP) { | 1103 | if (ENABLE_FEATURE_CLEAN_UP) |
1047 | free(dest_str); | 1104 | free(dest_str); |
1048 | } | ||
1049 | 1105 | ||
1050 | if (op & OPT_SOURCE) | 1106 | if (op & OPT_SOURCE) |
1051 | printf(" from %s", source); | 1107 | printf(" from %s", source); |
1052 | printf(", %d hops max, %d byte packets\n", max_ttl, packlen); | 1108 | printf(", %d hops max, %d byte packets\n", G.max_ttl, packlen); |
1109 | } | ||
1110 | |||
1111 | static int | ||
1112 | common_traceroute_main(int op, char **argv) | ||
1113 | { | ||
1114 | int ttl; | ||
1115 | int seq; | ||
1116 | struct sockaddr *lastaddr; | ||
1117 | |||
1118 | traceroute_init(op, argv); | ||
1053 | 1119 | ||
1054 | from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len); | ||
1055 | lastaddr = xzalloc(dest_lsa->len); | 1120 | lastaddr = xzalloc(dest_lsa->len); |
1056 | to = xzalloc(dest_lsa->len); | ||
1057 | seq = 0; | 1121 | seq = 0; |
1058 | for (ttl = first_ttl; ttl <= max_ttl; ++ttl) { | 1122 | for (ttl = G.first_ttl; ttl <= G.max_ttl; ++ttl) { |
1059 | int probe; | 1123 | int probe; |
1060 | int unreachable = 0; /* counter */ | 1124 | int unreachable = 0; /* counter */ |
1061 | int gotlastaddr = 0; /* flags */ | ||
1062 | int got_there = 0; | 1125 | int got_there = 0; |
1063 | 1126 | ||
1064 | printf("%2d", ttl); | 1127 | printf("%2d", ttl); |
1065 | for (probe = 0; probe < nprobes; ++probe) { | 1128 | for (probe = 0; probe < G.nprobes; ++probe) { |
1066 | int read_len; | ||
1067 | unsigned t1; | 1129 | unsigned t1; |
1068 | unsigned t2; | 1130 | unsigned t2; |
1069 | int left_ms; | 1131 | int left_ms; |
1070 | struct ip *ip; | 1132 | int read_len; |
1133 | int icmp_code; | ||
1071 | 1134 | ||
1072 | fflush_all(); | 1135 | fflush_all(); |
1073 | if (probe != 0 && pausemsecs > 0) | 1136 | if (probe != 0) |
1074 | usleep(pausemsecs * 1000); | 1137 | msleep(G.pausemsecs); |
1075 | 1138 | ||
1076 | send_probe(++seq, ttl); | 1139 | send_probe(++seq, ttl); |
1077 | t2 = t1 = monotonic_us(); | ||
1078 | 1140 | ||
1141 | t2 = t1 = monotonic_us(); | ||
1079 | left_ms = waittime * 1000; | 1142 | left_ms = waittime * 1000; |
1080 | while ((read_len = wait_for_reply(from_lsa, to, &t2, &left_ms)) != 0) { | 1143 | for (;;) { |
1081 | int icmp_code; | 1144 | /* NB: wait_for_reply() fills "G.from_lsa" and "G.to" with |
1082 | 1145 | * "where it came from" and "what local address it arrived to" | |
1083 | /* Recv'ed a packet, or read error */ | 1146 | * addresses. Sets t2 = monotonic_us(), updates left_ms. |
1084 | /* t2 = monotonic_us() - set by wait_for_reply */ | 1147 | */ |
1085 | 1148 | read_len = wait_for_reply(&t2, &left_ms); | |
1086 | if (read_len < 0) | 1149 | |
1087 | continue; | 1150 | if (read_len == 0) { /* there was no packet at all? */ |
1088 | icmp_code = packet_ok(read_len, from_lsa, to, seq); | 1151 | printf(" *"); |
1089 | /* Skip short packet */ | 1152 | goto next_probe; |
1090 | if (icmp_code == 0) | ||
1091 | continue; | ||
1092 | |||
1093 | if (!gotlastaddr | ||
1094 | || (memcmp(lastaddr, &from_lsa->u.sa, from_lsa->len) != 0) | ||
1095 | ) { | ||
1096 | print(read_len, &from_lsa->u.sa, to); | ||
1097 | memcpy(lastaddr, &from_lsa->u.sa, from_lsa->len); | ||
1098 | gotlastaddr = 1; | ||
1099 | } | 1153 | } |
1154 | icmp_code = packet_ok(read_len, seq); | ||
1155 | if (icmp_code != 0) | ||
1156 | break; /* got a good response */ | ||
1157 | /* unrecognized type/code or too short, back to recv */ | ||
1158 | } | ||
1100 | 1159 | ||
1101 | print_delta_ms(t1, t2); | 1160 | if (probe == 0 |
1102 | ip = (struct ip *)recv_pkt; | 1161 | || (memcmp(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len) != 0) |
1162 | ) { | ||
1163 | print(read_len); | ||
1164 | memcpy(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len); | ||
1165 | } | ||
1166 | print_delta_ms(t1, t2); | ||
1167 | if (!G_ipv6) { | ||
1168 | if (op & OPT_TTL_FLAG) { | ||
1169 | struct ip *ip = (struct ip *)recv_pkt; | ||
1170 | printf(" (%d)", ip->ip_ttl); | ||
1171 | } | ||
1172 | } | ||
1103 | 1173 | ||
1104 | if (from_lsa->u.sa.sa_family == AF_INET) | 1174 | /* Got a "time exceeded in transit" icmp message? */ |
1105 | if (op & OPT_TTL_FLAG) | 1175 | if (icmp_code == -1) |
1106 | printf(" (%d)", ip->ip_ttl); | 1176 | continue; |
1107 | 1177 | ||
1108 | /* time exceeded in transit */ | 1178 | icmp_code--; |
1109 | if (icmp_code == -1) | 1179 | switch (icmp_code) { |
1110 | break; | ||
1111 | icmp_code--; | ||
1112 | switch (icmp_code) { | ||
1113 | #if ENABLE_TRACEROUTE6 | 1180 | #if ENABLE_TRACEROUTE6 |
1114 | case ICMP6_DST_UNREACH_NOPORT << 8: | 1181 | case ICMP6_DST_UNREACH_NOPORT << 8: |
1115 | got_there = 1; | 1182 | got_there = 1; |
1116 | break; | 1183 | break; |
1117 | #endif | 1184 | #endif |
1118 | case ICMP_UNREACH_PORT: | 1185 | case ICMP_UNREACH_PORT: { |
1119 | if (ip->ip_ttl <= 1) | 1186 | struct ip *ip = (struct ip *)recv_pkt; |
1120 | printf(" !"); | 1187 | if (ip->ip_ttl <= 1) |
1121 | got_there = 1; | 1188 | printf(" !"); |
1122 | break; | 1189 | got_there = 1; |
1123 | 1190 | break; | |
1124 | case ICMP_UNREACH_NET: | 1191 | } |
1192 | case ICMP_UNREACH_NET: | ||
1125 | #if ENABLE_TRACEROUTE6 && (ICMP6_DST_UNREACH_NOROUTE != ICMP_UNREACH_NET) | 1193 | #if ENABLE_TRACEROUTE6 && (ICMP6_DST_UNREACH_NOROUTE != ICMP_UNREACH_NET) |
1126 | case ICMP6_DST_UNREACH_NOROUTE << 8: | 1194 | case ICMP6_DST_UNREACH_NOROUTE << 8: |
1127 | #endif | 1195 | #endif |
1128 | printf(" !N"); | 1196 | printf(" !N"); |
1129 | ++unreachable; | 1197 | ++unreachable; |
1130 | break; | 1198 | break; |
1131 | case ICMP_UNREACH_HOST: | 1199 | case ICMP_UNREACH_HOST: |
1132 | #if ENABLE_TRACEROUTE6 | 1200 | #if ENABLE_TRACEROUTE6 |
1133 | case ICMP6_DST_UNREACH_ADDR << 8: | 1201 | case ICMP6_DST_UNREACH_ADDR << 8: |
1134 | #endif | 1202 | #endif |
1135 | printf(" !H"); | 1203 | printf(" !H"); |
1136 | ++unreachable; | 1204 | ++unreachable; |
1137 | break; | 1205 | break; |
1138 | case ICMP_UNREACH_PROTOCOL: | 1206 | case ICMP_UNREACH_PROTOCOL: |
1139 | printf(" !P"); | 1207 | printf(" !P"); |
1140 | got_there = 1; | 1208 | got_there = 1; |
1141 | break; | 1209 | break; |
1142 | case ICMP_UNREACH_NEEDFRAG: | 1210 | case ICMP_UNREACH_NEEDFRAG: |
1143 | printf(" !F-%d", pmtu); | 1211 | printf(" !F-%d", pmtu); |
1144 | ++unreachable; | 1212 | ++unreachable; |
1145 | break; | 1213 | break; |
1146 | case ICMP_UNREACH_SRCFAIL: | 1214 | case ICMP_UNREACH_SRCFAIL: |
1147 | #if ENABLE_TRACEROUTE6 | 1215 | #if ENABLE_TRACEROUTE6 |
1148 | case ICMP6_DST_UNREACH_ADMIN << 8: | 1216 | case ICMP6_DST_UNREACH_ADMIN << 8: |
1149 | #endif | 1217 | #endif |
1150 | printf(" !S"); | 1218 | printf(" !S"); |
1151 | ++unreachable; | 1219 | ++unreachable; |
1152 | break; | ||
1153 | case ICMP_UNREACH_FILTER_PROHIB: | ||
1154 | case ICMP_UNREACH_NET_PROHIB: /* misuse */ | ||
1155 | printf(" !A"); | ||
1156 | ++unreachable; | ||
1157 | break; | ||
1158 | case ICMP_UNREACH_HOST_PROHIB: | ||
1159 | printf(" !C"); | ||
1160 | ++unreachable; | ||
1161 | break; | ||
1162 | case ICMP_UNREACH_HOST_PRECEDENCE: | ||
1163 | printf(" !V"); | ||
1164 | ++unreachable; | ||
1165 | break; | ||
1166 | case ICMP_UNREACH_PRECEDENCE_CUTOFF: | ||
1167 | printf(" !C"); | ||
1168 | ++unreachable; | ||
1169 | break; | ||
1170 | case ICMP_UNREACH_NET_UNKNOWN: | ||
1171 | case ICMP_UNREACH_HOST_UNKNOWN: | ||
1172 | printf(" !U"); | ||
1173 | ++unreachable; | ||
1174 | break; | ||
1175 | case ICMP_UNREACH_ISOLATED: | ||
1176 | printf(" !I"); | ||
1177 | ++unreachable; | ||
1178 | break; | ||
1179 | case ICMP_UNREACH_TOSNET: | ||
1180 | case ICMP_UNREACH_TOSHOST: | ||
1181 | printf(" !T"); | ||
1182 | ++unreachable; | ||
1183 | break; | ||
1184 | default: | ||
1185 | printf(" !<%d>", icmp_code); | ||
1186 | ++unreachable; | ||
1187 | break; | ||
1188 | } | ||
1189 | break; | 1220 | break; |
1190 | } /* while (wait and read a packet) */ | 1221 | case ICMP_UNREACH_FILTER_PROHIB: |
1191 | 1222 | case ICMP_UNREACH_NET_PROHIB: /* misuse */ | |
1192 | /* there was no packet at all? */ | 1223 | printf(" !A"); |
1193 | if (read_len == 0) | 1224 | ++unreachable; |
1194 | printf(" *"); | 1225 | break; |
1226 | case ICMP_UNREACH_HOST_PROHIB: | ||
1227 | printf(" !C"); | ||
1228 | ++unreachable; | ||
1229 | break; | ||
1230 | case ICMP_UNREACH_HOST_PRECEDENCE: | ||
1231 | printf(" !V"); | ||
1232 | ++unreachable; | ||
1233 | break; | ||
1234 | case ICMP_UNREACH_PRECEDENCE_CUTOFF: | ||
1235 | printf(" !C"); | ||
1236 | ++unreachable; | ||
1237 | break; | ||
1238 | case ICMP_UNREACH_NET_UNKNOWN: | ||
1239 | case ICMP_UNREACH_HOST_UNKNOWN: | ||
1240 | printf(" !U"); | ||
1241 | ++unreachable; | ||
1242 | break; | ||
1243 | case ICMP_UNREACH_ISOLATED: | ||
1244 | printf(" !I"); | ||
1245 | ++unreachable; | ||
1246 | break; | ||
1247 | case ICMP_UNREACH_TOSNET: | ||
1248 | case ICMP_UNREACH_TOSHOST: | ||
1249 | printf(" !T"); | ||
1250 | ++unreachable; | ||
1251 | break; | ||
1252 | default: | ||
1253 | printf(" !<%d>", icmp_code); | ||
1254 | ++unreachable; | ||
1255 | break; | ||
1256 | } | ||
1257 | next_probe: ; | ||
1195 | } /* for (nprobes) */ | 1258 | } /* for (nprobes) */ |
1196 | 1259 | ||
1197 | bb_putchar('\n'); | 1260 | bb_putchar('\n'); |
1198 | if (got_there | 1261 | if (got_there |
1199 | || (unreachable > 0 && unreachable >= nprobes - 1) | 1262 | || (unreachable > 0 && unreachable >= G.nprobes - 1) |
1200 | ) { | 1263 | ) { |
1201 | break; | 1264 | break; |
1202 | } | 1265 | } |
1203 | } | 1266 | } |
1204 | 1267 | ||
1205 | if (ENABLE_FEATURE_CLEAN_UP) { | 1268 | if (ENABLE_FEATURE_CLEAN_UP) { |
1206 | free(to); | 1269 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE |
1270 | free(G.to); | ||
1271 | #endif | ||
1207 | free(lastaddr); | 1272 | free(lastaddr); |
1208 | free(from_lsa); | 1273 | free(G.from_lsa); |
1209 | } | 1274 | } |
1210 | 1275 | ||
1211 | return 0; | 1276 | return 0; |
diff --git a/networking/tunctl.c b/networking/tunctl.c index 0f010e196..97e6917aa 100644 --- a/networking/tunctl.c +++ b/networking/tunctl.c | |||
@@ -28,16 +28,16 @@ | |||
28 | //kbuild:lib-$(CONFIG_TUNCTL) += tunctl.o | 28 | //kbuild:lib-$(CONFIG_TUNCTL) += tunctl.o |
29 | 29 | ||
30 | //usage:#define tunctl_trivial_usage | 30 | //usage:#define tunctl_trivial_usage |
31 | //usage: "[-f device] ([-t name] | -d name)" IF_FEATURE_TUNCTL_UG(" [-u owner] [-g group] [-b]") | 31 | //usage: "[-f DEVICE] [-t NAME | -d NAME]" IF_FEATURE_TUNCTL_UG(" [-u USER] [-g GRP] [-b]") |
32 | //usage:#define tunctl_full_usage "\n\n" | 32 | //usage:#define tunctl_full_usage "\n\n" |
33 | //usage: "Create or delete tun interfaces\n" | 33 | //usage: "Create or delete TUN/TAP interfaces\n" |
34 | //usage: "\n -f name tun device (/dev/net/tun)" | 34 | //usage: "\n -f DEV TUN device (default /dev/net/tun)" |
35 | //usage: "\n -t name Create iface 'name'" | 35 | //usage: "\n -t NAME Create iface (default: tapN)" |
36 | //usage: "\n -d name Delete iface 'name'" | 36 | //usage: "\n -d NAME Delete iface" |
37 | //usage: IF_FEATURE_TUNCTL_UG( | 37 | //usage: IF_FEATURE_TUNCTL_UG( |
38 | //usage: "\n -u owner Set iface owner" | 38 | //usage: "\n -u USER Set iface owner" |
39 | //usage: "\n -g group Set iface group" | 39 | //usage: "\n -g GRP Set iface group" |
40 | //usage: "\n -b Brief output" | 40 | //usage: "\n -b Brief output" |
41 | //usage: ) | 41 | //usage: ) |
42 | //usage: | 42 | //usage: |
43 | //usage:#define tunctl_example_usage | 43 | //usage:#define tunctl_example_usage |
diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src index 7d04bb246..8c8c11c26 100644 --- a/networking/udhcp/Config.src +++ b/networking/udhcp/Config.src | |||
@@ -104,6 +104,14 @@ INSERT | |||
104 | comment "Common options for DHCP applets" | 104 | comment "Common options for DHCP applets" |
105 | depends on UDHCPD || UDHCPC || UDHCPC6 || DHCPRELAY | 105 | depends on UDHCPD || UDHCPC || UDHCPC6 || DHCPRELAY |
106 | 106 | ||
107 | config UDHCPC_DEFAULT_INTERFACE | ||
108 | string "Default interface name" | ||
109 | default "eth0" | ||
110 | depends on UDHCPC || UDHCPC6 | ||
111 | help | ||
112 | The interface that will be used if no other interface is | ||
113 | specified on the commandline. | ||
114 | |||
107 | config FEATURE_UDHCP_PORT | 115 | config FEATURE_UDHCP_PORT |
108 | bool "Enable '-P port' option for udhcpd and udhcpc" | 116 | bool "Enable '-P port' option for udhcpd and udhcpc" |
109 | default n | 117 | default n |
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 3cbd2d3c8..cc0abd269 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
@@ -343,7 +343,8 @@ int udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, | |||
343 | 343 | ||
344 | int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, | 344 | int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, |
345 | uint32_t source_nip, int source_port, | 345 | uint32_t source_nip, int source_port, |
346 | uint32_t dest_nip, int dest_port) FAST_FUNC; | 346 | uint32_t dest_nip, int dest_port, |
347 | const char *ifname) FAST_FUNC; | ||
347 | 348 | ||
348 | void udhcp_sp_setup(void) FAST_FUNC; | 349 | void udhcp_sp_setup(void) FAST_FUNC; |
349 | void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; | 350 | void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; |
diff --git a/networking/udhcp/d6_common.h b/networking/udhcp/d6_common.h index 688f5d6c7..9dfde7709 100644 --- a/networking/udhcp/d6_common.h +++ b/networking/udhcp/d6_common.h | |||
@@ -159,18 +159,16 @@ int FAST_FUNC d6_recv_kernel_packet( | |||
159 | struct d6_packet *packet, int fd | 159 | struct d6_packet *packet, int fd |
160 | ); | 160 | ); |
161 | 161 | ||
162 | int FAST_FUNC d6_send_raw_packet( | 162 | int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( |
163 | struct d6_packet *d6_pkt, unsigned d6_pkt_size, | 163 | struct d6_packet *d6_pkt, unsigned d6_pkt_size, |
164 | struct in6_addr *src_ipv6, int source_port, | 164 | struct in6_addr *src_ipv6, int source_port, |
165 | struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp, | 165 | struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp |
166 | int ifindex | ||
167 | ); | 166 | ); |
168 | 167 | ||
169 | int FAST_FUNC d6_send_kernel_packet( | 168 | int FAST_FUNC d6_send_kernel_packet_from_client_data_ifindex( |
170 | struct d6_packet *d6_pkt, unsigned d6_pkt_size, | 169 | struct d6_packet *d6_pkt, unsigned d6_pkt_size, |
171 | struct in6_addr *src_ipv6, int source_port, | 170 | struct in6_addr *src_ipv6, int source_port, |
172 | struct in6_addr *dst_ipv6, int dest_port, | 171 | struct in6_addr *dst_ipv6, int dest_port |
173 | int ifindex | ||
174 | ); | 172 | ); |
175 | 173 | ||
176 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 | 174 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 |
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index ac8af91d3..fbdaa99bd 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c | |||
@@ -558,11 +558,10 @@ static int d6_mcast_from_client_data_ifindex(struct d6_packet *packet, uint8_t * | |||
558 | 0x33, 0x33, 0x00, 0x01, 0x00, 0x02, | 558 | 0x33, 0x33, 0x00, 0x01, 0x00, 0x02, |
559 | }; | 559 | }; |
560 | 560 | ||
561 | return d6_send_raw_packet( | 561 | return d6_send_raw_packet_from_client_data_ifindex( |
562 | packet, (end - (uint8_t*) packet), | 562 | packet, (end - (uint8_t*) packet), |
563 | /*src*/ &client6_data.ll_ip6, CLIENT_PORT6, | 563 | /*src*/ &client6_data.ll_ip6, CLIENT_PORT6, |
564 | /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_DHCP6MCAST_ADDR, | 564 | /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_DHCP6MCAST_ADDR |
565 | client_data.ifindex | ||
566 | ); | 565 | ); |
567 | } | 566 | } |
568 | 567 | ||
@@ -864,11 +863,10 @@ static NOINLINE int send_d6_renew(uint32_t xid, struct in6_addr *server_ipv6, st | |||
864 | 863 | ||
865 | bb_info_msg("sending %s", "renew"); | 864 | bb_info_msg("sending %s", "renew"); |
866 | if (server_ipv6) | 865 | if (server_ipv6) |
867 | return d6_send_kernel_packet( | 866 | return d6_send_kernel_packet_from_client_data_ifindex( |
868 | &packet, (opt_ptr - (uint8_t*) &packet), | 867 | &packet, (opt_ptr - (uint8_t*) &packet), |
869 | our_cur_ipv6, CLIENT_PORT6, | 868 | our_cur_ipv6, CLIENT_PORT6, |
870 | server_ipv6, SERVER_PORT6, | 869 | server_ipv6, SERVER_PORT6 |
871 | client_data.ifindex | ||
872 | ); | 870 | ); |
873 | return d6_mcast_from_client_data_ifindex(&packet, opt_ptr); | 871 | return d6_mcast_from_client_data_ifindex(&packet, opt_ptr); |
874 | } | 872 | } |
@@ -893,11 +891,10 @@ int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) | |||
893 | opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); | 891 | opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); |
894 | 892 | ||
895 | bb_info_msg("sending %s", "release"); | 893 | bb_info_msg("sending %s", "release"); |
896 | return d6_send_kernel_packet( | 894 | return d6_send_kernel_packet_from_client_data_ifindex( |
897 | &packet, (opt_ptr - (uint8_t*) &packet), | 895 | &packet, (opt_ptr - (uint8_t*) &packet), |
898 | our_cur_ipv6, CLIENT_PORT6, | 896 | our_cur_ipv6, CLIENT_PORT6, |
899 | server_ipv6, SERVER_PORT6, | 897 | server_ipv6, SERVER_PORT6 |
900 | client_data.ifindex | ||
901 | ); | 898 | ); |
902 | } | 899 | } |
903 | 900 | ||
@@ -1164,9 +1161,9 @@ static void client_background(void) | |||
1164 | //usage:#endif | 1161 | //usage:#endif |
1165 | //usage:#define udhcpc6_trivial_usage | 1162 | //usage:#define udhcpc6_trivial_usage |
1166 | //usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"odR] [-i IFACE] [-r IPv6] [-s PROG] [-p PIDFILE]\n" | 1163 | //usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"odR] [-i IFACE] [-r IPv6] [-s PROG] [-p PIDFILE]\n" |
1167 | //usage: " [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]") | 1164 | //usage: " [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P PORT]") |
1168 | //usage:#define udhcpc6_full_usage "\n" | 1165 | //usage:#define udhcpc6_full_usage "\n" |
1169 | //usage: "\n -i IFACE Interface to use (default eth0)" | 1166 | //usage: "\n -i IFACE Interface to use (default "CONFIG_UDHCPC_DEFAULT_INTERFACE")" |
1170 | //usage: "\n -p FILE Create pidfile" | 1167 | //usage: "\n -p FILE Create pidfile" |
1171 | //usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" | 1168 | //usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" |
1172 | //usage: "\n -B Request broadcast replies" | 1169 | //usage: "\n -B Request broadcast replies" |
@@ -1182,7 +1179,7 @@ static void client_background(void) | |||
1182 | //usage: "\n -R Release IP on exit" | 1179 | //usage: "\n -R Release IP on exit" |
1183 | //usage: "\n -S Log to syslog too" | 1180 | //usage: "\n -S Log to syslog too" |
1184 | //usage: IF_FEATURE_UDHCP_PORT( | 1181 | //usage: IF_FEATURE_UDHCP_PORT( |
1185 | //usage: "\n -P N Use port N (default 546)" | 1182 | //usage: "\n -P PORT Use PORT (default 546)" |
1186 | //usage: ) | 1183 | //usage: ) |
1187 | ////usage: IF_FEATURE_UDHCPC_ARPING( | 1184 | ////usage: IF_FEATURE_UDHCPC_ARPING( |
1188 | ////usage: "\n -a Use arping to validate offered address" | 1185 | ////usage: "\n -a Use arping to validate offered address" |
@@ -1234,7 +1231,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1234 | /* Default options */ | 1231 | /* Default options */ |
1235 | IF_FEATURE_UDHCP_PORT(SERVER_PORT6 = 547;) | 1232 | IF_FEATURE_UDHCP_PORT(SERVER_PORT6 = 547;) |
1236 | IF_FEATURE_UDHCP_PORT(CLIENT_PORT6 = 546;) | 1233 | IF_FEATURE_UDHCP_PORT(CLIENT_PORT6 = 546;) |
1237 | client_data.interface = "eth0"; | 1234 | client_data.interface = CONFIG_UDHCPC_DEFAULT_INTERFACE; |
1238 | client_data.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; | 1235 | client_data.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; |
1239 | client_data.sockfd = -1; | 1236 | client_data.sockfd = -1; |
1240 | 1237 | ||
diff --git a/networking/udhcp/d6_packet.c b/networking/udhcp/d6_packet.c index 167a813e3..172f8e1ab 100644 --- a/networking/udhcp/d6_packet.c +++ b/networking/udhcp/d6_packet.c | |||
@@ -6,6 +6,7 @@ | |||
6 | */ | 6 | */ |
7 | #include "common.h" | 7 | #include "common.h" |
8 | #include "d6_common.h" | 8 | #include "d6_common.h" |
9 | #include "dhcpc.h" | ||
9 | #include "dhcpd.h" | 10 | #include "dhcpd.h" |
10 | #include <netinet/in.h> | 11 | #include <netinet/in.h> |
11 | #include <netinet/if_ether.h> | 12 | #include <netinet/if_ether.h> |
@@ -50,11 +51,10 @@ int FAST_FUNC d6_recv_kernel_packet(struct in6_addr *peer_ipv6 | |||
50 | } | 51 | } |
51 | 52 | ||
52 | /* Construct a ipv6+udp header for a packet, send packet */ | 53 | /* Construct a ipv6+udp header for a packet, send packet */ |
53 | int FAST_FUNC d6_send_raw_packet( | 54 | int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( |
54 | struct d6_packet *d6_pkt, unsigned d6_pkt_size, | 55 | struct d6_packet *d6_pkt, unsigned d6_pkt_size, |
55 | struct in6_addr *src_ipv6, int source_port, | 56 | struct in6_addr *src_ipv6, int source_port, |
56 | struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp, | 57 | struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp) |
57 | int ifindex) | ||
58 | { | 58 | { |
59 | struct sockaddr_ll dest_sll; | 59 | struct sockaddr_ll dest_sll; |
60 | struct ip6_udp_d6_packet packet; | 60 | struct ip6_udp_d6_packet packet; |
@@ -74,7 +74,7 @@ int FAST_FUNC d6_send_raw_packet( | |||
74 | 74 | ||
75 | dest_sll.sll_family = AF_PACKET; | 75 | dest_sll.sll_family = AF_PACKET; |
76 | dest_sll.sll_protocol = htons(ETH_P_IPV6); | 76 | dest_sll.sll_protocol = htons(ETH_P_IPV6); |
77 | dest_sll.sll_ifindex = ifindex; | 77 | dest_sll.sll_ifindex = client_data.ifindex; |
78 | /*dest_sll.sll_hatype = ARPHRD_???;*/ | 78 | /*dest_sll.sll_hatype = ARPHRD_???;*/ |
79 | /*dest_sll.sll_pkttype = PACKET_???;*/ | 79 | /*dest_sll.sll_pkttype = PACKET_???;*/ |
80 | dest_sll.sll_halen = 6; | 80 | dest_sll.sll_halen = 6; |
@@ -103,8 +103,8 @@ int FAST_FUNC d6_send_raw_packet( | |||
103 | */ | 103 | */ |
104 | packet.ip6.ip6_hlim = IPPROTO_UDP; | 104 | packet.ip6.ip6_hlim = IPPROTO_UDP; |
105 | packet.udp.check = inet_cksum( | 105 | packet.udp.check = inet_cksum( |
106 | (uint8_t *)&packet + 4, | 106 | (uint8_t *)&packet + 4, |
107 | offsetof(struct ip6_udp_d6_packet, data) - 4 + d6_pkt_size | 107 | offsetof(struct ip6_udp_d6_packet, data) - 4 + d6_pkt_size |
108 | ); | 108 | ); |
109 | /* fix 'hop limit' and 'next header' after UDP checksumming */ | 109 | /* fix 'hop limit' and 'next header' after UDP checksumming */ |
110 | packet.ip6.ip6_hlim = 1; /* observed Windows machines to use hlim=1 */ | 110 | packet.ip6.ip6_hlim = 1; /* observed Windows machines to use hlim=1 */ |
@@ -126,11 +126,10 @@ int FAST_FUNC d6_send_raw_packet( | |||
126 | } | 126 | } |
127 | 127 | ||
128 | /* Let the kernel do all the work for packet generation */ | 128 | /* Let the kernel do all the work for packet generation */ |
129 | int FAST_FUNC d6_send_kernel_packet( | 129 | int FAST_FUNC d6_send_kernel_packet_from_client_data_ifindex( |
130 | struct d6_packet *d6_pkt, unsigned d6_pkt_size, | 130 | struct d6_packet *d6_pkt, unsigned d6_pkt_size, |
131 | struct in6_addr *src_ipv6, int source_port, | 131 | struct in6_addr *src_ipv6, int source_port, |
132 | struct in6_addr *dst_ipv6, int dest_port, | 132 | struct in6_addr *dst_ipv6, int dest_port) |
133 | int ifindex) | ||
134 | { | 133 | { |
135 | struct sockaddr_in6 sa; | 134 | struct sockaddr_in6 sa; |
136 | int fd; | 135 | int fd; |
@@ -157,7 +156,7 @@ int FAST_FUNC d6_send_kernel_packet( | |||
157 | sa.sin6_family = AF_INET6; | 156 | sa.sin6_family = AF_INET6; |
158 | sa.sin6_port = htons(dest_port); | 157 | sa.sin6_port = htons(dest_port); |
159 | sa.sin6_addr = *dst_ipv6; /* struct copy */ | 158 | sa.sin6_addr = *dst_ipv6; /* struct copy */ |
160 | sa.sin6_scope_id = ifindex; | 159 | sa.sin6_scope_id = client_data.ifindex; |
161 | if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { | 160 | if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { |
162 | msg = "connect"; | 161 | msg = "connect"; |
163 | goto ret_close; | 162 | goto ret_close; |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 66aa38c20..922c71ebd 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -702,7 +702,8 @@ static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t | |||
702 | if (server) | 702 | if (server) |
703 | return udhcp_send_kernel_packet(packet, | 703 | return udhcp_send_kernel_packet(packet, |
704 | ciaddr, CLIENT_PORT, | 704 | ciaddr, CLIENT_PORT, |
705 | server, SERVER_PORT); | 705 | server, SERVER_PORT, |
706 | client_data.interface); | ||
706 | return raw_bcast_from_client_data_ifindex(packet, ciaddr); | 707 | return raw_bcast_from_client_data_ifindex(packet, ciaddr); |
707 | } | 708 | } |
708 | 709 | ||
@@ -1195,7 +1196,7 @@ static void client_background(void) | |||
1195 | //usage: " [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s PROG] [-p PIDFILE]\n" | 1196 | //usage: " [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s PROG] [-p PIDFILE]\n" |
1196 | //usage: " [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]..." | 1197 | //usage: " [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]..." |
1197 | //usage:#define udhcpc_full_usage "\n" | 1198 | //usage:#define udhcpc_full_usage "\n" |
1198 | //usage: "\n -i IFACE Interface to use (default eth0)" | 1199 | //usage: "\n -i IFACE Interface to use (default "CONFIG_UDHCPC_DEFAULT_INTERFACE")" |
1199 | //usage: IF_FEATURE_UDHCP_PORT( | 1200 | //usage: IF_FEATURE_UDHCP_PORT( |
1200 | //usage: "\n -P PORT Use PORT (default 68)" | 1201 | //usage: "\n -P PORT Use PORT (default 68)" |
1201 | //usage: ) | 1202 | //usage: ) |
@@ -1264,7 +1265,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1264 | /* Default options */ | 1265 | /* Default options */ |
1265 | IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;) | 1266 | IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;) |
1266 | IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;) | 1267 | IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;) |
1267 | client_data.interface = "eth0"; | 1268 | client_data.interface = CONFIG_UDHCPC_DEFAULT_INTERFACE; |
1268 | client_data.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; | 1269 | client_data.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; |
1269 | client_data.sockfd = -1; | 1270 | client_data.sockfd = -1; |
1270 | str_V = "udhcp "BB_VER; | 1271 | str_V = "udhcp "BB_VER; |
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index acfdaa8c3..cd32cb437 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
@@ -27,7 +27,7 @@ | |||
27 | //kbuild:lib-$(CONFIG_FEATURE_UDHCP_RFC3397) += domain_codec.o | 27 | //kbuild:lib-$(CONFIG_FEATURE_UDHCP_RFC3397) += domain_codec.o |
28 | 28 | ||
29 | //usage:#define udhcpd_trivial_usage | 29 | //usage:#define udhcpd_trivial_usage |
30 | //usage: "[-fS] [-I ADDR]" IF_FEATURE_UDHCP_PORT(" [-P N]") " [CONFFILE]" | 30 | //usage: "[-fS] [-I ADDR]" IF_FEATURE_UDHCP_PORT(" [-P PORT]") " [CONFFILE]" |
31 | //usage:#define udhcpd_full_usage "\n\n" | 31 | //usage:#define udhcpd_full_usage "\n\n" |
32 | //usage: "DHCP server\n" | 32 | //usage: "DHCP server\n" |
33 | //usage: "\n -f Run in foreground" | 33 | //usage: "\n -f Run in foreground" |
@@ -35,7 +35,7 @@ | |||
35 | //usage: "\n -I ADDR Local address" | 35 | //usage: "\n -I ADDR Local address" |
36 | //usage: "\n -a MSEC Timeout for ARP ping (default 2000)" | 36 | //usage: "\n -a MSEC Timeout for ARP ping (default 2000)" |
37 | //usage: IF_FEATURE_UDHCP_PORT( | 37 | //usage: IF_FEATURE_UDHCP_PORT( |
38 | //usage: "\n -P N Use port N (default 67)" | 38 | //usage: "\n -P PORT Use PORT (default 67)" |
39 | //usage: ) | 39 | //usage: ) |
40 | //usage: "\nSignals:" | 40 | //usage: "\nSignals:" |
41 | //usage: "\n USR1 Update lease file" | 41 | //usage: "\n USR1 Update lease file" |
@@ -398,7 +398,7 @@ struct config_keyword { | |||
398 | 398 | ||
399 | #define OFS(field) offsetof(struct server_data_t, field) | 399 | #define OFS(field) offsetof(struct server_data_t, field) |
400 | 400 | ||
401 | static const struct config_keyword keywords[] = { | 401 | static const struct config_keyword keywords[] ALIGN_PTR = { |
402 | /* keyword handler variable address default */ | 402 | /* keyword handler variable address default */ |
403 | {"start" , udhcp_str2nip , OFS(start_ip ), "192.168.0.20"}, | 403 | {"start" , udhcp_str2nip , OFS(start_ip ), "192.168.0.20"}, |
404 | {"end" , udhcp_str2nip , OFS(end_ip ), "192.168.0.254"}, | 404 | {"end" , udhcp_str2nip , OFS(end_ip ), "192.168.0.254"}, |
@@ -612,7 +612,8 @@ static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt) | |||
612 | 612 | ||
613 | udhcp_send_kernel_packet(dhcp_pkt, | 613 | udhcp_send_kernel_packet(dhcp_pkt, |
614 | server_data.server_nip, SERVER_PORT, | 614 | server_data.server_nip, SERVER_PORT, |
615 | dhcp_pkt->gateway_nip, SERVER_PORT); | 615 | dhcp_pkt->gateway_nip, SERVER_PORT, |
616 | server_data.interface); | ||
616 | } | 617 | } |
617 | 618 | ||
618 | static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast) | 619 | static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast) |
diff --git a/networking/udhcp/dumpleases.c b/networking/udhcp/dumpleases.c index 70d2d1434..1e9405205 100644 --- a/networking/udhcp/dumpleases.c +++ b/networking/udhcp/dumpleases.c | |||
@@ -10,18 +10,10 @@ | |||
10 | //usage: "[-r|-a] [-d] [-f LEASEFILE]" | 10 | //usage: "[-r|-a] [-d] [-f LEASEFILE]" |
11 | //usage:#define dumpleases_full_usage "\n\n" | 11 | //usage:#define dumpleases_full_usage "\n\n" |
12 | //usage: "Display DHCP leases granted by udhcpd\n" | 12 | //usage: "Display DHCP leases granted by udhcpd\n" |
13 | //usage: IF_LONG_OPTS( | ||
14 | //usage: "\n -f,--file FILE Lease file" | ||
15 | //usage: "\n -r,--remaining Show remaining time" | ||
16 | //usage: "\n -a,--absolute Show expiration time" | ||
17 | //usage: "\n -d,--decimal Show time in seconds" | ||
18 | //usage: ) | ||
19 | //usage: IF_NOT_LONG_OPTS( | ||
20 | //usage: "\n -f FILE Lease file" | 13 | //usage: "\n -f FILE Lease file" |
21 | //usage: "\n -r Show remaining time" | 14 | //usage: "\n -r Show remaining time" |
22 | //usage: "\n -a Show expiration time" | 15 | //usage: "\n -a Show expiration time" |
23 | //usage: "\n -d Show time in seconds" | 16 | //usage: "\n -d Show time in seconds" |
24 | //usage: ) | ||
25 | 17 | ||
26 | #include "common.h" | 18 | #include "common.h" |
27 | #include "dhcpd.h" | 19 | #include "dhcpd.h" |
diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c index 51374646d..4d8e005d4 100644 --- a/networking/udhcp/packet.c +++ b/networking/udhcp/packet.c | |||
@@ -189,7 +189,8 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, | |||
189 | /* Let the kernel do all the work for packet generation */ | 189 | /* Let the kernel do all the work for packet generation */ |
190 | int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, | 190 | int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, |
191 | uint32_t source_nip, int source_port, | 191 | uint32_t source_nip, int source_port, |
192 | uint32_t dest_nip, int dest_port) | 192 | uint32_t dest_nip, int dest_port, |
193 | const char *ifname) | ||
193 | { | 194 | { |
194 | struct sockaddr_in sa; | 195 | struct sockaddr_in sa; |
195 | unsigned padding; | 196 | unsigned padding; |
@@ -204,6 +205,21 @@ int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, | |||
204 | } | 205 | } |
205 | setsockopt_reuseaddr(fd); | 206 | setsockopt_reuseaddr(fd); |
206 | 207 | ||
208 | /* If interface carrier goes down, unless we | ||
209 | * bind socket to a particular netdev, the packet | ||
210 | * can go out through another interface, eg. via | ||
211 | * default route despite being bound to a specific | ||
212 | * source IP. As such, bind to device hard and fail | ||
213 | * otherwise. Sending renewal packets on foreign | ||
214 | * interfaces makes no sense. | ||
215 | */ | ||
216 | if (ifname) { | ||
217 | if (setsockopt_bindtodevice(fd, ifname) < 0) { | ||
218 | msg = "bindtodevice"; | ||
219 | goto ret_close; | ||
220 | } | ||
221 | } | ||
222 | |||
207 | memset(&sa, 0, sizeof(sa)); | 223 | memset(&sa, 0, sizeof(sa)); |
208 | sa.sin_family = AF_INET; | 224 | sa.sin_family = AF_INET; |
209 | sa.sin_port = htons(source_port); | 225 | sa.sin_port = htons(source_port); |
diff --git a/networking/wget.c b/networking/wget.c index 8a967fe20..270eab141 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
@@ -128,19 +128,14 @@ | |||
128 | 128 | ||
129 | //usage:#define wget_trivial_usage | 129 | //usage:#define wget_trivial_usage |
130 | //usage: IF_FEATURE_WGET_LONG_OPTIONS( | 130 | //usage: IF_FEATURE_WGET_LONG_OPTIONS( |
131 | //usage: "[-c|--continue] [--spider] [-q|--quiet] [-O|--output-document FILE]\n" | 131 | //usage: "[-cqS] [--spider] [-O FILE] [-o LOGFILE] [--header 'HEADER: VALUE'] [-Y on/off]\n" |
132 | //usage: " [-o|--output-file FILE] [--header 'header: value'] [-Y|--proxy on/off]\n" | ||
133 | //usage: IF_FEATURE_WGET_OPENSSL( | ||
134 | //usage: " [--no-check-certificate]\n" | ||
135 | //usage: ) | ||
136 | /* Since we ignore these opts, we don't show them in --help */ | 132 | /* Since we ignore these opts, we don't show them in --help */ |
137 | /* //usage: " [--no-cache] [--passive-ftp] [-t TRIES]" */ | 133 | /* //usage: " [--no-cache] [--passive-ftp] [-t TRIES]" */ |
138 | /* //usage: " [-nv] [-nc] [-nH] [-np]" */ | 134 | /* //usage: " [-nv] [-nc] [-nH] [-np]" */ |
139 | //usage: " [-P DIR] [-S|--server-response] [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." | 135 | //usage: " "IF_FEATURE_WGET_OPENSSL("[--no-check-certificate] ")"[-P DIR] [-U AGENT]"IF_FEATURE_WGET_TIMEOUT(" [-T SEC]")" URL..." |
140 | //usage: ) | 136 | //usage: ) |
141 | //usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS( | 137 | //usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS( |
142 | //usage: "[-cq] [-O FILE] [-o FILE] [-Y on/off] [-P DIR] [-S] [-U AGENT]" | 138 | //usage: "[-cqS] [-O FILE] [-o LOGFILE] [-Y on/off] [-P DIR] [-U AGENT]"IF_FEATURE_WGET_TIMEOUT(" [-T SEC]")" URL..." |
143 | //usage: IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." | ||
144 | //usage: ) | 139 | //usage: ) |
145 | //usage:#define wget_full_usage "\n\n" | 140 | //usage:#define wget_full_usage "\n\n" |
146 | //usage: "Retrieve files via HTTP or FTP\n" | 141 | //usage: "Retrieve files via HTTP or FTP\n" |
@@ -158,7 +153,7 @@ | |||
158 | //usage: "\n -T SEC Network read timeout is SEC seconds" | 153 | //usage: "\n -T SEC Network read timeout is SEC seconds" |
159 | //usage: ) | 154 | //usage: ) |
160 | //usage: "\n -O FILE Save to FILE ('-' for stdout)" | 155 | //usage: "\n -O FILE Save to FILE ('-' for stdout)" |
161 | //usage: "\n -o FILE Log messages to FILE" | 156 | //usage: "\n -o LOGFILE Log messages to FILE" |
162 | //usage: "\n -U STR Use STR for User-Agent header" | 157 | //usage: "\n -U STR Use STR for User-Agent header" |
163 | //usage: "\n -Y on/off Use proxy" | 158 | //usage: "\n -Y on/off Use proxy" |
164 | 159 | ||
@@ -287,6 +282,8 @@ enum { | |||
287 | WGET_OPT_POST_DATA = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS, | 282 | WGET_OPT_POST_DATA = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS, |
288 | WGET_OPT_SPIDER = (1 << 13) * ENABLE_FEATURE_WGET_LONG_OPTIONS, | 283 | WGET_OPT_SPIDER = (1 << 13) * ENABLE_FEATURE_WGET_LONG_OPTIONS, |
289 | WGET_OPT_NO_CHECK_CERT = (1 << 14) * ENABLE_FEATURE_WGET_LONG_OPTIONS, | 284 | WGET_OPT_NO_CHECK_CERT = (1 << 14) * ENABLE_FEATURE_WGET_LONG_OPTIONS, |
285 | /* hijack this bit for other than opts purposes: */ | ||
286 | WGET_NO_FTRUNCATE = (1 << 31) | ||
290 | }; | 287 | }; |
291 | 288 | ||
292 | enum { | 289 | enum { |
@@ -1085,8 +1082,13 @@ static void NOINLINE retrieve_file_data(FILE *dfp) | |||
1085 | */ | 1082 | */ |
1086 | { | 1083 | { |
1087 | off_t pos = lseek(G.output_fd, 0, SEEK_CUR); | 1084 | off_t pos = lseek(G.output_fd, 0, SEEK_CUR); |
1088 | if (pos != (off_t)-1) | 1085 | if (pos != (off_t)-1) { |
1089 | ftruncate(G.output_fd, pos); | 1086 | /* do not truncate if -O- is in use, a user complained about |
1087 | * "wget -qO- 'http://example.com/empty' >>FILE" truncating FILE. | ||
1088 | */ | ||
1089 | if (!(option_mask32 & WGET_NO_FTRUNCATE)) | ||
1090 | ftruncate(G.output_fd, pos); | ||
1091 | } | ||
1090 | } | 1092 | } |
1091 | 1093 | ||
1092 | if (!(option_mask32 & WGET_OPT_QUIET)) { | 1094 | if (!(option_mask32 & WGET_OPT_QUIET)) { |
@@ -1599,7 +1601,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0") | |||
1599 | if (G.fname_out) { /* -O FILE ? */ | 1601 | if (G.fname_out) { /* -O FILE ? */ |
1600 | if (LONE_DASH(G.fname_out)) { /* -O - ? */ | 1602 | if (LONE_DASH(G.fname_out)) { /* -O - ? */ |
1601 | G.output_fd = 1; | 1603 | G.output_fd = 1; |
1602 | option_mask32 &= ~WGET_OPT_CONTINUE; | 1604 | option_mask32 = (option_mask32 & (~WGET_OPT_CONTINUE)) | WGET_NO_FTRUNCATE; |
1603 | } | 1605 | } |
1604 | /* compat with wget: -O FILE can overwrite */ | 1606 | /* compat with wget: -O FILE can overwrite */ |
1605 | G.o_flags = O_WRONLY | O_CREAT | O_TRUNC; | 1607 | G.o_flags = O_WRONLY | O_CREAT | O_TRUNC; |
diff --git a/procps/free.c b/procps/free.c index b33506b9e..0adef501f 100644 --- a/procps/free.c +++ b/procps/free.c | |||
@@ -97,10 +97,10 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) | |||
97 | case 'k': /* 2^10 */ | 97 | case 'k': /* 2^10 */ |
98 | /* G.unit_steps = 10; - already is */ | 98 | /* G.unit_steps = 10; - already is */ |
99 | break; | 99 | break; |
100 | case 'm': /* 2^(2*10) */ | 100 | case 'm': /* 2^20 */ |
101 | G.unit_steps = 20; | 101 | G.unit_steps = 20; |
102 | break; | 102 | break; |
103 | case 'g': /* 2^(3*10) */ | 103 | case 'g': /* 2^30 */ |
104 | G.unit_steps = 30; | 104 | G.unit_steps = 30; |
105 | break; | 105 | break; |
106 | default: | 106 | default: |
@@ -117,16 +117,24 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) | |||
117 | ); | 117 | ); |
118 | 118 | ||
119 | sysinfo(&info); | 119 | sysinfo(&info); |
120 | /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */ | ||
121 | G.mem_unit = (info.mem_unit ? info.mem_unit : 1); | ||
122 | /* Extract cached and memavailable from /proc/meminfo and convert to mem_units */ | 120 | /* Extract cached and memavailable from /proc/meminfo and convert to mem_units */ |
123 | seen_available = parse_meminfo(&G); | 121 | seen_available = parse_meminfo(&G); |
122 | G.mem_unit = (info.mem_unit ? info.mem_unit : 1); /* kernels < 2.4.x return mem_unit==0, so cope */ | ||
124 | available = ((unsigned long long) G.available_kb * 1024) / G.mem_unit; | 123 | available = ((unsigned long long) G.available_kb * 1024) / G.mem_unit; |
125 | cached = ((unsigned long long) G.cached_kb * 1024) / G.mem_unit; | 124 | cached = ((unsigned long long) G.cached_kb * 1024) / G.mem_unit; |
126 | cached += info.bufferram; | 125 | cached += info.bufferram; |
127 | cached += ((unsigned long long) G.reclaimable_kb * 1024) / G.mem_unit; | 126 | cached += ((unsigned long long) G.reclaimable_kb * 1024) / G.mem_unit; |
128 | cached_plus_free = cached + info.freeram; | 127 | cached_plus_free = cached + info.freeram; |
129 | 128 | ||
129 | /* In case (long long * G.mem_unit) can overflow, this can be used to reduce the chances */ | ||
130 | #if 0 //ENABLE_DESKTOP | ||
131 | while (!(G.mem_unit & 1) && G.unit_steps != 0) { | ||
132 | G.mem_unit >>= 1; | ||
133 | G.unit_steps--; | ||
134 | //bb_error_msg("mem_unit:%d unit_steps:%d", G.mem_unit, G.unit_steps); | ||
135 | } | ||
136 | #endif | ||
137 | |||
130 | #define FIELDS_6 "%12llu %11llu %11llu %11llu %11llu %11llu\n" | 138 | #define FIELDS_6 "%12llu %11llu %11llu %11llu %11llu %11llu\n" |
131 | #define FIELDS_3 (FIELDS_6 + 6 + 7 + 7) | 139 | #define FIELDS_3 (FIELDS_6 + 6 + 7 + 7) |
132 | #define FIELDS_2 (FIELDS_6 + 6 + 7 + 7 + 7) | 140 | #define FIELDS_2 (FIELDS_6 + 6 + 7 + 7 + 7) |
diff --git a/procps/fuser.c b/procps/fuser.c index 418f57b57..191746751 100644 --- a/procps/fuser.c +++ b/procps/fuser.c | |||
@@ -19,7 +19,7 @@ | |||
19 | //kbuild:lib-$(CONFIG_FUSER) += fuser.o | 19 | //kbuild:lib-$(CONFIG_FUSER) += fuser.o |
20 | 20 | ||
21 | //usage:#define fuser_trivial_usage | 21 | //usage:#define fuser_trivial_usage |
22 | //usage: "[OPTIONS] FILE or PORT/PROTO" | 22 | //usage: "[-msk46] [-SIGNAL] FILE or PORT/PROTO" |
23 | //usage:#define fuser_full_usage "\n\n" | 23 | //usage:#define fuser_full_usage "\n\n" |
24 | //usage: "Find processes which use FILEs or PORTs\n" | 24 | //usage: "Find processes which use FILEs or PORTs\n" |
25 | //usage: "\n -m Find processes which use same fs as FILEs" | 25 | //usage: "\n -m Find processes which use same fs as FILEs" |
diff --git a/procps/nmeter.c b/procps/nmeter.c index 856ce0202..f08938654 100644 --- a/procps/nmeter.c +++ b/procps/nmeter.c | |||
@@ -838,7 +838,7 @@ static void FAST_FUNC collect_info(s_stat *s) | |||
838 | typedef s_stat* init_func(const char *param); | 838 | typedef s_stat* init_func(const char *param); |
839 | 839 | ||
840 | static const char options[] ALIGN1 = "ncmsfixptTbr"; | 840 | static const char options[] ALIGN1 = "ncmsfixptTbr"; |
841 | static init_func *const init_functions[] = { | 841 | static init_func *const init_functions[] ALIGN_PTR = { |
842 | init_if, | 842 | init_if, |
843 | init_cpu, | 843 | init_cpu, |
844 | init_mem, | 844 | init_mem, |
@@ -952,11 +952,11 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv) | |||
952 | reset_outbuf(); | 952 | reset_outbuf(); |
953 | 953 | ||
954 | if (G.delta >= 0) { | 954 | if (G.delta >= 0) { |
955 | gettimeofday(&G.tv, NULL); | 955 | xgettimeofday(&G.tv); |
956 | usleep(G.delta > 1000000 ? 1000000 : G.delta - G.tv.tv_usec % G.deltanz); | 956 | usleep(G.delta > 1000000 ? 1000000 : G.delta - G.tv.tv_usec % G.deltanz); |
957 | } | 957 | } |
958 | 958 | ||
959 | gettimeofday(&G.start, NULL); | 959 | xgettimeofday(&G.start); |
960 | G.tv = G.start; | 960 | G.tv = G.start; |
961 | while (1) { | 961 | while (1) { |
962 | collect_info(first); | 962 | collect_info(first); |
@@ -971,7 +971,7 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv) | |||
971 | if (G.delta >= 0) { | 971 | if (G.delta >= 0) { |
972 | int rem; | 972 | int rem; |
973 | // can be commented out, will sacrifice sleep time precision a bit | 973 | // can be commented out, will sacrifice sleep time precision a bit |
974 | gettimeofday(&G.tv, NULL); | 974 | xgettimeofday(&G.tv); |
975 | if (need_seconds) | 975 | if (need_seconds) |
976 | rem = G.delta - ((ullong)G.tv.tv_sec*1000000 + G.tv.tv_usec) % G.deltanz; | 976 | rem = G.delta - ((ullong)G.tv.tv_sec*1000000 + G.tv.tv_usec) % G.deltanz; |
977 | else | 977 | else |
@@ -983,7 +983,7 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv) | |||
983 | } | 983 | } |
984 | usleep(rem); | 984 | usleep(rem); |
985 | } | 985 | } |
986 | gettimeofday(&G.tv, NULL); | 986 | xgettimeofday(&G.tv); |
987 | } | 987 | } |
988 | 988 | ||
989 | /*return 0;*/ | 989 | /*return 0;*/ |
diff --git a/procps/pidof.c b/procps/pidof.c index 5595e3421..b81709a81 100644 --- a/procps/pidof.c +++ b/procps/pidof.c | |||
@@ -39,7 +39,7 @@ | |||
39 | 39 | ||
40 | //usage:#if (ENABLE_FEATURE_PIDOF_SINGLE || ENABLE_FEATURE_PIDOF_OMIT) | 40 | //usage:#if (ENABLE_FEATURE_PIDOF_SINGLE || ENABLE_FEATURE_PIDOF_OMIT) |
41 | //usage:#define pidof_trivial_usage | 41 | //usage:#define pidof_trivial_usage |
42 | //usage: "[OPTIONS] [NAME]..." | 42 | //usage: IF_FEATURE_PIDOF_SINGLE("[-s] ")IF_FEATURE_PIDOF_OMIT("[-o PID] ")"[NAME]..." |
43 | //usage:#define USAGE_PIDOF "\n" | 43 | //usage:#define USAGE_PIDOF "\n" |
44 | //usage:#else | 44 | //usage:#else |
45 | //usage:#define pidof_trivial_usage | 45 | //usage:#define pidof_trivial_usage |
diff --git a/procps/pmap.c b/procps/pmap.c index 9e541c707..408cbfce7 100644 --- a/procps/pmap.c +++ b/procps/pmap.c | |||
@@ -27,20 +27,14 @@ | |||
27 | 27 | ||
28 | #include "libbb.h" | 28 | #include "libbb.h" |
29 | 29 | ||
30 | #if ULONG_MAX == 0xffffffff | 30 | #if ULLONG_MAX == 0xffffffff |
31 | # define TABS "\t" | 31 | # define TABS "\t" |
32 | # define AFMT "8" | 32 | # define AFMTLL "8" |
33 | # define DASHES "" | 33 | # define DASHES "" |
34 | #else | 34 | #else |
35 | # define TABS "\t\t" | 35 | # define TABS "\t\t" |
36 | # define AFMT "16" | ||
37 | # define DASHES "--------" | ||
38 | #endif | ||
39 | |||
40 | #if ULLONG_MAX == 0xffffffff | ||
41 | # define AFMTLL "8" | ||
42 | #else | ||
43 | # define AFMTLL "16" | 36 | # define AFMTLL "16" |
37 | # define DASHES "--------" | ||
44 | #endif | 38 | #endif |
45 | 39 | ||
46 | enum { | 40 | enum { |
diff --git a/procps/ps.c b/procps/ps.c index a4de11379..f84060447 100644 --- a/procps/ps.c +++ b/procps/ps.c | |||
@@ -381,7 +381,7 @@ static void func_pcpu(char *buf, int size, const procps_status_t *ps) | |||
381 | } | 381 | } |
382 | */ | 382 | */ |
383 | 383 | ||
384 | static const ps_out_t out_spec[] = { | 384 | static const ps_out_t out_spec[] ALIGN_PTR = { |
385 | /* Mandated by http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html: */ | 385 | /* Mandated by http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html: */ |
386 | { 8 , "user" ,"USER" ,func_user ,PSSCAN_UIDGID }, | 386 | { 8 , "user" ,"USER" ,func_user ,PSSCAN_UIDGID }, |
387 | { 8 , "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID }, | 387 | { 8 , "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID }, |
diff --git a/runit/runsv.c b/runit/runsv.c index 36d85101e..ecab8cdf5 100644 --- a/runit/runsv.c +++ b/runit/runsv.c | |||
@@ -58,11 +58,19 @@ static void gettimeofday_ns(struct timespec *ts) | |||
58 | #else | 58 | #else |
59 | static void gettimeofday_ns(struct timespec *ts) | 59 | static void gettimeofday_ns(struct timespec *ts) |
60 | { | 60 | { |
61 | BUILD_BUG_ON(sizeof(struct timeval) != sizeof(struct timespec)); | 61 | if (sizeof(struct timeval) == sizeof(struct timespec) |
62 | BUILD_BUG_ON(sizeof(((struct timeval*)ts)->tv_usec) != sizeof(ts->tv_nsec)); | 62 | && sizeof(((struct timeval*)ts)->tv_usec) == sizeof(ts->tv_nsec) |
63 | /* Cheat */ | 63 | ) { |
64 | gettimeofday((void*)ts, NULL); | 64 | /* Cheat */ |
65 | ts->tv_nsec *= 1000; | 65 | xgettimeofday((void*)ts); |
66 | ts->tv_nsec *= 1000; | ||
67 | } else { | ||
68 | /* For example, musl has "incompatible" layouts */ | ||
69 | struct timeval tv; | ||
70 | xgettimeofday(&tv); | ||
71 | ts->tv_sec = tv.tv_sec; | ||
72 | ts->tv_nsec = tv.tv_usec * 1000; | ||
73 | } | ||
66 | } | 74 | } |
67 | #endif | 75 | #endif |
68 | 76 | ||
@@ -651,7 +659,7 @@ int runsv_main(int argc UNUSED_PARAM, char **argv) | |||
651 | gettimeofday_ns(&svd[0].start); | 659 | gettimeofday_ns(&svd[0].start); |
652 | update_status(&svd[0]); | 660 | update_status(&svd[0]); |
653 | if (LESS(svd[0].start.tv_sec, deadline)) | 661 | if (LESS(svd[0].start.tv_sec, deadline)) |
654 | sleep(1); | 662 | sleep1(); |
655 | } | 663 | } |
656 | if (haslog) { | 664 | if (haslog) { |
657 | if (child == svd[1].pid) { | 665 | if (child == svd[1].pid) { |
@@ -664,7 +672,7 @@ int runsv_main(int argc UNUSED_PARAM, char **argv) | |||
664 | gettimeofday_ns(&svd[1].start); | 672 | gettimeofday_ns(&svd[1].start); |
665 | update_status(&svd[1]); | 673 | update_status(&svd[1]); |
666 | if (LESS(svd[1].start.tv_sec, deadline)) | 674 | if (LESS(svd[1].start.tv_sec, deadline)) |
667 | sleep(1); | 675 | sleep1(); |
668 | } | 676 | } |
669 | } | 677 | } |
670 | } /* for (;;) */ | 678 | } /* for (;;) */ |
diff --git a/runit/svlogd.c b/runit/svlogd.c index a250058a1..294e31aca 100644 --- a/runit/svlogd.c +++ b/runit/svlogd.c | |||
@@ -351,7 +351,7 @@ static void fmt_time_human_30nul(char *s, char dt_delim) | |||
351 | struct tm *ptm; | 351 | struct tm *ptm; |
352 | struct timeval tv; | 352 | struct timeval tv; |
353 | 353 | ||
354 | gettimeofday(&tv, NULL); | 354 | xgettimeofday(&tv); |
355 | ptm = gmtime_r(&tv.tv_sec, &tm); | 355 | ptm = gmtime_r(&tv.tv_sec, &tm); |
356 | /* ^^^ using gmtime_r() instead of gmtime() to not use static data */ | 356 | /* ^^^ using gmtime_r() instead of gmtime() to not use static data */ |
357 | sprintf(s, "%04u-%02u-%02u%c%02u:%02u:%02u.%06u000", | 357 | sprintf(s, "%04u-%02u-%02u%c%02u:%02u:%02u.%06u000", |
@@ -376,7 +376,7 @@ static void fmt_time_bernstein_25(char *s) | |||
376 | struct timeval tv; | 376 | struct timeval tv; |
377 | unsigned sec_hi; | 377 | unsigned sec_hi; |
378 | 378 | ||
379 | gettimeofday(&tv, NULL); | 379 | xgettimeofday(&tv); |
380 | sec_hi = (0x400000000000000aULL + tv.tv_sec) >> 32; | 380 | sec_hi = (0x400000000000000aULL + tv.tv_sec) >> 32; |
381 | tv.tv_sec = (time_t)(0x400000000000000aULL) + tv.tv_sec; | 381 | tv.tv_sec = (time_t)(0x400000000000000aULL) + tv.tv_sec; |
382 | tv.tv_usec *= 1000; | 382 | tv.tv_usec *= 1000; |
@@ -775,7 +775,7 @@ static NOINLINE unsigned logdir_open(struct logdir *ld, const char *fn) | |||
775 | ld->nmin = xatoi_positive(&s[1]); | 775 | ld->nmin = xatoi_positive(&s[1]); |
776 | break; | 776 | break; |
777 | case 't': { | 777 | case 't': { |
778 | static const struct suffix_mult mh_suffixes[] = { | 778 | static const struct suffix_mult mh_suffixes[] ALIGN_SUFFIX = { |
779 | { "m", 60 }, | 779 | { "m", 60 }, |
780 | { "h", 60*60 }, | 780 | { "h", 60*60 }, |
781 | /*{ "d", 24*60*60 },*/ | 781 | /*{ "d", 24*60*60 },*/ |
diff --git a/scripts/bb_release b/scripts/bb_release index 2e146bf84..545440d3a 100755 --- a/scripts/bb_release +++ b/scripts/bb_release | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | #svn co svn://busybox.net/trunk/busybox | 9 | #svn co svn://busybox.net/trunk/busybox |
10 | cd busybox || { echo "cd busybox failed"; exit 1; } | 10 | cd busybox || { echo "cd busybox failed"; exit 1; } |
11 | chmod -Rc u+w,a+rX,go-w . | ||
11 | make release || { echo "make release failed"; exit 1; } | 12 | make release || { echo "make release failed"; exit 1; } |
12 | cd .. | 13 | cd .. |
13 | 14 | ||
diff --git a/selinux/chcon.c b/selinux/chcon.c index 9b13679b8..2e4f94c0f 100644 --- a/selinux/chcon.c +++ b/selinux/chcon.c | |||
@@ -19,10 +19,10 @@ | |||
19 | //kbuild:lib-$(CONFIG_CHCON) += chcon.o | 19 | //kbuild:lib-$(CONFIG_CHCON) += chcon.o |
20 | 20 | ||
21 | //usage:#define chcon_trivial_usage | 21 | //usage:#define chcon_trivial_usage |
22 | //usage: "[OPTIONS] CONTEXT FILE..." | 22 | //usage: "[-chfRv] CONTEXT FILE..." |
23 | //usage: "\n chcon [OPTIONS] [-u USER] [-r ROLE] [-l RANGE] [-t TYPE] FILE..." | 23 | //usage: "\n chcon [-chfRv] [-u USER] [-r ROLE] [-l RANGE] [-t TYPE] FILE..." |
24 | //usage: IF_LONG_OPTS( | 24 | //usage: IF_LONG_OPTS( |
25 | //usage: "\n chcon [OPTIONS] --reference=RFILE FILE..." | 25 | //usage: "\n chcon [-chfRv] --reference=RFILE FILE..." |
26 | //usage: ) | 26 | //usage: ) |
27 | //usage: | 27 | //usage: |
28 | //usage:#define chcon_full_usage "\n\n" | 28 | //usage:#define chcon_full_usage "\n\n" |
@@ -37,7 +37,7 @@ | |||
37 | //usage: "\n -u USER Set user/role/type/range in the target security context" | 37 | //usage: "\n -u USER Set user/role/type/range in the target security context" |
38 | //usage: "\n -r ROLE" | 38 | //usage: "\n -r ROLE" |
39 | //usage: "\n -t TYPE" | 39 | //usage: "\n -t TYPE" |
40 | //usage: "\n -l RNG" | 40 | //usage: "\n -l RANGE" |
41 | //usage: "\n -R Recurse" | 41 | //usage: "\n -R Recurse" |
42 | 42 | ||
43 | #include <selinux/context.h> | 43 | #include <selinux/context.h> |
diff --git a/shell/ash.c b/shell/ash.c index 897548f3c..780900b40 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -418,9 +418,12 @@ static void forkshell_print(FILE *fp0, struct forkshell *fs, const char **notes) | |||
418 | 418 | ||
419 | /* ============ Shell options */ | 419 | /* ============ Shell options */ |
420 | 420 | ||
421 | /* If you add/change options hare, update --help text too */ | ||
421 | static const char *const optletters_optnames[] = { | 422 | static const char *const optletters_optnames[] = { |
422 | "e" "errexit", | 423 | "e" "errexit", |
423 | "f" "noglob", | 424 | "f" "noglob", |
425 | /* bash has '-o ignoreeof', but no short synonym -I for it */ | ||
426 | /* (in bash, set -I disables invisible variables (what's that?)) */ | ||
424 | "I" "ignoreeof", | 427 | "I" "ignoreeof", |
425 | /* The below allowed this invocation: | 428 | /* The below allowed this invocation: |
426 | * ash -c 'set -i; echo $-; sleep 5; echo $-' | 429 | * ash -c 'set -i; echo $-; sleep 5; echo $-' |
@@ -429,9 +432,10 @@ static const char *const optletters_optnames[] = { | |||
429 | * In our code, this is denoted by empty long name: | 432 | * In our code, this is denoted by empty long name: |
430 | */ | 433 | */ |
431 | "i" "", | 434 | "i" "", |
435 | /* (removing "i" altogether would remove it from "$-", not good) */ | ||
432 | "m" "monitor", | 436 | "m" "monitor", |
433 | "n" "noexec", | 437 | "n" "noexec", |
434 | /* Ditto: bash has no "set -s" */ | 438 | /* Ditto: bash has no "set -s", "set -c" */ |
435 | #if !ENABLE_PLATFORM_MINGW32 | 439 | #if !ENABLE_PLATFORM_MINGW32 |
436 | "s" "", | 440 | "s" "", |
437 | #else | 441 | #else |
@@ -707,6 +711,63 @@ var_end(const char *var) | |||
707 | } | 711 | } |
708 | 712 | ||
709 | 713 | ||
714 | /* ============ Parser data */ | ||
715 | |||
716 | /* | ||
717 | * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up. | ||
718 | */ | ||
719 | struct strlist { | ||
720 | struct strlist *next; | ||
721 | char *text; | ||
722 | }; | ||
723 | |||
724 | struct alias; | ||
725 | |||
726 | struct strpush { | ||
727 | struct strpush *prev; /* preceding string on stack */ | ||
728 | char *prev_string; | ||
729 | int prev_left_in_line; | ||
730 | #if ENABLE_ASH_ALIAS | ||
731 | struct alias *ap; /* if push was associated with an alias */ | ||
732 | #endif | ||
733 | char *string; /* remember the string since it may change */ | ||
734 | |||
735 | /* Remember last two characters for pungetc. */ | ||
736 | int lastc[2]; | ||
737 | |||
738 | /* Number of outstanding calls to pungetc. */ | ||
739 | int unget; | ||
740 | }; | ||
741 | |||
742 | /* | ||
743 | * The parsefile structure pointed to by the global variable parsefile | ||
744 | * contains information about the current file being read. | ||
745 | */ | ||
746 | struct parsefile { | ||
747 | struct parsefile *prev; /* preceding file on stack */ | ||
748 | int linno; /* current line */ | ||
749 | int pf_fd; /* file descriptor (or -1 if string) */ | ||
750 | int left_in_line; /* number of chars left in this line */ | ||
751 | int left_in_buffer; /* number of chars left in this buffer past the line */ | ||
752 | char *next_to_pgetc; /* next char in buffer */ | ||
753 | char *buf; /* input buffer */ | ||
754 | struct strpush *strpush; /* for pushing strings at this level */ | ||
755 | struct strpush basestrpush; /* so pushing one is fast */ | ||
756 | |||
757 | /* Remember last two characters for pungetc. */ | ||
758 | int lastc[2]; | ||
759 | |||
760 | /* Number of outstanding calls to pungetc. */ | ||
761 | int unget; | ||
762 | }; | ||
763 | |||
764 | static struct parsefile basepf; /* top level input file */ | ||
765 | static struct parsefile *g_parsefile = &basepf; /* current input file */ | ||
766 | #if ENABLE_PLATFORM_POSIX | ||
767 | static char *commandname; /* currently executing command */ | ||
768 | #endif | ||
769 | |||
770 | |||
710 | /* ============ Interrupts / exceptions */ | 771 | /* ============ Interrupts / exceptions */ |
711 | 772 | ||
712 | static void exitshell(void) NORETURN; | 773 | static void exitshell(void) NORETURN; |
@@ -1466,63 +1527,6 @@ showtree(union node *n) | |||
1466 | #endif /* DEBUG */ | 1527 | #endif /* DEBUG */ |
1467 | 1528 | ||
1468 | 1529 | ||
1469 | /* ============ Parser data */ | ||
1470 | |||
1471 | /* | ||
1472 | * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up. | ||
1473 | */ | ||
1474 | struct strlist { | ||
1475 | struct strlist *next; | ||
1476 | char *text; | ||
1477 | }; | ||
1478 | |||
1479 | struct alias; | ||
1480 | |||
1481 | struct strpush { | ||
1482 | struct strpush *prev; /* preceding string on stack */ | ||
1483 | char *prev_string; | ||
1484 | int prev_left_in_line; | ||
1485 | #if ENABLE_ASH_ALIAS | ||
1486 | struct alias *ap; /* if push was associated with an alias */ | ||
1487 | #endif | ||
1488 | char *string; /* remember the string since it may change */ | ||
1489 | |||
1490 | /* Remember last two characters for pungetc. */ | ||
1491 | int lastc[2]; | ||
1492 | |||
1493 | /* Number of outstanding calls to pungetc. */ | ||
1494 | int unget; | ||
1495 | }; | ||
1496 | |||
1497 | /* | ||
1498 | * The parsefile structure pointed to by the global variable parsefile | ||
1499 | * contains information about the current file being read. | ||
1500 | */ | ||
1501 | struct parsefile { | ||
1502 | struct parsefile *prev; /* preceding file on stack */ | ||
1503 | int linno; /* current line */ | ||
1504 | int pf_fd; /* file descriptor (or -1 if string) */ | ||
1505 | int left_in_line; /* number of chars left in this line */ | ||
1506 | int left_in_buffer; /* number of chars left in this buffer past the line */ | ||
1507 | char *next_to_pgetc; /* next char in buffer */ | ||
1508 | char *buf; /* input buffer */ | ||
1509 | struct strpush *strpush; /* for pushing strings at this level */ | ||
1510 | struct strpush basestrpush; /* so pushing one is fast */ | ||
1511 | |||
1512 | /* Remember last two characters for pungetc. */ | ||
1513 | int lastc[2]; | ||
1514 | |||
1515 | /* Number of outstanding calls to pungetc. */ | ||
1516 | int unget; | ||
1517 | }; | ||
1518 | |||
1519 | static struct parsefile basepf; /* top level input file */ | ||
1520 | static struct parsefile *g_parsefile = &basepf; /* current input file */ | ||
1521 | #if ENABLE_PLATFORM_POSIX | ||
1522 | static char *commandname; /* currently executing command */ | ||
1523 | #endif | ||
1524 | |||
1525 | |||
1526 | /* ============ Message printing */ | 1530 | /* ============ Message printing */ |
1527 | 1531 | ||
1528 | static void | 1532 | static void |
@@ -2284,7 +2288,7 @@ static const struct { | |||
2284 | int flags; | 2288 | int flags; |
2285 | const char *var_text; | 2289 | const char *var_text; |
2286 | void (*var_func)(const char *) FAST_FUNC; | 2290 | void (*var_func)(const char *) FAST_FUNC; |
2287 | } varinit_data[] = { | 2291 | } varinit_data[] ALIGN_PTR = { |
2288 | /* | 2292 | /* |
2289 | * Note: VEXPORT would not work correctly here for NOFORK applets: | 2293 | * Note: VEXPORT would not work correctly here for NOFORK applets: |
2290 | * some environment strings may be constant. | 2294 | * some environment strings may be constant. |
@@ -5137,7 +5141,7 @@ getstatus(struct job *job) | |||
5137 | job->sigint = 1; | 5141 | job->sigint = 1; |
5138 | #endif | 5142 | #endif |
5139 | } | 5143 | } |
5140 | retval += 128; | 5144 | retval |= 128; |
5141 | } | 5145 | } |
5142 | TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n", | 5146 | TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n", |
5143 | jobno(job), job->nprocs, status, retval)); | 5147 | jobno(job), job->nprocs, status, retval)); |
@@ -5203,7 +5207,7 @@ waitcmd(int argc UNUSED_PARAM, char **argv) | |||
5203 | if (status != -1 && !WIFSTOPPED(status)) { | 5207 | if (status != -1 && !WIFSTOPPED(status)) { |
5204 | retval = WEXITSTATUS(status); | 5208 | retval = WEXITSTATUS(status); |
5205 | if (WIFSIGNALED(status)) | 5209 | if (WIFSIGNALED(status)) |
5206 | retval = WTERMSIG(status) + 128; | 5210 | retval = 128 | WTERMSIG(status); |
5207 | goto ret; | 5211 | goto ret; |
5208 | } | 5212 | } |
5209 | } | 5213 | } |
@@ -5238,7 +5242,7 @@ waitcmd(int argc UNUSED_PARAM, char **argv) | |||
5238 | ret: | 5242 | ret: |
5239 | return retval; | 5243 | return retval; |
5240 | sigout: | 5244 | sigout: |
5241 | retval = 128 + pending_sig; | 5245 | retval = 128 | pending_sig; |
5242 | return retval; | 5246 | return retval; |
5243 | } | 5247 | } |
5244 | 5248 | ||
@@ -5340,7 +5344,7 @@ static char *cmdnextc; | |||
5340 | static void | 5344 | static void |
5341 | cmdputs(const char *s) | 5345 | cmdputs(const char *s) |
5342 | { | 5346 | { |
5343 | static const char vstype[VSTYPE + 1][3] = { | 5347 | static const char vstype[VSTYPE + 1][3] ALIGN1 = { |
5344 | "", "}", "-", "+", "?", "=", | 5348 | "", "}", "-", "+", "?", "=", |
5345 | "%", "%%", "#", "##" | 5349 | "%", "%%", "#", "##" |
5346 | IF_BASH_SUBSTR(, ":") | 5350 | IF_BASH_SUBSTR(, ":") |
@@ -7578,7 +7582,8 @@ subevalvar(char *start, char *str, int strloc, | |||
7578 | slash_pos = -1; | 7582 | slash_pos = -1; |
7579 | if (repl) { | 7583 | if (repl) { |
7580 | slash_pos = expdest - ((char *)stackblock() + strloc); | 7584 | slash_pos = expdest - ((char *)stackblock() + strloc); |
7581 | STPUTC('/', expdest); | 7585 | if (!(flag & EXP_DISCARD)) |
7586 | STPUTC('/', expdest); | ||
7582 | //bb_error_msg("repl+1:'%s'", repl + 1); | 7587 | //bb_error_msg("repl+1:'%s'", repl + 1); |
7583 | p = argstr(repl + 1, (flag & EXP_DISCARD) | EXP_TILDE); /* EXP_TILDE: echo "${v/x/~}" expands ~ ! */ | 7588 | p = argstr(repl + 1, (flag & EXP_DISCARD) | EXP_TILDE); /* EXP_TILDE: echo "${v/x/~}" expands ~ ! */ |
7584 | *repl = '/'; | 7589 | *repl = '/'; |
@@ -7740,7 +7745,7 @@ subevalvar(char *start, char *str, int strloc, | |||
7740 | len = 0; | 7745 | len = 0; |
7741 | idx = startp; | 7746 | idx = startp; |
7742 | end = str - 1; | 7747 | end = str - 1; |
7743 | while (idx < end) { | 7748 | while (idx <= end) { |
7744 | try_to_match: | 7749 | try_to_match: |
7745 | loc = scanright(idx, rmesc, rmescend, str, quotes, 1); | 7750 | loc = scanright(idx, rmesc, rmescend, str, quotes, 1); |
7746 | //bb_error_msg("scanright('%s'):'%s'", str, loc); | 7751 | //bb_error_msg("scanright('%s'):'%s'", str, loc); |
@@ -7748,6 +7753,8 @@ subevalvar(char *start, char *str, int strloc, | |||
7748 | /* No match, advance */ | 7753 | /* No match, advance */ |
7749 | char *restart_detect = stackblock(); | 7754 | char *restart_detect = stackblock(); |
7750 | skip_matching: | 7755 | skip_matching: |
7756 | if (idx >= end) | ||
7757 | break; | ||
7751 | STPUTC(*idx, expdest); | 7758 | STPUTC(*idx, expdest); |
7752 | if (quotes && (unsigned char)*idx == CTLESC) { | 7759 | if (quotes && (unsigned char)*idx == CTLESC) { |
7753 | idx++; | 7760 | idx++; |
@@ -7760,8 +7767,6 @@ subevalvar(char *start, char *str, int strloc, | |||
7760 | len++; | 7767 | len++; |
7761 | rmesc++; | 7768 | rmesc++; |
7762 | /* continue; - prone to quadratic behavior, smarter code: */ | 7769 | /* continue; - prone to quadratic behavior, smarter code: */ |
7763 | if (idx >= end) | ||
7764 | break; | ||
7765 | if (str[0] == '*') { | 7770 | if (str[0] == '*') { |
7766 | /* Pattern is "*foo". If "*foo" does not match "long_string", | 7771 | /* Pattern is "*foo". If "*foo" does not match "long_string", |
7767 | * it would never match "ong_string" etc, no point in trying. | 7772 | * it would never match "ong_string" etc, no point in trying. |
@@ -7844,7 +7849,9 @@ subevalvar(char *start, char *str, int strloc, | |||
7844 | out: | 7849 | out: |
7845 | amount = loc - expdest; | 7850 | amount = loc - expdest; |
7846 | STADJUST(amount, expdest); | 7851 | STADJUST(amount, expdest); |
7852 | #if BASH_PATTERN_SUBST | ||
7847 | out1: | 7853 | out1: |
7854 | #endif | ||
7848 | /* Remove any recorded regions beyond start of variable */ | 7855 | /* Remove any recorded regions beyond start of variable */ |
7849 | removerecordregions(startloc); | 7856 | removerecordregions(startloc); |
7850 | 7857 | ||
@@ -9127,7 +9134,7 @@ enum { | |||
9127 | , /* thus far 29 bits used */ | 9134 | , /* thus far 29 bits used */ |
9128 | }; | 9135 | }; |
9129 | 9136 | ||
9130 | static const char *const tokname_array[] = { | 9137 | static const char *const tokname_array[] ALIGN_PTR = { |
9131 | "end of file", | 9138 | "end of file", |
9132 | "newline", | 9139 | "newline", |
9133 | "redirection", | 9140 | "redirection", |
@@ -11360,7 +11367,7 @@ preadfd(void) | |||
11360 | 11367 | ||
11361 | g_parsefile->next_to_pgetc = buf; | 11368 | g_parsefile->next_to_pgetc = buf; |
11362 | #if ENABLE_FEATURE_EDITING | 11369 | #if ENABLE_FEATURE_EDITING |
11363 | retry: | 11370 | /* retry: */ |
11364 | if (!iflag || g_parsefile->pf_fd != STDIN_FILENO) | 11371 | if (!iflag || g_parsefile->pf_fd != STDIN_FILENO) |
11365 | nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1); | 11372 | nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1); |
11366 | else { | 11373 | else { |
@@ -11382,17 +11389,16 @@ preadfd(void) | |||
11382 | if (nr == 0) { | 11389 | if (nr == 0) { |
11383 | /* ^C pressed, "convert" to SIGINT */ | 11390 | /* ^C pressed, "convert" to SIGINT */ |
11384 | write(STDOUT_FILENO, "^C", 2); | 11391 | write(STDOUT_FILENO, "^C", 2); |
11392 | # if !ENABLE_PLATFORM_MINGW32 | ||
11393 | raise(SIGINT); | ||
11394 | # endif | ||
11385 | if (trap[SIGINT]) { | 11395 | if (trap[SIGINT]) { |
11386 | buf[0] = '\n'; | 11396 | buf[0] = '\n'; |
11387 | buf[1] = '\0'; | 11397 | buf[1] = '\0'; |
11388 | # if !ENABLE_PLATFORM_MINGW32 | ||
11389 | raise(SIGINT); | ||
11390 | # endif | ||
11391 | return 1; | 11398 | return 1; |
11392 | } | 11399 | } |
11393 | exitstatus = 128 + SIGINT; | 11400 | exitstatus = 128 + SIGINT; |
11394 | bb_putchar('\n'); | 11401 | return -1; |
11395 | goto retry; | ||
11396 | } | 11402 | } |
11397 | if (nr < 0) { | 11403 | if (nr < 0) { |
11398 | if (errno == 0) { | 11404 | if (errno == 0) { |
@@ -12164,10 +12170,10 @@ static void FAST_FUNC | |||
12164 | change_epoch(struct var *vepoch, const char *fmt) | 12170 | change_epoch(struct var *vepoch, const char *fmt) |
12165 | { | 12171 | { |
12166 | struct timeval tv; | 12172 | struct timeval tv; |
12167 | char buffer[sizeof("%lu.nnnnnn") + sizeof(long)*3]; | 12173 | char buffer[sizeof("%llu.nnnnnn") + sizeof(long long)*3]; |
12168 | 12174 | ||
12169 | gettimeofday(&tv, NULL); | 12175 | xgettimeofday(&tv); |
12170 | sprintf(buffer, fmt, (unsigned long)tv.tv_sec, (unsigned)tv.tv_usec); | 12176 | sprintf(buffer, fmt, (unsigned long long)tv.tv_sec, (unsigned)tv.tv_usec); |
12171 | setvar(vepoch->var_text, buffer, VNOFUNC); | 12177 | setvar(vepoch->var_text, buffer, VNOFUNC); |
12172 | vepoch->flags &= ~VNOFUNC; | 12178 | vepoch->flags &= ~VNOFUNC; |
12173 | } | 12179 | } |
@@ -12175,13 +12181,13 @@ change_epoch(struct var *vepoch, const char *fmt) | |||
12175 | static void FAST_FUNC | 12181 | static void FAST_FUNC |
12176 | change_seconds(const char *value UNUSED_PARAM) | 12182 | change_seconds(const char *value UNUSED_PARAM) |
12177 | { | 12183 | { |
12178 | change_epoch(&vepochs, "%lu"); | 12184 | change_epoch(&vepochs, "%llu"); |
12179 | } | 12185 | } |
12180 | 12186 | ||
12181 | static void FAST_FUNC | 12187 | static void FAST_FUNC |
12182 | change_realtime(const char *value UNUSED_PARAM) | 12188 | change_realtime(const char *value UNUSED_PARAM) |
12183 | { | 12189 | { |
12184 | change_epoch(&vepochr, "%lu.%06u"); | 12190 | change_epoch(&vepochr, "%llu.%06u"); |
12185 | } | 12191 | } |
12186 | #endif | 12192 | #endif |
12187 | 12193 | ||
@@ -15001,6 +15007,7 @@ reset(void) | |||
15001 | /* from input.c: */ | 15007 | /* from input.c: */ |
15002 | g_parsefile->left_in_buffer = 0; | 15008 | g_parsefile->left_in_buffer = 0; |
15003 | g_parsefile->left_in_line = 0; /* clear input buffer */ | 15009 | g_parsefile->left_in_line = 0; /* clear input buffer */ |
15010 | g_parsefile->unget = 0; | ||
15004 | popallfiles(); | 15011 | popallfiles(); |
15005 | 15012 | ||
15006 | /* from var.c: */ | 15013 | /* from var.c: */ |
@@ -15017,8 +15024,7 @@ exitshell(void) | |||
15017 | char *p; | 15024 | char *p; |
15018 | 15025 | ||
15019 | #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT | 15026 | #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT |
15020 | if (line_input_state) | 15027 | save_history(line_input_state); /* may be NULL */ |
15021 | save_history(line_input_state); | ||
15022 | #endif | 15028 | #endif |
15023 | savestatus = exitstatus; | 15029 | savestatus = exitstatus; |
15024 | TRACE(("pid %d, exitshell(%d)\n", getpid(), savestatus)); | 15030 | TRACE(("pid %d, exitshell(%d)\n", getpid(), savestatus)); |
@@ -15197,7 +15203,8 @@ init(void) | |||
15197 | 15203 | ||
15198 | 15204 | ||
15199 | //usage:#define ash_trivial_usage | 15205 | //usage:#define ash_trivial_usage |
15200 | //usage: "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]" | 15206 | //usage: "[-il] [-/+Cabefmnuvx] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]" |
15207 | //////// comes from ^^^^^^^^^^optletters | ||
15201 | //usage:#define ash_full_usage "\n\n" | 15208 | //usage:#define ash_full_usage "\n\n" |
15202 | //usage: "Unix shell interpreter" | 15209 | //usage: "Unix shell interpreter" |
15203 | 15210 | ||
@@ -15246,9 +15253,9 @@ procargs(char **argv) | |||
15246 | } | 15253 | } |
15247 | if (mflag == 2) | 15254 | if (mflag == 2) |
15248 | mflag = iflag; | 15255 | mflag = iflag; |
15256 | /* Unset options which weren't explicitly set or unset */ | ||
15249 | for (i = 0; i < NOPTS; i++) | 15257 | for (i = 0; i < NOPTS; i++) |
15250 | if (optlist[i] == 2) | 15258 | optlist[i] &= 1; /* same effect as "if (optlist[i] == 2) optlist[i] = 0;" */ |
15251 | optlist[i] = 0; | ||
15252 | #if DEBUG == 2 | 15259 | #if DEBUG == 2 |
15253 | debug = 1; | 15260 | debug = 1; |
15254 | #endif | 15261 | #endif |
@@ -15277,6 +15284,19 @@ procargs(char **argv) | |||
15277 | shellparam.nparam++; | 15284 | shellparam.nparam++; |
15278 | xargv++; | 15285 | xargv++; |
15279 | } | 15286 | } |
15287 | |||
15288 | /* Interactive bash re-enables SIGHUP which is SIG_IGNed on entry. | ||
15289 | * Try: | ||
15290 | * trap '' hup; bash; echo RET # type "kill -hup $$", see SIGHUP having effect | ||
15291 | * trap '' hup; bash -c 'kill -hup $$; echo ALIVE' # here SIGHUP is SIG_IGNed | ||
15292 | * NB: must do it before setting up signals (in optschanged()) | ||
15293 | * and reading .profile etc (after we return from here): | ||
15294 | */ | ||
15295 | #if !ENABLE_PLATFORM_MINGW32 | ||
15296 | if (iflag) | ||
15297 | signal(SIGHUP, SIG_DFL); | ||
15298 | #endif | ||
15299 | |||
15280 | optschanged(); | 15300 | optschanged(); |
15281 | 15301 | ||
15282 | return login_sh; | 15302 | return login_sh; |
@@ -15493,7 +15513,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
15493 | 15513 | ||
15494 | if (sflag || minusc == NULL) { | 15514 | if (sflag || minusc == NULL) { |
15495 | #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY | 15515 | #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY |
15496 | if (iflag) { | 15516 | if (line_input_state) { |
15497 | const char *hp = lookupvar("HISTFILE"); | 15517 | const char *hp = lookupvar("HISTFILE"); |
15498 | if (!hp) { | 15518 | if (!hp) { |
15499 | hp = lookupvar("HOME"); | 15519 | hp = lookupvar("HOME"); |
@@ -15507,7 +15527,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
15507 | } | 15527 | } |
15508 | } | 15528 | } |
15509 | if (hp) | 15529 | if (hp) |
15510 | line_input_state->hist_file = hp; | 15530 | line_input_state->hist_file = xstrdup(hp); |
15511 | # if ENABLE_FEATURE_SH_HISTFILESIZE | 15531 | # if ENABLE_FEATURE_SH_HISTFILESIZE |
15512 | hp = lookupvar("HISTFILESIZE"); | 15532 | hp = lookupvar("HISTFILESIZE"); |
15513 | line_input_state->max_history = size_from_HISTFILESIZE(hp); | 15533 | line_input_state->max_history = size_from_HISTFILESIZE(hp); |
@@ -15515,16 +15535,6 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
15515 | } | 15535 | } |
15516 | #endif | 15536 | #endif |
15517 | state4: /* XXX ??? - why isn't this before the "if" statement */ | 15537 | state4: /* XXX ??? - why isn't this before the "if" statement */ |
15518 | |||
15519 | /* Interactive bash re-enables SIGHUP which is SIG_IGNed on entry. | ||
15520 | * Try: | ||
15521 | * trap '' hup; bash; echo RET # type "kill -hup $$", see SIGHUP having effect | ||
15522 | * trap '' hup; bash -c 'kill -hup $$; echo ALIVE' # here SIGHUP is SIG_IGNed | ||
15523 | */ | ||
15524 | #if !ENABLE_PLATFORM_MINGW32 | ||
15525 | signal(SIGHUP, SIG_DFL); | ||
15526 | #endif | ||
15527 | |||
15528 | cmdloop(1); | 15538 | cmdloop(1); |
15529 | } | 15539 | } |
15530 | #if PROFILE | 15540 | #if PROFILE |
diff --git a/shell/ash_test/ash-misc/piped_input.right b/shell/ash_test/ash-misc/piped_input.right new file mode 100644 index 000000000..7b8bf6758 --- /dev/null +++ b/shell/ash_test/ash-misc/piped_input.right | |||
@@ -0,0 +1,2 @@ | |||
1 | TEST | ||
2 | One:1 | ||
diff --git a/shell/ash_test/ash-misc/piped_input.tests b/shell/ash_test/ash-misc/piped_input.tests new file mode 100755 index 000000000..929fec0db --- /dev/null +++ b/shell/ash_test/ash-misc/piped_input.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | exec 2>&1 | ||
2 | echo 'echo TEST; false' | $THIS_SH | ||
3 | echo One:$? | ||
diff --git a/shell/ash_test/ash-vars/var_bash_repl_empty_var.right b/shell/ash_test/ash-vars/var_bash_repl_empty_var.right index 892916783..a8d1a3bef 100644 --- a/shell/ash_test/ash-vars/var_bash_repl_empty_var.right +++ b/shell/ash_test/ash-vars/var_bash_repl_empty_var.right | |||
@@ -1,2 +1,3 @@ | |||
1 | 1 | ||
2 | w | ||
2 | Ok:0 | 3 | Ok:0 |
diff --git a/shell/ash_test/ash-vars/var_bash_repl_empty_var.tests b/shell/ash_test/ash-vars/var_bash_repl_empty_var.tests index 73a43d38e..22aaba560 100755 --- a/shell/ash_test/ash-vars/var_bash_repl_empty_var.tests +++ b/shell/ash_test/ash-vars/var_bash_repl_empty_var.tests | |||
@@ -1,3 +1,5 @@ | |||
1 | unset v | ||
2 | echo ${v/*/w} | ||
1 | v='' | 3 | v='' |
2 | echo ${v/*/w} | 4 | echo ${v/*/w} |
3 | echo Ok:$? | 5 | echo Ok:$? |
diff --git a/shell/hush.c b/shell/hush.c index ab7263381..77f90f82f 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -596,10 +596,10 @@ typedef struct in_str { | |||
596 | /* The descrip member of this structure is only used to make | 596 | /* The descrip member of this structure is only used to make |
597 | * debugging output pretty */ | 597 | * debugging output pretty */ |
598 | static const struct { | 598 | static const struct { |
599 | int mode; | 599 | int32_t mode; |
600 | signed char default_fd; | 600 | signed char default_fd; |
601 | char descrip[3]; | 601 | char descrip[3]; |
602 | } redir_table[] = { | 602 | } redir_table[] ALIGN4 = { |
603 | { O_RDONLY, 0, "<" }, | 603 | { O_RDONLY, 0, "<" }, |
604 | { O_CREAT|O_TRUNC|O_WRONLY, 1, ">" }, | 604 | { O_CREAT|O_TRUNC|O_WRONLY, 1, ">" }, |
605 | { O_CREAT|O_APPEND|O_WRONLY, 1, ">>" }, | 605 | { O_CREAT|O_APPEND|O_WRONLY, 1, ">>" }, |
@@ -653,7 +653,7 @@ struct command { | |||
653 | /* used for "[[ EXPR ]]" */ | 653 | /* used for "[[ EXPR ]]" */ |
654 | # define CMD_TEST2_SINGLEWORD_NOGLOB 2 | 654 | # define CMD_TEST2_SINGLEWORD_NOGLOB 2 |
655 | #endif | 655 | #endif |
656 | #if ENABLE_HUSH_LOCAL || ENABLE_HUSH_EXPORT || ENABLE_HUSH_READONLY | 656 | #if BASH_TEST2 || ENABLE_HUSH_LOCAL || ENABLE_HUSH_EXPORT || ENABLE_HUSH_READONLY |
657 | /* used to prevent word splitting and globbing in "export v=t*" */ | 657 | /* used to prevent word splitting and globbing in "export v=t*" */ |
658 | # define CMD_SINGLEWORD_NOGLOB 3 | 658 | # define CMD_SINGLEWORD_NOGLOB 3 |
659 | #endif | 659 | #endif |
@@ -1027,7 +1027,7 @@ struct globals { | |||
1027 | struct sigaction sa; | 1027 | struct sigaction sa; |
1028 | char optstring_buf[sizeof("eixcs")]; | 1028 | char optstring_buf[sizeof("eixcs")]; |
1029 | #if BASH_EPOCH_VARS | 1029 | #if BASH_EPOCH_VARS |
1030 | char epoch_buf[sizeof("%lu.nnnnnn") + sizeof(long)*3]; | 1030 | char epoch_buf[sizeof("%llu.nnnnnn") + sizeof(long long)*3]; |
1031 | #endif | 1031 | #endif |
1032 | #if ENABLE_FEATURE_EDITING | 1032 | #if ENABLE_FEATURE_EDITING |
1033 | char user_input_buf[CONFIG_FEATURE_EDITING_MAX_LEN]; | 1033 | char user_input_buf[CONFIG_FEATURE_EDITING_MAX_LEN]; |
@@ -1140,7 +1140,7 @@ struct built_in_command { | |||
1140 | #endif | 1140 | #endif |
1141 | }; | 1141 | }; |
1142 | 1142 | ||
1143 | static const struct built_in_command bltins1[] = { | 1143 | static const struct built_in_command bltins1[] ALIGN_PTR = { |
1144 | BLTIN("." , builtin_source , "Run commands in file"), | 1144 | BLTIN("." , builtin_source , "Run commands in file"), |
1145 | BLTIN(":" , builtin_true , NULL), | 1145 | BLTIN(":" , builtin_true , NULL), |
1146 | #if ENABLE_HUSH_JOB | 1146 | #if ENABLE_HUSH_JOB |
@@ -1225,7 +1225,7 @@ static const struct built_in_command bltins1[] = { | |||
1225 | /* These builtins won't be used if we are on NOMMU and need to re-exec | 1225 | /* These builtins won't be used if we are on NOMMU and need to re-exec |
1226 | * (it's cheaper to run an external program in this case): | 1226 | * (it's cheaper to run an external program in this case): |
1227 | */ | 1227 | */ |
1228 | static const struct built_in_command bltins2[] = { | 1228 | static const struct built_in_command bltins2[] ALIGN_PTR = { |
1229 | #if ENABLE_HUSH_TEST | 1229 | #if ENABLE_HUSH_TEST |
1230 | BLTIN("[" , builtin_test , NULL), | 1230 | BLTIN("[" , builtin_test , NULL), |
1231 | #endif | 1231 | #endif |
@@ -1649,13 +1649,33 @@ static int refill_HFILE_and_getc(HFILE *fp) | |||
1649 | /* Already saw EOF */ | 1649 | /* Already saw EOF */ |
1650 | return EOF; | 1650 | return EOF; |
1651 | } | 1651 | } |
1652 | #if ENABLE_HUSH_INTERACTIVE && !ENABLE_FEATURE_EDITING | ||
1653 | /* If user presses ^C, read() restarts after SIGINT (we use SA_RESTART). | ||
1654 | * IOW: ^C will not immediately stop line input. | ||
1655 | * But poll() is different: it does NOT restart after signals. | ||
1656 | */ | ||
1657 | if (fp == G.HFILE_stdin) { | ||
1658 | struct pollfd pfd[1]; | ||
1659 | pfd[0].fd = fp->fd; | ||
1660 | pfd[0].events = POLLIN; | ||
1661 | n = poll(pfd, 1, -1); | ||
1662 | if (n < 0 | ||
1663 | /*&& errno == EINTR - assumed true */ | ||
1664 | && sigismember(&G.pending_set, SIGINT) | ||
1665 | ) { | ||
1666 | return '\0'; | ||
1667 | } | ||
1668 | } | ||
1669 | #else | ||
1670 | /* if FEATURE_EDITING=y, we do not use this routine for interactive input */ | ||
1671 | #endif | ||
1652 | /* Try to buffer more input */ | 1672 | /* Try to buffer more input */ |
1653 | fp->cur = fp->buf; | ||
1654 | n = safe_read(fp->fd, fp->buf, sizeof(fp->buf)); | 1673 | n = safe_read(fp->fd, fp->buf, sizeof(fp->buf)); |
1655 | if (n < 0) { | 1674 | if (n < 0) { |
1656 | bb_simple_perror_msg("read error"); | 1675 | bb_simple_perror_msg("read error"); |
1657 | n = 0; | 1676 | n = 0; |
1658 | } | 1677 | } |
1678 | fp->cur = fp->buf; | ||
1659 | fp->end = fp->buf + n; | 1679 | fp->end = fp->buf + n; |
1660 | if (n == 0) { | 1680 | if (n == 0) { |
1661 | /* EOF/error */ | 1681 | /* EOF/error */ |
@@ -2050,8 +2070,7 @@ static sighandler_t pick_sighandler(unsigned sig) | |||
2050 | static void hush_exit(int exitcode) | 2070 | static void hush_exit(int exitcode) |
2051 | { | 2071 | { |
2052 | #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT | 2072 | #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT |
2053 | if (G.line_input_state) | 2073 | save_history(G.line_input_state); /* may be NULL */ |
2054 | save_history(G.line_input_state); | ||
2055 | #endif | 2074 | #endif |
2056 | 2075 | ||
2057 | fflush_all(); | 2076 | fflush_all(); |
@@ -2091,7 +2110,6 @@ static void hush_exit(int exitcode) | |||
2091 | #endif | 2110 | #endif |
2092 | } | 2111 | } |
2093 | 2112 | ||
2094 | |||
2095 | //TODO: return a mask of ALL handled sigs? | 2113 | //TODO: return a mask of ALL handled sigs? |
2096 | static int check_and_run_traps(void) | 2114 | static int check_and_run_traps(void) |
2097 | { | 2115 | { |
@@ -2259,13 +2277,13 @@ static const char* FAST_FUNC get_local_var_value(const char *name) | |||
2259 | { | 2277 | { |
2260 | const char *fmt = NULL; | 2278 | const char *fmt = NULL; |
2261 | if (strcmp(name, "EPOCHSECONDS") == 0) | 2279 | if (strcmp(name, "EPOCHSECONDS") == 0) |
2262 | fmt = "%lu"; | 2280 | fmt = "%llu"; |
2263 | else if (strcmp(name, "EPOCHREALTIME") == 0) | 2281 | else if (strcmp(name, "EPOCHREALTIME") == 0) |
2264 | fmt = "%lu.%06u"; | 2282 | fmt = "%llu.%06u"; |
2265 | if (fmt) { | 2283 | if (fmt) { |
2266 | struct timeval tv; | 2284 | struct timeval tv; |
2267 | gettimeofday(&tv, NULL); | 2285 | xgettimeofday(&tv); |
2268 | sprintf(G.epoch_buf, fmt, (unsigned long)tv.tv_sec, | 2286 | sprintf(G.epoch_buf, fmt, (unsigned long long)tv.tv_sec, |
2269 | (unsigned)tv.tv_usec); | 2287 | (unsigned)tv.tv_usec); |
2270 | return G.epoch_buf; | 2288 | return G.epoch_buf; |
2271 | } | 2289 | } |
@@ -2614,7 +2632,7 @@ static const char *setup_prompt_string(void) | |||
2614 | /* bash uses $PWD value, even if it is set by user. | 2632 | /* bash uses $PWD value, even if it is set by user. |
2615 | * It uses current dir only if PWD is unset. | 2633 | * It uses current dir only if PWD is unset. |
2616 | * We always use current dir. */ | 2634 | * We always use current dir. */ |
2617 | G.PS1 = xasprintf("%s %c ", get_cwd(0), (geteuid() != 0) ? '$' : '#'); | 2635 | prompt_str = G.PS1 = xasprintf("%s %c ", get_cwd(0), (geteuid() != 0) ? '$' : '#'); |
2618 | } | 2636 | } |
2619 | # endif | 2637 | # endif |
2620 | debug_printf("prompt_str '%s'\n", prompt_str); | 2638 | debug_printf("prompt_str '%s'\n", prompt_str); |
@@ -2622,33 +2640,33 @@ static const char *setup_prompt_string(void) | |||
2622 | } | 2640 | } |
2623 | static int get_user_input(struct in_str *i) | 2641 | static int get_user_input(struct in_str *i) |
2624 | { | 2642 | { |
2643 | # if ENABLE_FEATURE_EDITING | ||
2644 | /* In EDITING case, this function reads next input line, | ||
2645 | * saves it in i->p, then returns 1st char of it. | ||
2646 | */ | ||
2625 | int r; | 2647 | int r; |
2626 | const char *prompt_str; | 2648 | const char *prompt_str; |
2627 | 2649 | ||
2628 | prompt_str = setup_prompt_string(); | 2650 | prompt_str = setup_prompt_string(); |
2629 | # if ENABLE_FEATURE_EDITING | ||
2630 | for (;;) { | 2651 | for (;;) { |
2631 | reinit_unicode_for_hush(); | 2652 | reinit_unicode_for_hush(); |
2632 | if (G.flag_SIGINT) { | 2653 | G.flag_SIGINT = 0; |
2633 | /* There was ^C'ed, make it look prettier: */ | ||
2634 | bb_putchar('\n'); | ||
2635 | G.flag_SIGINT = 0; | ||
2636 | } | ||
2637 | /* buglet: SIGINT will not make new prompt to appear _at once_, | 2654 | /* buglet: SIGINT will not make new prompt to appear _at once_, |
2638 | * only after <Enter>. (^C works immediately) */ | 2655 | * only after <Enter>. (^C works immediately) */ |
2639 | r = read_line_input(G.line_input_state, prompt_str, | 2656 | r = read_line_input(G.line_input_state, prompt_str, |
2640 | G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1 | 2657 | G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1 |
2641 | ); | 2658 | ); |
2642 | /* read_line_input intercepts ^C, "convert" it to SIGINT */ | 2659 | /* read_line_input intercepts ^C, "convert" it to SIGINT */ |
2643 | if (r == 0) | 2660 | if (r == 0) { |
2644 | raise(SIGINT); | 2661 | raise(SIGINT); |
2662 | } | ||
2645 | check_and_run_traps(); | 2663 | check_and_run_traps(); |
2646 | if (r != 0 && !G.flag_SIGINT) | 2664 | if (r != 0 && !G.flag_SIGINT) |
2647 | break; | 2665 | break; |
2648 | /* ^C or SIGINT: repeat */ | 2666 | /* ^C or SIGINT: repeat */ |
2649 | /* bash prints ^C even on real SIGINT (non-kbd generated) */ | 2667 | /* bash prints ^C even on real SIGINT (non-kbd generated) */ |
2650 | write(STDOUT_FILENO, "^C", 2); | 2668 | write(STDOUT_FILENO, "^C\n", 3); |
2651 | G.last_exitcode = 128 + SIGINT; | 2669 | G.last_exitcode = 128 | SIGINT; |
2652 | } | 2670 | } |
2653 | if (r < 0) { | 2671 | if (r < 0) { |
2654 | /* EOF/error detected */ | 2672 | /* EOF/error detected */ |
@@ -2659,9 +2677,15 @@ static int get_user_input(struct in_str *i) | |||
2659 | i->p = G.user_input_buf; | 2677 | i->p = G.user_input_buf; |
2660 | return (unsigned char)*i->p++; | 2678 | return (unsigned char)*i->p++; |
2661 | # else | 2679 | # else |
2680 | /* In !EDITING case, this function gets called for every char. | ||
2681 | * Buffering happens deeper in the call chain, in hfgetc(i->file). | ||
2682 | */ | ||
2683 | int r; | ||
2684 | |||
2662 | for (;;) { | 2685 | for (;;) { |
2663 | G.flag_SIGINT = 0; | 2686 | G.flag_SIGINT = 0; |
2664 | if (i->last_char == '\0' || i->last_char == '\n') { | 2687 | if (i->last_char == '\0' || i->last_char == '\n') { |
2688 | const char *prompt_str = setup_prompt_string(); | ||
2665 | /* Why check_and_run_traps here? Try this interactively: | 2689 | /* Why check_and_run_traps here? Try this interactively: |
2666 | * $ trap 'echo INT' INT; (sleep 2; kill -INT $$) & | 2690 | * $ trap 'echo INT' INT; (sleep 2; kill -INT $$) & |
2667 | * $ <[enter], repeatedly...> | 2691 | * $ <[enter], repeatedly...> |
@@ -2669,19 +2693,23 @@ static int get_user_input(struct in_str *i) | |||
2669 | */ | 2693 | */ |
2670 | check_and_run_traps(); | 2694 | check_and_run_traps(); |
2671 | fputs(prompt_str, stdout); | 2695 | fputs(prompt_str, stdout); |
2696 | fflush_all(); | ||
2672 | } | 2697 | } |
2673 | fflush_all(); | ||
2674 | //FIXME: here ^C or SIGINT will have effect only after <Enter> | ||
2675 | r = hfgetc(i->file); | 2698 | r = hfgetc(i->file); |
2676 | /* In !ENABLE_FEATURE_EDITING we don't use read_line_input, | 2699 | /* In !ENABLE_FEATURE_EDITING we don't use read_line_input, |
2677 | * no ^C masking happens during fgetc, no special code for ^C: | 2700 | * no ^C masking happens during fgetc, no special code for ^C: |
2678 | * it generates SIGINT as usual. | 2701 | * it generates SIGINT as usual. |
2679 | */ | 2702 | */ |
2680 | check_and_run_traps(); | 2703 | check_and_run_traps(); |
2681 | if (G.flag_SIGINT) | 2704 | if (r != '\0' && !G.flag_SIGINT) |
2682 | G.last_exitcode = 128 + SIGINT; | ||
2683 | if (r != '\0') | ||
2684 | break; | 2705 | break; |
2706 | if (G.flag_SIGINT) { | ||
2707 | /* ^C or SIGINT: repeat */ | ||
2708 | /* bash prints ^C even on real SIGINT (non-kbd generated) */ | ||
2709 | /* kernel prints "^C" itself, just print newline: */ | ||
2710 | write(STDOUT_FILENO, "\n", 1); | ||
2711 | G.last_exitcode = 128 | SIGINT; | ||
2712 | } | ||
2685 | } | 2713 | } |
2686 | return r; | 2714 | return r; |
2687 | # endif | 2715 | # endif |
@@ -2703,14 +2731,14 @@ static int fgetc_interactive(struct in_str *i) | |||
2703 | } | 2731 | } |
2704 | return ch; | 2732 | return ch; |
2705 | } | 2733 | } |
2706 | #else | 2734 | #else /* !INTERACTIVE */ |
2707 | static ALWAYS_INLINE int fgetc_interactive(struct in_str *i) | 2735 | static ALWAYS_INLINE int fgetc_interactive(struct in_str *i) |
2708 | { | 2736 | { |
2709 | int ch; | 2737 | int ch; |
2710 | do ch = hfgetc(i->file); while (ch == '\0'); | 2738 | do ch = hfgetc(i->file); while (ch == '\0'); |
2711 | return ch; | 2739 | return ch; |
2712 | } | 2740 | } |
2713 | #endif /* INTERACTIVE */ | 2741 | #endif /* !INTERACTIVE */ |
2714 | 2742 | ||
2715 | static int i_getch(struct in_str *i) | 2743 | static int i_getch(struct in_str *i) |
2716 | { | 2744 | { |
@@ -3888,7 +3916,7 @@ struct reserved_combo { | |||
3888 | char literal[6]; | 3916 | char literal[6]; |
3889 | unsigned char res; | 3917 | unsigned char res; |
3890 | unsigned char assignment_flag; | 3918 | unsigned char assignment_flag; |
3891 | int flag; | 3919 | uint32_t flag; |
3892 | }; | 3920 | }; |
3893 | enum { | 3921 | enum { |
3894 | FLAG_END = (1 << RES_NONE ), | 3922 | FLAG_END = (1 << RES_NONE ), |
@@ -3921,7 +3949,7 @@ static const struct reserved_combo* match_reserved_word(o_string *word) | |||
3921 | * to turn the compound list into a command. | 3949 | * to turn the compound list into a command. |
3922 | * FLAG_START means the word must start a new compound list. | 3950 | * FLAG_START means the word must start a new compound list. |
3923 | */ | 3951 | */ |
3924 | static const struct reserved_combo reserved_list[] = { | 3952 | static const struct reserved_combo reserved_list[] ALIGN4 = { |
3925 | # if ENABLE_HUSH_IF | 3953 | # if ENABLE_HUSH_IF |
3926 | { "!", RES_NONE, NOT_ASSIGNMENT , 0 }, | 3954 | { "!", RES_NONE, NOT_ASSIGNMENT , 0 }, |
3927 | { "if", RES_IF, MAYBE_ASSIGNMENT, FLAG_THEN | FLAG_START }, | 3955 | { "if", RES_IF, MAYBE_ASSIGNMENT, FLAG_THEN | FLAG_START }, |
@@ -5263,19 +5291,19 @@ static struct pipe *parse_stream(char **pstring, | |||
5263 | 5291 | ||
5264 | if (heredoc_cnt) { | 5292 | if (heredoc_cnt) { |
5265 | syntax_error_unterm_str("here document"); | 5293 | syntax_error_unterm_str("here document"); |
5266 | goto parse_error; | 5294 | goto parse_error_exitcode1; |
5267 | } | 5295 | } |
5268 | if (end_trigger == ')') { | 5296 | if (end_trigger == ')') { |
5269 | syntax_error_unterm_ch('('); | 5297 | syntax_error_unterm_ch('('); |
5270 | goto parse_error; | 5298 | goto parse_error_exitcode1; |
5271 | } | 5299 | } |
5272 | if (end_trigger == '}') { | 5300 | if (end_trigger == '}') { |
5273 | syntax_error_unterm_ch('{'); | 5301 | syntax_error_unterm_ch('{'); |
5274 | goto parse_error; | 5302 | goto parse_error_exitcode1; |
5275 | } | 5303 | } |
5276 | 5304 | ||
5277 | if (done_word(&ctx)) { | 5305 | if (done_word(&ctx)) { |
5278 | goto parse_error; | 5306 | goto parse_error_exitcode1; |
5279 | } | 5307 | } |
5280 | o_free_and_set_NULL(&ctx.word); | 5308 | o_free_and_set_NULL(&ctx.word); |
5281 | done_pipe(&ctx, PIPE_SEQ); | 5309 | done_pipe(&ctx, PIPE_SEQ); |
@@ -5345,7 +5373,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5345 | while (1) { | 5373 | while (1) { |
5346 | if (ch == EOF) { | 5374 | if (ch == EOF) { |
5347 | syntax_error_unterm_ch('\''); | 5375 | syntax_error_unterm_ch('\''); |
5348 | goto parse_error; | 5376 | goto parse_error_exitcode1; |
5349 | } | 5377 | } |
5350 | nommu_addchr(&ctx.as_string, ch); | 5378 | nommu_addchr(&ctx.as_string, ch); |
5351 | if (ch == '\'') | 5379 | if (ch == '\'') |
@@ -5424,7 +5452,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5424 | /* ch == last eaten whitespace char */ | 5452 | /* ch == last eaten whitespace char */ |
5425 | #endif | 5453 | #endif |
5426 | if (done_word(&ctx)) { | 5454 | if (done_word(&ctx)) { |
5427 | goto parse_error; | 5455 | goto parse_error_exitcode1; |
5428 | } | 5456 | } |
5429 | if (ch == '\n') { | 5457 | if (ch == '\n') { |
5430 | /* Is this a case when newline is simply ignored? | 5458 | /* Is this a case when newline is simply ignored? |
@@ -5467,7 +5495,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5467 | if (heredoc_cnt) { | 5495 | if (heredoc_cnt) { |
5468 | heredoc_cnt = fetch_heredocs(&ctx.as_string, ctx.list_head, heredoc_cnt, input); | 5496 | heredoc_cnt = fetch_heredocs(&ctx.as_string, ctx.list_head, heredoc_cnt, input); |
5469 | if (heredoc_cnt != 0) | 5497 | if (heredoc_cnt != 0) |
5470 | goto parse_error; | 5498 | goto parse_error_exitcode1; |
5471 | } | 5499 | } |
5472 | ctx.is_assignment = MAYBE_ASSIGNMENT; | 5500 | ctx.is_assignment = MAYBE_ASSIGNMENT; |
5473 | debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]); | 5501 | debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]); |
@@ -5517,7 +5545,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5517 | #endif | 5545 | #endif |
5518 | ) { | 5546 | ) { |
5519 | if (done_word(&ctx)) { | 5547 | if (done_word(&ctx)) { |
5520 | goto parse_error; | 5548 | goto parse_error_exitcode1; |
5521 | } | 5549 | } |
5522 | done_pipe(&ctx, PIPE_SEQ); | 5550 | done_pipe(&ctx, PIPE_SEQ); |
5523 | ctx.is_assignment = MAYBE_ASSIGNMENT; | 5551 | ctx.is_assignment = MAYBE_ASSIGNMENT; |
@@ -5538,7 +5566,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5538 | /* Example: bare "{ }", "()" */ | 5566 | /* Example: bare "{ }", "()" */ |
5539 | G.last_exitcode = 2; /* bash compat */ | 5567 | G.last_exitcode = 2; /* bash compat */ |
5540 | syntax_error_unexpected_ch(ch); | 5568 | syntax_error_unexpected_ch(ch); |
5541 | goto parse_error2; | 5569 | goto parse_error; |
5542 | } | 5570 | } |
5543 | if (heredoc_cnt_ptr) | 5571 | if (heredoc_cnt_ptr) |
5544 | *heredoc_cnt_ptr = heredoc_cnt; | 5572 | *heredoc_cnt_ptr = heredoc_cnt; |
@@ -5560,7 +5588,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5560 | case '>': | 5588 | case '>': |
5561 | redir_fd = redirect_opt_num(&ctx.word); | 5589 | redir_fd = redirect_opt_num(&ctx.word); |
5562 | if (done_word(&ctx)) { | 5590 | if (done_word(&ctx)) { |
5563 | goto parse_error; | 5591 | goto parse_error_exitcode1; |
5564 | } | 5592 | } |
5565 | redir_style = REDIRECT_OVERWRITE; | 5593 | redir_style = REDIRECT_OVERWRITE; |
5566 | if (next == '>') { | 5594 | if (next == '>') { |
@@ -5571,16 +5599,16 @@ static struct pipe *parse_stream(char **pstring, | |||
5571 | #if 0 | 5599 | #if 0 |
5572 | else if (next == '(') { | 5600 | else if (next == '(') { |
5573 | syntax_error(">(process) not supported"); | 5601 | syntax_error(">(process) not supported"); |
5574 | goto parse_error; | 5602 | goto parse_error_exitcode1; |
5575 | } | 5603 | } |
5576 | #endif | 5604 | #endif |
5577 | if (parse_redirect(&ctx, redir_fd, redir_style, input)) | 5605 | if (parse_redirect(&ctx, redir_fd, redir_style, input)) |
5578 | goto parse_error; | 5606 | goto parse_error_exitcode1; |
5579 | continue; /* get next char */ | 5607 | continue; /* get next char */ |
5580 | case '<': | 5608 | case '<': |
5581 | redir_fd = redirect_opt_num(&ctx.word); | 5609 | redir_fd = redirect_opt_num(&ctx.word); |
5582 | if (done_word(&ctx)) { | 5610 | if (done_word(&ctx)) { |
5583 | goto parse_error; | 5611 | goto parse_error_exitcode1; |
5584 | } | 5612 | } |
5585 | redir_style = REDIRECT_INPUT; | 5613 | redir_style = REDIRECT_INPUT; |
5586 | if (next == '<') { | 5614 | if (next == '<') { |
@@ -5597,11 +5625,11 @@ static struct pipe *parse_stream(char **pstring, | |||
5597 | #if 0 | 5625 | #if 0 |
5598 | else if (next == '(') { | 5626 | else if (next == '(') { |
5599 | syntax_error("<(process) not supported"); | 5627 | syntax_error("<(process) not supported"); |
5600 | goto parse_error; | 5628 | goto parse_error_exitcode1; |
5601 | } | 5629 | } |
5602 | #endif | 5630 | #endif |
5603 | if (parse_redirect(&ctx, redir_fd, redir_style, input)) | 5631 | if (parse_redirect(&ctx, redir_fd, redir_style, input)) |
5604 | goto parse_error; | 5632 | goto parse_error_exitcode1; |
5605 | continue; /* get next char */ | 5633 | continue; /* get next char */ |
5606 | case '#': | 5634 | case '#': |
5607 | if (ctx.word.length == 0 && !ctx.word.has_quoted_part) { | 5635 | if (ctx.word.length == 0 && !ctx.word.has_quoted_part) { |
@@ -5655,7 +5683,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5655 | if (!parse_dollar(&ctx.as_string, &ctx.word, input, /*quote_mask:*/ 0)) { | 5683 | if (!parse_dollar(&ctx.as_string, &ctx.word, input, /*quote_mask:*/ 0)) { |
5656 | debug_printf_parse("parse_stream parse error: " | 5684 | debug_printf_parse("parse_stream parse error: " |
5657 | "parse_dollar returned 0 (error)\n"); | 5685 | "parse_dollar returned 0 (error)\n"); |
5658 | goto parse_error; | 5686 | goto parse_error_exitcode1; |
5659 | } | 5687 | } |
5660 | continue; /* get next char */ | 5688 | continue; /* get next char */ |
5661 | case '"': | 5689 | case '"': |
@@ -5671,7 +5699,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5671 | if (ctx.is_assignment == NOT_ASSIGNMENT) | 5699 | if (ctx.is_assignment == NOT_ASSIGNMENT) |
5672 | ctx.word.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS; | 5700 | ctx.word.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS; |
5673 | if (!encode_string(&ctx.as_string, &ctx.word, input, '"')) | 5701 | if (!encode_string(&ctx.as_string, &ctx.word, input, '"')) |
5674 | goto parse_error; | 5702 | goto parse_error_exitcode1; |
5675 | ctx.word.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS; | 5703 | ctx.word.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS; |
5676 | continue; /* get next char */ | 5704 | continue; /* get next char */ |
5677 | #if ENABLE_HUSH_TICK | 5705 | #if ENABLE_HUSH_TICK |
@@ -5682,7 +5710,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5682 | o_addchr(&ctx.word, '`'); | 5710 | o_addchr(&ctx.word, '`'); |
5683 | USE_FOR_NOMMU(pos = ctx.word.length;) | 5711 | USE_FOR_NOMMU(pos = ctx.word.length;) |
5684 | if (!add_till_backquote(&ctx.word, input, /*in_dquote:*/ 0)) | 5712 | if (!add_till_backquote(&ctx.word, input, /*in_dquote:*/ 0)) |
5685 | goto parse_error; | 5713 | goto parse_error_exitcode1; |
5686 | # if !BB_MMU | 5714 | # if !BB_MMU |
5687 | o_addstr(&ctx.as_string, ctx.word.data + pos); | 5715 | o_addstr(&ctx.as_string, ctx.word.data + pos); |
5688 | o_addchr(&ctx.as_string, '`'); | 5716 | o_addchr(&ctx.as_string, '`'); |
@@ -5697,7 +5725,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5697 | case_semi: | 5725 | case_semi: |
5698 | #endif | 5726 | #endif |
5699 | if (done_word(&ctx)) { | 5727 | if (done_word(&ctx)) { |
5700 | goto parse_error; | 5728 | goto parse_error_exitcode1; |
5701 | } | 5729 | } |
5702 | done_pipe(&ctx, PIPE_SEQ); | 5730 | done_pipe(&ctx, PIPE_SEQ); |
5703 | #if ENABLE_HUSH_CASE | 5731 | #if ENABLE_HUSH_CASE |
@@ -5724,7 +5752,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5724 | continue; /* get next char */ | 5752 | continue; /* get next char */ |
5725 | case '&': | 5753 | case '&': |
5726 | if (done_word(&ctx)) { | 5754 | if (done_word(&ctx)) { |
5727 | goto parse_error; | 5755 | goto parse_error_exitcode1; |
5728 | } | 5756 | } |
5729 | if (next == '&') { | 5757 | if (next == '&') { |
5730 | ch = i_getch(input); | 5758 | ch = i_getch(input); |
@@ -5736,7 +5764,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5736 | goto new_cmd; | 5764 | goto new_cmd; |
5737 | case '|': | 5765 | case '|': |
5738 | if (done_word(&ctx)) { | 5766 | if (done_word(&ctx)) { |
5739 | goto parse_error; | 5767 | goto parse_error_exitcode1; |
5740 | } | 5768 | } |
5741 | #if ENABLE_HUSH_CASE | 5769 | #if ENABLE_HUSH_CASE |
5742 | if (ctx.ctx_res_w == RES_MATCH) | 5770 | if (ctx.ctx_res_w == RES_MATCH) |
@@ -5768,7 +5796,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5768 | case '{': { | 5796 | case '{': { |
5769 | int n = parse_group(&ctx, input, ch); | 5797 | int n = parse_group(&ctx, input, ch); |
5770 | if (n < 0) { | 5798 | if (n < 0) { |
5771 | goto parse_error; | 5799 | goto parse_error_exitcode1; |
5772 | } | 5800 | } |
5773 | debug_printf_heredoc("parse_group done, needs heredocs:%d\n", n); | 5801 | debug_printf_heredoc("parse_group done, needs heredocs:%d\n", n); |
5774 | heredoc_cnt += n; | 5802 | heredoc_cnt += n; |
@@ -5786,16 +5814,16 @@ static struct pipe *parse_stream(char **pstring, | |||
5786 | * and it will match } earlier (not here). */ | 5814 | * and it will match } earlier (not here). */ |
5787 | G.last_exitcode = 2; | 5815 | G.last_exitcode = 2; |
5788 | syntax_error_unexpected_ch(ch); | 5816 | syntax_error_unexpected_ch(ch); |
5789 | goto parse_error2; | 5817 | goto parse_error; |
5790 | default: | 5818 | default: |
5791 | if (HUSH_DEBUG) | 5819 | if (HUSH_DEBUG) |
5792 | bb_error_msg_and_die("BUG: unexpected %c", ch); | 5820 | bb_error_msg_and_die("BUG: unexpected %c", ch); |
5793 | } | 5821 | } |
5794 | } /* while (1) */ | 5822 | } /* while (1) */ |
5795 | 5823 | ||
5796 | parse_error: | 5824 | parse_error_exitcode1: |
5797 | G.last_exitcode = 1; | 5825 | G.last_exitcode = 1; |
5798 | parse_error2: | 5826 | parse_error: |
5799 | { | 5827 | { |
5800 | struct parse_context *pctx; | 5828 | struct parse_context *pctx; |
5801 | IF_HAS_KEYWORDS(struct parse_context *p2;) | 5829 | IF_HAS_KEYWORDS(struct parse_context *p2;) |
@@ -6490,9 +6518,11 @@ static NOINLINE int expand_one_var(o_string *output, int n, | |||
6490 | * Word is expanded to produce a glob pattern. | 6518 | * Word is expanded to produce a glob pattern. |
6491 | * Then var's value is matched to it and matching part removed. | 6519 | * Then var's value is matched to it and matching part removed. |
6492 | */ | 6520 | */ |
6493 | //FIXME: ${x#...${...}...} | 6521 | /* bash compat: if x is "" and no shrinking of it is possible, |
6494 | //should evaluate inner ${...} even if x is "" and no shrinking of it is possible - | 6522 | * inner ${...} is not evaluated. Example: |
6495 | //inner ${...} may have side effects! | 6523 | * unset b; : ${a%${b=B}}; echo $b |
6524 | * assignment b=B only happens if $a is not "". | ||
6525 | */ | ||
6496 | if (val && val[0]) { | 6526 | if (val && val[0]) { |
6497 | char *t; | 6527 | char *t; |
6498 | char *exp_exp_word; | 6528 | char *exp_exp_word; |
@@ -6531,7 +6561,12 @@ static NOINLINE int expand_one_var(o_string *output, int n, | |||
6531 | * and if // is used, it is encoded as \: | 6561 | * and if // is used, it is encoded as \: |
6532 | * var\pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL> | 6562 | * var\pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL> |
6533 | */ | 6563 | */ |
6534 | if (val && val[0]) { | 6564 | /* bash compat: if var is "", both pattern and repl |
6565 | * are still evaluated, if it is unset, then not: | ||
6566 | * unset b; a=; : ${a/z/${b=3}}; echo $b # b=3 | ||
6567 | * unset b; unset a; : ${a/z/${b=3}}; echo $b # b not set | ||
6568 | */ | ||
6569 | if (val /*&& val[0]*/) { | ||
6535 | /* pattern uses non-standard expansion. | 6570 | /* pattern uses non-standard expansion. |
6536 | * repl should be unbackslashed and globbed | 6571 | * repl should be unbackslashed and globbed |
6537 | * by the usual expansion rules: | 6572 | * by the usual expansion rules: |
@@ -6567,8 +6602,9 @@ static NOINLINE int expand_one_var(o_string *output, int n, | |||
6567 | free(pattern); | 6602 | free(pattern); |
6568 | free(repl); | 6603 | free(repl); |
6569 | } else { | 6604 | } else { |
6570 | /* Empty variable always gives nothing */ | 6605 | /* Unset variable always gives nothing */ |
6571 | // "v=''; echo ${v/*/w}" prints "", not "w" | 6606 | // a=; echo ${a/*/w} # "w" |
6607 | // unset a; echo ${a/*/w} # "" | ||
6572 | /* Just skip "replace" part */ | 6608 | /* Just skip "replace" part */ |
6573 | *p++ = SPECIAL_VAR_SYMBOL; | 6609 | *p++ = SPECIAL_VAR_SYMBOL; |
6574 | p = strchr(p, SPECIAL_VAR_SYMBOL); | 6610 | p = strchr(p, SPECIAL_VAR_SYMBOL); |
@@ -6583,40 +6619,48 @@ static NOINLINE int expand_one_var(o_string *output, int n, | |||
6583 | * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL> | 6619 | * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL> |
6584 | */ | 6620 | */ |
6585 | arith_t beg, len; | 6621 | arith_t beg, len; |
6622 | unsigned vallen; | ||
6586 | const char *errmsg; | 6623 | const char *errmsg; |
6587 | 6624 | ||
6588 | beg = expand_and_evaluate_arith(exp_word, &errmsg); | 6625 | beg = expand_and_evaluate_arith(exp_word, &errmsg); |
6589 | if (errmsg) | 6626 | if (errmsg) |
6590 | goto arith_err; | 6627 | goto empty_result; |
6591 | debug_printf_varexp("beg:'%s'=%lld\n", exp_word, (long long)beg); | 6628 | debug_printf_varexp("beg:'%s'=%lld\n", exp_word, (long long)beg); |
6592 | *p++ = SPECIAL_VAR_SYMBOL; | 6629 | *p++ = SPECIAL_VAR_SYMBOL; |
6593 | exp_word = p; | 6630 | exp_word = p; |
6594 | p = strchr(p, SPECIAL_VAR_SYMBOL); | 6631 | p = strchr(p, SPECIAL_VAR_SYMBOL); |
6595 | *p = '\0'; | 6632 | *p = '\0'; |
6596 | len = expand_and_evaluate_arith(exp_word, &errmsg); | 6633 | vallen = val ? strlen(val) : 0; |
6597 | if (errmsg) | ||
6598 | goto arith_err; | ||
6599 | debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len); | ||
6600 | if (beg < 0) { | 6634 | if (beg < 0) { |
6601 | /* negative beg counts from the end */ | 6635 | /* negative beg counts from the end */ |
6602 | beg = (arith_t)strlen(val) + beg; | 6636 | beg = (arith_t)vallen + beg; |
6603 | if (beg < 0) /* ${v: -999999} is "" */ | 6637 | } |
6604 | beg = len = 0; | 6638 | /* If expansion will be empty, do not even evaluate len */ |
6639 | if (!val || beg < 0 || beg > vallen) { | ||
6640 | /* Why > vallen, not >=? bash: | ||
6641 | * unset b; a=ab; : ${a:2:${b=3}}; echo $b # "", b=3 (!!!) | ||
6642 | * unset b; a=a; : ${a:2:${b=3}}; echo $b # "", b not set | ||
6643 | */ | ||
6644 | goto empty_result; | ||
6605 | } | 6645 | } |
6646 | len = expand_and_evaluate_arith(exp_word, &errmsg); | ||
6647 | if (errmsg) | ||
6648 | goto empty_result; | ||
6649 | debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len); | ||
6606 | debug_printf_varexp("from val:'%s'\n", val); | 6650 | debug_printf_varexp("from val:'%s'\n", val); |
6607 | if (len < 0) { | 6651 | if (len < 0) { |
6608 | /* in bash, len=-n means strlen()-n */ | 6652 | /* in bash, len=-n means strlen()-n */ |
6609 | len = (arith_t)strlen(val) - beg + len; | 6653 | len = (arith_t)vallen - beg + len; |
6610 | if (len < 0) /* bash compat */ | 6654 | if (len < 0) /* bash compat */ |
6611 | msg_and_die_if_script("%s: substring expression < 0", var); | 6655 | msg_and_die_if_script("%s: substring expression < 0", var); |
6612 | } | 6656 | } |
6613 | if (len <= 0 || !val || beg >= strlen(val)) { | 6657 | if (len <= 0 || !val /*|| beg >= vallen*/) { |
6614 | arith_err: | 6658 | empty_result: |
6615 | val = NULL; | 6659 | val = NULL; |
6616 | } else { | 6660 | } else { |
6617 | /* Paranoia. What if user entered 9999999999999 | 6661 | /* Paranoia. What if user entered 9999999999999 |
6618 | * which fits in arith_t but not int? */ | 6662 | * which fits in arith_t but not int? */ |
6619 | if (len >= INT_MAX) | 6663 | if (len > INT_MAX) |
6620 | len = INT_MAX; | 6664 | len = INT_MAX; |
6621 | val = to_be_freed = xstrndup(val + beg, len); | 6665 | val = to_be_freed = xstrndup(val + beg, len); |
6622 | } | 6666 | } |
@@ -6650,12 +6694,13 @@ static NOINLINE int expand_one_var(o_string *output, int n, | |||
6650 | * | 6694 | * |
6651 | * Word-splitting and single quote behavior: | 6695 | * Word-splitting and single quote behavior: |
6652 | * | 6696 | * |
6653 | * $ f() { for i; do echo "|$i|"; done; }; | 6697 | * $ f() { for i; do echo "|$i|"; done; } |
6654 | * | 6698 | * |
6655 | * $ x=; f ${x:?'x y' z} | 6699 | * $ x=; f ${x:?'x y' z}; echo $? |
6656 | * bash: x: x y z #BUG: does not abort, ${} results in empty expansion | 6700 | * bash: x: x y z # neither f nor "echo $?" executes |
6701 | * (if interactive, bash does not exit, but merely aborts to prompt. $? is set to 1) | ||
6657 | * $ x=; f "${x:?'x y' z}" | 6702 | * $ x=; f "${x:?'x y' z}" |
6658 | * bash: x: x y z # dash prints: dash: x: 'x y' z #BUG: does not abort, ${} results in "" | 6703 | * bash: x: x y z # dash prints: dash: x: 'x y' z |
6659 | * | 6704 | * |
6660 | * $ x=; f ${x:='x y' z} | 6705 | * $ x=; f ${x:='x y' z} |
6661 | * |x| | 6706 | * |x| |
@@ -7743,7 +7788,11 @@ static void restore_redirects(struct squirrel *sq) | |||
7743 | free(sq); | 7788 | free(sq); |
7744 | } | 7789 | } |
7745 | if (G.HFILE_stdin | 7790 | if (G.HFILE_stdin |
7746 | && G.HFILE_stdin->fd != STDIN_FILENO | 7791 | && G.HFILE_stdin->fd > STDIN_FILENO |
7792 | /* we compare > STDIN, not == STDIN, since hfgetc() | ||
7793 | * closes fd and sets ->fd to -1 if EOF is reached. | ||
7794 | * Testcase: echo 'pwd' | hush | ||
7795 | */ | ||
7747 | ) { | 7796 | ) { |
7748 | /* Testcase: interactive "read r <FILE; echo $r; read r; echo $r". | 7797 | /* Testcase: interactive "read r <FILE; echo $r; read r; echo $r". |
7749 | * Redirect moves ->fd to e.g. 10, | 7798 | * Redirect moves ->fd to e.g. 10, |
@@ -8136,7 +8185,6 @@ static void exec_function(char ***to_free, | |||
8136 | 8185 | ||
8137 | /* On MMU, funcp->body is always non-NULL */ | 8186 | /* On MMU, funcp->body is always non-NULL */ |
8138 | n = run_list(funcp->body); | 8187 | n = run_list(funcp->body); |
8139 | fflush_all(); | ||
8140 | _exit(n); | 8188 | _exit(n); |
8141 | # else | 8189 | # else |
8142 | //? close_saved_fds_and_FILE_fds(); | 8190 | //? close_saved_fds_and_FILE_fds(); |
@@ -8211,7 +8259,6 @@ static void exec_builtin(char ***to_free, | |||
8211 | { | 8259 | { |
8212 | #if BB_MMU | 8260 | #if BB_MMU |
8213 | int rcode; | 8261 | int rcode; |
8214 | fflush_all(); | ||
8215 | //? close_saved_fds_and_FILE_fds(); | 8262 | //? close_saved_fds_and_FILE_fds(); |
8216 | rcode = x->b_function(argv); | 8263 | rcode = x->b_function(argv); |
8217 | fflush_all(); | 8264 | fflush_all(); |
@@ -8715,6 +8762,7 @@ static int process_wait_result(struct pipe *fg_pipe, pid_t childpid, int status) | |||
8715 | */ | 8762 | */ |
8716 | if (WIFSIGNALED(status)) { | 8763 | if (WIFSIGNALED(status)) { |
8717 | int sig = WTERMSIG(status); | 8764 | int sig = WTERMSIG(status); |
8765 | #if ENABLE_HUSH_JOB | ||
8718 | if (G.run_list_level == 1 | 8766 | if (G.run_list_level == 1 |
8719 | /* ^^^^^ Do not print in nested contexts, example: | 8767 | /* ^^^^^ Do not print in nested contexts, example: |
8720 | * echo `sleep 1; sh -c 'kill -9 $$'` - prints "137", NOT "Killed 137" | 8768 | * echo `sleep 1; sh -c 'kill -9 $$'` - prints "137", NOT "Killed 137" |
@@ -8724,10 +8772,12 @@ static int process_wait_result(struct pipe *fg_pipe, pid_t childpid, int status) | |||
8724 | /* strsignal() is for bash compat. ~600 bloat versus bbox's get_signame() */ | 8772 | /* strsignal() is for bash compat. ~600 bloat versus bbox's get_signame() */ |
8725 | puts(sig == SIGINT || sig == SIGPIPE ? "" : strsignal(sig)); | 8773 | puts(sig == SIGINT || sig == SIGPIPE ? "" : strsignal(sig)); |
8726 | } | 8774 | } |
8775 | #endif | ||
8727 | /* TODO: if (WCOREDUMP(status)) + " (core dumped)"; */ | 8776 | /* TODO: if (WCOREDUMP(status)) + " (core dumped)"; */ |
8728 | /* TODO: MIPS has 128 sigs (1..128), what if sig==128 here? | 8777 | /* MIPS has 128 sigs (1..128), if sig==128, |
8729 | * Maybe we need to use sig | 128? */ | 8778 | * 128 + sig would result in exitcode 256 -> 0! |
8730 | ex = sig + 128; | 8779 | */ |
8780 | ex = 128 | sig; | ||
8731 | } | 8781 | } |
8732 | fg_pipe->cmds[i].cmd_exitcode = ex; | 8782 | fg_pipe->cmds[i].cmd_exitcode = ex; |
8733 | } else { | 8783 | } else { |
@@ -8774,7 +8824,8 @@ static int process_wait_result(struct pipe *fg_pipe, pid_t childpid, int status) | |||
8774 | /* child exited */ | 8824 | /* child exited */ |
8775 | int rcode = WEXITSTATUS(status); | 8825 | int rcode = WEXITSTATUS(status); |
8776 | if (WIFSIGNALED(status)) | 8826 | if (WIFSIGNALED(status)) |
8777 | rcode = 128 + WTERMSIG(status); | 8827 | /* NB: not 128 + sig, MIPS has sig 128 */ |
8828 | rcode = 128 | WTERMSIG(status); | ||
8778 | pi->cmds[i].cmd_exitcode = rcode; | 8829 | pi->cmds[i].cmd_exitcode = rcode; |
8779 | if (G.last_bg_pid == pi->cmds[i].pid) | 8830 | if (G.last_bg_pid == pi->cmds[i].pid) |
8780 | G.last_bg_pid_exitcode = rcode; | 8831 | G.last_bg_pid_exitcode = rcode; |
@@ -8894,10 +8945,10 @@ static int checkjobs(struct pipe *fg_pipe, pid_t waitfor_pid) | |||
8894 | debug_printf_exec("childpid==waitfor_pid:%d status:0x%08x\n", childpid, status); | 8945 | debug_printf_exec("childpid==waitfor_pid:%d status:0x%08x\n", childpid, status); |
8895 | rcode = WEXITSTATUS(status); | 8946 | rcode = WEXITSTATUS(status); |
8896 | if (WIFSIGNALED(status)) | 8947 | if (WIFSIGNALED(status)) |
8897 | rcode = 128 + WTERMSIG(status); | 8948 | rcode = 128 | WTERMSIG(status); |
8898 | if (WIFSTOPPED(status)) | 8949 | if (WIFSTOPPED(status)) |
8899 | /* bash: "cmd & wait $!" and cmd stops: $? = 128 + stopsig */ | 8950 | /* bash: "cmd & wait $!" and cmd stops: $? = 128 | stopsig */ |
8900 | rcode = 128 + WSTOPSIG(status); | 8951 | rcode = 128 | WSTOPSIG(status); |
8901 | rcode++; | 8952 | rcode++; |
8902 | break; /* "wait PID" called us, give it exitcode+1 */ | 8953 | break; /* "wait PID" called us, give it exitcode+1 */ |
8903 | } | 8954 | } |
@@ -9287,7 +9338,7 @@ static NOINLINE int run_pipe(struct pipe *pi) | |||
9287 | * during builtin/nofork. | 9338 | * during builtin/nofork. |
9288 | */ | 9339 | */ |
9289 | if (sigismember(&G.pending_set, SIGINT)) | 9340 | if (sigismember(&G.pending_set, SIGINT)) |
9290 | rcode = 128 + SIGINT; | 9341 | rcode = 128 | SIGINT; |
9291 | } | 9342 | } |
9292 | free(argv_expanded); | 9343 | free(argv_expanded); |
9293 | IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;) | 9344 | IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;) |
@@ -9972,11 +10023,14 @@ static int set_mode(int state, char mode, const char *o_opt) | |||
9972 | int hush_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 10023 | int hush_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
9973 | int hush_main(int argc, char **argv) | 10024 | int hush_main(int argc, char **argv) |
9974 | { | 10025 | { |
10026 | pid_t cached_getpid; | ||
9975 | enum { | 10027 | enum { |
9976 | OPT_login = (1 << 0), | 10028 | OPT_login = (1 << 0), |
9977 | }; | 10029 | }; |
9978 | unsigned flags; | 10030 | unsigned flags; |
9979 | unsigned builtin_argc; | 10031 | #if !BB_MMU |
10032 | unsigned builtin_argc = 0; | ||
10033 | #endif | ||
9980 | char **e; | 10034 | char **e; |
9981 | struct variable *cur_var; | 10035 | struct variable *cur_var; |
9982 | struct variable *shell_ver; | 10036 | struct variable *shell_ver; |
@@ -9998,6 +10052,10 @@ int hush_main(int argc, char **argv) | |||
9998 | G.argv0_for_re_execing = argv[0]; | 10052 | G.argv0_for_re_execing = argv[0]; |
9999 | #endif | 10053 | #endif |
10000 | 10054 | ||
10055 | cached_getpid = getpid(); /* for tcsetpgrp() during init */ | ||
10056 | G.root_pid = cached_getpid; /* for $PID (NOMMU can override via -$HEXPID:HEXPPID:...) */ | ||
10057 | G.root_ppid = getppid(); /* for $PPID (NOMMU can override) */ | ||
10058 | |||
10001 | /* Deal with HUSH_VERSION */ | 10059 | /* Deal with HUSH_VERSION */ |
10002 | debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); | 10060 | debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); |
10003 | unsetenv("HUSH_VERSION"); /* in case it exists in initial env */ | 10061 | unsetenv("HUSH_VERSION"); /* in case it exists in initial env */ |
@@ -10080,6 +10138,17 @@ int hush_main(int argc, char **argv) | |||
10080 | * PS4='+ ' | 10138 | * PS4='+ ' |
10081 | */ | 10139 | */ |
10082 | 10140 | ||
10141 | #if NUM_SCRIPTS > 0 | ||
10142 | if (argc < 0) { | ||
10143 | char *script = get_script_content(-argc - 1); | ||
10144 | G.global_argv = argv; | ||
10145 | G.global_argc = string_array_len(argv); | ||
10146 | //install_special_sighandlers(); - needed? | ||
10147 | parse_and_run_string(script); | ||
10148 | goto final_return; | ||
10149 | } | ||
10150 | #endif | ||
10151 | |||
10083 | /* Initialize some more globals to non-zero values */ | 10152 | /* Initialize some more globals to non-zero values */ |
10084 | die_func = restore_ttypgrp_and__exit; | 10153 | die_func = restore_ttypgrp_and__exit; |
10085 | 10154 | ||
@@ -10093,17 +10162,9 @@ int hush_main(int argc, char **argv) | |||
10093 | /* Parse options */ | 10162 | /* Parse options */ |
10094 | /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */ | 10163 | /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */ |
10095 | flags = (argv[0] && argv[0][0] == '-') ? OPT_login : 0; | 10164 | flags = (argv[0] && argv[0][0] == '-') ? OPT_login : 0; |
10096 | builtin_argc = 0; | ||
10097 | #if NUM_SCRIPTS > 0 | ||
10098 | if (argc < 0) { | ||
10099 | optarg = get_script_content(-argc - 1); | ||
10100 | optind = 0; | ||
10101 | argc = string_array_len(argv); | ||
10102 | goto run_script; | ||
10103 | } | ||
10104 | #endif | ||
10105 | while (1) { | 10165 | while (1) { |
10106 | int opt = getopt(argc, argv, "+c:exinsl" | 10166 | int opt = getopt(argc, argv, "+" /* stop at 1st non-option */ |
10167 | "cexinsl" | ||
10107 | #if !BB_MMU | 10168 | #if !BB_MMU |
10108 | "<:$:R:V:" | 10169 | "<:$:R:V:" |
10109 | # if ENABLE_HUSH_FUNCTIONS | 10170 | # if ENABLE_HUSH_FUNCTIONS |
@@ -10115,50 +10176,11 @@ int hush_main(int argc, char **argv) | |||
10115 | break; | 10176 | break; |
10116 | switch (opt) { | 10177 | switch (opt) { |
10117 | case 'c': | 10178 | case 'c': |
10118 | /* Possibilities: | 10179 | /* Note: -c is not an option with param! |
10119 | * sh ... -c 'script' | 10180 | * "hush -c -l SCRIPT" is valid. "hush -cSCRIPT" is not. |
10120 | * sh ... -c 'script' ARG0 [ARG1...] | ||
10121 | * On NOMMU, if builtin_argc != 0, | ||
10122 | * sh ... -c 'builtin' BARGV... "" ARG0 [ARG1...] | ||
10123 | * "" needs to be replaced with NULL | ||
10124 | * and BARGV vector fed to builtin function. | ||
10125 | * Note: the form without ARG0 never happens: | ||
10126 | * sh ... -c 'builtin' BARGV... "" | ||
10127 | */ | 10181 | */ |
10128 | #if NUM_SCRIPTS > 0 | ||
10129 | run_script: | ||
10130 | #endif | ||
10131 | if (!G.root_pid) { | ||
10132 | G.root_pid = getpid(); | ||
10133 | G.root_ppid = getppid(); | ||
10134 | } | ||
10135 | G.global_argv = argv + optind; | ||
10136 | G.global_argc = argc - optind; | ||
10137 | if (builtin_argc) { | ||
10138 | /* -c 'builtin' [BARGV...] "" ARG0 [ARG1...] */ | ||
10139 | const struct built_in_command *x; | ||
10140 | |||
10141 | install_special_sighandlers(); | ||
10142 | x = find_builtin(optarg); | ||
10143 | if (x) { /* paranoia */ | ||
10144 | G.global_argc -= builtin_argc; /* skip [BARGV...] "" */ | ||
10145 | G.global_argv += builtin_argc; | ||
10146 | G.global_argv[-1] = NULL; /* replace "" */ | ||
10147 | fflush_all(); | ||
10148 | G.last_exitcode = x->b_function(argv + optind - 1); | ||
10149 | } | ||
10150 | goto final_return; | ||
10151 | } | ||
10152 | G.opt_c = 1; | 10182 | G.opt_c = 1; |
10153 | if (!G.global_argv[0]) { | 10183 | break; |
10154 | /* -c 'script' (no params): prevent empty $0 */ | ||
10155 | G.global_argv--; /* points to argv[i] of 'script' */ | ||
10156 | G.global_argv[0] = argv[0]; | ||
10157 | G.global_argc++; | ||
10158 | } /* else -c 'script' ARG0 [ARG1...]: $0 is ARG0 */ | ||
10159 | install_special_sighandlers(); | ||
10160 | parse_and_run_string(optarg); | ||
10161 | goto final_return; | ||
10162 | case 'i': | 10184 | case 'i': |
10163 | /* Well, we cannot just declare interactiveness, | 10185 | /* Well, we cannot just declare interactiveness, |
10164 | * we have to have some stuff (ctty, etc) */ | 10186 | * we have to have some stuff (ctty, etc) */ |
@@ -10205,6 +10227,11 @@ int hush_main(int argc, char **argv) | |||
10205 | optarg++; | 10227 | optarg++; |
10206 | G.depth_of_loop = bb_strtou(optarg, &optarg, 16); | 10228 | G.depth_of_loop = bb_strtou(optarg, &optarg, 16); |
10207 | # endif | 10229 | # endif |
10230 | /* Suppress "killed by signal" message, -$ hack is used | ||
10231 | * for subshells: echo `sh -c 'kill -9 $$'` | ||
10232 | * should be silent. | ||
10233 | */ | ||
10234 | IF_HUSH_JOB(G.run_list_level = 1;) | ||
10208 | # if ENABLE_HUSH_FUNCTIONS | 10235 | # if ENABLE_HUSH_FUNCTIONS |
10209 | /* nommu uses re-exec trick for "... | func | ...", | 10236 | /* nommu uses re-exec trick for "... | func | ...", |
10210 | * should allow "return". | 10237 | * should allow "return". |
@@ -10229,19 +10256,14 @@ int hush_main(int argc, char **argv) | |||
10229 | } | 10256 | } |
10230 | # endif | 10257 | # endif |
10231 | #endif | 10258 | #endif |
10232 | case 'n': | 10259 | /*case '?': invalid option encountered (set_mode('?') will fail) */ |
10233 | case 'x': | 10260 | /*case 'n':*/ |
10234 | case 'e': | 10261 | /*case 'x':*/ |
10262 | /*case 'e':*/ | ||
10263 | default: | ||
10235 | if (set_mode(1, opt, NULL) == 0) /* no error */ | 10264 | if (set_mode(1, opt, NULL) == 0) /* no error */ |
10236 | break; | 10265 | break; |
10237 | default: | ||
10238 | #ifndef BB_VER | ||
10239 | fprintf(stderr, "Usage: sh [FILE]...\n" | ||
10240 | " or: sh -c command [args]...\n\n"); | ||
10241 | exit(EXIT_FAILURE); | ||
10242 | #else | ||
10243 | bb_show_usage(); | 10266 | bb_show_usage(); |
10244 | #endif | ||
10245 | } | 10267 | } |
10246 | } /* option parsing loop */ | 10268 | } /* option parsing loop */ |
10247 | 10269 | ||
@@ -10250,16 +10272,14 @@ int hush_main(int argc, char **argv) | |||
10250 | G.global_argv = argv + (optind - 1); | 10272 | G.global_argv = argv + (optind - 1); |
10251 | G.global_argv[0] = argv[0]; | 10273 | G.global_argv[0] = argv[0]; |
10252 | 10274 | ||
10253 | if (!G.root_pid) { | ||
10254 | G.root_pid = getpid(); | ||
10255 | G.root_ppid = getppid(); | ||
10256 | } | ||
10257 | |||
10258 | /* If we are login shell... */ | 10275 | /* If we are login shell... */ |
10259 | if (flags & OPT_login) { | 10276 | if (flags & OPT_login) { |
10277 | const char *hp = NULL; | ||
10260 | HFILE *input; | 10278 | HFILE *input; |
10279 | |||
10261 | debug_printf("sourcing /etc/profile\n"); | 10280 | debug_printf("sourcing /etc/profile\n"); |
10262 | input = hfopen("/etc/profile"); | 10281 | input = hfopen("/etc/profile"); |
10282 | run_profile: | ||
10263 | if (input != NULL) { | 10283 | if (input != NULL) { |
10264 | install_special_sighandlers(); | 10284 | install_special_sighandlers(); |
10265 | parse_and_run_file(input); | 10285 | parse_and_run_file(input); |
@@ -10272,6 +10292,64 @@ int hush_main(int argc, char **argv) | |||
10272 | * bash also sources ~/.bash_logout on exit. | 10292 | * bash also sources ~/.bash_logout on exit. |
10273 | * If called as sh, skips .bash_XXX files. | 10293 | * If called as sh, skips .bash_XXX files. |
10274 | */ | 10294 | */ |
10295 | if (!hp) { /* unless we looped on the "goto" already */ | ||
10296 | hp = get_local_var_value("HOME"); | ||
10297 | if (hp && hp[0]) { | ||
10298 | debug_printf("sourcing ~/.profile\n"); | ||
10299 | hp = concat_path_file(hp, ".profile"); | ||
10300 | input = hfopen(hp); | ||
10301 | free((char*)hp); | ||
10302 | goto run_profile; | ||
10303 | } | ||
10304 | } | ||
10305 | } | ||
10306 | |||
10307 | /* -c takes effect *after* -l */ | ||
10308 | if (G.opt_c) { | ||
10309 | /* Possibilities: | ||
10310 | * sh ... -c 'script' | ||
10311 | * sh ... -c 'script' ARG0 [ARG1...] | ||
10312 | * On NOMMU, if builtin_argc != 0, | ||
10313 | * sh ... -c 'builtin' BARGV... "" ARG0 [ARG1...] | ||
10314 | * "" needs to be replaced with NULL | ||
10315 | * and BARGV vector fed to builtin function. | ||
10316 | * Note: the form without ARG0 never happens: | ||
10317 | * sh ... -c 'builtin' BARGV... "" | ||
10318 | */ | ||
10319 | char *script; | ||
10320 | |||
10321 | install_special_sighandlers(); | ||
10322 | |||
10323 | G.global_argc--; | ||
10324 | G.global_argv++; | ||
10325 | #if !BB_MMU | ||
10326 | if (builtin_argc) { | ||
10327 | /* -c 'builtin' [BARGV...] "" ARG0 [ARG1...] */ | ||
10328 | const struct built_in_command *x; | ||
10329 | x = find_builtin(G.global_argv[0]); | ||
10330 | if (x) { /* paranoia */ | ||
10331 | argv = G.global_argv; | ||
10332 | G.global_argc -= builtin_argc + 1; /* skip [BARGV...] "" */ | ||
10333 | G.global_argv += builtin_argc + 1; | ||
10334 | G.global_argv[-1] = NULL; /* replace "" */ | ||
10335 | G.last_exitcode = x->b_function(argv); | ||
10336 | } | ||
10337 | goto final_return; | ||
10338 | } | ||
10339 | #endif | ||
10340 | |||
10341 | script = G.global_argv[0]; | ||
10342 | if (!script) | ||
10343 | bb_error_msg_and_die(bb_msg_requires_arg, "-c"); | ||
10344 | if (!G.global_argv[1]) { | ||
10345 | /* -c 'script' (no params): prevent empty $0 */ | ||
10346 | G.global_argv[0] = argv[0]; | ||
10347 | } else { /* else -c 'script' ARG0 [ARG1...]: $0 is ARG0 */ | ||
10348 | G.global_argc--; | ||
10349 | G.global_argv++; | ||
10350 | } | ||
10351 | parse_and_run_string(script); | ||
10352 | goto final_return; | ||
10275 | } | 10353 | } |
10276 | 10354 | ||
10277 | /* -s is: hush -s ARGV1 ARGV2 (no SCRIPT) */ | 10355 | /* -s is: hush -s ARGV1 ARGV2 (no SCRIPT) */ |
@@ -10363,7 +10441,7 @@ int hush_main(int argc, char **argv) | |||
10363 | * (bash, too, does this only if ctty is available) */ | 10441 | * (bash, too, does this only if ctty is available) */ |
10364 | bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */ | 10442 | bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */ |
10365 | /* Grab control of the terminal */ | 10443 | /* Grab control of the terminal */ |
10366 | tcsetpgrp(G_interactive_fd, getpid()); | 10444 | tcsetpgrp(G_interactive_fd, cached_getpid); |
10367 | } | 10445 | } |
10368 | enable_restore_tty_pgrp_on_exit(); | 10446 | enable_restore_tty_pgrp_on_exit(); |
10369 | 10447 | ||
@@ -10456,7 +10534,7 @@ static int FAST_FUNC builtin_true(char **argv UNUSED_PARAM) | |||
10456 | } | 10534 | } |
10457 | 10535 | ||
10458 | #if ENABLE_HUSH_TEST || ENABLE_HUSH_ECHO || ENABLE_HUSH_PRINTF || ENABLE_HUSH_KILL | 10536 | #if ENABLE_HUSH_TEST || ENABLE_HUSH_ECHO || ENABLE_HUSH_PRINTF || ENABLE_HUSH_KILL |
10459 | static int run_applet_main(char **argv, int (*applet_main_func)(int argc, char **argv)) | 10537 | static NOINLINE int run_applet_main(char **argv, int (*applet_main_func)(int argc, char **argv)) |
10460 | { | 10538 | { |
10461 | int argc = string_array_len(argv); | 10539 | int argc = string_array_len(argv); |
10462 | return applet_main_func(argc, argv); | 10540 | return applet_main_func(argc, argv); |
@@ -11662,7 +11740,7 @@ static int wait_for_child_or_signal(struct pipe *waitfor_pipe, pid_t waitfor_pid | |||
11662 | sig = check_and_run_traps(); | 11740 | sig = check_and_run_traps(); |
11663 | if (sig /*&& sig != SIGCHLD - always true */) { | 11741 | if (sig /*&& sig != SIGCHLD - always true */) { |
11664 | /* Do this for any (non-ignored) signal, not only for ^C */ | 11742 | /* Do this for any (non-ignored) signal, not only for ^C */ |
11665 | ret = 128 + sig; | 11743 | ret = 128 | sig; |
11666 | break; | 11744 | break; |
11667 | } | 11745 | } |
11668 | /* SIGCHLD, or no signal, or ignored one, such as SIGQUIT. Repeat */ | 11746 | /* SIGCHLD, or no signal, or ignored one, such as SIGQUIT. Repeat */ |
@@ -11762,7 +11840,7 @@ static int FAST_FUNC builtin_wait(char **argv) | |||
11762 | process_wait_result(NULL, pid, status); | 11840 | process_wait_result(NULL, pid, status); |
11763 | ret = WEXITSTATUS(status); | 11841 | ret = WEXITSTATUS(status); |
11764 | if (WIFSIGNALED(status)) | 11842 | if (WIFSIGNALED(status)) |
11765 | ret = 128 + WTERMSIG(status); | 11843 | ret = 128 | WTERMSIG(status); |
11766 | } | 11844 | } |
11767 | } while (*++argv); | 11845 | } while (*++argv); |
11768 | 11846 | ||
diff --git a/shell/hush_test/hush-misc/piped_input.right b/shell/hush_test/hush-misc/piped_input.right new file mode 100644 index 000000000..7b8bf6758 --- /dev/null +++ b/shell/hush_test/hush-misc/piped_input.right | |||
@@ -0,0 +1,2 @@ | |||
1 | TEST | ||
2 | One:1 | ||
diff --git a/shell/hush_test/hush-misc/piped_input.tests b/shell/hush_test/hush-misc/piped_input.tests new file mode 100755 index 000000000..929fec0db --- /dev/null +++ b/shell/hush_test/hush-misc/piped_input.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | exec 2>&1 | ||
2 | echo 'echo TEST; false' | $THIS_SH | ||
3 | echo One:$? | ||
diff --git a/shell/hush_test/hush-vars/var_bash_repl_empty_var.right b/shell/hush_test/hush-vars/var_bash_repl_empty_var.right index 892916783..a8d1a3bef 100644 --- a/shell/hush_test/hush-vars/var_bash_repl_empty_var.right +++ b/shell/hush_test/hush-vars/var_bash_repl_empty_var.right | |||
@@ -1,2 +1,3 @@ | |||
1 | 1 | ||
2 | w | ||
2 | Ok:0 | 3 | Ok:0 |
diff --git a/shell/hush_test/hush-vars/var_bash_repl_empty_var.tests b/shell/hush_test/hush-vars/var_bash_repl_empty_var.tests index 73a43d38e..22aaba560 100755 --- a/shell/hush_test/hush-vars/var_bash_repl_empty_var.tests +++ b/shell/hush_test/hush-vars/var_bash_repl_empty_var.tests | |||
@@ -1,3 +1,5 @@ | |||
1 | unset v | ||
2 | echo ${v/*/w} | ||
1 | v='' | 3 | v='' |
2 | echo ${v/*/w} | 4 | echo ${v/*/w} |
3 | echo Ok:$? | 5 | echo Ok:$? |
diff --git a/shell/shell_common.c b/shell/shell_common.c index a6ee60851..1897fee3b 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c | |||
@@ -393,12 +393,18 @@ struct limits { | |||
393 | uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */ | 393 | uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */ |
394 | }; | 394 | }; |
395 | 395 | ||
396 | static const struct limits limits_tbl[] = { | 396 | /* Order of entries matches order in which bash prints "ulimit -a" */ |
397 | static const struct limits limits_tbl[] ALIGN2 = { | ||
397 | { RLIMIT_CORE, 9, }, // -c | 398 | { RLIMIT_CORE, 9, }, // -c |
398 | { RLIMIT_DATA, 10, }, // -d | 399 | { RLIMIT_DATA, 10, }, // -d |
400 | #ifdef RLIMIT_NICE | ||
399 | { RLIMIT_NICE, 0, }, // -e | 401 | { RLIMIT_NICE, 0, }, // -e |
400 | { RLIMIT_FSIZE, 9, }, // -f | ||
401 | #define LIMIT_F_IDX 3 | 402 | #define LIMIT_F_IDX 3 |
403 | #else | ||
404 | /* for example, Hurd */ | ||
405 | #define LIMIT_F_IDX 2 | ||
406 | #endif | ||
407 | { RLIMIT_FSIZE, 9, }, // -f | ||
402 | #ifdef RLIMIT_SIGPENDING | 408 | #ifdef RLIMIT_SIGPENDING |
403 | { RLIMIT_SIGPENDING, 0, }, // -i | 409 | { RLIMIT_SIGPENDING, 0, }, // -i |
404 | #endif | 410 | #endif |
@@ -433,13 +439,16 @@ static const struct limits limits_tbl[] = { | |||
433 | { RLIMIT_LOCKS, 0, }, // -x | 439 | { RLIMIT_LOCKS, 0, }, // -x |
434 | #endif | 440 | #endif |
435 | }; | 441 | }; |
436 | // bash also shows: | 442 | // 1) bash also shows: |
437 | //pipe size (512 bytes, -p) 8 | 443 | //pipe size (512 bytes, -p) 8 |
444 | // 2) RLIMIT_RTTIME ("timeout for RT tasks in us") is not in the table | ||
438 | 445 | ||
439 | static const char limits_help[] ALIGN1 = | 446 | static const char limits_help[] ALIGN1 = |
440 | "core file size (blocks)" // -c | 447 | "core file size (blocks)" // -c |
441 | "\0""data seg size (kb)" // -d | 448 | "\0""data seg size (kb)" // -d |
449 | #ifdef RLIMIT_NICE | ||
442 | "\0""scheduling priority" // -e | 450 | "\0""scheduling priority" // -e |
451 | #endif | ||
443 | "\0""file size (blocks)" // -f | 452 | "\0""file size (blocks)" // -f |
444 | #ifdef RLIMIT_SIGPENDING | 453 | #ifdef RLIMIT_SIGPENDING |
445 | "\0""pending signals" // -i | 454 | "\0""pending signals" // -i |
@@ -479,7 +488,9 @@ static const char limits_help[] ALIGN1 = | |||
479 | static const char limit_chars[] ALIGN1 = | 488 | static const char limit_chars[] ALIGN1 = |
480 | "c" | 489 | "c" |
481 | "d" | 490 | "d" |
491 | #ifdef RLIMIT_NICE | ||
482 | "e" | 492 | "e" |
493 | #endif | ||
483 | "f" | 494 | "f" |
484 | #ifdef RLIMIT_SIGPENDING | 495 | #ifdef RLIMIT_SIGPENDING |
485 | "i" | 496 | "i" |
@@ -520,7 +531,9 @@ static const char limit_chars[] ALIGN1 = | |||
520 | static const char ulimit_opt_string[] ALIGN1 = "-HSa" | 531 | static const char ulimit_opt_string[] ALIGN1 = "-HSa" |
521 | "c::" | 532 | "c::" |
522 | "d::" | 533 | "d::" |
534 | #ifdef RLIMIT_NICE | ||
523 | "e::" | 535 | "e::" |
536 | #endif | ||
524 | "f::" | 537 | "f::" |
525 | #ifdef RLIMIT_SIGPENDING | 538 | #ifdef RLIMIT_SIGPENDING |
526 | "i::" | 539 | "i::" |
@@ -737,7 +750,7 @@ shell_builtin_ulimit(char **argv) | |||
737 | 750 | ||
738 | if (opt_cnt == 0) { | 751 | if (opt_cnt == 0) { |
739 | /* "bare ulimit": treat it as if it was -f */ | 752 | /* "bare ulimit": treat it as if it was -f */ |
740 | getrlimit(limits_tbl[LIMIT_F_IDX].cmd, &limit); | 753 | getrlimit(RLIMIT_FSIZE, &limit); |
741 | printlim(opts, &limit, &limits_tbl[LIMIT_F_IDX]); | 754 | printlim(opts, &limit, &limits_tbl[LIMIT_F_IDX]); |
742 | } | 755 | } |
743 | 756 | ||
diff --git a/sysklogd/klogd.c b/sysklogd/klogd.c index c0ec1c0bf..82596bc0b 100644 --- a/sysklogd/klogd.c +++ b/sysklogd/klogd.c | |||
@@ -100,7 +100,7 @@ static void klogd_close(void) | |||
100 | #else | 100 | #else |
101 | 101 | ||
102 | # ifndef _PATH_KLOG | 102 | # ifndef _PATH_KLOG |
103 | # ifdef __GNU__ | 103 | # if defined(__GNU__) || defined (__FreeBSD__) |
104 | # define _PATH_KLOG "/dev/klog" | 104 | # define _PATH_KLOG "/dev/klog" |
105 | # else | 105 | # else |
106 | # error "your system's _PATH_KLOG is unknown" | 106 | # error "your system's _PATH_KLOG is unknown" |
diff --git a/sysklogd/logger.c b/sysklogd/logger.c index 4d692d6fc..9422b6ea7 100644 --- a/sysklogd/logger.c +++ b/sysklogd/logger.c | |||
@@ -21,7 +21,7 @@ | |||
21 | //kbuild:lib-$(CONFIG_LOGGER) += syslogd_and_logger.o | 21 | //kbuild:lib-$(CONFIG_LOGGER) += syslogd_and_logger.o |
22 | 22 | ||
23 | //usage:#define logger_trivial_usage | 23 | //usage:#define logger_trivial_usage |
24 | //usage: "[OPTIONS] [MESSAGE]" | 24 | //usage: "[-s] [-t TAG] [-p PRIO] [MESSAGE]" |
25 | //usage:#define logger_full_usage "\n\n" | 25 | //usage:#define logger_full_usage "\n\n" |
26 | //usage: "Write MESSAGE (or stdin) to syslog\n" | 26 | //usage: "Write MESSAGE (or stdin) to syslog\n" |
27 | //usage: "\n -s Log to stderr as well as the system log" | 27 | //usage: "\n -s Log to stderr as well as the system log" |
diff --git a/sysklogd/logread.c b/sysklogd/logread.c index 1e1f1347f..b52dc9cac 100644 --- a/sysklogd/logread.c +++ b/sysklogd/logread.c | |||
@@ -180,7 +180,7 @@ int logread_main(int argc UNUSED_PARAM, char **argv) | |||
180 | if (cur == shbuf_tail) { | 180 | if (cur == shbuf_tail) { |
181 | sem_up(log_semid); | 181 | sem_up(log_semid); |
182 | fflush_all(); | 182 | fflush_all(); |
183 | sleep(1); /* TODO: replace me with a sleep_on */ | 183 | sleep1(); /* TODO: replace me with a sleep_on */ |
184 | continue; | 184 | continue; |
185 | } | 185 | } |
186 | } | 186 | } |
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index f61da9de5..6ddfd771a 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c | |||
@@ -842,7 +842,7 @@ static void timestamp_and_log(int pri, char *msg, int len) | |||
842 | #if ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS | 842 | #if ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS |
843 | if (!timestamp) { | 843 | if (!timestamp) { |
844 | struct timeval tv; | 844 | struct timeval tv; |
845 | gettimeofday(&tv, NULL); | 845 | xgettimeofday(&tv); |
846 | now = tv.tv_sec; | 846 | now = tv.tv_sec; |
847 | timestamp = ctime(&now) + 4; /* skip day of week */ | 847 | timestamp = ctime(&now) + 4; /* skip day of week */ |
848 | /* overwrite year by milliseconds, zero terminate */ | 848 | /* overwrite year by milliseconds, zero terminate */ |
@@ -1034,6 +1034,7 @@ static void do_syslogd(void) | |||
1034 | kmsg_init(); | 1034 | kmsg_init(); |
1035 | 1035 | ||
1036 | timestamp_and_log_internal("syslogd started: BusyBox v" BB_VER); | 1036 | timestamp_and_log_internal("syslogd started: BusyBox v" BB_VER); |
1037 | write_pidfile_std_path_and_ext("syslogd"); | ||
1037 | 1038 | ||
1038 | while (!bb_got_signal) { | 1039 | while (!bb_got_signal) { |
1039 | ssize_t sz; | 1040 | ssize_t sz; |
@@ -1182,9 +1183,6 @@ int syslogd_main(int argc UNUSED_PARAM, char **argv) | |||
1182 | bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); | 1183 | bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); |
1183 | } | 1184 | } |
1184 | 1185 | ||
1185 | //umask(0); - why?? | ||
1186 | write_pidfile_std_path_and_ext("syslogd"); | ||
1187 | |||
1188 | do_syslogd(); | 1186 | do_syslogd(); |
1189 | /* return EXIT_SUCCESS; */ | 1187 | /* return EXIT_SUCCESS; */ |
1190 | } | 1188 | } |
diff --git a/testsuite/awk.tests b/testsuite/awk.tests index 87f6b5007..92c83d719 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests | |||
@@ -398,5 +398,19 @@ testing 'awk do not allow "str"++' \ | |||
398 | '' \ | 398 | '' \ |
399 | 'anything' | 399 | 'anything' |
400 | 400 | ||
401 | # gawk compat: FS regex matches only non-empty separators: | ||
402 | # with -*, the splitting is NOT f o o b a r, but foo bar: | ||
403 | testing 'awk FS regex which can match empty string' \ | ||
404 | "awk -F '-*' '{print \$1 \"-\" \$2 \"=\" \$3 \"*\" \$4}'" \ | ||
405 | "foo-bar=*\n" \ | ||
406 | '' \ | ||
407 | 'foo--bar' | ||
408 | |||
409 | # last+1 field should be empty (had a bug where it wasn't) | ||
410 | testing 'awk $NF is empty' \ | ||
411 | "awk -F '=+' '{print \$NF}'" \ | ||
412 | "\n" \ | ||
413 | '' \ | ||
414 | 'a=====123=' | ||
401 | 415 | ||
402 | exit $FAILCOUNT | 416 | exit $FAILCOUNT |
diff --git a/testsuite/dc_add_results.txt b/testsuite/dc_add_results.txt index 542a62ea3..2d955935f 100644 --- a/testsuite/dc_add_results.txt +++ b/testsuite/dc_add_results.txt | |||
@@ -9,9 +9,9 @@ | |||
9 | 1998 | 9 | 1998 |
10 | 324869359109479 | 10 | 324869359109479 |
11 | 2378639108055453348401 | 11 | 2378639108055453348401 |
12 | 78562139406792834691802347619083467219846713490861872324967138636055\ | 12 | 785621394067928346918023476190834672198467134908618723249671386360554\ |
13 | 45508706362018540498696043776980521464405852627147161556994835657433\ | 13 | 550870636201854049869604377698052146440585262714716155699483565743300\ |
14 | 00967298 | 14 | 967298 |
15 | 1.1 | 15 | 1.1 |
16 | 1.1 | 16 | 1.1 |
17 | 37842935130118.1187478621432354 | 17 | 37842935130118.1187478621432354 |
@@ -20,21 +20,21 @@ | |||
20 | -2 | 20 | -2 |
21 | -19 | 21 | -19 |
22 | -1287904651762470260258 | 22 | -1287904651762470260258 |
23 | 100000000000000000000000000000000000000000000000000000000000.0000000\ | 23 | 100000000000000000000000000000000000000000000000000000000000.00000000\ |
24 | 00000000000000000000000000000000000000000000000000000000000000000000\ | 24 | 000000000000000000000000000000000000000000000000000000000000000000000\ |
25 | 000000000000000000000000000000000000000000000 | 25 | 0000000000000000000000000000000000000000000 |
26 | 100000000000000000000000000000000000000000000000000000000000.0000000\ | 26 | 100000000000000000000000000000000000000000000000000000000000.00000000\ |
27 | 00000000000000000000000000000000000000000000000000000000000000000000\ | 27 | 000000000000000000000000000000000000000000000000000000000000000000000\ |
28 | 000000000000000000000000000000000000000000000 | 28 | 0000000000000000000000000000000000000000000 |
29 | 100000000000000000000000000000000000000000000000000000000000.0000000\ | 29 | 100000000000000000000000000000000000000000000000000000000000.00000000\ |
30 | 00000000000000000000000000000000000000000000000000000000000000000000\ | 30 | 000000000000000000000000000000000000000000000000000000000000000000000\ |
31 | 000000000000000000000000000000000000000009999 | 31 | 0000000000000000000000000000000000000009999 |
32 | 99999999999999999999999999999999999999999999999999999999999.99999999\ | 32 | 99999999999999999999999999999999999999999999999999999999999.999999999\ |
33 | 99999999999999999999999999999999999999999999999999000000000000000000\ | 33 | 999999999999999999999999999999999999999999999999900000000000000000000\ |
34 | 00000000000000000000000000000000000000009999 | 34 | 000000000000000000000000000000000000009999 |
35 | 99999999999999999999999999999999999990000000000000000000000.00000000\ | 35 | 99999999999999999999999999999999999990000000000000000000000.000000000\ |
36 | 00000000000000000000000000000000000000000000000000000000000000000000\ | 36 | 000000000000000000000000000000000000000000000000000000000000000000000\ |
37 | 00000000000000000000000000000000000000009999 | 37 | 000000000000000000000000000000000000009999 |
38 | 122761518 | 38 | 122761518 |
39 | -14338.391079082 | 39 | -14338.391079082 |
40 | -2422295.6865057444 | 40 | -2422295.6865057444 |
diff --git a/testsuite/dc_decimal_results.txt b/testsuite/dc_decimal_results.txt index 275d431c6..66bb91ac3 100644 --- a/testsuite/dc_decimal_results.txt +++ b/testsuite/dc_decimal_results.txt | |||
@@ -9,19 +9,17 @@ | |||
9 | 123 | 9 | 123 |
10 | 7505 | 10 | 7505 |
11 | 1023468723275435238491972521917846 | 11 | 1023468723275435238491972521917846 |
12 | 43434724324317058673920735170382703980273527090273892739207390379379\ | 12 | 434347243243170586739207351703827039802735270902738927392073903793796\ |
13 | 60379637893607893607893670530278200795207952702873892786172916728961\ | 13 | 037963789360789360789367053027820079520795270287389278617291672896178\ |
14 | 78390789360741897358785738607967926792673752073092537298378279365279\ | 14 | 3907893607418973587857386079679267926737520730925372983782793652793 |
15 | 3 | ||
16 | -1 | 15 | -1 |
17 | -203 | 16 | -203 |
18 | -57 | 17 | -57 |
19 | -18586 | 18 | -18586 |
20 | -31378682943772818461924738352952347258 | 19 | -31378682943772818461924738352952347258 |
21 | -8239456287456735894950672387239865203756982376208346745096273452730\ | 20 | -82394562874567358949506723872398652037569823762083467450962734527309\ |
22 | 96287563846592384526349872634895763257893467523987578690283762897568\ | 21 | 628756384659238452634987263489576325789346752398757869028376289756845\ |
23 | 45907234875807107108781350187590812735901871502384171023987230138727\ | 22 | 9072348758071071087813501875908127359018715023841710239872301387278 |
24 | 8 | ||
25 | .123521346523546 | 23 | .123521346523546 |
26 | .1245923756273856 | 24 | .1245923756273856 |
27 | -.1024678456387 | 25 | -.1024678456387 |
@@ -31,21 +29,21 @@ | |||
31 | 234237468293576.000000000000000000000000000000 | 29 | 234237468293576.000000000000000000000000000000 |
32 | 23987623568943567.00000000000000000005677834650000000000000 | 30 | 23987623568943567.00000000000000000005677834650000000000000 |
33 | 23856934568940675.000000000000000435676782300000000000000456784 | 31 | 23856934568940675.000000000000000435676782300000000000000456784 |
34 | 77567648698496.00000000000000000058767475000000000045856380000000000\ | 32 | 77567648698496.000000000000000000587674750000000000458563800000000000\ |
35 | 0000 | 33 | 000 |
36 | 2348672354968723.237482354600000000000325698739450234689243562387000\ | 34 | 2348672354968723.2374823546000000000003256987394502346892435623870000\ |
37 | 0000034578 | 35 | 000034578 |
38 | -2354768.000000000000000000000000000000000000 | 36 | -2354768.000000000000000000000000000000000000 |
39 | -96739874567.000000000347683456 | 37 | -96739874567.000000000347683456 |
40 | -3764568345.000000000004573845000000347683460 | 38 | -3764568345.000000000004573845000000347683460 |
41 | -356784356.934568495770004586495678300000000 | 39 | -356784356.934568495770004586495678300000000 |
42 | 74325437345273852773827101738273127312738521733017537073520735207307\ | 40 | 743254373452738527738271017382731273127385217330175370735207352073075\ |
43 | 570358738257390761276072160719802671980267018728630178.7082681027680\ | 41 | 70358738257390761276072160719802671980267018728630178.708268102768052\ |
44 | 52176021786784127612768127086782782176817317820783071097801773817867\ | 42 | 176021786784127612768127086782782176817317820783071097801773817867801\ |
45 | 8012767377058785378278207385237085237803278203782037237582795870 | 43 | 2767377058785378278207385237085237803278203782037237582795870 |
46 | -7567527327852738512737285378527382578372836789657385273852729836783\ | 44 | -75675273278527385127372853785273825783728367896573852738527298367837\ |
47 | 72867327835672967385278372637862738627836279863782673862783670.71738\ | 45 | 2867327835672967385278372637862738627836279863782673862783670.7173817\ |
48 | 17836173871836718637861073861783678160376017836701860376017810773527\ | 46 | 836173871836718637861073861783678160376017836701860376017810773527837\ |
49 | 8372832783728367826738627836278378260736270367362073867097307925 | 47 | 2832783728367826738627836278378260736270367362073867097307925 |
50 | 9812734012837410982345719208345712908357412903587192048571920458712.\ | 48 | 9812734012837410982345719208345712908357412903587192048571920458712.2\ |
51 | 23957182459817249058172945781 | 49 | 3957182459817249058172945781 |
diff --git a/testsuite/dc_divmod_results.txt b/testsuite/dc_divmod_results.txt index c55e9303d..ee91ee88c 100644 --- a/testsuite/dc_divmod_results.txt +++ b/testsuite/dc_divmod_results.txt | |||
@@ -58,8 +58,8 @@ | |||
58 | 100864416620775.31076855630746548983 | 58 | 100864416620775.31076855630746548983 |
59 | -53336.193401942302558132911110799109649707477 | 59 | -53336.193401942302558132911110799109649707477 |
60 | .00000000052530099381 | 60 | .00000000052530099381 |
61 | .0000000000000000000000000000000000000000000000000000000000000001907\ | 61 | .00000000000000000000000000000000000000000000000000000000000000019072\ |
62 | 266929376630027064745963897 | 62 | 66929376630027064745963897 |
63 | 42612515855353136519261264261472677699404182.78776061098893912189 | 63 | 42612515855353136519261264261472677699404182.78776061098893912189 |
64 | 0 | 64 | 0 |
65 | 0 | 65 | 0 |
@@ -121,6 +121,6 @@ | |||
121 | 100864416620775 | 121 | 100864416620775 |
122 | -3878923750692883.7238596702834756902 | 122 | -3878923750692883.7238596702834756902 |
123 | 0 | 123 | 0 |
124 | .0000000000000000000000000000000000000000000184866017689020776005643\ | 124 | .00000000000000000000000000000000000000000001848660176890207760056433\ |
125 | 3621086 | 125 | 621086 |
126 | 42612515855353136519261264261472677699404182 | 126 | 42612515855353136519261264261472677699404182 |
diff --git a/testsuite/dc_multiply_results.txt b/testsuite/dc_multiply_results.txt index 9666059a5..aaf3a20fc 100644 --- a/testsuite/dc_multiply_results.txt +++ b/testsuite/dc_multiply_results.txt | |||
@@ -15,8 +15,8 @@ | |||
15 | 3543531533584430580556128344529291738 | 15 | 3543531533584430580556128344529291738 |
16 | 568600835566479683035874339053.4411638427543228060 | 16 | 568600835566479683035874339053.4411638427543228060 |
17 | 7487566285885.8557453089005171423976251098 | 17 | 7487566285885.8557453089005171423976251098 |
18 | 373846412427291014394738378015501363938345620046.7869650248829232267\ | 18 | 373846412427291014394738378015501363938345620046.78696502488292322672\ |
19 | 2297002026819 | 19 | 297002026819 |
20 | -1 | 20 | -1 |
21 | -2 | 21 | -2 |
22 | -2751507058396910892 | 22 | -2751507058396910892 |
diff --git a/testsuite/dc_power_results.txt b/testsuite/dc_power_results.txt index 997f44f59..dc5d56766 100644 --- a/testsuite/dc_power_results.txt +++ b/testsuite/dc_power_results.txt | |||
@@ -10,15 +10,15 @@ | |||
10 | 18927361346 | 10 | 18927361346 |
11 | .23523785962738592635777 | 11 | .23523785962738592635777 |
12 | 328956734869213746.89782398457234 | 12 | 328956734869213746.89782398457234 |
13 | 16473742664221279051571200630760751138799221376964991600670000200609\ | 13 | 164737426642212790515712006307607511387992213769649916006700002006090\ |
14 | 08006052596520320731708604393844468006290371918262741885989163144389\ | 14 | 800605259652032073170860439384446800629037191826274188598916314438939\ |
15 | 39367835091560809036359941703341471396407660150658436796925310445979\ | 15 | 367835091560809036359941703341471396407660150658436796925310445979213\ |
16 | 21333166245765946557344383284626113908419359990042883048537750217279\ | 16 | 331662457659465573443832846261139084193599900428830485377502172791748\ |
17 | 17481980123593363177308481941550382845381799410533956718500484099889\ | 17 | 198012359336317730848194155038284538179941053395671850048409988961080\ |
18 | 610805653325917409549921909941664118421333562129 | 18 | 5653325917409549921909941664118421333562129 |
19 | 0 | 19 | 0 |
20 | 43287877285033571298394739716218787350087163435619825150259705419.98\ | 20 | 43287877285033571298394739716218787350087163435619825150259705419.980\ |
21 | 016445740928054425 | 21 | 16445740928054425 |
22 | 1.00000000000000000000 | 22 | 1.00000000000000000000 |
23 | .50000000000000000000 | 23 | .50000000000000000000 |
24 | .10000000000000000000 | 24 | .10000000000000000000 |
@@ -31,27 +31,27 @@ | |||
31 | 1 | 31 | 1 |
32 | -2 | 32 | -2 |
33 | 4 | 33 | 4 |
34 | 14997322375665265051328725757939209353051902095893907150382724666290\ | 34 | 149973223756652650513287257579392093530519020958939071503827246662904\ |
35 | 49749481660976421019742616298227588464420182758442163654172400528243\ | 35 | 974948166097642101974261629822758846442018275844216365417240052824300\ |
36 | 00885441207762486233574213374503090372518590691583139696652847404883\ | 36 | 885441207762486233574213374503090372518590691583139696652847404883085\ |
37 | 08573912261119588874308960204159666762789603037188471170006223907416\ | 37 | 739122611195888743089602041596667627896030371884711700062239074166049\ |
38 | 60492840269152716750700089148882139254399347568222390231015487895905\ | 38 | 284026915271675070008914888213925439934756822239023101548789590573727\ |
39 | 73727080561379177721440905866857248917982113340543176658480139248897\ | 39 | 080561379177721440905866857248917982113340543176658480139248897548025\ |
40 | 54802503253413282808814063861470711399810899724515727713334909764746\ | 40 | 032534132828088140638614707113998108997245157277133349097647462791029\ |
41 | 27910290211411231279325882505708287941671508154740003122373284699097\ | 41 | 021141123127932588250570828794167150815474000312237328469909778346501\ |
42 | 78346501539634198926772266511968381368929692275950529960923432771985\ | 42 | 539634198926772266511968381368929692275950529960923432771985125971893\ |
43 | 12597189390708050983487158873301681237787429436264801751664042999180\ | 43 | 907080509834871588733016812377874294362648017516640429991803448659818\ |
44 | 3448659818912436089 | 44 | 912436089 |
45 | 11478830555358864333472551120140548480416206583184496764727387456058\ | 45 | 114788305553588643334725511201405484804162065831844967647273874560587\ |
46 | 792742209537931243951391229607936 | 46 | 92742209537931243951391229607936 |
47 | -.00000000000000017759 | 47 | -.00000000000000017759 |
48 | -2067373624686414405470850679965010694114490999957199847684803894306\ | 48 | -20673736246864144054708506799650106941144909999571998476848038943065\ |
49 | 56243666149296582304582679590231948238805965642713928910384741502707\ | 49 | 6243666149296582304582679590231948238805965642713928910384741502707.2\ |
50 | .23224479257866798694 | 50 | 3224479257866798694 |
51 | 11606078892843496082360561256965139908586179418605021706789617179085\ | 51 | 116060788928434960823605612569651399085861794186050217067896171790858\ |
52 | 85768049299693425729565480314913006780973928345684673490252494674985\ | 52 | 576804929969342572956548031491300678097392834568467349025249467498501\ |
53 | 0186164225375953066263609289359900615361965737717208159874390.293769\ | 53 | 86164225375953066263609289359900615361965737717208159874390.293769702\ |
54 | 70206344604971 | 54 | 06344604971 |
55 | -1.00000000000000000000 | 55 | -1.00000000000000000000 |
56 | 1.00000000000000000000 | 56 | 1.00000000000000000000 |
57 | -.50000000000000000000 | 57 | -.50000000000000000000 |
@@ -59,14 +59,14 @@ | |||
59 | 0 | 59 | 0 |
60 | 0 | 60 | 0 |
61 | -.00000000000002874159 | 61 | -.00000000000002874159 |
62 | -1945134149489344891879057554905782841936258356736314337975569799825\ | 62 | -19451341494893448918790575549057828419362583567363143379755697998259\ |
63 | 94091939572752348215929683891336730843553721422164737465108229034947\ | 63 | 409193957275234821592968389133673084355372142216473746510822903494787\ |
64 | 87333189564755763444242676978610321731298729194092653999616928308494\ | 64 | 333189564755763444242676978610321731298729194092653999616928308494264\ |
65 | 26419468484566422775668903315088810746121307679948574976162519479931\ | 65 | 194684845664227756689033150888107461213076799485749761625194799311893\ |
66 | 18935243698160094347216562490000767121041786977792546155155934655909\ | 66 | 524369816009434721656249000076712104178697779254615515593465590914123\ |
67 | 14123833869470494708767968978717730012864171105540029928688274136791\ | 67 | 833869470494708767968978717730012864171105540029928688274136791981750\ |
68 | 98175053824022144065005509214813689232148489884560100200475909009813\ | 68 | 538240221440650055092148136892321484898845601002004759090098133400981\ |
69 | 340098100705258138.98542904577525702068 | 69 | 00705258138.98542904577525702068 |
70 | 0 | 70 | 0 |
71 | 0 | 71 | 0 |
72 | 0 | 72 | 0 |
diff --git a/testsuite/dc_subtract_results.txt b/testsuite/dc_subtract_results.txt index 9f7726254..0a9762381 100644 --- a/testsuite/dc_subtract_results.txt +++ b/testsuite/dc_subtract_results.txt | |||
@@ -8,15 +8,15 @@ | |||
8 | 2874519803456326214611 | 8 | 2874519803456326214611 |
9 | 9000000000000000000000000000000000000001 | 9 | 9000000000000000000000000000000000000001 |
10 | 1 | 10 | 1 |
11 | 9000000000000000000000000000000000000000.000000000000000000000000000\ | 11 | 9000000000000000000000000000000000000000.0000000000000000000000000000\ |
12 | 00000001 | 12 | 0000001 |
13 | .0000000000000000000000000000000001 | 13 | .0000000000000000000000000000000001 |
14 | 9999999999999999999999999999999999999999.999999999999999999999999999\ | 14 | 9999999999999999999999999999999999999999.9999999999999999999999999999\ |
15 | 9999999999999999999999999999999999999999999999999999999999 | ||
16 | 10000000000000000000000000000000000000000.999999999999999999999999999\ | ||
15 | 99999999999999999999999999999999999999999999999999999999999 | 17 | 99999999999999999999999999999999999999999999999999999999999 |
16 | 10000000000000000000000000000000000000000.99999999999999999999999999\ | 18 | 10000000000000000000000000000000000000000.000000000099999999999999999\ |
17 | 999999999999999999999999999999999999999999999999999999999999 | 19 | 9999999999999999999999999999999999999999999999999 |
18 | 10000000000000000000000000000000000000000.00000000009999999999999999\ | ||
19 | 99999999999999999999999999999999999999999999999999 | ||
20 | -8 | 20 | -8 |
21 | -182934721309467230894628759280719690 | 21 | -182934721309467230894628759280719690 |
22 | 1245723576605103923392087218483 | 22 | 1245723576605103923392087218483 |
diff --git a/testsuite/factor.tests b/testsuite/factor.tests index 2cf4a54ce..e404e29c1 100755 --- a/testsuite/factor.tests +++ b/testsuite/factor.tests | |||
@@ -45,4 +45,27 @@ testing "factor \$((2*3*5*7*11*13*17*19*23*29*31*37*41*43*47))" \ | |||
45 | "614889782588491410: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47\n" \ | 45 | "614889782588491410: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47\n" \ |
46 | "" "" | 46 | "" "" |
47 | 47 | ||
48 | # Test that square-detection code is not buggy | ||
49 | testing "factor 2 * 3037000493 * 3037000493" \ | ||
50 | "factor 18446743988964486098" \ | ||
51 | "18446743988964486098: 2 3037000493 3037000493\n" \ | ||
52 | "" "" | ||
53 | testing "factor 3 * 2479700513 * 2479700513" \ | ||
54 | "factor 18446743902517389507" \ | ||
55 | "18446743902517389507: 3 2479700513 2479700513\n" \ | ||
56 | "" "" | ||
57 | # including square-of-square cases: | ||
58 | testing "factor 3 * 37831 * 37831 * 37831 * 37831" \ | ||
59 | "factor 6144867742934288163" \ | ||
60 | "6144867742934288163: 3 37831 37831 37831 37831\n" \ | ||
61 | "" "" | ||
62 | testing "factor 3 * 13^16" \ | ||
63 | "factor 1996249827549539523" \ | ||
64 | "1996249827549539523: 3 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13\n" \ | ||
65 | "" "" | ||
66 | testing "factor 13^16" \ | ||
67 | "factor 665416609183179841" \ | ||
68 | "665416609183179841: 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13\n" \ | ||
69 | "" "" | ||
70 | |||
48 | exit $FAILCOUNT | 71 | exit $FAILCOUNT |
diff --git a/testsuite/mount.tests b/testsuite/mount.tests index 91c2e8b42..b6d5ebe08 100755 --- a/testsuite/mount.tests +++ b/testsuite/mount.tests | |||
@@ -34,6 +34,8 @@ umount -d "$testdir" 2>/dev/null | |||
34 | # file input will be file called "input" | 34 | # file input will be file called "input" |
35 | # test can create a file "actual" instead of writing to stdout | 35 | # test can create a file "actual" instead of writing to stdout |
36 | 36 | ||
37 | # This will always fail on !CONFIG_MANDATORY_FILE_LOCKING kernels | ||
38 | test "$SKIP_MOUNT_MAND_TESTS" = "1" || \ | ||
37 | testing "mount -o remount,mand" \ | 39 | testing "mount -o remount,mand" \ |
38 | "mount -o loop mount.image1m $testdir "\ | 40 | "mount -o loop mount.image1m $testdir "\ |
39 | "&& grep -Fc $testdir </proc/mounts "\ | 41 | "&& grep -Fc $testdir </proc/mounts "\ |
diff --git a/testsuite/xargs.tests b/testsuite/xargs.tests index e7c7c4b3d..c5e7b99e9 100755 --- a/testsuite/xargs.tests +++ b/testsuite/xargs.tests | |||
@@ -61,7 +61,7 @@ testing "xargs -n2" \ | |||
61 | 61 | ||
62 | SKIP= | 62 | SKIP= |
63 | 63 | ||
64 | optional FEATURE_XARGS_SUPPORT_QUOTES | 64 | optional FEATURE_XARGS_SUPPORT_QUOTES FEATURE_XARGS_SUPPORT_REPL_STR |
65 | testing "xargs -I skips empty lines and leading whitespace" \ | 65 | testing "xargs -I skips empty lines and leading whitespace" \ |
66 | "xargs -I% echo '[%]'" \ | 66 | "xargs -I% echo '[%]'" \ |
67 | "[2]\n[4]\n[6 6 ]\n[7]\n" \ | 67 | "[2]\n[4]\n[6 6 ]\n[7]\n" \ |
diff --git a/util-linux/acpid.c b/util-linux/acpid.c index d473e24fc..00613f8e3 100644 --- a/util-linux/acpid.c +++ b/util-linux/acpid.c | |||
@@ -99,7 +99,7 @@ struct acpi_event { | |||
99 | const char *desc; | 99 | const char *desc; |
100 | }; | 100 | }; |
101 | 101 | ||
102 | static const struct acpi_event f_evt_tab[] = { | 102 | static const struct acpi_event f_evt_tab[] ALIGN_PTR = { |
103 | { "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRF 00000080" }, | 103 | { "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRF 00000080" }, |
104 | { "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRB 00000080" }, | 104 | { "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRB 00000080" }, |
105 | { "EV_SW", 0x05, "SW_LID", 0x00, 1, "button/lid LID0 00000080" }, | 105 | { "EV_SW", 0x05, "SW_LID", 0x00, 1, "button/lid LID0 00000080" }, |
@@ -110,7 +110,7 @@ struct acpi_action { | |||
110 | const char *action; | 110 | const char *action; |
111 | }; | 111 | }; |
112 | 112 | ||
113 | static const struct acpi_action f_act_tab[] = { | 113 | static const struct acpi_action f_act_tab[] ALIGN_PTR = { |
114 | { "PWRF", "PWRF/00000080" }, | 114 | { "PWRF", "PWRF/00000080" }, |
115 | { "LID0", "LID/00000080" }, | 115 | { "LID0", "LID/00000080" }, |
116 | }; | 116 | }; |
diff --git a/util-linux/blockdev.c b/util-linux/blockdev.c index e60bbe609..20a031377 100644 --- a/util-linux/blockdev.c +++ b/util-linux/blockdev.c | |||
@@ -60,7 +60,7 @@ static const char bdcmd_names[] ALIGN1 = | |||
60 | "flushbufs" "\0" | 60 | "flushbufs" "\0" |
61 | "rereadpt" "\0" | 61 | "rereadpt" "\0" |
62 | ; | 62 | ; |
63 | static const uint32_t bdcmd_ioctl[] = { | 63 | static const uint32_t bdcmd_ioctl[] ALIGN4 = { |
64 | BLKROSET, //setro | 64 | BLKROSET, //setro |
65 | BLKROSET, //setrw | 65 | BLKROSET, //setrw |
66 | BLKROGET, //getro | 66 | BLKROGET, //getro |
diff --git a/util-linux/chrt.c b/util-linux/chrt.c index 4dd78dabf..a8701b55f 100644 --- a/util-linux/chrt.c +++ b/util-linux/chrt.c | |||
@@ -17,7 +17,7 @@ | |||
17 | //kbuild:lib-$(CONFIG_CHRT) += chrt.o | 17 | //kbuild:lib-$(CONFIG_CHRT) += chrt.o |
18 | 18 | ||
19 | //usage:#define chrt_trivial_usage | 19 | //usage:#define chrt_trivial_usage |
20 | //usage: "-m | -p [PRIO] PID | [-rfobi] PRIO PROG [ARGS]" | 20 | //usage: "-m | -p [PRIO] PID | [-rfobi] PRIO PROG ARGS" |
21 | //usage:#define chrt_full_usage "\n\n" | 21 | //usage:#define chrt_full_usage "\n\n" |
22 | //usage: "Change scheduling priority and class for a process\n" | 22 | //usage: "Change scheduling priority and class for a process\n" |
23 | //usage: "\n -m Show min/max priorities" | 23 | //usage: "\n -m Show min/max priorities" |
@@ -39,6 +39,17 @@ | |||
39 | # define SCHED_IDLE 5 | 39 | # define SCHED_IDLE 5 |
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | //musl has no __MUSL__ or similar define to check for, | ||
43 | //but its <sys/types.h> has these lines: | ||
44 | // #define __NEED_fsblkcnt_t | ||
45 | // #define __NEED_fsfilcnt_t | ||
46 | #if defined(__linux__) && defined(__NEED_fsblkcnt_t) && defined(__NEED_fsfilcnt_t) | ||
47 | # define LIBC_IS_MUSL 1 | ||
48 | # include <sys/syscall.h> | ||
49 | #else | ||
50 | # define LIBC_IS_MUSL 0 | ||
51 | #endif | ||
52 | |||
42 | static const char *policy_name(int pol) | 53 | static const char *policy_name(int pol) |
43 | { | 54 | { |
44 | if (pol > 6) | 55 | if (pol > 6) |
@@ -85,6 +96,7 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) | |||
85 | char *priority = priority; /* for compiler */ | 96 | char *priority = priority; /* for compiler */ |
86 | const char *current_new; | 97 | const char *current_new; |
87 | int policy = SCHED_RR; | 98 | int policy = SCHED_RR; |
99 | int ret; | ||
88 | 100 | ||
89 | opt = getopt32(argv, "^" | 101 | opt = getopt32(argv, "^" |
90 | "+" "mprfobi" | 102 | "+" "mprfobi" |
@@ -132,7 +144,15 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) | |||
132 | if (opt & OPT_p) { | 144 | if (opt & OPT_p) { |
133 | int pol; | 145 | int pol; |
134 | print_rt_info: | 146 | print_rt_info: |
147 | #if LIBC_IS_MUSL | ||
148 | /* musl libc returns ENOSYS for its sched_getscheduler library | ||
149 | * function, because the sched_getscheduler Linux kernel system call | ||
150 | * does not conform to Posix; so we use the system call directly | ||
151 | */ | ||
152 | pol = syscall(SYS_sched_getscheduler, pid); | ||
153 | #else | ||
135 | pol = sched_getscheduler(pid); | 154 | pol = sched_getscheduler(pid); |
155 | #endif | ||
136 | if (pol < 0) | 156 | if (pol < 0) |
137 | bb_perror_msg_and_die("can't %cet pid %u's policy", 'g', (int)pid); | 157 | bb_perror_msg_and_die("can't %cet pid %u's policy", 'g', (int)pid); |
138 | #ifdef SCHED_RESET_ON_FORK | 158 | #ifdef SCHED_RESET_ON_FORK |
@@ -149,7 +169,12 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) | |||
149 | printf("pid %u's %s scheduling policy: SCHED_%s\n", | 169 | printf("pid %u's %s scheduling policy: SCHED_%s\n", |
150 | pid, current_new, policy_name(pol) | 170 | pid, current_new, policy_name(pol) |
151 | ); | 171 | ); |
152 | if (sched_getparam(pid, &sp)) | 172 | #if LIBC_IS_MUSL |
173 | ret = syscall(SYS_sched_getparam, pid, &sp); | ||
174 | #else | ||
175 | ret = sched_getparam(pid, &sp); | ||
176 | #endif | ||
177 | if (ret) | ||
153 | bb_perror_msg_and_die("can't get pid %u's attributes", (int)pid); | 178 | bb_perror_msg_and_die("can't get pid %u's attributes", (int)pid); |
154 | printf("pid %u's %s scheduling priority: %d\n", | 179 | printf("pid %u's %s scheduling priority: %d\n", |
155 | (int)pid, current_new, sp.sched_priority | 180 | (int)pid, current_new, sp.sched_priority |
@@ -168,7 +193,12 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) | |||
168 | sched_get_priority_min(policy), sched_get_priority_max(policy) | 193 | sched_get_priority_min(policy), sched_get_priority_max(policy) |
169 | ); | 194 | ); |
170 | 195 | ||
171 | if (sched_setscheduler(pid, policy, &sp) < 0) | 196 | #if LIBC_IS_MUSL |
197 | ret = syscall(SYS_sched_setscheduler, pid, policy, &sp); | ||
198 | #else | ||
199 | ret = sched_setscheduler(pid, policy, &sp); | ||
200 | #endif | ||
201 | if (ret) | ||
172 | bb_perror_msg_and_die("can't %cet pid %u's policy", 's', (int)pid); | 202 | bb_perror_msg_and_die("can't %cet pid %u's policy", 's', (int)pid); |
173 | 203 | ||
174 | if (!argv[0]) /* "-p PRIO PID [...]" */ | 204 | if (!argv[0]) /* "-p PRIO PID [...]" */ |
diff --git a/util-linux/fbset.c b/util-linux/fbset.c index 0b9a9a6bc..cc5413b40 100644 --- a/util-linux/fbset.c +++ b/util-linux/fbset.c | |||
@@ -193,7 +193,7 @@ static const struct cmdoptions_t { | |||
193 | const char name[9]; | 193 | const char name[9]; |
194 | const unsigned char param_count; | 194 | const unsigned char param_count; |
195 | const unsigned char code; | 195 | const unsigned char code; |
196 | } g_cmdoptions[] = { | 196 | } g_cmdoptions[] ALIGN1 = { |
197 | /*"12345678" + NUL */ | 197 | /*"12345678" + NUL */ |
198 | //TODO: convert to index_in_strings() | 198 | //TODO: convert to index_in_strings() |
199 | { "fb" , 1, CMD_FB }, | 199 | { "fb" , 1, CMD_FB }, |
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c index 0fb2e3e17..c50ceead1 100644 --- a/util-linux/fdisk.c +++ b/util-linux/fdisk.c | |||
@@ -185,8 +185,11 @@ struct hd_geometry { | |||
185 | 185 | ||
186 | #define HDIO_GETGEO 0x0301 /* get device geometry */ | 186 | #define HDIO_GETGEO 0x0301 /* get device geometry */ |
187 | 187 | ||
188 | /* TODO: #if ENABLE_FEATURE_FDISK_WRITABLE */ | 188 | /* TODO: just #if ENABLE_FEATURE_FDISK_WRITABLE */ |
189 | /* (currently fdisk_sun/sgi.c do not have proper WRITABLE #ifs) */ | 189 | /* (currently fdisk_sun/sgi.c do not have proper WRITABLE #ifs) */ |
190 | #if ENABLE_FEATURE_FDISK_WRITABLE \ | ||
191 | || ENABLE_FEATURE_SGI_LABEL \ | ||
192 | || ENABLE_FEATURE_SUN_LABEL | ||
190 | static const char msg_building_new_label[] ALIGN1 = | 193 | static const char msg_building_new_label[] ALIGN1 = |
191 | "Building a new %s. Changes will remain in memory only,\n" | 194 | "Building a new %s. Changes will remain in memory only,\n" |
192 | "until you decide to write them. After that the previous content\n" | 195 | "until you decide to write them. After that the previous content\n" |
@@ -194,7 +197,7 @@ static const char msg_building_new_label[] ALIGN1 = | |||
194 | 197 | ||
195 | static const char msg_part_already_defined[] ALIGN1 = | 198 | static const char msg_part_already_defined[] ALIGN1 = |
196 | "Partition %u is already defined, delete it before re-adding\n"; | 199 | "Partition %u is already defined, delete it before re-adding\n"; |
197 | /* #endif */ | 200 | #endif |
198 | 201 | ||
199 | 202 | ||
200 | struct partition { | 203 | struct partition { |
@@ -303,7 +306,7 @@ static sector_t get_nr_sects(const struct partition *p); | |||
303 | 306 | ||
304 | /* DOS partition types */ | 307 | /* DOS partition types */ |
305 | 308 | ||
306 | static const char *const i386_sys_types[] = { | 309 | static const char *const i386_sys_types[] ALIGN_PTR = { |
307 | "\x00" "Empty", | 310 | "\x00" "Empty", |
308 | "\x01" "FAT12", | 311 | "\x01" "FAT12", |
309 | "\x04" "FAT16 <32M", | 312 | "\x04" "FAT16 <32M", |
@@ -2667,7 +2670,7 @@ reread_partition_table(int leave) | |||
2667 | /* Users with slow external USB disks on a 320MHz ARM system (year 2011) | 2670 | /* Users with slow external USB disks on a 320MHz ARM system (year 2011) |
2668 | * report that sleep is needed, otherwise BLKRRPART may fail with -EIO: | 2671 | * report that sleep is needed, otherwise BLKRRPART may fail with -EIO: |
2669 | */ | 2672 | */ |
2670 | sleep(1); | 2673 | sleep1(); |
2671 | i = ioctl_or_perror(dev_fd, BLKRRPART, NULL, | 2674 | i = ioctl_or_perror(dev_fd, BLKRRPART, NULL, |
2672 | "WARNING: rereading partition table " | 2675 | "WARNING: rereading partition table " |
2673 | "failed, kernel still uses old table"); | 2676 | "failed, kernel still uses old table"); |
diff --git a/util-linux/fdisk_osf.c b/util-linux/fdisk_osf.c index 92180b2bc..765740ff1 100644 --- a/util-linux/fdisk_osf.c +++ b/util-linux/fdisk_osf.c | |||
@@ -144,7 +144,7 @@ struct xbsd_disklabel { | |||
144 | #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */ | 144 | #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */ |
145 | #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */ | 145 | #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */ |
146 | 146 | ||
147 | static const char *const xbsd_dktypenames[] = { | 147 | static const char *const xbsd_dktypenames[] ALIGN_PTR = { |
148 | "unknown", | 148 | "unknown", |
149 | "SMD", | 149 | "SMD", |
150 | "MSCP", | 150 | "MSCP", |
@@ -190,7 +190,7 @@ static const char *const xbsd_dktypenames[] = { | |||
190 | #define BSD_FS_MSDOS 8 /* MS-DOS file system */ | 190 | #define BSD_FS_MSDOS 8 /* MS-DOS file system */ |
191 | #endif | 191 | #endif |
192 | 192 | ||
193 | static const char *const xbsd_fstypes[] = { | 193 | static const char *const xbsd_fstypes[] ALIGN_PTR = { |
194 | "\x00" "unused", /* BSD_FS_UNUSED */ | 194 | "\x00" "unused", /* BSD_FS_UNUSED */ |
195 | "\x01" "swap", /* BSD_FS_SWAP */ | 195 | "\x01" "swap", /* BSD_FS_SWAP */ |
196 | "\x02" "Version 6", /* BSD_FS_V6 */ | 196 | "\x02" "Version 6", /* BSD_FS_V6 */ |
diff --git a/util-linux/fdisk_sgi.c b/util-linux/fdisk_sgi.c index c90c801e2..acb438ac0 100644 --- a/util-linux/fdisk_sgi.c +++ b/util-linux/fdisk_sgi.c | |||
@@ -174,7 +174,7 @@ isinfreelist(unsigned int b) | |||
174 | * end of free blocks section | 174 | * end of free blocks section |
175 | */ | 175 | */ |
176 | 176 | ||
177 | static const char *const sgi_sys_types[] = { | 177 | static const char *const sgi_sys_types[] ALIGN_PTR = { |
178 | /* SGI_VOLHDR */ "\x00" "SGI volhdr" , | 178 | /* SGI_VOLHDR */ "\x00" "SGI volhdr" , |
179 | /* 0x01 */ "\x01" "SGI trkrepl" , | 179 | /* 0x01 */ "\x01" "SGI trkrepl" , |
180 | /* 0x02 */ "\x02" "SGI secrepl" , | 180 | /* 0x02 */ "\x02" "SGI secrepl" , |
diff --git a/util-linux/fdisk_sun.c b/util-linux/fdisk_sun.c index 29d7c283a..427b9487b 100644 --- a/util-linux/fdisk_sun.c +++ b/util-linux/fdisk_sun.c | |||
@@ -61,7 +61,7 @@ guess_device_type(void) | |||
61 | } | 61 | } |
62 | } | 62 | } |
63 | 63 | ||
64 | static const char *const sun_sys_types[] = { | 64 | static const char *const sun_sys_types[] ALIGN_PTR = { |
65 | "\x00" "Empty" , /* 0 */ | 65 | "\x00" "Empty" , /* 0 */ |
66 | "\x01" "Boot" , /* 1 */ | 66 | "\x01" "Boot" , /* 1 */ |
67 | "\x02" "SunOS root" , /* 2 */ | 67 | "\x02" "SunOS root" , /* 2 */ |
@@ -133,7 +133,7 @@ static const struct sun_predefined_drives { | |||
133 | unsigned short ntrks; | 133 | unsigned short ntrks; |
134 | unsigned short nsect; | 134 | unsigned short nsect; |
135 | unsigned short rspeed; | 135 | unsigned short rspeed; |
136 | } sun_drives[] = { | 136 | } sun_drives[] ALIGN_PTR = { |
137 | { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662}, | 137 | { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662}, |
138 | { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662}, | 138 | { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662}, |
139 | { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600}, | 139 | { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600}, |
diff --git a/util-linux/fstrim.c b/util-linux/fstrim.c index 8d29a6d54..6d673002f 100644 --- a/util-linux/fstrim.c +++ b/util-linux/fstrim.c | |||
@@ -20,18 +20,10 @@ | |||
20 | //usage:#define fstrim_trivial_usage | 20 | //usage:#define fstrim_trivial_usage |
21 | //usage: "[OPTIONS] MOUNTPOINT" | 21 | //usage: "[OPTIONS] MOUNTPOINT" |
22 | //usage:#define fstrim_full_usage "\n\n" | 22 | //usage:#define fstrim_full_usage "\n\n" |
23 | //usage: IF_LONG_OPTS( | ||
24 | //usage: " -o,--offset OFFSET Offset in bytes to discard from" | ||
25 | //usage: "\n -l,--length LEN Bytes to discard" | ||
26 | //usage: "\n -m,--minimum MIN Minimum extent length" | ||
27 | //usage: "\n -v,--verbose Print number of discarded bytes" | ||
28 | //usage: ) | ||
29 | //usage: IF_NOT_LONG_OPTS( | ||
30 | //usage: " -o OFFSET Offset in bytes to discard from" | 23 | //usage: " -o OFFSET Offset in bytes to discard from" |
31 | //usage: "\n -l LEN Bytes to discard" | 24 | //usage: "\n -l LEN Bytes to discard" |
32 | //usage: "\n -m MIN Minimum extent length" | 25 | //usage: "\n -m MIN Minimum extent length" |
33 | //usage: "\n -v Print number of discarded bytes" | 26 | //usage: "\n -v Print number of discarded bytes" |
34 | //usage: ) | ||
35 | 27 | ||
36 | #include "libbb.h" | 28 | #include "libbb.h" |
37 | #include <linux/fs.h> | 29 | #include <linux/fs.h> |
diff --git a/util-linux/hexdump.c b/util-linux/hexdump.c index 2174c3008..57e7e8db7 100644 --- a/util-linux/hexdump.c +++ b/util-linux/hexdump.c | |||
@@ -28,7 +28,7 @@ | |||
28 | //kbuild:lib-$(CONFIG_HD) += hexdump.o | 28 | //kbuild:lib-$(CONFIG_HD) += hexdump.o |
29 | 29 | ||
30 | //usage:#define hexdump_trivial_usage | 30 | //usage:#define hexdump_trivial_usage |
31 | //usage: "[-bcCdefnosvx] [FILE]..." | 31 | //usage: "[-bcdoxCv] [-e FMT] [-f FMT_FILE] [-n LEN] [-s OFS] [FILE]..." |
32 | //usage:#define hexdump_full_usage "\n\n" | 32 | //usage:#define hexdump_full_usage "\n\n" |
33 | //usage: "Display FILEs (or stdin) in a user specified format\n" | 33 | //usage: "Display FILEs (or stdin) in a user specified format\n" |
34 | //usage: "\n -b 1-byte octal display" | 34 | //usage: "\n -b 1-byte octal display" |
diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c index d2f4b6ed8..29bbc6633 100644 --- a/util-linux/hexdump_xxd.c +++ b/util-linux/hexdump_xxd.c | |||
@@ -41,7 +41,7 @@ | |||
41 | // -u use upper case hex letters. | 41 | // -u use upper case hex letters. |
42 | 42 | ||
43 | //usage:#define xxd_trivial_usage | 43 | //usage:#define xxd_trivial_usage |
44 | //usage: "[OPTIONS] [FILE]" | 44 | //usage: "[-pr] [-g N] [-c N] [-n LEN] [-s OFS] [FILE]" |
45 | //usage:#define xxd_full_usage "\n\n" | 45 | //usage:#define xxd_full_usage "\n\n" |
46 | //usage: "Hex dump FILE (or stdin)\n" | 46 | //usage: "Hex dump FILE (or stdin)\n" |
47 | //usage: "\n -g N Bytes per group" | 47 | //usage: "\n -g N Bytes per group" |
@@ -51,7 +51,6 @@ | |||
51 | //usage: "\n -l LENGTH Show only first LENGTH bytes" | 51 | //usage: "\n -l LENGTH Show only first LENGTH bytes" |
52 | //usage: "\n -s OFFSET Skip OFFSET bytes" | 52 | //usage: "\n -s OFFSET Skip OFFSET bytes" |
53 | //usage: "\n -r Reverse (with -p, assumes no offsets in input)" | 53 | //usage: "\n -r Reverse (with -p, assumes no offsets in input)" |
54 | // TODO: implement -r (see hexdump -R) | ||
55 | 54 | ||
56 | #include "libbb.h" | 55 | #include "libbb.h" |
57 | #include "dump.h" | 56 | #include "dump.h" |
diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c index e85bca2b2..723b09589 100644 --- a/util-linux/hwclock.c +++ b/util-linux/hwclock.c | |||
@@ -36,6 +36,19 @@ | |||
36 | #include <sys/utsname.h> | 36 | #include <sys/utsname.h> |
37 | #include "rtc_.h" | 37 | #include "rtc_.h" |
38 | 38 | ||
39 | |||
40 | //musl has no __MUSL__ or similar define to check for, | ||
41 | //but its <sys/types.h> has these lines: | ||
42 | // #define __NEED_fsblkcnt_t | ||
43 | // #define __NEED_fsfilcnt_t | ||
44 | #if defined(__linux__) && defined(__NEED_fsblkcnt_t) && defined(__NEED_fsfilcnt_t) | ||
45 | # define LIBC_IS_MUSL 1 | ||
46 | # include <sys/syscall.h> | ||
47 | #else | ||
48 | # define LIBC_IS_MUSL 0 | ||
49 | #endif | ||
50 | |||
51 | |||
39 | /* diff code is disabled: it's not sys/hw clock diff, it's some useless | 52 | /* diff code is disabled: it's not sys/hw clock diff, it's some useless |
40 | * "time between hwclock was started and we saw CMOS tick" quantity. | 53 | * "time between hwclock was started and we saw CMOS tick" quantity. |
41 | * It's useless since hwclock is started at a random moment, | 54 | * It's useless since hwclock is started at a random moment, |
@@ -66,7 +79,7 @@ static time_t read_rtc(const char **pp_rtcname, struct timeval *sys_tv, int utc) | |||
66 | int before = tm_time.tm_sec; | 79 | int before = tm_time.tm_sec; |
67 | while (1) { | 80 | while (1) { |
68 | rtc_read_tm(&tm_time, fd); | 81 | rtc_read_tm(&tm_time, fd); |
69 | gettimeofday(sys_tv, NULL); | 82 | xgettimeofday(sys_tv); |
70 | if (before != (int)tm_time.tm_sec) | 83 | if (before != (int)tm_time.tm_sec) |
71 | break; | 84 | break; |
72 | } | 85 | } |
@@ -116,26 +129,72 @@ static void show_clock(const char **pp_rtcname, int utc) | |||
116 | #endif | 129 | #endif |
117 | } | 130 | } |
118 | 131 | ||
119 | static void to_sys_clock(const char **pp_rtcname, int utc) | 132 | static void set_kernel_tz(const struct timezone *tz) |
120 | { | 133 | { |
121 | struct timeval tv; | 134 | #if LIBC_IS_MUSL |
122 | struct timezone tz; | 135 | /* musl libc does not pass tz argument to syscall |
123 | 136 | * because "it's deprecated by POSIX, therefore it's fine | |
124 | tz.tz_minuteswest = timezone / 60; | 137 | * if we gratuitously break stuff" :( |
125 | /* ^^^ used to also subtract 60*daylight, but it's wrong: | ||
126 | * daylight!=0 means "this timezone has some DST | ||
127 | * during the year", not "DST is in effect now". | ||
128 | */ | 138 | */ |
129 | tz.tz_dsttime = 0; | 139 | #if !defined(SYS_settimeofday) && defined(SYS_settimeofday_time32) |
130 | 140 | # define SYS_settimeofday SYS_settimeofday_time32 | |
131 | /* glibc v2.31+ returns an error if both args are non-NULL */ | 141 | #endif |
132 | if (settimeofday(NULL, &tz)) | 142 | int ret = syscall(SYS_settimeofday, NULL, tz); |
143 | #else | ||
144 | int ret = settimeofday(NULL, tz); | ||
145 | #endif | ||
146 | if (ret) | ||
133 | bb_simple_perror_msg_and_die("settimeofday"); | 147 | bb_simple_perror_msg_and_die("settimeofday"); |
148 | } | ||
149 | |||
150 | /* | ||
151 | * At system boot, kernel may set system time from RTC, | ||
152 | * but it knows nothing about timezones. If RTC is in local time, | ||
153 | * then system time is wrong - it is offset by timezone. | ||
154 | * --systz option corrects system time if RTC is in local time, | ||
155 | * and (always) sets in-kernel timezone. | ||
156 | * (Unlike --hctosys, it does not read the RTC). | ||
157 | * | ||
158 | * util-linux's code has this comment: | ||
159 | * RTC | settimeofday calls | ||
160 | * ------|------------------------------------------------- | ||
161 | * Local | 1st) warps system time*, sets PCIL* and kernel tz | ||
162 | * UTC | 1st) locks warp_clock 2nd) sets kernel tz | ||
163 | * * only on first call after boot | ||
164 | * (PCIL is "persistent_clock_is_local" kernel internal flag, | ||
165 | * it makes kernel save RTC in local time, not UTC.) | ||
166 | */ | ||
167 | static void set_kernel_timezone_and_clock(int utc, const struct timeval *hctosys) | ||
168 | { | ||
169 | time_t cur; | ||
170 | struct tm *broken; | ||
171 | struct timezone tz = { 0 }; | ||
172 | |||
173 | /* if --utc, prevent kernel's warp_clock() with a dummy call */ | ||
174 | if (utc) | ||
175 | set_kernel_tz(&tz); | ||
176 | |||
177 | /* Set kernel's timezone offset based on userspace one */ | ||
178 | //It's tempting to call tzset() and use libc global "timezone" variable | ||
179 | //...but it does NOT include DST shift (IOW: it's WRONG, usually by one hour, | ||
180 | //if DST is in effect!) Thus this ridiculous dance: | ||
181 | cur = time(NULL); | ||
182 | broken = localtime(&cur); | ||
183 | tz.tz_minuteswest = -broken->tm_gmtoff / 60; | ||
184 | /*tz.tz_dsttime = 0; already is */ | ||
185 | set_kernel_tz(&tz); /* MIGHT warp_clock() if 1st call since boot */ | ||
186 | |||
187 | if (hctosys) /* it's --hctosys: set time too */ | ||
188 | xsettimeofday(hctosys); | ||
189 | } | ||
190 | |||
191 | static void to_sys_clock(const char **pp_rtcname, int utc) | ||
192 | { | ||
193 | struct timeval tv; | ||
134 | 194 | ||
135 | tv.tv_sec = read_rtc(pp_rtcname, NULL, utc); | 195 | tv.tv_sec = read_rtc(pp_rtcname, NULL, utc); |
136 | tv.tv_usec = 0; | 196 | tv.tv_usec = 0; |
137 | if (settimeofday(&tv, NULL)) | 197 | return set_kernel_timezone_and_clock(utc, &tv); |
138 | bb_simple_perror_msg_and_die("settimeofday"); | ||
139 | } | 198 | } |
140 | 199 | ||
141 | static void from_sys_clock(const char **pp_rtcname, int utc) | 200 | static void from_sys_clock(const char **pp_rtcname, int utc) |
@@ -146,7 +205,7 @@ static void from_sys_clock(const char **pp_rtcname, int utc) | |||
146 | int rtc; | 205 | int rtc; |
147 | 206 | ||
148 | rtc = rtc_xopen(pp_rtcname, O_WRONLY); | 207 | rtc = rtc_xopen(pp_rtcname, O_WRONLY); |
149 | gettimeofday(&tv, NULL); | 208 | xgettimeofday(&tv); |
150 | /* Prepare tm_time */ | 209 | /* Prepare tm_time */ |
151 | if (sizeof(time_t) == sizeof(tv.tv_sec)) { | 210 | if (sizeof(time_t) == sizeof(tv.tv_sec)) { |
152 | if (utc) | 211 | if (utc) |
@@ -194,7 +253,7 @@ static void from_sys_clock(const char **pp_rtcname, int utc) | |||
194 | unsigned rem_usec; | 253 | unsigned rem_usec; |
195 | time_t t; | 254 | time_t t; |
196 | 255 | ||
197 | gettimeofday(&tv, NULL); | 256 | xgettimeofday(&tv); |
198 | 257 | ||
199 | t = tv.tv_sec; | 258 | t = tv.tv_sec; |
200 | rem_usec = 1000000 - tv.tv_usec; | 259 | rem_usec = 1000000 - tv.tv_usec; |
@@ -215,7 +274,7 @@ static void from_sys_clock(const char **pp_rtcname, int utc) | |||
215 | } | 274 | } |
216 | 275 | ||
217 | /* gmtime/localtime took some time, re-get cur time */ | 276 | /* gmtime/localtime took some time, re-get cur time */ |
218 | gettimeofday(&tv, NULL); | 277 | xgettimeofday(&tv); |
219 | 278 | ||
220 | if (tv.tv_sec < t /* we are still in old second */ | 279 | if (tv.tv_sec < t /* we are still in old second */ |
221 | || (tv.tv_sec == t && tv.tv_usec < adj) /* not too far into next second */ | 280 | || (tv.tv_sec == t && tv.tv_usec < adj) /* not too far into next second */ |
@@ -261,64 +320,53 @@ static void from_sys_clock(const char **pp_rtcname, int utc) | |||
261 | close(rtc); | 320 | close(rtc); |
262 | } | 321 | } |
263 | 322 | ||
264 | /* | 323 | // hwclock from util-linux 2.36.1 |
265 | * At system boot, kernel may set system time from RTC, | 324 | // hwclock [function] [option...] |
266 | * but it knows nothing about timezones. If RTC is in local time, | 325 | //Functions: |
267 | * then system time is wrong - it is offset by timezone. | 326 | // -r, --show display the RTC time |
268 | * This option corrects system time if RTC is in local time, | 327 | // --get display drift corrected RTC time |
269 | * and (always) sets in-kernel timezone. | 328 | // --set set the RTC according to --date |
270 | * | 329 | // -s, --hctosys set the system time from the RTC |
271 | * This is an alternate option to --hctosys that does not read the | 330 | // -w, --systohc set the RTC from the system time |
272 | * hardware clock. | 331 | // --systz send timescale configurations to the kernel |
273 | */ | 332 | // -a, --adjust adjust the RTC to account for systematic drift |
274 | static void set_system_clock_timezone(int utc) | 333 | // --predict predict the drifted RTC time according to --date |
275 | { | 334 | //Options: |
276 | struct timeval tv; | 335 | // -u, --utc the RTC timescale is UTC |
277 | struct tm *broken; | 336 | // -l, --localtime the RTC timescale is Local |
278 | struct timezone tz; | 337 | // -f, --rtc <file> use an alternate file to /dev/rtc0 |
279 | 338 | // --directisa use the ISA bus instead of /dev/rtc0 access | |
280 | gettimeofday(&tv, NULL); | 339 | // --date <time> date/time input for --set and --predict |
281 | broken = localtime(&tv.tv_sec); | 340 | // --delay <sec> delay used when set new RTC time |
282 | tz.tz_minuteswest = timezone / 60; | 341 | // --update-drift update the RTC drift factor |
283 | if (broken->tm_isdst > 0) | 342 | // --noadjfile do not use /etc/adjtime |
284 | tz.tz_minuteswest -= 60; | 343 | // --adjfile <file> use an alternate file to /etc/adjtime |
285 | tz.tz_dsttime = 0; | 344 | // --test dry run; implies --verbose |
286 | gettimeofday(&tv, NULL); | 345 | // -v, --verbose display more details |
287 | if (!utc) | ||
288 | tv.tv_sec += tz.tz_minuteswest * 60; | ||
289 | |||
290 | /* glibc v2.31+ returns an error if both args are non-NULL */ | ||
291 | if (settimeofday(NULL, &tz)) | ||
292 | bb_simple_perror_msg_and_die("settimeofday"); | ||
293 | if (settimeofday(&tv, NULL)) | ||
294 | bb_simple_perror_msg_and_die("settimeofday"); | ||
295 | } | ||
296 | 346 | ||
297 | //usage:#define hwclock_trivial_usage | 347 | //usage:#define hwclock_trivial_usage |
298 | //usage: IF_LONG_OPTS( | 348 | //usage: IF_LONG_OPTS( |
299 | //usage: "[-r|--show] [-s|--hctosys] [-w|--systohc] [--systz]" | 349 | //usage: "[-swul] [--systz] [-f DEV]" |
300 | //usage: " [--localtime] [-u|--utc]" | ||
301 | //usage: " [-f|--rtc FILE]" | ||
302 | //usage: ) | 350 | //usage: ) |
303 | //usage: IF_NOT_LONG_OPTS( | 351 | //usage: IF_NOT_LONG_OPTS( |
304 | //usage: "[-r] [-s] [-w] [-t] [-l] [-u] [-f FILE]" | 352 | //usage: "[-swult] [-f DEV]" |
305 | //usage: ) | 353 | //usage: ) |
306 | //usage:#define hwclock_full_usage "\n\n" | 354 | //usage:#define hwclock_full_usage "\n\n" |
307 | //usage: "Query and set hardware clock (RTC)\n" | 355 | //usage: "Show or set hardware clock (RTC)\n" |
308 | //usage: "\n -r Show hardware clock time" | 356 | ///////: "\n -r Show RTC time" |
309 | //usage: "\n -s Set system time from hardware clock" | 357 | ///////-r is default, don't bother showing it in help |
310 | //usage: "\n -w Set hardware clock from system time" | 358 | //usage: "\n -s Set system time from RTC" |
359 | //usage: "\n -w Set RTC from system time" | ||
311 | //usage: IF_LONG_OPTS( | 360 | //usage: IF_LONG_OPTS( |
312 | //usage: "\n --systz Set in-kernel timezone, correct system time" | 361 | //usage: "\n --systz Set in-kernel timezone, correct system time" |
362 | //usage: "\n if RTC is kept in local time" | ||
313 | //usage: ) | 363 | //usage: ) |
314 | //usage: "\n if hardware clock is in local time" | 364 | //usage: "\n -f DEV Use specified device (e.g. /dev/rtc2)" |
315 | //usage: "\n -u Assume hardware clock is kept in UTC" | 365 | //usage: "\n -u Assume RTC is kept in UTC" |
316 | //usage: IF_LONG_OPTS( | 366 | //usage: "\n -l Assume RTC is kept in local time" |
317 | //usage: "\n --localtime Assume hardware clock is kept in local time" | 367 | //usage: "\n (if neither is given, read from "ADJTIME_PATH")" |
318 | //usage: ) | ||
319 | //usage: "\n -f FILE Use specified device (e.g. /dev/rtc2)" | ||
320 | 368 | ||
321 | //TODO: get rid of incompatible -t and -l aliases to --systz and --localtime | 369 | //TODO: get rid of incompatible -t alias to --systz? |
322 | 370 | ||
323 | #define HWCLOCK_OPT_LOCALTIME 0x01 | 371 | #define HWCLOCK_OPT_LOCALTIME 0x01 |
324 | #define HWCLOCK_OPT_UTC 0x02 | 372 | #define HWCLOCK_OPT_UTC 0x02 |
@@ -334,10 +382,9 @@ int hwclock_main(int argc UNUSED_PARAM, char **argv) | |||
334 | const char *rtcname = NULL; | 382 | const char *rtcname = NULL; |
335 | unsigned opt; | 383 | unsigned opt; |
336 | int utc; | 384 | int utc; |
337 | |||
338 | #if ENABLE_LONG_OPTS | 385 | #if ENABLE_LONG_OPTS |
339 | static const char hwclock_longopts[] ALIGN1 = | 386 | static const char hwclock_longopts[] ALIGN1 = |
340 | "localtime\0" No_argument "l" /* short opt is non-standard */ | 387 | "localtime\0" No_argument "l" |
341 | "utc\0" No_argument "u" | 388 | "utc\0" No_argument "u" |
342 | "show\0" No_argument "r" | 389 | "show\0" No_argument "r" |
343 | "hctosys\0" No_argument "s" | 390 | "hctosys\0" No_argument "s" |
@@ -346,17 +393,15 @@ int hwclock_main(int argc UNUSED_PARAM, char **argv) | |||
346 | "rtc\0" Required_argument "f" | 393 | "rtc\0" Required_argument "f" |
347 | ; | 394 | ; |
348 | #endif | 395 | #endif |
349 | |||
350 | /* Initialize "timezone" (libc global variable) */ | ||
351 | tzset(); | ||
352 | |||
353 | opt = getopt32long(argv, | 396 | opt = getopt32long(argv, |
354 | "^lurswtf:" "\0" "r--wst:w--rst:s--wrt:t--rsw:l--u:u--l", | 397 | "^""lurswtf:v" /* -v is accepted and ignored */ |
398 | "\0" | ||
399 | "r--wst:w--rst:s--wrt:t--rsw:l--u:u--l", | ||
355 | hwclock_longopts, | 400 | hwclock_longopts, |
356 | &rtcname | 401 | &rtcname |
357 | ); | 402 | ); |
358 | 403 | ||
359 | /* If -u or -l wasn't given check if we are using utc */ | 404 | /* If -u or -l wasn't given, check if we are using utc */ |
360 | if (opt & (HWCLOCK_OPT_UTC | HWCLOCK_OPT_LOCALTIME)) | 405 | if (opt & (HWCLOCK_OPT_UTC | HWCLOCK_OPT_LOCALTIME)) |
361 | utc = (opt & HWCLOCK_OPT_UTC); | 406 | utc = (opt & HWCLOCK_OPT_UTC); |
362 | else | 407 | else |
@@ -367,7 +412,7 @@ int hwclock_main(int argc UNUSED_PARAM, char **argv) | |||
367 | else if (opt & HWCLOCK_OPT_SYSTOHC) | 412 | else if (opt & HWCLOCK_OPT_SYSTOHC) |
368 | from_sys_clock(&rtcname, utc); | 413 | from_sys_clock(&rtcname, utc); |
369 | else if (opt & HWCLOCK_OPT_SYSTZ) | 414 | else if (opt & HWCLOCK_OPT_SYSTZ) |
370 | set_system_clock_timezone(utc); | 415 | set_kernel_timezone_and_clock(utc, NULL); |
371 | else | 416 | else |
372 | /* default HWCLOCK_OPT_SHOW */ | 417 | /* default HWCLOCK_OPT_SHOW */ |
373 | show_clock(&rtcname, utc); | 418 | show_clock(&rtcname, utc); |
diff --git a/util-linux/ionice.c b/util-linux/ionice.c index 40c04d5e0..c8fb1a777 100644 --- a/util-linux/ionice.c +++ b/util-linux/ionice.c | |||
@@ -18,11 +18,11 @@ | |||
18 | //kbuild:lib-$(CONFIG_IONICE) += ionice.o | 18 | //kbuild:lib-$(CONFIG_IONICE) += ionice.o |
19 | 19 | ||
20 | //usage:#define ionice_trivial_usage | 20 | //usage:#define ionice_trivial_usage |
21 | //usage: "[-c 1-3] [-n 0-7] [-p PID] [PROG]" | 21 | //usage: "[-c 1-3] [-n 0-7] [-p PID] [PROG ARGS]" |
22 | //usage:#define ionice_full_usage "\n\n" | 22 | //usage:#define ionice_full_usage "\n\n" |
23 | //usage: "Change I/O priority and class\n" | 23 | //usage: "Change I/O priority and class\n" |
24 | //usage: "\n -c Class. 1:realtime 2:best-effort 3:idle" | 24 | //usage: "\n -c N Class. 1:realtime 2:best-effort 3:idle" |
25 | //usage: "\n -n Priority" | 25 | //usage: "\n -n N Priority" |
26 | 26 | ||
27 | #include <sys/syscall.h> | 27 | #include <sys/syscall.h> |
28 | #include <asm/unistd.h> | 28 | #include <asm/unistd.h> |
@@ -61,7 +61,7 @@ int ionice_main(int argc UNUSED_PARAM, char **argv) | |||
61 | /* Defaults */ | 61 | /* Defaults */ |
62 | int ioclass = 0; | 62 | int ioclass = 0; |
63 | int pri = 0; | 63 | int pri = 0; |
64 | int pid = 0; /* affect own porcess */ | 64 | int pid = 0; /* affect own process */ |
65 | int opt; | 65 | int opt; |
66 | enum { | 66 | enum { |
67 | OPT_n = 1, | 67 | OPT_n = 1, |
diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 59dbcf0cd..dbbcbc655 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c | |||
@@ -80,12 +80,14 @@ | |||
80 | //kbuild:lib-$(CONFIG_MDEV) += mdev.o | 80 | //kbuild:lib-$(CONFIG_MDEV) += mdev.o |
81 | 81 | ||
82 | //usage:#define mdev_trivial_usage | 82 | //usage:#define mdev_trivial_usage |
83 | //usage: "[-s]" IF_FEATURE_MDEV_DAEMON(" | [-df]") | 83 | //usage: "[-vS] " IF_FEATURE_MDEV_DAEMON("{ ") "[-s]" IF_FEATURE_MDEV_DAEMON(" | [-df] }") |
84 | //usage:#define mdev_full_usage "\n\n" | 84 | //usage:#define mdev_full_usage "\n\n" |
85 | //usage: "mdev -s is to be run during boot to scan /sys and populate /dev.\n" | 85 | //usage: " -v verbose\n" |
86 | //usage: " -S log to syslog too\n" | ||
87 | //usage: " -s scan /sys and populate /dev\n" | ||
86 | //usage: IF_FEATURE_MDEV_DAEMON( | 88 | //usage: IF_FEATURE_MDEV_DAEMON( |
87 | //usage: "mdev -d[f]: daemon, listen on netlink.\n" | 89 | //usage: " -d daemon, listen on netlink\n" |
88 | //usage: " -f: stay in foreground.\n" | 90 | //usage: " -f stay in foreground\n" |
89 | //usage: ) | 91 | //usage: ) |
90 | //usage: "\n" | 92 | //usage: "\n" |
91 | //usage: "Bare mdev is a kernel hotplug helper. To activate it:\n" | 93 | //usage: "Bare mdev is a kernel hotplug helper. To activate it:\n" |
@@ -113,6 +115,7 @@ | |||
113 | #include "common_bufsiz.h" | 115 | #include "common_bufsiz.h" |
114 | #include "xregex.h" | 116 | #include "xregex.h" |
115 | #include <linux/netlink.h> | 117 | #include <linux/netlink.h> |
118 | #include <syslog.h> | ||
116 | 119 | ||
117 | /* "mdev -s" scans /sys/class/xxx, looking for directories which have dev | 120 | /* "mdev -s" scans /sys/class/xxx, looking for directories which have dev |
118 | * file (it is of the form "M:m\n"). Example: /sys/class/tty/tty0/dev | 121 | * file (it is of the form "M:m\n"). Example: /sys/class/tty/tty0/dev |
@@ -269,10 +272,6 @@ | |||
269 | # define dbg3s(msg) ((void)0) | 272 | # define dbg3s(msg) ((void)0) |
270 | #endif | 273 | #endif |
271 | 274 | ||
272 | |||
273 | #ifndef SO_RCVBUFFORCE | ||
274 | #define SO_RCVBUFFORCE 33 | ||
275 | #endif | ||
276 | static const char keywords[] ALIGN1 = "add\0remove\0"; // "change\0" | 275 | static const char keywords[] ALIGN1 = "add\0remove\0"; // "change\0" |
277 | enum { OP_add, OP_remove }; | 276 | enum { OP_add, OP_remove }; |
278 | 277 | ||
@@ -297,7 +296,7 @@ struct rule { | |||
297 | 296 | ||
298 | struct globals { | 297 | struct globals { |
299 | int root_major, root_minor; | 298 | int root_major, root_minor; |
300 | smallint verbose; | 299 | int verbose; |
301 | char *subsystem; | 300 | char *subsystem; |
302 | char *subsys_env; /* for putenv("SUBSYSTEM=subsystem") */ | 301 | char *subsys_env; /* for putenv("SUBSYSTEM=subsystem") */ |
303 | #if ENABLE_FEATURE_MDEV_CONF | 302 | #if ENABLE_FEATURE_MDEV_CONF |
@@ -921,7 +920,7 @@ static void load_firmware(const char *firmware, const char *sysfs_path) | |||
921 | loading_fd = open("loading", O_WRONLY); | 920 | loading_fd = open("loading", O_WRONLY); |
922 | if (loading_fd >= 0) | 921 | if (loading_fd >= 0) |
923 | goto loading; | 922 | goto loading; |
924 | sleep(1); | 923 | sleep1(); |
925 | } | 924 | } |
926 | goto out; | 925 | goto out; |
927 | 926 | ||
@@ -964,7 +963,7 @@ static void load_firmware(const char *firmware, const char *sysfs_path) | |||
964 | static char *curtime(void) | 963 | static char *curtime(void) |
965 | { | 964 | { |
966 | struct timeval tv; | 965 | struct timeval tv; |
967 | gettimeofday(&tv, NULL); | 966 | xgettimeofday(&tv); |
968 | sprintf( | 967 | sprintf( |
969 | strftime_HHMMSS(G.timestr, sizeof(G.timestr), &tv.tv_sec), | 968 | strftime_HHMMSS(G.timestr, sizeof(G.timestr), &tv.tv_sec), |
970 | ".%06u", | 969 | ".%06u", |
@@ -1152,15 +1151,50 @@ static void initial_scan(char *temp) | |||
1152 | 1151 | ||
1153 | #if ENABLE_FEATURE_MDEV_DAEMON | 1152 | #if ENABLE_FEATURE_MDEV_DAEMON |
1154 | 1153 | ||
1155 | /* uevent applet uses 16k buffer, and mmaps it before every read */ | 1154 | /* |
1156 | # define BUFFER_SIZE (2 * 1024) | 1155 | * The kernel (as of v5.4) will pass up to 32 environment variables with a |
1157 | # define RCVBUF (2 * 1024 * 1024) | 1156 | * total of 2kiB on each event. On top of that the action string and device |
1157 | * path are added. Using a 3kiB buffer for the event should suffice in any | ||
1158 | * case. | ||
1159 | * | ||
1160 | * As far as the socket receive buffer size is concerned 2MiB proved to be too | ||
1161 | * small (see [1]). Udevd seems to use a whooping 128MiB. The socket receive | ||
1162 | * buffer size is just a resource limit. The buffers are allocated lazily so | ||
1163 | * the memory is not wasted. | ||
1164 | * | ||
1165 | * [1] http://lists.busybox.net/pipermail/busybox/2019-December/087665.html | ||
1166 | */ | ||
1167 | # define USER_RCVBUF (3 * 1024) | ||
1168 | # define KERN_RCVBUF (128 * 1024 * 1024) | ||
1158 | # define MAX_ENV 32 | 1169 | # define MAX_ENV 32 |
1159 | 1170 | ||
1171 | static int daemon_init(char *temp) | ||
1172 | { | ||
1173 | int fd; | ||
1174 | |||
1175 | /* Subscribe for UEVENT kernel messages */ | ||
1176 | /* Without a sufficiently big RCVBUF, a ton of simultaneous events | ||
1177 | * can trigger ENOBUFS on read, which is unrecoverable. | ||
1178 | * Reproducer: | ||
1179 | * mdev -d | ||
1180 | * find /sys -name uevent -exec sh -c 'echo add >"{}"' ';' | ||
1181 | */ | ||
1182 | fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, 1 << 0, KERN_RCVBUF); | ||
1183 | |||
1184 | /* | ||
1185 | * Make inital scan after the uevent socket is alive and | ||
1186 | * _before_ we fork away. Already open mdev.log because we work | ||
1187 | * in daemon mode. | ||
1188 | */ | ||
1189 | initial_scan(temp); | ||
1190 | |||
1191 | return fd; | ||
1192 | } | ||
1193 | |||
1160 | static void daemon_loop(char *temp, int fd) | 1194 | static void daemon_loop(char *temp, int fd) |
1161 | { | 1195 | { |
1162 | for (;;) { | 1196 | for (;;) { |
1163 | char netbuf[BUFFER_SIZE]; | 1197 | char netbuf[USER_RCVBUF]; |
1164 | char *env[MAX_ENV]; | 1198 | char *env[MAX_ENV]; |
1165 | char *s, *end; | 1199 | char *s, *end; |
1166 | ssize_t len; | 1200 | ssize_t len; |
@@ -1168,6 +1202,16 @@ static void daemon_loop(char *temp, int fd) | |||
1168 | 1202 | ||
1169 | len = safe_read(fd, netbuf, sizeof(netbuf) - 1); | 1203 | len = safe_read(fd, netbuf, sizeof(netbuf) - 1); |
1170 | if (len < 0) { | 1204 | if (len < 0) { |
1205 | if (errno == ENOBUFS) { | ||
1206 | /* | ||
1207 | * We ran out of socket receive buffer space. | ||
1208 | * Start from scratch. | ||
1209 | */ | ||
1210 | dbg1s("uevent overrun, rescanning"); | ||
1211 | close(fd); | ||
1212 | fd = daemon_init(temp); | ||
1213 | continue; | ||
1214 | } | ||
1171 | bb_simple_perror_msg_and_die("read"); | 1215 | bb_simple_perror_msg_and_die("read"); |
1172 | } | 1216 | } |
1173 | end = netbuf + len; | 1217 | end = netbuf + len; |
@@ -1196,8 +1240,9 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) | |||
1196 | { | 1240 | { |
1197 | enum { | 1241 | enum { |
1198 | MDEV_OPT_SCAN = 1 << 0, | 1242 | MDEV_OPT_SCAN = 1 << 0, |
1199 | MDEV_OPT_DAEMON = 1 << 1, | 1243 | MDEV_OPT_SYSLOG = 1 << 1, |
1200 | MDEV_OPT_FOREGROUND = 1 << 2, | 1244 | MDEV_OPT_DAEMON = 1 << 2, |
1245 | MDEV_OPT_FOREGROUND = 1 << 3, | ||
1201 | }; | 1246 | }; |
1202 | int opt; | 1247 | int opt; |
1203 | RESERVE_CONFIG_BUFFER(temp, PATH_MAX + SCRATCH_SIZE); | 1248 | RESERVE_CONFIG_BUFFER(temp, PATH_MAX + SCRATCH_SIZE); |
@@ -1213,7 +1258,11 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) | |||
1213 | 1258 | ||
1214 | xchdir("/dev"); | 1259 | xchdir("/dev"); |
1215 | 1260 | ||
1216 | opt = getopt32(argv, "s" IF_FEATURE_MDEV_DAEMON("df")); | 1261 | opt = getopt32(argv, "^" |
1262 | "sS" IF_FEATURE_MDEV_DAEMON("df") "v" | ||
1263 | "\0" | ||
1264 | "vv", | ||
1265 | &G.verbose); | ||
1217 | 1266 | ||
1218 | #if ENABLE_FEATURE_MDEV_CONF | 1267 | #if ENABLE_FEATURE_MDEV_CONF |
1219 | G.filename = "/etc/mdev.conf"; | 1268 | G.filename = "/etc/mdev.conf"; |
@@ -1223,32 +1272,24 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) | |||
1223 | } | 1272 | } |
1224 | #endif | 1273 | #endif |
1225 | 1274 | ||
1275 | if (opt & MDEV_OPT_SYSLOG) { | ||
1276 | openlog(applet_name, LOG_PID, LOG_DAEMON); | ||
1277 | logmode |= LOGMODE_SYSLOG; | ||
1278 | } | ||
1279 | |||
1226 | #if ENABLE_FEATURE_MDEV_DAEMON | 1280 | #if ENABLE_FEATURE_MDEV_DAEMON |
1227 | if (opt & MDEV_OPT_DAEMON) { | 1281 | if (opt & MDEV_OPT_DAEMON) { |
1228 | /* | 1282 | /* Daemon mode listening on uevent netlink socket. Fork away |
1229 | * Daemon mode listening on uevent netlink socket. | 1283 | * after initial scan so that caller can be sure everything |
1230 | */ | 1284 | * is up-to-date when mdev process returns. |
1231 | int fd; | ||
1232 | |||
1233 | /* Subscribe for UEVENT kernel messages */ | ||
1234 | /* Without a sufficiently big RCVBUF, a ton of simultaneous events | ||
1235 | * can trigger ENOBUFS on read, which is unrecoverable. | ||
1236 | * Reproducer: | ||
1237 | * mdev -d | ||
1238 | * find /sys -name uevent -exec sh -c 'echo add >"{}"' ';' | ||
1239 | */ | 1285 | */ |
1240 | fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, 1 << 0, RCVBUF); | 1286 | int fd = daemon_init(temp); |
1241 | 1287 | ||
1242 | /* | 1288 | if (!(opt & MDEV_OPT_FOREGROUND)) { |
1243 | * Make inital scan after the uevent socket is alive and | 1289 | /* there is no point in logging to /dev/null */ |
1244 | * _before_ we fork away. | 1290 | logmode &= ~LOGMODE_STDIO; |
1245 | */ | ||
1246 | initial_scan(temp); | ||
1247 | |||
1248 | if (!(opt & MDEV_OPT_FOREGROUND)) | ||
1249 | bb_daemonize_or_rexec(0, argv); | 1291 | bb_daemonize_or_rexec(0, argv); |
1250 | 1292 | } | |
1251 | open_mdev_log(NULL, getpid()); | ||
1252 | 1293 | ||
1253 | daemon_loop(temp, fd); | 1294 | daemon_loop(temp, fd); |
1254 | } | 1295 | } |
diff --git a/util-linux/mkfs_ext2.c b/util-linux/mkfs_ext2.c index 1f525d75b..fcf374b2d 100644 --- a/util-linux/mkfs_ext2.c +++ b/util-linux/mkfs_ext2.c | |||
@@ -131,7 +131,7 @@ static void allocate(uint8_t *bitmap, uint32_t blocksize, uint32_t start, uint32 | |||
131 | static uint32_t has_super(uint32_t x) | 131 | static uint32_t has_super(uint32_t x) |
132 | { | 132 | { |
133 | // 0, 1 and powers of 3, 5, 7 up to 2^32 limit | 133 | // 0, 1 and powers of 3, 5, 7 up to 2^32 limit |
134 | static const uint32_t supers[] = { | 134 | static const uint32_t supers[] ALIGN4 = { |
135 | 0, 1, 3, 5, 7, 9, 25, 27, 49, 81, 125, 243, 343, 625, 729, | 135 | 0, 1, 3, 5, 7, 9, 25, 27, 49, 81, 125, 243, 343, 625, 729, |
136 | 2187, 2401, 3125, 6561, 15625, 16807, 19683, 59049, 78125, | 136 | 2187, 2401, 3125, 6561, 15625, 16807, 19683, 59049, 78125, |
137 | 117649, 177147, 390625, 531441, 823543, 1594323, 1953125, | 137 | 117649, 177147, 390625, 531441, 823543, 1594323, 1953125, |
diff --git a/util-linux/mkswap.c b/util-linux/mkswap.c index 9e51a1dcc..8fe5d0293 100644 --- a/util-linux/mkswap.c +++ b/util-linux/mkswap.c | |||
@@ -128,7 +128,7 @@ int mkswap_main(int argc UNUSED_PARAM, char **argv) | |||
128 | 128 | ||
129 | /* Figure out how big the device is */ | 129 | /* Figure out how big the device is */ |
130 | len = get_volume_size_in_bytes(fd, argv[1], 1024, /*extend:*/ 1); | 130 | len = get_volume_size_in_bytes(fd, argv[1], 1024, /*extend:*/ 1); |
131 | pagesize = getpagesize(); | 131 | pagesize = bb_getpagesize(); |
132 | len -= pagesize; | 132 | len -= pagesize; |
133 | 133 | ||
134 | /* Announce our intentions */ | 134 | /* Announce our intentions */ |
diff --git a/util-linux/mount.c b/util-linux/mount.c index fc5161d7f..831dab9e2 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c | |||
@@ -182,14 +182,16 @@ | |||
182 | //usage: "Returns 0 for success, number of failed mounts for -a, or errno for one mount." | 182 | //usage: "Returns 0 for success, number of failed mounts for -a, or errno for one mount." |
183 | 183 | ||
184 | #include <mntent.h> | 184 | #include <mntent.h> |
185 | #if ENABLE_FEATURE_SYSLOG | ||
185 | #include <syslog.h> | 186 | #include <syslog.h> |
187 | #endif | ||
186 | #include <sys/mount.h> | 188 | #include <sys/mount.h> |
187 | // Grab more as needed from util-linux's mount/mount_constants.h | 189 | // Grab more as needed from util-linux's mount/mount_constants.h |
188 | #ifndef MS_DIRSYNC | 190 | #ifndef MS_DIRSYNC |
189 | # define MS_DIRSYNC (1 << 7) // Directory modifications are synchronous | 191 | # define MS_DIRSYNC (1 << 7) // Directory modifications are synchronous |
190 | #endif | 192 | #endif |
191 | #ifndef MS_UNION | 193 | #ifndef MS_NOSYMFOLLOW |
192 | # define MS_UNION (1 << 8) | 194 | # define MS_NOSYMFOLLOW (1 << 8) |
193 | #endif | 195 | #endif |
194 | #ifndef MS_BIND | 196 | #ifndef MS_BIND |
195 | # define MS_BIND (1 << 12) | 197 | # define MS_BIND (1 << 12) |
@@ -216,12 +218,16 @@ | |||
216 | #ifndef MS_SHARED | 218 | #ifndef MS_SHARED |
217 | # define MS_SHARED (1 << 20) | 219 | # define MS_SHARED (1 << 20) |
218 | #endif | 220 | #endif |
221 | |||
219 | #ifndef MS_RELATIME | 222 | #ifndef MS_RELATIME |
220 | # define MS_RELATIME (1 << 21) | 223 | # define MS_RELATIME (1 << 21) |
221 | #endif | 224 | #endif |
222 | #ifndef MS_STRICTATIME | 225 | #ifndef MS_STRICTATIME |
223 | # define MS_STRICTATIME (1 << 24) | 226 | # define MS_STRICTATIME (1 << 24) |
224 | #endif | 227 | #endif |
228 | #ifndef MS_LAZYTIME | ||
229 | # define MS_LAZYTIME (1 << 25) | ||
230 | #endif | ||
225 | 231 | ||
226 | /* Any ~MS_FOO value has this bit set: */ | 232 | /* Any ~MS_FOO value has this bit set: */ |
227 | #define BB_MS_INVERTED_VALUE (1u << 31) | 233 | #define BB_MS_INVERTED_VALUE (1u << 31) |
@@ -323,7 +329,7 @@ enum { | |||
323 | 329 | ||
324 | // Standard mount options (from -o options or --options), | 330 | // Standard mount options (from -o options or --options), |
325 | // with corresponding flags | 331 | // with corresponding flags |
326 | static const int32_t mount_options[] = { | 332 | static const int32_t mount_options[] ALIGN4 = { |
327 | // MS_FLAGS set a bit. ~MS_FLAGS disable that bit. 0 flags are NOPs. | 333 | // MS_FLAGS set a bit. ~MS_FLAGS disable that bit. 0 flags are NOPs. |
328 | 334 | ||
329 | IF_FEATURE_MOUNT_LOOP( | 335 | IF_FEATURE_MOUNT_LOOP( |
@@ -358,16 +364,19 @@ static const int32_t mount_options[] = { | |||
358 | /* "noatime" */ MS_NOATIME, | 364 | /* "noatime" */ MS_NOATIME, |
359 | /* "diratime" */ ~MS_NODIRATIME, | 365 | /* "diratime" */ ~MS_NODIRATIME, |
360 | /* "nodiratime" */ MS_NODIRATIME, | 366 | /* "nodiratime" */ MS_NODIRATIME, |
361 | /* "mand" */ MS_MANDLOCK, | ||
362 | /* "nomand" */ ~MS_MANDLOCK, | ||
363 | /* "relatime" */ MS_RELATIME, | 367 | /* "relatime" */ MS_RELATIME, |
364 | /* "norelatime" */ ~MS_RELATIME, | 368 | /* "norelatime" */ ~MS_RELATIME, |
365 | /* "strictatime" */ MS_STRICTATIME, | 369 | /* "strictatime" */ MS_STRICTATIME, |
366 | /* "loud" */ ~MS_SILENT, | 370 | /* "nostrictatime"*/ ~MS_STRICTATIME, |
367 | /* "rbind" */ MS_BIND|MS_RECURSIVE, | 371 | /* "lazytime" */ MS_LAZYTIME, |
372 | /* "nolazytime" */ ~MS_LAZYTIME, | ||
373 | /* "nosymfollow" */ MS_NOSYMFOLLOW, | ||
374 | /* "mand" */ MS_MANDLOCK, | ||
375 | /* "nomand" */ ~MS_MANDLOCK, | ||
376 | /* "loud" */ ~MS_SILENT, | ||
368 | 377 | ||
369 | // action flags | 378 | // action flags |
370 | /* "union" */ MS_UNION, | 379 | /* "rbind" */ MS_BIND|MS_RECURSIVE, |
371 | /* "bind" */ MS_BIND, | 380 | /* "bind" */ MS_BIND, |
372 | /* "move" */ MS_MOVE, | 381 | /* "move" */ MS_MOVE, |
373 | /* "shared" */ MS_SHARED, | 382 | /* "shared" */ MS_SHARED, |
@@ -404,29 +413,32 @@ static const char mount_option_str[] ALIGN1 = | |||
404 | ) | 413 | ) |
405 | IF_FEATURE_MOUNT_FLAGS( | 414 | IF_FEATURE_MOUNT_FLAGS( |
406 | // vfs flags | 415 | // vfs flags |
407 | "nosuid\0" | 416 | "nosuid" "\0" |
408 | "suid\0" | 417 | "suid" "\0" |
409 | "dev\0" | 418 | "dev" "\0" |
410 | "nodev\0" | 419 | "nodev" "\0" |
411 | "exec\0" | 420 | "exec" "\0" |
412 | "noexec\0" | 421 | "noexec" "\0" |
413 | "sync\0" | 422 | "sync" "\0" |
414 | "dirsync\0" | 423 | "dirsync" "\0" |
415 | "async\0" | 424 | "async" "\0" |
416 | "atime\0" | 425 | "atime" "\0" |
417 | "noatime\0" | 426 | "noatime" "\0" |
418 | "diratime\0" | 427 | "diratime" "\0" |
419 | "nodiratime\0" | 428 | "nodiratime" "\0" |
420 | "mand\0" | 429 | "relatime" "\0" |
421 | "nomand\0" | 430 | "norelatime" "\0" |
422 | "relatime\0" | 431 | "strictatime" "\0" |
423 | "norelatime\0" | 432 | "nostrictatime""\0" |
424 | "strictatime\0" | 433 | "lazytime" "\0" |
425 | "loud\0" | 434 | "nolazytime" "\0" |
426 | "rbind\0" | 435 | "nosymfollow" "\0" |
436 | "mand" "\0" | ||
437 | "nomand" "\0" | ||
438 | "loud" "\0" | ||
427 | 439 | ||
428 | // action flags | 440 | // action flags |
429 | "union\0" | 441 | "rbind\0" |
430 | "bind\0" | 442 | "bind\0" |
431 | "move\0" | 443 | "move\0" |
432 | "make-shared\0" | 444 | "make-shared\0" |
@@ -641,7 +653,7 @@ static unsigned long parse_mount_options(char *options, char **unrecognized) | |||
641 | // Return a list of all block device backed filesystems | 653 | // Return a list of all block device backed filesystems |
642 | static llist_t *get_block_backed_filesystems(void) | 654 | static llist_t *get_block_backed_filesystems(void) |
643 | { | 655 | { |
644 | static const char filesystems[2][sizeof("/proc/filesystems")] = { | 656 | static const char filesystems[2][sizeof("/proc/filesystems")] ALIGN1 = { |
645 | "/etc/filesystems", | 657 | "/etc/filesystems", |
646 | "/proc/filesystems", | 658 | "/proc/filesystems", |
647 | }; | 659 | }; |
@@ -2064,13 +2076,18 @@ static int singlemount(struct mntent *mp, int ignore_busy) | |||
2064 | } | 2076 | } |
2065 | 2077 | ||
2066 | // Might this be an NFS filesystem? | 2078 | // Might this be an NFS filesystem? |
2067 | if ((!mp->mnt_type || is_prefixed_with(mp->mnt_type, "nfs")) | 2079 | if (!(vfsflags & (MS_BIND | MS_MOVE)) |
2068 | && strchr(mp->mnt_fsname, ':') != NULL | 2080 | && (!mp->mnt_type || is_prefixed_with(mp->mnt_type, "nfs")) |
2069 | ) { | 2081 | ) { |
2070 | if (!mp->mnt_type) | 2082 | char *colon = strchr(mp->mnt_fsname, ':'); |
2071 | mp->mnt_type = (char*)"nfs"; | 2083 | if (colon // looks like "hostname:..." |
2072 | rc = nfsmount(mp, vfsflags, filteropts); | 2084 | && strchrnul(mp->mnt_fsname, '/') > colon // "hostname:" has no slashes |
2073 | goto report_error; | 2085 | ) { |
2086 | if (!mp->mnt_type) | ||
2087 | mp->mnt_type = (char*)"nfs"; | ||
2088 | rc = nfsmount(mp, vfsflags, filteropts); | ||
2089 | goto report_error; | ||
2090 | } | ||
2074 | } | 2091 | } |
2075 | 2092 | ||
2076 | // Look at the file. (Not found isn't a failure for remount, or for | 2093 | // Look at the file. (Not found isn't a failure for remount, or for |
@@ -2110,7 +2127,7 @@ static int singlemount(struct mntent *mp, int ignore_busy) | |||
2110 | bb_simple_error_msg(bb_msg_perm_denied_are_you_root); | 2127 | bb_simple_error_msg(bb_msg_perm_denied_are_you_root); |
2111 | else | 2128 | else |
2112 | bb_simple_perror_msg("can't setup loop device"); | 2129 | bb_simple_perror_msg("can't setup loop device"); |
2113 | return errno; | 2130 | return loopfd; // was "return errno", but it can be 0 here |
2114 | } | 2131 | } |
2115 | 2132 | ||
2116 | // Autodetect bind mounts | 2133 | // Autodetect bind mounts |
diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c index c48dcf885..e6339da2f 100644 --- a/util-linux/nsenter.c +++ b/util-linux/nsenter.c | |||
@@ -17,7 +17,7 @@ | |||
17 | //kbuild:lib-$(CONFIG_NSENTER) += nsenter.o | 17 | //kbuild:lib-$(CONFIG_NSENTER) += nsenter.o |
18 | 18 | ||
19 | //usage:#define nsenter_trivial_usage | 19 | //usage:#define nsenter_trivial_usage |
20 | //usage: "[OPTIONS] [PROG [ARGS]]" | 20 | //usage: "[OPTIONS] [PROG ARGS]" |
21 | //usage:#define nsenter_full_usage "\n" | 21 | //usage:#define nsenter_full_usage "\n" |
22 | //usage: "\n -t PID Target process to get namespaces from" | 22 | //usage: "\n -t PID Target process to get namespaces from" |
23 | //usage: "\n -m[FILE] Enter mount namespace" | 23 | //usage: "\n -m[FILE] Enter mount namespace" |
@@ -103,8 +103,9 @@ static const struct namespace_descr ns_list[] = { | |||
103 | }; | 103 | }; |
104 | /* | 104 | /* |
105 | * Upstream nsenter doesn't support the short option for --preserve-credentials | 105 | * Upstream nsenter doesn't support the short option for --preserve-credentials |
106 | * "+": stop on first non-option | ||
106 | */ | 107 | */ |
107 | static const char opt_str[] ALIGN1 = "U::i::u::n::p::m::""t:+S:+G:+r::w::F"; | 108 | static const char opt_str[] ALIGN1 = "+""U::i::u::n::p::m::""t:+S:+G:+r::w::F"; |
108 | 109 | ||
109 | #if ENABLE_LONG_OPTS | 110 | #if ENABLE_LONG_OPTS |
110 | static const char nsenter_longopts[] ALIGN1 = | 111 | static const char nsenter_longopts[] ALIGN1 = |
diff --git a/util-linux/rdate.c b/util-linux/rdate.c index bb1dc519a..9b80141c9 100644 --- a/util-linux/rdate.c +++ b/util-linux/rdate.c | |||
@@ -96,11 +96,10 @@ int rdate_main(int argc UNUSED_PARAM, char **argv) | |||
96 | if (time(NULL) == remote_time) | 96 | if (time(NULL) == remote_time) |
97 | bb_simple_error_msg("current time matches remote time"); | 97 | bb_simple_error_msg("current time matches remote time"); |
98 | else { | 98 | else { |
99 | struct timespec ts; | 99 | struct timeval ts; |
100 | ts.tv_sec = remote_time; | 100 | ts.tv_sec = remote_time; |
101 | ts.tv_nsec = 0; | 101 | ts.tv_usec = 0; |
102 | if (clock_settime(CLOCK_REALTIME, &ts) < 0) | 102 | xsettimeofday(&ts); |
103 | bb_simple_perror_msg_and_die("can't set time of day"); | ||
104 | } | 103 | } |
105 | } | 104 | } |
106 | 105 | ||
diff --git a/util-linux/rtcwake.c b/util-linux/rtcwake.c index 823e55662..eac16077d 100644 --- a/util-linux/rtcwake.c +++ b/util-linux/rtcwake.c | |||
@@ -36,24 +36,13 @@ | |||
36 | //usage: "[-a | -l | -u] [-d DEV] [-m MODE] [-s SEC | -t TIME]" | 36 | //usage: "[-a | -l | -u] [-d DEV] [-m MODE] [-s SEC | -t TIME]" |
37 | //usage:#define rtcwake_full_usage "\n\n" | 37 | //usage:#define rtcwake_full_usage "\n\n" |
38 | //usage: "Enter a system sleep state until specified wakeup time\n" | 38 | //usage: "Enter a system sleep state until specified wakeup time\n" |
39 | //usage: IF_LONG_OPTS( | 39 | //usage: "\n -a Read clock mode from "ADJTIME_PATH" (default)" |
40 | //usage: "\n -a,--auto Read clock mode from adjtime" | ||
41 | //usage: "\n -l,--local Clock is set to local time" | ||
42 | //usage: "\n -u,--utc Clock is set to UTC time" | ||
43 | //usage: "\n -d,--device DEV Specify the RTC device" | ||
44 | //usage: "\n -m,--mode MODE Set sleep state (default: standby)" | ||
45 | //usage: "\n -s,--seconds SEC Set timeout in SEC seconds from now" | ||
46 | //usage: "\n -t,--time TIME Set timeout to TIME seconds from epoch" | ||
47 | //usage: ) | ||
48 | //usage: IF_NOT_LONG_OPTS( | ||
49 | //usage: "\n -a Read clock mode from adjtime" | ||
50 | //usage: "\n -l Clock is set to local time" | 40 | //usage: "\n -l Clock is set to local time" |
51 | //usage: "\n -u Clock is set to UTC time" | 41 | //usage: "\n -u Clock is set to UTC time" |
52 | //usage: "\n -d DEV Specify the RTC device" | 42 | //usage: "\n -d DEV Specify the RTC device" |
53 | //usage: "\n -m MODE Set sleep state (default: standby)" | 43 | //usage: "\n -m MODE Set sleep state (default: standby)" |
54 | //usage: "\n -s SEC Set timeout in SEC seconds from now" | 44 | //usage: "\n -s SEC Set timeout in SEC seconds from now" |
55 | //usage: "\n -t TIME Set timeout to TIME seconds from epoch" | 45 | //usage: "\n -t TIME Set timeout to TIME seconds from epoch" |
56 | //usage: ) | ||
57 | 46 | ||
58 | #include "libbb.h" | 47 | #include "libbb.h" |
59 | #include "rtc_.h" | 48 | #include "rtc_.h" |
diff --git a/util-linux/script.c b/util-linux/script.c index 4eac5e94f..963435335 100644 --- a/util-linux/script.c +++ b/util-linux/script.c | |||
@@ -172,7 +172,7 @@ int script_main(int argc UNUSED_PARAM, char **argv) | |||
172 | struct timeval tv; | 172 | struct timeval tv; |
173 | double newtime; | 173 | double newtime; |
174 | 174 | ||
175 | gettimeofday(&tv, NULL); | 175 | xgettimeofday(&tv); |
176 | newtime = tv.tv_sec + (double) tv.tv_usec / 1000000; | 176 | newtime = tv.tv_sec + (double) tv.tv_usec / 1000000; |
177 | fprintf(timing_fp, "%f %u\n", newtime - oldtime, count); | 177 | fprintf(timing_fp, "%f %u\n", newtime - oldtime, count); |
178 | oldtime = newtime; | 178 | oldtime = newtime; |
diff --git a/util-linux/setpriv.c b/util-linux/setpriv.c index 1e4b201ed..6904cf019 100644 --- a/util-linux/setpriv.c +++ b/util-linux/setpriv.c | |||
@@ -47,7 +47,7 @@ | |||
47 | //kbuild:lib-$(CONFIG_SETPRIV) += setpriv.o | 47 | //kbuild:lib-$(CONFIG_SETPRIV) += setpriv.o |
48 | 48 | ||
49 | //usage:#define setpriv_trivial_usage | 49 | //usage:#define setpriv_trivial_usage |
50 | //usage: "[OPTIONS] PROG [ARGS]" | 50 | //usage: "[OPTIONS] PROG ARGS" |
51 | //usage:#define setpriv_full_usage "\n\n" | 51 | //usage:#define setpriv_full_usage "\n\n" |
52 | //usage: "Run PROG with different privilege settings\n" | 52 | //usage: "Run PROG with different privilege settings\n" |
53 | //usage: IF_FEATURE_SETPRIV_DUMP( | 53 | //usage: IF_FEATURE_SETPRIV_DUMP( |
diff --git a/util-linux/uevent.c b/util-linux/uevent.c index 57d9328ef..db11746d0 100644 --- a/util-linux/uevent.c +++ b/util-linux/uevent.c | |||
@@ -15,7 +15,7 @@ | |||
15 | //kbuild:lib-$(CONFIG_UEVENT) += uevent.o | 15 | //kbuild:lib-$(CONFIG_UEVENT) += uevent.o |
16 | 16 | ||
17 | //usage:#define uevent_trivial_usage | 17 | //usage:#define uevent_trivial_usage |
18 | //usage: "[PROG [ARGS]]" | 18 | //usage: "[PROG ARGS]" |
19 | //usage:#define uevent_full_usage "\n\n" | 19 | //usage:#define uevent_full_usage "\n\n" |
20 | //usage: "uevent runs PROG for every netlink notification." | 20 | //usage: "uevent runs PROG for every netlink notification." |
21 | //usage: "\n""PROG's environment contains data passed from the kernel." | 21 | //usage: "\n""PROG's environment contains data passed from the kernel." |
@@ -26,22 +26,26 @@ | |||
26 | #include "common_bufsiz.h" | 26 | #include "common_bufsiz.h" |
27 | #include <linux/netlink.h> | 27 | #include <linux/netlink.h> |
28 | 28 | ||
29 | #define BUFFER_SIZE 16*1024 | ||
30 | |||
31 | #define env ((char **)bb_common_bufsiz1) | 29 | #define env ((char **)bb_common_bufsiz1) |
32 | #define INIT_G() do { setup_common_bufsiz(); } while (0) | 30 | #define INIT_G() do { setup_common_bufsiz(); } while (0) |
33 | enum { | 31 | enum { |
34 | MAX_ENV = COMMON_BUFSIZE / sizeof(char*) - 1, | 32 | MAX_ENV = COMMON_BUFSIZE / sizeof(char*) - 1, |
35 | /* sizeof(env[0]) instead of sizeof(char*) | 33 | // ^^^sizeof(env[0]) instead of sizeof(char*) |
36 | * makes gcc-6.3.0 emit "strict-aliasing" warning. | 34 | // makes gcc-6.3.0 emit "strict-aliasing" warning. |
37 | */ | 35 | |
36 | // socket receive buffer of 2MiB proved to be too small: | ||
37 | // http://lists.busybox.net/pipermail/busybox/2019-December/087665.html | ||
38 | // udevd seems to use a whooping 128MiB. | ||
39 | // The socket receive buffer size is just a resource limit. | ||
40 | // The buffers are allocated lazily so the memory is not wasted. | ||
41 | KERN_RCVBUF = 128 * 1024 * 1024, | ||
42 | |||
43 | // Might be made smaller: the kernel v5.4 passes up to 32 environment | ||
44 | // variables with a total of 2kb on each event. | ||
45 | // On top of that the action string and device path are added. | ||
46 | USER_RCVBUF = 16 * 1024, | ||
38 | }; | 47 | }; |
39 | 48 | ||
40 | #ifndef SO_RCVBUFFORCE | ||
41 | #define SO_RCVBUFFORCE 33 | ||
42 | #endif | ||
43 | enum { RCVBUF = 2 * 1024 * 1024 }; | ||
44 | |||
45 | int uevent_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 49 | int uevent_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
46 | int uevent_main(int argc UNUSED_PARAM, char **argv) | 50 | int uevent_main(int argc UNUSED_PARAM, char **argv) |
47 | { | 51 | { |
@@ -57,7 +61,8 @@ int uevent_main(int argc UNUSED_PARAM, char **argv) | |||
57 | // Reproducer: | 61 | // Reproducer: |
58 | // uevent mdev & | 62 | // uevent mdev & |
59 | // find /sys -name uevent -exec sh -c 'echo add >"{}"' ';' | 63 | // find /sys -name uevent -exec sh -c 'echo add >"{}"' ';' |
60 | fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, /*groups:*/ 1 << 0, RCVBUF); | 64 | reopen: |
65 | fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, /*groups:*/ 1 << 0, KERN_RCVBUF); | ||
61 | 66 | ||
62 | for (;;) { | 67 | for (;;) { |
63 | char *netbuf; | 68 | char *netbuf; |
@@ -69,17 +74,20 @@ int uevent_main(int argc UNUSED_PARAM, char **argv) | |||
69 | // for a new uevent notification to come in. | 74 | // for a new uevent notification to come in. |
70 | // We use a fresh mmap so that buffer is not allocated | 75 | // We use a fresh mmap so that buffer is not allocated |
71 | // until kernel actually starts filling it. | 76 | // until kernel actually starts filling it. |
72 | netbuf = mmap(NULL, BUFFER_SIZE, | 77 | netbuf = xmmap_anon(USER_RCVBUF); |
73 | PROT_READ | PROT_WRITE, | ||
74 | MAP_PRIVATE | MAP_ANON, | ||
75 | /* ignored: */ -1, 0); | ||
76 | if (netbuf == MAP_FAILED) | ||
77 | bb_simple_perror_msg_and_die("mmap"); | ||
78 | 78 | ||
79 | // Here we block, possibly for a very long time | 79 | // Here we block, possibly for a very long time |
80 | len = safe_read(fd, netbuf, BUFFER_SIZE - 1); | 80 | len = safe_read(fd, netbuf, USER_RCVBUF - 1); |
81 | if (len < 0) | 81 | if (len < 0) { |
82 | if (errno == ENOBUFS) { | ||
83 | // Ran out of socket receive buffer | ||
84 | bb_simple_error_msg("uevent overrun"); | ||
85 | close(fd); | ||
86 | munmap(netbuf, USER_RCVBUF); | ||
87 | goto reopen; | ||
88 | } | ||
82 | bb_simple_perror_msg_and_die("read"); | 89 | bb_simple_perror_msg_and_die("read"); |
90 | } | ||
83 | end = netbuf + len; | 91 | end = netbuf + len; |
84 | *end = '\0'; | 92 | *end = '\0'; |
85 | 93 | ||
@@ -108,7 +116,7 @@ int uevent_main(int argc UNUSED_PARAM, char **argv) | |||
108 | while (env[idx]) | 116 | while (env[idx]) |
109 | bb_unsetenv(env[idx++]); | 117 | bb_unsetenv(env[idx++]); |
110 | } | 118 | } |
111 | munmap(netbuf, BUFFER_SIZE); | 119 | munmap(netbuf, USER_RCVBUF); |
112 | } | 120 | } |
113 | 121 | ||
114 | return 0; // not reached | 122 | return 0; // not reached |
diff --git a/util-linux/umount.c b/util-linux/umount.c index 63a3bf504..23da32868 100644 --- a/util-linux/umount.c +++ b/util-linux/umount.c | |||
@@ -41,16 +41,16 @@ | |||
41 | //kbuild:lib-$(CONFIG_UMOUNT) += umount.o | 41 | //kbuild:lib-$(CONFIG_UMOUNT) += umount.o |
42 | 42 | ||
43 | //usage:#define umount_trivial_usage | 43 | //usage:#define umount_trivial_usage |
44 | //usage: "[OPTIONS] FILESYSTEM|DIRECTORY" | 44 | //usage: "[-rlf"IF_FEATURE_MTAB_SUPPORT("m")IF_FEATURE_MOUNT_LOOP("d")IF_FEATURE_UMOUNT_ALL("a")"] [-t FSTYPE] FILESYSTEM|DIRECTORY" |
45 | //usage:#define umount_full_usage "\n\n" | 45 | //usage:#define umount_full_usage "\n\n" |
46 | //usage: "Unmount file systems\n" | 46 | //usage: "Unmount filesystems\n" |
47 | //usage: IF_FEATURE_UMOUNT_ALL( | 47 | //usage: IF_FEATURE_UMOUNT_ALL( |
48 | //usage: "\n -a Unmount all file systems" IF_FEATURE_MTAB_SUPPORT(" in /etc/mtab") | 48 | //usage: "\n -a Unmount all filesystems" IF_FEATURE_MTAB_SUPPORT(" in /etc/mtab") |
49 | //usage: ) | 49 | //usage: ) |
50 | //usage: IF_FEATURE_MTAB_SUPPORT( | 50 | //usage: IF_FEATURE_MTAB_SUPPORT( |
51 | //usage: "\n -n Don't erase /etc/mtab entries" | 51 | //usage: "\n -n Don't erase /etc/mtab entries" |
52 | //usage: ) | 52 | //usage: ) |
53 | //usage: "\n -r Try to remount devices as read-only if mount is busy" | 53 | //usage: "\n -r Remount devices read-only if mount is busy" |
54 | //usage: "\n -l Lazy umount (detach filesystem)" | 54 | //usage: "\n -l Lazy umount (detach filesystem)" |
55 | //usage: "\n -f Force umount (i.e., unreachable NFS server)" | 55 | //usage: "\n -f Force umount (i.e., unreachable NFS server)" |
56 | //usage: IF_FEATURE_MOUNT_LOOP( | 56 | //usage: IF_FEATURE_MOUNT_LOOP( |
diff --git a/util-linux/unshare.c b/util-linux/unshare.c index 2087413e8..68ccdd874 100644 --- a/util-linux/unshare.c +++ b/util-linux/unshare.c | |||
@@ -23,7 +23,7 @@ | |||
23 | //kbuild:lib-$(CONFIG_UNSHARE) += unshare.o | 23 | //kbuild:lib-$(CONFIG_UNSHARE) += unshare.o |
24 | 24 | ||
25 | //usage:#define unshare_trivial_usage | 25 | //usage:#define unshare_trivial_usage |
26 | //usage: "[OPTIONS] [PROG [ARGS]]" | 26 | //usage: "[OPTIONS] [PROG ARGS]" |
27 | //usage:#define unshare_full_usage "\n" | 27 | //usage:#define unshare_full_usage "\n" |
28 | //usage: "\n -m,--mount[=FILE] Unshare mount namespace" | 28 | //usage: "\n -m,--mount[=FILE] Unshare mount namespace" |
29 | //usage: "\n -u,--uts[=FILE] Unshare UTS namespace (hostname etc.)" | 29 | //usage: "\n -u,--uts[=FILE] Unshare UTS namespace (hostname etc.)" |
@@ -31,8 +31,8 @@ | |||
31 | //usage: "\n -n,--net[=FILE] Unshare network namespace" | 31 | //usage: "\n -n,--net[=FILE] Unshare network namespace" |
32 | //usage: "\n -p,--pid[=FILE] Unshare PID namespace" | 32 | //usage: "\n -p,--pid[=FILE] Unshare PID namespace" |
33 | //usage: "\n -U,--user[=FILE] Unshare user namespace" | 33 | //usage: "\n -U,--user[=FILE] Unshare user namespace" |
34 | //usage: "\n -f,--fork Fork before execing PROG" | 34 | //usage: "\n -f Fork before execing PROG" |
35 | //usage: "\n -r,--map-root-user Map current user to root (implies -U)" | 35 | //usage: "\n -r Map current user to root (implies -U)" |
36 | //usage: "\n --mount-proc[=DIR] Mount /proc filesystem first (implies -m)" | 36 | //usage: "\n --mount-proc[=DIR] Mount /proc filesystem first (implies -m)" |
37 | //usage: "\n --propagation slave|shared|private|unchanged" | 37 | //usage: "\n --propagation slave|shared|private|unchanged" |
38 | //usage: "\n Modify mount propagation in mount namespace" | 38 | //usage: "\n Modify mount propagation in mount namespace" |
diff --git a/util-linux/volume_id/erofs.c b/util-linux/volume_id/erofs.c new file mode 100644 index 000000000..a163a353d --- /dev/null +++ b/util-linux/volume_id/erofs.c | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * volume_id - reads filesystem label and uuid | ||
3 | * | ||
4 | * Copyright (C) 2020 Norbert Lange <nolange79@gmail.com> | ||
5 | * | ||
6 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
7 | */ | ||
8 | //config:config FEATURE_VOLUMEID_EROFS | ||
9 | //config: bool "erofs filesystem" | ||
10 | //config: default y | ||
11 | //config: depends on VOLUMEID | ||
12 | //config: help | ||
13 | //config: Erofs is a compressed readonly filesystem for Linux. | ||
14 | |||
15 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_EROFS) += erofs.o | ||
16 | |||
17 | #include "volume_id_internal.h" | ||
18 | |||
19 | #define EROFS_SUPER_MAGIC_V1 0xE0F5E1E2 | ||
20 | #define EROFS_SUPER_OFFSET 1024 | ||
21 | #define EROFS_FEATURE_COMPAT_SB_CHKSUM 0x00000001 | ||
22 | |||
23 | /* 128-byte erofs on-disk super block */ | ||
24 | struct erofs_super_block { | ||
25 | uint32_t magic; /* file system magic number */ | ||
26 | uint32_t checksum; /* crc32c(super_block) */ | ||
27 | uint32_t feature_compat; | ||
28 | uint8_t blkszbits; /* support block_size == PAGE_SIZE only */ | ||
29 | uint8_t reserved; | ||
30 | |||
31 | uint16_t root_nid; /* nid of root directory */ | ||
32 | uint64_t inos; /* total valid ino # (== f_files - f_favail) */ | ||
33 | |||
34 | uint64_t build_time; /* inode v1 time derivation */ | ||
35 | uint32_t build_time_nsec; /* inode v1 time derivation in nano scale */ | ||
36 | uint32_t blocks; /* used for statfs */ | ||
37 | uint32_t meta_blkaddr; /* start block address of metadata area */ | ||
38 | uint32_t xattr_blkaddr; /* start block address of shared xattr area */ | ||
39 | uint8_t uuid[16]; /* 128-bit uuid for volume */ | ||
40 | uint8_t volume_name[16]; /* volume name */ | ||
41 | uint32_t feature_incompat; | ||
42 | uint8_t reserved2[44]; | ||
43 | } PACKED; | ||
44 | |||
45 | int FAST_FUNC volume_id_probe_erofs(struct volume_id *id /*,uint64_t off*/) | ||
46 | { | ||
47 | struct erofs_super_block *sb; | ||
48 | |||
49 | BUILD_BUG_ON(sizeof(struct erofs_super_block) != 128); | ||
50 | |||
51 | dbg("erofs: probing at offset 0x%llx", EROFS_SUPER_OFFSET); | ||
52 | sb = volume_id_get_buffer(id, EROFS_SUPER_OFFSET, sizeof(*sb)); | ||
53 | if (!sb) | ||
54 | return -1; | ||
55 | |||
56 | if (sb->magic != cpu_to_le32(EROFS_SUPER_MAGIC_V1)) | ||
57 | return -1; | ||
58 | |||
59 | IF_FEATURE_BLKID_TYPE(id->type = "erofs"); | ||
60 | |||
61 | volume_id_set_label_string(id, sb->volume_name, | ||
62 | MIN(sizeof(sb->volume_name), VOLUME_ID_LABEL_SIZE)); | ||
63 | |||
64 | volume_id_set_uuid(id, sb->uuid, UUID_DCE); | ||
65 | |||
66 | return 0; | ||
67 | } | ||
diff --git a/util-linux/volume_id/volume_id.c b/util-linux/volume_id/volume_id.c index c3f07a741..8ceb61bde 100644 --- a/util-linux/volume_id/volume_id.c +++ b/util-linux/volume_id/volume_id.c | |||
@@ -49,7 +49,7 @@ | |||
49 | typedef int FAST_FUNC (*raid_probe_fptr)(struct volume_id *id, /*uint64_t off,*/ uint64_t size); | 49 | typedef int FAST_FUNC (*raid_probe_fptr)(struct volume_id *id, /*uint64_t off,*/ uint64_t size); |
50 | typedef int FAST_FUNC (*probe_fptr)(struct volume_id *id /*, uint64_t off*/); | 50 | typedef int FAST_FUNC (*probe_fptr)(struct volume_id *id /*, uint64_t off*/); |
51 | 51 | ||
52 | static const raid_probe_fptr raid1[] = { | 52 | static const raid_probe_fptr raid1[] ALIGN_PTR = { |
53 | #if ENABLE_FEATURE_VOLUMEID_LINUXRAID | 53 | #if ENABLE_FEATURE_VOLUMEID_LINUXRAID |
54 | volume_id_probe_linux_raid, | 54 | volume_id_probe_linux_raid, |
55 | #endif | 55 | #endif |
@@ -76,7 +76,7 @@ static const raid_probe_fptr raid1[] = { | |||
76 | #endif | 76 | #endif |
77 | }; | 77 | }; |
78 | 78 | ||
79 | static const probe_fptr raid2[] = { | 79 | static const probe_fptr raid2[] ALIGN_PTR = { |
80 | #if ENABLE_FEATURE_VOLUMEID_LVM | 80 | #if ENABLE_FEATURE_VOLUMEID_LVM |
81 | volume_id_probe_lvm1, | 81 | volume_id_probe_lvm1, |
82 | volume_id_probe_lvm2, | 82 | volume_id_probe_lvm2, |
@@ -90,7 +90,7 @@ static const probe_fptr raid2[] = { | |||
90 | }; | 90 | }; |
91 | 91 | ||
92 | /* signature in the first block, only small buffer needed */ | 92 | /* signature in the first block, only small buffer needed */ |
93 | static const probe_fptr fs1[] = { | 93 | static const probe_fptr fs1[] ALIGN_PTR = { |
94 | #if ENABLE_FEATURE_VOLUMEID_FAT | 94 | #if ENABLE_FEATURE_VOLUMEID_FAT |
95 | volume_id_probe_vfat, | 95 | volume_id_probe_vfat, |
96 | #endif | 96 | #endif |
@@ -106,6 +106,9 @@ static const probe_fptr fs1[] = { | |||
106 | #if ENABLE_FEATURE_VOLUMEID_SQUASHFS | 106 | #if ENABLE_FEATURE_VOLUMEID_SQUASHFS |
107 | volume_id_probe_squashfs, | 107 | volume_id_probe_squashfs, |
108 | #endif | 108 | #endif |
109 | #if ENABLE_FEATURE_VOLUMEID_EROFS | ||
110 | volume_id_probe_erofs, | ||
111 | #endif | ||
109 | #if ENABLE_FEATURE_VOLUMEID_XFS | 112 | #if ENABLE_FEATURE_VOLUMEID_XFS |
110 | volume_id_probe_xfs, | 113 | volume_id_probe_xfs, |
111 | #endif | 114 | #endif |
@@ -115,7 +118,7 @@ static const probe_fptr fs1[] = { | |||
115 | }; | 118 | }; |
116 | 119 | ||
117 | /* fill buffer with maximum */ | 120 | /* fill buffer with maximum */ |
118 | static const probe_fptr fs2[] = { | 121 | static const probe_fptr fs2[] ALIGN_PTR = { |
119 | #if ENABLE_FEATURE_VOLUMEID_LINUXSWAP | 122 | #if ENABLE_FEATURE_VOLUMEID_LINUXSWAP |
120 | volume_id_probe_linux_swap, | 123 | volume_id_probe_linux_swap, |
121 | #endif | 124 | #endif |
diff --git a/util-linux/volume_id/volume_id_internal.h b/util-linux/volume_id/volume_id_internal.h index ada18339d..b1e44481f 100644 --- a/util-linux/volume_id/volume_id_internal.h +++ b/util-linux/volume_id/volume_id_internal.h | |||
@@ -66,6 +66,9 @@ struct volume_id { | |||
66 | uint8_t *sbbuf; | 66 | uint8_t *sbbuf; |
67 | uint8_t *seekbuf; | 67 | uint8_t *seekbuf; |
68 | uint64_t seekbuf_off; | 68 | uint64_t seekbuf_off; |
69 | #if ENABLE_FEATURE_BLKID_TYPE | ||
70 | const char *type; | ||
71 | #endif | ||
69 | #ifdef UNUSED_PARTITION_CODE | 72 | #ifdef UNUSED_PARTITION_CODE |
70 | struct volume_id_partition *partitions; | 73 | struct volume_id_partition *partitions; |
71 | size_t partition_count; | 74 | size_t partition_count; |
@@ -80,9 +83,6 @@ struct volume_id { | |||
80 | // char type_version[VOLUME_ID_FORMAT_SIZE]; | 83 | // char type_version[VOLUME_ID_FORMAT_SIZE]; |
81 | // smallint usage_id; | 84 | // smallint usage_id; |
82 | // const char *usage; | 85 | // const char *usage; |
83 | #if ENABLE_FEATURE_BLKID_TYPE | ||
84 | const char *type; | ||
85 | #endif | ||
86 | }; | 86 | }; |
87 | 87 | ||
88 | struct volume_id* FAST_FUNC volume_id_open_node(int fd); | 88 | struct volume_id* FAST_FUNC volume_id_open_node(int fd); |
@@ -215,6 +215,8 @@ int FAST_FUNC volume_id_probe_romfs(struct volume_id *id /*,uint64_t off*/); | |||
215 | 215 | ||
216 | int FAST_FUNC volume_id_probe_squashfs(struct volume_id *id /*,uint64_t off*/); | 216 | int FAST_FUNC volume_id_probe_squashfs(struct volume_id *id /*,uint64_t off*/); |
217 | 217 | ||
218 | int FAST_FUNC volume_id_probe_erofs(struct volume_id *id /*,uint64_t off*/); | ||
219 | |||
218 | int FAST_FUNC volume_id_probe_sysv(struct volume_id *id /*,uint64_t off*/); | 220 | int FAST_FUNC volume_id_probe_sysv(struct volume_id *id /*,uint64_t off*/); |
219 | 221 | ||
220 | int FAST_FUNC volume_id_probe_udf(struct volume_id *id /*,uint64_t off*/); | 222 | int FAST_FUNC volume_id_probe_udf(struct volume_id *id /*,uint64_t off*/); |