From 744a20d8f9b1baf7c8cc1ed33ec744a52c89768f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 2 Mar 2018 17:13:22 +0100 Subject: shell: two new tests, both fail for ash and hush Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-quoting/bkslash_in_varexp.right | 5 +++++ shell/ash_test/ash-quoting/bkslash_in_varexp.tests | 6 ++++++ shell/ash_test/ash-quoting/squote_in_varexp.right | 5 +++++ shell/ash_test/ash-quoting/squote_in_varexp.tests | 6 ++++++ shell/hush_test/hush-quoting/bkslash_in_varexp.right | 5 +++++ shell/hush_test/hush-quoting/bkslash_in_varexp.tests | 6 ++++++ shell/hush_test/hush-quoting/squote_in_varexp.right | 5 +++++ shell/hush_test/hush-quoting/squote_in_varexp.tests | 6 ++++++ 8 files changed, 44 insertions(+) create mode 100644 shell/ash_test/ash-quoting/bkslash_in_varexp.right create mode 100755 shell/ash_test/ash-quoting/bkslash_in_varexp.tests create mode 100644 shell/ash_test/ash-quoting/squote_in_varexp.right create mode 100755 shell/ash_test/ash-quoting/squote_in_varexp.tests create mode 100644 shell/hush_test/hush-quoting/bkslash_in_varexp.right create mode 100755 shell/hush_test/hush-quoting/bkslash_in_varexp.tests create mode 100644 shell/hush_test/hush-quoting/squote_in_varexp.right create mode 100755 shell/hush_test/hush-quoting/squote_in_varexp.tests 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 @@ +Nothing: +Nothing: +Nothing: +Nothing: +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..41b31ab54 --- /dev/null +++ b/shell/ash_test/ash-quoting/bkslash_in_varexp.tests @@ -0,0 +1,6 @@ +x=a +echo Nothing:${x#[a\]]} +echo Nothing:"${x#[a\]]}" +echo Nothing:${x%[a\]]} +echo Nothing:"${x%[a\]]}" +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 @@ +z +z +y +y +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 @@ +x=yz +echo ${x#'y'} +echo "${x#'y'}" +echo ${x%'z'} +echo "${x%'z'}" +echo Ok:$? 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 @@ +Nothing: +Nothing: +Nothing: +Nothing: +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..41b31ab54 --- /dev/null +++ b/shell/hush_test/hush-quoting/bkslash_in_varexp.tests @@ -0,0 +1,6 @@ +x=a +echo Nothing:${x#[a\]]} +echo Nothing:"${x#[a\]]}" +echo Nothing:${x%[a\]]} +echo Nothing:"${x%[a\]]}" +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 @@ +z +z +y +y +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 @@ +x=yz +echo ${x#'y'} +echo "${x#'y'}" +echo ${x%'z'} +echo "${x%'z'}" +echo Ok:$? -- cgit v1.2.3-55-g6feb From 55f8133a4fb207d6fecd02f43c36809d3c2f6672 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 2 Mar 2018 18:12:12 +0100 Subject: shell: tweak bkslash_in_varexp.tests, add bkslash_in_varexp1.tests It turns out bkslash_in_varexp.tests was a bash bug :] ash and hush fail "corrected" bkslash_in_varexp.tests as well, just not as badly as I thought (hush gets half of the cases right). Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-quoting/bkslash_in_varexp.tests | 12 +++++++++++- shell/ash_test/ash-quoting/bkslash_in_varexp1.right | 5 +++++ shell/ash_test/ash-quoting/bkslash_in_varexp1.tests | 6 ++++++ shell/hush.c | 7 ++++--- shell/hush_test/hush-quoting/bkslash_in_varexp.tests | 12 +++++++++++- shell/hush_test/hush-quoting/bkslash_in_varexp1.right | 5 +++++ shell/hush_test/hush-quoting/bkslash_in_varexp1.tests | 6 ++++++ shell/match.c | 2 ++ 8 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 shell/ash_test/ash-quoting/bkslash_in_varexp1.right create mode 100755 shell/ash_test/ash-quoting/bkslash_in_varexp1.tests create mode 100644 shell/hush_test/hush-quoting/bkslash_in_varexp1.right create mode 100755 shell/hush_test/hush-quoting/bkslash_in_varexp1.tests diff --git a/shell/ash_test/ash-quoting/bkslash_in_varexp.tests b/shell/ash_test/ash-quoting/bkslash_in_varexp.tests index 41b31ab54..6c7b4b0cc 100755 --- a/shell/ash_test/ash-quoting/bkslash_in_varexp.tests +++ b/shell/ash_test/ash-quoting/bkslash_in_varexp.tests @@ -1,4 +1,14 @@ -x=a +x='a]' +# +# \] is not a valid escape for ] in set glob expression. +# Glob sets have no escaping at all: +# ] can be in a set if it is the first char: []abc], +# dash can be in a set if it is first or last: [abc-], +# [ and \ need no protections at all: [a[b\c] is a valid set of 5 chars. +# +# bash-4.3.43 misinterprets [a\]] as "set of 'a' or ']'". +# Correct interpretation is "set of 'a' or '\', followed by ']'". +# echo Nothing:${x#[a\]]} echo Nothing:"${x#[a\]]}" echo Nothing:${x%[a\]]} 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 @@ +Nothing: +Nothing: +Nothing: +Nothing: +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 @@ +x=a +echo Nothing:${x#[]a]} +echo Nothing:"${x#[]a]}" +echo Nothing:${x%[]a]} +echo Nothing:"${x%[]a]}" +echo Ok:$? diff --git a/shell/hush.c b/shell/hush.c index e005b0a20..da4967a8a 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 } if (ch == end_ch # if BASH_SUBSTR || BASH_PATTERN_SUBST - || ch == end_char2 + || ch == end_char2 # endif ) { if (!dbl) @@ -5842,17 +5842,18 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha unsigned scan_flags = pick_scan(exp_op, *exp_word); if (exp_op == *exp_word) /* ## or %% */ exp_word++; + debug_printf_expand("expand: exp_word:'%s'\n", exp_word); exp_exp_word = encode_then_expand_string(exp_word, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); if (exp_exp_word) exp_word = exp_exp_word; + debug_printf_expand("expand: exp_exp_word:'%s'\n", exp_word); /* HACK ALERT. We depend here on the fact that * G.global_argv and results of utoa and get_local_var_value * are actually in writable memory: * scan_and_match momentarily stores NULs there. */ t = (char*)val; loc = scan_and_match(t, exp_word, scan_flags); - //bb_error_msg("op:%c str:'%s' pat:'%s' res:'%s'", - // exp_op, t, exp_word, loc); + debug_printf_expand("op:%c str:'%s' pat:'%s' res:'%s'\n", exp_op, t, exp_word, loc); free(exp_exp_word); if (loc) { /* match was found */ if (scan_flags & SCAN_MATCH_LEFT_HALF) /* #[#] */ diff --git a/shell/hush_test/hush-quoting/bkslash_in_varexp.tests b/shell/hush_test/hush-quoting/bkslash_in_varexp.tests index 41b31ab54..6c7b4b0cc 100755 --- a/shell/hush_test/hush-quoting/bkslash_in_varexp.tests +++ b/shell/hush_test/hush-quoting/bkslash_in_varexp.tests @@ -1,4 +1,14 @@ -x=a +x='a]' +# +# \] is not a valid escape for ] in set glob expression. +# Glob sets have no escaping at all: +# ] can be in a set if it is the first char: []abc], +# dash can be in a set if it is first or last: [abc-], +# [ and \ need no protections at all: [a[b\c] is a valid set of 5 chars. +# +# bash-4.3.43 misinterprets [a\]] as "set of 'a' or ']'". +# Correct interpretation is "set of 'a' or '\', followed by ']'". +# echo Nothing:${x#[a\]]} echo Nothing:"${x#[a\]]}" echo Nothing:${x%[a\]]} 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 @@ +Nothing: +Nothing: +Nothing: +Nothing: +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 @@ +x=a +echo Nothing:${x#[]a]} +echo Nothing:"${x#[]a]}" +echo Nothing:${x%[]a]} +echo Nothing:"${x%[]a]}" +echo Ok:$? diff --git a/shell/match.c b/shell/match.c index fee3cf2a8..8f2a2fb38 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 if (flags & SCAN_MATCH_LEFT_HALF) { *loc = '\0'; r = fnmatch(pattern, string, 0); + //bb_error_msg("fnmatch('%s','%s',0):%d", pattern, string, r); *loc = c; } else { r = fnmatch(pattern, loc, 0); + //bb_error_msg("fnmatch('%s','%s',0):%d", pattern, string, r); } if (r == 0) /* match found */ return loc; -- cgit v1.2.3-55-g6feb From d4802c6243e64e28690577bc0bb4f030581c496b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 2 Mar 2018 20:48:36 +0100 Subject: hush: fix a='a\\'; echo "${a%\\\\}" Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-quoting/squote_in_varexp1.right | 3 +++ shell/ash_test/ash-quoting/squote_in_varexp1.tests | 4 ++++ shell/ash_test/ash-quoting/squote_in_varexp2.right | 3 +++ shell/ash_test/ash-quoting/squote_in_varexp2.tests | 4 ++++ shell/hush.c | 12 ++++++++++-- shell/hush_test/hush-quoting/squote_in_varexp1.right | 3 +++ shell/hush_test/hush-quoting/squote_in_varexp1.tests | 4 ++++ shell/hush_test/hush-quoting/squote_in_varexp2.right | 3 +++ shell/hush_test/hush-quoting/squote_in_varexp2.tests | 4 ++++ shell/match.c | 2 +- 10 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 shell/ash_test/ash-quoting/squote_in_varexp1.right create mode 100755 shell/ash_test/ash-quoting/squote_in_varexp1.tests create mode 100644 shell/ash_test/ash-quoting/squote_in_varexp2.right create mode 100755 shell/ash_test/ash-quoting/squote_in_varexp2.tests create mode 100644 shell/hush_test/hush-quoting/squote_in_varexp1.right create mode 100755 shell/hush_test/hush-quoting/squote_in_varexp1.tests create mode 100644 shell/hush_test/hush-quoting/squote_in_varexp2.right create mode 100755 shell/hush_test/hush-quoting/squote_in_varexp2.tests 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 @@ +Nothing: +Nothing: +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 @@ +x='\\\\' +printf Nothing:'%s\n' ${x#\\\\\\\\} +printf Nothing:'%s\n' "${x#\\\\\\\\}" +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 @@ +Nothing: +Nothing: +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 @@ +x='\\\\' +printf Nothing:'%s\n' ${x#'\\\\'} +printf Nothing:'%s\n' "${x#'\\\\'}" +echo Ok:$? diff --git a/shell/hush.c b/shell/hush.c index da4967a8a..762cc3fe4 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -4500,6 +4500,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign } } o_addchr(dest, ch); + //bb_error_msg("%s:o_addchr('%c')", __func__, ch); if (ch == '(' || ch == '{') { ch = (ch == '(' ? ')' : '}'); 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 /* \x. Copy verbatim. Important for \(, \) */ ch = i_getch(input); if (ch == EOF) { - syntax_error_unterm_ch(')'); + syntax_error_unterm_ch(end_ch); return 0; } #if 0 @@ -4540,6 +4541,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign } #endif o_addchr(dest, ch); + //bb_error_msg("%s:o_addchr('%c') after '\\'", __func__, ch); continue; } } @@ -5843,7 +5845,13 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha if (exp_op == *exp_word) /* ## or %% */ exp_word++; debug_printf_expand("expand: exp_word:'%s'\n", exp_word); - exp_exp_word = encode_then_expand_string(exp_word, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); + /* + * process_bkslash:1 unbackslash:1 breaks this: + * a='a\\'; echo ${a%\\\\} # correct output is: a + * process_bkslash:1 unbackslash:0 breaks this: + * a='a}'; echo ${a%\}} # correct output is: a + */ + exp_exp_word = encode_then_expand_string(exp_word, /*process_bkslash:*/ 0, /*unbackslash:*/ 0); if (exp_exp_word) exp_word = exp_exp_word; debug_printf_expand("expand: exp_exp_word:'%s'\n", exp_word); 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 @@ +Nothing: +Nothing: +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 @@ +x='\\\\' +printf Nothing:'%s\n' ${x#\\\\\\\\} +printf Nothing:'%s\n' "${x#\\\\\\\\}" +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 @@ +Nothing: +Nothing: +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 @@ +x='\\\\' +printf Nothing:'%s\n' ${x#'\\\\'} +printf Nothing:'%s\n' "${x#'\\\\'}" +echo Ok:$? diff --git a/shell/match.c b/shell/match.c index 8f2a2fb38..ee8abb2db 100644 --- a/shell/match.c +++ b/shell/match.c @@ -75,7 +75,7 @@ char* FAST_FUNC scan_and_match(char *string, const char *pattern, unsigned flags *loc = c; } else { r = fnmatch(pattern, loc, 0); - //bb_error_msg("fnmatch('%s','%s',0):%d", pattern, string, r); + //bb_error_msg("fnmatch('%s','%s',0):%d", pattern, loc, r); } if (r == 0) /* match found */ return loc; -- cgit v1.2.3-55-g6feb From d9aabfe578e58ef8a884c402d6294edc8dfda883 Mon Sep 17 00:00:00 2001 From: Sean MacLennan Date: Sun, 4 Mar 2018 23:15:59 +0100 Subject: make busybox more portable Move some distro specific include files into the appropriate #ifdef blocks to make the code more portable. Signed-off-by: Sean MacLennan Signed-off-by: Denys Vlasenko --- libbb/missing_syscalls.c | 5 ++--- libbb/vfork_daemon_rexec.c | 15 +++++++-------- 2 files changed, 9 insertions(+), 11 deletions(-) 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 @@ * * Licensed under GPLv2, see file LICENSE in this source tree. */ - //kbuild:lib-y += missing_syscalls.o -/*#include - for struct timex, but may collide with */ -#include #include "libbb.h" #if defined(ANDROID) || defined(__ANDROID__) +/*# include - for struct timex, but may collide with */ +# include pid_t getsid(pid_t pid) { return syscall(__NR_getsid, pid); diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 6125983ce..c0bea0ed2 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -14,14 +14,6 @@ * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ -#include -#ifndef PR_SET_NAME -#define PR_SET_NAME 15 -#endif -#ifndef PR_GET_NAME -#define PR_GET_NAME 16 -#endif - #include "busybox.h" /* uses applet tables */ #include "NUM_APPLETS.h" @@ -29,6 +21,13 @@ #define NOEXEC_SUPPORT ((NUM_APPLETS > 1) && (ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE)) #if defined(__linux__) && (NUM_APPLETS > 1) +# include +# ifndef PR_SET_NAME +# define PR_SET_NAME 15 +# endif +# ifndef PR_GET_NAME +# define PR_GET_NAME 16 +# endif void FAST_FUNC set_task_comm(const char *comm) { /* okay if too long (truncates) */ -- cgit v1.2.3-55-g6feb From 804ce5a6fed63a2da6268a2d06f1ee2075435297 Mon Sep 17 00:00:00 2001 From: Peter Lloyd Date: Mon, 5 Mar 2018 00:17:02 +0100 Subject: wget: fix fetching of https URLs with http proxy When fetching a https:// URL with HTTP proxy configured (e.g. with environment variable http_proxy=http://your-proxy:3128) busybox was making a https connection to the proxy. This was because the protocol scheme for the target URL was used to determine whether to connect to the proxy over SSL or not. When the proxy is in use, the decision on whether to connect to the proxy over https should based on the proxy URL not on the target URL. function old new delta wget_main 2381 2387 +6 Signed-off-by: Peter Lloyd Signed-off-by: Denys Vlasenko --- networking/wget.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/networking/wget.c b/networking/wget.c index 3a5d68173..8969310a4 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -1011,7 +1011,6 @@ static void download_one_url(const char *url) len_and_sockaddr *lsa; FILE *sfp; /* socket to web/ftp server */ FILE *dfp; /* socket to ftp server (data) */ - char *proxy = NULL; char *fname_out_alloc; char *redirected_path = NULL; struct host_info server; @@ -1027,13 +1026,14 @@ static void download_one_url(const char *url) /* Use the proxy if necessary */ use_proxy = (strcmp(G.proxy_flag, "off") != 0); if (use_proxy) { - proxy = getenv(target.protocol[0] == 'f' ? "ftp_proxy" : "http_proxy"); + char *proxy = getenv(target.protocol[0] == 'f' ? "ftp_proxy" : "http_proxy"); //FIXME: what if protocol is https? Ok to use http_proxy? use_proxy = (proxy && proxy[0]); if (use_proxy) parse_url(proxy, &server); } if (!use_proxy) { + server.protocol = target.protocol; server.port = target.port; if (ENABLE_FEATURE_IPV6) { //free(server.allocated); - can't be non-NULL @@ -1098,7 +1098,7 @@ static void download_one_url(const char *url) /* Open socket to http(s) server */ #if ENABLE_FEATURE_WGET_OPENSSL /* openssl (and maybe internal TLS) support is configured */ - if (target.protocol == P_HTTPS) { + if (server.protocol == P_HTTPS) { /* openssl-based helper * Inconvenient API since we can't give it an open fd */ @@ -1122,7 +1122,7 @@ static void download_one_url(const char *url) #elif ENABLE_FEATURE_WGET_HTTPS /* Only internal TLS support is configured */ sfp = open_socket(lsa); - if (target.protocol == P_HTTPS) + if (server.protocol == P_HTTPS) spawn_ssl_client(server.host, fileno(sfp), /*flags*/ 0); #else /* ssl (https) support is not configured */ -- cgit v1.2.3-55-g6feb From 8a5299fcfd54ae3b895b66249d6d105e956192cb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 5 Mar 2018 16:56:16 +0100 Subject: networking/interface.c: code shrink function old new delta ife_print 1293 1296 +3 display_interfaces 145 146 +1 if_readconf 162 141 -21 if_readlist_proc 631 560 -71 do_if_fetch 753 643 -110 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/3 up/down: 4/-202) Total: -198 bytes Signed-off-by: Denys Vlasenko --- networking/interface.c | 137 +++++++++++++++++++++++++++---------------------- 1 file changed, 76 insertions(+), 61 deletions(-) diff --git a/networking/interface.c b/networking/interface.c index 89427f2f4..0bbef9879 100644 --- a/networking/interface.c +++ b/networking/interface.c @@ -318,20 +318,27 @@ struct interface { char name[IFNAMSIZ]; /* interface name */ short type; /* if type */ short flags; /* various flags */ + int tx_queue_len; /* transmit queue length */ + + /* these should be contiguous, zeroed in one go in if_fetch(): */ +#define FIRST_TO_ZERO metric int metric; /* routing metric */ int mtu; /* MTU value */ - int tx_queue_len; /* transmit queue length */ struct ifmap map; /* hardware setup */ struct sockaddr addr; /* IP address */ struct sockaddr dstaddr; /* P-P IP address */ struct sockaddr broadaddr; /* IP broadcast address */ struct sockaddr netmask; /* IP network mask */ - int has_ip; char hwaddr[32]; /* HW address */ - int statistics_valid; +#define LAST_TO_ZERO hwaddr + + smallint has_ip; + smallint statistics_valid; struct user_net_device_stats stats; /* statistics */ +#if 0 /* UNUSED */ int keepalive; /* keepalive value for SLIP */ int outfill; /* outfill value for SLIP */ +#endif }; @@ -342,7 +349,7 @@ static struct interface *int_list, *int_last; #if 0 /* like strcmp(), but knows about numbers */ -except that the freshly added calls to xatoul() brf on ethernet aliases with +except that the freshly added calls to xatoul() barf on ethernet aliases with uClibc with e.g.: ife->name='lo' name='eth0:1' static int nstrcmp(const char *a, const char *b) { @@ -394,32 +401,31 @@ static struct interface *add_interface(char *name) return new; } -static char *get_name(char *name, char *p) +static char *get_name(char name[IFNAMSIZ], char *p) { - /* Extract from nul-terminated p where p matches - * : after leading whitespace. - * If match is not made, set name empty and return unchanged p + /* Extract NAME from nul-terminated p of the form "NAME:" + * If match is not made, set NAME to "" and return unchanged p. */ char *nameend; - char *namestart = skip_whitespace(p); + char *namestart; - nameend = namestart; - while (*nameend && *nameend != ':' && !isspace(*nameend)) - nameend++; - if (*nameend == ':') { - if ((nameend - namestart) < IFNAMSIZ) { + nameend = namestart = skip_whitespace(p); + + for (;;) { + if ((nameend - namestart) >= IFNAMSIZ) + break; /* interface name too large - return "" */ + if (*nameend == ':') { memcpy(name, namestart, nameend - namestart); name[nameend - namestart] = '\0'; - p = nameend; - } else { - /* Interface name too large */ - name[0] = '\0'; + return nameend + 1; } - } else { - /* trailing ':' not found - return empty */ - name[0] = '\0'; + nameend++; + /* isspace, NUL, any control char? */ + if ((unsigned char)*nameend <= (unsigned char)' ') + break; /* trailing ':' not found - return "" */ } - return p + 1; + name[0] = '\0'; + return p; } /* If scanf supports size qualifiers for %n conversions, then we can @@ -435,7 +441,10 @@ static char *get_name(char *name, char *p) /* "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" */ /* }; */ - /* Lie about the size of the int pointed to for %n. */ +/* We use %n for unavailable data in older versions of /proc/net/dev formats. + * This results in bogus stores to ife->FOO members corresponding to + * %n specifiers (even the size of integers may not match). + */ #if INT_MAX == LONG_MAX static const char *const ss_fmt[] = { "%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[] = { "%llu%llu%lu%lu%lu%lu%n%n%llu%llu%lu%lu%lu%lu%lu", "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" }; - #endif 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) memset(&ife->stats, 0, sizeof(struct user_net_device_stats)); sscanf(bp, ss_fmt[procnetdev_vsn], - &ife->stats.rx_bytes, /* missing for 0 */ + &ife->stats.rx_bytes, /* missing for v0 */ &ife->stats.rx_packets, &ife->stats.rx_errors, &ife->stats.rx_dropped, &ife->stats.rx_fifo_errors, &ife->stats.rx_frame_errors, - &ife->stats.rx_compressed, /* missing for <= 1 */ - &ife->stats.rx_multicast, /* missing for <= 1 */ - &ife->stats.tx_bytes, /* missing for 0 */ + &ife->stats.rx_compressed, /* missing for v0, v1 */ + &ife->stats.rx_multicast, /* missing for v0, v1 */ + &ife->stats.tx_bytes, /* missing for v0 */ &ife->stats.tx_packets, &ife->stats.tx_errors, &ife->stats.tx_dropped, &ife->stats.tx_fifo_errors, &ife->stats.collisions, &ife->stats.tx_carrier_errors, - &ife->stats.tx_compressed /* missing for <= 1 */ + &ife->stats.tx_compressed /* missing for v0, v1 */ ); if (procnetdev_vsn <= 1) { @@ -499,24 +507,21 @@ static int if_readconf(void) int numreqs = 30; struct ifconf ifc; struct ifreq *ifr; - int n, err = -1; + int n, err; int skfd; ifc.ifc_buf = NULL; /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets (as of 2.1.128) */ - skfd = socket(AF_INET, SOCK_DGRAM, 0); - if (skfd < 0) { - bb_perror_msg("error: no inet socket available"); - return -1; - } + skfd = xsocket(AF_INET, SOCK_DGRAM, 0); for (;;) { ifc.ifc_len = sizeof(struct ifreq) * numreqs; ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len); - if (ioctl_or_warn(skfd, SIOCGIFCONF, &ifc) < 0) { + err = ioctl_or_warn(skfd, SIOCGIFCONF, &ifc); + if (err < 0) { goto out; } if (ifc.ifc_len == (int)(sizeof(struct ifreq) * numreqs)) { @@ -565,7 +570,7 @@ static int if_readlist_proc(char *target) err = 0; while (fgets(buf, sizeof buf, fh)) { - char *s, name[128]; + char *s, name[IFNAMSIZ]; s = get_name(name, buf); ife = add_interface(name); @@ -574,11 +579,15 @@ static int if_readlist_proc(char *target) if (target && strcmp(target, name) == 0) break; } + +#if 0 /* we trust kernel to not be buggy, /proc/net/dev reads never fail */ if (ferror(fh)) { bb_perror_msg(_PATH_PROCNET_DEV); err = -1; proc_read = 0; } +#endif + fclose(fh); return err; } @@ -608,24 +617,29 @@ static int if_fetch(struct interface *ife) } ife->flags = ifr.ifr_flags; + /* set up default values if ioctl's would fail */ + ife->tx_queue_len = -1; /* unknown value */ + memset(&ife->FIRST_TO_ZERO, 0, + offsetof(struct interface, LAST_TO_ZERO) + - offsetof(struct interface, FIRST_TO_ZERO) + + sizeof(ife->LAST_TO_ZERO) + ); + strncpy_IFNAMSIZ(ifr.ifr_name, ifname); - memset(ife->hwaddr, 0, 32); if (ioctl(skfd, SIOCGIFHWADDR, &ifr) >= 0) memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8); +//er.... why this _isnt_ inside if()? ife->type = ifr.ifr_hwaddr.sa_family; strncpy_IFNAMSIZ(ifr.ifr_name, ifname); - ife->metric = 0; if (ioctl(skfd, SIOCGIFMETRIC, &ifr) >= 0) ife->metric = ifr.ifr_metric; strncpy_IFNAMSIZ(ifr.ifr_name, ifname); - ife->mtu = 0; if (ioctl(skfd, SIOCGIFMTU, &ifr) >= 0) ife->mtu = ifr.ifr_mtu; - memset(&ife->map, 0, sizeof(struct ifmap)); #ifdef SIOCGIFMAP strncpy_IFNAMSIZ(ifr.ifr_name, ifname); if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0) @@ -634,31 +648,24 @@ static int if_fetch(struct interface *ife) #ifdef HAVE_TXQUEUELEN strncpy_IFNAMSIZ(ifr.ifr_name, ifname); - ife->tx_queue_len = -1; /* unknown value */ if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) >= 0) ife->tx_queue_len = ifr.ifr_qlen; -#else - ife->tx_queue_len = -1; /* unknown value */ #endif strncpy_IFNAMSIZ(ifr.ifr_name, ifname); ifr.ifr_addr.sa_family = AF_INET; - memset(&ife->addr, 0, sizeof(struct sockaddr)); if (ioctl(skfd, SIOCGIFADDR, &ifr) == 0) { ife->has_ip = 1; ife->addr = ifr.ifr_addr; strncpy_IFNAMSIZ(ifr.ifr_name, ifname); - memset(&ife->dstaddr, 0, sizeof(struct sockaddr)); if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) >= 0) ife->dstaddr = ifr.ifr_dstaddr; strncpy_IFNAMSIZ(ifr.ifr_name, ifname); - memset(&ife->broadaddr, 0, sizeof(struct sockaddr)); if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) >= 0) ife->broadaddr = ifr.ifr_broadaddr; strncpy_IFNAMSIZ(ifr.ifr_name, ifname); - memset(&ife->netmask, 0, sizeof(struct sockaddr)); if (ioctl(skfd, SIOCGIFNETMASK, &ifr) >= 0) ife->netmask = ifr.ifr_netmask; } @@ -1020,9 +1027,11 @@ static void ife_print(struct interface *ptr) /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */ printf(" MTU:%d Metric:%d", ptr->mtu, ptr->metric ? ptr->metric : 1); +#if 0 #ifdef SIOCSKEEPALIVE if (ptr->outfill || ptr->keepalive) printf(" Outfill:%d Keepalive:%d", ptr->outfill, ptr->keepalive); +#endif #endif bb_putchar('\n'); @@ -1105,8 +1114,11 @@ static int for_all_interfaces(int (*doit) (struct interface *, void *), { struct interface *ife; - if (!int_list && (if_readlist() < 0)) - return -1; + if (!int_list) { + int err = if_readlist(); + if (err < 0) + return err; + } for (ife = int_list; ife; ife = ife->next) { int err = doit(ife, cookie); if (err) @@ -1124,8 +1136,11 @@ static int if_print(char *ifname) if (!ifname) { /*res = for_all_interfaces(do_if_print, &interface_opt_a);*/ - if (!int_list && (if_readlist() < 0)) - return -1; + if (!int_list) { + int err = if_readlist(); + if (err < 0) + return err; + } for (ife = int_list; ife; ife = ife->next) { int err = do_if_print(ife); /*, &interface_opt_a);*/ if (err) @@ -1140,6 +1155,15 @@ static int if_print(char *ifname) return res; } +int FAST_FUNC display_interfaces(char *ifname) +{ + int status; + + status = if_print(ifname); + + return (status < 0); /* status < 0 == 1 -- error */ +} + #if ENABLE_FEATURE_HWIB /* Input an Infiniband address and convert to binary. */ int FAST_FUNC in_ib(const char *bufp, struct sockaddr *sap) @@ -1153,12 +1177,3 @@ int FAST_FUNC in_ib(const char *bufp, struct sockaddr *sap) return 0; } #endif - -int FAST_FUNC display_interfaces(char *ifname) -{ - int status; - - status = if_print(ifname); - - return (status < 0); /* status < 0 == 1 -- error */ -} -- cgit v1.2.3-55-g6feb From 82ec89480d524a219ad027d1f7c5aa42cc6373d5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 5 Mar 2018 17:46:17 +0100 Subject: networking/interface.c: get rid of global "smallint interface_opt_a" Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 +- networking/ifconfig.c | 8 +++++--- networking/interface.c | 37 ++++++++++++++----------------------- 3 files changed, 20 insertions(+), 27 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index f1ab1ca6f..fa878433e 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1367,7 +1367,7 @@ struct hwtype { int FAST_FUNC (*activate)(int fd); int suppress_null_addr; }; -extern smallint interface_opt_a; +#define IFNAME_SHOW_DOWNED_TOO ((char*)(intptr_t)1) int display_interfaces(char *ifname) FAST_FUNC; int in_ether(const char *bufp, struct sockaddr *sap) FAST_FUNC; #if ENABLE_FEATURE_HWIB 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) char *p; /*char host[128];*/ const char *host = NULL; /* make gcc happy */ + IF_FEATURE_IFCONFIG_STATUS(char *show_all_param;) did_flags = 0; #if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS @@ -349,15 +350,16 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv) ++argv; #if ENABLE_FEATURE_IFCONFIG_STATUS - if (argv[0] && (argv[0][0] == '-' && argv[0][1] == 'a' && !argv[0][2])) { - interface_opt_a = 1; + show_all_param = NULL; + if (argv[0] && argv[0][0] == '-' && argv[0][1] == 'a' && !argv[0][2]) { ++argv; + show_all_param = IFNAME_SHOW_DOWNED_TOO; } #endif if (!argv[0] || !argv[1]) { /* one or no args */ #if ENABLE_FEATURE_IFCONFIG_STATUS - return display_interfaces(argv[0] /* can be NULL */); + return display_interfaces(argv[0] ? argv[0] : show_all_param); #else bb_error_msg_and_die("no support for status display"); #endif diff --git a/networking/interface.c b/networking/interface.c index 0bbef9879..ff99c2981 100644 --- a/networking/interface.c +++ b/networking/interface.c @@ -342,8 +342,6 @@ struct interface { }; -smallint interface_opt_a; /* show all interfaces */ - static struct interface *int_list, *int_last; @@ -1086,13 +1084,13 @@ static void ife_print(struct interface *ptr) bb_putchar('\n'); } -static int do_if_print(struct interface *ife) /*, int *opt_a)*/ +static int do_if_print(struct interface *ife, int show_downed_too) { int res; res = do_if_fetch(ife); if (res >= 0) { - if ((ife->flags & IFF_UP) || interface_opt_a) + if ((ife->flags & IFF_UP) || show_downed_too) ife_print(ife); } return res; @@ -1128,40 +1126,33 @@ static int for_all_interfaces(int (*doit) (struct interface *, void *), } #endif -/* for ipv4 add/del modes */ -static int if_print(char *ifname) +int FAST_FUNC display_interfaces(char *ifname) { struct interface *ife; int res; - if (!ifname) { + if (!ifname || ifname == IFNAME_SHOW_DOWNED_TOO) { /*res = for_all_interfaces(do_if_print, &interface_opt_a);*/ if (!int_list) { - int err = if_readlist(); - if (err < 0) - return err; + res = if_readlist(); + if (res < 0) + goto ret; } for (ife = int_list; ife; ife = ife->next) { - int err = do_if_print(ife); /*, &interface_opt_a);*/ - if (err) - return err; + BUILD_BUG_ON((int)(intptr_t)IFNAME_SHOW_DOWNED_TOO != 1); + res = do_if_print(ife, (int)(intptr_t)ifname); + if (res < 0) + goto ret; } return 0; } + ife = lookup_interface(ifname); res = do_if_fetch(ife); if (res >= 0) ife_print(ife); - return res; -} - -int FAST_FUNC display_interfaces(char *ifname) -{ - int status; - - status = if_print(ifname); - - return (status < 0); /* status < 0 == 1 -- error */ + ret: + return (res < 0); /* status < 0 == 1 -- error */ } #if ENABLE_FEATURE_HWIB -- cgit v1.2.3-55-g6feb From d51ba0b5ab13aa09ab0482bd2dc63f39e8b40fad Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 5 Mar 2018 18:28:04 +0100 Subject: networking/interface.c: get rid of global data These were data/bss: static.proc_read 1 - -1 int_list 4 - -4 int_last 4 - -4 We never call display_interfaces() twice, thus code to not scan /proc twice never triggers. function old new delta do_if_print - 1998 +1998 display_interfaces 145 249 +104 static.proc_read 1 - -1 add_interface 104 103 -1 int_list 4 - -4 int_last 4 - -4 if_readlist_proc 560 542 -18 if_readconf 141 - -141 do_if_fetch 643 - -643 ife_print 1296 - -1296 ------------------------------------------------------------------------------ (add/remove: 1/6 grow/shrink: 1/2 up/down: 2102/-2108) Total: -6 bytes text data bss dec hex filename 933084 473 6844 940401 e5971 busybox_old 933087 473 6836 940396 e596c busybox_unstripped Signed-off-by: Denys Vlasenko --- networking/interface.c | 121 +++++++++++++++---------------------------------- 1 file changed, 36 insertions(+), 85 deletions(-) diff --git a/networking/interface.c b/networking/interface.c index ff99c2981..e5e55d8d4 100644 --- a/networking/interface.c +++ b/networking/interface.c @@ -341,8 +341,9 @@ struct interface { #endif }; - -static struct interface *int_list, *int_last; +struct iface_list { + struct interface *int_list, *int_last; +}; #if 0 @@ -373,11 +374,11 @@ static int nstrcmp(const char *a, const char *b) } #endif -static struct interface *add_interface(char *name) +static struct interface *add_interface(struct iface_list *ilist, char *name) { struct interface *ife, **nextp, *new; - for (ife = int_last; ife; ife = ife->prev) { + for (ife = ilist->int_last; ife; ife = ife->prev) { int n = /*n*/strcmp(ife->name, name); if (n == 0) @@ -388,13 +389,14 @@ static struct interface *add_interface(char *name) new = xzalloc(sizeof(*new)); strncpy_IFNAMSIZ(new->name, name); - nextp = ife ? &ife->next : &int_list; + + nextp = ife ? &ife->next : &ilist->int_list; new->prev = ife; new->next = *nextp; if (new->next) new->next->prev = new; else - int_last = new; + ilist->int_last = new; *nextp = new; return new; } @@ -500,12 +502,12 @@ static int procnetdev_version(char *buf) return 0; } -static int if_readconf(void) +static void if_readconf(struct iface_list *ilist) { int numreqs = 30; struct ifconf ifc; struct ifreq *ifr; - int n, err; + int n; int skfd; ifc.ifc_buf = NULL; @@ -518,10 +520,7 @@ static int if_readconf(void) ifc.ifc_len = sizeof(struct ifreq) * numreqs; ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len); - err = ioctl_or_warn(skfd, SIOCGIFCONF, &ifc); - if (err < 0) { - goto out; - } + xioctl(skfd, SIOCGIFCONF, &ifc); if (ifc.ifc_len == (int)(sizeof(struct ifreq) * numreqs)) { /* assume it overflowed and try again */ numreqs += 10; @@ -532,71 +531,54 @@ static int if_readconf(void) ifr = ifc.ifc_req; for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) { - add_interface(ifr->ifr_name); + add_interface(ilist, ifr->ifr_name); ifr++; } - err = 0; - out: close(skfd); free(ifc.ifc_buf); - return err; } -static int if_readlist_proc(char *target) +static int if_readlist_proc(struct iface_list *ilist, char *ifname) { - static smallint proc_read; - FILE *fh; char buf[512]; struct interface *ife; - int err, procnetdev_vsn; - - if (proc_read) - return 0; - if (!target) - proc_read = 1; + int procnetdev_vsn; + int ret; fh = fopen_or_warn(_PATH_PROCNET_DEV, "r"); if (!fh) { - return if_readconf(); + return 0; /* "not found" */ } fgets(buf, sizeof buf, fh); /* eat line */ fgets(buf, sizeof buf, fh); procnetdev_vsn = procnetdev_version(buf); - err = 0; + ret = 0; while (fgets(buf, sizeof buf, fh)) { char *s, name[IFNAMSIZ]; s = get_name(name, buf); - ife = add_interface(name); + ife = add_interface(ilist, name); get_dev_fields(s, ife, procnetdev_vsn); ife->statistics_valid = 1; - if (target && strcmp(target, name) == 0) + if (ifname && strcmp(ifname, name) == 0) { + ret = 1; /* found */ break; + } } - -#if 0 /* we trust kernel to not be buggy, /proc/net/dev reads never fail */ - if (ferror(fh)) { - bb_perror_msg(_PATH_PROCNET_DEV); - err = -1; - proc_read = 0; - } -#endif - fclose(fh); - return err; + return ret; } -static int if_readlist(void) +static void if_readlist(struct iface_list *ilist, char *ifname) { - int err = if_readlist_proc(NULL); + int found = if_readlist_proc(ilist, ifname); /* Needed in order to get ethN:M aliases */ - if (!err) - err = if_readconf(); - return err; + if (!found) + if_readconf(ilist); } /* Fetch the interface configuration from the kernel. */ @@ -1096,50 +1078,21 @@ static int do_if_print(struct interface *ife, int show_downed_too) return res; } -static struct interface *lookup_interface(char *name) -{ - struct interface *ife = NULL; - - if (if_readlist_proc(name) < 0) - return NULL; - ife = add_interface(name); - return ife; -} - -#ifdef UNUSED -static int for_all_interfaces(int (*doit) (struct interface *, void *), - void *cookie) -{ - struct interface *ife; - - if (!int_list) { - int err = if_readlist(); - if (err < 0) - return err; - } - for (ife = int_list; ife; ife = ife->next) { - int err = doit(ife, cookie); - if (err) - return err; - } - return 0; -} -#endif - int FAST_FUNC display_interfaces(char *ifname) { struct interface *ife; int res; + struct iface_list ilist; + + ilist.int_list = NULL; + ilist.int_last = NULL; + if_readlist(&ilist, ifname != IFNAME_SHOW_DOWNED_TOO ? ifname : NULL); if (!ifname || ifname == IFNAME_SHOW_DOWNED_TOO) { - /*res = for_all_interfaces(do_if_print, &interface_opt_a);*/ - if (!int_list) { - res = if_readlist(); - if (res < 0) - goto ret; - } - for (ife = int_list; ife; ife = ife->next) { + for (ife = ilist.int_list; ife; ife = ife->next) { + BUILD_BUG_ON((int)(intptr_t)IFNAME_SHOW_DOWNED_TOO != 1); + res = do_if_print(ife, (int)(intptr_t)ifname); if (res < 0) goto ret; @@ -1147,10 +1100,8 @@ int FAST_FUNC display_interfaces(char *ifname) return 0; } - ife = lookup_interface(ifname); - res = do_if_fetch(ife); - if (res >= 0) - ife_print(ife); + ife = add_interface(&ilist, ifname); + res = do_if_print(ife, /*show_downed_too:*/ 1); ret: return (res < 0); /* status < 0 == 1 -- error */ } -- cgit v1.2.3-55-g6feb From 33f7c8f200b6c3f7163dc89723ab67462688dccd Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 6 Mar 2018 17:21:57 +0100 Subject: hush: code shrink function old new delta run_pipe 1589 1591 +2 pseudo_exec_argv 374 375 +1 builtin_type 114 115 +1 find_function 8 - -8 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 3/0 up/down: 4/-8) Total: -4 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 762cc3fe4..6e64efb70 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -7181,21 +7181,22 @@ static const struct built_in_command *find_builtin(const char *name) #if ENABLE_HUSH_FUNCTIONS static struct function **find_function_slot(const char *name) { + struct function *funcp; struct function **funcpp = &G.top_func; - while (*funcpp) { - if (strcmp(name, (*funcpp)->name) == 0) { + + while ((funcp = *funcpp) != NULL) { + if (strcmp(name, funcp->name) == 0) { + debug_printf_exec("found function '%s'\n", name); break; } - funcpp = &(*funcpp)->next; + funcpp = &funcp->next; } return funcpp; } -static const struct function *find_function(const char *name) +static ALWAYS_INLINE const struct function *find_function(const char *name) { const struct function *funcp = *find_function_slot(name); - if (funcp) - debug_printf_exec("found function '%s'\n", name); return funcp; } -- cgit v1.2.3-55-g6feb From e1b1b7926975c3cd4313be0019212b1cf68fa529 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 6 Mar 2018 18:11:47 +0100 Subject: use gmtime_r() instead of gmtime() This avoids pulling in gmtime's static buffer: function old new delta svlogd_main 1401 1412 +11 send_headers 668 678 +10 gmtime 21 - -21 ------------------------------------------------------------------------------ (add/remove: 0/2 grow/shrink: 2/0 up/down: 21/-21) Total: 0 bytes text data bss dec hex filename 920221 555 5804 926580 e2374 busybox_old 920221 555 5740 926516 e2334 busybox_unstripped ^^^^ Signed-off-by: Denys Vlasenko --- networking/httpd.c | 6 ++++-- runit/svlogd.c | 4 +++- sysklogd/syslogd_and_logger.c | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) 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) /* Fixed size 29-byte string. Example: Sun, 06 Nov 1994 08:49:37 GMT */ char date_str[40]; /* using a bit larger buffer to paranoia reasons */ + struct tm tm; const char *responseString = ""; const char *infoString = NULL; #if ENABLE_FEATURE_HTTPD_ERROR_PAGES @@ -1074,7 +1075,8 @@ static void send_headers(int responseNum) * always fit into those kbytes. */ - strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime(&timer)); + strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime_r(&timer, &tm)); + /* ^^^ using gmtime_r() instead of gmtime() to not use static data */ len = sprintf(iobuf, "HTTP/1.0 %d %s\r\n" "Content-type: %s\r\n" @@ -1128,7 +1130,7 @@ static void send_headers(int responseNum) #endif if (file_size != -1) { /* file */ - strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime(&last_mod)); + strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime_r(&last_mod, &tm)); #if ENABLE_FEATURE_HTTPD_RANGES if (responseNum == HTTP_PARTIAL_CONTENT) { len += sprintf(iobuf + len, 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) /* NUL terminated */ static void fmt_time_human_30nul(char *s, char dt_delim) { + struct tm tm; struct tm *ptm; struct timeval tv; gettimeofday(&tv, NULL); - ptm = gmtime(&tv.tv_sec); + ptm = gmtime_r(&tv.tv_sec, &tm); + /* ^^^ using gmtime_r() instead of gmtime() to not use static data */ sprintf(s, "%04u-%02u-%02u%c%02u:%02u:%02u.%06u000", (unsigned)(1900 + ptm->tm_year), (unsigned)(ptm->tm_mon + 1), 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 { static const CODE *const bb_prioritynames = prioritynames; static const CODE *const bb_facilitynames = facilitynames; + #if ENABLE_SYSLOGD #include "syslogd.c" #endif -- cgit v1.2.3-55-g6feb From 86107d6dc7b6a182e01fb8296cb4e1680963184d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 7 Mar 2018 03:59:52 +0100 Subject: top: handle much larger VSZ values function old new delta display_process_list 1018 999 -19 Signed-off-by: Denys Vlasenko --- procps/top.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/procps/top.c b/procps/top.c index b777c494e..9bb3eed29 100644 --- a/procps/top.c +++ b/procps/top.c @@ -607,7 +607,6 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width) }; top_status_t *s; - char vsz_str_buf[8]; unsigned long total_memory = display_header(scr_width, &lines_rem); /* or use total_vsz? */ /* xxx_shift and xxx_scale variables allow us to replace * expensive divides with multiply and shift */ @@ -688,19 +687,18 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width) lines_rem = ntop - G_scroll_ofs; s = top + G_scroll_ofs; while (--lines_rem >= 0) { + char vsz_str_buf[8]; unsigned col; + CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift); #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE CALC_STAT(pcpu, (s->pcpu*pcpu_scale + pcpu_half) >> pcpu_shift); #endif - if (s->vsz >= 100000) - sprintf(vsz_str_buf, "%6ldm", s->vsz/1024); - else - sprintf(vsz_str_buf, "%7lu", s->vsz); + smart_ulltoa5(s->vsz, vsz_str_buf, " mgtpezy"); /* PID PPID USER STAT VSZ %VSZ [%CPU] COMMAND */ col = snprintf(line_buf, scr_width, - "\n" "%5u%6u %-8.8s %s%s" FMT + "\n" "%5u%6u %-8.8s %s %.5s" FMT IF_FEATURE_TOP_SMP_PROCESS(" %3d") IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(FMT) " ", @@ -710,7 +708,7 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width) IF_FEATURE_TOP_SMP_PROCESS(, s->last_seen_on_cpu) IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(, SHOW_STAT(pcpu)) ); - if ((int)(col + 1) < scr_width) + if ((int)(scr_width - col) > 1) read_cmdline(line_buf + col, scr_width - col, s->pid, s->comm); fputs(line_buf, stdout); /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu, -- cgit v1.2.3-55-g6feb From 75e56a3db9c1415dac1a3d83a12f694930897a8c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 7 Mar 2018 04:20:22 +0100 Subject: top: do unsigned rather than signed division in do_stats() Signed-off-by: Denys Vlasenko --- procps/top.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/procps/top.c b/procps/top.c index 9bb3eed29..fc056621b 100644 --- a/procps/top.c +++ b/procps/top.c @@ -180,7 +180,7 @@ struct globals { #else cmp_funcp sort_function[SORT_DEPTH]; struct save_hist *prev_hist; - int prev_hist_count; + unsigned prev_hist_count; jiffy_counts_t cur_jif, prev_jif; /* int hist_iterations; */ unsigned total_pcpu; @@ -189,7 +189,7 @@ struct globals { #if ENABLE_FEATURE_TOP_SMP_CPU /* Per CPU samples: current and last */ jiffy_counts_t *cpu_jif, *cpu_prev_jif; - int num_cpus; + unsigned num_cpus; #endif #if ENABLE_FEATURE_TOP_INTERACTIVE char kbd_input[KEYCODE_BUFFER_SIZE]; @@ -355,7 +355,8 @@ static void do_stats(void) { top_status_t *cur; pid_t pid; - int i, last_i, n; + int n; + unsigned i, last_i; struct save_hist *new_hist; get_jiffy_counts(); -- cgit v1.2.3-55-g6feb From a2cae937d026d70f5014b95498b08251f73d39eb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 7 Mar 2018 04:47:52 +0100 Subject: top: much faster cursor key navigation by avoiding process rescan function old new delta handle_input 549 560 +11 top_main 889 891 +2 Signed-off-by: Denys Vlasenko --- procps/top.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/procps/top.c b/procps/top.c index fc056621b..075c96c27 100644 --- a/procps/top.c +++ b/procps/top.c @@ -896,7 +896,8 @@ enum { | PSSCAN_PID | PSSCAN_SMAPS | PSSCAN_COMM, - EXIT_MASK = (unsigned)-1, + EXIT_MASK = 0, + NO_RESCAN_MASK = (unsigned)-1, }; #if ENABLE_FEATURE_TOP_INTERACTIVE @@ -934,7 +935,7 @@ static unsigned handle_input(unsigned scan_mask, unsigned interval) } if (c == KEYCODE_HOME) { G_scroll_ofs = 0; - break; + goto normalize_ofs; } if (c == KEYCODE_END) { G_scroll_ofs = ntop - G.lines / 2; @@ -951,7 +952,7 @@ static unsigned handle_input(unsigned scan_mask, unsigned interval) G_scroll_ofs = ntop - 1; if (G_scroll_ofs < 0) G_scroll_ofs = 0; - break; + return NO_RESCAN_MASK; } c |= 0x20; /* lowercase */ @@ -1156,6 +1157,7 @@ int top_main(int argc UNUSED_PARAM, char **argv) #endif while (scan_mask != EXIT_MASK) { + unsigned new_mask; procps_status_t *p = NULL; if (OPT_BATCH_MODE) { @@ -1233,21 +1235,32 @@ int top_main(int argc UNUSED_PARAM, char **argv) #else qsort(top, ntop, sizeof(top_status_t), (void*)(sort_function[0])); #endif - display_process_list(G.lines, col); } #if ENABLE_FEATURE_TOPMEM else { /* TOPMEM */ qsort(topmem, ntop, sizeof(topmem_status_t), (void*)topmem_sort); + } +#endif + IF_FEATURE_TOP_INTERACTIVE(display:) + IF_FEATURE_TOPMEM(if (scan_mask != TOPMEM_MASK)) { + display_process_list(G.lines, col); + } +#if ENABLE_FEATURE_TOPMEM + else { /* TOPMEM */ display_topmem_process_list(G.lines, col); } #endif - clearmems(); if (iterations >= 0 && !--iterations) break; #if !ENABLE_FEATURE_TOP_INTERACTIVE + clearmems(); sleep(interval); #else - scan_mask = handle_input(scan_mask, interval); + new_mask = handle_input(scan_mask, interval); + if (new_mask == NO_RESCAN_MASK) + goto display; + scan_mask = new_mask; + clearmems(); #endif } /* end of "while (not Q)" */ -- cgit v1.2.3-55-g6feb From 694bc0634587e2535567c1732a372ec79ba0e0c7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 8 Mar 2018 12:47:13 +0100 Subject: md5sum: use config help text similar to other "sum" tools Signed-off-by: Denys Vlasenko --- coreutils/md5_sha1_sum.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 @@ //config: bool "md5sum (6.8 kb)" //config: default y //config: help -//config: md5sum is used to print or check MD5 checksums. +//config: Compute and check MD5 message digest //config: //config:config SHA1SUM //config: bool "sha1sum (6 kb)" -- cgit v1.2.3-55-g6feb From f7fa8001b7db605b8ab18c688051583f6d5b687f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 8 Mar 2018 13:10:23 +0100 Subject: ipcs: code shrink function old new delta packed_usage 32539 32543 +4 format 1 - -1 do_shm 883 880 -3 do_sem 636 633 -3 do_msg 782 779 -3 ipcs_main 1049 1014 -35 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/4 up/down: 4/-45) Total: -41 bytes Signed-off-by: Denys Vlasenko --- util-linux/ipcs.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/util-linux/ipcs.c b/util-linux/ipcs.c index 7092ecd92..dc107eb95 100644 --- a/util-linux/ipcs.c +++ b/util-linux/ipcs.c @@ -101,8 +101,6 @@ union semun { #define TIME 4 #define PID 5 -static char format; - static void print_perms(int id, struct ipc_perm *ipcp) { struct passwd *pw; @@ -125,8 +123,7 @@ static void print_perms(int id, struct ipc_perm *ipcp) else printf(" %-10d\n", ipcp->gid); } - -static NOINLINE void do_shm(void) +static NOINLINE void do_shm(int format) { int maxid, shmid, id; struct shmid_ds shmseg; @@ -252,8 +249,7 @@ static NOINLINE void do_shm(void) } } - -static NOINLINE void do_sem(void) +static NOINLINE void do_sem(int format) { int maxid, semid, id; struct semid_ds semary; @@ -358,8 +354,7 @@ static NOINLINE void do_sem(void) } } - -static NOINLINE void do_msg(void) +static NOINLINE void do_msg(int format) { int maxid, msqid, id; struct msqid_ds msgque; @@ -466,7 +461,6 @@ static NOINLINE void do_msg(void) } } - static void print_shm(int shmid) { struct shmid_ds shmds; @@ -493,7 +487,6 @@ static void print_shm(int shmid) printf("change_time=%-26.24s\n\n", ctime(&shmds.shm_ctime)); } - static void print_msg(int msqid) { struct msqid_ds buf; @@ -570,7 +563,7 @@ static void print_sem(int semid) } //usage:#define ipcs_trivial_usage -//usage: "[[-smq] -i shmid] | [[-asmq] [-tcplu]]" +//usage: "[[-smq] -i SHMID] | [[-asmq] [-tcplu]]" //usage:#define ipcs_full_usage "\n\n" //usage: " -i Show specific resource" //usage: "\nResource specification:" @@ -588,20 +581,15 @@ static void print_sem(int semid) int ipcs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int ipcs_main(int argc UNUSED_PARAM, char **argv) { - int id = 0; + int format = 0; unsigned flags = 0; unsigned opt; char *opt_i; -#define flag_print (1<<0) -#define flag_msg (1<<1) -#define flag_sem (1<<2) -#define flag_shm (1<<3) +#define flag_msg (1<<0) +#define flag_sem (1<<1) +#define flag_shm (1<<2) opt = getopt32(argv, "i:aqsmtcplu", &opt_i); - if (opt & 0x1) { // -i - id = xatoi(opt_i); - flags |= flag_print; - } if (opt & 0x2) flags |= flag_msg | flag_sem | flag_shm; // -a if (opt & 0x4) flags |= flag_msg; // -q if (opt & 0x8) flags |= flag_sem; // -s @@ -612,7 +600,10 @@ int ipcs_main(int argc UNUSED_PARAM, char **argv) if (opt & 0x100) format = LIMITS; // -l if (opt & 0x200) format = STATUS; // -u - if (flags & flag_print) { + if (opt & 1) { // -i + int id; + + id = xatoi(opt_i); if (flags & flag_shm) { print_shm(id); fflush_stdout_and_exit(EXIT_SUCCESS); @@ -633,15 +624,15 @@ int ipcs_main(int argc UNUSED_PARAM, char **argv) bb_putchar('\n'); if (flags & flag_msg) { - do_msg(); + do_msg(format); bb_putchar('\n'); } if (flags & flag_shm) { - do_shm(); + do_shm(format); bb_putchar('\n'); } if (flags & flag_sem) { - do_sem(); + do_sem(format); bb_putchar('\n'); } fflush_stdout_and_exit(EXIT_SUCCESS); -- cgit v1.2.3-55-g6feb From 7798282db22cb60d95d452007cab73f0f5631ce5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 8 Mar 2018 13:23:06 +0100 Subject: ipcs: further code shrink function old new delta packed_usage 32543 32547 +4 ipcs_main 1014 980 -34 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 4/-34) Total: -30 bytes Signed-off-by: Denys Vlasenko --- util-linux/ipcs.c | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/util-linux/ipcs.c b/util-linux/ipcs.c index dc107eb95..4863a5c29 100644 --- a/util-linux/ipcs.c +++ b/util-linux/ipcs.c @@ -565,7 +565,7 @@ static void print_sem(int semid) //usage:#define ipcs_trivial_usage //usage: "[[-smq] -i SHMID] | [[-asmq] [-tcplu]]" //usage:#define ipcs_full_usage "\n\n" -//usage: " -i Show specific resource" +//usage: " -i ID Show specific resource" //usage: "\nResource specification:" //usage: "\n -m Shared memory segments" //usage: "\n -q Message queues" @@ -582,56 +582,55 @@ int ipcs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int ipcs_main(int argc UNUSED_PARAM, char **argv) { int format = 0; - unsigned flags = 0; unsigned opt; char *opt_i; -#define flag_msg (1<<0) -#define flag_sem (1<<1) -#define flag_shm (1<<2) opt = getopt32(argv, "i:aqsmtcplu", &opt_i); - if (opt & 0x2) flags |= flag_msg | flag_sem | flag_shm; // -a - if (opt & 0x4) flags |= flag_msg; // -q - if (opt & 0x8) flags |= flag_sem; // -s - if (opt & 0x10) flags |= flag_shm; // -m - if (opt & 0x20) format = TIME; // -t - if (opt & 0x40) format = CREATOR; // -c - if (opt & 0x80) format = PID; // -p - if (opt & 0x100) format = LIMITS; // -l - if (opt & 0x200) format = STATUS; // -u - - if (opt & 1) { // -i +#define flag_msg (1<<2) +#define flag_sem (1<<3) +#define flag_shm (1<<4) + if (opt & (1<<5)) format = TIME; // -t + if (opt & (1<<6)) format = CREATOR; // -c + if (opt & (1<<7)) format = PID; // -p + if (opt & (1<<8)) format = LIMITS; // -l + if (opt & (1<<9)) format = STATUS; // -u + + if (opt & (1<<0)) { // -i int id; id = xatoi(opt_i); - if (flags & flag_shm) { + if (opt & flag_shm) { print_shm(id); fflush_stdout_and_exit(EXIT_SUCCESS); } - if (flags & flag_sem) { + if (opt & flag_sem) { print_sem(id); fflush_stdout_and_exit(EXIT_SUCCESS); } - if (flags & flag_msg) { + if (opt & flag_msg) { print_msg(id); fflush_stdout_and_exit(EXIT_SUCCESS); } bb_show_usage(); } - if (!(flags & (flag_shm | flag_msg | flag_sem))) - flags |= flag_msg | flag_shm | flag_sem; + if ((opt & (1<<1)) // -a + || !(opt & (flag_msg | flag_sem | flag_shm)) // none of -q,-s,-m == all + ) { + opt |= flag_msg | flag_sem | flag_shm; + } + bb_putchar('\n'); - if (flags & flag_msg) { + if (opt & flag_msg) { do_msg(format); bb_putchar('\n'); } - if (flags & flag_shm) { + if (opt & flag_shm) { do_shm(format); bb_putchar('\n'); } - if (flags & flag_sem) { + if (opt & flag_sem) { do_sem(format); bb_putchar('\n'); } -- cgit v1.2.3-55-g6feb From db169f253854db572c0c2b7e3d74ebbe6afdb97f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 8 Mar 2018 15:55:07 +0100 Subject: ip: fix "ip -oneline a" Signed-off-by: Denys Vlasenko --- networking/libiproute/ipaddress.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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) } for (l = linfo; l; l = l->next) { - if (no_link || print_linkinfo(&l->h) == 0) { + if (no_link + || (oneline || print_linkinfo(&l->h) == 0) + /* ^^^^^^^^^ "ip -oneline a" does not print link info */ + ) { struct ifinfomsg *ifi = NLMSG_DATA(&l->h); if (G_filter.family != AF_PACKET) print_selected_addrinfo(ifi->ifi_index, ainfo); -- cgit v1.2.3-55-g6feb From 3936222a0ac793f94824fbcb054148ceb8898425 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 8 Mar 2018 16:06:18 +0100 Subject: remove stray newline in "iplink --help" function old new delta packed_usage 32547 32550 +3 Signed-off-by: Denys Vlasenko --- networking/ip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 @@ //usage:#define iplink_trivial_usage //usage: /*Usage:iplink*/"set IFACE [up|down] [arp on|off] [multicast on|off]\n" //usage: " [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]\n" -//usage: " [master IFACE | nomaster]\n" +//usage: " [master IFACE | nomaster]" // * short help shows only "set" command, long help continues (with just one "\n") // * and shows all other commands: //usage:#define iplink_full_usage "\n" -- cgit v1.2.3-55-g6feb From 3293bc146985c56790033409facc0ad64a471084 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 10 Mar 2018 19:01:48 +0100 Subject: udhcpd: fix "not dying on SIGTERM" Fixes: commit 52a515d18724bbb34e3ccbbb0218efcc4eccc0a8 "udhcp: use poll() instead of select()" Feb 16 2017 udhcp_sp_read() is meant to check whether signal pipe indeed has some data to read. In the above commit, it was changed as follows: - if (!FD_ISSET(signal_pipe.rd, rfds)) + if (!pfds[0].revents) return 0; The problem is, the check was working for select() purely by accident. Caught signal interrupts select()/poll() syscalls, they return with EINTR (regardless of SA_RESTART flag in sigaction). _Then_ signal handler is invoked. IOW: they can't see any changes to fd state caused by signal haldler (in our case, signal handler makes signal pipe ready to be read). For select(), it means that rfds[] bit array is unmodified, bit of signal pipe's read fd is still set, and the above check "works": it thinks select() says there is data to read. This accident does not work for poll(): .revents stays clear, and we do not try reading signal pipe as we should. In udhcpd, we fall through and block in socket read. Further SIGTERM signals simply cause socket read to be interrupted and then restarted (since SIGTERM handler has SA_RESTART=1). Fixing this as follows: remove the check altogether. Set signal pipe read fd to nonblocking mode. Always read it in udhcp_sp_read(). If read fails, assume it's EAGAIN and return 0 ("no signal seen"). udhcpd avoids reading signal pipe on every recvd packet by looping if EINTR (using safe_poll()) - thus ensuring we have correct .revents for all fds - and calling udhcp_sp_read() only if pfds[0].revents!=0. udhcpc performs much fewer reads (typically it sleeps >99.999% of the time), there is no need to optimize it: can call udhcp_sp_read() after each poll unconditionally. To robustify socket reads, unconditionally set pfds[1].revents=0 in udhcp_sp_fd_set() (which is before poll), and check it before reading network socket in udhcpd. TODO: This might still fail: if pfds[1].revents=POLLIN, socket read may still block. There are rare cases when select/poll indicates that data can be read, but then actual read still blocks (one such case is UDP packets with wrong checksum). General advise is, if you use a poll/select loop, keep all your fds nonblocking. Maybe we should also do that to our network sockets? function old new delta udhcp_sp_setup 55 65 +10 udhcp_sp_fd_set 54 60 +6 udhcp_sp_read 46 36 -10 udhcpd_main 1451 1437 -14 udhcpc_main 2723 2708 -15 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/3 up/down: 16/-39) Total: -23 bytes Signed-off-by: Denys Vlasenko --- examples/var_service/dhcpd_if/run | 4 ++-- examples/var_service/dhcpd_if/udhcpc.conf | 28 ------------------------- examples/var_service/dhcpd_if/udhcpd.conf | 28 +++++++++++++++++++++++++ networking/udhcp/common.h | 2 +- networking/udhcp/d6_dhcpc.c | 9 ++++---- networking/udhcp/dhcpc.c | 9 ++++---- networking/udhcp/dhcpd.c | 34 ++++++++++++++++--------------- networking/udhcp/signalpipe.c | 11 +++++----- 8 files changed, 63 insertions(+), 62 deletions(-) delete mode 100644 examples/var_service/dhcpd_if/udhcpc.conf create mode 100644 examples/var_service/dhcpd_if/udhcpd.conf 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" ip link set dev $if up >>udhcpd.leases -sed 's/^interface.*$/interface '"$if/" -i udhcpc.conf +sed 's/^interface.*$/interface '"$if/" -i udhcpd.conf echo "* Starting udhcpd" exec \ env - PATH="$PATH" \ softlimit \ setuidgid root \ -udhcpd -f -vv udhcpc.conf +udhcpd -f -vv udhcpd.conf exit $? diff --git a/examples/var_service/dhcpd_if/udhcpc.conf b/examples/var_service/dhcpd_if/udhcpc.conf deleted file mode 100644 index a81925970..000000000 --- a/examples/var_service/dhcpd_if/udhcpc.conf +++ /dev/null @@ -1,28 +0,0 @@ -# Directives with defaults: -# start 192.168.0.20 -# end 192.168.0.254 -# interface eth0 -# max_leases 235 -# auto_time 7200 -# decline_time 3600 -# conflict_time 3600 -# offer_time 60 -# min_lease 60 -# lease_file /var/lib/misc/udhcpd.leases -# pidfile /var/run/udhcpd.pid -# siaddr 0.0.0.0 -# -# Directives with no defaults (or with empty defaults): -# option/opt NAME VALUE -# notify_file /path/to/script_to_run_after_leasefile_is_written -# (it is run with $1 = lease_file_name) -# sname dhcp_packet_sname_field_contents -# boot_file dhcp_packet_bootfile_field_contents -# static_lease XX:XX:XX:XX:XX:XX IP.ADD.RE.SS - -interface if -pidfile /dev/null -lease_file udhcpd.leases -option subnet 255.255.255.0 -option lease 3600 -#option router 192.168.0.1 diff --git a/examples/var_service/dhcpd_if/udhcpd.conf b/examples/var_service/dhcpd_if/udhcpd.conf new file mode 100644 index 000000000..a81925970 --- /dev/null +++ b/examples/var_service/dhcpd_if/udhcpd.conf @@ -0,0 +1,28 @@ +# Directives with defaults: +# start 192.168.0.20 +# end 192.168.0.254 +# interface eth0 +# max_leases 235 +# auto_time 7200 +# decline_time 3600 +# conflict_time 3600 +# offer_time 60 +# min_lease 60 +# lease_file /var/lib/misc/udhcpd.leases +# pidfile /var/run/udhcpd.pid +# siaddr 0.0.0.0 +# +# Directives with no defaults (or with empty defaults): +# option/opt NAME VALUE +# notify_file /path/to/script_to_run_after_leasefile_is_written +# (it is run with $1 = lease_file_name) +# sname dhcp_packet_sname_field_contents +# boot_file dhcp_packet_bootfile_field_contents +# static_lease XX:XX:XX:XX:XX:XX IP.ADD.RE.SS + +interface if +pidfile /dev/null +lease_file udhcpd.leases +option subnet 255.255.255.0 +option lease 3600 +#option router 192.168.0.1 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, void udhcp_sp_setup(void) FAST_FUNC; void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; -int udhcp_sp_read(struct pollfd *pfds) FAST_FUNC; +int udhcp_sp_read(void) FAST_FUNC; int udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC; 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) /* yah, I know, *you* say it would never happen */ timeout = INT_MAX; continue; /* back to main loop */ - } /* if select timed out */ + } /* if poll timed out */ - /* select() didn't timeout, something happened */ + /* poll() didn't timeout, something happened */ /* Is it a signal? */ - /* note: udhcp_sp_read checks poll result before reading */ - switch (udhcp_sp_read(pfds)) { + switch (udhcp_sp_read()) { case SIGUSR1: client_config.first_secs = 0; /* make secs field count from 0 */ already_waited_sec = 0; @@ -1416,7 +1415,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) } /* Is it a packet? */ - if (listen_mode == LISTEN_NONE || !pfds[1].revents) + if (!pfds[1].revents) continue; /* no */ { 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) /* yah, I know, *you* say it would never happen */ timeout = INT_MAX; continue; /* back to main loop */ - } /* if select timed out */ + } /* if poll timed out */ - /* select() didn't timeout, something happened */ + /* poll() didn't timeout, something happened */ /* Is it a signal? */ - /* note: udhcp_sp_read checks poll result before reading */ - switch (udhcp_sp_read(pfds)) { + switch (udhcp_sp_read()) { case SIGUSR1: client_config.first_secs = 0; /* make secs field count from 0 */ already_waited_sec = 0; @@ -1615,7 +1614,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) } /* Is it a packet? */ - if (listen_mode == LISTEN_NONE || !pfds[1].revents) + if (!pfds[1].revents) continue; /* no */ { diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 093239536..db3ab4f00 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -915,20 +915,18 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) udhcp_sp_fd_set(pfds, server_socket); tv = timeout_end - monotonic_sec(); - retval = 0; - if (!server_config.auto_time || tv > 0) { - retval = poll(pfds, 2, server_config.auto_time ? tv * 1000 : -1); - } - if (retval == 0) { - write_leases(); - goto continue_with_autotime; - } - if (retval < 0 && errno != EINTR) { - log1("error on select"); - continue; + /* Block here waiting for either signal or packet */ + retval = safe_poll(pfds, 2, server_config.auto_time ? tv * 1000 : -1); + if (retval <= 0) { + if (retval == 0) { + write_leases(); + goto continue_with_autotime; + } + /* < 0 and not EINTR: should not happen */ + bb_perror_msg_and_die("poll"); } - switch (udhcp_sp_read(pfds)) { + if (pfds[0].revents) switch (udhcp_sp_read()) { case SIGUSR1: bb_error_msg("received %s", "SIGUSR1"); write_leases(); @@ -938,12 +936,16 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) bb_error_msg("received %s", "SIGTERM"); write_leases(); goto ret0; - case 0: /* no signal: read a packet */ - break; - default: /* signal or error (probably EINTR): back to select */ - continue; } + /* Is it a packet? */ + if (!pfds[1].revents) + continue; /* no */ + + /* Note: we do not block here, we block on poll() instead. + * Blocking here would prevent SIGTERM from working: + * socket read inside this call is restarted on caught signals. + */ bytes = udhcp_recv_kernel_packet(&packet, server_socket); if (bytes < 0) { /* 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) xpiped_pair(signal_pipe); close_on_exec_on(signal_pipe.rd); close_on_exec_on(signal_pipe.wr); + ndelay_on(signal_pipe.rd); ndelay_on(signal_pipe.wr); bb_signals(0 + (1 << SIGUSR1) @@ -61,20 +62,20 @@ void FAST_FUNC udhcp_sp_fd_set(struct pollfd pfds[2], int extra_fd) pfds[1].fd = extra_fd; pfds[1].events = POLLIN; } + /* this simplifies "is extra_fd ready?" tests elsewhere: */ + pfds[1].revents = 0; } /* Read a signal from the signal pipe. Returns 0 if there is * no signal, -1 on error (and sets errno appropriately), and * your signal on success */ -int FAST_FUNC udhcp_sp_read(struct pollfd pfds[2]) +int FAST_FUNC udhcp_sp_read(void) { unsigned char sig; - if (!pfds[0].revents) - return 0; - + /* Can't block here, fd is in nonblocking mode */ if (safe_read(signal_pipe.rd, &sig, 1) != 1) - return -1; + return 0; return sig; } -- cgit v1.2.3-55-g6feb From 39dfb4de38fc5b31ca4472dbf45bcde3bb0d6e77 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 10 Mar 2018 21:25:53 +0100 Subject: ntpd: suppress in-kernel frequency correction in first 8 adjtimex calls In other words: try to correct initially existing clock offset first, before assuming that our clock drifts. function old new delta update_local_clock 826 834 +8 ntp_init 550 557 +7 filter_datapoints 179 173 -6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 15/-6) Total: 9 bytes Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 17e5c7da6..2754170c0 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -165,8 +165,12 @@ * Using exact power of 2 (1/8) results in smaller code */ #define SLEW_THRESHOLD 0.125 +//^^^^^^^^^^^^^^^^^^^^^^^^^^ TODO: man adjtimex about tmx.offset: +// "Since Linux 2.6.26, the supplied value is clamped to the range (-0.5s, +0.5s)" +// - can use this larger value instead? + /* Stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */ -#define WATCH_THRESHOLD 128 +//UNUSED: #define WATCH_THRESHOLD 128 /* NB: set WATCH_THRESHOLD to ~60 when debugging to save time) */ //UNUSED: #define PANIC_THRESHOLD 1000 /* panic threshold (sec) */ @@ -419,6 +423,7 @@ struct globals { uint8_t discipline_state; // doc calls it c.state uint8_t poll_exp; // s.poll int polladj_count; // c.count + int FREQHOLD_cnt; long kernel_freq_drift; peer_t *last_update_peer; double last_update_offset; // c.last @@ -1034,6 +1039,7 @@ step_time(double offset) tval = tvn.tv_sec; strftime_YYYYMMDDHHMMSS(buf, sizeof(buf), &tval); bb_error_msg("setting time to %s.%06u (offset %+fs)", buf, (unsigned)tvn.tv_usec, offset); + //maybe? G.FREQHOLD_cnt = 0; /* Correct various fields which contain time-relative values: */ @@ -1709,6 +1715,28 @@ update_local_clock(peer_t *p) tmx.freq = G.discipline_freq_drift * 65536e6; #endif tmx.modes = ADJ_OFFSET | ADJ_STATUS | ADJ_TIMECONST;// | ADJ_MAXERROR | ADJ_ESTERROR; + tmx.status = STA_PLL; + if (G.FREQHOLD_cnt != 0) { + G.FREQHOLD_cnt--; + /* man adjtimex on STA_FREQHOLD: + * "Normally adjustments made via ADJ_OFFSET result in dampened + * frequency adjustments also being made. + * This flag prevents the small frequency adjustment from being + * made when correcting for an ADJ_OFFSET value." + * + * Use this flag for a few first adjustments at the beginning + * of ntpd execution, otherwise even relatively small initial + * offset tend to cause largish changes to in-kernel tmx.freq. + * If ntpd was restarted due to e.g. switch to another network, + * this destroys already well-established tmx.freq value. + */ + tmx.status |= STA_FREQHOLD; + } + if (G.ntp_status & LI_PLUSSEC) + tmx.status |= STA_INS; + if (G.ntp_status & LI_MINUSSEC) + tmx.status |= STA_DEL; + tmx.constant = (int)G.poll_exp - 4; /* EXPERIMENTAL. * The below if statement should be unnecessary, but... @@ -1722,25 +1750,18 @@ update_local_clock(peer_t *p) */ if (G.offset_to_jitter_ratio >= TIMECONST_HACK_GATE) tmx.constant--; + if (tmx.constant < 0) + tmx.constant = 0; + tmx.offset = (long)(offset * 1000000); /* usec */ if (SLEW_THRESHOLD < STEP_THRESHOLD) { if (tmx.offset > (long)(SLEW_THRESHOLD * 1000000)) { tmx.offset = (long)(SLEW_THRESHOLD * 1000000); - tmx.constant--; } if (tmx.offset < -(long)(SLEW_THRESHOLD * 1000000)) { tmx.offset = -(long)(SLEW_THRESHOLD * 1000000); - tmx.constant--; } } - if (tmx.constant < 0) - tmx.constant = 0; - - tmx.status = STA_PLL; - if (G.ntp_status & LI_PLUSSEC) - tmx.status |= STA_INS; - if (G.ntp_status & LI_MINUSSEC) - tmx.status |= STA_DEL; //tmx.esterror = (uint32_t)(clock_jitter * 1e6); //tmx.maxerror = (uint32_t)((sys_rootdelay / 2 + sys_rootdisp) * 1e6); @@ -2227,6 +2248,7 @@ static NOINLINE void ntp_init(char **argv) if (BURSTPOLL != 0) G.poll_exp = BURSTPOLL; /* speeds up initial sync */ G.last_script_run = G.reftime = G.last_update_recv_time = gettime1900d(); /* sets G.cur_time too */ + G.FREQHOLD_cnt = 8; /* Parse options */ peers = NULL; -- cgit v1.2.3-55-g6feb From 3d306bffc5981b083ebb365c51e93c2231ff9b22 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 11 Mar 2018 11:34:44 +0100 Subject: udhcpd: clamp down huge auto_times to ~2M seconds, better EINTR poll handling EINTR _should_ only happen on two signals we trap, and safe_poll _should_ work here just fine, but there were kernel bugs where spurious EINTRs happen (e.g. on ptrace attach). Be safe. function old new delta udhcpd_main 1437 1468 +31 Signed-off-by: Denys Vlasenko --- networking/udhcp/dhcpd.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index db3ab4f00..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) /* Would rather not do read_config before daemonization - * otherwise NOMMU machines will parse config twice */ read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE); + /* prevent poll timeout overflow */ + if (server_config.auto_time > INT_MAX / 1000) + server_config.auto_time = INT_MAX / 1000; /* Make sure fd 0,1,2 are open */ bb_sanitize_stdio(); @@ -914,14 +917,26 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) } udhcp_sp_fd_set(pfds, server_socket); - tv = timeout_end - monotonic_sec(); - /* Block here waiting for either signal or packet */ - retval = safe_poll(pfds, 2, server_config.auto_time ? tv * 1000 : -1); - if (retval <= 0) { - if (retval == 0) { + + new_tv: + tv = -1; + if (server_config.auto_time) { + tv = timeout_end - monotonic_sec(); + if (tv <= 0) { + write_leases: write_leases(); goto continue_with_autotime; } + tv *= 1000; + } + + /* Block here waiting for either signal or packet */ + retval = poll(pfds, 2, tv); + if (retval <= 0) { + if (retval == 0) + goto write_leases; + if (errno == EINTR) + goto new_tv; /* < 0 and not EINTR: should not happen */ bb_perror_msg_and_die("poll"); } -- cgit v1.2.3-55-g6feb From 448fdcc17df39ac90c59d0588ccaf9ee0400eb7e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 11 Mar 2018 17:08:02 +0100 Subject: ntpd: choose initial FREQHOLD_cnt dynamically function old new delta update_local_clock 834 858 +24 Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 66 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 2754170c0..8205ab271 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -1715,9 +1715,19 @@ update_local_clock(peer_t *p) tmx.freq = G.discipline_freq_drift * 65536e6; #endif tmx.modes = ADJ_OFFSET | ADJ_STATUS | ADJ_TIMECONST;// | ADJ_MAXERROR | ADJ_ESTERROR; + + tmx.offset = (long)(offset * 1000000); /* usec */ + if (SLEW_THRESHOLD < STEP_THRESHOLD) { + if (tmx.offset > (long)(SLEW_THRESHOLD * 1000000)) { + tmx.offset = (long)(SLEW_THRESHOLD * 1000000); + } + if (tmx.offset < -(long)(SLEW_THRESHOLD * 1000000)) { + tmx.offset = -(long)(SLEW_THRESHOLD * 1000000); + } + } + tmx.status = STA_PLL; if (G.FREQHOLD_cnt != 0) { - G.FREQHOLD_cnt--; /* man adjtimex on STA_FREQHOLD: * "Normally adjustments made via ADJ_OFFSET result in dampened * frequency adjustments also being made. @@ -1730,6 +1740,48 @@ update_local_clock(peer_t *p) * If ntpd was restarted due to e.g. switch to another network, * this destroys already well-established tmx.freq value. */ + if (G.FREQHOLD_cnt < 0) { + /* Initialize it */ +// Example: a laptop whose clock runs slower when hibernated, +// after wake up it still has good tmx.freq, but accumulated ~0.5 sec offset: +// Run with code where initial G.FREQHOLD_cnt was always 8: +//15:17:52.947 no valid datapoints, no peer selected +//15:17:56.515 update from: offset:+0.485133 delay:0.157762 jitter:0.209310 clock drift:-1.393ppm tc:4 +//15:17:57.719 update from: offset:+0.483825 delay:0.158070 jitter:0.181159 clock drift:-1.393ppm tc:4 +//15:17:59.925 update from: offset:+0.479504 delay:0.158147 jitter:0.156657 clock drift:-1.393ppm tc:4 +//15:18:33.322 update from: offset:+0.428119 delay:0.158317 jitter:0.138071 clock drift:-1.393ppm tc:4 +//15:19:06.718 update from: offset:+0.376932 delay:0.158276 jitter:0.122075 clock drift:-1.393ppm tc:4 +//15:19:39.114 update from: offset:+0.327022 delay:0.158384 jitter:0.108538 clock drift:-1.393ppm tc:4 +//15:20:12.715 update from: offset:+0.275596 delay:0.158297 jitter:0.097292 clock drift:-1.393ppm tc:4 +//15:20:45.111 update from: offset:+0.225715 delay:0.158271 jitter:0.087841 clock drift:-1.393ppm tc:4 +// If allwed to continue, it would start increasing tmx.freq now. +// Instead, it was ^Ced, and started anew: +//15:21:15.043 no valid datapoints, no peer selected +//15:21:17.408 update from: offset:+0.175910 delay:0.158314 jitter:0.076683 clock drift:-1.393ppm tc:4 +//15:21:19.774 update from: offset:+0.171784 delay:0.158401 jitter:0.066436 clock drift:-1.393ppm tc:4 +//15:21:22.140 update from: offset:+0.171660 delay:0.158592 jitter:0.057536 clock drift:-1.393ppm tc:4 +//15:21:22.140 update from: offset:+0.167126 delay:0.158507 jitter:0.049792 clock drift:-1.393ppm tc:4 +//15:21:55.696 update from: offset:+0.115223 delay:0.158277 jitter:0.050240 clock drift:-1.393ppm tc:4 +//15:22:29.093 update from: offset:+0.068051 delay:0.158243 jitter:0.049405 clock drift:-1.393ppm tc:5 +//15:23:02.490 update from: offset:+0.051632 delay:0.158215 jitter:0.043545 clock drift:-1.393ppm tc:5 +//15:23:34.726 update from: offset:+0.039984 delay:0.158157 jitter:0.038106 clock drift:-1.393ppm tc:5 +// STA_FREQHOLD no longer set, started increasing tmx.freq now: +//15:24:06.961 update from: offset:+0.030968 delay:0.158190 jitter:0.033306 clock drift:+2.387ppm tc:5 +//15:24:40.357 update from: offset:+0.023648 delay:0.158211 jitter:0.029072 clock drift:+5.454ppm tc:5 +//15:25:13.774 update from: offset:+0.018068 delay:0.157660 jitter:0.025288 clock drift:+7.728ppm tc:5 +//15:26:19.173 update from: offset:+0.010057 delay:0.157969 jitter:0.022255 clock drift:+8.361ppm tc:6 +//15:27:26.602 update from: offset:+0.006737 delay:0.158103 jitter:0.019316 clock drift:+8.792ppm tc:6 +//15:28:33.030 update from: offset:+0.004513 delay:0.158294 jitter:0.016765 clock drift:+9.080ppm tc:6 +//15:29:40.617 update from: offset:+0.002787 delay:0.157745 jitter:0.014543 clock drift:+9.258ppm tc:6 +//15:30:47.045 update from: offset:+0.001324 delay:0.157709 jitter:0.012594 clock drift:+9.342ppm tc:6 +//15:31:53.473 update from: offset:+0.000007 delay:0.158142 jitter:0.010922 clock drift:+9.343ppm tc:6 +//15:32:58.902 update from: offset:-0.000728 delay:0.158222 jitter:0.009454 clock drift:+9.298ppm tc:6 + /* + * This expression would choose 15 in the above example. + */ + G.FREQHOLD_cnt = 8 + ((unsigned)(abs(tmx.offset)) >> 16); + } + G.FREQHOLD_cnt--; tmx.status |= STA_FREQHOLD; } if (G.ntp_status & LI_PLUSSEC) @@ -1753,16 +1805,6 @@ update_local_clock(peer_t *p) if (tmx.constant < 0) tmx.constant = 0; - tmx.offset = (long)(offset * 1000000); /* usec */ - if (SLEW_THRESHOLD < STEP_THRESHOLD) { - if (tmx.offset > (long)(SLEW_THRESHOLD * 1000000)) { - tmx.offset = (long)(SLEW_THRESHOLD * 1000000); - } - if (tmx.offset < -(long)(SLEW_THRESHOLD * 1000000)) { - tmx.offset = -(long)(SLEW_THRESHOLD * 1000000); - } - } - //tmx.esterror = (uint32_t)(clock_jitter * 1e6); //tmx.maxerror = (uint32_t)((sys_rootdelay / 2 + sys_rootdisp) * 1e6); rc = adjtimex(&tmx); @@ -2248,7 +2290,7 @@ static NOINLINE void ntp_init(char **argv) if (BURSTPOLL != 0) G.poll_exp = BURSTPOLL; /* speeds up initial sync */ G.last_script_run = G.reftime = G.last_update_recv_time = gettime1900d(); /* sets G.cur_time too */ - G.FREQHOLD_cnt = 8; + G.FREQHOLD_cnt = -1; /* Parse options */ peers = NULL; -- cgit v1.2.3-55-g6feb From 0e09ded2f1ab4b2e941cb29bed6c5dca7ecb9b53 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 11 Mar 2018 19:35:58 +0100 Subject: readprofile: code shrink function old new delta defaultpro 14 - -14 defaultmap 17 - -17 readprofile_main 1762 1719 -43 ------------------------------------------------------------------------------ (add/remove: 0/2 grow/shrink: 0/1 up/down: 0/-74) Total: -74 bytes text data bss dec hex filename 933081 473 6836 940390 e5966 busybox_old 933035 473 6836 940344 e5938 busybox_unstripped Signed-off-by: Denys Vlasenko --- util-linux/readprofile.c | 67 ++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 34 deletions(-) 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 @@ #define S_LEN 128 -/* These are the defaults */ -static const char defaultmap[] ALIGN1 = "/boot/System.map"; -static const char defaultpro[] ALIGN1 = "/proc/profile"; - int readprofile_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int readprofile_main(int argc UNUSED_PARAM, char **argv) { FILE *map; const char *mapFile, *proFile; - unsigned long indx = 1; + unsigned long indx; size_t len; - uint64_t add0 = 0; + uint64_t add0; unsigned int step; unsigned int *buf, total, fn_len; unsigned long long fn_add, next_add; /* current and next address */ char fn_name[S_LEN], next_name[S_LEN]; /* current and next name */ char mapline[S_LEN]; char mode[8]; - int maplineno = 1; - int header_printed; - int multiplier = 0; + int maplineno; + int multiplier; unsigned opt; enum { OPT_M = (1 << 0), @@ -106,8 +101,9 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv) #define next (current^1) - proFile = defaultpro; - mapFile = defaultmap; + proFile = "/proc/profile"; + mapFile = "/boot/System.map"; + multiplier = 0; opt = getopt32(argv, "M:+m:p:nabsirv", &multiplier, &mapFile, &proFile); @@ -122,7 +118,7 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv) if (!optMult) to_write = 1; /* sth different from sizeof(int) */ - fd = xopen(defaultpro, O_WRONLY); + fd = xopen("/proc/profile", O_WRONLY); xwrite(fd, &multiplier, to_write); close(fd); return EXIT_SUCCESS; @@ -133,12 +129,13 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv) */ len = MAXINT(ssize_t); buf = xmalloc_xopen_read_close(proFile, &len); + len /= sizeof(*buf); + if (!optNative) { - int entries = len / sizeof(*buf); - int big = 0, small = 0, i; + int big = 0, small = 0; unsigned *p; - for (p = buf+1; p < buf+entries; p++) { + for (p = buf+1; p < buf+len; p++) { if (*p & ~0U << (sizeof(*buf)*4)) big++; if (*p & ((1 << (sizeof(*buf)*4))-1)) @@ -147,15 +144,15 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv) if (big > small) { bb_error_msg("assuming reversed byte order, " "use -n to force native byte order"); - for (p = buf; p < buf+entries; p++) - for (i = 0; i < sizeof(*buf)/2; i++) { - unsigned char *b = (unsigned char *) p; - unsigned char tmp; - - tmp = b[i]; - b[i] = b[sizeof(*buf)-i-1]; - b[sizeof(*buf)-i-1] = tmp; - } + BUILD_BUG_ON(sizeof(*p) > 8); + for (p = buf; p < buf+len; p++) { + if (sizeof(*p) == 2) + *p = bswap_16(*p); + if (sizeof(*p) == 4) + *p = bswap_32(*p); + if (sizeof(*p) == 8) + *p = bb_bswap_64(*p); + } } } @@ -165,10 +162,9 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv) return EXIT_SUCCESS; } - total = 0; - map = xfopen_for_read(mapFile); - + add0 = 0; + maplineno = 1; while (fgets(mapline, S_LEN, map)) { if (sscanf(mapline, "%llx %s %s", &fn_add, mode, fn_name) != 3) bb_error_msg_and_die("%s(%i): wrong map line", @@ -187,8 +183,11 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv) /* * Main loop. */ + total = 0; + indx = 1; while (fgets(mapline, S_LEN, map)) { - unsigned int this = 0; + bool header_printed; + unsigned int this; if (sscanf(mapline, "%llx %s %s", &next_add, mode, next_name) != 3) bb_error_msg_and_die("%s(%i): wrong map line", @@ -198,17 +197,17 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv) /* ignore any LEADING (before a '[tT]' symbol is found) Absolute symbols */ - if ((*mode == 'A' || *mode == '?') && total == 0) continue; - if (*mode != 'T' && *mode != 't' - && *mode != 'W' && *mode != 'w' - ) { + if ((mode[0] == 'A' || mode[0] == '?') && total == 0) + continue; + if ((mode[0]|0x20) != 't' && (mode[0]|0x20) != 'w') { break; /* only text is profiled */ } - if (indx >= len / sizeof(*buf)) + if (indx >= len) bb_error_msg_and_die("profile address out of range. " "Wrong map file?"); + this = 0; while (indx < (next_add-add0)/step) { if (optBins && (buf[indx] || optAll)) { if (!header_printed) { @@ -256,7 +255,7 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv) } /* clock ticks, out of kernel text - probably modules */ - printf("%6u %s\n", buf[len/sizeof(*buf)-1], "*unknown*"); + printf("%6u *unknown*\n", buf[len-1]); /* trailer */ if (optVerbose) -- cgit v1.2.3-55-g6feb From bbe47d9b9aee3824845f1ce08c9caeb262c15059 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 11 Mar 2018 23:02:50 +0100 Subject: tcpsvd: fix fallout from opt_complementary removal text data bss dec hex filename 933035 473 6836 940344 e5938 busybox_old 933051 473 6836 940360 e5948 busybox_unstripped Signed-off-by: Denys Vlasenko --- networking/tcpudp.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) 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) tcp = (applet_name[0] == 't'); + /* "+": stop on first non-option */ #ifdef SSLSVD opts = getopt32(argv, "^+" "c:+C:i:x:u:l:Eb:+hpt:vU:/:Z:K:" /* -c NUM, -b NUM */ + "\0" /* 3+ args, -i at most once, -p implies -h, -v is a counter */ - "\0" "-3:i--i:ph:vv", + "-3:i--i:ph:vv", &cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, &backlog, &str_t, &ssluser, &root, &cert, &key, &verbose ); #else - /* "+": stop on first non-option */ - opts = getopt32(argv, "+c:+C:i:x:u:l:Eb:hpt:v", + opts = getopt32(argv, "^+" + "c:+C:i:x:u:l:Eb:+hpt:v" /* -c NUM, -b NUM */ + "\0" + /* 3+ args, -i at most once, -p implies -h, -v is a counter */ + "-3:i--i:ph:vv", &cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, &backlog, &str_t, &verbose ); -- cgit v1.2.3-55-g6feb