aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--Makefile.flags5
-rw-r--r--coreutils/echo.c10
-rw-r--r--editors/diff.c2
-rw-r--r--editors/vi.c40
-rw-r--r--include/libbb.h1
-rw-r--r--include/platform.h8
-rw-r--r--libbb/appletlib.c29
-rw-r--r--libbb/lineedit.c10
-rw-r--r--libbb/platform.c12
-rw-r--r--libbb/vfork_daemon_rexec.c5
-rw-r--r--miscutils/bc.c64
-rw-r--r--networking/dnsd.c17
-rw-r--r--networking/ntpd.c337
-rw-r--r--networking/udhcp/d6_dhcpc.c14
-rw-r--r--networking/udhcp/dhcpc.c36
-rw-r--r--networking/udhcp/dhcpd.c4
-rwxr-xr-xscripts/trylink17
-rw-r--r--shell/ash.c4
-rwxr-xr-xtestsuite/bc.tests5
-rwxr-xr-xtestsuite/dc.tests5
-rwxr-xr-xtestsuite/start-stop-daemon.tests5
22 files changed, 273 insertions, 358 deletions
diff --git a/Makefile b/Makefile
index 17f55dce2..ea182325d 100644
--- a/Makefile
+++ b/Makefile
@@ -612,6 +612,7 @@ quiet_cmd_busybox__ ?= LINK $@
"$(core-y)" \
"$(libs-y)" \
"$(LDLIBS)" \
+ "$(CONFIG_EXTRA_LDLIBS)" \
&& $(srctree)/scripts/generate_BUFSIZ.sh --post include/common_bufsiz.h
# Generate System.map
diff --git a/Makefile.flags b/Makefile.flags
index 7a445c3b5..3b02bfaac 100644
--- a/Makefile.flags
+++ b/Makefile.flags
@@ -209,11 +209,6 @@ LDFLAGS += $(strip $(subst ",,$(CONFIG_EXTRA_LDFLAGS)))
#"))
endif
-ifneq ($(CONFIG_EXTRA_LDLIBS),)
-LDLIBS += $(strip $(subst ",,$(CONFIG_EXTRA_LDLIBS)))
-#"))
-endif
-
# Busybox is a stack-fatty so make sure we increase default size
# TODO: use "make stksizes" to find & fix big stack users
# (we stole scripts/checkstack.pl from the kernel... thanks guys!)
diff --git a/coreutils/echo.c b/coreutils/echo.c
index b3828894c..61ba060ec 100644
--- a/coreutils/echo.c
+++ b/coreutils/echo.c
@@ -97,6 +97,7 @@ int echo_main(int argc UNUSED_PARAM, char **argv)
#else
char nflag = 1;
char eflag = 0;
+ int err;
while ((arg = *++argv) != NULL) {
char n, e;
@@ -185,13 +186,12 @@ int echo_main(int argc UNUSED_PARAM, char **argv)
do_write:
/* Careful to error out on partial writes too (think ENOSPC!) */
errno = 0;
- /*r =*/ full_write(STDOUT_FILENO, buffer, out - buffer);
- free(buffer);
- if (/*WRONG:r < 0*/ errno) {
+ err = full_write(STDOUT_FILENO, buffer, out - buffer) != out - buffer;
+ if (err) {
bb_simple_perror_msg(bb_msg_write_error);
- return 1;
}
- return 0;
+ free(buffer);
+ return err;
}
/*
diff --git a/editors/diff.c b/editors/diff.c
index 280091756..1adc4cbc7 100644
--- a/editors/diff.c
+++ b/editors/diff.c
@@ -1050,7 +1050,7 @@ int diff_main(int argc UNUSED_PARAM, char **argv)
/* diffreg can get non-regular files here */
print_status(gotstdin > 1 ? STATUS_SAME : diffreg(file), file);
- if (dirfile)
+ if (ENABLE_FEATURE_CLEAN_UP && dirfile)
free(file[dir]);
}
diff --git a/editors/vi.c b/editors/vi.c
index 458ca6293..abc0aeae8 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -2258,7 +2258,7 @@ static char *get_one_address(char *p, int *addr) // get colon addr, if present
q = begin_line(dot);
*addr = count_lines(text, q);
}
-#if ENABLE_FEATURE_VI_YANKMARK
+# if ENABLE_FEATURE_VI_YANKMARK
else if (*p == '\'') { // is this a mark addr
p++;
c = tolower(*p);
@@ -2272,8 +2272,8 @@ static char *get_one_address(char *p, int *addr) // get colon addr, if present
}
}
}
-#endif
-#if ENABLE_FEATURE_VI_SEARCH
+# endif
+# if ENABLE_FEATURE_VI_SEARCH
else if (*p == '/') { // a search pattern
q = strchrnul(p + 1, '/');
if (p + 1 != q) {
@@ -2290,7 +2290,7 @@ static char *get_one_address(char *p, int *addr) // get colon addr, if present
*addr = count_lines(text, q);
}
}
-#endif
+# endif
else if (*p == '$') { // the last line in file
p++;
q = begin_line(end - 1);
@@ -2333,16 +2333,13 @@ static char *get_address(char *p, int *b, int *e) // get two colon addrs, if pre
return p;
}
-#if ENABLE_FEATURE_VI_SET && ENABLE_FEATURE_VI_SETOPTS
-static void setops(const char *args, const char *opname, int flg_no,
- const char *short_opname, int opt)
+# if ENABLE_FEATURE_VI_SET && ENABLE_FEATURE_VI_SETOPTS
+static void setops(const char *args, const char *nm_longname, int flg_no, int opt)
{
const char *a = args + flg_no;
- int l = strlen(opname) - 1; // opname have + ' '
- // maybe strncmp? we had tons of erroneous strncasecmp's...
- if (strncasecmp(a, opname, l) == 0
- || strncasecmp(a, short_opname, 2) == 0
+ if (strcmp(a, nm_longname) == 0
+ || strcmp(a, nm_longname + 3) == 0
) {
if (flg_no)
vi_setops &= ~opt;
@@ -2350,7 +2347,7 @@ static void setops(const char *args, const char *opname, int flg_no,
vi_setops |= opt;
}
}
-#endif
+# endif
#endif /* FEATURE_VI_COLON */
@@ -2709,7 +2706,6 @@ static void colon(char *buf)
# if ENABLE_FEATURE_VI_SETOPTS
char *argp;
# endif
- i = 0; // offset into args
// only blank is regarded as args delimiter. What about tab '\t'?
if (!args[0] || strcasecmp(args, "all") == 0) {
// print out values of all options
@@ -2732,15 +2728,15 @@ static void colon(char *buf)
# if ENABLE_FEATURE_VI_SETOPTS
argp = args;
while (*argp) {
- if (strncmp(argp, "no", 2) == 0)
- i = 2; // ":set noautoindent"
- setops(argp, "autoindent ", i, "ai", VI_AUTOINDENT);
- setops(argp, "flash " , i, "fl", VI_ERR_METHOD);
- setops(argp, "ignorecase ", i, "ic", VI_IGNORECASE);
- setops(argp, "showmatch " , i, "sm", VI_SHOWMATCH );
- if (strncmp(argp + i, "tabstop=", 8) == 0) {
- int t = 0;
- sscanf(argp + i+8, "%u", &t);
+ i = 0;
+ if (argp[0] == 'n' && argp[1] == 'o') // "noXXX"
+ i = 2;
+ setops(argp, "ai""\0""autoindent", i, VI_AUTOINDENT);
+ setops(argp, "fl""\0""flash" , i, VI_ERR_METHOD);
+ setops(argp, "ic""\0""ignorecase", i, VI_IGNORECASE);
+ setops(argp, "sm""\0""showmatch" , i, VI_SHOWMATCH );
+ if (strncmp(argp, "tabstop=", 8) == 0) {
+ int t = bb_strtou(argp + 8, NULL, 10);
if (t > 0 && t <= MAX_TABSTOP)
tabstop = t;
}
diff --git a/include/libbb.h b/include/libbb.h
index 135d9111d..ece03e7d8 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1219,6 +1219,7 @@ void run_noexec_applet_and_exit(int a, const char *name, char **argv) NORETURN F
int find_applet_by_name(const char *name) FAST_FUNC;
void run_applet_no_and_exit(int a, const char *name, char **argv) NORETURN FAST_FUNC;
#endif
+void show_usage_if_dash_dash_help(int applet_no, char **argv) FAST_FUNC;
#if defined(__linux__)
void set_task_comm(const char *comm) FAST_FUNC;
#else
diff --git a/include/platform.h b/include/platform.h
index d991f3140..24efd186b 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -407,6 +407,7 @@ typedef unsigned smalluint;
#define HAVE_SETBIT 1
#define HAVE_SIGHANDLER_T 1
#define HAVE_STPCPY 1
+#define HAVE_STPNCPY 1
#define HAVE_MEMPCPY 1
#define HAVE_STRCASESTR 1
#define HAVE_STRCHRNUL 1
@@ -442,6 +443,7 @@ typedef unsigned smalluint;
# undef HAVE_MKDTEMP
# undef HAVE_SETBIT
# undef HAVE_STPCPY
+# undef HAVE_STPNCPY
# undef HAVE_STRCASESTR
# undef HAVE_STRCHRNUL
# undef HAVE_STRSEP
@@ -514,6 +516,7 @@ typedef unsigned smalluint;
#if defined(__digital__) && defined(__unix__)
# undef HAVE_STPCPY
+# undef HAVE_STPNCPY
#endif
#if defined(ANDROID) || defined(__ANDROID__)
@@ -530,6 +533,7 @@ typedef unsigned smalluint;
# undef HAVE_TTYNAME_R
# undef HAVE_GETLINE
# undef HAVE_STPCPY
+# undef HAVE_STPNCPY
# endif
# undef HAVE_MEMPCPY
# undef HAVE_STRCHRNUL
@@ -574,6 +578,10 @@ typedef void (*sighandler_t)(int);
extern char *stpcpy(char *p, const char *to_add) FAST_FUNC;
#endif
+#ifndef HAVE_STPNCPY
+extern char *stpncpy(char *p, const char *to_add, size_t n) FAST_FUNC;
+#endif
+
#ifndef HAVE_MEMPCPY
#include <string.h>
/* In case we are wrong about !HAVE_MEMPCPY, and toolchain _does_ have
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 542211255..67c540abb 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -905,16 +905,8 @@ int busybox_main(int argc UNUSED_PARAM, char **argv)
# endif
# if NUM_APPLETS > 0
-void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **argv)
+void FAST_FUNC show_usage_if_dash_dash_help(int applet_no, char **argv)
{
- int argc = string_array_len(argv);
-
- /*
- * We do not use argv[0]: do not want to repeat massaging of
- * "-/sbin/halt" -> "halt", for example.
- */
- applet_name = name;
-
/* Special case. POSIX says "test --help"
* should be no different from e.g. "test --foo".
* Thus for "test", we skip --help check.
@@ -931,15 +923,32 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **ar
&& applet_no != APPLET_NO_false
# endif
) {
- if (argc == 2 && strcmp(argv[1], "--help") == 0) {
+ if (argv[1] && !argv[2] && strcmp(argv[1], "--help") == 0) {
/* Make "foo --help" exit with 0: */
xfunc_error_retval = 0;
bb_show_usage();
}
}
+}
+
+void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **argv)
+{
+ int argc;
+
+ /*
+ * We do not use argv[0]: do not want to repeat massaging of
+ * "-/sbin/halt" -> "halt", for example.
+ */
+ applet_name = name;
+
+ show_usage_if_dash_dash_help(applet_no, argv);
+
if (ENABLE_FEATURE_SUID)
check_suid(applet_no);
+
+ argc = string_array_len(argv);
xfunc_error_retval = applet_main[applet_no](argc, argv);
+
/* Note: applet_main() may also not return (die on a xfunc or such) */
xfunc_die();
}
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 367396b91..b0adcf140 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -769,8 +769,6 @@ static unsigned path_parse(char ***p)
if (!tmp)
break;
tmp++;
- if (*tmp == '\0')
- break; /* :<empty> */
npth++;
}
@@ -782,8 +780,6 @@ static unsigned path_parse(char ***p)
if (!tmp)
break;
*tmp++ = '\0'; /* ':' -> '\0' */
- if (*tmp == '\0')
- break; /* :<empty> */
res[npth++] = tmp;
}
/* special case: "match subdirectories of the current directory" */
@@ -854,6 +850,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
struct dirent *next;
struct stat st;
char *found;
+ const char *lpath;
if (paths[i] == NULL) { /* path_parse()'s last component? */
/* in PATH completion, current dir's subdir names
@@ -863,7 +860,8 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
paths[i] = (char *)".";
}
- dir = opendir(paths[i]);
+ lpath = *paths[i] ? paths[i] : ".";
+ dir = opendir(lpath);
if (!dir)
continue; /* don't print an error */
@@ -878,7 +876,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
if (strncmp(basecmd, name_found, baselen) != 0)
continue; /* no */
- found = concat_path_file(paths[i], name_found);
+ found = concat_path_file(lpath, name_found);
/* NB: stat() first so that we see is it a directory;
* but if that fails, use lstat() so that
* we still match dangling links */
diff --git a/libbb/platform.c b/libbb/platform.c
index 329b0237e..7913353e2 100644
--- a/libbb/platform.c
+++ b/libbb/platform.c
@@ -166,6 +166,18 @@ char* FAST_FUNC stpcpy(char *p, const char *to_add)
}
#endif
+#ifndef HAVE_STPNCPY
+char* FAST_FUNC stpncpy(char *p, const char *to_add, size_t n)
+{
+ while (n != 0 && (*p = *to_add) != '\0') {
+ p++;
+ to_add++;
+ n--;
+ }
+ return p;
+}
+#endif
+
#ifndef HAVE_GETLINE
ssize_t FAST_FUNC getline(char **lineptr, size_t *n, FILE *stream)
{
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index 65271e84f..a49fe8e01 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -109,8 +109,13 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv)
char *tmp_argv[argc+1];
memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0]));
applet_name = tmp_argv[0];
+
+ /* longjmp's (instead of returning) if --help is seen */
+ show_usage_if_dash_dash_help(applet_no, argv);
+
/* Finally we can call NOFORK applet's main() */
rc = applet_main[applet_no](argc, tmp_argv);
+
/* Important for shells: `which CMD` was failing */
fflush_all();
} else {
diff --git a/miscutils/bc.c b/miscutils/bc.c
index 02a61ac49..553d0f472 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -138,11 +138,54 @@
//usage:
//usage:#define dc_full_usage "\n"
//usage: "\nTiny RPN calculator. Operations:"
-//usage: "\n+, -, *, /, %, ~, ^," IF_FEATURE_DC_BIG(" |,")
+//usage: "\nArithmetic: + - * / % ^"
+//usage: IF_FEATURE_DC_BIG(
+//usage: "\n~ - divide with remainder"
+//usage: "\n| - modular exponentiation"
+//usage: "\nv - square root"
+//////// "\nA-F - digits 10..15
+//////// "\n_NNN - push negative number -NNN
+//////// "\n[string] - push string (in FreeBSD, \[, \] and \\ are escapes, not implemented here and in GNU)
+//////// "\nR - DC_LEX_POP pop and discard
+//////// "\nc - DC_LEX_CLEAR_STACK clear stack
+//////// "\nd - DC_LEX_DUPLICATE duplicate top-of-stack
+//////// "\nr - DC_LEX_SWAP swap top-of-stack
+//////// "\n:r - DC_LEX_COLON pop index, pop value, store to array 'r'
+//////// "\n;r - DC_LEX_SCOLON pop index, fetch from array 'r', push
+//////// "\nLr - DC_LEX_LOAD_POP pop register 'r', push
+//////// "\nSr - DC_LEX_STORE_PUSH pop, push to register 'r'
+//////// "\nlr - DC_LEX_LOAD read register 'r', push
+//////// "\nsr - DC_LEX_OP_ASSIGN pop, assign to register 'r'
+//////// "\n? - DC_LEX_READ read line and execute
+//////// "\nx - DC_LEX_EXECUTE pop string and execute
+//////// "\n<r - XC_LEX_OP_REL_GT pop, pop, execute register 'r' if top-of-stack was less
+//////// "\n>r - XC_LEX_OP_REL_LT pop, pop, execute register 'r' if top-of-stack was greater
+//////// "\n=r - XC_LEX_OP_REL_EQ pop, pop, execute register 'r' if equal
+//////// "\n !<r !>r !=r - negated forms
+//////// "\n >tef - "if greater execute register 't' else execute 'f'"
+//////// "\nQ - DC_LEX_NQUIT pop, "break N" from macro invocations
+//////// "\nq - DC_LEX_QUIT "break 2" (if less than 2 levels of macros, exit dc)
+//////// "\nX - DC_LEX_SCALE_FACTOR pop, push number of fractional digits
+//////// "\nZ - DC_LEX_LENGTH pop, push number of digits it has (or number of characters in string)
+//////// "\na - DC_LEX_ASCIIFY pop, push low-order byte as char or 1st char of string
+//////// "\n( - DC_LEX_LPAREN (FreeBSD, not in GNU) pop, pop, if top-of-stack was less push 1 else push 0
+//////// "\n{ - DC_LEX_LBRACE (FreeBSD, not in GNU) pop, pop, if top-of-stack was less-or-equal push 1 else push 0
+//////// "\nG - DC_LEX_EQ_NO_REG (FreeBSD, not in GNU) pop, pop, if equal push 1 else push 0
+//////// "\nN - DC_LEX_OP_BOOL_NOT (FreeBSD, not in GNU) pop, if 0 push 1 else push 0
+//////// FreeBSD also has J and M commands, used internally by bc
+//////// "\nn - DC_LEX_PRINT_POP pop, print without newline
+//////// "\nP - DC_LEX_PRINT_STREAM pop, print string or hex bytes
+//usage: )
//usage: "\np - print top of the stack without popping"
//usage: "\nf - print entire stack"
-//usage: "\nk - pop the value and set the precision"
+//////// "\nz - DC_LEX_STACK_LEVEL push stack depth
+//////// "\nK - DC_LEX_SCALE push precision
+//////// "\nI - DC_LEX_IBASE push input radix
+//////// "\nO - DC_LEX_OBASE push output radix
+//usage: IF_FEATURE_DC_BIG(
+//usage: "\nk - pop the value and set precision"
//usage: "\ni - pop the value and set input radix"
+//usage: )
//usage: "\no - pop the value and set output radix"
//usage: "\nExamples: dc -e'2 2 + p' -> 4, dc -e'8 8 * 2 2 + / p' -> 16"
//usage:
@@ -6217,13 +6260,20 @@ static unsigned long xc_program_len(BcNum *n)
{
size_t len = n->len;
- if (n->rdx != len) return len;
+ if (n->rdx != len)
+ // length(100): rdx 0 len 3, return 3
+ // length(0.01-0.01): rdx 2 len 0, return 2
+ // dc: 0.01 0.01 - Zp: rdx 2 len 0, return 1
+ return len != 0 ? len : (IS_BC ? n->rdx : 1);
+
+ // length(0): return 1
+ // length(0.000nnn): count nnn
for (;;) {
if (len == 0) break;
len--;
if (n->num[len] != 0) break;
}
- return len;
+ return len + 1;
}
static BC_STATUS zxc_program_builtin(char inst)
@@ -6251,12 +6301,12 @@ static BC_STATUS zxc_program_builtin(char inst)
if (inst == XC_INST_SQRT)
s = zbc_num_sqrt(num, &res.d.n, G.prog.scale);
#if ENABLE_BC
- else if (len != 0 && opnd->t == XC_RESULT_ARRAY) {
+ else if (len && opnd->t == XC_RESULT_ARRAY) {
bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len);
}
#endif
#if ENABLE_DC
- else if (len != 0 && !BC_PROG_NUM(opnd, num)) {
+ else if (len && !BC_PROG_NUM(opnd, num)) {
char **str;
size_t idx = opnd->t == XC_RESULT_STR ? opnd->d.id.idx : num->rdx;
@@ -6265,6 +6315,8 @@ static BC_STATUS zxc_program_builtin(char inst)
}
#endif
else {
+//TODO: length(.00) and scale(.00) should return 2, they return 1 and 0 now
+//(don't forget to check that dc Z and X commands do not break)
bc_num_ulong2num(&res.d.n, len ? xc_program_len(num) : xc_program_scale(num));
}
diff --git a/networking/dnsd.c b/networking/dnsd.c
index 0ff0290fb..a0f320c6c 100644
--- a/networking/dnsd.c
+++ b/networking/dnsd.c
@@ -379,7 +379,8 @@ Domain name in a message can be represented as either:
*/
static int process_packet(struct dns_entry *conf_data,
uint32_t conf_ttl,
- uint8_t *buf)
+ uint8_t *buf,
+ unsigned buflen)
{
struct dns_head *head;
struct type_and_class *unaligned_type_class;
@@ -402,9 +403,6 @@ static int process_packet(struct dns_entry *conf_data,
bb_simple_error_msg("response packet, ignored");
return 0; /* don't reply */
}
- /* QR = 1 "response", RCODE = 4 "Not Implemented" */
- outr_flags = htons(0x8000 | 4);
- err_msg = NULL;
/* start of query string */
query_string = (void *)(head + 1);
@@ -416,6 +414,15 @@ static int process_packet(struct dns_entry *conf_data,
/* where to append answer block */
answb = (void *)(unaligned_type_class + 1);
+ if (buflen < answb - buf) {
+ bb_simple_error_msg("packet too short");
+ return 0; /* don't reply */
+ }
+
+ /* QR = 1 "response", RCODE = 4 "Not Implemented" */
+ outr_flags = htons(0x8000 | 4);
+ err_msg = NULL;
+
/* OPCODE != 0 "standard query"? */
if ((head->flags & htons(0x7800)) != 0) {
err_msg = "opcode != 0";
@@ -559,7 +566,7 @@ int dnsd_main(int argc UNUSED_PARAM, char **argv)
if (OPT_verbose)
bb_simple_info_msg("got UDP packet");
buf[r] = '\0'; /* paranoia */
- r = process_packet(conf_data, conf_ttl, buf);
+ r = process_packet(conf_data, conf_ttl, buf, r);
if (r <= 0)
continue;
send_to_from(udps, buf, r, 0, &from->u.sa, &to->u.sa, lsa->len);
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 1f17b08ef..0f350fa6f 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -127,24 +127,15 @@
*/
#define MAX_VERBOSE 3
-
/* High-level description of the algorithm:
*
* We start running with very small poll_exp, BURSTPOLL,
* in order to quickly accumulate INITIAL_SAMPLES datapoints
* for each peer. Then, time is stepped if the offset is larger
- * than STEP_THRESHOLD, otherwise it isn't; anyway, we enlarge
- * poll_exp to MINPOLL and enter frequency measurement step:
- * we collect new datapoints but ignore them for WATCH_THRESHOLD
- * seconds. After WATCH_THRESHOLD seconds we look at accumulated
- * offset and estimate frequency drift.
- *
- * (frequency measurement step seems to not be strictly needed,
- * it is conditionally disabled with USING_INITIAL_FREQ_ESTIMATION
- * define set to 0)
+ * than STEP_THRESHOLD, otherwise it isn't stepped.
*
- * After this, we enter "steady state": we collect a datapoint,
- * we select the best peer, if this datapoint is not a new one
+ * Then poll_exp is set to MINPOLL, and we enter "steady state": we collect
+ * a datapoint, we select the best peer, if this datapoint is not a new one
* (IOW: if this datapoint isn't for selected peer), sleep
* and collect another one; otherwise, use its offset to update
* frequency drift, if offset is somewhat large, reduce poll_exp,
@@ -169,7 +160,7 @@
* datapoints after the step.
*/
-#define INITIAL_SAMPLES 4 /* how many samples do we want for init */
+#define INITIAL_SAMPLES 3 /* how many samples do we want for init */
#define MIN_FREQHOLD 10 /* adjust offset, but not freq in this many first adjustments */
#define BAD_DELAY_GROWTH 4 /* drop packet if its delay grew by more than this factor */
@@ -189,13 +180,10 @@
// ^^^^ used to be 0.125.
// Since Linux 2.6.26 (circa 2006), kernel accepts (-0.5s, +0.5s) range
-/* Stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */
-//UNUSED: #define WATCH_THRESHOLD 128
-/* NB: set WATCH_THRESHOLD to ~60 when debugging to save time) */
-//UNUSED: #define PANIC_THRESHOLD 1000 /* panic threshold (sec) */
-/*
- * If we got |offset| > BIGOFF from a peer, cap next query interval
+// #define PANIC_THRESHOLD 1000 /* panic threshold (sec) */
+
+/* If we got |offset| > BIGOFF from a peer, cap next query interval
* for this peer by this many seconds:
*/
#define BIGOFF STEP_THRESHOLD
@@ -204,18 +192,16 @@
#define FREQ_TOLERANCE 0.000015 /* frequency tolerance (15 PPM) */
#define BURSTPOLL 0 /* initial poll */
#define MINPOLL 5 /* minimum poll interval. std ntpd uses 6 (6: 64 sec) */
-/*
- * If offset > discipline_jitter * POLLADJ_GATE, and poll interval is > 2^BIGPOLL,
+/* If offset > discipline_jitter * POLLADJ_GATE, and poll interval is > 2^BIGPOLL,
* then it is decreased _at once_. (If <= 2^BIGPOLL, it will be decreased _eventually_).
*/
#define BIGPOLL 9 /* 2^9 sec ~= 8.5 min */
#define MAXPOLL 12 /* maximum poll interval (12: 1.1h, 17: 36.4h). std ntpd uses 17 */
-/*
- * Actively lower poll when we see such big offsets.
+/* Actively lower poll when we see such big offsets.
* With SLEW_THRESHOLD = 0.125, it means we try to sync more aggressively
* if offset increases over ~0.04 sec
*/
-//#define POLLDOWN_OFFSET (SLEW_THRESHOLD / 3)
+// #define POLLDOWN_OFFSET (SLEW_THRESHOLD / 3)
#define MINDISP 0.01 /* minimum dispersion (sec) */
#define MAXDISP 16 /* maximum dispersion (sec) */
#define MAXSTRAT 16 /* maximum stratum (infinity metric) */
@@ -223,7 +209,16 @@
#define MIN_SELECTED 1 /* minimum intersection survivors */
#define MIN_CLUSTERED 3 /* minimum cluster survivors */
-#define MAXDRIFT 0.000500 /* frequency drift we can correct (500 PPM) */
+/* Correct frequency ourself (0) or let kernel do it (1)? */
+#define USING_KERNEL_PLL_LOOP 1
+// /* frequency drift we can correct (500 PPM) */
+// #define MAXDRIFT 0.000500
+// /* Compromise Allan intercept (sec). doc uses 1500, std ntpd uses 512 */
+// #define ALLAN 512
+// /* PLL loop gain */
+// #define PLL 65536
+// /* FLL loop gain [why it depends on MAXPOLL??] */
+// #define FLL (MAXPOLL + 1)
/* Poll-adjust threshold.
* When we see that offset is small enough compared to discipline jitter,
@@ -239,12 +234,6 @@
*/
#define POLLADJ_GATE 4
#define TIMECONST_HACK_GATE 2
-/* Compromise Allan intercept (sec). doc uses 1500, std ntpd uses 512 */
-#define ALLAN 512
-/* PLL loop gain */
-#define PLL 65536
-/* FLL loop gain [why it depends on MAXPOLL??] */
-#define FLL (MAXPOLL + 1)
/* Parameter averaging constant */
#define AVG 4
@@ -372,10 +361,6 @@ typedef struct {
char p_hostname[1];
} peer_t;
-
-#define USING_KERNEL_PLL_LOOP 1
-#define USING_INITIAL_FREQ_ESTIMATION 0
-
enum {
OPT_n = (1 << 0),
OPT_q = (1 << 1),
@@ -454,7 +439,7 @@ struct globals {
*/
#define G_precision_exp -9
/*
- * G_precision_exp is used only for construction outgoing packets.
+ * G_precision_exp is used only for constructing outgoing packets.
* It's ok to set G_precision_sec to a slightly different value
* (One which is "nicer looking" in logs).
* Exact value would be (1.0 / (1 << (- G_precision_exp))):
@@ -462,12 +447,7 @@ struct globals {
#define G_precision_sec 0.002
uint8_t stratum;
-#define STATE_NSET 0 /* initial state, "nothing is set" */
-//#define STATE_FSET 1 /* frequency set from file */
-//#define STATE_SPIK 2 /* spike detected */
-//#define STATE_FREQ 3 /* initial frequency */
-#define STATE_SYNC 4 /* clock synchronized (normal operation) */
- uint8_t discipline_state; // doc calls it c.state
+ //uint8_t discipline_state; // doc calls it c.state
uint8_t poll_exp; // s.poll
int polladj_count; // c.count
int FREQHOLD_cnt;
@@ -490,7 +470,6 @@ struct globals {
};
#define G (*ptr_to_globals)
-
#define VERB1 if (MAX_VERBOSE && G.verbose)
#define VERB2 if (MAX_VERBOSE >= 2 && G.verbose >= 2)
#define VERB3 if (MAX_VERBOSE >= 3 && G.verbose >= 3)
@@ -657,104 +636,11 @@ filter_datapoints(peer_t *p)
double sum, wavg;
datapoint_t *fdp;
-#if 0
/* Simulations have shown that use of *averaged* offset for p->filter_offset
* is in fact worse than simply using last received one: with large poll intervals
* (>= 2048) averaging code uses offset values which are outdated by hours,
* and time/frequency correction goes totally wrong when fed essentially bogus offsets.
*/
- int got_newest;
- double minoff, maxoff, w;
- double x = x; /* for compiler */
- double oldest_off = oldest_off;
- double oldest_age = oldest_age;
- double newest_off = newest_off;
- double newest_age = newest_age;
-
- fdp = p->filter_datapoint;
-
- minoff = maxoff = fdp[0].d_offset;
- for (i = 1; i < NUM_DATAPOINTS; i++) {
- if (minoff > fdp[i].d_offset)
- minoff = fdp[i].d_offset;
- if (maxoff < fdp[i].d_offset)
- maxoff = fdp[i].d_offset;
- }
-
- idx = p->datapoint_idx; /* most recent datapoint's index */
- /* Average offset:
- * Drop two outliers and take weighted average of the rest:
- * most_recent/2 + older1/4 + older2/8 ... + older5/32 + older6/32
- * we use older6/32, not older6/64 since sum of weights should be 1:
- * 1/2 + 1/4 + 1/8 + 1/16 + 1/32 + 1/32 = 1
- */
- wavg = 0;
- w = 0.5;
- /* n-1
- * --- dispersion(i)
- * filter_dispersion = \ -------------
- * / (i+1)
- * --- 2
- * i=0
- */
- got_newest = 0;
- sum = 0;
- for (i = 0; i < NUM_DATAPOINTS; i++) {
- VERB5 {
- bb_error_msg("datapoint[%d]: off:%f disp:%f(%f) age:%f%s",
- i,
- fdp[idx].d_offset,
- fdp[idx].d_dispersion, dispersion(&fdp[idx]),
- G.cur_time - fdp[idx].d_recv_time,
- (minoff == fdp[idx].d_offset || maxoff == fdp[idx].d_offset)
- ? " (outlier by offset)" : ""
- );
- }
-
- sum += dispersion(&fdp[idx]) / (2 << i);
-
- if (minoff == fdp[idx].d_offset) {
- minoff -= 1; /* so that we don't match it ever again */
- } else
- if (maxoff == fdp[idx].d_offset) {
- maxoff += 1;
- } else {
- oldest_off = fdp[idx].d_offset;
- oldest_age = G.cur_time - fdp[idx].d_recv_time;
- if (!got_newest) {
- got_newest = 1;
- newest_off = oldest_off;
- newest_age = oldest_age;
- }
- x = oldest_off * w;
- wavg += x;
- w /= 2;
- }
-
- idx = (idx - 1) & (NUM_DATAPOINTS - 1);
- }
- p->filter_dispersion = sum;
- wavg += x; /* add another older6/64 to form older6/32 */
- /* Fix systematic underestimation with large poll intervals.
- * Imagine that we still have a bit of uncorrected drift,
- * and poll interval is big (say, 100 sec). Offsets form a progression:
- * 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 - 0.7 is most recent.
- * The algorithm above drops 0.0 and 0.7 as outliers,
- * and then we have this estimation, ~25% off from 0.7:
- * 0.1/32 + 0.2/32 + 0.3/16 + 0.4/8 + 0.5/4 + 0.6/2 = 0.503125
- */
- x = oldest_age - newest_age;
- if (x != 0) {
- x = newest_age / x; /* in above example, 100 / (600 - 100) */
- if (x < 1) { /* paranoia check */
- x = (newest_off - oldest_off) * x; /* 0.5 * 100/500 = 0.1 */
- wavg += x;
- }
- }
- p->filter_offset = wavg;
-
-#else
-
fdp = p->filter_datapoint;
idx = p->datapoint_idx; /* most recent datapoint's index */
@@ -777,7 +663,6 @@ filter_datapoints(peer_t *p)
}
wavg /= NUM_DATAPOINTS;
p->filter_dispersion = sum;
-#endif
/* +----- -----+ ^ 1/2
* | n-1 |
@@ -1089,7 +974,6 @@ send_query_to_peer(peer_t *p)
set_next(p, RESPONSE_INTERVAL);
}
-
/* Note that there is no provision to prevent several run_scripts
* to be started in quick succession. In fact, it happens rather often
* if initial syncronization results in a step.
@@ -1548,15 +1432,14 @@ select_and_cluster(void)
* Local clock discipline and its helpers
*/
static void
-set_new_values(int disc_state, double offset, double recv_time)
+set_new_values(double offset, double recv_time)
{
/* Enter new state and set state variables. Note we use the time
* of the last clock filter sample, which must be earlier than
* the current time.
*/
- VERB4 bb_error_msg("disc_state=%d last update offset=%f recv_time=%f",
- disc_state, offset, recv_time);
- G.discipline_state = disc_state;
+ VERB4 bb_error_msg("last update offset=%f recv_time=%f",
+ offset, recv_time);
G.last_update_offset = offset;
G.last_update_recv_time = recv_time;
}
@@ -1572,8 +1455,6 @@ update_local_clock(peer_t *p)
double abs_offset;
#if !USING_KERNEL_PLL_LOOP
double freq_drift;
-#endif
-#if !USING_KERNEL_PLL_LOOP || USING_INITIAL_FREQ_ESTIMATION
double since_last_update;
#endif
double etemp, dtemp;
@@ -1603,63 +1484,15 @@ update_local_clock(peer_t *p)
* action is and defines how the system reacts to large time
* and frequency errors.
*/
-#if !USING_KERNEL_PLL_LOOP || USING_INITIAL_FREQ_ESTIMATION
- since_last_update = recv_time - G.reftime;
-#endif
#if !USING_KERNEL_PLL_LOOP
+ since_last_update = recv_time - G.reftime;
freq_drift = 0;
#endif
-#if USING_INITIAL_FREQ_ESTIMATION
- if (G.discipline_state == STATE_FREQ) {
- /* Ignore updates until the stepout threshold */
- if (since_last_update < WATCH_THRESHOLD) {
- VERB4 bb_error_msg("measuring drift, datapoint ignored, %f sec remains",
- WATCH_THRESHOLD - since_last_update);
- return 0; /* "leave poll interval as is" */
- }
-# if !USING_KERNEL_PLL_LOOP
- freq_drift = (offset - G.last_update_offset) / since_last_update;
-# endif
- }
-#endif
/* There are two main regimes: when the
* offset exceeds the step threshold and when it does not.
*/
if (abs_offset > STEP_THRESHOLD) {
-#if 0
- double remains;
-
-// This "spike state" seems to be useless, peer selection already drops
-// occassional "bad" datapoints. If we are here, there were _many_
-// large offsets. When a few first large offsets are seen,
-// we end up in "no valid datapoints, no peer selected" state.
-// Only when enough of them are seen (which means it's not a fluke),
-// we end up here. Looks like _our_ clock is off.
- switch (G.discipline_state) {
- case STATE_SYNC:
- /* The first outlyer: ignore it, switch to SPIK state */
- VERB3 bb_error_msg("update from %s: offset:%+f, spike%s",
- p->p_dotted, offset,
- "");
- G.discipline_state = STATE_SPIK;
- return -1; /* "decrease poll interval" */
-
- case STATE_SPIK:
- /* Ignore succeeding outlyers until either an inlyer
- * is found or the stepout threshold is exceeded.
- */
- remains = WATCH_THRESHOLD - since_last_update;
- if (remains > 0) {
- VERB3 bb_error_msg("update from %s: offset:%+f, spike%s",
- p->p_dotted, offset,
- ", datapoint ignored");
- return -1; /* "decrease poll interval" */
- }
- /* fall through: we need to step */
- } /* switch */
-#endif
-
/* Step the time and clamp down the poll interval.
*
* In NSET state an initial frequency correction is
@@ -1694,16 +1527,17 @@ update_local_clock(peer_t *p)
recv_time += offset;
-#if USING_INITIAL_FREQ_ESTIMATION
- if (G.discipline_state == STATE_NSET) {
- set_new_values(STATE_FREQ, /*offset:*/ 0, recv_time);
- return 1; /* "ok to increase poll interval" */
- }
-#endif
abs_offset = offset = 0;
- set_new_values(STATE_SYNC, offset, recv_time);
+ set_new_values(offset, recv_time);
} else { /* abs_offset <= STEP_THRESHOLD */
+ if (option_mask32 & OPT_q) {
+ /* We were only asked to set time once.
+ * The clock is precise enough, no need to step.
+ */
+ exit(0);
+ }
+
/* The ratio is calculated before jitter is updated to make
* poll adjust code more sensitive to large offsets.
*/
@@ -1718,75 +1552,31 @@ update_local_clock(peer_t *p)
if (G.discipline_jitter < G_precision_sec)
G.discipline_jitter = G_precision_sec;
- switch (G.discipline_state) {
- case STATE_NSET:
- if (option_mask32 & OPT_q) {
- /* We were only asked to set time once.
- * The clock is precise enough, no need to step.
- */
- exit(0);
- }
-#if USING_INITIAL_FREQ_ESTIMATION
- /* This is the first update received and the frequency
- * has not been initialized. The first thing to do
- * is directly measure the oscillator frequency.
- */
- set_new_values(STATE_FREQ, offset, recv_time);
-#else
- set_new_values(STATE_SYNC, offset, recv_time);
-#endif
- VERB4 bb_simple_error_msg("transitioning to FREQ, datapoint ignored");
- return 0; /* "leave poll interval as is" */
-
-#if 0 /* this is dead code for now */
- case STATE_FSET:
- /* This is the first update and the frequency
- * has been initialized. Adjust the phase, but
- * don't adjust the frequency until the next update.
- */
- set_new_values(STATE_SYNC, offset, recv_time);
- /* freq_drift remains 0 */
- break;
-#endif
-
-#if USING_INITIAL_FREQ_ESTIMATION
- case STATE_FREQ:
- /* since_last_update >= WATCH_THRESHOLD, we waited enough.
- * Correct the phase and frequency and switch to SYNC state.
- * freq_drift was already estimated (see code above)
- */
- set_new_values(STATE_SYNC, offset, recv_time);
- break;
-#endif
-
- default:
#if !USING_KERNEL_PLL_LOOP
- /* Compute freq_drift due to PLL and FLL contributions.
- *
- * The FLL and PLL frequency gain constants
- * depend on the poll interval and Allan
- * intercept. The FLL is not used below one-half
- * the Allan intercept. Above that the loop gain
- * increases in steps to 1 / AVG.
- */
- if ((1 << G.poll_exp) > ALLAN / 2) {
- etemp = FLL - G.poll_exp;
- if (etemp < AVG)
- etemp = AVG;
- freq_drift += (offset - G.last_update_offset) / (MAXD(since_last_update, ALLAN) * etemp);
- }
- /* For the PLL the integration interval
- * (numerator) is the minimum of the update
- * interval and poll interval. This allows
- * oversampling, but not undersampling.
- */
- etemp = MIND(since_last_update, (1 << G.poll_exp));
- dtemp = (4 * PLL) << G.poll_exp;
- freq_drift += offset * etemp / SQUARE(dtemp);
-#endif
- set_new_values(STATE_SYNC, offset, recv_time);
- break;
+ /* Compute freq_drift due to PLL and FLL contributions.
+ *
+ * The FLL and PLL frequency gain constants
+ * depend on the poll interval and Allan
+ * intercept. The FLL is not used below one-half
+ * the Allan intercept. Above that the loop gain
+ * increases in steps to 1 / AVG.
+ */
+ if ((1 << G.poll_exp) > ALLAN / 2) {
+ etemp = FLL - G.poll_exp;
+ if (etemp < AVG)
+ etemp = AVG;
+ freq_drift += (offset - G.last_update_offset) / (MAXD(since_last_update, ALLAN) * etemp);
}
+ /* For the PLL the integration interval
+ * (numerator) is the minimum of the update
+ * interval and poll interval. This allows
+ * oversampling, but not undersampling.
+ */
+ etemp = MIND(since_last_update, (1 << G.poll_exp));
+ dtemp = (4 * PLL) << G.poll_exp;
+ freq_drift += offset * etemp / SQUARE(dtemp);
+#endif
+ set_new_values(offset, recv_time);
if (G.stratum != p->lastpkt_stratum + 1) {
G.stratum = p->lastpkt_stratum + 1;
run_script("stratum", offset);
@@ -1805,9 +1595,7 @@ update_local_clock(peer_t *p)
G.rootdisp = p->lastpkt_rootdisp + dtemp;
VERB4 bb_error_msg("updating leap/refid/reftime/rootdisp from peer %s", p->p_dotted);
- /* We are in STATE_SYNC now, but did not do adjtimex yet.
- * (Any other state does not reach this, they all return earlier)
- * By this time, freq_drift and offset are set
+ /* By this time, freq_drift and offset are set
* to values suitable for adjtimex.
*/
#if !USING_KERNEL_PLL_LOOP
@@ -1963,7 +1751,6 @@ update_local_clock(peer_t *p)
return 1; /* "ok to increase poll interval" */
}
-
/*
* We've got a new reply packet from a peer, process it
* (helpers first)
@@ -2349,6 +2136,12 @@ recv_and_process_client_pkt(void /*int fd*/)
do_sendto(G_listen_fd,
/*from:*/ &to->u.sa, /*to:*/ from, /*addrlen:*/ to->len,
&msg, size);
+ VERB3 {
+ char *addr;
+ addr = xmalloc_sockaddr2dotted_noport(from);
+ bb_error_msg("responded to query from %s", addr);
+ free(addr);
+ }
bail:
free(to);
@@ -2767,7 +2560,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
timeout++; /* (nextaction - G.cur_time) rounds down, compensating */
/* Here we may block */
- VERB2 {
+ VERB3 {
if (i > (ENABLE_FEATURE_NTPD_SERVER && G_listen_fd != -1)) {
/* We wait for at least one reply.
* Poll for it, without wasting time for message.
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index fbdaa99bd..76b087b92 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -1589,8 +1589,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
}
if ((packet.d6_xid32 & htonl(0x00ffffff)) != xid) {
- log1("xid %x (our is %x), ignoring packet",
- (unsigned)(packet.d6_xid32 & htonl(0x00ffffff)), (unsigned)xid);
+ log1("xid %x (our is %x)%s",
+ (unsigned)(packet.d6_xid32 & htonl(0x00ffffff)), (unsigned)xid,
+ ", ignoring packet"
+ );
continue;
}
@@ -1743,7 +1745,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
free(client6_data.ia_na);
client6_data.ia_na = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_NA);
if (!client6_data.ia_na) {
- bb_info_msg("no %s option, ignoring packet", "IA_NA");
+ bb_info_msg("no %s option%s", "IA_NA", ", ignoring packet");
continue;
}
if (client6_data.ia_na->len < (4 + 4 + 4) + (2 + 2 + 16 + 4 + 4)) {
@@ -1756,7 +1758,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
D6_OPT_IAADDR
);
if (!iaaddr) {
- bb_info_msg("no %s option, ignoring packet", "IAADDR");
+ bb_info_msg("no %s option%s", "IAADDR", ", ignoring packet");
continue;
}
if (iaaddr->len < (16 + 4 + 4)) {
@@ -1781,7 +1783,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
free(client6_data.ia_pd);
client6_data.ia_pd = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_PD);
if (!client6_data.ia_pd) {
- bb_info_msg("no %s option, ignoring packet", "IA_PD");
+ bb_info_msg("no %s option%s", "IA_PD", ", ignoring packet");
continue;
}
if (client6_data.ia_pd->len < (4 + 4 + 4) + (2 + 2 + 4 + 4 + 1 + 16)) {
@@ -1794,7 +1796,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
D6_OPT_IAPREFIX
);
if (!iaprefix) {
- bb_info_msg("no %s option, ignoring packet", "IAPREFIX");
+ bb_info_msg("no %s option%s", "IAPREFIX", ", ignoring packet");
continue;
}
if (iaprefix->len < (4 + 4 + 1 + 16)) {
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 922c71ebd..bbcbd1fca 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -729,7 +729,7 @@ static NOINLINE int send_discover(uint32_t xid, uint32_t requested)
*/
add_client_options(&packet);
- bb_info_msg("sending %s", "discover");
+ bb_simple_info_msg("broadcasting discover");
return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY);
}
@@ -742,6 +742,7 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste
{
struct dhcp_packet packet;
struct in_addr temp_addr;
+ char server_str[sizeof("255.255.255.255")];
/*
* RFC 2131 4.3.2 DHCPREQUEST message
@@ -772,8 +773,13 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste
*/
add_client_options(&packet);
+ temp_addr.s_addr = server;
+ strcpy(server_str, inet_ntoa(temp_addr));
temp_addr.s_addr = requested;
- bb_info_msg("sending select for %s", inet_ntoa(temp_addr));
+ bb_info_msg("broadcasting select for %s, server %s",
+ inet_ntoa(temp_addr),
+ server_str
+ );
return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY);
}
@@ -782,7 +788,6 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste
static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr)
{
struct dhcp_packet packet;
- struct in_addr temp_addr;
/*
* RFC 2131 4.3.2 DHCPREQUEST message
@@ -813,8 +818,14 @@ static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr)
*/
add_client_options(&packet);
- temp_addr.s_addr = server;
- bb_info_msg("sending renew to %s", inet_ntoa(temp_addr));
+ if (server) {
+ struct in_addr temp_addr;
+ temp_addr.s_addr = server;
+ bb_info_msg("sending renew to server %s", inet_ntoa(temp_addr));
+ } else {
+ bb_simple_info_msg("broadcasting renew");
+ }
+
return bcast_or_ucast(&packet, ciaddr, server);
}
@@ -843,7 +854,7 @@ static NOINLINE int send_decline(/*uint32_t xid,*/ uint32_t server, uint32_t req
udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
- bb_info_msg("sending %s", "decline");
+ bb_simple_info_msg("broadcasting decline");
return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY);
}
#endif
@@ -1644,8 +1655,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
}
if (packet.xid != xid) {
- log1("xid %x (our is %x), ignoring packet",
- (unsigned)packet.xid, (unsigned)xid);
+ log1("xid %x (our is %x)%s",
+ (unsigned)packet.xid, (unsigned)xid,
+ ", ignoring packet"
+ );
continue;
}
@@ -1720,6 +1733,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
unsigned start;
uint32_t lease_seconds;
struct in_addr temp_addr;
+ char server_str[sizeof("255.255.255.255")];
uint8_t *temp;
temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME);
@@ -1775,9 +1789,11 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
}
#endif
/* enter bound state */
+ temp_addr.s_addr = server_addr;
+ strcpy(server_str, inet_ntoa(temp_addr));
temp_addr.s_addr = packet.yiaddr;
- bb_info_msg("lease of %s obtained, lease time %u",
- inet_ntoa(temp_addr), (unsigned)lease_seconds);
+ bb_info_msg("lease of %s obtained from %s, lease time %u",
+ inet_ntoa(temp_addr), server_str, (unsigned)lease_seconds);
requested_ip = packet.yiaddr;
start = monotonic_sec();
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index cd32cb437..260130507 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -1048,7 +1048,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
move_from_unaligned32(server_id_network_order, server_id_opt);
if (server_id_network_order != server_data.server_nip) {
/* client talks to somebody else */
- log1("server ID doesn't match%s", ", ignoring");
+ log1("server ID doesn't match%s", ", ignoring packet");
continue;
}
}
@@ -1171,7 +1171,7 @@ o DHCPREQUEST generated during REBINDING state:
if (!requested_ip_opt) {
requested_nip = packet.ciaddr;
if (requested_nip == 0) {
- log1("no requested IP and no ciaddr%s", ", ignoring");
+ log1("no requested IP and no ciaddr%s", ", ignoring packet");
break;
}
}
diff --git a/scripts/trylink b/scripts/trylink
index 6b74f092d..2255deee7 100755
--- a/scripts/trylink
+++ b/scripts/trylink
@@ -1,5 +1,6 @@
#!/bin/sh
+#debug=true
debug=false
# Linker flags used:
@@ -77,7 +78,13 @@ CFLAGS="$3"
LDFLAGS="$4"
O_FILES="$5"
A_FILES="$6"
+# We try to drop libraries from LDLIBS if build works without them,
+# but ones from CONFIG_EXTRA_LDLIBS are always linked in.
+# (For example, musl has stub utmp implementation, and if you link with
+# a real utmp library in LDLIBS, dropping it "works" but resulting binary
+# does not work properly).
LDLIBS="$7"
+CONFIG_EXTRA_LDLIBS="$8"
# The --sort-section option is not supported by older versions of ld
SORT_SECTION="-Wl,--sort-section,alignment"
@@ -125,8 +132,8 @@ LDLIBS=`echo "$LDLIBS" | xargs -n1 | sort | uniq | xargs`
# First link with all libs. If it fails, bail out
echo "Trying libraries: $LDLIBS"
# "lib1 lib2 lib3" -> "-llib1 -llib2 -llib3"
-l_list=`echo " $LDLIBS " | sed -e 's: \([^- ][^ ]*\): -l\1:g'`
-test "x$l_list" != "x" && l_list="$START_GROUP $l_list $END_GROUP"
+l_list=`echo " $LDLIBS $CONFIG_EXTRA_LDLIBS " | sed -e 's: \([^- ][^ ]*\): -l\1:g' -e 's/^ *//'`
+test x"$l_list" != x"" && l_list="$START_GROUP $l_list $END_GROUP"
try $CC $CFLAGS $LDFLAGS \
-o $EXE \
$SORT_COMMON \
@@ -151,7 +158,7 @@ while test "$LDLIBS"; do
for one in $LDLIBS; do
without_one=`echo " $LDLIBS " | sed "s/ $one / /g" | xargs`
# "lib1 lib2 lib3" -> "-llib1 -llib2 -llib3"
- l_list=`echo " $without_one " | sed -e 's: \([^- ][^ ]*\): -l\1:g'`
+ l_list=`echo " $without_one $CONFIG_EXTRA_LDLIBS " | sed -e 's: \([^- ][^ ]*\): -l\1:g' -e 's/^ *//'`
test x"$l_list" != x"" && l_list="$START_GROUP $l_list $END_GROUP"
$debug && echo "Trying -l options: '$l_list'"
try $CC $CFLAGS $LDFLAGS \
@@ -179,8 +186,8 @@ done
# Make the binary with final, minimal list of libs
echo "Final link with: ${LDLIBS:-<none>}"
-l_list=`echo " $LDLIBS " | sed -e 's: \([^- ][^ ]*\): -l\1:g'`
-test "x$l_list" != "x" && l_list="$START_GROUP $l_list $END_GROUP"
+l_list=`echo " $LDLIBS $CONFIG_EXTRA_LDLIBS " | sed -e 's: \([^- ][^ ]*\): -l\1:g' -e 's/^ *//'`
+test x"$l_list" != x"" && l_list="$START_GROUP $l_list $END_GROUP"
# --verbose gives us gobs of info to stdout (e.g. linker script used)
if ! test -f busybox_ldscript; then
try $CC $CFLAGS $LDFLAGS \
diff --git a/shell/ash.c b/shell/ash.c
index 1aead6df4..6a16833b1 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -4263,9 +4263,7 @@ sprint_status48(char *os, int status, int sigonly)
#endif
}
st &= 0x7f;
-//TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
- //s = stpncpy(s, strsignal(st), 32); //not all libc have stpncpy()
- s += fmtstr(s, 32, strsignal(st));
+ s = stpncpy(s, strsignal(st), 32);
if (WCOREDUMP(status)) {
s = stpcpy(s, " (core dumped)");
}
diff --git a/testsuite/bc.tests b/testsuite/bc.tests
index 179d5d2a2..1c748727a 100755
--- a/testsuite/bc.tests
+++ b/testsuite/bc.tests
@@ -182,6 +182,11 @@ testing "bc print 1,2,3" \
"123" \
"" "print 1,2,3"
+testing "bc length" \
+ "bc" \
+ "1\n3\n1\n3\n3\n" \
+ "" "length(0); length(100); length(0.01); length(0.00120); length(0.012-0.012);"
+
testing "bc { print 1 }" \
"bc" \
"1" \
diff --git a/testsuite/dc.tests b/testsuite/dc.tests
index 361bc8459..ad0099354 100755
--- a/testsuite/dc.tests
+++ b/testsuite/dc.tests
@@ -114,6 +114,11 @@ testing "dc newline can be a register" \
"2\n9\n" \
"" "[2p]s\n[3p]l\nx\n9p"
+testing "dc Z (length) for numbers" \
+ "dc" \
+ "1\n1\n3\n1\n3\n1\n" \
+ "" "0Zp\n0.000Zp\n100Zp\n0.01Zp\n0.00120Zp\n0.0012 0.0012 - Zp\n"
+
for f in dc_*.dc; do
r="`basename "$f" .dc`_results.txt"
test -f "$r" || continue
diff --git a/testsuite/start-stop-daemon.tests b/testsuite/start-stop-daemon.tests
index 2ddb7fefb..0757b1288 100755
--- a/testsuite/start-stop-daemon.tests
+++ b/testsuite/start-stop-daemon.tests
@@ -21,8 +21,13 @@ testing "start-stop-daemon without -x and -a" \
"1\n" \
"" ""
+# This runs /bin/false with argv[0..2] of { "qwerty", "false", NULL }.
+#
# Unfortunately, this does not actually check argv[0] correctness,
# but at least it checks that pathname to exec() is correct
+#
+# NB: this fails if /bin/false is a busybox symlink:
+# busybox looks at argv[0] and says "qwerty: applet not found"
testing "start-stop-daemon with both -x and -a" \
'start-stop-daemon -S -x /bin/false -a qwerty false 2>&1; echo $?' \
"1\n" \