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*/); |
