diff options
author | Ron Yorston <rmy@pobox.com> | 2018-03-15 08:49:48 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-03-15 08:49:48 +0000 |
commit | 6fe4ad9a6c96624c2b75c0d51b035bc1a71d9eba (patch) | |
tree | bb7620a3217f5adf6fb5f3358b2b89a97331b5e8 | |
parent | f3d24e08a385a68c4bacb284bd8a8e3da7f0f4b3 (diff) | |
parent | bbe47d9b9aee3824845f1ce08c9caeb262c15059 (diff) | |
download | busybox-w32-6fe4ad9a6c96624c2b75c0d51b035bc1a71d9eba.tar.gz busybox-w32-6fe4ad9a6c96624c2b75c0d51b035bc1a71d9eba.tar.bz2 busybox-w32-6fe4ad9a6c96624c2b75c0d51b035bc1a71d9eba.zip |
Merge branch 'busybox' into merge
46 files changed, 500 insertions, 323 deletions
diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c index ccdfd6855..871145143 100644 --- a/coreutils/md5_sha1_sum.c +++ b/coreutils/md5_sha1_sum.c | |||
@@ -9,7 +9,7 @@ | |||
9 | //config: bool "md5sum (6.8 kb)" | 9 | //config: bool "md5sum (6.8 kb)" |
10 | //config: default y | 10 | //config: default y |
11 | //config: help | 11 | //config: help |
12 | //config: md5sum is used to print or check MD5 checksums. | 12 | //config: Compute and check MD5 message digest |
13 | //config: | 13 | //config: |
14 | //config:config SHA1SUM | 14 | //config:config SHA1SUM |
15 | //config: bool "sha1sum (6 kb)" | 15 | //config: bool "sha1sum (6 kb)" |
diff --git a/examples/var_service/dhcpd_if/run b/examples/var_service/dhcpd_if/run index de85dece0..a603bdc71 100755 --- a/examples/var_service/dhcpd_if/run +++ b/examples/var_service/dhcpd_if/run | |||
@@ -11,13 +11,13 @@ echo "* Upping iface $if" | |||
11 | ip link set dev $if up | 11 | ip link set dev $if up |
12 | 12 | ||
13 | >>udhcpd.leases | 13 | >>udhcpd.leases |
14 | sed 's/^interface.*$/interface '"$if/" -i udhcpc.conf | 14 | sed 's/^interface.*$/interface '"$if/" -i udhcpd.conf |
15 | 15 | ||
16 | echo "* Starting udhcpd" | 16 | echo "* Starting udhcpd" |
17 | exec \ | 17 | exec \ |
18 | env - PATH="$PATH" \ | 18 | env - PATH="$PATH" \ |
19 | softlimit \ | 19 | softlimit \ |
20 | setuidgid root \ | 20 | setuidgid root \ |
21 | udhcpd -f -vv udhcpc.conf | 21 | udhcpd -f -vv udhcpd.conf |
22 | 22 | ||
23 | exit $? | 23 | exit $? |
diff --git a/examples/var_service/dhcpd_if/udhcpc.conf b/examples/var_service/dhcpd_if/udhcpd.conf index a81925970..a81925970 100644 --- a/examples/var_service/dhcpd_if/udhcpc.conf +++ b/examples/var_service/dhcpd_if/udhcpd.conf | |||
diff --git a/include/libbb.h b/include/libbb.h index e816a2726..2c0e02971 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -1415,7 +1415,7 @@ struct hwtype { | |||
1415 | int FAST_FUNC (*activate)(int fd); | 1415 | int FAST_FUNC (*activate)(int fd); |
1416 | int suppress_null_addr; | 1416 | int suppress_null_addr; |
1417 | }; | 1417 | }; |
1418 | extern smallint interface_opt_a; | 1418 | #define IFNAME_SHOW_DOWNED_TOO ((char*)(intptr_t)1) |
1419 | int display_interfaces(char *ifname) FAST_FUNC; | 1419 | int display_interfaces(char *ifname) FAST_FUNC; |
1420 | int in_ether(const char *bufp, struct sockaddr *sap) FAST_FUNC; | 1420 | int in_ether(const char *bufp, struct sockaddr *sap) FAST_FUNC; |
1421 | #if ENABLE_FEATURE_HWIB | 1421 | #if ENABLE_FEATURE_HWIB |
diff --git a/libbb/missing_syscalls.c b/libbb/missing_syscalls.c index 093412811..87cf59b3d 100644 --- a/libbb/missing_syscalls.c +++ b/libbb/missing_syscalls.c | |||
@@ -3,14 +3,13 @@ | |||
3 | * | 3 | * |
4 | * Licensed under GPLv2, see file LICENSE in this source tree. | 4 | * Licensed under GPLv2, see file LICENSE in this source tree. |
5 | */ | 5 | */ |
6 | |||
7 | //kbuild:lib-y += missing_syscalls.o | 6 | //kbuild:lib-y += missing_syscalls.o |
8 | 7 | ||
9 | /*#include <linux/timex.h> - for struct timex, but may collide with <time.h> */ | ||
10 | #include <sys/syscall.h> | ||
11 | #include "libbb.h" | 8 | #include "libbb.h" |
12 | 9 | ||
13 | #if defined(ANDROID) || defined(__ANDROID__) | 10 | #if defined(ANDROID) || defined(__ANDROID__) |
11 | /*# include <linux/timex.h> - for struct timex, but may collide with <time.h> */ | ||
12 | # include <sys/syscall.h> | ||
14 | pid_t getsid(pid_t pid) | 13 | pid_t getsid(pid_t pid) |
15 | { | 14 | { |
16 | return syscall(__NR_getsid, pid); | 15 | return syscall(__NR_getsid, pid); |
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 1c24f0d10..569a6fc34 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c | |||
@@ -14,14 +14,6 @@ | |||
14 | * | 14 | * |
15 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 15 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
16 | */ | 16 | */ |
17 | #include <sys/prctl.h> | ||
18 | #ifndef PR_SET_NAME | ||
19 | #define PR_SET_NAME 15 | ||
20 | #endif | ||
21 | #ifndef PR_GET_NAME | ||
22 | #define PR_GET_NAME 16 | ||
23 | #endif | ||
24 | |||
25 | #include "busybox.h" /* uses applet tables */ | 17 | #include "busybox.h" /* uses applet tables */ |
26 | #include "NUM_APPLETS.h" | 18 | #include "NUM_APPLETS.h" |
27 | 19 | ||
@@ -29,6 +21,13 @@ | |||
29 | #define NOEXEC_SUPPORT ((NUM_APPLETS > 1) && (ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE)) | 21 | #define NOEXEC_SUPPORT ((NUM_APPLETS > 1) && (ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE)) |
30 | 22 | ||
31 | #if defined(__linux__) && (NUM_APPLETS > 1) | 23 | #if defined(__linux__) && (NUM_APPLETS > 1) |
24 | # include <sys/prctl.h> | ||
25 | # ifndef PR_SET_NAME | ||
26 | # define PR_SET_NAME 15 | ||
27 | # endif | ||
28 | # ifndef PR_GET_NAME | ||
29 | # define PR_GET_NAME 16 | ||
30 | # endif | ||
32 | void FAST_FUNC set_task_comm(const char *comm) | 31 | void FAST_FUNC set_task_comm(const char *comm) |
33 | { | 32 | { |
34 | /* okay if too long (truncates) */ | 33 | /* okay if too long (truncates) */ |
diff --git a/networking/httpd.c b/networking/httpd.c index 74196a4f1..9439e206c 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -1046,6 +1046,7 @@ static void send_headers(int responseNum) | |||
1046 | /* Fixed size 29-byte string. Example: Sun, 06 Nov 1994 08:49:37 GMT */ | 1046 | /* Fixed size 29-byte string. Example: Sun, 06 Nov 1994 08:49:37 GMT */ |
1047 | char date_str[40]; /* using a bit larger buffer to paranoia reasons */ | 1047 | char date_str[40]; /* using a bit larger buffer to paranoia reasons */ |
1048 | 1048 | ||
1049 | struct tm tm; | ||
1049 | const char *responseString = ""; | 1050 | const char *responseString = ""; |
1050 | const char *infoString = NULL; | 1051 | const char *infoString = NULL; |
1051 | #if ENABLE_FEATURE_HTTPD_ERROR_PAGES | 1052 | #if ENABLE_FEATURE_HTTPD_ERROR_PAGES |
@@ -1074,7 +1075,8 @@ static void send_headers(int responseNum) | |||
1074 | * always fit into those kbytes. | 1075 | * always fit into those kbytes. |
1075 | */ | 1076 | */ |
1076 | 1077 | ||
1077 | strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime(&timer)); | 1078 | strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime_r(&timer, &tm)); |
1079 | /* ^^^ using gmtime_r() instead of gmtime() to not use static data */ | ||
1078 | len = sprintf(iobuf, | 1080 | len = sprintf(iobuf, |
1079 | "HTTP/1.0 %d %s\r\n" | 1081 | "HTTP/1.0 %d %s\r\n" |
1080 | "Content-type: %s\r\n" | 1082 | "Content-type: %s\r\n" |
@@ -1128,7 +1130,7 @@ static void send_headers(int responseNum) | |||
1128 | #endif | 1130 | #endif |
1129 | 1131 | ||
1130 | if (file_size != -1) { /* file */ | 1132 | if (file_size != -1) { /* file */ |
1131 | strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime(&last_mod)); | 1133 | strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime_r(&last_mod, &tm)); |
1132 | #if ENABLE_FEATURE_HTTPD_RANGES | 1134 | #if ENABLE_FEATURE_HTTPD_RANGES |
1133 | if (responseNum == HTTP_PARTIAL_CONTENT) { | 1135 | if (responseNum == HTTP_PARTIAL_CONTENT) { |
1134 | len += sprintf(iobuf + len, | 1136 | len += sprintf(iobuf + len, |
diff --git a/networking/ifconfig.c b/networking/ifconfig.c index 61d91788a..5c47abc16 100644 --- a/networking/ifconfig.c +++ b/networking/ifconfig.c | |||
@@ -338,6 +338,7 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv) | |||
338 | char *p; | 338 | char *p; |
339 | /*char host[128];*/ | 339 | /*char host[128];*/ |
340 | const char *host = NULL; /* make gcc happy */ | 340 | const char *host = NULL; /* make gcc happy */ |
341 | IF_FEATURE_IFCONFIG_STATUS(char *show_all_param;) | ||
341 | 342 | ||
342 | did_flags = 0; | 343 | did_flags = 0; |
343 | #if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS | 344 | #if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS |
@@ -349,15 +350,16 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv) | |||
349 | ++argv; | 350 | ++argv; |
350 | 351 | ||
351 | #if ENABLE_FEATURE_IFCONFIG_STATUS | 352 | #if ENABLE_FEATURE_IFCONFIG_STATUS |
352 | if (argv[0] && (argv[0][0] == '-' && argv[0][1] == 'a' && !argv[0][2])) { | 353 | show_all_param = NULL; |
353 | interface_opt_a = 1; | 354 | if (argv[0] && argv[0][0] == '-' && argv[0][1] == 'a' && !argv[0][2]) { |
354 | ++argv; | 355 | ++argv; |
356 | show_all_param = IFNAME_SHOW_DOWNED_TOO; | ||
355 | } | 357 | } |
356 | #endif | 358 | #endif |
357 | 359 | ||
358 | if (!argv[0] || !argv[1]) { /* one or no args */ | 360 | if (!argv[0] || !argv[1]) { /* one or no args */ |
359 | #if ENABLE_FEATURE_IFCONFIG_STATUS | 361 | #if ENABLE_FEATURE_IFCONFIG_STATUS |
360 | return display_interfaces(argv[0] /* can be NULL */); | 362 | return display_interfaces(argv[0] ? argv[0] : show_all_param); |
361 | #else | 363 | #else |
362 | bb_error_msg_and_die("no support for status display"); | 364 | bb_error_msg_and_die("no support for status display"); |
363 | #endif | 365 | #endif |
diff --git a/networking/interface.c b/networking/interface.c index 89427f2f4..e5e55d8d4 100644 --- a/networking/interface.c +++ b/networking/interface.c | |||
@@ -318,31 +318,37 @@ struct interface { | |||
318 | char name[IFNAMSIZ]; /* interface name */ | 318 | char name[IFNAMSIZ]; /* interface name */ |
319 | short type; /* if type */ | 319 | short type; /* if type */ |
320 | short flags; /* various flags */ | 320 | short flags; /* various flags */ |
321 | int tx_queue_len; /* transmit queue length */ | ||
322 | |||
323 | /* these should be contiguous, zeroed in one go in if_fetch(): */ | ||
324 | #define FIRST_TO_ZERO metric | ||
321 | int metric; /* routing metric */ | 325 | int metric; /* routing metric */ |
322 | int mtu; /* MTU value */ | 326 | int mtu; /* MTU value */ |
323 | int tx_queue_len; /* transmit queue length */ | ||
324 | struct ifmap map; /* hardware setup */ | 327 | struct ifmap map; /* hardware setup */ |
325 | struct sockaddr addr; /* IP address */ | 328 | struct sockaddr addr; /* IP address */ |
326 | struct sockaddr dstaddr; /* P-P IP address */ | 329 | struct sockaddr dstaddr; /* P-P IP address */ |
327 | struct sockaddr broadaddr; /* IP broadcast address */ | 330 | struct sockaddr broadaddr; /* IP broadcast address */ |
328 | struct sockaddr netmask; /* IP network mask */ | 331 | struct sockaddr netmask; /* IP network mask */ |
329 | int has_ip; | ||
330 | char hwaddr[32]; /* HW address */ | 332 | char hwaddr[32]; /* HW address */ |
331 | int statistics_valid; | 333 | #define LAST_TO_ZERO hwaddr |
334 | |||
335 | smallint has_ip; | ||
336 | smallint statistics_valid; | ||
332 | struct user_net_device_stats stats; /* statistics */ | 337 | struct user_net_device_stats stats; /* statistics */ |
338 | #if 0 /* UNUSED */ | ||
333 | int keepalive; /* keepalive value for SLIP */ | 339 | int keepalive; /* keepalive value for SLIP */ |
334 | int outfill; /* outfill value for SLIP */ | 340 | int outfill; /* outfill value for SLIP */ |
341 | #endif | ||
335 | }; | 342 | }; |
336 | 343 | ||
337 | 344 | struct iface_list { | |
338 | smallint interface_opt_a; /* show all interfaces */ | 345 | struct interface *int_list, *int_last; |
339 | 346 | }; | |
340 | static struct interface *int_list, *int_last; | ||
341 | 347 | ||
342 | 348 | ||
343 | #if 0 | 349 | #if 0 |
344 | /* like strcmp(), but knows about numbers */ | 350 | /* like strcmp(), but knows about numbers */ |
345 | except that the freshly added calls to xatoul() brf on ethernet aliases with | 351 | except that the freshly added calls to xatoul() barf on ethernet aliases with |
346 | uClibc with e.g.: ife->name='lo' name='eth0:1' | 352 | uClibc with e.g.: ife->name='lo' name='eth0:1' |
347 | static int nstrcmp(const char *a, const char *b) | 353 | static int nstrcmp(const char *a, const char *b) |
348 | { | 354 | { |
@@ -368,11 +374,11 @@ static int nstrcmp(const char *a, const char *b) | |||
368 | } | 374 | } |
369 | #endif | 375 | #endif |
370 | 376 | ||
371 | static struct interface *add_interface(char *name) | 377 | static struct interface *add_interface(struct iface_list *ilist, char *name) |
372 | { | 378 | { |
373 | struct interface *ife, **nextp, *new; | 379 | struct interface *ife, **nextp, *new; |
374 | 380 | ||
375 | for (ife = int_last; ife; ife = ife->prev) { | 381 | for (ife = ilist->int_last; ife; ife = ife->prev) { |
376 | int n = /*n*/strcmp(ife->name, name); | 382 | int n = /*n*/strcmp(ife->name, name); |
377 | 383 | ||
378 | if (n == 0) | 384 | if (n == 0) |
@@ -383,43 +389,43 @@ static struct interface *add_interface(char *name) | |||
383 | 389 | ||
384 | new = xzalloc(sizeof(*new)); | 390 | new = xzalloc(sizeof(*new)); |
385 | strncpy_IFNAMSIZ(new->name, name); | 391 | strncpy_IFNAMSIZ(new->name, name); |
386 | nextp = ife ? &ife->next : &int_list; | 392 | |
393 | nextp = ife ? &ife->next : &ilist->int_list; | ||
387 | new->prev = ife; | 394 | new->prev = ife; |
388 | new->next = *nextp; | 395 | new->next = *nextp; |
389 | if (new->next) | 396 | if (new->next) |
390 | new->next->prev = new; | 397 | new->next->prev = new; |
391 | else | 398 | else |
392 | int_last = new; | 399 | ilist->int_last = new; |
393 | *nextp = new; | 400 | *nextp = new; |
394 | return new; | 401 | return new; |
395 | } | 402 | } |
396 | 403 | ||
397 | static char *get_name(char *name, char *p) | 404 | static char *get_name(char name[IFNAMSIZ], char *p) |
398 | { | 405 | { |
399 | /* Extract <name> from nul-terminated p where p matches | 406 | /* Extract NAME from nul-terminated p of the form "<whitespace>NAME:" |
400 | * <name>: after leading whitespace. | 407 | * If match is not made, set NAME to "" and return unchanged p. |
401 | * If match is not made, set name empty and return unchanged p | ||
402 | */ | 408 | */ |
403 | char *nameend; | 409 | char *nameend; |
404 | char *namestart = skip_whitespace(p); | 410 | char *namestart; |
405 | 411 | ||
406 | nameend = namestart; | 412 | nameend = namestart = skip_whitespace(p); |
407 | while (*nameend && *nameend != ':' && !isspace(*nameend)) | 413 | |
408 | nameend++; | 414 | for (;;) { |
409 | if (*nameend == ':') { | 415 | if ((nameend - namestart) >= IFNAMSIZ) |
410 | if ((nameend - namestart) < IFNAMSIZ) { | 416 | break; /* interface name too large - return "" */ |
417 | if (*nameend == ':') { | ||
411 | memcpy(name, namestart, nameend - namestart); | 418 | memcpy(name, namestart, nameend - namestart); |
412 | name[nameend - namestart] = '\0'; | 419 | name[nameend - namestart] = '\0'; |
413 | p = nameend; | 420 | return nameend + 1; |
414 | } else { | ||
415 | /* Interface name too large */ | ||
416 | name[0] = '\0'; | ||
417 | } | 421 | } |
418 | } else { | 422 | nameend++; |
419 | /* trailing ':' not found - return empty */ | 423 | /* isspace, NUL, any control char? */ |
420 | name[0] = '\0'; | 424 | if ((unsigned char)*nameend <= (unsigned char)' ') |
425 | break; /* trailing ':' not found - return "" */ | ||
421 | } | 426 | } |
422 | return p + 1; | 427 | name[0] = '\0'; |
428 | return p; | ||
423 | } | 429 | } |
424 | 430 | ||
425 | /* If scanf supports size qualifiers for %n conversions, then we can | 431 | /* If scanf supports size qualifiers for %n conversions, then we can |
@@ -435,7 +441,10 @@ static char *get_name(char *name, char *p) | |||
435 | /* "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" */ | 441 | /* "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" */ |
436 | /* }; */ | 442 | /* }; */ |
437 | 443 | ||
438 | /* Lie about the size of the int pointed to for %n. */ | 444 | /* We use %n for unavailable data in older versions of /proc/net/dev formats. |
445 | * This results in bogus stores to ife->FOO members corresponding to | ||
446 | * %n specifiers (even the size of integers may not match). | ||
447 | */ | ||
439 | #if INT_MAX == LONG_MAX | 448 | #if INT_MAX == LONG_MAX |
440 | static const char *const ss_fmt[] = { | 449 | static const char *const ss_fmt[] = { |
441 | "%n%llu%u%u%u%u%n%n%n%llu%u%u%u%u%u", | 450 | "%n%llu%u%u%u%u%n%n%n%llu%u%u%u%u%u", |
@@ -448,7 +457,6 @@ static const char *const ss_fmt[] = { | |||
448 | "%llu%llu%lu%lu%lu%lu%n%n%llu%llu%lu%lu%lu%lu%lu", | 457 | "%llu%llu%lu%lu%lu%lu%n%n%llu%llu%lu%lu%lu%lu%lu", |
449 | "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" | 458 | "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" |
450 | }; | 459 | }; |
451 | |||
452 | #endif | 460 | #endif |
453 | 461 | ||
454 | static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn) | 462 | static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn) |
@@ -456,22 +464,22 @@ static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn) | |||
456 | memset(&ife->stats, 0, sizeof(struct user_net_device_stats)); | 464 | memset(&ife->stats, 0, sizeof(struct user_net_device_stats)); |
457 | 465 | ||
458 | sscanf(bp, ss_fmt[procnetdev_vsn], | 466 | sscanf(bp, ss_fmt[procnetdev_vsn], |
459 | &ife->stats.rx_bytes, /* missing for 0 */ | 467 | &ife->stats.rx_bytes, /* missing for v0 */ |
460 | &ife->stats.rx_packets, | 468 | &ife->stats.rx_packets, |
461 | &ife->stats.rx_errors, | 469 | &ife->stats.rx_errors, |
462 | &ife->stats.rx_dropped, | 470 | &ife->stats.rx_dropped, |
463 | &ife->stats.rx_fifo_errors, | 471 | &ife->stats.rx_fifo_errors, |
464 | &ife->stats.rx_frame_errors, | 472 | &ife->stats.rx_frame_errors, |
465 | &ife->stats.rx_compressed, /* missing for <= 1 */ | 473 | &ife->stats.rx_compressed, /* missing for v0, v1 */ |
466 | &ife->stats.rx_multicast, /* missing for <= 1 */ | 474 | &ife->stats.rx_multicast, /* missing for v0, v1 */ |
467 | &ife->stats.tx_bytes, /* missing for 0 */ | 475 | &ife->stats.tx_bytes, /* missing for v0 */ |
468 | &ife->stats.tx_packets, | 476 | &ife->stats.tx_packets, |
469 | &ife->stats.tx_errors, | 477 | &ife->stats.tx_errors, |
470 | &ife->stats.tx_dropped, | 478 | &ife->stats.tx_dropped, |
471 | &ife->stats.tx_fifo_errors, | 479 | &ife->stats.tx_fifo_errors, |
472 | &ife->stats.collisions, | 480 | &ife->stats.collisions, |
473 | &ife->stats.tx_carrier_errors, | 481 | &ife->stats.tx_carrier_errors, |
474 | &ife->stats.tx_compressed /* missing for <= 1 */ | 482 | &ife->stats.tx_compressed /* missing for v0, v1 */ |
475 | ); | 483 | ); |
476 | 484 | ||
477 | if (procnetdev_vsn <= 1) { | 485 | if (procnetdev_vsn <= 1) { |
@@ -494,31 +502,25 @@ static int procnetdev_version(char *buf) | |||
494 | return 0; | 502 | return 0; |
495 | } | 503 | } |
496 | 504 | ||
497 | static int if_readconf(void) | 505 | static void if_readconf(struct iface_list *ilist) |
498 | { | 506 | { |
499 | int numreqs = 30; | 507 | int numreqs = 30; |
500 | struct ifconf ifc; | 508 | struct ifconf ifc; |
501 | struct ifreq *ifr; | 509 | struct ifreq *ifr; |
502 | int n, err = -1; | 510 | int n; |
503 | int skfd; | 511 | int skfd; |
504 | 512 | ||
505 | ifc.ifc_buf = NULL; | 513 | ifc.ifc_buf = NULL; |
506 | 514 | ||
507 | /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets | 515 | /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets |
508 | (as of 2.1.128) */ | 516 | (as of 2.1.128) */ |
509 | skfd = socket(AF_INET, SOCK_DGRAM, 0); | 517 | skfd = xsocket(AF_INET, SOCK_DGRAM, 0); |
510 | if (skfd < 0) { | ||
511 | bb_perror_msg("error: no inet socket available"); | ||
512 | return -1; | ||
513 | } | ||
514 | 518 | ||
515 | for (;;) { | 519 | for (;;) { |
516 | ifc.ifc_len = sizeof(struct ifreq) * numreqs; | 520 | ifc.ifc_len = sizeof(struct ifreq) * numreqs; |
517 | ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len); | 521 | ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len); |
518 | 522 | ||
519 | if (ioctl_or_warn(skfd, SIOCGIFCONF, &ifc) < 0) { | 523 | xioctl(skfd, SIOCGIFCONF, &ifc); |
520 | goto out; | ||
521 | } | ||
522 | if (ifc.ifc_len == (int)(sizeof(struct ifreq) * numreqs)) { | 524 | if (ifc.ifc_len == (int)(sizeof(struct ifreq) * numreqs)) { |
523 | /* assume it overflowed and try again */ | 525 | /* assume it overflowed and try again */ |
524 | numreqs += 10; | 526 | numreqs += 10; |
@@ -529,67 +531,54 @@ static int if_readconf(void) | |||
529 | 531 | ||
530 | ifr = ifc.ifc_req; | 532 | ifr = ifc.ifc_req; |
531 | for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) { | 533 | for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) { |
532 | add_interface(ifr->ifr_name); | 534 | add_interface(ilist, ifr->ifr_name); |
533 | ifr++; | 535 | ifr++; |
534 | } | 536 | } |
535 | err = 0; | ||
536 | 537 | ||
537 | out: | ||
538 | close(skfd); | 538 | close(skfd); |
539 | free(ifc.ifc_buf); | 539 | free(ifc.ifc_buf); |
540 | return err; | ||
541 | } | 540 | } |
542 | 541 | ||
543 | static int if_readlist_proc(char *target) | 542 | static int if_readlist_proc(struct iface_list *ilist, char *ifname) |
544 | { | 543 | { |
545 | static smallint proc_read; | ||
546 | |||
547 | FILE *fh; | 544 | FILE *fh; |
548 | char buf[512]; | 545 | char buf[512]; |
549 | struct interface *ife; | 546 | struct interface *ife; |
550 | int err, procnetdev_vsn; | 547 | int procnetdev_vsn; |
551 | 548 | int ret; | |
552 | if (proc_read) | ||
553 | return 0; | ||
554 | if (!target) | ||
555 | proc_read = 1; | ||
556 | 549 | ||
557 | fh = fopen_or_warn(_PATH_PROCNET_DEV, "r"); | 550 | fh = fopen_or_warn(_PATH_PROCNET_DEV, "r"); |
558 | if (!fh) { | 551 | if (!fh) { |
559 | return if_readconf(); | 552 | return 0; /* "not found" */ |
560 | } | 553 | } |
561 | fgets(buf, sizeof buf, fh); /* eat line */ | 554 | fgets(buf, sizeof buf, fh); /* eat line */ |
562 | fgets(buf, sizeof buf, fh); | 555 | fgets(buf, sizeof buf, fh); |
563 | 556 | ||
564 | procnetdev_vsn = procnetdev_version(buf); | 557 | procnetdev_vsn = procnetdev_version(buf); |
565 | 558 | ||
566 | err = 0; | 559 | ret = 0; |
567 | while (fgets(buf, sizeof buf, fh)) { | 560 | while (fgets(buf, sizeof buf, fh)) { |
568 | char *s, name[128]; | 561 | char *s, name[IFNAMSIZ]; |
569 | 562 | ||
570 | s = get_name(name, buf); | 563 | s = get_name(name, buf); |
571 | ife = add_interface(name); | 564 | ife = add_interface(ilist, name); |
572 | get_dev_fields(s, ife, procnetdev_vsn); | 565 | get_dev_fields(s, ife, procnetdev_vsn); |
573 | ife->statistics_valid = 1; | 566 | ife->statistics_valid = 1; |
574 | if (target && strcmp(target, name) == 0) | 567 | if (ifname && strcmp(ifname, name) == 0) { |
568 | ret = 1; /* found */ | ||
575 | break; | 569 | break; |
576 | } | 570 | } |
577 | if (ferror(fh)) { | ||
578 | bb_perror_msg(_PATH_PROCNET_DEV); | ||
579 | err = -1; | ||
580 | proc_read = 0; | ||
581 | } | 571 | } |
582 | fclose(fh); | 572 | fclose(fh); |
583 | return err; | 573 | return ret; |
584 | } | 574 | } |
585 | 575 | ||
586 | static int if_readlist(void) | 576 | static void if_readlist(struct iface_list *ilist, char *ifname) |
587 | { | 577 | { |
588 | int err = if_readlist_proc(NULL); | 578 | int found = if_readlist_proc(ilist, ifname); |
589 | /* Needed in order to get ethN:M aliases */ | 579 | /* Needed in order to get ethN:M aliases */ |
590 | if (!err) | 580 | if (!found) |
591 | err = if_readconf(); | 581 | if_readconf(ilist); |
592 | return err; | ||
593 | } | 582 | } |
594 | 583 | ||
595 | /* Fetch the interface configuration from the kernel. */ | 584 | /* Fetch the interface configuration from the kernel. */ |
@@ -608,24 +597,29 @@ static int if_fetch(struct interface *ife) | |||
608 | } | 597 | } |
609 | ife->flags = ifr.ifr_flags; | 598 | ife->flags = ifr.ifr_flags; |
610 | 599 | ||
600 | /* set up default values if ioctl's would fail */ | ||
601 | ife->tx_queue_len = -1; /* unknown value */ | ||
602 | memset(&ife->FIRST_TO_ZERO, 0, | ||
603 | offsetof(struct interface, LAST_TO_ZERO) | ||
604 | - offsetof(struct interface, FIRST_TO_ZERO) | ||
605 | + sizeof(ife->LAST_TO_ZERO) | ||
606 | ); | ||
607 | |||
611 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | 608 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
612 | memset(ife->hwaddr, 0, 32); | ||
613 | if (ioctl(skfd, SIOCGIFHWADDR, &ifr) >= 0) | 609 | if (ioctl(skfd, SIOCGIFHWADDR, &ifr) >= 0) |
614 | memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8); | 610 | memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8); |
615 | 611 | ||
612 | //er.... why this _isnt_ inside if()? | ||
616 | ife->type = ifr.ifr_hwaddr.sa_family; | 613 | ife->type = ifr.ifr_hwaddr.sa_family; |
617 | 614 | ||
618 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | 615 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
619 | ife->metric = 0; | ||
620 | if (ioctl(skfd, SIOCGIFMETRIC, &ifr) >= 0) | 616 | if (ioctl(skfd, SIOCGIFMETRIC, &ifr) >= 0) |
621 | ife->metric = ifr.ifr_metric; | 617 | ife->metric = ifr.ifr_metric; |
622 | 618 | ||
623 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | 619 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
624 | ife->mtu = 0; | ||
625 | if (ioctl(skfd, SIOCGIFMTU, &ifr) >= 0) | 620 | if (ioctl(skfd, SIOCGIFMTU, &ifr) >= 0) |
626 | ife->mtu = ifr.ifr_mtu; | 621 | ife->mtu = ifr.ifr_mtu; |
627 | 622 | ||
628 | memset(&ife->map, 0, sizeof(struct ifmap)); | ||
629 | #ifdef SIOCGIFMAP | 623 | #ifdef SIOCGIFMAP |
630 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | 624 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
631 | if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0) | 625 | if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0) |
@@ -634,31 +628,24 @@ static int if_fetch(struct interface *ife) | |||
634 | 628 | ||
635 | #ifdef HAVE_TXQUEUELEN | 629 | #ifdef HAVE_TXQUEUELEN |
636 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | 630 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
637 | ife->tx_queue_len = -1; /* unknown value */ | ||
638 | if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) >= 0) | 631 | if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) >= 0) |
639 | ife->tx_queue_len = ifr.ifr_qlen; | 632 | ife->tx_queue_len = ifr.ifr_qlen; |
640 | #else | ||
641 | ife->tx_queue_len = -1; /* unknown value */ | ||
642 | #endif | 633 | #endif |
643 | 634 | ||
644 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | 635 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
645 | ifr.ifr_addr.sa_family = AF_INET; | 636 | ifr.ifr_addr.sa_family = AF_INET; |
646 | memset(&ife->addr, 0, sizeof(struct sockaddr)); | ||
647 | if (ioctl(skfd, SIOCGIFADDR, &ifr) == 0) { | 637 | if (ioctl(skfd, SIOCGIFADDR, &ifr) == 0) { |
648 | ife->has_ip = 1; | 638 | ife->has_ip = 1; |
649 | ife->addr = ifr.ifr_addr; | 639 | ife->addr = ifr.ifr_addr; |
650 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | 640 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
651 | memset(&ife->dstaddr, 0, sizeof(struct sockaddr)); | ||
652 | if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) >= 0) | 641 | if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) >= 0) |
653 | ife->dstaddr = ifr.ifr_dstaddr; | 642 | ife->dstaddr = ifr.ifr_dstaddr; |
654 | 643 | ||
655 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | 644 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
656 | memset(&ife->broadaddr, 0, sizeof(struct sockaddr)); | ||
657 | if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) >= 0) | 645 | if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) >= 0) |
658 | ife->broadaddr = ifr.ifr_broadaddr; | 646 | ife->broadaddr = ifr.ifr_broadaddr; |
659 | 647 | ||
660 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | 648 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
661 | memset(&ife->netmask, 0, sizeof(struct sockaddr)); | ||
662 | if (ioctl(skfd, SIOCGIFNETMASK, &ifr) >= 0) | 649 | if (ioctl(skfd, SIOCGIFNETMASK, &ifr) >= 0) |
663 | ife->netmask = ifr.ifr_netmask; | 650 | ife->netmask = ifr.ifr_netmask; |
664 | } | 651 | } |
@@ -1020,10 +1007,12 @@ static void ife_print(struct interface *ptr) | |||
1020 | 1007 | ||
1021 | /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */ | 1008 | /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */ |
1022 | printf(" MTU:%d Metric:%d", ptr->mtu, ptr->metric ? ptr->metric : 1); | 1009 | printf(" MTU:%d Metric:%d", ptr->mtu, ptr->metric ? ptr->metric : 1); |
1010 | #if 0 | ||
1023 | #ifdef SIOCSKEEPALIVE | 1011 | #ifdef SIOCSKEEPALIVE |
1024 | if (ptr->outfill || ptr->keepalive) | 1012 | if (ptr->outfill || ptr->keepalive) |
1025 | printf(" Outfill:%d Keepalive:%d", ptr->outfill, ptr->keepalive); | 1013 | printf(" Outfill:%d Keepalive:%d", ptr->outfill, ptr->keepalive); |
1026 | #endif | 1014 | #endif |
1015 | #endif | ||
1027 | bb_putchar('\n'); | 1016 | bb_putchar('\n'); |
1028 | 1017 | ||
1029 | /* If needed, display the interface statistics. */ | 1018 | /* If needed, display the interface statistics. */ |
@@ -1077,67 +1066,44 @@ static void ife_print(struct interface *ptr) | |||
1077 | bb_putchar('\n'); | 1066 | bb_putchar('\n'); |
1078 | } | 1067 | } |
1079 | 1068 | ||
1080 | static int do_if_print(struct interface *ife) /*, int *opt_a)*/ | 1069 | static int do_if_print(struct interface *ife, int show_downed_too) |
1081 | { | 1070 | { |
1082 | int res; | 1071 | int res; |
1083 | 1072 | ||
1084 | res = do_if_fetch(ife); | 1073 | res = do_if_fetch(ife); |
1085 | if (res >= 0) { | 1074 | if (res >= 0) { |
1086 | if ((ife->flags & IFF_UP) || interface_opt_a) | 1075 | if ((ife->flags & IFF_UP) || show_downed_too) |
1087 | ife_print(ife); | 1076 | ife_print(ife); |
1088 | } | 1077 | } |
1089 | return res; | 1078 | return res; |
1090 | } | 1079 | } |
1091 | 1080 | ||
1092 | static struct interface *lookup_interface(char *name) | 1081 | int FAST_FUNC display_interfaces(char *ifname) |
1093 | { | ||
1094 | struct interface *ife = NULL; | ||
1095 | |||
1096 | if (if_readlist_proc(name) < 0) | ||
1097 | return NULL; | ||
1098 | ife = add_interface(name); | ||
1099 | return ife; | ||
1100 | } | ||
1101 | |||
1102 | #ifdef UNUSED | ||
1103 | static int for_all_interfaces(int (*doit) (struct interface *, void *), | ||
1104 | void *cookie) | ||
1105 | { | 1082 | { |
1106 | struct interface *ife; | 1083 | struct interface *ife; |
1084 | int res; | ||
1085 | struct iface_list ilist; | ||
1107 | 1086 | ||
1108 | if (!int_list && (if_readlist() < 0)) | 1087 | ilist.int_list = NULL; |
1109 | return -1; | 1088 | ilist.int_last = NULL; |
1110 | for (ife = int_list; ife; ife = ife->next) { | 1089 | if_readlist(&ilist, ifname != IFNAME_SHOW_DOWNED_TOO ? ifname : NULL); |
1111 | int err = doit(ife, cookie); | ||
1112 | if (err) | ||
1113 | return err; | ||
1114 | } | ||
1115 | return 0; | ||
1116 | } | ||
1117 | #endif | ||
1118 | 1090 | ||
1119 | /* for ipv4 add/del modes */ | 1091 | if (!ifname || ifname == IFNAME_SHOW_DOWNED_TOO) { |
1120 | static int if_print(char *ifname) | 1092 | for (ife = ilist.int_list; ife; ife = ife->next) { |
1121 | { | ||
1122 | struct interface *ife; | ||
1123 | int res; | ||
1124 | 1093 | ||
1125 | if (!ifname) { | 1094 | BUILD_BUG_ON((int)(intptr_t)IFNAME_SHOW_DOWNED_TOO != 1); |
1126 | /*res = for_all_interfaces(do_if_print, &interface_opt_a);*/ | 1095 | |
1127 | if (!int_list && (if_readlist() < 0)) | 1096 | res = do_if_print(ife, (int)(intptr_t)ifname); |
1128 | return -1; | 1097 | if (res < 0) |
1129 | for (ife = int_list; ife; ife = ife->next) { | 1098 | goto ret; |
1130 | int err = do_if_print(ife); /*, &interface_opt_a);*/ | ||
1131 | if (err) | ||
1132 | return err; | ||
1133 | } | 1099 | } |
1134 | return 0; | 1100 | return 0; |
1135 | } | 1101 | } |
1136 | ife = lookup_interface(ifname); | 1102 | |
1137 | res = do_if_fetch(ife); | 1103 | ife = add_interface(&ilist, ifname); |
1138 | if (res >= 0) | 1104 | res = do_if_print(ife, /*show_downed_too:*/ 1); |
1139 | ife_print(ife); | 1105 | ret: |
1140 | return res; | 1106 | return (res < 0); /* status < 0 == 1 -- error */ |
1141 | } | 1107 | } |
1142 | 1108 | ||
1143 | #if ENABLE_FEATURE_HWIB | 1109 | #if ENABLE_FEATURE_HWIB |
@@ -1153,12 +1119,3 @@ int FAST_FUNC in_ib(const char *bufp, struct sockaddr *sap) | |||
1153 | return 0; | 1119 | return 0; |
1154 | } | 1120 | } |
1155 | #endif | 1121 | #endif |
1156 | |||
1157 | int FAST_FUNC display_interfaces(char *ifname) | ||
1158 | { | ||
1159 | int status; | ||
1160 | |||
1161 | status = if_print(ifname); | ||
1162 | |||
1163 | return (status < 0); /* status < 0 == 1 -- error */ | ||
1164 | } | ||
diff --git a/networking/ip.c b/networking/ip.c index accf90759..9ecb99abb 100644 --- a/networking/ip.c +++ b/networking/ip.c | |||
@@ -157,7 +157,7 @@ | |||
157 | //usage:#define iplink_trivial_usage | 157 | //usage:#define iplink_trivial_usage |
158 | //usage: /*Usage:iplink*/"set IFACE [up|down] [arp on|off] [multicast on|off]\n" | 158 | //usage: /*Usage:iplink*/"set IFACE [up|down] [arp on|off] [multicast on|off]\n" |
159 | //usage: " [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]\n" | 159 | //usage: " [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]\n" |
160 | //usage: " [master IFACE | nomaster]\n" | 160 | //usage: " [master IFACE | nomaster]" |
161 | // * short help shows only "set" command, long help continues (with just one "\n") | 161 | // * short help shows only "set" command, long help continues (with just one "\n") |
162 | // * and shows all other commands: | 162 | // * and shows all other commands: |
163 | //usage:#define iplink_full_usage "\n" | 163 | //usage:#define iplink_full_usage "\n" |
diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c index d7f888176..9ec665b69 100644 --- a/networking/libiproute/ipaddress.c +++ b/networking/libiproute/ipaddress.c | |||
@@ -570,7 +570,10 @@ int FAST_FUNC ipaddr_list_or_flush(char **argv, int flush) | |||
570 | } | 570 | } |
571 | 571 | ||
572 | for (l = linfo; l; l = l->next) { | 572 | for (l = linfo; l; l = l->next) { |
573 | if (no_link || print_linkinfo(&l->h) == 0) { | 573 | if (no_link |
574 | || (oneline || print_linkinfo(&l->h) == 0) | ||
575 | /* ^^^^^^^^^ "ip -oneline a" does not print link info */ | ||
576 | ) { | ||
574 | struct ifinfomsg *ifi = NLMSG_DATA(&l->h); | 577 | struct ifinfomsg *ifi = NLMSG_DATA(&l->h); |
575 | if (G_filter.family != AF_PACKET) | 578 | if (G_filter.family != AF_PACKET) |
576 | print_selected_addrinfo(ifi->ifi_index, ainfo); | 579 | print_selected_addrinfo(ifi->ifi_index, ainfo); |
diff --git a/networking/ntpd.c b/networking/ntpd.c index 17e5c7da6..8205ab271 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c | |||
@@ -165,8 +165,12 @@ | |||
165 | * Using exact power of 2 (1/8) results in smaller code | 165 | * Using exact power of 2 (1/8) results in smaller code |
166 | */ | 166 | */ |
167 | #define SLEW_THRESHOLD 0.125 | 167 | #define SLEW_THRESHOLD 0.125 |
168 | //^^^^^^^^^^^^^^^^^^^^^^^^^^ TODO: man adjtimex about tmx.offset: | ||
169 | // "Since Linux 2.6.26, the supplied value is clamped to the range (-0.5s, +0.5s)" | ||
170 | // - can use this larger value instead? | ||
171 | |||
168 | /* Stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */ | 172 | /* Stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */ |
169 | #define WATCH_THRESHOLD 128 | 173 | //UNUSED: #define WATCH_THRESHOLD 128 |
170 | /* NB: set WATCH_THRESHOLD to ~60 when debugging to save time) */ | 174 | /* NB: set WATCH_THRESHOLD to ~60 when debugging to save time) */ |
171 | //UNUSED: #define PANIC_THRESHOLD 1000 /* panic threshold (sec) */ | 175 | //UNUSED: #define PANIC_THRESHOLD 1000 /* panic threshold (sec) */ |
172 | 176 | ||
@@ -419,6 +423,7 @@ struct globals { | |||
419 | uint8_t discipline_state; // doc calls it c.state | 423 | uint8_t discipline_state; // doc calls it c.state |
420 | uint8_t poll_exp; // s.poll | 424 | uint8_t poll_exp; // s.poll |
421 | int polladj_count; // c.count | 425 | int polladj_count; // c.count |
426 | int FREQHOLD_cnt; | ||
422 | long kernel_freq_drift; | 427 | long kernel_freq_drift; |
423 | peer_t *last_update_peer; | 428 | peer_t *last_update_peer; |
424 | double last_update_offset; // c.last | 429 | double last_update_offset; // c.last |
@@ -1034,6 +1039,7 @@ step_time(double offset) | |||
1034 | tval = tvn.tv_sec; | 1039 | tval = tvn.tv_sec; |
1035 | strftime_YYYYMMDDHHMMSS(buf, sizeof(buf), &tval); | 1040 | strftime_YYYYMMDDHHMMSS(buf, sizeof(buf), &tval); |
1036 | bb_error_msg("setting time to %s.%06u (offset %+fs)", buf, (unsigned)tvn.tv_usec, offset); | 1041 | bb_error_msg("setting time to %s.%06u (offset %+fs)", buf, (unsigned)tvn.tv_usec, offset); |
1042 | //maybe? G.FREQHOLD_cnt = 0; | ||
1037 | 1043 | ||
1038 | /* Correct various fields which contain time-relative values: */ | 1044 | /* Correct various fields which contain time-relative values: */ |
1039 | 1045 | ||
@@ -1709,39 +1715,96 @@ update_local_clock(peer_t *p) | |||
1709 | tmx.freq = G.discipline_freq_drift * 65536e6; | 1715 | tmx.freq = G.discipline_freq_drift * 65536e6; |
1710 | #endif | 1716 | #endif |
1711 | tmx.modes = ADJ_OFFSET | ADJ_STATUS | ADJ_TIMECONST;// | ADJ_MAXERROR | ADJ_ESTERROR; | 1717 | tmx.modes = ADJ_OFFSET | ADJ_STATUS | ADJ_TIMECONST;// | ADJ_MAXERROR | ADJ_ESTERROR; |
1712 | tmx.constant = (int)G.poll_exp - 4; | 1718 | |
1713 | /* EXPERIMENTAL. | ||
1714 | * The below if statement should be unnecessary, but... | ||
1715 | * It looks like Linux kernel's PLL is far too gentle in changing | ||
1716 | * tmx.freq in response to clock offset. Offset keeps growing | ||
1717 | * and eventually we fall back to smaller poll intervals. | ||
1718 | * We can make correction more aggressive (about x2) by supplying | ||
1719 | * PLL time constant which is one less than the real one. | ||
1720 | * To be on a safe side, let's do it only if offset is significantly | ||
1721 | * larger than jitter. | ||
1722 | */ | ||
1723 | if (G.offset_to_jitter_ratio >= TIMECONST_HACK_GATE) | ||
1724 | tmx.constant--; | ||
1725 | tmx.offset = (long)(offset * 1000000); /* usec */ | 1719 | tmx.offset = (long)(offset * 1000000); /* usec */ |
1726 | if (SLEW_THRESHOLD < STEP_THRESHOLD) { | 1720 | if (SLEW_THRESHOLD < STEP_THRESHOLD) { |
1727 | if (tmx.offset > (long)(SLEW_THRESHOLD * 1000000)) { | 1721 | if (tmx.offset > (long)(SLEW_THRESHOLD * 1000000)) { |
1728 | tmx.offset = (long)(SLEW_THRESHOLD * 1000000); | 1722 | tmx.offset = (long)(SLEW_THRESHOLD * 1000000); |
1729 | tmx.constant--; | ||
1730 | } | 1723 | } |
1731 | if (tmx.offset < -(long)(SLEW_THRESHOLD * 1000000)) { | 1724 | if (tmx.offset < -(long)(SLEW_THRESHOLD * 1000000)) { |
1732 | tmx.offset = -(long)(SLEW_THRESHOLD * 1000000); | 1725 | tmx.offset = -(long)(SLEW_THRESHOLD * 1000000); |
1733 | tmx.constant--; | ||
1734 | } | 1726 | } |
1735 | } | 1727 | } |
1736 | if (tmx.constant < 0) | ||
1737 | tmx.constant = 0; | ||
1738 | 1728 | ||
1739 | tmx.status = STA_PLL; | 1729 | tmx.status = STA_PLL; |
1730 | if (G.FREQHOLD_cnt != 0) { | ||
1731 | /* man adjtimex on STA_FREQHOLD: | ||
1732 | * "Normally adjustments made via ADJ_OFFSET result in dampened | ||
1733 | * frequency adjustments also being made. | ||
1734 | * This flag prevents the small frequency adjustment from being | ||
1735 | * made when correcting for an ADJ_OFFSET value." | ||
1736 | * | ||
1737 | * Use this flag for a few first adjustments at the beginning | ||
1738 | * of ntpd execution, otherwise even relatively small initial | ||
1739 | * offset tend to cause largish changes to in-kernel tmx.freq. | ||
1740 | * If ntpd was restarted due to e.g. switch to another network, | ||
1741 | * this destroys already well-established tmx.freq value. | ||
1742 | */ | ||
1743 | if (G.FREQHOLD_cnt < 0) { | ||
1744 | /* Initialize it */ | ||
1745 | // Example: a laptop whose clock runs slower when hibernated, | ||
1746 | // after wake up it still has good tmx.freq, but accumulated ~0.5 sec offset: | ||
1747 | // Run with code where initial G.FREQHOLD_cnt was always 8: | ||
1748 | //15:17:52.947 no valid datapoints, no peer selected | ||
1749 | //15:17:56.515 update from:<IP> offset:+0.485133 delay:0.157762 jitter:0.209310 clock drift:-1.393ppm tc:4 | ||
1750 | //15:17:57.719 update from:<IP> offset:+0.483825 delay:0.158070 jitter:0.181159 clock drift:-1.393ppm tc:4 | ||
1751 | //15:17:59.925 update from:<IP> offset:+0.479504 delay:0.158147 jitter:0.156657 clock drift:-1.393ppm tc:4 | ||
1752 | //15:18:33.322 update from:<IP> offset:+0.428119 delay:0.158317 jitter:0.138071 clock drift:-1.393ppm tc:4 | ||
1753 | //15:19:06.718 update from:<IP> offset:+0.376932 delay:0.158276 jitter:0.122075 clock drift:-1.393ppm tc:4 | ||
1754 | //15:19:39.114 update from:<IP> offset:+0.327022 delay:0.158384 jitter:0.108538 clock drift:-1.393ppm tc:4 | ||
1755 | //15:20:12.715 update from:<IP> offset:+0.275596 delay:0.158297 jitter:0.097292 clock drift:-1.393ppm tc:4 | ||
1756 | //15:20:45.111 update from:<IP> offset:+0.225715 delay:0.158271 jitter:0.087841 clock drift:-1.393ppm tc:4 | ||
1757 | // If allwed to continue, it would start increasing tmx.freq now. | ||
1758 | // Instead, it was ^Ced, and started anew: | ||
1759 | //15:21:15.043 no valid datapoints, no peer selected | ||
1760 | //15:21:17.408 update from:<IP> offset:+0.175910 delay:0.158314 jitter:0.076683 clock drift:-1.393ppm tc:4 | ||
1761 | //15:21:19.774 update from:<IP> offset:+0.171784 delay:0.158401 jitter:0.066436 clock drift:-1.393ppm tc:4 | ||
1762 | //15:21:22.140 update from:<IP> offset:+0.171660 delay:0.158592 jitter:0.057536 clock drift:-1.393ppm tc:4 | ||
1763 | //15:21:22.140 update from:<IP> offset:+0.167126 delay:0.158507 jitter:0.049792 clock drift:-1.393ppm tc:4 | ||
1764 | //15:21:55.696 update from:<IP> offset:+0.115223 delay:0.158277 jitter:0.050240 clock drift:-1.393ppm tc:4 | ||
1765 | //15:22:29.093 update from:<IP> offset:+0.068051 delay:0.158243 jitter:0.049405 clock drift:-1.393ppm tc:5 | ||
1766 | //15:23:02.490 update from:<IP> offset:+0.051632 delay:0.158215 jitter:0.043545 clock drift:-1.393ppm tc:5 | ||
1767 | //15:23:34.726 update from:<IP> offset:+0.039984 delay:0.158157 jitter:0.038106 clock drift:-1.393ppm tc:5 | ||
1768 | // STA_FREQHOLD no longer set, started increasing tmx.freq now: | ||
1769 | //15:24:06.961 update from:<IP> offset:+0.030968 delay:0.158190 jitter:0.033306 clock drift:+2.387ppm tc:5 | ||
1770 | //15:24:40.357 update from:<IP> offset:+0.023648 delay:0.158211 jitter:0.029072 clock drift:+5.454ppm tc:5 | ||
1771 | //15:25:13.774 update from:<IP> offset:+0.018068 delay:0.157660 jitter:0.025288 clock drift:+7.728ppm tc:5 | ||
1772 | //15:26:19.173 update from:<IP> offset:+0.010057 delay:0.157969 jitter:0.022255 clock drift:+8.361ppm tc:6 | ||
1773 | //15:27:26.602 update from:<IP> offset:+0.006737 delay:0.158103 jitter:0.019316 clock drift:+8.792ppm tc:6 | ||
1774 | //15:28:33.030 update from:<IP> offset:+0.004513 delay:0.158294 jitter:0.016765 clock drift:+9.080ppm tc:6 | ||
1775 | //15:29:40.617 update from:<IP> offset:+0.002787 delay:0.157745 jitter:0.014543 clock drift:+9.258ppm tc:6 | ||
1776 | //15:30:47.045 update from:<IP> offset:+0.001324 delay:0.157709 jitter:0.012594 clock drift:+9.342ppm tc:6 | ||
1777 | //15:31:53.473 update from:<IP> offset:+0.000007 delay:0.158142 jitter:0.010922 clock drift:+9.343ppm tc:6 | ||
1778 | //15:32:58.902 update from:<IP> offset:-0.000728 delay:0.158222 jitter:0.009454 clock drift:+9.298ppm tc:6 | ||
1779 | /* | ||
1780 | * This expression would choose 15 in the above example. | ||
1781 | */ | ||
1782 | G.FREQHOLD_cnt = 8 + ((unsigned)(abs(tmx.offset)) >> 16); | ||
1783 | } | ||
1784 | G.FREQHOLD_cnt--; | ||
1785 | tmx.status |= STA_FREQHOLD; | ||
1786 | } | ||
1740 | if (G.ntp_status & LI_PLUSSEC) | 1787 | if (G.ntp_status & LI_PLUSSEC) |
1741 | tmx.status |= STA_INS; | 1788 | tmx.status |= STA_INS; |
1742 | if (G.ntp_status & LI_MINUSSEC) | 1789 | if (G.ntp_status & LI_MINUSSEC) |
1743 | tmx.status |= STA_DEL; | 1790 | tmx.status |= STA_DEL; |
1744 | 1791 | ||
1792 | tmx.constant = (int)G.poll_exp - 4; | ||
1793 | /* EXPERIMENTAL. | ||
1794 | * The below if statement should be unnecessary, but... | ||
1795 | * It looks like Linux kernel's PLL is far too gentle in changing | ||
1796 | * tmx.freq in response to clock offset. Offset keeps growing | ||
1797 | * and eventually we fall back to smaller poll intervals. | ||
1798 | * We can make correction more aggressive (about x2) by supplying | ||
1799 | * PLL time constant which is one less than the real one. | ||
1800 | * To be on a safe side, let's do it only if offset is significantly | ||
1801 | * larger than jitter. | ||
1802 | */ | ||
1803 | if (G.offset_to_jitter_ratio >= TIMECONST_HACK_GATE) | ||
1804 | tmx.constant--; | ||
1805 | if (tmx.constant < 0) | ||
1806 | tmx.constant = 0; | ||
1807 | |||
1745 | //tmx.esterror = (uint32_t)(clock_jitter * 1e6); | 1808 | //tmx.esterror = (uint32_t)(clock_jitter * 1e6); |
1746 | //tmx.maxerror = (uint32_t)((sys_rootdelay / 2 + sys_rootdisp) * 1e6); | 1809 | //tmx.maxerror = (uint32_t)((sys_rootdelay / 2 + sys_rootdisp) * 1e6); |
1747 | rc = adjtimex(&tmx); | 1810 | rc = adjtimex(&tmx); |
@@ -2227,6 +2290,7 @@ static NOINLINE void ntp_init(char **argv) | |||
2227 | if (BURSTPOLL != 0) | 2290 | if (BURSTPOLL != 0) |
2228 | G.poll_exp = BURSTPOLL; /* speeds up initial sync */ | 2291 | G.poll_exp = BURSTPOLL; /* speeds up initial sync */ |
2229 | G.last_script_run = G.reftime = G.last_update_recv_time = gettime1900d(); /* sets G.cur_time too */ | 2292 | G.last_script_run = G.reftime = G.last_update_recv_time = gettime1900d(); /* sets G.cur_time too */ |
2293 | G.FREQHOLD_cnt = -1; | ||
2230 | 2294 | ||
2231 | /* Parse options */ | 2295 | /* Parse options */ |
2232 | peers = NULL; | 2296 | peers = NULL; |
diff --git a/networking/tcpudp.c b/networking/tcpudp.c index a90e3f80a..c914221ae 100644 --- a/networking/tcpudp.c +++ b/networking/tcpudp.c | |||
@@ -270,17 +270,22 @@ int tcpudpsvd_main(int argc UNUSED_PARAM, char **argv) | |||
270 | 270 | ||
271 | tcp = (applet_name[0] == 't'); | 271 | tcp = (applet_name[0] == 't'); |
272 | 272 | ||
273 | /* "+": stop on first non-option */ | ||
273 | #ifdef SSLSVD | 274 | #ifdef SSLSVD |
274 | opts = getopt32(argv, "^+" | 275 | opts = getopt32(argv, "^+" |
275 | "c:+C:i:x:u:l:Eb:+hpt:vU:/:Z:K:" /* -c NUM, -b NUM */ | 276 | "c:+C:i:x:u:l:Eb:+hpt:vU:/:Z:K:" /* -c NUM, -b NUM */ |
277 | "\0" | ||
276 | /* 3+ args, -i at most once, -p implies -h, -v is a counter */ | 278 | /* 3+ args, -i at most once, -p implies -h, -v is a counter */ |
277 | "\0" "-3:i--i:ph:vv", | 279 | "-3:i--i:ph:vv", |
278 | &cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, | 280 | &cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, |
279 | &backlog, &str_t, &ssluser, &root, &cert, &key, &verbose | 281 | &backlog, &str_t, &ssluser, &root, &cert, &key, &verbose |
280 | ); | 282 | ); |
281 | #else | 283 | #else |
282 | /* "+": stop on first non-option */ | 284 | opts = getopt32(argv, "^+" |
283 | opts = getopt32(argv, "+c:+C:i:x:u:l:Eb:hpt:v", | 285 | "c:+C:i:x:u:l:Eb:+hpt:v" /* -c NUM, -b NUM */ |
286 | "\0" | ||
287 | /* 3+ args, -i at most once, -p implies -h, -v is a counter */ | ||
288 | "-3:i--i:ph:vv", | ||
284 | &cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, | 289 | &cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, |
285 | &backlog, &str_t, &verbose | 290 | &backlog, &str_t, &verbose |
286 | ); | 291 | ); |
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 04939e707..13059f106 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
@@ -314,7 +314,7 @@ int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, | |||
314 | 314 | ||
315 | void udhcp_sp_setup(void) FAST_FUNC; | 315 | void udhcp_sp_setup(void) FAST_FUNC; |
316 | void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; | 316 | void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; |
317 | int udhcp_sp_read(struct pollfd *pfds) FAST_FUNC; | 317 | int udhcp_sp_read(void) FAST_FUNC; |
318 | 318 | ||
319 | int udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC; | 319 | int udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC; |
320 | 320 | ||
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 35c99e89c..289df66ee 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c | |||
@@ -1375,13 +1375,12 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1375 | /* yah, I know, *you* say it would never happen */ | 1375 | /* yah, I know, *you* say it would never happen */ |
1376 | timeout = INT_MAX; | 1376 | timeout = INT_MAX; |
1377 | continue; /* back to main loop */ | 1377 | continue; /* back to main loop */ |
1378 | } /* if select timed out */ | 1378 | } /* if poll timed out */ |
1379 | 1379 | ||
1380 | /* select() didn't timeout, something happened */ | 1380 | /* poll() didn't timeout, something happened */ |
1381 | 1381 | ||
1382 | /* Is it a signal? */ | 1382 | /* Is it a signal? */ |
1383 | /* note: udhcp_sp_read checks poll result before reading */ | 1383 | switch (udhcp_sp_read()) { |
1384 | switch (udhcp_sp_read(pfds)) { | ||
1385 | case SIGUSR1: | 1384 | case SIGUSR1: |
1386 | client_config.first_secs = 0; /* make secs field count from 0 */ | 1385 | client_config.first_secs = 0; /* make secs field count from 0 */ |
1387 | already_waited_sec = 0; | 1386 | already_waited_sec = 0; |
@@ -1416,7 +1415,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1416 | } | 1415 | } |
1417 | 1416 | ||
1418 | /* Is it a packet? */ | 1417 | /* Is it a packet? */ |
1419 | if (listen_mode == LISTEN_NONE || !pfds[1].revents) | 1418 | if (!pfds[1].revents) |
1420 | continue; /* no */ | 1419 | continue; /* no */ |
1421 | 1420 | ||
1422 | { | 1421 | { |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 35694fbe3..90b07bf4b 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -1574,13 +1574,12 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1574 | /* yah, I know, *you* say it would never happen */ | 1574 | /* yah, I know, *you* say it would never happen */ |
1575 | timeout = INT_MAX; | 1575 | timeout = INT_MAX; |
1576 | continue; /* back to main loop */ | 1576 | continue; /* back to main loop */ |
1577 | } /* if select timed out */ | 1577 | } /* if poll timed out */ |
1578 | 1578 | ||
1579 | /* select() didn't timeout, something happened */ | 1579 | /* poll() didn't timeout, something happened */ |
1580 | 1580 | ||
1581 | /* Is it a signal? */ | 1581 | /* Is it a signal? */ |
1582 | /* note: udhcp_sp_read checks poll result before reading */ | 1582 | switch (udhcp_sp_read()) { |
1583 | switch (udhcp_sp_read(pfds)) { | ||
1584 | case SIGUSR1: | 1583 | case SIGUSR1: |
1585 | client_config.first_secs = 0; /* make secs field count from 0 */ | 1584 | client_config.first_secs = 0; /* make secs field count from 0 */ |
1586 | already_waited_sec = 0; | 1585 | already_waited_sec = 0; |
@@ -1615,7 +1614,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1615 | } | 1614 | } |
1616 | 1615 | ||
1617 | /* Is it a packet? */ | 1616 | /* Is it a packet? */ |
1618 | if (listen_mode == LISTEN_NONE || !pfds[1].revents) | 1617 | if (!pfds[1].revents) |
1619 | continue; /* no */ | 1618 | continue; /* no */ |
1620 | 1619 | ||
1621 | { | 1620 | { |
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 093239536..19f94a2d7 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
@@ -853,6 +853,9 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
853 | /* Would rather not do read_config before daemonization - | 853 | /* Would rather not do read_config before daemonization - |
854 | * otherwise NOMMU machines will parse config twice */ | 854 | * otherwise NOMMU machines will parse config twice */ |
855 | read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE); | 855 | read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE); |
856 | /* prevent poll timeout overflow */ | ||
857 | if (server_config.auto_time > INT_MAX / 1000) | ||
858 | server_config.auto_time = INT_MAX / 1000; | ||
856 | 859 | ||
857 | /* Make sure fd 0,1,2 are open */ | 860 | /* Make sure fd 0,1,2 are open */ |
858 | bb_sanitize_stdio(); | 861 | bb_sanitize_stdio(); |
@@ -914,21 +917,31 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
914 | } | 917 | } |
915 | 918 | ||
916 | udhcp_sp_fd_set(pfds, server_socket); | 919 | udhcp_sp_fd_set(pfds, server_socket); |
917 | tv = timeout_end - monotonic_sec(); | 920 | |
918 | retval = 0; | 921 | new_tv: |
919 | if (!server_config.auto_time || tv > 0) { | 922 | tv = -1; |
920 | retval = poll(pfds, 2, server_config.auto_time ? tv * 1000 : -1); | 923 | if (server_config.auto_time) { |
921 | } | 924 | tv = timeout_end - monotonic_sec(); |
922 | if (retval == 0) { | 925 | if (tv <= 0) { |
923 | write_leases(); | 926 | write_leases: |
924 | goto continue_with_autotime; | 927 | write_leases(); |
928 | goto continue_with_autotime; | ||
929 | } | ||
930 | tv *= 1000; | ||
925 | } | 931 | } |
926 | if (retval < 0 && errno != EINTR) { | 932 | |
927 | log1("error on select"); | 933 | /* Block here waiting for either signal or packet */ |
928 | continue; | 934 | retval = poll(pfds, 2, tv); |
935 | if (retval <= 0) { | ||
936 | if (retval == 0) | ||
937 | goto write_leases; | ||
938 | if (errno == EINTR) | ||
939 | goto new_tv; | ||
940 | /* < 0 and not EINTR: should not happen */ | ||
941 | bb_perror_msg_and_die("poll"); | ||
929 | } | 942 | } |
930 | 943 | ||
931 | switch (udhcp_sp_read(pfds)) { | 944 | if (pfds[0].revents) switch (udhcp_sp_read()) { |
932 | case SIGUSR1: | 945 | case SIGUSR1: |
933 | bb_error_msg("received %s", "SIGUSR1"); | 946 | bb_error_msg("received %s", "SIGUSR1"); |
934 | write_leases(); | 947 | write_leases(); |
@@ -938,12 +951,16 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
938 | bb_error_msg("received %s", "SIGTERM"); | 951 | bb_error_msg("received %s", "SIGTERM"); |
939 | write_leases(); | 952 | write_leases(); |
940 | goto ret0; | 953 | goto ret0; |
941 | case 0: /* no signal: read a packet */ | ||
942 | break; | ||
943 | default: /* signal or error (probably EINTR): back to select */ | ||
944 | continue; | ||
945 | } | 954 | } |
946 | 955 | ||
956 | /* Is it a packet? */ | ||
957 | if (!pfds[1].revents) | ||
958 | continue; /* no */ | ||
959 | |||
960 | /* Note: we do not block here, we block on poll() instead. | ||
961 | * Blocking here would prevent SIGTERM from working: | ||
962 | * socket read inside this call is restarted on caught signals. | ||
963 | */ | ||
947 | bytes = udhcp_recv_kernel_packet(&packet, server_socket); | 964 | bytes = udhcp_recv_kernel_packet(&packet, server_socket); |
948 | if (bytes < 0) { | 965 | if (bytes < 0) { |
949 | /* bytes can also be -2 ("bad packet data") */ | 966 | /* bytes can also be -2 ("bad packet data") */ |
diff --git a/networking/udhcp/signalpipe.c b/networking/udhcp/signalpipe.c index b101b4ce4..2ff78f0f2 100644 --- a/networking/udhcp/signalpipe.c +++ b/networking/udhcp/signalpipe.c | |||
@@ -40,6 +40,7 @@ void FAST_FUNC udhcp_sp_setup(void) | |||
40 | xpiped_pair(signal_pipe); | 40 | xpiped_pair(signal_pipe); |
41 | close_on_exec_on(signal_pipe.rd); | 41 | close_on_exec_on(signal_pipe.rd); |
42 | close_on_exec_on(signal_pipe.wr); | 42 | close_on_exec_on(signal_pipe.wr); |
43 | ndelay_on(signal_pipe.rd); | ||
43 | ndelay_on(signal_pipe.wr); | 44 | ndelay_on(signal_pipe.wr); |
44 | bb_signals(0 | 45 | bb_signals(0 |
45 | + (1 << SIGUSR1) | 46 | + (1 << SIGUSR1) |
@@ -61,20 +62,20 @@ void FAST_FUNC udhcp_sp_fd_set(struct pollfd pfds[2], int extra_fd) | |||
61 | pfds[1].fd = extra_fd; | 62 | pfds[1].fd = extra_fd; |
62 | pfds[1].events = POLLIN; | 63 | pfds[1].events = POLLIN; |
63 | } | 64 | } |
65 | /* this simplifies "is extra_fd ready?" tests elsewhere: */ | ||
66 | pfds[1].revents = 0; | ||
64 | } | 67 | } |
65 | 68 | ||
66 | /* Read a signal from the signal pipe. Returns 0 if there is | 69 | /* Read a signal from the signal pipe. Returns 0 if there is |
67 | * no signal, -1 on error (and sets errno appropriately), and | 70 | * no signal, -1 on error (and sets errno appropriately), and |
68 | * your signal on success */ | 71 | * your signal on success */ |
69 | int FAST_FUNC udhcp_sp_read(struct pollfd pfds[2]) | 72 | int FAST_FUNC udhcp_sp_read(void) |
70 | { | 73 | { |
71 | unsigned char sig; | 74 | unsigned char sig; |
72 | 75 | ||
73 | if (!pfds[0].revents) | 76 | /* Can't block here, fd is in nonblocking mode */ |
74 | return 0; | ||
75 | |||
76 | if (safe_read(signal_pipe.rd, &sig, 1) != 1) | 77 | if (safe_read(signal_pipe.rd, &sig, 1) != 1) |
77 | return -1; | 78 | return 0; |
78 | 79 | ||
79 | return sig; | 80 | return sig; |
80 | } | 81 | } |
diff --git a/networking/wget.c b/networking/wget.c index b9225fac0..150bc8e12 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
@@ -1017,7 +1017,6 @@ static void download_one_url(const char *url) | |||
1017 | len_and_sockaddr *lsa; | 1017 | len_and_sockaddr *lsa; |
1018 | FILE *sfp; /* socket to web/ftp server */ | 1018 | FILE *sfp; /* socket to web/ftp server */ |
1019 | FILE *dfp; /* socket to ftp server (data) */ | 1019 | FILE *dfp; /* socket to ftp server (data) */ |
1020 | char *proxy = NULL; | ||
1021 | char *fname_out_alloc; | 1020 | char *fname_out_alloc; |
1022 | char *redirected_path = NULL; | 1021 | char *redirected_path = NULL; |
1023 | struct host_info server; | 1022 | struct host_info server; |
@@ -1033,13 +1032,14 @@ static void download_one_url(const char *url) | |||
1033 | /* Use the proxy if necessary */ | 1032 | /* Use the proxy if necessary */ |
1034 | use_proxy = (strcmp(G.proxy_flag, "off") != 0); | 1033 | use_proxy = (strcmp(G.proxy_flag, "off") != 0); |
1035 | if (use_proxy) { | 1034 | if (use_proxy) { |
1036 | proxy = getenv(target.protocol[0] == 'f' ? "ftp_proxy" : "http_proxy"); | 1035 | char *proxy = getenv(target.protocol[0] == 'f' ? "ftp_proxy" : "http_proxy"); |
1037 | //FIXME: what if protocol is https? Ok to use http_proxy? | 1036 | //FIXME: what if protocol is https? Ok to use http_proxy? |
1038 | use_proxy = (proxy && proxy[0]); | 1037 | use_proxy = (proxy && proxy[0]); |
1039 | if (use_proxy) | 1038 | if (use_proxy) |
1040 | parse_url(proxy, &server); | 1039 | parse_url(proxy, &server); |
1041 | } | 1040 | } |
1042 | if (!use_proxy) { | 1041 | if (!use_proxy) { |
1042 | server.protocol = target.protocol; | ||
1043 | server.port = target.port; | 1043 | server.port = target.port; |
1044 | if (ENABLE_FEATURE_IPV6) { | 1044 | if (ENABLE_FEATURE_IPV6) { |
1045 | //free(server.allocated); - can't be non-NULL | 1045 | //free(server.allocated); - can't be non-NULL |
@@ -1104,7 +1104,7 @@ static void download_one_url(const char *url) | |||
1104 | /* Open socket to http(s) server */ | 1104 | /* Open socket to http(s) server */ |
1105 | #if ENABLE_FEATURE_WGET_OPENSSL | 1105 | #if ENABLE_FEATURE_WGET_OPENSSL |
1106 | /* openssl (and maybe internal TLS) support is configured */ | 1106 | /* openssl (and maybe internal TLS) support is configured */ |
1107 | if (target.protocol == P_HTTPS) { | 1107 | if (server.protocol == P_HTTPS) { |
1108 | /* openssl-based helper | 1108 | /* openssl-based helper |
1109 | * Inconvenient API since we can't give it an open fd | 1109 | * Inconvenient API since we can't give it an open fd |
1110 | */ | 1110 | */ |
@@ -1128,7 +1128,7 @@ static void download_one_url(const char *url) | |||
1128 | #elif ENABLE_FEATURE_WGET_HTTPS | 1128 | #elif ENABLE_FEATURE_WGET_HTTPS |
1129 | /* Only internal TLS support is configured */ | 1129 | /* Only internal TLS support is configured */ |
1130 | sfp = open_socket(lsa); | 1130 | sfp = open_socket(lsa); |
1131 | if (target.protocol == P_HTTPS) | 1131 | if (server.protocol == P_HTTPS) |
1132 | spawn_ssl_client(server.host, fileno(sfp), /*flags*/ 0); | 1132 | spawn_ssl_client(server.host, fileno(sfp), /*flags*/ 0); |
1133 | #else | 1133 | #else |
1134 | /* ssl (https) support is not configured */ | 1134 | /* ssl (https) support is not configured */ |
diff --git a/procps/top.c b/procps/top.c index b777c494e..075c96c27 100644 --- a/procps/top.c +++ b/procps/top.c | |||
@@ -180,7 +180,7 @@ struct globals { | |||
180 | #else | 180 | #else |
181 | cmp_funcp sort_function[SORT_DEPTH]; | 181 | cmp_funcp sort_function[SORT_DEPTH]; |
182 | struct save_hist *prev_hist; | 182 | struct save_hist *prev_hist; |
183 | int prev_hist_count; | 183 | unsigned prev_hist_count; |
184 | jiffy_counts_t cur_jif, prev_jif; | 184 | jiffy_counts_t cur_jif, prev_jif; |
185 | /* int hist_iterations; */ | 185 | /* int hist_iterations; */ |
186 | unsigned total_pcpu; | 186 | unsigned total_pcpu; |
@@ -189,7 +189,7 @@ struct globals { | |||
189 | #if ENABLE_FEATURE_TOP_SMP_CPU | 189 | #if ENABLE_FEATURE_TOP_SMP_CPU |
190 | /* Per CPU samples: current and last */ | 190 | /* Per CPU samples: current and last */ |
191 | jiffy_counts_t *cpu_jif, *cpu_prev_jif; | 191 | jiffy_counts_t *cpu_jif, *cpu_prev_jif; |
192 | int num_cpus; | 192 | unsigned num_cpus; |
193 | #endif | 193 | #endif |
194 | #if ENABLE_FEATURE_TOP_INTERACTIVE | 194 | #if ENABLE_FEATURE_TOP_INTERACTIVE |
195 | char kbd_input[KEYCODE_BUFFER_SIZE]; | 195 | char kbd_input[KEYCODE_BUFFER_SIZE]; |
@@ -355,7 +355,8 @@ static void do_stats(void) | |||
355 | { | 355 | { |
356 | top_status_t *cur; | 356 | top_status_t *cur; |
357 | pid_t pid; | 357 | pid_t pid; |
358 | int i, last_i, n; | 358 | int n; |
359 | unsigned i, last_i; | ||
359 | struct save_hist *new_hist; | 360 | struct save_hist *new_hist; |
360 | 361 | ||
361 | get_jiffy_counts(); | 362 | get_jiffy_counts(); |
@@ -607,7 +608,6 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width) | |||
607 | }; | 608 | }; |
608 | 609 | ||
609 | top_status_t *s; | 610 | top_status_t *s; |
610 | char vsz_str_buf[8]; | ||
611 | unsigned long total_memory = display_header(scr_width, &lines_rem); /* or use total_vsz? */ | 611 | unsigned long total_memory = display_header(scr_width, &lines_rem); /* or use total_vsz? */ |
612 | /* xxx_shift and xxx_scale variables allow us to replace | 612 | /* xxx_shift and xxx_scale variables allow us to replace |
613 | * expensive divides with multiply and shift */ | 613 | * expensive divides with multiply and shift */ |
@@ -688,19 +688,18 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width) | |||
688 | lines_rem = ntop - G_scroll_ofs; | 688 | lines_rem = ntop - G_scroll_ofs; |
689 | s = top + G_scroll_ofs; | 689 | s = top + G_scroll_ofs; |
690 | while (--lines_rem >= 0) { | 690 | while (--lines_rem >= 0) { |
691 | char vsz_str_buf[8]; | ||
691 | unsigned col; | 692 | unsigned col; |
693 | |||
692 | CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift); | 694 | CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift); |
693 | #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE | 695 | #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE |
694 | CALC_STAT(pcpu, (s->pcpu*pcpu_scale + pcpu_half) >> pcpu_shift); | 696 | CALC_STAT(pcpu, (s->pcpu*pcpu_scale + pcpu_half) >> pcpu_shift); |
695 | #endif | 697 | #endif |
696 | 698 | ||
697 | if (s->vsz >= 100000) | 699 | smart_ulltoa5(s->vsz, vsz_str_buf, " mgtpezy"); |
698 | sprintf(vsz_str_buf, "%6ldm", s->vsz/1024); | ||
699 | else | ||
700 | sprintf(vsz_str_buf, "%7lu", s->vsz); | ||
701 | /* PID PPID USER STAT VSZ %VSZ [%CPU] COMMAND */ | 700 | /* PID PPID USER STAT VSZ %VSZ [%CPU] COMMAND */ |
702 | col = snprintf(line_buf, scr_width, | 701 | col = snprintf(line_buf, scr_width, |
703 | "\n" "%5u%6u %-8.8s %s%s" FMT | 702 | "\n" "%5u%6u %-8.8s %s %.5s" FMT |
704 | IF_FEATURE_TOP_SMP_PROCESS(" %3d") | 703 | IF_FEATURE_TOP_SMP_PROCESS(" %3d") |
705 | IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(FMT) | 704 | IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(FMT) |
706 | " ", | 705 | " ", |
@@ -710,7 +709,7 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width) | |||
710 | IF_FEATURE_TOP_SMP_PROCESS(, s->last_seen_on_cpu) | 709 | IF_FEATURE_TOP_SMP_PROCESS(, s->last_seen_on_cpu) |
711 | IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(, SHOW_STAT(pcpu)) | 710 | IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(, SHOW_STAT(pcpu)) |
712 | ); | 711 | ); |
713 | if ((int)(col + 1) < scr_width) | 712 | if ((int)(scr_width - col) > 1) |
714 | read_cmdline(line_buf + col, scr_width - col, s->pid, s->comm); | 713 | read_cmdline(line_buf + col, scr_width - col, s->pid, s->comm); |
715 | fputs(line_buf, stdout); | 714 | fputs(line_buf, stdout); |
716 | /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu, | 715 | /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu, |
@@ -897,7 +896,8 @@ enum { | |||
897 | | PSSCAN_PID | 896 | | PSSCAN_PID |
898 | | PSSCAN_SMAPS | 897 | | PSSCAN_SMAPS |
899 | | PSSCAN_COMM, | 898 | | PSSCAN_COMM, |
900 | EXIT_MASK = (unsigned)-1, | 899 | EXIT_MASK = 0, |
900 | NO_RESCAN_MASK = (unsigned)-1, | ||
901 | }; | 901 | }; |
902 | 902 | ||
903 | #if ENABLE_FEATURE_TOP_INTERACTIVE | 903 | #if ENABLE_FEATURE_TOP_INTERACTIVE |
@@ -935,7 +935,7 @@ static unsigned handle_input(unsigned scan_mask, unsigned interval) | |||
935 | } | 935 | } |
936 | if (c == KEYCODE_HOME) { | 936 | if (c == KEYCODE_HOME) { |
937 | G_scroll_ofs = 0; | 937 | G_scroll_ofs = 0; |
938 | break; | 938 | goto normalize_ofs; |
939 | } | 939 | } |
940 | if (c == KEYCODE_END) { | 940 | if (c == KEYCODE_END) { |
941 | G_scroll_ofs = ntop - G.lines / 2; | 941 | G_scroll_ofs = ntop - G.lines / 2; |
@@ -952,7 +952,7 @@ static unsigned handle_input(unsigned scan_mask, unsigned interval) | |||
952 | G_scroll_ofs = ntop - 1; | 952 | G_scroll_ofs = ntop - 1; |
953 | if (G_scroll_ofs < 0) | 953 | if (G_scroll_ofs < 0) |
954 | G_scroll_ofs = 0; | 954 | G_scroll_ofs = 0; |
955 | break; | 955 | return NO_RESCAN_MASK; |
956 | } | 956 | } |
957 | 957 | ||
958 | c |= 0x20; /* lowercase */ | 958 | c |= 0x20; /* lowercase */ |
@@ -1157,6 +1157,7 @@ int top_main(int argc UNUSED_PARAM, char **argv) | |||
1157 | #endif | 1157 | #endif |
1158 | 1158 | ||
1159 | while (scan_mask != EXIT_MASK) { | 1159 | while (scan_mask != EXIT_MASK) { |
1160 | unsigned new_mask; | ||
1160 | procps_status_t *p = NULL; | 1161 | procps_status_t *p = NULL; |
1161 | 1162 | ||
1162 | if (OPT_BATCH_MODE) { | 1163 | if (OPT_BATCH_MODE) { |
@@ -1234,21 +1235,32 @@ int top_main(int argc UNUSED_PARAM, char **argv) | |||
1234 | #else | 1235 | #else |
1235 | qsort(top, ntop, sizeof(top_status_t), (void*)(sort_function[0])); | 1236 | qsort(top, ntop, sizeof(top_status_t), (void*)(sort_function[0])); |
1236 | #endif | 1237 | #endif |
1237 | display_process_list(G.lines, col); | ||
1238 | } | 1238 | } |
1239 | #if ENABLE_FEATURE_TOPMEM | 1239 | #if ENABLE_FEATURE_TOPMEM |
1240 | else { /* TOPMEM */ | 1240 | else { /* TOPMEM */ |
1241 | qsort(topmem, ntop, sizeof(topmem_status_t), (void*)topmem_sort); | 1241 | qsort(topmem, ntop, sizeof(topmem_status_t), (void*)topmem_sort); |
1242 | } | ||
1243 | #endif | ||
1244 | IF_FEATURE_TOP_INTERACTIVE(display:) | ||
1245 | IF_FEATURE_TOPMEM(if (scan_mask != TOPMEM_MASK)) { | ||
1246 | display_process_list(G.lines, col); | ||
1247 | } | ||
1248 | #if ENABLE_FEATURE_TOPMEM | ||
1249 | else { /* TOPMEM */ | ||
1242 | display_topmem_process_list(G.lines, col); | 1250 | display_topmem_process_list(G.lines, col); |
1243 | } | 1251 | } |
1244 | #endif | 1252 | #endif |
1245 | clearmems(); | ||
1246 | if (iterations >= 0 && !--iterations) | 1253 | if (iterations >= 0 && !--iterations) |
1247 | break; | 1254 | break; |
1248 | #if !ENABLE_FEATURE_TOP_INTERACTIVE | 1255 | #if !ENABLE_FEATURE_TOP_INTERACTIVE |
1256 | clearmems(); | ||
1249 | sleep(interval); | 1257 | sleep(interval); |
1250 | #else | 1258 | #else |
1251 | scan_mask = handle_input(scan_mask, interval); | 1259 | new_mask = handle_input(scan_mask, interval); |
1260 | if (new_mask == NO_RESCAN_MASK) | ||
1261 | goto display; | ||
1262 | scan_mask = new_mask; | ||
1263 | clearmems(); | ||
1252 | #endif | 1264 | #endif |
1253 | } /* end of "while (not Q)" */ | 1265 | } /* end of "while (not Q)" */ |
1254 | 1266 | ||
diff --git a/runit/svlogd.c b/runit/svlogd.c index 412290ca9..13de2570f 100644 --- a/runit/svlogd.c +++ b/runit/svlogd.c | |||
@@ -347,11 +347,13 @@ static unsigned pmatch(const char *p, const char *s, unsigned len) | |||
347 | /* NUL terminated */ | 347 | /* NUL terminated */ |
348 | static void fmt_time_human_30nul(char *s, char dt_delim) | 348 | static void fmt_time_human_30nul(char *s, char dt_delim) |
349 | { | 349 | { |
350 | struct tm tm; | ||
350 | struct tm *ptm; | 351 | struct tm *ptm; |
351 | struct timeval tv; | 352 | struct timeval tv; |
352 | 353 | ||
353 | gettimeofday(&tv, NULL); | 354 | gettimeofday(&tv, NULL); |
354 | ptm = gmtime(&tv.tv_sec); | 355 | ptm = gmtime_r(&tv.tv_sec, &tm); |
356 | /* ^^^ using gmtime_r() instead of gmtime() to not use static data */ | ||
355 | sprintf(s, "%04u-%02u-%02u%c%02u:%02u:%02u.%06u000", | 357 | sprintf(s, "%04u-%02u-%02u%c%02u:%02u:%02u.%06u000", |
356 | (unsigned)(1900 + ptm->tm_year), | 358 | (unsigned)(1900 + ptm->tm_year), |
357 | (unsigned)(ptm->tm_mon + 1), | 359 | (unsigned)(ptm->tm_mon + 1), |
diff --git a/shell/ash_test/ash-quoting/bkslash_in_varexp.right b/shell/ash_test/ash-quoting/bkslash_in_varexp.right new file mode 100644 index 000000000..d03047024 --- /dev/null +++ b/shell/ash_test/ash-quoting/bkslash_in_varexp.right | |||
@@ -0,0 +1,5 @@ | |||
1 | Nothing: | ||
2 | Nothing: | ||
3 | Nothing: | ||
4 | Nothing: | ||
5 | Ok:0 | ||
diff --git a/shell/ash_test/ash-quoting/bkslash_in_varexp.tests b/shell/ash_test/ash-quoting/bkslash_in_varexp.tests new file mode 100755 index 000000000..6c7b4b0cc --- /dev/null +++ b/shell/ash_test/ash-quoting/bkslash_in_varexp.tests | |||
@@ -0,0 +1,16 @@ | |||
1 | x='a]' | ||
2 | # | ||
3 | # \] is not a valid escape for ] in set glob expression. | ||
4 | # Glob sets have no escaping at all: | ||
5 | # ] can be in a set if it is the first char: []abc], | ||
6 | # dash can be in a set if it is first or last: [abc-], | ||
7 | # [ and \ need no protections at all: [a[b\c] is a valid set of 5 chars. | ||
8 | # | ||
9 | # bash-4.3.43 misinterprets [a\]] as "set of 'a' or ']'". | ||
10 | # Correct interpretation is "set of 'a' or '\', followed by ']'". | ||
11 | # | ||
12 | echo Nothing:${x#[a\]]} | ||
13 | echo Nothing:"${x#[a\]]}" | ||
14 | echo Nothing:${x%[a\]]} | ||
15 | echo Nothing:"${x%[a\]]}" | ||
16 | echo Ok:$? | ||
diff --git a/shell/ash_test/ash-quoting/bkslash_in_varexp1.right b/shell/ash_test/ash-quoting/bkslash_in_varexp1.right new file mode 100644 index 000000000..d03047024 --- /dev/null +++ b/shell/ash_test/ash-quoting/bkslash_in_varexp1.right | |||
@@ -0,0 +1,5 @@ | |||
1 | Nothing: | ||
2 | Nothing: | ||
3 | Nothing: | ||
4 | Nothing: | ||
5 | Ok:0 | ||
diff --git a/shell/ash_test/ash-quoting/bkslash_in_varexp1.tests b/shell/ash_test/ash-quoting/bkslash_in_varexp1.tests new file mode 100755 index 000000000..3c817eae1 --- /dev/null +++ b/shell/ash_test/ash-quoting/bkslash_in_varexp1.tests | |||
@@ -0,0 +1,6 @@ | |||
1 | x=a | ||
2 | echo Nothing:${x#[]a]} | ||
3 | echo Nothing:"${x#[]a]}" | ||
4 | echo Nothing:${x%[]a]} | ||
5 | echo Nothing:"${x%[]a]}" | ||
6 | echo Ok:$? | ||
diff --git a/shell/ash_test/ash-quoting/squote_in_varexp.right b/shell/ash_test/ash-quoting/squote_in_varexp.right new file mode 100644 index 000000000..a75c0bfd6 --- /dev/null +++ b/shell/ash_test/ash-quoting/squote_in_varexp.right | |||
@@ -0,0 +1,5 @@ | |||
1 | z | ||
2 | z | ||
3 | y | ||
4 | y | ||
5 | Ok:0 | ||
diff --git a/shell/ash_test/ash-quoting/squote_in_varexp.tests b/shell/ash_test/ash-quoting/squote_in_varexp.tests new file mode 100755 index 000000000..a2d05a246 --- /dev/null +++ b/shell/ash_test/ash-quoting/squote_in_varexp.tests | |||
@@ -0,0 +1,6 @@ | |||
1 | x=yz | ||
2 | echo ${x#'y'} | ||
3 | echo "${x#'y'}" | ||
4 | echo ${x%'z'} | ||
5 | echo "${x%'z'}" | ||
6 | echo Ok:$? | ||
diff --git a/shell/ash_test/ash-quoting/squote_in_varexp1.right b/shell/ash_test/ash-quoting/squote_in_varexp1.right new file mode 100644 index 000000000..9d0add3c5 --- /dev/null +++ b/shell/ash_test/ash-quoting/squote_in_varexp1.right | |||
@@ -0,0 +1,3 @@ | |||
1 | Nothing: | ||
2 | Nothing: | ||
3 | Ok:0 | ||
diff --git a/shell/ash_test/ash-quoting/squote_in_varexp1.tests b/shell/ash_test/ash-quoting/squote_in_varexp1.tests new file mode 100755 index 000000000..efb380db3 --- /dev/null +++ b/shell/ash_test/ash-quoting/squote_in_varexp1.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | x='\\\\' | ||
2 | printf Nothing:'%s\n' ${x#\\\\\\\\} | ||
3 | printf Nothing:'%s\n' "${x#\\\\\\\\}" | ||
4 | echo Ok:$? | ||
diff --git a/shell/ash_test/ash-quoting/squote_in_varexp2.right b/shell/ash_test/ash-quoting/squote_in_varexp2.right new file mode 100644 index 000000000..9d0add3c5 --- /dev/null +++ b/shell/ash_test/ash-quoting/squote_in_varexp2.right | |||
@@ -0,0 +1,3 @@ | |||
1 | Nothing: | ||
2 | Nothing: | ||
3 | Ok:0 | ||
diff --git a/shell/ash_test/ash-quoting/squote_in_varexp2.tests b/shell/ash_test/ash-quoting/squote_in_varexp2.tests new file mode 100755 index 000000000..806ad12b9 --- /dev/null +++ b/shell/ash_test/ash-quoting/squote_in_varexp2.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | x='\\\\' | ||
2 | printf Nothing:'%s\n' ${x#'\\\\'} | ||
3 | printf Nothing:'%s\n' "${x#'\\\\'}" | ||
4 | echo Ok:$? | ||
diff --git a/shell/hush.c b/shell/hush.c index e005b0a20..6e64efb70 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -4488,7 +4488,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign | |||
4488 | } | 4488 | } |
4489 | if (ch == end_ch | 4489 | if (ch == end_ch |
4490 | # if BASH_SUBSTR || BASH_PATTERN_SUBST | 4490 | # if BASH_SUBSTR || BASH_PATTERN_SUBST |
4491 | || ch == end_char2 | 4491 | || ch == end_char2 |
4492 | # endif | 4492 | # endif |
4493 | ) { | 4493 | ) { |
4494 | if (!dbl) | 4494 | if (!dbl) |
@@ -4500,6 +4500,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign | |||
4500 | } | 4500 | } |
4501 | } | 4501 | } |
4502 | o_addchr(dest, ch); | 4502 | o_addchr(dest, ch); |
4503 | //bb_error_msg("%s:o_addchr('%c')", __func__, ch); | ||
4503 | if (ch == '(' || ch == '{') { | 4504 | if (ch == '(' || ch == '{') { |
4504 | ch = (ch == '(' ? ')' : '}'); | 4505 | ch = (ch == '(' ? ')' : '}'); |
4505 | if (!add_till_closing_bracket(dest, input, ch)) | 4506 | if (!add_till_closing_bracket(dest, input, ch)) |
@@ -4529,7 +4530,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign | |||
4529 | /* \x. Copy verbatim. Important for \(, \) */ | 4530 | /* \x. Copy verbatim. Important for \(, \) */ |
4530 | ch = i_getch(input); | 4531 | ch = i_getch(input); |
4531 | if (ch == EOF) { | 4532 | if (ch == EOF) { |
4532 | syntax_error_unterm_ch(')'); | 4533 | syntax_error_unterm_ch(end_ch); |
4533 | return 0; | 4534 | return 0; |
4534 | } | 4535 | } |
4535 | #if 0 | 4536 | #if 0 |
@@ -4540,6 +4541,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign | |||
4540 | } | 4541 | } |
4541 | #endif | 4542 | #endif |
4542 | o_addchr(dest, ch); | 4543 | o_addchr(dest, ch); |
4544 | //bb_error_msg("%s:o_addchr('%c') after '\\'", __func__, ch); | ||
4543 | continue; | 4545 | continue; |
4544 | } | 4546 | } |
4545 | } | 4547 | } |
@@ -5842,17 +5844,24 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |||
5842 | unsigned scan_flags = pick_scan(exp_op, *exp_word); | 5844 | unsigned scan_flags = pick_scan(exp_op, *exp_word); |
5843 | if (exp_op == *exp_word) /* ## or %% */ | 5845 | if (exp_op == *exp_word) /* ## or %% */ |
5844 | exp_word++; | 5846 | exp_word++; |
5845 | exp_exp_word = encode_then_expand_string(exp_word, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); | 5847 | debug_printf_expand("expand: exp_word:'%s'\n", exp_word); |
5848 | /* | ||
5849 | * process_bkslash:1 unbackslash:1 breaks this: | ||
5850 | * a='a\\'; echo ${a%\\\\} # correct output is: a | ||
5851 | * process_bkslash:1 unbackslash:0 breaks this: | ||
5852 | * a='a}'; echo ${a%\}} # correct output is: a | ||
5853 | */ | ||
5854 | exp_exp_word = encode_then_expand_string(exp_word, /*process_bkslash:*/ 0, /*unbackslash:*/ 0); | ||
5846 | if (exp_exp_word) | 5855 | if (exp_exp_word) |
5847 | exp_word = exp_exp_word; | 5856 | exp_word = exp_exp_word; |
5857 | debug_printf_expand("expand: exp_exp_word:'%s'\n", exp_word); | ||
5848 | /* HACK ALERT. We depend here on the fact that | 5858 | /* HACK ALERT. We depend here on the fact that |
5849 | * G.global_argv and results of utoa and get_local_var_value | 5859 | * G.global_argv and results of utoa and get_local_var_value |
5850 | * are actually in writable memory: | 5860 | * are actually in writable memory: |
5851 | * scan_and_match momentarily stores NULs there. */ | 5861 | * scan_and_match momentarily stores NULs there. */ |
5852 | t = (char*)val; | 5862 | t = (char*)val; |
5853 | loc = scan_and_match(t, exp_word, scan_flags); | 5863 | loc = scan_and_match(t, exp_word, scan_flags); |
5854 | //bb_error_msg("op:%c str:'%s' pat:'%s' res:'%s'", | 5864 | debug_printf_expand("op:%c str:'%s' pat:'%s' res:'%s'\n", exp_op, t, exp_word, loc); |
5855 | // exp_op, t, exp_word, loc); | ||
5856 | free(exp_exp_word); | 5865 | free(exp_exp_word); |
5857 | if (loc) { /* match was found */ | 5866 | if (loc) { /* match was found */ |
5858 | if (scan_flags & SCAN_MATCH_LEFT_HALF) /* #[#] */ | 5867 | if (scan_flags & SCAN_MATCH_LEFT_HALF) /* #[#] */ |
@@ -7172,21 +7181,22 @@ static const struct built_in_command *find_builtin(const char *name) | |||
7172 | #if ENABLE_HUSH_FUNCTIONS | 7181 | #if ENABLE_HUSH_FUNCTIONS |
7173 | static struct function **find_function_slot(const char *name) | 7182 | static struct function **find_function_slot(const char *name) |
7174 | { | 7183 | { |
7184 | struct function *funcp; | ||
7175 | struct function **funcpp = &G.top_func; | 7185 | struct function **funcpp = &G.top_func; |
7176 | while (*funcpp) { | 7186 | |
7177 | if (strcmp(name, (*funcpp)->name) == 0) { | 7187 | while ((funcp = *funcpp) != NULL) { |
7188 | if (strcmp(name, funcp->name) == 0) { | ||
7189 | debug_printf_exec("found function '%s'\n", name); | ||
7178 | break; | 7190 | break; |
7179 | } | 7191 | } |
7180 | funcpp = &(*funcpp)->next; | 7192 | funcpp = &funcp->next; |
7181 | } | 7193 | } |
7182 | return funcpp; | 7194 | return funcpp; |
7183 | } | 7195 | } |
7184 | 7196 | ||
7185 | static const struct function *find_function(const char *name) | 7197 | static ALWAYS_INLINE const struct function *find_function(const char *name) |
7186 | { | 7198 | { |
7187 | const struct function *funcp = *find_function_slot(name); | 7199 | const struct function *funcp = *find_function_slot(name); |
7188 | if (funcp) | ||
7189 | debug_printf_exec("found function '%s'\n", name); | ||
7190 | return funcp; | 7200 | return funcp; |
7191 | } | 7201 | } |
7192 | 7202 | ||
diff --git a/shell/hush_test/hush-quoting/bkslash_in_varexp.right b/shell/hush_test/hush-quoting/bkslash_in_varexp.right new file mode 100644 index 000000000..d03047024 --- /dev/null +++ b/shell/hush_test/hush-quoting/bkslash_in_varexp.right | |||
@@ -0,0 +1,5 @@ | |||
1 | Nothing: | ||
2 | Nothing: | ||
3 | Nothing: | ||
4 | Nothing: | ||
5 | Ok:0 | ||
diff --git a/shell/hush_test/hush-quoting/bkslash_in_varexp.tests b/shell/hush_test/hush-quoting/bkslash_in_varexp.tests new file mode 100755 index 000000000..6c7b4b0cc --- /dev/null +++ b/shell/hush_test/hush-quoting/bkslash_in_varexp.tests | |||
@@ -0,0 +1,16 @@ | |||
1 | x='a]' | ||
2 | # | ||
3 | # \] is not a valid escape for ] in set glob expression. | ||
4 | # Glob sets have no escaping at all: | ||
5 | # ] can be in a set if it is the first char: []abc], | ||
6 | # dash can be in a set if it is first or last: [abc-], | ||
7 | # [ and \ need no protections at all: [a[b\c] is a valid set of 5 chars. | ||
8 | # | ||
9 | # bash-4.3.43 misinterprets [a\]] as "set of 'a' or ']'". | ||
10 | # Correct interpretation is "set of 'a' or '\', followed by ']'". | ||
11 | # | ||
12 | echo Nothing:${x#[a\]]} | ||
13 | echo Nothing:"${x#[a\]]}" | ||
14 | echo Nothing:${x%[a\]]} | ||
15 | echo Nothing:"${x%[a\]]}" | ||
16 | echo Ok:$? | ||
diff --git a/shell/hush_test/hush-quoting/bkslash_in_varexp1.right b/shell/hush_test/hush-quoting/bkslash_in_varexp1.right new file mode 100644 index 000000000..d03047024 --- /dev/null +++ b/shell/hush_test/hush-quoting/bkslash_in_varexp1.right | |||
@@ -0,0 +1,5 @@ | |||
1 | Nothing: | ||
2 | Nothing: | ||
3 | Nothing: | ||
4 | Nothing: | ||
5 | Ok:0 | ||
diff --git a/shell/hush_test/hush-quoting/bkslash_in_varexp1.tests b/shell/hush_test/hush-quoting/bkslash_in_varexp1.tests new file mode 100755 index 000000000..3c817eae1 --- /dev/null +++ b/shell/hush_test/hush-quoting/bkslash_in_varexp1.tests | |||
@@ -0,0 +1,6 @@ | |||
1 | x=a | ||
2 | echo Nothing:${x#[]a]} | ||
3 | echo Nothing:"${x#[]a]}" | ||
4 | echo Nothing:${x%[]a]} | ||
5 | echo Nothing:"${x%[]a]}" | ||
6 | echo Ok:$? | ||
diff --git a/shell/hush_test/hush-quoting/squote_in_varexp.right b/shell/hush_test/hush-quoting/squote_in_varexp.right new file mode 100644 index 000000000..a75c0bfd6 --- /dev/null +++ b/shell/hush_test/hush-quoting/squote_in_varexp.right | |||
@@ -0,0 +1,5 @@ | |||
1 | z | ||
2 | z | ||
3 | y | ||
4 | y | ||
5 | Ok:0 | ||
diff --git a/shell/hush_test/hush-quoting/squote_in_varexp.tests b/shell/hush_test/hush-quoting/squote_in_varexp.tests new file mode 100755 index 000000000..a2d05a246 --- /dev/null +++ b/shell/hush_test/hush-quoting/squote_in_varexp.tests | |||
@@ -0,0 +1,6 @@ | |||
1 | x=yz | ||
2 | echo ${x#'y'} | ||
3 | echo "${x#'y'}" | ||
4 | echo ${x%'z'} | ||
5 | echo "${x%'z'}" | ||
6 | echo Ok:$? | ||
diff --git a/shell/hush_test/hush-quoting/squote_in_varexp1.right b/shell/hush_test/hush-quoting/squote_in_varexp1.right new file mode 100644 index 000000000..9d0add3c5 --- /dev/null +++ b/shell/hush_test/hush-quoting/squote_in_varexp1.right | |||
@@ -0,0 +1,3 @@ | |||
1 | Nothing: | ||
2 | Nothing: | ||
3 | Ok:0 | ||
diff --git a/shell/hush_test/hush-quoting/squote_in_varexp1.tests b/shell/hush_test/hush-quoting/squote_in_varexp1.tests new file mode 100755 index 000000000..efb380db3 --- /dev/null +++ b/shell/hush_test/hush-quoting/squote_in_varexp1.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | x='\\\\' | ||
2 | printf Nothing:'%s\n' ${x#\\\\\\\\} | ||
3 | printf Nothing:'%s\n' "${x#\\\\\\\\}" | ||
4 | echo Ok:$? | ||
diff --git a/shell/hush_test/hush-quoting/squote_in_varexp2.right b/shell/hush_test/hush-quoting/squote_in_varexp2.right new file mode 100644 index 000000000..9d0add3c5 --- /dev/null +++ b/shell/hush_test/hush-quoting/squote_in_varexp2.right | |||
@@ -0,0 +1,3 @@ | |||
1 | Nothing: | ||
2 | Nothing: | ||
3 | Ok:0 | ||
diff --git a/shell/hush_test/hush-quoting/squote_in_varexp2.tests b/shell/hush_test/hush-quoting/squote_in_varexp2.tests new file mode 100755 index 000000000..806ad12b9 --- /dev/null +++ b/shell/hush_test/hush-quoting/squote_in_varexp2.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | x='\\\\' | ||
2 | printf Nothing:'%s\n' ${x#'\\\\'} | ||
3 | printf Nothing:'%s\n' "${x#'\\\\'}" | ||
4 | echo Ok:$? | ||
diff --git a/shell/match.c b/shell/match.c index fee3cf2a8..ee8abb2db 100644 --- a/shell/match.c +++ b/shell/match.c | |||
@@ -71,9 +71,11 @@ char* FAST_FUNC scan_and_match(char *string, const char *pattern, unsigned flags | |||
71 | if (flags & SCAN_MATCH_LEFT_HALF) { | 71 | if (flags & SCAN_MATCH_LEFT_HALF) { |
72 | *loc = '\0'; | 72 | *loc = '\0'; |
73 | r = fnmatch(pattern, string, 0); | 73 | r = fnmatch(pattern, string, 0); |
74 | //bb_error_msg("fnmatch('%s','%s',0):%d", pattern, string, r); | ||
74 | *loc = c; | 75 | *loc = c; |
75 | } else { | 76 | } else { |
76 | r = fnmatch(pattern, loc, 0); | 77 | r = fnmatch(pattern, loc, 0); |
78 | //bb_error_msg("fnmatch('%s','%s',0):%d", pattern, loc, r); | ||
77 | } | 79 | } |
78 | if (r == 0) /* match found */ | 80 | if (r == 0) /* match found */ |
79 | return loc; | 81 | return loc; |
diff --git a/sysklogd/syslogd_and_logger.c b/sysklogd/syslogd_and_logger.c index 9bba195d4..94d8273b6 100644 --- a/sysklogd/syslogd_and_logger.c +++ b/sysklogd/syslogd_and_logger.c | |||
@@ -53,6 +53,7 @@ typedef struct _code { | |||
53 | static const CODE *const bb_prioritynames = prioritynames; | 53 | static const CODE *const bb_prioritynames = prioritynames; |
54 | static const CODE *const bb_facilitynames = facilitynames; | 54 | static const CODE *const bb_facilitynames = facilitynames; |
55 | 55 | ||
56 | |||
56 | #if ENABLE_SYSLOGD | 57 | #if ENABLE_SYSLOGD |
57 | #include "syslogd.c" | 58 | #include "syslogd.c" |
58 | #endif | 59 | #endif |
diff --git a/util-linux/ipcs.c b/util-linux/ipcs.c index 7092ecd92..4863a5c29 100644 --- a/util-linux/ipcs.c +++ b/util-linux/ipcs.c | |||
@@ -101,8 +101,6 @@ union semun { | |||
101 | #define TIME 4 | 101 | #define TIME 4 |
102 | #define PID 5 | 102 | #define PID 5 |
103 | 103 | ||
104 | static char format; | ||
105 | |||
106 | static void print_perms(int id, struct ipc_perm *ipcp) | 104 | static void print_perms(int id, struct ipc_perm *ipcp) |
107 | { | 105 | { |
108 | struct passwd *pw; | 106 | struct passwd *pw; |
@@ -125,8 +123,7 @@ static void print_perms(int id, struct ipc_perm *ipcp) | |||
125 | else printf(" %-10d\n", ipcp->gid); | 123 | else printf(" %-10d\n", ipcp->gid); |
126 | } | 124 | } |
127 | 125 | ||
128 | 126 | static NOINLINE void do_shm(int format) | |
129 | static NOINLINE void do_shm(void) | ||
130 | { | 127 | { |
131 | int maxid, shmid, id; | 128 | int maxid, shmid, id; |
132 | struct shmid_ds shmseg; | 129 | struct shmid_ds shmseg; |
@@ -252,8 +249,7 @@ static NOINLINE void do_shm(void) | |||
252 | } | 249 | } |
253 | } | 250 | } |
254 | 251 | ||
255 | 252 | static NOINLINE void do_sem(int format) | |
256 | static NOINLINE void do_sem(void) | ||
257 | { | 253 | { |
258 | int maxid, semid, id; | 254 | int maxid, semid, id; |
259 | struct semid_ds semary; | 255 | struct semid_ds semary; |
@@ -358,8 +354,7 @@ static NOINLINE void do_sem(void) | |||
358 | } | 354 | } |
359 | } | 355 | } |
360 | 356 | ||
361 | 357 | static NOINLINE void do_msg(int format) | |
362 | static NOINLINE void do_msg(void) | ||
363 | { | 358 | { |
364 | int maxid, msqid, id; | 359 | int maxid, msqid, id; |
365 | struct msqid_ds msgque; | 360 | struct msqid_ds msgque; |
@@ -466,7 +461,6 @@ static NOINLINE void do_msg(void) | |||
466 | } | 461 | } |
467 | } | 462 | } |
468 | 463 | ||
469 | |||
470 | static void print_shm(int shmid) | 464 | static void print_shm(int shmid) |
471 | { | 465 | { |
472 | struct shmid_ds shmds; | 466 | struct shmid_ds shmds; |
@@ -493,7 +487,6 @@ static void print_shm(int shmid) | |||
493 | printf("change_time=%-26.24s\n\n", ctime(&shmds.shm_ctime)); | 487 | printf("change_time=%-26.24s\n\n", ctime(&shmds.shm_ctime)); |
494 | } | 488 | } |
495 | 489 | ||
496 | |||
497 | static void print_msg(int msqid) | 490 | static void print_msg(int msqid) |
498 | { | 491 | { |
499 | struct msqid_ds buf; | 492 | struct msqid_ds buf; |
@@ -570,9 +563,9 @@ static void print_sem(int semid) | |||
570 | } | 563 | } |
571 | 564 | ||
572 | //usage:#define ipcs_trivial_usage | 565 | //usage:#define ipcs_trivial_usage |
573 | //usage: "[[-smq] -i shmid] | [[-asmq] [-tcplu]]" | 566 | //usage: "[[-smq] -i SHMID] | [[-asmq] [-tcplu]]" |
574 | //usage:#define ipcs_full_usage "\n\n" | 567 | //usage:#define ipcs_full_usage "\n\n" |
575 | //usage: " -i Show specific resource" | 568 | //usage: " -i ID Show specific resource" |
576 | //usage: "\nResource specification:" | 569 | //usage: "\nResource specification:" |
577 | //usage: "\n -m Shared memory segments" | 570 | //usage: "\n -m Shared memory segments" |
578 | //usage: "\n -q Message queues" | 571 | //usage: "\n -q Message queues" |
@@ -588,60 +581,57 @@ static void print_sem(int semid) | |||
588 | int ipcs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 581 | int ipcs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
589 | int ipcs_main(int argc UNUSED_PARAM, char **argv) | 582 | int ipcs_main(int argc UNUSED_PARAM, char **argv) |
590 | { | 583 | { |
591 | int id = 0; | 584 | int format = 0; |
592 | unsigned flags = 0; | ||
593 | unsigned opt; | 585 | unsigned opt; |
594 | char *opt_i; | 586 | char *opt_i; |
595 | #define flag_print (1<<0) | ||
596 | #define flag_msg (1<<1) | ||
597 | #define flag_sem (1<<2) | ||
598 | #define flag_shm (1<<3) | ||
599 | 587 | ||
600 | opt = getopt32(argv, "i:aqsmtcplu", &opt_i); | 588 | opt = getopt32(argv, "i:aqsmtcplu", &opt_i); |
601 | if (opt & 0x1) { // -i | 589 | #define flag_msg (1<<2) |
590 | #define flag_sem (1<<3) | ||
591 | #define flag_shm (1<<4) | ||
592 | if (opt & (1<<5)) format = TIME; // -t | ||
593 | if (opt & (1<<6)) format = CREATOR; // -c | ||
594 | if (opt & (1<<7)) format = PID; // -p | ||
595 | if (opt & (1<<8)) format = LIMITS; // -l | ||
596 | if (opt & (1<<9)) format = STATUS; // -u | ||
597 | |||
598 | if (opt & (1<<0)) { // -i | ||
599 | int id; | ||
600 | |||
602 | id = xatoi(opt_i); | 601 | id = xatoi(opt_i); |
603 | flags |= flag_print; | 602 | if (opt & flag_shm) { |
604 | } | ||
605 | if (opt & 0x2) flags |= flag_msg | flag_sem | flag_shm; // -a | ||
606 | if (opt & 0x4) flags |= flag_msg; // -q | ||
607 | if (opt & 0x8) flags |= flag_sem; // -s | ||
608 | if (opt & 0x10) flags |= flag_shm; // -m | ||
609 | if (opt & 0x20) format = TIME; // -t | ||
610 | if (opt & 0x40) format = CREATOR; // -c | ||
611 | if (opt & 0x80) format = PID; // -p | ||
612 | if (opt & 0x100) format = LIMITS; // -l | ||
613 | if (opt & 0x200) format = STATUS; // -u | ||
614 | |||
615 | if (flags & flag_print) { | ||
616 | if (flags & flag_shm) { | ||
617 | print_shm(id); | 603 | print_shm(id); |
618 | fflush_stdout_and_exit(EXIT_SUCCESS); | 604 | fflush_stdout_and_exit(EXIT_SUCCESS); |
619 | } | 605 | } |
620 | if (flags & flag_sem) { | 606 | if (opt & flag_sem) { |
621 | print_sem(id); | 607 | print_sem(id); |
622 | fflush_stdout_and_exit(EXIT_SUCCESS); | 608 | fflush_stdout_and_exit(EXIT_SUCCESS); |
623 | } | 609 | } |
624 | if (flags & flag_msg) { | 610 | if (opt & flag_msg) { |
625 | print_msg(id); | 611 | print_msg(id); |
626 | fflush_stdout_and_exit(EXIT_SUCCESS); | 612 | fflush_stdout_and_exit(EXIT_SUCCESS); |
627 | } | 613 | } |
628 | bb_show_usage(); | 614 | bb_show_usage(); |
629 | } | 615 | } |
630 | 616 | ||
631 | if (!(flags & (flag_shm | flag_msg | flag_sem))) | 617 | if ((opt & (1<<1)) // -a |
632 | flags |= flag_msg | flag_shm | flag_sem; | 618 | || !(opt & (flag_msg | flag_sem | flag_shm)) // none of -q,-s,-m == all |
619 | ) { | ||
620 | opt |= flag_msg | flag_sem | flag_shm; | ||
621 | } | ||
622 | |||
633 | bb_putchar('\n'); | 623 | bb_putchar('\n'); |
634 | 624 | ||
635 | if (flags & flag_msg) { | 625 | if (opt & flag_msg) { |
636 | do_msg(); | 626 | do_msg(format); |
637 | bb_putchar('\n'); | 627 | bb_putchar('\n'); |
638 | } | 628 | } |
639 | if (flags & flag_shm) { | 629 | if (opt & flag_shm) { |
640 | do_shm(); | 630 | do_shm(format); |
641 | bb_putchar('\n'); | 631 | bb_putchar('\n'); |
642 | } | 632 | } |
643 | if (flags & flag_sem) { | 633 | if (opt & flag_sem) { |
644 | do_sem(); | 634 | do_sem(format); |
645 | bb_putchar('\n'); | 635 | bb_putchar('\n'); |
646 | } | 636 | } |
647 | fflush_stdout_and_exit(EXIT_SUCCESS); | 637 | fflush_stdout_and_exit(EXIT_SUCCESS); |
diff --git a/util-linux/readprofile.c b/util-linux/readprofile.c index 8fc33be3c..219c0c18c 100644 --- a/util-linux/readprofile.c +++ b/util-linux/readprofile.c | |||
@@ -61,27 +61,22 @@ | |||
61 | 61 | ||
62 | #define S_LEN 128 | 62 | #define S_LEN 128 |
63 | 63 | ||
64 | /* These are the defaults */ | ||
65 | static const char defaultmap[] ALIGN1 = "/boot/System.map"; | ||
66 | static const char defaultpro[] ALIGN1 = "/proc/profile"; | ||
67 | |||
68 | int readprofile_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 64 | int readprofile_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
69 | int readprofile_main(int argc UNUSED_PARAM, char **argv) | 65 | int readprofile_main(int argc UNUSED_PARAM, char **argv) |
70 | { | 66 | { |
71 | FILE *map; | 67 | FILE *map; |
72 | const char *mapFile, *proFile; | 68 | const char *mapFile, *proFile; |
73 | unsigned long indx = 1; | 69 | unsigned long indx; |
74 | size_t len; | 70 | size_t len; |
75 | uint64_t add0 = 0; | 71 | uint64_t add0; |
76 | unsigned int step; | 72 | unsigned int step; |
77 | unsigned int *buf, total, fn_len; | 73 | unsigned int *buf, total, fn_len; |
78 | unsigned long long fn_add, next_add; /* current and next address */ | 74 | unsigned long long fn_add, next_add; /* current and next address */ |
79 | char fn_name[S_LEN], next_name[S_LEN]; /* current and next name */ | 75 | char fn_name[S_LEN], next_name[S_LEN]; /* current and next name */ |
80 | char mapline[S_LEN]; | 76 | char mapline[S_LEN]; |
81 | char mode[8]; | 77 | char mode[8]; |
82 | int maplineno = 1; | 78 | int maplineno; |
83 | int header_printed; | 79 | int multiplier; |
84 | int multiplier = 0; | ||
85 | unsigned opt; | 80 | unsigned opt; |
86 | enum { | 81 | enum { |
87 | OPT_M = (1 << 0), | 82 | OPT_M = (1 << 0), |
@@ -106,8 +101,9 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv) | |||
106 | 101 | ||
107 | #define next (current^1) | 102 | #define next (current^1) |
108 | 103 | ||
109 | proFile = defaultpro; | 104 | proFile = "/proc/profile"; |
110 | mapFile = defaultmap; | 105 | mapFile = "/boot/System.map"; |
106 | multiplier = 0; | ||
111 | 107 | ||
112 | opt = getopt32(argv, "M:+m:p:nabsirv", &multiplier, &mapFile, &proFile); | 108 | opt = getopt32(argv, "M:+m:p:nabsirv", &multiplier, &mapFile, &proFile); |
113 | 109 | ||
@@ -122,7 +118,7 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv) | |||
122 | if (!optMult) | 118 | if (!optMult) |
123 | to_write = 1; /* sth different from sizeof(int) */ | 119 | to_write = 1; /* sth different from sizeof(int) */ |
124 | 120 | ||
125 | fd = xopen(defaultpro, O_WRONLY); | 121 | fd = xopen("/proc/profile", O_WRONLY); |
126 | xwrite(fd, &multiplier, to_write); | 122 | xwrite(fd, &multiplier, to_write); |
127 | close(fd); | 123 | close(fd); |
128 | return EXIT_SUCCESS; | 124 | return EXIT_SUCCESS; |
@@ -133,12 +129,13 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv) | |||
133 | */ | 129 | */ |
134 | len = MAXINT(ssize_t); | 130 | len = MAXINT(ssize_t); |
135 | buf = xmalloc_xopen_read_close(proFile, &len); | 131 | buf = xmalloc_xopen_read_close(proFile, &len); |
132 | len /= sizeof(*buf); | ||
133 | |||
136 | if (!optNative) { | 134 | if (!optNative) { |
137 | int entries = len / sizeof(*buf); | 135 | int big = 0, small = 0; |
138 | int big = 0, small = 0, i; | ||
139 | unsigned *p; | 136 | unsigned *p; |
140 | 137 | ||
141 | for (p = buf+1; p < buf+entries; p++) { | 138 | for (p = buf+1; p < buf+len; p++) { |
142 | if (*p & ~0U << (sizeof(*buf)*4)) | 139 | if (*p & ~0U << (sizeof(*buf)*4)) |
143 | big++; | 140 | big++; |
144 | if (*p & ((1 << (sizeof(*buf)*4))-1)) | 141 | if (*p & ((1 << (sizeof(*buf)*4))-1)) |
@@ -147,15 +144,15 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv) | |||
147 | if (big > small) { | 144 | if (big > small) { |
148 | bb_error_msg("assuming reversed byte order, " | 145 | bb_error_msg("assuming reversed byte order, " |
149 | "use -n to force native byte order"); | 146 | "use -n to force native byte order"); |
150 | for (p = buf; p < buf+entries; p++) | 147 | BUILD_BUG_ON(sizeof(*p) > 8); |
151 | for (i = 0; i < sizeof(*buf)/2; i++) { | 148 | for (p = buf; p < buf+len; p++) { |
152 | unsigned char *b = (unsigned char *) p; | 149 | if (sizeof(*p) == 2) |
153 | unsigned char tmp; | 150 | *p = bswap_16(*p); |
154 | 151 | if (sizeof(*p) == 4) | |
155 | tmp = b[i]; | 152 | *p = bswap_32(*p); |
156 | b[i] = b[sizeof(*buf)-i-1]; | 153 | if (sizeof(*p) == 8) |
157 | b[sizeof(*buf)-i-1] = tmp; | 154 | *p = bb_bswap_64(*p); |
158 | } | 155 | } |
159 | } | 156 | } |
160 | } | 157 | } |
161 | 158 | ||
@@ -165,10 +162,9 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv) | |||
165 | return EXIT_SUCCESS; | 162 | return EXIT_SUCCESS; |
166 | } | 163 | } |
167 | 164 | ||
168 | total = 0; | ||
169 | |||
170 | map = xfopen_for_read(mapFile); | 165 | map = xfopen_for_read(mapFile); |
171 | 166 | add0 = 0; | |
167 | maplineno = 1; | ||
172 | while (fgets(mapline, S_LEN, map)) { | 168 | while (fgets(mapline, S_LEN, map)) { |
173 | if (sscanf(mapline, "%llx %s %s", &fn_add, mode, fn_name) != 3) | 169 | if (sscanf(mapline, "%llx %s %s", &fn_add, mode, fn_name) != 3) |
174 | bb_error_msg_and_die("%s(%i): wrong map line", | 170 | bb_error_msg_and_die("%s(%i): wrong map line", |
@@ -187,8 +183,11 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv) | |||
187 | /* | 183 | /* |
188 | * Main loop. | 184 | * Main loop. |
189 | */ | 185 | */ |
186 | total = 0; | ||
187 | indx = 1; | ||
190 | while (fgets(mapline, S_LEN, map)) { | 188 | while (fgets(mapline, S_LEN, map)) { |
191 | unsigned int this = 0; | 189 | bool header_printed; |
190 | unsigned int this; | ||
192 | 191 | ||
193 | if (sscanf(mapline, "%llx %s %s", &next_add, mode, next_name) != 3) | 192 | if (sscanf(mapline, "%llx %s %s", &next_add, mode, next_name) != 3) |
194 | bb_error_msg_and_die("%s(%i): wrong map line", | 193 | bb_error_msg_and_die("%s(%i): wrong map line", |
@@ -198,17 +197,17 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv) | |||
198 | 197 | ||
199 | /* ignore any LEADING (before a '[tT]' symbol is found) | 198 | /* ignore any LEADING (before a '[tT]' symbol is found) |
200 | Absolute symbols */ | 199 | Absolute symbols */ |
201 | if ((*mode == 'A' || *mode == '?') && total == 0) continue; | 200 | if ((mode[0] == 'A' || mode[0] == '?') && total == 0) |
202 | if (*mode != 'T' && *mode != 't' | 201 | continue; |
203 | && *mode != 'W' && *mode != 'w' | 202 | if ((mode[0]|0x20) != 't' && (mode[0]|0x20) != 'w') { |
204 | ) { | ||
205 | break; /* only text is profiled */ | 203 | break; /* only text is profiled */ |
206 | } | 204 | } |
207 | 205 | ||
208 | if (indx >= len / sizeof(*buf)) | 206 | if (indx >= len) |
209 | bb_error_msg_and_die("profile address out of range. " | 207 | bb_error_msg_and_die("profile address out of range. " |
210 | "Wrong map file?"); | 208 | "Wrong map file?"); |
211 | 209 | ||
210 | this = 0; | ||
212 | while (indx < (next_add-add0)/step) { | 211 | while (indx < (next_add-add0)/step) { |
213 | if (optBins && (buf[indx] || optAll)) { | 212 | if (optBins && (buf[indx] || optAll)) { |
214 | if (!header_printed) { | 213 | if (!header_printed) { |
@@ -256,7 +255,7 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv) | |||
256 | } | 255 | } |
257 | 256 | ||
258 | /* clock ticks, out of kernel text - probably modules */ | 257 | /* clock ticks, out of kernel text - probably modules */ |
259 | printf("%6u %s\n", buf[len/sizeof(*buf)-1], "*unknown*"); | 258 | printf("%6u *unknown*\n", buf[len-1]); |
260 | 259 | ||
261 | /* trailer */ | 260 | /* trailer */ |
262 | if (optVerbose) | 261 | if (optVerbose) |