aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-03-01 11:48:04 +0000
committerRon Yorston <rmy@pobox.com>2021-03-01 11:48:04 +0000
commite2e8e16b465d34759678b8170c44ce62c5b74eb0 (patch)
treeabc31e3e2c1d0de089ae5e1e6d37672394757af9
parentb5cd41cdf4e6afd475fe34b755f99578e20b08ca (diff)
parent9b6bcfda0e11c0e73a966a77110f6c68425cff34 (diff)
downloadbusybox-w32-e2e8e16b465d34759678b8170c44ce62c5b74eb0.tar.gz
busybox-w32-e2e8e16b465d34759678b8170c44ce62c5b74eb0.tar.bz2
busybox-w32-e2e8e16b465d34759678b8170c44ce62c5b74eb0.zip
Merge branch 'busybox' into merge
-rw-r--r--Makefile1
-rw-r--r--Makefile.flags7
-rw-r--r--applets/usage_pod.c2
-rw-r--r--coreutils/echo.c10
-rw-r--r--editors/diff.c2
-rw-r--r--include/libbb.h1
-rw-r--r--include/platform.h8
-rw-r--r--libbb/appletlib.c70
-rw-r--r--libbb/lineedit.c19
-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.c280
-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
21 files changed, 253 insertions, 330 deletions
diff --git a/Makefile b/Makefile
index 14c4c4440..4cb8d924c 100644
--- a/Makefile
+++ b/Makefile
@@ -625,6 +625,7 @@ quiet_cmd_busybox__ ?= LINK $@
625 "$(core-y)" \ 625 "$(core-y)" \
626 "$(libs-y)" \ 626 "$(libs-y)" \
627 "$(LDLIBS)" \ 627 "$(LDLIBS)" \
628 "$(CONFIG_EXTRA_LDLIBS)" \
628 && $(srctree)/scripts/generate_BUFSIZ.sh --post include/common_bufsiz.h 629 && $(srctree)/scripts/generate_BUFSIZ.sh --post include/common_bufsiz.h
629 630
630# Generate System.map 631# Generate System.map
diff --git a/Makefile.flags b/Makefile.flags
index 94ed4e40e..8ea0687c7 100644
--- a/Makefile.flags
+++ b/Makefile.flags
@@ -190,7 +190,7 @@ LDLIBS += $(if $(SELINUX_LIBS),$(SELINUX_LIBS:-l%=%),$(SELINUX_PC_MODULES:lib%=%
190endif 190endif
191 191
192ifeq ($(CONFIG_FEATURE_NSLOOKUP_BIG),y) 192ifeq ($(CONFIG_FEATURE_NSLOOKUP_BIG),y)
193ifeq ($(CONFIG_UNAME_OSNAME),Linux) 193ifneq (,$(findstring linux,$(shell $(CC) $(CFLAGS) -dumpmachine)))
194LDLIBS += resolv 194LDLIBS += resolv
195endif 195endif
196endif 196endif
@@ -218,11 +218,6 @@ LDFLAGS += $(strip $(subst ",,$(CONFIG_EXTRA_LDFLAGS)))
218#")) 218#"))
219endif 219endif
220 220
221ifneq ($(CONFIG_EXTRA_LDLIBS),)
222LDLIBS += $(strip $(subst ",,$(CONFIG_EXTRA_LDLIBS)))
223#"))
224endif
225
226# Busybox is a stack-fatty so make sure we increase default size 221# Busybox is a stack-fatty so make sure we increase default size
227# TODO: use "make stksizes" to find & fix big stack users 222# TODO: use "make stksizes" to find & fix big stack users
228# (we stole scripts/checkstack.pl from the kernel... thanks guys!) 223# (we stole scripts/checkstack.pl from the kernel... thanks guys!)
diff --git a/applets/usage_pod.c b/applets/usage_pod.c
index ccc166aed..9e6d3f0ee 100644
--- a/applets/usage_pod.c
+++ b/applets/usage_pod.c
@@ -71,7 +71,7 @@ int main(void)
71 } else { 71 } else {
72 printf(", "); 72 printf(", ");
73 } 73 }
74 printf(usage_array[i].aname); 74 printf("%s", usage_array[i].aname);
75 col += len2; 75 col += len2;
76 } 76 }
77 printf("\n\n"); 77 printf("\n\n");
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)
97#else 97#else
98 char nflag = 1; 98 char nflag = 1;
99 char eflag = 0; 99 char eflag = 0;
100 int err;
100 101
101 while ((arg = *++argv) != NULL) { 102 while ((arg = *++argv) != NULL) {
102 char n, e; 103 char n, e;
@@ -185,13 +186,12 @@ int echo_main(int argc UNUSED_PARAM, char **argv)
185 do_write: 186 do_write:
186 /* Careful to error out on partial writes too (think ENOSPC!) */ 187 /* Careful to error out on partial writes too (think ENOSPC!) */
187 errno = 0; 188 errno = 0;
188 /*r =*/ full_write(STDOUT_FILENO, buffer, out - buffer); 189 err = full_write(STDOUT_FILENO, buffer, out - buffer) != out - buffer;
189 free(buffer); 190 if (err) {
190 if (/*WRONG:r < 0*/ errno) {
191 bb_simple_perror_msg(bb_msg_write_error); 191 bb_simple_perror_msg(bb_msg_write_error);
192 return 1;
193 } 192 }
194 return 0; 193 free(buffer);
194 return err;
195} 195}
196 196
197/* 197/*
diff --git a/editors/diff.c b/editors/diff.c
index a1c51ebb9..17d41af8d 100644
--- a/editors/diff.c
+++ b/editors/diff.c
@@ -1076,7 +1076,7 @@ int diff_main(int argc UNUSED_PARAM, char **argv)
1076 /* diffreg can get non-regular files here */ 1076 /* diffreg can get non-regular files here */
1077 print_status(gotstdin > 1 ? STATUS_SAME : diffreg(file), file); 1077 print_status(gotstdin > 1 ? STATUS_SAME : diffreg(file), file);
1078 1078
1079 if (dirfile) 1079 if (ENABLE_FEATURE_CLEAN_UP && dirfile)
1080 free(file[dir]); 1080 free(file[dir]);
1081 } 1081 }
1082 1082
diff --git a/include/libbb.h b/include/libbb.h
index 5e1d1fc5b..63e99cfe2 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1262,6 +1262,7 @@ void run_noexec_applet_and_exit(int a, const char *name, char **argv) NORETURN F
1262int find_applet_by_name(const char *name) FAST_FUNC; 1262int find_applet_by_name(const char *name) FAST_FUNC;
1263void run_applet_no_and_exit(int a, const char *name, char **argv) NORETURN FAST_FUNC; 1263void run_applet_no_and_exit(int a, const char *name, char **argv) NORETURN FAST_FUNC;
1264#endif 1264#endif
1265void show_usage_if_dash_dash_help(int applet_no, char **argv) FAST_FUNC;
1265#if defined(__linux__) 1266#if defined(__linux__)
1266void set_task_comm(const char *comm) FAST_FUNC; 1267void set_task_comm(const char *comm) FAST_FUNC;
1267#else 1268#else
diff --git a/include/platform.h b/include/platform.h
index 0fc270fab..dc4a63ed4 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -428,6 +428,7 @@ typedef unsigned smalluint;
428#define HAVE_SETBIT 1 428#define HAVE_SETBIT 1
429#define HAVE_SIGHANDLER_T 1 429#define HAVE_SIGHANDLER_T 1
430#define HAVE_STPCPY 1 430#define HAVE_STPCPY 1
431#define HAVE_STPNCPY 1
431#define HAVE_MEMPCPY 1 432#define HAVE_MEMPCPY 1
432#define HAVE_STRCASESTR 1 433#define HAVE_STRCASESTR 1
433#define HAVE_STRCHRNUL 1 434#define HAVE_STRCHRNUL 1
@@ -484,6 +485,7 @@ typedef unsigned smalluint;
484# undef HAVE_MKDTEMP 485# undef HAVE_MKDTEMP
485# undef HAVE_SETBIT 486# undef HAVE_SETBIT
486# undef HAVE_STPCPY 487# undef HAVE_STPCPY
488# undef HAVE_STPNCPY
487# undef HAVE_STRCASESTR 489# undef HAVE_STRCASESTR
488# undef HAVE_STRCHRNUL 490# undef HAVE_STRCHRNUL
489# undef HAVE_STRSEP 491# undef HAVE_STRSEP
@@ -556,6 +558,7 @@ typedef unsigned smalluint;
556 558
557#if defined(__digital__) && defined(__unix__) 559#if defined(__digital__) && defined(__unix__)
558# undef HAVE_STPCPY 560# undef HAVE_STPCPY
561# undef HAVE_STPNCPY
559#endif 562#endif
560 563
561#if defined(ANDROID) || defined(__ANDROID__) 564#if defined(ANDROID) || defined(__ANDROID__)
@@ -572,6 +575,7 @@ typedef unsigned smalluint;
572# undef HAVE_TTYNAME_R 575# undef HAVE_TTYNAME_R
573# undef HAVE_GETLINE 576# undef HAVE_GETLINE
574# undef HAVE_STPCPY 577# undef HAVE_STPCPY
578# undef HAVE_STPNCPY
575# endif 579# endif
576# undef HAVE_MEMPCPY 580# undef HAVE_MEMPCPY
577# undef HAVE_STRCHRNUL 581# undef HAVE_STRCHRNUL
@@ -617,6 +621,10 @@ typedef void (*sighandler_t)(int);
617extern char *stpcpy(char *p, const char *to_add) FAST_FUNC; 621extern char *stpcpy(char *p, const char *to_add) FAST_FUNC;
618#endif 622#endif
619 623
624#ifndef HAVE_STPNCPY
625extern char *stpncpy(char *p, const char *to_add, size_t n) FAST_FUNC;
626#endif
627
620#ifndef HAVE_MEMPCPY 628#ifndef HAVE_MEMPCPY
621#include <string.h> 629#include <string.h>
622/* In case we are wrong about !HAVE_MEMPCPY, and toolchain _does_ have 630/* In case we are wrong about !HAVE_MEMPCPY, and toolchain _does_ have
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 1587cf36f..846417d59 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -1034,6 +1034,34 @@ int busybox_main(int argc UNUSED_PARAM, char **argv)
1034# endif 1034# endif
1035 1035
1036# if NUM_APPLETS > 0 1036# if NUM_APPLETS > 0
1037void FAST_FUNC show_usage_if_dash_dash_help(int applet_no, char **argv)
1038{
1039 /* Special case. POSIX says "test --help"
1040 * should be no different from e.g. "test --foo".
1041 * Thus for "test", we skip --help check.
1042 * "true" and "false" are also special.
1043 */
1044 if (1
1045# if defined APPLET_NO_test
1046 && applet_no != APPLET_NO_test
1047# endif
1048# if defined APPLET_NO_true
1049 && applet_no != APPLET_NO_true
1050# endif
1051# if defined APPLET_NO_false
1052 && applet_no != APPLET_NO_false
1053# endif
1054# if defined APPLET_NO_busybox
1055 && applet_no != APPLET_NO_busybox
1056# endif
1057 ) {
1058 if (argv[1] && !argv[2] && strcmp(argv[1], "--help") == 0) {
1059 /* Make "foo --help" exit with 0: */
1060 xfunc_error_retval = 0;
1061 bb_show_usage();
1062 }
1063 }
1064}
1037 1065
1038# if ENABLE_PLATFORM_MINGW32 1066# if ENABLE_PLATFORM_MINGW32
1039static int interp = 0; 1067static int interp = 0;
@@ -1043,11 +1071,13 @@ char bb_command_line[128];
1043 1071
1044void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **argv) 1072void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **argv)
1045{ 1073{
1046 int argc = string_array_len(argv);
1047# if ENABLE_PLATFORM_MINGW32 1074# if ENABLE_PLATFORM_MINGW32
1075 int argc = string_array_len(argv);
1048 int i; 1076 int i;
1049 const char *vmask; 1077 const char *vmask;
1050 unsigned int mask; 1078 unsigned int mask;
1079# else
1080 int argc;
1051# endif 1081# endif
1052 1082
1053 /* 1083 /*
@@ -1055,6 +1085,12 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **ar
1055 * "-/sbin/halt" -> "halt", for example. 1085 * "-/sbin/halt" -> "halt", for example.
1056 */ 1086 */
1057 applet_name = name; 1087 applet_name = name;
1088
1089 show_usage_if_dash_dash_help(applet_no, argv);
1090
1091 if (ENABLE_FEATURE_SUID)
1092 check_suid(applet_no);
1093
1058# if ENABLE_PLATFORM_MINGW32 1094# if ENABLE_PLATFORM_MINGW32
1059 safe_strncpy(bb_comm, 1095 safe_strncpy(bb_comm,
1060 interp ? bb_basename(argv[interp]) : applet_name, 1096 interp ? bb_basename(argv[interp]) : applet_name,
@@ -1069,37 +1105,11 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **ar
1069 vmask = getenv("BB_UMASK"); 1105 vmask = getenv("BB_UMASK");
1070 if (vmask && sscanf(vmask, "%o", &mask) == 1) 1106 if (vmask && sscanf(vmask, "%o", &mask) == 1)
1071 umask((mode_t)(mask&0777)); 1107 umask((mode_t)(mask&0777));
1108# else
1109 argc = string_array_len(argv);
1072# endif 1110# endif
1073
1074 /* Special case. POSIX says "test --help"
1075 * should be no different from e.g. "test --foo".
1076 * Thus for "test", we skip --help check.
1077 * "true" and "false" are also special.
1078 */
1079 if (1
1080# if defined APPLET_NO_test
1081 && applet_no != APPLET_NO_test
1082# endif
1083# if defined APPLET_NO_true
1084 && applet_no != APPLET_NO_true
1085# endif
1086# if defined APPLET_NO_false
1087 && applet_no != APPLET_NO_false
1088# endif
1089# if defined APPLET_NO_busybox
1090 && applet_no != APPLET_NO_busybox
1091# endif
1092 ) {
1093 if (argc == 2 && strcmp(argv[1], "--help") == 0) {
1094 /* Make "foo --help" exit with 0: */
1095 xfunc_error_retval = 0;
1096 bb_show_usage();
1097 }
1098 }
1099 if (ENABLE_FEATURE_SUID)
1100 check_suid(applet_no);
1101
1102 xfunc_error_retval = applet_main[applet_no](argc, argv); 1111 xfunc_error_retval = applet_main[applet_no](argc, argv);
1112
1103 /* Note: applet_main() may also not return (die on a xfunc or such) */ 1113 /* Note: applet_main() may also not return (die on a xfunc or such) */
1104 xfunc_die(); 1114 xfunc_die();
1105} 1115}
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 55141e141..205044630 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -829,8 +829,6 @@ static unsigned path_parse(char ***p)
829 if (!tmp) 829 if (!tmp)
830 break; 830 break;
831 tmp++; 831 tmp++;
832 if (*tmp == '\0')
833 break; /* :<empty> */
834 npth++; 832 npth++;
835 } 833 }
836 834
@@ -842,8 +840,6 @@ static unsigned path_parse(char ***p)
842 if (!tmp) 840 if (!tmp)
843 break; 841 break;
844 *tmp++ = '\0'; /* ':' -> '\0' */ 842 *tmp++ = '\0'; /* ':' -> '\0' */
845 if (*tmp == '\0')
846 break; /* :<empty> */
847 res[npth++] = tmp; 843 res[npth++] = tmp;
848 } 844 }
849 /* special case: "match subdirectories of the current directory" */ 845 /* special case: "match subdirectories of the current directory" */
@@ -925,9 +921,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
925 struct dirent *next; 921 struct dirent *next;
926 struct stat st; 922 struct stat st;
927 char *found; 923 char *found;
928#if ENABLE_PLATFORM_MINGW32 924 const char *lpath;
929 char *lpath;
930#endif
931 925
932 if (paths[i] == NULL) { /* path_parse()'s last component? */ 926 if (paths[i] == NULL) { /* path_parse()'s last component? */
933 /* in PATH completion, current dir's subdir names 927 /* in PATH completion, current dir's subdir names
@@ -937,12 +931,11 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
937 paths[i] = (char *)"."; 931 paths[i] = (char *)".";
938 } 932 }
939 933
934 lpath = *paths[i] ? paths[i] : ".";
940#if ENABLE_PLATFORM_MINGW32 935#if ENABLE_PLATFORM_MINGW32
941 lpath = auto_string(alloc_system_drive(paths[i])); 936 lpath = auto_string(alloc_system_drive(lpath));
942 dir = opendir(lpath);
943#else
944 dir = opendir(paths[i]);
945#endif 937#endif
938 dir = opendir(lpath);
946 if (!dir) 939 if (!dir)
947 continue; /* don't print an error */ 940 continue; /* don't print an error */
948 941
@@ -957,11 +950,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
957 if (strncmp(basecmd, name_found, baselen) != 0) 950 if (strncmp(basecmd, name_found, baselen) != 0)
958 continue; /* no */ 951 continue; /* no */
959 952
960#if ENABLE_PLATFORM_MINGW32
961 found = concat_path_file(lpath, name_found); 953 found = concat_path_file(lpath, name_found);
962#else
963 found = concat_path_file(paths[i], name_found);
964#endif
965 /* NB: stat() first so that we see is it a directory; 954 /* NB: stat() first so that we see is it a directory;
966 * but if that fails, use lstat() so that 955 * but if that fails, use lstat() so that
967 * we still match dangling links */ 956 * 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)
166} 166}
167#endif 167#endif
168 168
169#ifndef HAVE_STPNCPY
170char* FAST_FUNC stpncpy(char *p, const char *to_add, size_t n)
171{
172 while (n != 0 && (*p = *to_add) != '\0') {
173 p++;
174 to_add++;
175 n--;
176 }
177 return p;
178}
179#endif
180
169#ifndef HAVE_GETLINE 181#ifndef HAVE_GETLINE
170ssize_t FAST_FUNC getline(char **lineptr, size_t *n, FILE *stream) 182ssize_t FAST_FUNC getline(char **lineptr, size_t *n, FILE *stream)
171{ 183{
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index 26e1776a4..885c19f1a 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)
109 char *tmp_argv[argc+1]; 109 char *tmp_argv[argc+1];
110 memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); 110 memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0]));
111 applet_name = tmp_argv[0]; 111 applet_name = tmp_argv[0];
112
113 /* longjmp's (instead of returning) if --help is seen */
114 show_usage_if_dash_dash_help(applet_no, argv);
115
112 /* Finally we can call NOFORK applet's main() */ 116 /* Finally we can call NOFORK applet's main() */
113 rc = applet_main[applet_no](argc, tmp_argv); 117 rc = applet_main[applet_no](argc, tmp_argv);
118
114 /* Important for shells: `which CMD` was failing */ 119 /* Important for shells: `which CMD` was failing */
115 fflush_all(); 120 fflush_all();
116 } else { 121 } else {
diff --git a/miscutils/bc.c b/miscutils/bc.c
index 38ae7f7d1..4eb0f2d30 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -138,11 +138,54 @@
138//usage: 138//usage:
139//usage:#define dc_full_usage "\n" 139//usage:#define dc_full_usage "\n"
140//usage: "\nTiny RPN calculator. Operations:" 140//usage: "\nTiny RPN calculator. Operations:"
141//usage: "\n+, -, *, /, %, ~, ^," IF_FEATURE_DC_BIG(" |,") 141//usage: "\nArithmetic: + - * / % ^"
142//usage: IF_FEATURE_DC_BIG(
143//usage: "\n~ - divide with remainder"
144//usage: "\n| - modular exponentiation"
145//usage: "\nv - square root"
146//////// "\nA-F - digits 10..15
147//////// "\n_NNN - push negative number -NNN
148//////// "\n[string] - push string (in FreeBSD, \[, \] and \\ are escapes, not implemented here and in GNU)
149//////// "\nR - DC_LEX_POP pop and discard
150//////// "\nc - DC_LEX_CLEAR_STACK clear stack
151//////// "\nd - DC_LEX_DUPLICATE duplicate top-of-stack
152//////// "\nr - DC_LEX_SWAP swap top-of-stack
153//////// "\n:r - DC_LEX_COLON pop index, pop value, store to array 'r'
154//////// "\n;r - DC_LEX_SCOLON pop index, fetch from array 'r', push
155//////// "\nLr - DC_LEX_LOAD_POP pop register 'r', push
156//////// "\nSr - DC_LEX_STORE_PUSH pop, push to register 'r'
157//////// "\nlr - DC_LEX_LOAD read register 'r', push
158//////// "\nsr - DC_LEX_OP_ASSIGN pop, assign to register 'r'
159//////// "\n? - DC_LEX_READ read line and execute
160//////// "\nx - DC_LEX_EXECUTE pop string and execute
161//////// "\n<r - XC_LEX_OP_REL_GT pop, pop, execute register 'r' if top-of-stack was less
162//////// "\n>r - XC_LEX_OP_REL_LT pop, pop, execute register 'r' if top-of-stack was greater
163//////// "\n=r - XC_LEX_OP_REL_EQ pop, pop, execute register 'r' if equal
164//////// "\n !<r !>r !=r - negated forms
165//////// "\n >tef - "if greater execute register 't' else execute 'f'"
166//////// "\nQ - DC_LEX_NQUIT pop, "break N" from macro invocations
167//////// "\nq - DC_LEX_QUIT "break 2" (if less than 2 levels of macros, exit dc)
168//////// "\nX - DC_LEX_SCALE_FACTOR pop, push number of fractional digits
169//////// "\nZ - DC_LEX_LENGTH pop, push number of digits it has (or number of characters in string)
170//////// "\na - DC_LEX_ASCIIFY pop, push low-order byte as char or 1st char of string
171//////// "\n( - DC_LEX_LPAREN (FreeBSD, not in GNU) pop, pop, if top-of-stack was less push 1 else push 0
172//////// "\n{ - DC_LEX_LBRACE (FreeBSD, not in GNU) pop, pop, if top-of-stack was less-or-equal push 1 else push 0
173//////// "\nG - DC_LEX_EQ_NO_REG (FreeBSD, not in GNU) pop, pop, if equal push 1 else push 0
174//////// "\nN - DC_LEX_OP_BOOL_NOT (FreeBSD, not in GNU) pop, if 0 push 1 else push 0
175//////// FreeBSD also has J and M commands, used internally by bc
176//////// "\nn - DC_LEX_PRINT_POP pop, print without newline
177//////// "\nP - DC_LEX_PRINT_STREAM pop, print string or hex bytes
178//usage: )
142//usage: "\np - print top of the stack without popping" 179//usage: "\np - print top of the stack without popping"
143//usage: "\nf - print entire stack" 180//usage: "\nf - print entire stack"
144//usage: "\nk - pop the value and set the precision" 181//////// "\nz - DC_LEX_STACK_LEVEL push stack depth
182//////// "\nK - DC_LEX_SCALE push precision
183//////// "\nI - DC_LEX_IBASE push input radix
184//////// "\nO - DC_LEX_OBASE push output radix
185//usage: IF_FEATURE_DC_BIG(
186//usage: "\nk - pop the value and set precision"
145//usage: "\ni - pop the value and set input radix" 187//usage: "\ni - pop the value and set input radix"
188//usage: )
146//usage: "\no - pop the value and set output radix" 189//usage: "\no - pop the value and set output radix"
147//usage: "\nExamples: dc -e'2 2 + p' -> 4, dc -e'8 8 * 2 2 + / p' -> 16" 190//usage: "\nExamples: dc -e'2 2 + p' -> 4, dc -e'8 8 * 2 2 + / p' -> 16"
148//usage: 191//usage:
@@ -6217,13 +6260,20 @@ static unsigned long xc_program_len(BcNum *n)
6217{ 6260{
6218 size_t len = n->len; 6261 size_t len = n->len;
6219 6262
6220 if (n->rdx != len) return len; 6263 if (n->rdx != len)
6264 // length(100): rdx 0 len 3, return 3
6265 // length(0.01-0.01): rdx 2 len 0, return 2
6266 // dc: 0.01 0.01 - Zp: rdx 2 len 0, return 1
6267 return len != 0 ? len : (IS_BC ? n->rdx : 1);
6268
6269 // length(0): return 1
6270 // length(0.000nnn): count nnn
6221 for (;;) { 6271 for (;;) {
6222 if (len == 0) break; 6272 if (len == 0) break;
6223 len--; 6273 len--;
6224 if (n->num[len] != 0) break; 6274 if (n->num[len] != 0) break;
6225 } 6275 }
6226 return len; 6276 return len + 1;
6227} 6277}
6228 6278
6229static BC_STATUS zxc_program_builtin(char inst) 6279static BC_STATUS zxc_program_builtin(char inst)
@@ -6251,12 +6301,12 @@ static BC_STATUS zxc_program_builtin(char inst)
6251 if (inst == XC_INST_SQRT) 6301 if (inst == XC_INST_SQRT)
6252 s = zbc_num_sqrt(num, &res.d.n, G.prog.scale); 6302 s = zbc_num_sqrt(num, &res.d.n, G.prog.scale);
6253#if ENABLE_BC 6303#if ENABLE_BC
6254 else if (len != 0 && opnd->t == XC_RESULT_ARRAY) { 6304 else if (len && opnd->t == XC_RESULT_ARRAY) {
6255 bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len); 6305 bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len);
6256 } 6306 }
6257#endif 6307#endif
6258#if ENABLE_DC 6308#if ENABLE_DC
6259 else if (len != 0 && !BC_PROG_NUM(opnd, num)) { 6309 else if (len && !BC_PROG_NUM(opnd, num)) {
6260 char **str; 6310 char **str;
6261 size_t idx = opnd->t == XC_RESULT_STR ? opnd->d.id.idx : num->rdx; 6311 size_t idx = opnd->t == XC_RESULT_STR ? opnd->d.id.idx : num->rdx;
6262 6312
@@ -6265,6 +6315,8 @@ static BC_STATUS zxc_program_builtin(char inst)
6265 } 6315 }
6266#endif 6316#endif
6267 else { 6317 else {
6318//TODO: length(.00) and scale(.00) should return 2, they return 1 and 0 now
6319//(don't forget to check that dc Z and X commands do not break)
6268 bc_num_ulong2num(&res.d.n, len ? xc_program_len(num) : xc_program_scale(num)); 6320 bc_num_ulong2num(&res.d.n, len ? xc_program_len(num) : xc_program_scale(num));
6269 } 6321 }
6270 6322
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:
379 */ 379 */
380static int process_packet(struct dns_entry *conf_data, 380static int process_packet(struct dns_entry *conf_data,
381 uint32_t conf_ttl, 381 uint32_t conf_ttl,
382 uint8_t *buf) 382 uint8_t *buf,
383 unsigned buflen)
383{ 384{
384 struct dns_head *head; 385 struct dns_head *head;
385 struct type_and_class *unaligned_type_class; 386 struct type_and_class *unaligned_type_class;
@@ -402,9 +403,6 @@ static int process_packet(struct dns_entry *conf_data,
402 bb_simple_error_msg("response packet, ignored"); 403 bb_simple_error_msg("response packet, ignored");
403 return 0; /* don't reply */ 404 return 0; /* don't reply */
404 } 405 }
405 /* QR = 1 "response", RCODE = 4 "Not Implemented" */
406 outr_flags = htons(0x8000 | 4);
407 err_msg = NULL;
408 406
409 /* start of query string */ 407 /* start of query string */
410 query_string = (void *)(head + 1); 408 query_string = (void *)(head + 1);
@@ -416,6 +414,15 @@ static int process_packet(struct dns_entry *conf_data,
416 /* where to append answer block */ 414 /* where to append answer block */
417 answb = (void *)(unaligned_type_class + 1); 415 answb = (void *)(unaligned_type_class + 1);
418 416
417 if (buflen < answb - buf) {
418 bb_simple_error_msg("packet too short");
419 return 0; /* don't reply */
420 }
421
422 /* QR = 1 "response", RCODE = 4 "Not Implemented" */
423 outr_flags = htons(0x8000 | 4);
424 err_msg = NULL;
425
419 /* OPCODE != 0 "standard query"? */ 426 /* OPCODE != 0 "standard query"? */
420 if ((head->flags & htons(0x7800)) != 0) { 427 if ((head->flags & htons(0x7800)) != 0) {
421 err_msg = "opcode != 0"; 428 err_msg = "opcode != 0";
@@ -559,7 +566,7 @@ int dnsd_main(int argc UNUSED_PARAM, char **argv)
559 if (OPT_verbose) 566 if (OPT_verbose)
560 bb_simple_info_msg("got UDP packet"); 567 bb_simple_info_msg("got UDP packet");
561 buf[r] = '\0'; /* paranoia */ 568 buf[r] = '\0'; /* paranoia */
562 r = process_packet(conf_data, conf_ttl, buf); 569 r = process_packet(conf_data, conf_ttl, buf, r);
563 if (r <= 0) 570 if (r <= 0)
564 continue; 571 continue;
565 send_to_from(udps, buf, r, 0, &from->u.sa, &to->u.sa, lsa->len); 572 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..9c15999f3 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -373,8 +373,7 @@ typedef struct {
373} peer_t; 373} peer_t;
374 374
375 375
376#define USING_KERNEL_PLL_LOOP 1 376#define USING_KERNEL_PLL_LOOP 1
377#define USING_INITIAL_FREQ_ESTIMATION 0
378 377
379enum { 378enum {
380 OPT_n = (1 << 0), 379 OPT_n = (1 << 0),
@@ -462,12 +461,7 @@ struct globals {
462#define G_precision_sec 0.002 461#define G_precision_sec 0.002
463 uint8_t stratum; 462 uint8_t stratum;
464 463
465#define STATE_NSET 0 /* initial state, "nothing is set" */ 464 //uint8_t discipline_state; // doc calls it c.state
466//#define STATE_FSET 1 /* frequency set from file */
467//#define STATE_SPIK 2 /* spike detected */
468//#define STATE_FREQ 3 /* initial frequency */
469#define STATE_SYNC 4 /* clock synchronized (normal operation) */
470 uint8_t discipline_state; // doc calls it c.state
471 uint8_t poll_exp; // s.poll 465 uint8_t poll_exp; // s.poll
472 int polladj_count; // c.count 466 int polladj_count; // c.count
473 int FREQHOLD_cnt; 467 int FREQHOLD_cnt;
@@ -657,104 +651,11 @@ filter_datapoints(peer_t *p)
657 double sum, wavg; 651 double sum, wavg;
658 datapoint_t *fdp; 652 datapoint_t *fdp;
659 653
660#if 0
661/* Simulations have shown that use of *averaged* offset for p->filter_offset 654/* Simulations have shown that use of *averaged* offset for p->filter_offset
662 * is in fact worse than simply using last received one: with large poll intervals 655 * is in fact worse than simply using last received one: with large poll intervals
663 * (>= 2048) averaging code uses offset values which are outdated by hours, 656 * (>= 2048) averaging code uses offset values which are outdated by hours,
664 * and time/frequency correction goes totally wrong when fed essentially bogus offsets. 657 * and time/frequency correction goes totally wrong when fed essentially bogus offsets.
665 */ 658 */
666 int got_newest;
667 double minoff, maxoff, w;
668 double x = x; /* for compiler */
669 double oldest_off = oldest_off;
670 double oldest_age = oldest_age;
671 double newest_off = newest_off;
672 double newest_age = newest_age;
673
674 fdp = p->filter_datapoint;
675
676 minoff = maxoff = fdp[0].d_offset;
677 for (i = 1; i < NUM_DATAPOINTS; i++) {
678 if (minoff > fdp[i].d_offset)
679 minoff = fdp[i].d_offset;
680 if (maxoff < fdp[i].d_offset)
681 maxoff = fdp[i].d_offset;
682 }
683
684 idx = p->datapoint_idx; /* most recent datapoint's index */
685 /* Average offset:
686 * Drop two outliers and take weighted average of the rest:
687 * most_recent/2 + older1/4 + older2/8 ... + older5/32 + older6/32
688 * we use older6/32, not older6/64 since sum of weights should be 1:
689 * 1/2 + 1/4 + 1/8 + 1/16 + 1/32 + 1/32 = 1
690 */
691 wavg = 0;
692 w = 0.5;
693 /* n-1
694 * --- dispersion(i)
695 * filter_dispersion = \ -------------
696 * / (i+1)
697 * --- 2
698 * i=0
699 */
700 got_newest = 0;
701 sum = 0;
702 for (i = 0; i < NUM_DATAPOINTS; i++) {
703 VERB5 {
704 bb_error_msg("datapoint[%d]: off:%f disp:%f(%f) age:%f%s",
705 i,
706 fdp[idx].d_offset,
707 fdp[idx].d_dispersion, dispersion(&fdp[idx]),
708 G.cur_time - fdp[idx].d_recv_time,
709 (minoff == fdp[idx].d_offset || maxoff == fdp[idx].d_offset)
710 ? " (outlier by offset)" : ""
711 );
712 }
713
714 sum += dispersion(&fdp[idx]) / (2 << i);
715
716 if (minoff == fdp[idx].d_offset) {
717 minoff -= 1; /* so that we don't match it ever again */
718 } else
719 if (maxoff == fdp[idx].d_offset) {
720 maxoff += 1;
721 } else {
722 oldest_off = fdp[idx].d_offset;
723 oldest_age = G.cur_time - fdp[idx].d_recv_time;
724 if (!got_newest) {
725 got_newest = 1;
726 newest_off = oldest_off;
727 newest_age = oldest_age;
728 }
729 x = oldest_off * w;
730 wavg += x;
731 w /= 2;
732 }
733
734 idx = (idx - 1) & (NUM_DATAPOINTS - 1);
735 }
736 p->filter_dispersion = sum;
737 wavg += x; /* add another older6/64 to form older6/32 */
738 /* Fix systematic underestimation with large poll intervals.
739 * Imagine that we still have a bit of uncorrected drift,
740 * and poll interval is big (say, 100 sec). Offsets form a progression:
741 * 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 - 0.7 is most recent.
742 * The algorithm above drops 0.0 and 0.7 as outliers,
743 * and then we have this estimation, ~25% off from 0.7:
744 * 0.1/32 + 0.2/32 + 0.3/16 + 0.4/8 + 0.5/4 + 0.6/2 = 0.503125
745 */
746 x = oldest_age - newest_age;
747 if (x != 0) {
748 x = newest_age / x; /* in above example, 100 / (600 - 100) */
749 if (x < 1) { /* paranoia check */
750 x = (newest_off - oldest_off) * x; /* 0.5 * 100/500 = 0.1 */
751 wavg += x;
752 }
753 }
754 p->filter_offset = wavg;
755
756#else
757
758 fdp = p->filter_datapoint; 659 fdp = p->filter_datapoint;
759 idx = p->datapoint_idx; /* most recent datapoint's index */ 660 idx = p->datapoint_idx; /* most recent datapoint's index */
760 661
@@ -777,7 +678,6 @@ filter_datapoints(peer_t *p)
777 } 678 }
778 wavg /= NUM_DATAPOINTS; 679 wavg /= NUM_DATAPOINTS;
779 p->filter_dispersion = sum; 680 p->filter_dispersion = sum;
780#endif
781 681
782 /* +----- -----+ ^ 1/2 682 /* +----- -----+ ^ 1/2
783 * | n-1 | 683 * | n-1 |
@@ -1548,15 +1448,14 @@ select_and_cluster(void)
1548 * Local clock discipline and its helpers 1448 * Local clock discipline and its helpers
1549 */ 1449 */
1550static void 1450static void
1551set_new_values(int disc_state, double offset, double recv_time) 1451set_new_values(double offset, double recv_time)
1552{ 1452{
1553 /* Enter new state and set state variables. Note we use the time 1453 /* Enter new state and set state variables. Note we use the time
1554 * of the last clock filter sample, which must be earlier than 1454 * of the last clock filter sample, which must be earlier than
1555 * the current time. 1455 * the current time.
1556 */ 1456 */
1557 VERB4 bb_error_msg("disc_state=%d last update offset=%f recv_time=%f", 1457 VERB4 bb_error_msg("last update offset=%f recv_time=%f",
1558 disc_state, offset, recv_time); 1458 offset, recv_time);
1559 G.discipline_state = disc_state;
1560 G.last_update_offset = offset; 1459 G.last_update_offset = offset;
1561 G.last_update_recv_time = recv_time; 1460 G.last_update_recv_time = recv_time;
1562} 1461}
@@ -1572,8 +1471,6 @@ update_local_clock(peer_t *p)
1572 double abs_offset; 1471 double abs_offset;
1573#if !USING_KERNEL_PLL_LOOP 1472#if !USING_KERNEL_PLL_LOOP
1574 double freq_drift; 1473 double freq_drift;
1575#endif
1576#if !USING_KERNEL_PLL_LOOP || USING_INITIAL_FREQ_ESTIMATION
1577 double since_last_update; 1474 double since_last_update;
1578#endif 1475#endif
1579 double etemp, dtemp; 1476 double etemp, dtemp;
@@ -1603,63 +1500,15 @@ update_local_clock(peer_t *p)
1603 * action is and defines how the system reacts to large time 1500 * action is and defines how the system reacts to large time
1604 * and frequency errors. 1501 * and frequency errors.
1605 */ 1502 */
1606#if !USING_KERNEL_PLL_LOOP || USING_INITIAL_FREQ_ESTIMATION
1607 since_last_update = recv_time - G.reftime;
1608#endif
1609#if !USING_KERNEL_PLL_LOOP 1503#if !USING_KERNEL_PLL_LOOP
1504 since_last_update = recv_time - G.reftime;
1610 freq_drift = 0; 1505 freq_drift = 0;
1611#endif 1506#endif
1612#if USING_INITIAL_FREQ_ESTIMATION
1613 if (G.discipline_state == STATE_FREQ) {
1614 /* Ignore updates until the stepout threshold */
1615 if (since_last_update < WATCH_THRESHOLD) {
1616 VERB4 bb_error_msg("measuring drift, datapoint ignored, %f sec remains",
1617 WATCH_THRESHOLD - since_last_update);
1618 return 0; /* "leave poll interval as is" */
1619 }
1620# if !USING_KERNEL_PLL_LOOP
1621 freq_drift = (offset - G.last_update_offset) / since_last_update;
1622# endif
1623 }
1624#endif
1625 1507
1626 /* There are two main regimes: when the 1508 /* There are two main regimes: when the
1627 * offset exceeds the step threshold and when it does not. 1509 * offset exceeds the step threshold and when it does not.
1628 */ 1510 */
1629 if (abs_offset > STEP_THRESHOLD) { 1511 if (abs_offset > STEP_THRESHOLD) {
1630#if 0
1631 double remains;
1632
1633// This "spike state" seems to be useless, peer selection already drops
1634// occassional "bad" datapoints. If we are here, there were _many_
1635// large offsets. When a few first large offsets are seen,
1636// we end up in "no valid datapoints, no peer selected" state.
1637// Only when enough of them are seen (which means it's not a fluke),
1638// we end up here. Looks like _our_ clock is off.
1639 switch (G.discipline_state) {
1640 case STATE_SYNC:
1641 /* The first outlyer: ignore it, switch to SPIK state */
1642 VERB3 bb_error_msg("update from %s: offset:%+f, spike%s",
1643 p->p_dotted, offset,
1644 "");
1645 G.discipline_state = STATE_SPIK;
1646 return -1; /* "decrease poll interval" */
1647
1648 case STATE_SPIK:
1649 /* Ignore succeeding outlyers until either an inlyer
1650 * is found or the stepout threshold is exceeded.
1651 */
1652 remains = WATCH_THRESHOLD - since_last_update;
1653 if (remains > 0) {
1654 VERB3 bb_error_msg("update from %s: offset:%+f, spike%s",
1655 p->p_dotted, offset,
1656 ", datapoint ignored");
1657 return -1; /* "decrease poll interval" */
1658 }
1659 /* fall through: we need to step */
1660 } /* switch */
1661#endif
1662
1663 /* Step the time and clamp down the poll interval. 1512 /* Step the time and clamp down the poll interval.
1664 * 1513 *
1665 * In NSET state an initial frequency correction is 1514 * In NSET state an initial frequency correction is
@@ -1694,16 +1543,17 @@ update_local_clock(peer_t *p)
1694 1543
1695 recv_time += offset; 1544 recv_time += offset;
1696 1545
1697#if USING_INITIAL_FREQ_ESTIMATION
1698 if (G.discipline_state == STATE_NSET) {
1699 set_new_values(STATE_FREQ, /*offset:*/ 0, recv_time);
1700 return 1; /* "ok to increase poll interval" */
1701 }
1702#endif
1703 abs_offset = offset = 0; 1546 abs_offset = offset = 0;
1704 set_new_values(STATE_SYNC, offset, recv_time); 1547 set_new_values(offset, recv_time);
1705 } else { /* abs_offset <= STEP_THRESHOLD */ 1548 } else { /* abs_offset <= STEP_THRESHOLD */
1706 1549
1550 if (option_mask32 & OPT_q) {
1551 /* We were only asked to set time once.
1552 * The clock is precise enough, no need to step.
1553 */
1554 exit(0);
1555 }
1556
1707 /* The ratio is calculated before jitter is updated to make 1557 /* The ratio is calculated before jitter is updated to make
1708 * poll adjust code more sensitive to large offsets. 1558 * poll adjust code more sensitive to large offsets.
1709 */ 1559 */
@@ -1718,75 +1568,31 @@ update_local_clock(peer_t *p)
1718 if (G.discipline_jitter < G_precision_sec) 1568 if (G.discipline_jitter < G_precision_sec)
1719 G.discipline_jitter = G_precision_sec; 1569 G.discipline_jitter = G_precision_sec;
1720 1570
1721 switch (G.discipline_state) {
1722 case STATE_NSET:
1723 if (option_mask32 & OPT_q) {
1724 /* We were only asked to set time once.
1725 * The clock is precise enough, no need to step.
1726 */
1727 exit(0);
1728 }
1729#if USING_INITIAL_FREQ_ESTIMATION
1730 /* This is the first update received and the frequency
1731 * has not been initialized. The first thing to do
1732 * is directly measure the oscillator frequency.
1733 */
1734 set_new_values(STATE_FREQ, offset, recv_time);
1735#else
1736 set_new_values(STATE_SYNC, offset, recv_time);
1737#endif
1738 VERB4 bb_simple_error_msg("transitioning to FREQ, datapoint ignored");
1739 return 0; /* "leave poll interval as is" */
1740
1741#if 0 /* this is dead code for now */
1742 case STATE_FSET:
1743 /* This is the first update and the frequency
1744 * has been initialized. Adjust the phase, but
1745 * don't adjust the frequency until the next update.
1746 */
1747 set_new_values(STATE_SYNC, offset, recv_time);
1748 /* freq_drift remains 0 */
1749 break;
1750#endif
1751
1752#if USING_INITIAL_FREQ_ESTIMATION
1753 case STATE_FREQ:
1754 /* since_last_update >= WATCH_THRESHOLD, we waited enough.
1755 * Correct the phase and frequency and switch to SYNC state.
1756 * freq_drift was already estimated (see code above)
1757 */
1758 set_new_values(STATE_SYNC, offset, recv_time);
1759 break;
1760#endif
1761
1762 default:
1763#if !USING_KERNEL_PLL_LOOP 1571#if !USING_KERNEL_PLL_LOOP
1764 /* Compute freq_drift due to PLL and FLL contributions. 1572 /* Compute freq_drift due to PLL and FLL contributions.
1765 * 1573 *
1766 * The FLL and PLL frequency gain constants 1574 * The FLL and PLL frequency gain constants
1767 * depend on the poll interval and Allan 1575 * depend on the poll interval and Allan
1768 * intercept. The FLL is not used below one-half 1576 * intercept. The FLL is not used below one-half
1769 * the Allan intercept. Above that the loop gain 1577 * the Allan intercept. Above that the loop gain
1770 * increases in steps to 1 / AVG. 1578 * increases in steps to 1 / AVG.
1771 */ 1579 */
1772 if ((1 << G.poll_exp) > ALLAN / 2) { 1580 if ((1 << G.poll_exp) > ALLAN / 2) {
1773 etemp = FLL - G.poll_exp; 1581 etemp = FLL - G.poll_exp;
1774 if (etemp < AVG) 1582 if (etemp < AVG)
1775 etemp = AVG; 1583 etemp = AVG;
1776 freq_drift += (offset - G.last_update_offset) / (MAXD(since_last_update, ALLAN) * etemp); 1584 freq_drift += (offset - G.last_update_offset) / (MAXD(since_last_update, ALLAN) * etemp);
1777 }
1778 /* For the PLL the integration interval
1779 * (numerator) is the minimum of the update
1780 * interval and poll interval. This allows
1781 * oversampling, but not undersampling.
1782 */
1783 etemp = MIND(since_last_update, (1 << G.poll_exp));
1784 dtemp = (4 * PLL) << G.poll_exp;
1785 freq_drift += offset * etemp / SQUARE(dtemp);
1786#endif
1787 set_new_values(STATE_SYNC, offset, recv_time);
1788 break;
1789 } 1585 }
1586 /* For the PLL the integration interval
1587 * (numerator) is the minimum of the update
1588 * interval and poll interval. This allows
1589 * oversampling, but not undersampling.
1590 */
1591 etemp = MIND(since_last_update, (1 << G.poll_exp));
1592 dtemp = (4 * PLL) << G.poll_exp;
1593 freq_drift += offset * etemp / SQUARE(dtemp);
1594#endif
1595 set_new_values(offset, recv_time);
1790 if (G.stratum != p->lastpkt_stratum + 1) { 1596 if (G.stratum != p->lastpkt_stratum + 1) {
1791 G.stratum = p->lastpkt_stratum + 1; 1597 G.stratum = p->lastpkt_stratum + 1;
1792 run_script("stratum", offset); 1598 run_script("stratum", offset);
@@ -1805,9 +1611,7 @@ update_local_clock(peer_t *p)
1805 G.rootdisp = p->lastpkt_rootdisp + dtemp; 1611 G.rootdisp = p->lastpkt_rootdisp + dtemp;
1806 VERB4 bb_error_msg("updating leap/refid/reftime/rootdisp from peer %s", p->p_dotted); 1612 VERB4 bb_error_msg("updating leap/refid/reftime/rootdisp from peer %s", p->p_dotted);
1807 1613
1808 /* We are in STATE_SYNC now, but did not do adjtimex yet. 1614 /* By this time, freq_drift and offset are set
1809 * (Any other state does not reach this, they all return earlier)
1810 * By this time, freq_drift and offset are set
1811 * to values suitable for adjtimex. 1615 * to values suitable for adjtimex.
1812 */ 1616 */
1813#if !USING_KERNEL_PLL_LOOP 1617#if !USING_KERNEL_PLL_LOOP
@@ -2349,6 +2153,12 @@ recv_and_process_client_pkt(void /*int fd*/)
2349 do_sendto(G_listen_fd, 2153 do_sendto(G_listen_fd,
2350 /*from:*/ &to->u.sa, /*to:*/ from, /*addrlen:*/ to->len, 2154 /*from:*/ &to->u.sa, /*to:*/ from, /*addrlen:*/ to->len,
2351 &msg, size); 2155 &msg, size);
2156 VERB3 {
2157 char *addr;
2158 addr = xmalloc_sockaddr2dotted_noport(from);
2159 bb_error_msg("responded to query from %s", addr);
2160 free(addr);
2161 }
2352 2162
2353 bail: 2163 bail:
2354 free(to); 2164 free(to);
@@ -2767,7 +2577,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
2767 timeout++; /* (nextaction - G.cur_time) rounds down, compensating */ 2577 timeout++; /* (nextaction - G.cur_time) rounds down, compensating */
2768 2578
2769 /* Here we may block */ 2579 /* Here we may block */
2770 VERB2 { 2580 VERB3 {
2771 if (i > (ENABLE_FEATURE_NTPD_SERVER && G_listen_fd != -1)) { 2581 if (i > (ENABLE_FEATURE_NTPD_SERVER && G_listen_fd != -1)) {
2772 /* We wait for at least one reply. 2582 /* We wait for at least one reply.
2773 * Poll for it, without wasting time for message. 2583 * 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)
1589 } 1589 }
1590 1590
1591 if ((packet.d6_xid32 & htonl(0x00ffffff)) != xid) { 1591 if ((packet.d6_xid32 & htonl(0x00ffffff)) != xid) {
1592 log1("xid %x (our is %x), ignoring packet", 1592 log1("xid %x (our is %x)%s",
1593 (unsigned)(packet.d6_xid32 & htonl(0x00ffffff)), (unsigned)xid); 1593 (unsigned)(packet.d6_xid32 & htonl(0x00ffffff)), (unsigned)xid,
1594 ", ignoring packet"
1595 );
1594 continue; 1596 continue;
1595 } 1597 }
1596 1598
@@ -1743,7 +1745,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1743 free(client6_data.ia_na); 1745 free(client6_data.ia_na);
1744 client6_data.ia_na = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_NA); 1746 client6_data.ia_na = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_NA);
1745 if (!client6_data.ia_na) { 1747 if (!client6_data.ia_na) {
1746 bb_info_msg("no %s option, ignoring packet", "IA_NA"); 1748 bb_info_msg("no %s option%s", "IA_NA", ", ignoring packet");
1747 continue; 1749 continue;
1748 } 1750 }
1749 if (client6_data.ia_na->len < (4 + 4 + 4) + (2 + 2 + 16 + 4 + 4)) { 1751 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)
1756 D6_OPT_IAADDR 1758 D6_OPT_IAADDR
1757 ); 1759 );
1758 if (!iaaddr) { 1760 if (!iaaddr) {
1759 bb_info_msg("no %s option, ignoring packet", "IAADDR"); 1761 bb_info_msg("no %s option%s", "IAADDR", ", ignoring packet");
1760 continue; 1762 continue;
1761 } 1763 }
1762 if (iaaddr->len < (16 + 4 + 4)) { 1764 if (iaaddr->len < (16 + 4 + 4)) {
@@ -1781,7 +1783,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1781 free(client6_data.ia_pd); 1783 free(client6_data.ia_pd);
1782 client6_data.ia_pd = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_PD); 1784 client6_data.ia_pd = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_PD);
1783 if (!client6_data.ia_pd) { 1785 if (!client6_data.ia_pd) {
1784 bb_info_msg("no %s option, ignoring packet", "IA_PD"); 1786 bb_info_msg("no %s option%s", "IA_PD", ", ignoring packet");
1785 continue; 1787 continue;
1786 } 1788 }
1787 if (client6_data.ia_pd->len < (4 + 4 + 4) + (2 + 2 + 4 + 4 + 1 + 16)) { 1789 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)
1794 D6_OPT_IAPREFIX 1796 D6_OPT_IAPREFIX
1795 ); 1797 );
1796 if (!iaprefix) { 1798 if (!iaprefix) {
1797 bb_info_msg("no %s option, ignoring packet", "IAPREFIX"); 1799 bb_info_msg("no %s option%s", "IAPREFIX", ", ignoring packet");
1798 continue; 1800 continue;
1799 } 1801 }
1800 if (iaprefix->len < (4 + 4 + 1 + 16)) { 1802 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)
729 */ 729 */
730 add_client_options(&packet); 730 add_client_options(&packet);
731 731
732 bb_info_msg("sending %s", "discover"); 732 bb_simple_info_msg("broadcasting discover");
733 return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY); 733 return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY);
734} 734}
735 735
@@ -742,6 +742,7 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste
742{ 742{
743 struct dhcp_packet packet; 743 struct dhcp_packet packet;
744 struct in_addr temp_addr; 744 struct in_addr temp_addr;
745 char server_str[sizeof("255.255.255.255")];
745 746
746/* 747/*
747 * RFC 2131 4.3.2 DHCPREQUEST message 748 * 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
772 */ 773 */
773 add_client_options(&packet); 774 add_client_options(&packet);
774 775
776 temp_addr.s_addr = server;
777 strcpy(server_str, inet_ntoa(temp_addr));
775 temp_addr.s_addr = requested; 778 temp_addr.s_addr = requested;
776 bb_info_msg("sending select for %s", inet_ntoa(temp_addr)); 779 bb_info_msg("broadcasting select for %s, server %s",
780 inet_ntoa(temp_addr),
781 server_str
782 );
777 return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY); 783 return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY);
778} 784}
779 785
@@ -782,7 +788,6 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste
782static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) 788static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr)
783{ 789{
784 struct dhcp_packet packet; 790 struct dhcp_packet packet;
785 struct in_addr temp_addr;
786 791
787/* 792/*
788 * RFC 2131 4.3.2 DHCPREQUEST message 793 * 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)
813 */ 818 */
814 add_client_options(&packet); 819 add_client_options(&packet);
815 820
816 temp_addr.s_addr = server; 821 if (server) {
817 bb_info_msg("sending renew to %s", inet_ntoa(temp_addr)); 822 struct in_addr temp_addr;
823 temp_addr.s_addr = server;
824 bb_info_msg("sending renew to server %s", inet_ntoa(temp_addr));
825 } else {
826 bb_simple_info_msg("broadcasting renew");
827 }
828
818 return bcast_or_ucast(&packet, ciaddr, server); 829 return bcast_or_ucast(&packet, ciaddr, server);
819} 830}
820 831
@@ -843,7 +854,7 @@ static NOINLINE int send_decline(/*uint32_t xid,*/ uint32_t server, uint32_t req
843 854
844 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); 855 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
845 856
846 bb_info_msg("sending %s", "decline"); 857 bb_simple_info_msg("broadcasting decline");
847 return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY); 858 return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY);
848} 859}
849#endif 860#endif
@@ -1644,8 +1655,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1644 } 1655 }
1645 1656
1646 if (packet.xid != xid) { 1657 if (packet.xid != xid) {
1647 log1("xid %x (our is %x), ignoring packet", 1658 log1("xid %x (our is %x)%s",
1648 (unsigned)packet.xid, (unsigned)xid); 1659 (unsigned)packet.xid, (unsigned)xid,
1660 ", ignoring packet"
1661 );
1649 continue; 1662 continue;
1650 } 1663 }
1651 1664
@@ -1720,6 +1733,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1720 unsigned start; 1733 unsigned start;
1721 uint32_t lease_seconds; 1734 uint32_t lease_seconds;
1722 struct in_addr temp_addr; 1735 struct in_addr temp_addr;
1736 char server_str[sizeof("255.255.255.255")];
1723 uint8_t *temp; 1737 uint8_t *temp;
1724 1738
1725 temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME); 1739 temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME);
@@ -1775,9 +1789,11 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1775 } 1789 }
1776#endif 1790#endif
1777 /* enter bound state */ 1791 /* enter bound state */
1792 temp_addr.s_addr = server_addr;
1793 strcpy(server_str, inet_ntoa(temp_addr));
1778 temp_addr.s_addr = packet.yiaddr; 1794 temp_addr.s_addr = packet.yiaddr;
1779 bb_info_msg("lease of %s obtained, lease time %u", 1795 bb_info_msg("lease of %s obtained from %s, lease time %u",
1780 inet_ntoa(temp_addr), (unsigned)lease_seconds); 1796 inet_ntoa(temp_addr), server_str, (unsigned)lease_seconds);
1781 requested_ip = packet.yiaddr; 1797 requested_ip = packet.yiaddr;
1782 1798
1783 start = monotonic_sec(); 1799 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)
1048 move_from_unaligned32(server_id_network_order, server_id_opt); 1048 move_from_unaligned32(server_id_network_order, server_id_opt);
1049 if (server_id_network_order != server_data.server_nip) { 1049 if (server_id_network_order != server_data.server_nip) {
1050 /* client talks to somebody else */ 1050 /* client talks to somebody else */
1051 log1("server ID doesn't match%s", ", ignoring"); 1051 log1("server ID doesn't match%s", ", ignoring packet");
1052 continue; 1052 continue;
1053 } 1053 }
1054 } 1054 }
@@ -1171,7 +1171,7 @@ o DHCPREQUEST generated during REBINDING state:
1171 if (!requested_ip_opt) { 1171 if (!requested_ip_opt) {
1172 requested_nip = packet.ciaddr; 1172 requested_nip = packet.ciaddr;
1173 if (requested_nip == 0) { 1173 if (requested_nip == 0) {
1174 log1("no requested IP and no ciaddr%s", ", ignoring"); 1174 log1("no requested IP and no ciaddr%s", ", ignoring packet");
1175 break; 1175 break;
1176 } 1176 }
1177 } 1177 }
diff --git a/scripts/trylink b/scripts/trylink
index 6b74f092d..2255deee7 100755
--- a/scripts/trylink
+++ b/scripts/trylink
@@ -1,5 +1,6 @@
1#!/bin/sh 1#!/bin/sh
2 2
3#debug=true
3debug=false 4debug=false
4 5
5# Linker flags used: 6# Linker flags used:
@@ -77,7 +78,13 @@ CFLAGS="$3"
77LDFLAGS="$4" 78LDFLAGS="$4"
78O_FILES="$5" 79O_FILES="$5"
79A_FILES="$6" 80A_FILES="$6"
81# We try to drop libraries from LDLIBS if build works without them,
82# but ones from CONFIG_EXTRA_LDLIBS are always linked in.
83# (For example, musl has stub utmp implementation, and if you link with
84# a real utmp library in LDLIBS, dropping it "works" but resulting binary
85# does not work properly).
80LDLIBS="$7" 86LDLIBS="$7"
87CONFIG_EXTRA_LDLIBS="$8"
81 88
82# The --sort-section option is not supported by older versions of ld 89# The --sort-section option is not supported by older versions of ld
83SORT_SECTION="-Wl,--sort-section,alignment" 90SORT_SECTION="-Wl,--sort-section,alignment"
@@ -125,8 +132,8 @@ LDLIBS=`echo "$LDLIBS" | xargs -n1 | sort | uniq | xargs`
125# First link with all libs. If it fails, bail out 132# First link with all libs. If it fails, bail out
126echo "Trying libraries: $LDLIBS" 133echo "Trying libraries: $LDLIBS"
127# "lib1 lib2 lib3" -> "-llib1 -llib2 -llib3" 134# "lib1 lib2 lib3" -> "-llib1 -llib2 -llib3"
128l_list=`echo " $LDLIBS " | sed -e 's: \([^- ][^ ]*\): -l\1:g'` 135l_list=`echo " $LDLIBS $CONFIG_EXTRA_LDLIBS " | sed -e 's: \([^- ][^ ]*\): -l\1:g' -e 's/^ *//'`
129test "x$l_list" != "x" && l_list="$START_GROUP $l_list $END_GROUP" 136test x"$l_list" != x"" && l_list="$START_GROUP $l_list $END_GROUP"
130try $CC $CFLAGS $LDFLAGS \ 137try $CC $CFLAGS $LDFLAGS \
131 -o $EXE \ 138 -o $EXE \
132 $SORT_COMMON \ 139 $SORT_COMMON \
@@ -151,7 +158,7 @@ while test "$LDLIBS"; do
151 for one in $LDLIBS; do 158 for one in $LDLIBS; do
152 without_one=`echo " $LDLIBS " | sed "s/ $one / /g" | xargs` 159 without_one=`echo " $LDLIBS " | sed "s/ $one / /g" | xargs`
153 # "lib1 lib2 lib3" -> "-llib1 -llib2 -llib3" 160 # "lib1 lib2 lib3" -> "-llib1 -llib2 -llib3"
154 l_list=`echo " $without_one " | sed -e 's: \([^- ][^ ]*\): -l\1:g'` 161 l_list=`echo " $without_one $CONFIG_EXTRA_LDLIBS " | sed -e 's: \([^- ][^ ]*\): -l\1:g' -e 's/^ *//'`
155 test x"$l_list" != x"" && l_list="$START_GROUP $l_list $END_GROUP" 162 test x"$l_list" != x"" && l_list="$START_GROUP $l_list $END_GROUP"
156 $debug && echo "Trying -l options: '$l_list'" 163 $debug && echo "Trying -l options: '$l_list'"
157 try $CC $CFLAGS $LDFLAGS \ 164 try $CC $CFLAGS $LDFLAGS \
@@ -179,8 +186,8 @@ done
179 186
180# Make the binary with final, minimal list of libs 187# Make the binary with final, minimal list of libs
181echo "Final link with: ${LDLIBS:-<none>}" 188echo "Final link with: ${LDLIBS:-<none>}"
182l_list=`echo " $LDLIBS " | sed -e 's: \([^- ][^ ]*\): -l\1:g'` 189l_list=`echo " $LDLIBS $CONFIG_EXTRA_LDLIBS " | sed -e 's: \([^- ][^ ]*\): -l\1:g' -e 's/^ *//'`
183test "x$l_list" != "x" && l_list="$START_GROUP $l_list $END_GROUP" 190test x"$l_list" != x"" && l_list="$START_GROUP $l_list $END_GROUP"
184# --verbose gives us gobs of info to stdout (e.g. linker script used) 191# --verbose gives us gobs of info to stdout (e.g. linker script used)
185if ! test -f busybox_ldscript; then 192if ! test -f busybox_ldscript; then
186 try $CC $CFLAGS $LDFLAGS \ 193 try $CC $CFLAGS $LDFLAGS \
diff --git a/shell/ash.c b/shell/ash.c
index 2c99c3ead..8cc7a5c75 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -4702,9 +4702,7 @@ sprint_status48(char *os, int status, int sigonly)
4702#endif 4702#endif
4703 } 4703 }
4704 st &= 0x7f; 4704 st &= 0x7f;
4705//TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata 4705 s = stpncpy(s, strsignal(st), 32);
4706 //s = stpncpy(s, strsignal(st), 32); //not all libc have stpncpy()
4707 s += fmtstr(s, 32, strsignal(st));
4708 if (WCOREDUMP(status)) { 4706 if (WCOREDUMP(status)) {
4709 s = stpcpy(s, " (core dumped)"); 4707 s = stpcpy(s, " (core dumped)");
4710 } 4708 }
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" \
182 "123" \ 182 "123" \
183 "" "print 1,2,3" 183 "" "print 1,2,3"
184 184
185testing "bc length" \
186 "bc" \
187 "1\n3\n1\n3\n3\n" \
188 "" "length(0); length(100); length(0.01); length(0.00120); length(0.012-0.012);"
189
185testing "bc { print 1 }" \ 190testing "bc { print 1 }" \
186 "bc" \ 191 "bc" \
187 "1" \ 192 "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" \
114 "2\n9\n" \ 114 "2\n9\n" \
115 "" "[2p]s\n[3p]l\nx\n9p" 115 "" "[2p]s\n[3p]l\nx\n9p"
116 116
117testing "dc Z (length) for numbers" \
118 "dc" \
119 "1\n1\n3\n1\n3\n1\n" \
120 "" "0Zp\n0.000Zp\n100Zp\n0.01Zp\n0.00120Zp\n0.0012 0.0012 - Zp\n"
121
117for f in dc_*.dc; do 122for f in dc_*.dc; do
118 r="`basename "$f" .dc`_results.txt" 123 r="`basename "$f" .dc`_results.txt"
119 test -f "$r" || continue 124 test -f "$r" || continue