diff options
author | Ron Yorston <rmy@pobox.com> | 2020-07-09 13:10:58 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2020-07-09 13:10:58 +0100 |
commit | 9c0b2f7020d7c30b21a930ef54be632e092e533b (patch) | |
tree | b2187c40bd2fd9f49f73599fb08e52cb7a596de0 | |
parent | a8c6e20e332a9e11a9d28cd6770eadb9c9d73cb7 (diff) | |
parent | d21a63f9fca8eb16f79de9b72d4a3484dfaec1fc (diff) | |
download | busybox-w32-9c0b2f7020d7c30b21a930ef54be632e092e533b.tar.gz busybox-w32-9c0b2f7020d7c30b21a930ef54be632e092e533b.tar.bz2 busybox-w32-9c0b2f7020d7c30b21a930ef54be632e092e533b.zip |
Merge branch 'busybox' into merge
46 files changed, 584 insertions, 390 deletions
@@ -1,5 +1,5 @@ | |||
1 | VERSION = 1 | 1 | VERSION = 1 |
2 | PATCHLEVEL = 32 | 2 | PATCHLEVEL = 33 |
3 | SUBLEVEL = 0 | 3 | SUBLEVEL = 0 |
4 | EXTRAVERSION = .git | 4 | EXTRAVERSION = .git |
5 | NAME = Unnamed | 5 | NAME = Unnamed |
diff --git a/Makefile.flags b/Makefile.flags index 26031f561..2c3fd0d25 100644 --- a/Makefile.flags +++ b/Makefile.flags | |||
@@ -78,7 +78,9 @@ CFLAGS += $(call cc-option,-fno-asynchronous-unwind-tables,) | |||
78 | CFLAGS += $(call cc-option,-fno-builtin-printf,) | 78 | CFLAGS += $(call cc-option,-fno-builtin-printf,) |
79 | 79 | ||
80 | # clang-9 does not like "str" + N and "if (CONFIG_ITEM && cond)" constructs | 80 | # clang-9 does not like "str" + N and "if (CONFIG_ITEM && cond)" constructs |
81 | ifeq ($(CC),clang) | ||
81 | CFLAGS += $(call cc-option,-Wno-string-plus-int -Wno-constant-logical-operand) | 82 | CFLAGS += $(call cc-option,-Wno-string-plus-int -Wno-constant-logical-operand) |
83 | endif | ||
82 | 84 | ||
83 | # FIXME: These warnings are at least partially to be concerned about and should | 85 | # FIXME: These warnings are at least partially to be concerned about and should |
84 | # be fixed.. | 86 | # be fixed.. |
diff --git a/archival/bbunzip.c b/archival/bbunzip.c index da6f031e3..320fe4fd1 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c | |||
@@ -388,7 +388,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) | |||
388 | * Normally, "zcat" is just "gunzip -c". | 388 | * Normally, "zcat" is just "gunzip -c". |
389 | * But if seamless magic is enabled, then we are much more clever. | 389 | * But if seamless magic is enabled, then we are much more clever. |
390 | */ | 390 | */ |
391 | if (ENABLE_ZCAT && (!ENABLE_GUNZIP || applet_name[1] == 'c')) | 391 | if (ENABLE_ZCAT && applet_name[1] == 'c') |
392 | option_mask32 |= BBUNPK_OPT_STDOUT | BBUNPK_SEAMLESS_MAGIC; | 392 | option_mask32 |= BBUNPK_OPT_STDOUT | BBUNPK_SEAMLESS_MAGIC; |
393 | 393 | ||
394 | return bbunpack(argv, unpack_gz_stream, make_new_name_gunzip, /*unused:*/ NULL); | 394 | return bbunpack(argv, unpack_gz_stream, make_new_name_gunzip, /*unused:*/ NULL); |
diff --git a/archival/cpio.c b/archival/cpio.c index 0f37ffbb9..94b4b8174 100644 --- a/archival/cpio.c +++ b/archival/cpio.c | |||
@@ -516,6 +516,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) | |||
516 | if (archive_handle->cpio__blocks != (off_t)-1 | 516 | if (archive_handle->cpio__blocks != (off_t)-1 |
517 | && !(opt & OPT_QUIET) | 517 | && !(opt & OPT_QUIET) |
518 | ) { | 518 | ) { |
519 | fflush_all(); | ||
519 | fprintf(stderr, "%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks); | 520 | fprintf(stderr, "%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks); |
520 | } | 521 | } |
521 | 522 | ||
diff --git a/archival/dpkg.c b/archival/dpkg.c index 6f28b994c..61631bd4d 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c | |||
@@ -1209,6 +1209,27 @@ static char **create_list(const char *filename) | |||
1209 | return file_list; | 1209 | return file_list; |
1210 | } | 1210 | } |
1211 | 1211 | ||
1212 | /** This tests if the filename is an "important" directory, which might be symlinked. | ||
1213 | * Debians dpkg test if directories are used by other packages, this | ||
1214 | * implementation doesn't and would remove for ex. an lib -> usr/lib symlink. | ||
1215 | */ | ||
1216 | static int is_builtin_exclude(const char *name) | ||
1217 | { | ||
1218 | if (*name++ != '/') | ||
1219 | return 0; | ||
1220 | if (index_in_strings(".\0" "etc\0" "opt\0" "srv\0" "var\0" "var/lib\0", | ||
1221 | name) >= 0) | ||
1222 | return 1; | ||
1223 | if (is_prefixed_with(name, "usr/")) { | ||
1224 | name += sizeof("usr/") - 1; | ||
1225 | if (is_prefixed_with(name, "local/")) | ||
1226 | name += sizeof("local/") - 1; | ||
1227 | } | ||
1228 | |||
1229 | return index_in_strings("bin\0" "lib\0" "lib32\0" "lib64\0" "sbin\0", | ||
1230 | name) >= 0; | ||
1231 | } | ||
1232 | |||
1212 | /* maybe i should try and hook this into remove_file.c somehow */ | 1233 | /* maybe i should try and hook this into remove_file.c somehow */ |
1213 | static int remove_file_array(char **remove_names, char **exclude_names) | 1234 | static int remove_file_array(char **remove_names, char **exclude_names) |
1214 | { | 1235 | { |
@@ -1220,6 +1241,8 @@ static int remove_file_array(char **remove_names, char **exclude_names) | |||
1220 | return 0; | 1241 | return 0; |
1221 | } | 1242 | } |
1222 | for (i = 0; remove_names[i] != NULL; i++) { | 1243 | for (i = 0; remove_names[i] != NULL; i++) { |
1244 | if (is_builtin_exclude(remove_names[i])) | ||
1245 | continue; | ||
1223 | if (exclude_names != NULL) { | 1246 | if (exclude_names != NULL) { |
1224 | for (j = 0; exclude_names[j] != NULL; j++) { | 1247 | for (j = 0; exclude_names[j] != NULL; j++) { |
1225 | if (strcmp(remove_names[i], exclude_names[j]) == 0) { | 1248 | if (strcmp(remove_names[i], exclude_names[j]) == 0) { |
diff --git a/coreutils/expand.c b/coreutils/expand.c index 4fa974df8..5f5993921 100644 --- a/coreutils/expand.c +++ b/coreutils/expand.c | |||
@@ -160,7 +160,7 @@ static void unexpand(FILE *file, unsigned tab_size, unsigned opt) | |||
160 | putchar('\t'); | 160 | putchar('\t'); |
161 | } | 161 | } |
162 | 162 | ||
163 | if ((opt & OPT_INITIAL) && ptr != line) { | 163 | if (!(opt & OPT_ALL) && ptr != line) { |
164 | printf("%*s%s", len, "", ptr); | 164 | printf("%*s%s", len, "", ptr); |
165 | break; | 165 | break; |
166 | } | 166 | } |
@@ -207,13 +207,13 @@ int expand_main(int argc UNUSED_PARAM, char **argv) | |||
207 | "ft:a" | 207 | "ft:a" |
208 | "\0" | 208 | "\0" |
209 | "ta" /* -t NUM sets -a */, | 209 | "ta" /* -t NUM sets -a */, |
210 | "first-only\0" No_argument "i" | 210 | "first-only\0" No_argument "f" |
211 | "tabs\0" Required_argument "t" | 211 | "tabs\0" Required_argument "t" |
212 | "all\0" No_argument "a" | 212 | "all\0" No_argument "a" |
213 | , &opt_t | 213 | , &opt_t |
214 | ); | 214 | ); |
215 | /* -f --first-only is the default */ | 215 | /* -t implies -a, but an explicit -f overrides */ |
216 | if (!(opt & OPT_ALL)) opt |= OPT_INITIAL; | 216 | if (opt & OPT_INITIAL) opt &= ~OPT_ALL; |
217 | } | 217 | } |
218 | tab_size = xatou_range(opt_t, 1, UINT_MAX); | 218 | tab_size = xatou_range(opt_t, 1, UINT_MAX); |
219 | 219 | ||
diff --git a/editors/awk.c b/editors/awk.c index 76385f33b..509f4ddd8 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -1363,8 +1363,10 @@ static node *parse_expr(uint32_t iexp) | |||
1363 | v = cn->l.v = xzalloc(sizeof(var)); | 1363 | v = cn->l.v = xzalloc(sizeof(var)); |
1364 | if (tc & TC_NUMBER) | 1364 | if (tc & TC_NUMBER) |
1365 | setvar_i(v, t_double); | 1365 | setvar_i(v, t_double); |
1366 | else | 1366 | else { |
1367 | setvar_s(v, t_string); | 1367 | setvar_s(v, t_string); |
1368 | xtc &= ~TC_UOPPOST; /* "str"++ is not allowed */ | ||
1369 | } | ||
1368 | break; | 1370 | break; |
1369 | 1371 | ||
1370 | case TC_REGEXP: | 1372 | case TC_REGEXP: |
diff --git a/editors/patch.c b/editors/patch.c index 0ce0210fd..aaa253591 100644 --- a/editors/patch.c +++ b/editors/patch.c | |||
@@ -264,7 +264,7 @@ static int apply_one_hunk(void) | |||
264 | if (!plist && matcheof) break; | 264 | if (!plist && matcheof) break; |
265 | 265 | ||
266 | if (backwarn) | 266 | if (backwarn) |
267 | fdprintf(2,"Possibly reversed hunk %d at %ld\n", | 267 | fdprintf(2, "Possibly reversed hunk %d at %ld\n", |
268 | TT.hunknum, TT.linenum); | 268 | TT.hunknum, TT.linenum); |
269 | 269 | ||
270 | // File ended before we found a place for this hunk. | 270 | // File ended before we found a place for this hunk. |
@@ -593,6 +593,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
593 | TT.linenum = 0; | 593 | TT.linenum = 0; |
594 | TT.hunknum = 0; | 594 | TT.hunknum = 0; |
595 | } | 595 | } |
596 | fflush_all(); // make "patching file F" visible | ||
596 | } | 597 | } |
597 | 598 | ||
598 | TT.hunknum++; | 599 | TT.hunknum++; |
diff --git a/examples/udhcp/simple.script b/examples/udhcp/simple.script index 6658fbeef..f079ec8b8 100755 --- a/examples/udhcp/simple.script +++ b/examples/udhcp/simple.script | |||
@@ -18,7 +18,7 @@ case "$1" in | |||
18 | deconfig) | 18 | deconfig) |
19 | echo "Clearing IP addresses on $interface, upping it" | 19 | echo "Clearing IP addresses on $interface, upping it" |
20 | if command -v ip >/dev/null; then | 20 | if command -v ip >/dev/null; then |
21 | ip addr flush dev $interface | 21 | ip -4 addr flush dev $interface |
22 | ip link set dev $interface up | 22 | ip link set dev $interface up |
23 | else | 23 | else |
24 | ifconfig $interface 0.0.0.0 | 24 | ifconfig $interface 0.0.0.0 |
diff --git a/include/libbb.h b/include/libbb.h index 7077f0e0d..32f4c4126 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -316,6 +316,7 @@ typedef unsigned long uoff_t; | |||
316 | /* scary. better ideas? (but do *test* them first!) */ | 316 | /* scary. better ideas? (but do *test* them first!) */ |
317 | #define OFF_T_MAX ((off_t)~((off_t)1 << (sizeof(off_t)*8-1))) | 317 | #define OFF_T_MAX ((off_t)~((off_t)1 << (sizeof(off_t)*8-1))) |
318 | /* Users report bionic to use 32-bit off_t even if LARGEFILE support is requested. | 318 | /* Users report bionic to use 32-bit off_t even if LARGEFILE support is requested. |
319 | * On musl, !ENABLE_LFS on 32-bit arches thinks that off_t is 32-bit. | ||
319 | * We misdetected that. Don't let it build: | 320 | * We misdetected that. Don't let it build: |
320 | */ | 321 | */ |
321 | struct BUG_off_t_size_is_misdetected { | 322 | struct BUG_off_t_size_is_misdetected { |
@@ -1428,8 +1429,10 @@ static inline void __attribute__ ((deprecated("use bb_simple_info_msg instead")) | |||
1428 | #define bb_perror_msg_and_die(...) BB_MSG(_perror_msg_and_die, BB_MSG_KIND(__VA_ARGS__), __VA_ARGS__) | 1429 | #define bb_perror_msg_and_die(...) BB_MSG(_perror_msg_and_die, BB_MSG_KIND(__VA_ARGS__), __VA_ARGS__) |
1429 | #define bb_herror_msg(...) BB_MSG(_herror_msg, BB_MSG_KIND(__VA_ARGS__), __VA_ARGS__) | 1430 | #define bb_herror_msg(...) BB_MSG(_herror_msg, BB_MSG_KIND(__VA_ARGS__), __VA_ARGS__) |
1430 | #define bb_herror_msg_and_die(...) BB_MSG(_herror_msg_and_die, BB_MSG_KIND(__VA_ARGS__), __VA_ARGS__) | 1431 | #define bb_herror_msg_and_die(...) BB_MSG(_herror_msg_and_die, BB_MSG_KIND(__VA_ARGS__), __VA_ARGS__) |
1432 | #if ENABLE_FEATURE_SYSLOG_INFO | ||
1431 | #define bb_info_msg(...) BB_MSG(_info_msg, BB_MSG_KIND(__VA_ARGS__), __VA_ARGS__) | 1433 | #define bb_info_msg(...) BB_MSG(_info_msg, BB_MSG_KIND(__VA_ARGS__), __VA_ARGS__) |
1432 | #endif | 1434 | #endif |
1435 | #endif | ||
1433 | 1436 | ||
1434 | /* We need to export XXX_main from libbusybox | 1437 | /* We need to export XXX_main from libbusybox |
1435 | * only if we build "individual" binaries | 1438 | * only if we build "individual" binaries |
diff --git a/include/platform.h b/include/platform.h index afd8cf292..f1c09c4d2 100644 --- a/include/platform.h +++ b/include/platform.h | |||
@@ -39,6 +39,10 @@ | |||
39 | # endif | 39 | # endif |
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | #if !__GNUC_PREREQ(5,0) | ||
43 | # define deprecated(msg) deprecated | ||
44 | #endif | ||
45 | |||
42 | #undef inline | 46 | #undef inline |
43 | #if defined(__STDC_VERSION__) && __STDC_VERSION__ > 199901L | 47 | #if defined(__STDC_VERSION__) && __STDC_VERSION__ > 199901L |
44 | /* it's a keyword */ | 48 | /* it's a keyword */ |
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 8c46d0d1b..d2f98567e 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -794,7 +794,9 @@ static void install_links(const char *busybox UNUSED_PARAM, | |||
794 | } | 794 | } |
795 | # endif | 795 | # endif |
796 | 796 | ||
797 | # if ENABLE_BUSYBOX || NUM_APPLETS > 0 | ||
797 | static void run_applet_and_exit(const char *name, char **argv) NORETURN; | 798 | static void run_applet_and_exit(const char *name, char **argv) NORETURN; |
799 | #endif | ||
798 | 800 | ||
799 | # if NUM_SCRIPTS > 0 | 801 | # if NUM_SCRIPTS > 0 |
800 | static int find_script_by_name(const char *name) | 802 | static int find_script_by_name(const char *name) |
@@ -815,13 +817,13 @@ int scripted_main(int argc UNUSED_PARAM, char **argv) | |||
815 | { | 817 | { |
816 | int script = find_script_by_name(applet_name); | 818 | int script = find_script_by_name(applet_name); |
817 | if (script >= 0) | 819 | if (script >= 0) |
818 | #if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH | 820 | # if ENABLE_SHELL_ASH |
819 | exit(ash_main(-script - 1, argv)); | 821 | exit(ash_main(-script - 1, argv)); |
820 | #elif ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH | 822 | # elif ENABLE_SHELL_HUSH |
821 | exit(hush_main(-script - 1, argv)); | 823 | exit(hush_main(-script - 1, argv)); |
822 | #else | 824 | # else |
823 | return 1; | 825 | return 1; |
824 | #endif | 826 | # endif |
825 | return 0; | 827 | return 0; |
826 | } | 828 | } |
827 | 829 | ||
@@ -1160,7 +1162,33 @@ static NORETURN void run_applet_and_exit(const char *name, char **argv) | |||
1160 | } | 1162 | } |
1161 | # endif | 1163 | # endif |
1162 | 1164 | ||
1163 | #endif /* !defined(SINGLE_APPLET_MAIN) */ | 1165 | #else /* defined(SINGLE_APPLET_MAIN) */ |
1166 | |||
1167 | # if NUM_SCRIPTS > 0 | ||
1168 | /* if SINGLE_APPLET_MAIN, these two functions are simpler: */ | ||
1169 | int scripted_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
1170 | int scripted_main(int argc UNUSED_PARAM, char **argv) | ||
1171 | { | ||
1172 | # if ENABLE_SHELL_ASH | ||
1173 | int script = 0; | ||
1174 | exit(ash_main(-script - 1, argv)); | ||
1175 | # elif ENABLE_SHELL_HUSH | ||
1176 | int script = 0; | ||
1177 | exit(hush_main(-script - 1, argv)); | ||
1178 | # else | ||
1179 | return 1; | ||
1180 | # endif | ||
1181 | } | ||
1182 | char* FAST_FUNC | ||
1183 | get_script_content(unsigned n UNUSED_PARAM) | ||
1184 | { | ||
1185 | char *t = unpack_bz2_data(packed_scripts, sizeof(packed_scripts), | ||
1186 | UNPACKED_SCRIPTS_LENGTH); | ||
1187 | return t; | ||
1188 | } | ||
1189 | # endif /* NUM_SCRIPTS > 0 */ | ||
1190 | |||
1191 | #endif /* defined(SINGLE_APPLET_MAIN) */ | ||
1164 | 1192 | ||
1165 | 1193 | ||
1166 | #if ENABLE_BUILD_LIBBUSYBOX | 1194 | #if ENABLE_BUILD_LIBBUSYBOX |
diff --git a/libbb/compare_string_array.c b/libbb/compare_string_array.c index 856739c41..ede5a97e3 100644 --- a/libbb/compare_string_array.c +++ b/libbb/compare_string_array.c | |||
@@ -158,8 +158,11 @@ int FAST_FUNC index_in_substrings(const char *strings, const char *key) | |||
158 | const char* FAST_FUNC nth_string(const char *strings, int n) | 158 | const char* FAST_FUNC nth_string(const char *strings, int n) |
159 | { | 159 | { |
160 | while (n) { | 160 | while (n) { |
161 | n--; | 161 | if (*strings++ == '\0') { |
162 | strings += strlen(strings) + 1; | 162 | if (*strings == '\0') /* reached end of strings */ |
163 | break; | ||
164 | n--; | ||
165 | } | ||
163 | } | 166 | } |
164 | return strings; | 167 | return strings; |
165 | } | 168 | } |
diff --git a/libbb/duration.c b/libbb/duration.c index 5acd0dba3..22b209f4d 100644 --- a/libbb/duration.c +++ b/libbb/duration.c | |||
@@ -17,6 +17,7 @@ | |||
17 | //kbuild:lib-$(CONFIG_TIMEOUT) += duration.o | 17 | //kbuild:lib-$(CONFIG_TIMEOUT) += duration.o |
18 | //kbuild:lib-$(CONFIG_PING) += duration.o | 18 | //kbuild:lib-$(CONFIG_PING) += duration.o |
19 | //kbuild:lib-$(CONFIG_PING6) += duration.o | 19 | //kbuild:lib-$(CONFIG_PING6) += duration.o |
20 | //kbuild:lib-$(CONFIG_WATCH) += duration.o | ||
20 | 21 | ||
21 | #include "libbb.h" | 22 | #include "libbb.h" |
22 | 23 | ||
diff --git a/libbb/last_char_is.c b/libbb/last_char_is.c index 66f2e3635..918526e6c 100644 --- a/libbb/last_char_is.c +++ b/libbb/last_char_is.c | |||
@@ -8,16 +8,17 @@ | |||
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | 10 | ||
11 | /* Find out if the last character of a string matches the one given. | 11 | /* Find out if the last character of a string matches the one given */ |
12 | * Don't underrun the buffer if the string length is 0. | ||
13 | */ | ||
14 | char* FAST_FUNC last_char_is(const char *s, int c) | 12 | char* FAST_FUNC last_char_is(const char *s, int c) |
15 | { | 13 | { |
16 | if (s && *s) { | 14 | if (s) { |
17 | size_t sz = strlen(s) - 1; | 15 | size_t sz = strlen(s); |
18 | s += sz; | 16 | /* Don't underrun the buffer if the string length is 0 */ |
19 | if ( (unsigned char)*s == c) | 17 | if (sz != 0) { |
20 | return (char*)s; | 18 | s += sz - 1; |
19 | if ((unsigned char)*s == c) | ||
20 | return (char*)s; | ||
21 | } | ||
21 | } | 22 | } |
22 | return NULL; | 23 | return NULL; |
23 | } | 24 | } |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index f4247d237..a36a1647d 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -99,7 +99,7 @@ static bool BB_ispunct(CHAR_T c) | |||
99 | # if ENABLE_FEATURE_EDITING_VI | 99 | # if ENABLE_FEATURE_EDITING_VI |
100 | static bool BB_isalnum_or_underscore(CHAR_T c) | 100 | static bool BB_isalnum_or_underscore(CHAR_T c) |
101 | { | 101 | { |
102 | return ((unsigned)c < 256 && isalnum(c)) || c == '_'; | 102 | return isalnum(c) || c == '_'; |
103 | } | 103 | } |
104 | # endif | 104 | # endif |
105 | # define BB_ispunct(c) ispunct(c) | 105 | # define BB_ispunct(c) ispunct(c) |
diff --git a/libbb/procps.c b/libbb/procps.c index e6892d7ff..4f9705bc1 100644 --- a/libbb/procps.c +++ b/libbb/procps.c | |||
@@ -178,6 +178,15 @@ static char *skip_fields(char *str, int count) | |||
178 | } | 178 | } |
179 | #endif | 179 | #endif |
180 | 180 | ||
181 | static char* skip_whitespace_if_prefixed_with(char *buf, const char *prefix) | ||
182 | { | ||
183 | char *tp = is_prefixed_with(buf, prefix); | ||
184 | if (tp) { | ||
185 | tp = skip_whitespace(tp); | ||
186 | } | ||
187 | return tp; | ||
188 | } | ||
189 | |||
181 | #if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP | 190 | #if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP |
182 | int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total, | 191 | int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total, |
183 | void (*cb)(struct smaprec *, void *), void *data) | 192 | void (*cb)(struct smaprec *, void *), void *data) |
@@ -208,8 +217,7 @@ int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total, | |||
208 | char *tp, *p; | 217 | char *tp, *p; |
209 | 218 | ||
210 | #define SCAN(S, X) \ | 219 | #define SCAN(S, X) \ |
211 | if ((tp = is_prefixed_with(buf, S)) != NULL) { \ | 220 | if ((tp = skip_whitespace_if_prefixed_with(buf, S)) != NULL) { \ |
212 | tp = skip_whitespace(tp); \ | ||
213 | total->X += currec.X = fast_strtoul_10(&tp); \ | 221 | total->X += currec.X = fast_strtoul_10(&tp); \ |
214 | continue; \ | 222 | continue; \ |
215 | } | 223 | } |
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index cfe062a47..6fdc0f6a4 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c | |||
@@ -93,26 +93,17 @@ char* FAST_FUNC xstrdup(const char *s) | |||
93 | // the (possibly truncated to length n) string into it. | 93 | // the (possibly truncated to length n) string into it. |
94 | char* FAST_FUNC xstrndup(const char *s, int n) | 94 | char* FAST_FUNC xstrndup(const char *s, int n) |
95 | { | 95 | { |
96 | int m; | ||
97 | char *t; | 96 | char *t; |
98 | 97 | ||
99 | if (ENABLE_DEBUG && s == NULL) | 98 | if (ENABLE_DEBUG && s == NULL) |
100 | bb_simple_error_msg_and_die("xstrndup bug"); | 99 | bb_simple_error_msg_and_die("xstrndup bug"); |
101 | 100 | ||
102 | /* We can just xmalloc(n+1) and strncpy into it, */ | 101 | t = strndup(s, n); |
103 | /* but think about xstrndup("abc", 10000) wastage! */ | ||
104 | m = n; | ||
105 | t = (char*) s; | ||
106 | while (m) { | ||
107 | if (!*t) break; | ||
108 | m--; | ||
109 | t++; | ||
110 | } | ||
111 | n -= m; | ||
112 | t = xmalloc(n + 1); | ||
113 | t[n] = '\0'; | ||
114 | 102 | ||
115 | return memcpy(t, s, n); | 103 | if (t == NULL) |
104 | bb_die_memory_exhausted(); | ||
105 | |||
106 | return t; | ||
116 | } | 107 | } |
117 | 108 | ||
118 | void* FAST_FUNC xmemdup(const void *s, int n) | 109 | void* FAST_FUNC xmemdup(const void *s, int n) |
diff --git a/loginutils/deluser.c b/loginutils/deluser.c index 56bc7eaa6..8e7df737c 100644 --- a/loginutils/deluser.c +++ b/loginutils/deluser.c | |||
@@ -99,8 +99,14 @@ int deluser_main(int argc, char **argv) | |||
99 | pfile = bb_path_passwd_file; | 99 | pfile = bb_path_passwd_file; |
100 | if (ENABLE_FEATURE_SHADOWPASSWDS) | 100 | if (ENABLE_FEATURE_SHADOWPASSWDS) |
101 | sfile = bb_path_shadow_file; | 101 | sfile = bb_path_shadow_file; |
102 | if (opt_delhome) | 102 | if (opt_delhome) { |
103 | remove_file(pw->pw_dir, FILEUTILS_RECUR); | 103 | struct stat st; |
104 | |||
105 | /* Make sure home is an actual directory before | ||
106 | * removing it (e.g. users with /dev/null as home) */ | ||
107 | if (stat(pw->pw_dir, &st) == 0 && S_ISDIR(st.st_mode)) | ||
108 | remove_file(pw->pw_dir, FILEUTILS_RECUR); | ||
109 | } | ||
104 | } else { | 110 | } else { |
105 | struct group *gr; | 111 | struct group *gr; |
106 | do_delgroup: | 112 | do_delgroup: |
diff --git a/make_single_applets.sh b/make_single_applets.sh index a37168cdf..7df53397e 100755 --- a/make_single_applets.sh +++ b/make_single_applets.sh | |||
@@ -29,6 +29,8 @@ for app in $apps; do | |||
29 | done | 29 | done |
30 | # remove "busybox" as well | 30 | # remove "busybox" as well |
31 | allno="`echo "$allno" | sed "s/^CONFIG_BUSYBOX=y\$/# CONFIG_BUSYBOX is not set/"`" | 31 | allno="`echo "$allno" | sed "s/^CONFIG_BUSYBOX=y\$/# CONFIG_BUSYBOX is not set/"`" |
32 | # disable any CONFIG_script_DEPENDENCIES as well | ||
33 | allno="`echo "$allno" | sed "s/^\(CONFIG_.*_DEPENDENCIES\)=y\$/# \1 is not set/"`" | ||
32 | #echo "$allno" >.config_allno | 34 | #echo "$allno" >.config_allno |
33 | 35 | ||
34 | trap 'test -f .config.SV && mv .config.SV .config && touch .config' EXIT | 36 | trap 'test -f .config.SV && mv .config.SV .config && touch .config' EXIT |
diff --git a/miscutils/bc.c b/miscutils/bc.c index c7246ea1a..4d987325e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
@@ -2522,7 +2522,9 @@ static void xc_read_line(BcVec *vec, FILE *fp) | |||
2522 | 2522 | ||
2523 | #if ENABLE_FEATURE_BC_INTERACTIVE | 2523 | #if ENABLE_FEATURE_BC_INTERACTIVE |
2524 | if (G_interrupt) { // ^C was pressed | 2524 | if (G_interrupt) { // ^C was pressed |
2525 | # if ENABLE_FEATURE_EDITING | ||
2525 | intr: | 2526 | intr: |
2527 | # endif | ||
2526 | if (fp != stdin) { | 2528 | if (fp != stdin) { |
2527 | // ^C while running a script (bc SCRIPT): die. | 2529 | // ^C while running a script (bc SCRIPT): die. |
2528 | // We do not return to interactive prompt: | 2530 | // We do not return to interactive prompt: |
diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c index f3d935b2e..d47ee4d47 100644 --- a/miscutils/devfsd.c +++ b/miscutils/devfsd.c | |||
@@ -353,6 +353,7 @@ static const char bb_msg_variable_not_found[] ALIGN1 = "variable: %s not found"; | |||
353 | #define error_logger_and_die(p, fmt, args...) bb_perror_msg_and_die(fmt, ## args) | 353 | #define error_logger_and_die(p, fmt, args...) bb_perror_msg_and_die(fmt, ## args) |
354 | #else | 354 | #else |
355 | #define info_logger(p, fmt, args...) | 355 | #define info_logger(p, fmt, args...) |
356 | #define simple_info_logger(p, msg) | ||
356 | #define msg_logger(p, fmt, args...) | 357 | #define msg_logger(p, fmt, args...) |
357 | #define simple_msg_logger(p, msg) | 358 | #define simple_msg_logger(p, msg) |
358 | #define msg_logger_and_die(p, fmt, args...) exit(EXIT_FAILURE) | 359 | #define msg_logger_and_die(p, fmt, args...) exit(EXIT_FAILURE) |
diff --git a/networking/brctl.c b/networking/brctl.c index 25640246d..2f4ac4a87 100644 --- a/networking/brctl.c +++ b/networking/brctl.c | |||
@@ -107,7 +107,7 @@ static unsigned str_to_jiffies(const char *time_str) | |||
107 | 107 | ||
108 | #define filedata bb_common_bufsiz1 | 108 | #define filedata bb_common_bufsiz1 |
109 | 109 | ||
110 | #if ENABLE_FEATURE_BRCTL_SHOW | 110 | #if ENABLE_FEATURE_BRCTL_SHOW || ENABLE_FEATURE_BRCTL_FANCY |
111 | static int read_file(const char *name) | 111 | static int read_file(const char *name) |
112 | { | 112 | { |
113 | int n = open_read_close(name, filedata, COMMON_BUFSIZE - 1); | 113 | int n = open_read_close(name, filedata, COMMON_BUFSIZE - 1); |
@@ -120,7 +120,9 @@ static int read_file(const char *name) | |||
120 | } | 120 | } |
121 | return n; | 121 | return n; |
122 | } | 122 | } |
123 | #endif | ||
123 | 124 | ||
125 | #if ENABLE_FEATURE_BRCTL_SHOW | ||
124 | /* NB: we are in /sys/class/net | 126 | /* NB: we are in /sys/class/net |
125 | */ | 127 | */ |
126 | static int show_bridge(const char *name, int need_hdr) | 128 | static int show_bridge(const char *name, int need_hdr) |
@@ -591,6 +593,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) | |||
591 | return EXIT_SUCCESS; | 593 | return EXIT_SUCCESS; |
592 | } | 594 | } |
593 | 595 | ||
596 | #if ENABLE_FEATURE_BRCTL_FANCY | ||
594 | if (key == ARG_showmacs) { | 597 | if (key == ARG_showmacs) { |
595 | show_bridge_macs(br); | 598 | show_bridge_macs(br); |
596 | return EXIT_SUCCESS; | 599 | return EXIT_SUCCESS; |
@@ -599,6 +602,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) | |||
599 | show_bridge_stp(br); | 602 | show_bridge_stp(br); |
600 | return EXIT_SUCCESS; | 603 | return EXIT_SUCCESS; |
601 | } | 604 | } |
605 | #endif | ||
602 | 606 | ||
603 | if (!*argv) /* All of the below need at least two arguments */ | 607 | if (!*argv) /* All of the below need at least two arguments */ |
604 | bb_show_usage(); | 608 | bb_show_usage(); |
diff --git a/networking/httpd.c b/networking/httpd.c index eeaa4bec1..5105eedac 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -2871,6 +2871,7 @@ int httpd_main(int argc UNUSED_PARAM, char **argv) | |||
2871 | #if !BB_MMU | 2871 | #if !BB_MMU |
2872 | if (!(opt & OPT_FOREGROUND)) { | 2872 | if (!(opt & OPT_FOREGROUND)) { |
2873 | bb_daemonize_or_rexec(0, argv); /* don't change current directory */ | 2873 | bb_daemonize_or_rexec(0, argv); /* don't change current directory */ |
2874 | re_execed = 0; /* for the following chdir to work */ | ||
2874 | } | 2875 | } |
2875 | #endif | 2876 | #endif |
2876 | #else /* ENABLE_PLATFORM_MINGW32 */ | 2877 | #else /* ENABLE_PLATFORM_MINGW32 */ |
@@ -2878,8 +2879,8 @@ int httpd_main(int argc UNUSED_PARAM, char **argv) | |||
2878 | mingw_daemonize(argv); | 2879 | mingw_daemonize(argv); |
2879 | #endif | 2880 | #endif |
2880 | 2881 | ||
2881 | /* Chdir to home (unless we were re-execed for NOMMU case: | 2882 | /* Chdir to home (unless we were re_exec()ed for NOMMU case |
2882 | * we are already in the home dir then). | 2883 | * in mini_httpd_nommu(): we are already in the home dir then). |
2883 | */ | 2884 | */ |
2884 | #if ENABLE_PLATFORM_MINGW32 | 2885 | #if ENABLE_PLATFORM_MINGW32 |
2885 | if (!(opt & OPT_INETD)) | 2886 | if (!(opt & OPT_INETD)) |
diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c index 034e03d21..88eda6b28 100644 --- a/networking/nc_bloaty.c +++ b/networking/nc_bloaty.c | |||
@@ -84,6 +84,7 @@ | |||
84 | //usage: ) | 84 | //usage: ) |
85 | //usage: "\n -n Don't do DNS resolution" | 85 | //usage: "\n -n Don't do DNS resolution" |
86 | //usage: "\n -u UDP mode" | 86 | //usage: "\n -u UDP mode" |
87 | //usage: "\n -b Allow broadcasts" | ||
87 | //usage: "\n -v Verbose" | 88 | //usage: "\n -v Verbose" |
88 | //usage: IF_NC_EXTRA( | 89 | //usage: IF_NC_EXTRA( |
89 | //usage: "\n -o FILE Hex dump traffic" | 90 | //usage: "\n -o FILE Hex dump traffic" |
@@ -171,17 +172,19 @@ enum { | |||
171 | OPT_p = (1 << 1), | 172 | OPT_p = (1 << 1), |
172 | OPT_s = (1 << 2), | 173 | OPT_s = (1 << 2), |
173 | OPT_u = (1 << 3), | 174 | OPT_u = (1 << 3), |
174 | OPT_v = (1 << 4), | 175 | OPT_b = (1 << 4), |
175 | OPT_w = (1 << 5), | 176 | OPT_v = (1 << 5), |
176 | OPT_l = (1 << 6) * ENABLE_NC_SERVER, | 177 | OPT_w = (1 << 6), |
177 | OPT_k = (1 << 7) * ENABLE_NC_SERVER, | 178 | OPT_l = (1 << 7) * ENABLE_NC_SERVER, |
178 | OPT_i = (1 << (6+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA, | 179 | OPT_k = (1 << 8) * ENABLE_NC_SERVER, |
179 | OPT_o = (1 << (7+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA, | 180 | OPT_i = (1 << (7+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA, |
180 | OPT_z = (1 << (8+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA, | 181 | OPT_o = (1 << (8+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA, |
182 | OPT_z = (1 << (9+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA, | ||
181 | }; | 183 | }; |
182 | 184 | ||
183 | #define o_nflag (option_mask32 & OPT_n) | 185 | #define o_nflag (option_mask32 & OPT_n) |
184 | #define o_udpmode (option_mask32 & OPT_u) | 186 | #define o_udpmode (option_mask32 & OPT_u) |
187 | #define o_bcmode (option_mask32 & OPT_b) | ||
185 | #if ENABLE_NC_EXTRA | 188 | #if ENABLE_NC_EXTRA |
186 | #define o_ofile (option_mask32 & OPT_o) | 189 | #define o_ofile (option_mask32 & OPT_o) |
187 | #define o_zero (option_mask32 & OPT_z) | 190 | #define o_zero (option_mask32 & OPT_z) |
@@ -788,7 +791,7 @@ int nc_main(int argc UNUSED_PARAM, char **argv) | |||
788 | 791 | ||
789 | // -g -G -t -r deleted, unimplemented -a deleted too | 792 | // -g -G -t -r deleted, unimplemented -a deleted too |
790 | getopt32(argv, "^" | 793 | getopt32(argv, "^" |
791 | "np:s:uvw:+"/* -w N */ IF_NC_SERVER("lk") | 794 | "np:s:ubvw:+"/* -w N */ IF_NC_SERVER("lk") |
792 | IF_NC_EXTRA("i:o:z") | 795 | IF_NC_EXTRA("i:o:z") |
793 | "\0" | 796 | "\0" |
794 | "?2:vv"IF_NC_SERVER(":ll"), /* max 2 params; -v and -l are counters */ | 797 | "?2:vv"IF_NC_SERVER(":ll"), /* max 2 params; -v and -l are counters */ |
@@ -851,8 +854,11 @@ int nc_main(int argc UNUSED_PARAM, char **argv) | |||
851 | } | 854 | } |
852 | xmove_fd(x, netfd); | 855 | xmove_fd(x, netfd); |
853 | setsockopt_reuseaddr(netfd); | 856 | setsockopt_reuseaddr(netfd); |
854 | if (o_udpmode) | 857 | if (o_udpmode) { |
858 | if (o_bcmode) | ||
859 | setsockopt_broadcast(netfd); | ||
855 | socket_want_pktinfo(netfd); | 860 | socket_want_pktinfo(netfd); |
861 | } | ||
856 | if (!ENABLE_FEATURE_UNIX_LOCAL | 862 | if (!ENABLE_FEATURE_UNIX_LOCAL |
857 | || cnt_l != 0 /* listen */ | 863 | || cnt_l != 0 /* listen */ |
858 | || ouraddr->u.sa.sa_family != AF_UNIX | 864 | || ouraddr->u.sa.sa_family != AF_UNIX |
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index 9ec752dfc..20d843bab 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c | |||
@@ -15,7 +15,7 @@ const uint8_t MAC_BCAST_ADDR[6] ALIGN2 = { | |||
15 | }; | 15 | }; |
16 | 16 | ||
17 | #if ENABLE_UDHCPC || ENABLE_UDHCPD | 17 | #if ENABLE_UDHCPC || ENABLE_UDHCPD |
18 | /* Supported options are easily added here. | 18 | /* Supported options are easily added here, they need to be sorted. |
19 | * See RFC2132 for more options. | 19 | * See RFC2132 for more options. |
20 | * OPTION_REQ: these options are requested by udhcpc (unless -o). | 20 | * OPTION_REQ: these options are requested by udhcpc (unless -o). |
21 | */ | 21 | */ |
@@ -222,79 +222,91 @@ unsigned FAST_FUNC udhcp_option_idx(const char *name, const char *option_strings | |||
222 | } | 222 | } |
223 | } | 223 | } |
224 | 224 | ||
225 | /* Get an option with bounds checking (warning, result is not aligned) */ | 225 | /* Initialize state to be used between subsequent udhcp_scan_options calls */ |
226 | uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code) | 226 | void FAST_FUNC init_scan_state(struct dhcp_packet *packet, struct dhcp_scan_state *scan_state) |
227 | { | ||
228 | scan_state->overload = 0; | ||
229 | scan_state->rem = sizeof(packet->options); | ||
230 | scan_state->optionptr = packet->options; | ||
231 | } | ||
232 | |||
233 | /* Iterate over packet's options, each call returning the next option. | ||
234 | * scan_state needs to be initialized with init_scan_state beforehand. | ||
235 | * Warning, result is not aligned. */ | ||
236 | uint8_t* FAST_FUNC udhcp_scan_options(struct dhcp_packet *packet, struct dhcp_scan_state *scan_state) | ||
227 | { | 237 | { |
228 | uint8_t *optionptr; | ||
229 | int len; | 238 | int len; |
230 | int rem; | ||
231 | int overload = 0; | ||
232 | enum { | 239 | enum { |
233 | FILE_FIELD101 = FILE_FIELD * 0x101, | 240 | FILE_FIELD101 = FILE_FIELD * 0x101, |
234 | SNAME_FIELD101 = SNAME_FIELD * 0x101, | 241 | SNAME_FIELD101 = SNAME_FIELD * 0x101, |
235 | }; | 242 | }; |
236 | 243 | ||
237 | /* option bytes: [code][len][data1][data2]..[dataLEN] */ | 244 | /* option bytes: [code][len][data1][data2]..[dataLEN] */ |
238 | optionptr = packet->options; | ||
239 | rem = sizeof(packet->options); | ||
240 | while (1) { | 245 | while (1) { |
241 | if (rem <= 0) { | 246 | if (scan_state->rem <= 0) { |
242 | complain: | 247 | complain: |
243 | bb_simple_error_msg("bad packet, malformed option field"); | 248 | bb_simple_error_msg("bad packet, malformed option field"); |
244 | return NULL; | 249 | return NULL; |
245 | } | 250 | } |
246 | 251 | ||
247 | /* DHCP_PADDING and DHCP_END have no [len] byte */ | 252 | /* DHCP_PADDING and DHCP_END have no [len] byte */ |
248 | if (optionptr[OPT_CODE] == DHCP_PADDING) { | 253 | if (scan_state->optionptr[OPT_CODE] == DHCP_PADDING) { |
249 | rem--; | 254 | scan_state->rem--; |
250 | optionptr++; | 255 | scan_state->optionptr++; |
251 | continue; | 256 | continue; |
252 | } | 257 | } |
253 | if (optionptr[OPT_CODE] == DHCP_END) { | 258 | if (scan_state->optionptr[OPT_CODE] == DHCP_END) { |
254 | if ((overload & FILE_FIELD101) == FILE_FIELD) { | 259 | if ((scan_state->overload & FILE_FIELD101) == FILE_FIELD) { |
255 | /* can use packet->file, and didn't look at it yet */ | 260 | /* can use packet->file, and didn't look at it yet */ |
256 | overload |= FILE_FIELD101; /* "we looked at it" */ | 261 | scan_state->overload |= FILE_FIELD101; /* "we looked at it" */ |
257 | optionptr = packet->file; | 262 | scan_state->optionptr = packet->file; |
258 | rem = sizeof(packet->file); | 263 | scan_state->rem = sizeof(packet->file); |
259 | continue; | 264 | continue; |
260 | } | 265 | } |
261 | if ((overload & SNAME_FIELD101) == SNAME_FIELD) { | 266 | if ((scan_state->overload & SNAME_FIELD101) == SNAME_FIELD) { |
262 | /* can use packet->sname, and didn't look at it yet */ | 267 | /* can use packet->sname, and didn't look at it yet */ |
263 | overload |= SNAME_FIELD101; /* "we looked at it" */ | 268 | scan_state->overload |= SNAME_FIELD101; /* "we looked at it" */ |
264 | optionptr = packet->sname; | 269 | scan_state->optionptr = packet->sname; |
265 | rem = sizeof(packet->sname); | 270 | scan_state->rem = sizeof(packet->sname); |
266 | continue; | 271 | continue; |
267 | } | 272 | } |
268 | break; | 273 | break; |
269 | } | 274 | } |
270 | 275 | ||
271 | if (rem <= OPT_LEN) | 276 | if (scan_state->rem <= OPT_LEN) |
272 | goto complain; /* complain and return NULL */ | 277 | goto complain; /* complain and return NULL */ |
273 | len = 2 + optionptr[OPT_LEN]; | 278 | len = 2 + scan_state->optionptr[OPT_LEN]; |
274 | rem -= len; | 279 | scan_state->rem -= len; |
275 | if (rem < 0) | 280 | /* So far no valid option with length 0 known. */ |
281 | if (scan_state->rem < 0 || scan_state->optionptr[OPT_LEN] == 0) | ||
276 | goto complain; /* complain and return NULL */ | 282 | goto complain; /* complain and return NULL */ |
277 | 283 | ||
278 | if (optionptr[OPT_CODE] == code) { | 284 | if (scan_state->optionptr[OPT_CODE] == DHCP_OPTION_OVERLOAD) { |
279 | if (optionptr[OPT_LEN] == 0) { | 285 | if (len >= 3) |
280 | /* So far no valid option with length 0 known. | 286 | scan_state->overload |= scan_state->optionptr[OPT_DATA]; |
281 | * Having this check means that searching | 287 | } else { |
282 | * for DHCP_MESSAGE_TYPE need not worry | 288 | uint8_t *return_ptr = scan_state->optionptr; |
283 | * that returned pointer might be unsafe | 289 | scan_state->optionptr += len; |
284 | * to dereference. | 290 | return return_ptr; |
285 | */ | ||
286 | goto complain; /* complain and return NULL */ | ||
287 | } | ||
288 | log_option("option found", optionptr); | ||
289 | return optionptr + OPT_DATA; | ||
290 | } | 291 | } |
292 | scan_state->optionptr += len; | ||
293 | } | ||
291 | 294 | ||
292 | if (optionptr[OPT_CODE] == DHCP_OPTION_OVERLOAD) { | 295 | return NULL; |
293 | if (len >= 3) | 296 | } |
294 | overload |= optionptr[OPT_DATA]; | 297 | |
295 | /* fall through */ | 298 | /* Get an option with bounds checking (warning, result is not aligned) */ |
299 | uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code) | ||
300 | { | ||
301 | uint8_t *optptr; | ||
302 | struct dhcp_scan_state scan_state; | ||
303 | |||
304 | init_scan_state(packet, &scan_state); | ||
305 | while ((optptr = udhcp_scan_options(packet, &scan_state)) != NULL) { | ||
306 | if (optptr[OPT_CODE] == code) { | ||
307 | log_option("option found", optptr); | ||
308 | return optptr + OPT_DATA; | ||
296 | } | 309 | } |
297 | optionptr += len; | ||
298 | } | 310 | } |
299 | 311 | ||
300 | /* log3 because udhcpc uses it a lot - very noisy */ | 312 | /* log3 because udhcpc uses it a lot - very noisy */ |
@@ -431,7 +443,7 @@ static NOINLINE void attach_option( | |||
431 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 443 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
432 | if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) { | 444 | if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) { |
433 | /* reuse buffer and length for RFC1035-formatted string */ | 445 | /* reuse buffer and length for RFC1035-formatted string */ |
434 | allocated = buffer = (char *)dname_enc(NULL, 0, buffer, &length); | 446 | allocated = buffer = (char *)dname_enc(/*NULL, 0,*/ buffer, &length); |
435 | } | 447 | } |
436 | #endif | 448 | #endif |
437 | 449 | ||
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 60255eefa..81c1dcbdc 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
@@ -78,7 +78,7 @@ struct BUG_bad_sizeof_struct_ip_udp_dhcp_packet { | |||
78 | /*** Options ***/ | 78 | /*** Options ***/ |
79 | 79 | ||
80 | enum { | 80 | enum { |
81 | OPTION_IP = 1, | 81 | OPTION_IP = 0, |
82 | OPTION_IP_PAIR, | 82 | OPTION_IP_PAIR, |
83 | OPTION_STRING, | 83 | OPTION_STRING, |
84 | /* Opts of STRING_HOST type will be sanitized before they are passed | 84 | /* Opts of STRING_HOST type will be sanitized before they are passed |
@@ -107,6 +107,12 @@ enum { | |||
107 | OPTION_LIST = 0x20, | 107 | OPTION_LIST = 0x20, |
108 | }; | 108 | }; |
109 | 109 | ||
110 | struct dhcp_scan_state { | ||
111 | int overload; | ||
112 | int rem; | ||
113 | uint8_t *optionptr; | ||
114 | }; | ||
115 | |||
110 | /* DHCP option codes (partial list). See RFC 2132 and | 116 | /* DHCP option codes (partial list). See RFC 2132 and |
111 | * http://www.iana.org/assignments/bootp-dhcp-parameters/ | 117 | * http://www.iana.org/assignments/bootp-dhcp-parameters/ |
112 | * Commented out options are handled by common option machinery, | 118 | * Commented out options are handled by common option machinery, |
@@ -206,6 +212,8 @@ extern const uint8_t dhcp_option_lengths[] ALIGN1; | |||
206 | 212 | ||
207 | unsigned FAST_FUNC udhcp_option_idx(const char *name, const char *option_strings); | 213 | unsigned FAST_FUNC udhcp_option_idx(const char *name, const char *option_strings); |
208 | 214 | ||
215 | void init_scan_state(struct dhcp_packet *packet, struct dhcp_scan_state *scan_state) FAST_FUNC; | ||
216 | uint8_t *udhcp_scan_options(struct dhcp_packet *packet, struct dhcp_scan_state *scan_state) FAST_FUNC; | ||
209 | uint8_t *udhcp_get_option(struct dhcp_packet *packet, int code) FAST_FUNC; | 217 | uint8_t *udhcp_get_option(struct dhcp_packet *packet, int code) FAST_FUNC; |
210 | /* Same as above + ensures that option length is 4 bytes | 218 | /* Same as above + ensures that option length is 4 bytes |
211 | * (returns NULL if size is different) | 219 | * (returns NULL if size is different) |
@@ -218,7 +226,7 @@ void udhcp_add_simple_option(struct dhcp_packet *packet, uint8_t code, uint32_t | |||
218 | #endif | 226 | #endif |
219 | #if ENABLE_FEATURE_UDHCP_RFC3397 || ENABLE_FEATURE_UDHCPC6_RFC3646 || ENABLE_FEATURE_UDHCPC6_RFC4704 | 227 | #if ENABLE_FEATURE_UDHCP_RFC3397 || ENABLE_FEATURE_UDHCPC6_RFC3646 || ENABLE_FEATURE_UDHCPC6_RFC4704 |
220 | char *dname_dec(const uint8_t *cstr, int clen, const char *pre) FAST_FUNC; | 228 | char *dname_dec(const uint8_t *cstr, int clen, const char *pre) FAST_FUNC; |
221 | uint8_t *dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen) FAST_FUNC; | 229 | uint8_t *dname_enc(/*const uint8_t *cstr, int clen,*/ const char *src, int *retlen) FAST_FUNC; |
222 | #endif | 230 | #endif |
223 | struct option_set *udhcp_find_option(struct option_set *opt_list, uint8_t code) FAST_FUNC; | 231 | struct option_set *udhcp_find_option(struct option_set *opt_list, uint8_t code) FAST_FUNC; |
224 | 232 | ||
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 85c410a7c..fc2d672b7 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c | |||
@@ -553,11 +553,15 @@ static int d6_mcast_from_client_data_ifindex(struct d6_packet *packet, uint8_t * | |||
553 | 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 553 | 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
554 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, | 554 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, |
555 | }; | 555 | }; |
556 | /* IPv6 requires different multicast contents in Ethernet Frame (RFC 2464) */ | ||
557 | static const uint8_t MAC_DHCP6MCAST_ADDR[6] ALIGN2 = { | ||
558 | 0x33, 0x33, 0x00, 0x01, 0x00, 0x02, | ||
559 | }; | ||
556 | 560 | ||
557 | return d6_send_raw_packet( | 561 | return d6_send_raw_packet( |
558 | packet, (end - (uint8_t*) packet), | 562 | packet, (end - (uint8_t*) packet), |
559 | /*src*/ &client6_data.ll_ip6, CLIENT_PORT6, | 563 | /*src*/ &client6_data.ll_ip6, CLIENT_PORT6, |
560 | /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_BCAST_ADDR, | 564 | /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_DHCP6MCAST_ADDR, |
561 | client_data.ifindex | 565 | client_data.ifindex |
562 | ); | 566 | ); |
563 | } | 567 | } |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 5a1f8fd7a..50dfead63 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -159,61 +159,27 @@ static int mton(uint32_t mask) | |||
159 | } | 159 | } |
160 | 160 | ||
161 | #if ENABLE_FEATURE_UDHCPC_SANITIZEOPT | 161 | #if ENABLE_FEATURE_UDHCPC_SANITIZEOPT |
162 | /* Check if a given label represents a valid DNS label | 162 | /* Check if a given name represents a valid DNS name */ |
163 | * Return pointer to the first character after the label | 163 | /* See RFC1035, 2.3.1 */ |
164 | * (NUL or dot) upon success, NULL otherwise. | ||
165 | * See RFC1035, 2.3.1 | ||
166 | */ | ||
167 | /* We don't need to be particularly anal. For example, allowing _, hyphen | 164 | /* We don't need to be particularly anal. For example, allowing _, hyphen |
168 | * at the end, or leading and trailing dots would be ok, since it | 165 | * at the end, or leading and trailing dots would be ok, since it |
169 | * can't be used for attacks. (Leading hyphen can be, if someone uses | 166 | * can't be used for attacks. (Leading hyphen can be, if someone uses cmd "$hostname" |
170 | * cmd "$hostname" | ||
171 | * in the script: then hostname may be treated as an option) | 167 | * in the script: then hostname may be treated as an option) |
172 | */ | 168 | */ |
173 | static const char *valid_domain_label(const char *label) | ||
174 | { | ||
175 | unsigned char ch; | ||
176 | //unsigned pos = 0; | ||
177 | |||
178 | if (label[0] == '-') | ||
179 | return NULL; | ||
180 | for (;;) { | ||
181 | ch = *label; | ||
182 | if ((ch|0x20) < 'a' || (ch|0x20) > 'z') { | ||
183 | if (ch < '0' || ch > '9') { | ||
184 | if (ch == '\0' || ch == '.') | ||
185 | return label; | ||
186 | /* DNS allows only '-', but we are more permissive */ | ||
187 | if (ch != '-' && ch != '_') | ||
188 | return NULL; | ||
189 | } | ||
190 | } | ||
191 | label++; | ||
192 | //pos++; | ||
193 | //Do we want this? | ||
194 | //if (pos > 63) /* NS_MAXLABEL; labels must be 63 chars or less */ | ||
195 | // return NULL; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | /* Check if a given name represents a valid DNS name */ | ||
200 | /* See RFC1035, 2.3.1 */ | ||
201 | static int good_hostname(const char *name) | 169 | static int good_hostname(const char *name) |
202 | { | 170 | { |
203 | //const char *start = name; | 171 | if (*name == '-') /* Can't start with '-' */ |
204 | 172 | return 0; | |
205 | for (;;) { | 173 | |
206 | name = valid_domain_label(name); | 174 | while (*name) { |
207 | if (!name) | 175 | unsigned char ch = *name++; |
208 | return 0; | 176 | if (!isalnum(ch)) |
209 | if (!name[0]) | 177 | /* DNS allows only '-', but we are more permissive */ |
210 | return 1; | 178 | if (ch != '-' && ch != '_' && ch != '.') |
211 | //Do we want this? | 179 | return 0; |
212 | //return ((name - start) < 1025); /* NS_MAXDNAME */ | 180 | // TODO: do we want to validate lengths against NS_MAXLABEL and NS_MAXDNAME? |
213 | name++; | ||
214 | if (*name == '\0') | ||
215 | return 1; // We allow trailing dot too | ||
216 | } | 181 | } |
182 | return 1; | ||
217 | } | 183 | } |
218 | #else | 184 | #else |
219 | # define good_hostname(name) 1 | 185 | # define good_hostname(name) 1 |
@@ -242,9 +208,8 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
242 | case OPTION_IP: | 208 | case OPTION_IP: |
243 | case OPTION_IP_PAIR: | 209 | case OPTION_IP_PAIR: |
244 | dest += sprint_nip(dest, "", option); | 210 | dest += sprint_nip(dest, "", option); |
245 | if (type == OPTION_IP) | 211 | if (type == OPTION_IP_PAIR) |
246 | break; | 212 | dest += sprint_nip(dest, "/", option + 4); |
247 | dest += sprint_nip(dest, "/", option + 4); | ||
248 | break; | 213 | break; |
249 | // case OPTION_BOOLEAN: | 214 | // case OPTION_BOOLEAN: |
250 | // dest += sprintf(dest, *option ? "yes" : "no"); | 215 | // dest += sprintf(dest, *option ? "yes" : "no"); |
@@ -346,7 +311,7 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
346 | * IPv4MaskLen <= 32, | 311 | * IPv4MaskLen <= 32, |
347 | * 6rdPrefixLen <= 128, | 312 | * 6rdPrefixLen <= 128, |
348 | * 6rdPrefixLen + (32 - IPv4MaskLen) <= 128 | 313 | * 6rdPrefixLen + (32 - IPv4MaskLen) <= 128 |
349 | * (2nd condition need no check - it follows from 1st and 3rd). | 314 | * (2nd condition needs no check - it follows from 1st and 3rd). |
350 | * Else, return envvar with empty value ("optname=") | 315 | * Else, return envvar with empty value ("optname=") |
351 | */ | 316 | */ |
352 | if (len >= (1 + 1 + 16 + 4) | 317 | if (len >= (1 + 1 + 16 + 4) |
@@ -360,17 +325,12 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
360 | /* 6rdPrefix */ | 325 | /* 6rdPrefix */ |
361 | dest += sprint_nip6(dest, /* "", */ option); | 326 | dest += sprint_nip6(dest, /* "", */ option); |
362 | option += 16; | 327 | option += 16; |
363 | len -= 1 + 1 + 16 + 4; | 328 | len -= 1 + 1 + 16; |
364 | /* "+ 4" above corresponds to the length of IPv4 addr | 329 | *dest++ = ' '; |
365 | * we consume in the loop below */ | 330 | /* 6rdBRIPv4Address(es), use common IPv4 logic to process them */ |
366 | while (1) { | 331 | type = OPTION_IP; |
367 | /* 6rdBRIPv4Address(es) */ | 332 | optlen = 4; |
368 | dest += sprint_nip(dest, " ", option); | 333 | continue; |
369 | option += 4; | ||
370 | len -= 4; /* do we have yet another 4+ bytes? */ | ||
371 | if (len < 0) | ||
372 | break; /* no */ | ||
373 | } | ||
374 | } | 334 | } |
375 | 335 | ||
376 | return ret; | 336 | return ret; |
@@ -392,23 +352,18 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
392 | */ | 352 | */ |
393 | option++; | 353 | option++; |
394 | len--; | 354 | len--; |
355 | if (option[-1] == 1) { | ||
356 | /* use common IPv4 logic to process IP addrs */ | ||
357 | type = OPTION_IP; | ||
358 | optlen = 4; | ||
359 | continue; | ||
360 | } | ||
395 | if (option[-1] == 0) { | 361 | if (option[-1] == 0) { |
396 | dest = dname_dec(option, len, ret); | 362 | dest = dname_dec(option, len, ret); |
397 | if (dest) { | 363 | if (dest) { |
398 | free(ret); | 364 | free(ret); |
399 | return dest; | 365 | return dest; |
400 | } | 366 | } |
401 | } else | ||
402 | if (option[-1] == 1) { | ||
403 | const char *pfx = ""; | ||
404 | while (1) { | ||
405 | len -= 4; | ||
406 | if (len < 0) | ||
407 | break; | ||
408 | dest += sprint_nip(dest, pfx, option); | ||
409 | pfx = " "; | ||
410 | option += 4; | ||
411 | } | ||
412 | } | 367 | } |
413 | return ret; | 368 | return ret; |
414 | #endif | 369 | #endif |
@@ -431,59 +386,78 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
431 | return ret; | 386 | return ret; |
432 | } | 387 | } |
433 | 388 | ||
434 | /* put all the parameters into the environment */ | 389 | static void putenvp(llist_t **envp, char *new_opt) |
435 | static char **fill_envp(struct dhcp_packet *packet) | 390 | { |
391 | putenv(new_opt); | ||
392 | log2(" %s", new_opt); | ||
393 | llist_add_to(envp, new_opt); | ||
394 | } | ||
395 | |||
396 | static const char* get_optname(uint8_t code, const struct dhcp_optflag **dh) | ||
436 | { | 397 | { |
437 | int envc; | 398 | /* Find the option: |
438 | int i; | 399 | * dhcp_optflags is sorted so we stop searching when dh->code >= code, which is faster |
439 | char **envp, **curr; | 400 | * than iterating over the entire array. |
440 | const char *opt_name; | 401 | * Options which don't have a match in dhcp_option_strings[], e.g DHCP_REQUESTED_IP, |
441 | uint8_t *temp; | 402 | * are located after the sorted array, so these entries will never be reached |
442 | uint8_t overload = 0; | 403 | * and they'll count as unknown options. |
443 | |||
444 | #define BITMAP unsigned | ||
445 | #define BBITS (sizeof(BITMAP) * 8) | ||
446 | #define BMASK(i) (1 << (i & (sizeof(BITMAP) * 8 - 1))) | ||
447 | #define FOUND_OPTS(i) (found_opts[(unsigned)i / BBITS]) | ||
448 | BITMAP found_opts[256 / BBITS]; | ||
449 | |||
450 | memset(found_opts, 0, sizeof(found_opts)); | ||
451 | |||
452 | /* We need 7 elements for: | ||
453 | * "interface=IFACE" | ||
454 | * "ip=N.N.N.N" from packet->yiaddr | ||
455 | * "giaddr=IP" from packet->gateway_nip (unless 0) | ||
456 | * "siaddr=IP" from packet->siaddr_nip (unless 0) | ||
457 | * "boot_file=FILE" from packet->file (unless overloaded) | ||
458 | * "sname=SERVER_HOSTNAME" from packet->sname (unless overloaded) | ||
459 | * terminating NULL | ||
460 | */ | 404 | */ |
461 | envc = 7; | 405 | for (*dh = dhcp_optflags; (*dh)->code && (*dh)->code < code; (*dh)++) |
462 | /* +1 element for each option, +2 for subnet option: */ | 406 | continue; |
463 | if (packet) { | 407 | |
464 | /* note: do not search for "pad" (0) and "end" (255) options */ | 408 | if ((*dh)->code == code) |
465 | //TODO: change logic to scan packet _once_ | 409 | return nth_string(dhcp_option_strings, (*dh - dhcp_optflags)); |
466 | for (i = 1; i < 255; i++) { | 410 | |
467 | temp = udhcp_get_option(packet, i); | 411 | return NULL; |
468 | if (temp) { | 412 | } |
469 | if (i == DHCP_OPTION_OVERLOAD) | 413 | |
470 | overload |= *temp; | 414 | /* put all the parameters into the environment */ |
471 | else if (i == DHCP_SUBNET) | 415 | static llist_t *fill_envp(struct dhcp_packet *packet) |
472 | envc++; /* for $mask */ | 416 | { |
473 | envc++; | 417 | uint8_t *optptr; |
474 | /*if (i != DHCP_MESSAGE_TYPE)*/ | 418 | struct dhcp_scan_state scan_state; |
475 | FOUND_OPTS(i) |= BMASK(i); | 419 | char *new_opt; |
476 | } | 420 | llist_t *envp = NULL; |
477 | } | ||
478 | } | ||
479 | curr = envp = xzalloc(sizeof(envp[0]) * envc); | ||
480 | 421 | ||
481 | *curr = xasprintf("interface=%s", client_data.interface); | 422 | putenvp(&envp, xasprintf("interface=%s", client_data.interface)); |
482 | putenv(*curr++); | ||
483 | 423 | ||
484 | if (!packet) | 424 | if (!packet) |
485 | return envp; | 425 | return envp; |
486 | 426 | ||
427 | init_scan_state(packet, &scan_state); | ||
428 | |||
429 | /* Iterate over the packet options. | ||
430 | * Handle each option based on whether it's an unknown / known option. | ||
431 | * There may be (although unlikely) duplicate options. For now, only the last | ||
432 | * appearing option will be stored in the environment, and all duplicates | ||
433 | * are freed properly. | ||
434 | * Long options may be implemented in the future (see RFC 3396) if needed. | ||
435 | */ | ||
436 | while ((optptr = udhcp_scan_options(packet, &scan_state)) != NULL) { | ||
437 | const struct dhcp_optflag *dh; | ||
438 | const char *opt_name; | ||
439 | uint8_t code = optptr[OPT_CODE]; | ||
440 | uint8_t len = optptr[OPT_LEN]; | ||
441 | uint8_t *data = optptr + OPT_DATA; | ||
442 | |||
443 | opt_name = get_optname(code, &dh); | ||
444 | if (opt_name) { | ||
445 | new_opt = xmalloc_optname_optval(data, dh, opt_name); | ||
446 | if (code == DHCP_SUBNET && len == 4) { | ||
447 | uint32_t subnet; | ||
448 | putenvp(&envp, new_opt); | ||
449 | move_from_unaligned32(subnet, data); | ||
450 | new_opt = xasprintf("mask=%u", mton(subnet)); | ||
451 | } | ||
452 | } else { | ||
453 | unsigned ofs; | ||
454 | new_opt = xmalloc(sizeof("optNNN=") + 1 + len*2); | ||
455 | ofs = sprintf(new_opt, "opt%u=", code); | ||
456 | bin2hex(new_opt + ofs, (char *)data, len)[0] = '\0'; | ||
457 | } | ||
458 | putenvp(&envp, new_opt); | ||
459 | } | ||
460 | |||
487 | /* Export BOOTP fields. Fields we don't (yet?) export: | 461 | /* Export BOOTP fields. Fields we don't (yet?) export: |
488 | * uint8_t op; // always BOOTREPLY | 462 | * uint8_t op; // always BOOTREPLY |
489 | * uint8_t htype; // hardware address type. 1 = 10mb ethernet | 463 | * uint8_t htype; // hardware address type. 1 = 10mb ethernet |
@@ -497,77 +471,31 @@ static char **fill_envp(struct dhcp_packet *packet) | |||
497 | * uint8_t chaddr[16]; // link-layer client hardware address (MAC) | 471 | * uint8_t chaddr[16]; // link-layer client hardware address (MAC) |
498 | */ | 472 | */ |
499 | /* Most important one: yiaddr as $ip */ | 473 | /* Most important one: yiaddr as $ip */ |
500 | *curr = xmalloc(sizeof("ip=255.255.255.255")); | 474 | new_opt = xmalloc(sizeof("ip=255.255.255.255")); |
501 | sprint_nip(*curr, "ip=", (uint8_t *) &packet->yiaddr); | 475 | sprint_nip(new_opt, "ip=", (uint8_t *) &packet->yiaddr); |
502 | putenv(*curr++); | 476 | putenvp(&envp, new_opt); |
477 | |||
503 | if (packet->siaddr_nip) { | 478 | if (packet->siaddr_nip) { |
504 | /* IP address of next server to use in bootstrap */ | 479 | /* IP address of next server to use in bootstrap */ |
505 | *curr = xmalloc(sizeof("siaddr=255.255.255.255")); | 480 | new_opt = xmalloc(sizeof("siaddr=255.255.255.255")); |
506 | sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip); | 481 | sprint_nip(new_opt, "siaddr=", (uint8_t *) &packet->siaddr_nip); |
507 | putenv(*curr++); | 482 | putenvp(&envp, new_opt); |
508 | } | 483 | } |
509 | if (packet->gateway_nip) { | 484 | if (packet->gateway_nip) { |
510 | /* IP address of DHCP relay agent */ | 485 | /* IP address of DHCP relay agent */ |
511 | *curr = xmalloc(sizeof("giaddr=255.255.255.255")); | 486 | new_opt = xmalloc(sizeof("giaddr=255.255.255.255")); |
512 | sprint_nip(*curr, "giaddr=", (uint8_t *) &packet->gateway_nip); | 487 | sprint_nip(new_opt, "giaddr=", (uint8_t *) &packet->gateway_nip); |
513 | putenv(*curr++); | 488 | putenvp(&envp, new_opt); |
514 | } | 489 | } |
515 | if (!(overload & FILE_FIELD) && packet->file[0]) { | 490 | if (!(scan_state.overload & FILE_FIELD) && packet->file[0]) { |
516 | /* watch out for invalid packets */ | 491 | /* watch out for invalid packets */ |
517 | *curr = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file); | 492 | new_opt = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file); |
518 | putenv(*curr++); | 493 | putenvp(&envp, new_opt); |
519 | } | 494 | } |
520 | if (!(overload & SNAME_FIELD) && packet->sname[0]) { | 495 | if (!(scan_state.overload & SNAME_FIELD) && packet->sname[0]) { |
521 | /* watch out for invalid packets */ | 496 | /* watch out for invalid packets */ |
522 | *curr = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname); | 497 | new_opt = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname); |
523 | putenv(*curr++); | 498 | putenvp(&envp, new_opt); |
524 | } | ||
525 | |||
526 | /* Export known DHCP options */ | ||
527 | opt_name = dhcp_option_strings; | ||
528 | i = 0; | ||
529 | while (*opt_name) { | ||
530 | uint8_t code = dhcp_optflags[i].code; | ||
531 | BITMAP *found_ptr = &FOUND_OPTS(code); | ||
532 | BITMAP found_mask = BMASK(code); | ||
533 | if (!(*found_ptr & found_mask)) | ||
534 | goto next; | ||
535 | *found_ptr &= ~found_mask; /* leave only unknown options */ | ||
536 | temp = udhcp_get_option(packet, code); | ||
537 | *curr = xmalloc_optname_optval(temp, &dhcp_optflags[i], opt_name); | ||
538 | putenv(*curr++); | ||
539 | if (code == DHCP_SUBNET && temp[-OPT_DATA + OPT_LEN] == 4) { | ||
540 | /* Subnet option: make things like "$ip/$mask" possible */ | ||
541 | uint32_t subnet; | ||
542 | move_from_unaligned32(subnet, temp); | ||
543 | *curr = xasprintf("mask=%u", mton(subnet)); | ||
544 | putenv(*curr++); | ||
545 | } | ||
546 | next: | ||
547 | opt_name += strlen(opt_name) + 1; | ||
548 | i++; | ||
549 | } | ||
550 | /* Export unknown options */ | ||
551 | for (i = 0; i < 256;) { | ||
552 | BITMAP bitmap = FOUND_OPTS(i); | ||
553 | if (!bitmap) { | ||
554 | i += BBITS; | ||
555 | continue; | ||
556 | } | ||
557 | if (bitmap & BMASK(i)) { | ||
558 | unsigned len, ofs; | ||
559 | |||
560 | temp = udhcp_get_option(packet, i); | ||
561 | /* udhcp_get_option returns ptr to data portion, | ||
562 | * need to go back to get len | ||
563 | */ | ||
564 | len = temp[-OPT_DATA + OPT_LEN]; | ||
565 | *curr = xmalloc(sizeof("optNNN=") + 1 + len*2); | ||
566 | ofs = sprintf(*curr, "opt%u=", i); | ||
567 | *bin2hex(*curr + ofs, (void*) temp, len) = '\0'; | ||
568 | putenv(*curr++); | ||
569 | } | ||
570 | i++; | ||
571 | } | 499 | } |
572 | 500 | ||
573 | return envp; | 501 | return envp; |
@@ -576,7 +504,7 @@ static char **fill_envp(struct dhcp_packet *packet) | |||
576 | /* Call a script with a par file and env vars */ | 504 | /* Call a script with a par file and env vars */ |
577 | static void udhcp_run_script(struct dhcp_packet *packet, const char *name) | 505 | static void udhcp_run_script(struct dhcp_packet *packet, const char *name) |
578 | { | 506 | { |
579 | char **envp, **curr; | 507 | llist_t *envp; |
580 | char *argv[3]; | 508 | char *argv[3]; |
581 | 509 | ||
582 | envp = fill_envp(packet); | 510 | envp = fill_envp(packet); |
@@ -588,11 +516,8 @@ static void udhcp_run_script(struct dhcp_packet *packet, const char *name) | |||
588 | argv[2] = NULL; | 516 | argv[2] = NULL; |
589 | spawn_and_wait(argv); | 517 | spawn_and_wait(argv); |
590 | 518 | ||
591 | for (curr = envp; *curr; curr++) { | 519 | /* Free all allocated environment variables */ |
592 | log2(" %s", *curr); | 520 | llist_free(envp, (void (*)(void *))bb_unsetenv_and_free); |
593 | bb_unsetenv_and_free(*curr); | ||
594 | } | ||
595 | free(envp); | ||
596 | } | 521 | } |
597 | 522 | ||
598 | 523 | ||
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 9d6604943..acfdaa8c3 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
@@ -46,6 +46,12 @@ | |||
46 | #include "dhcpc.h" | 46 | #include "dhcpc.h" |
47 | #include "dhcpd.h" | 47 | #include "dhcpd.h" |
48 | 48 | ||
49 | #if ENABLE_PID_FILE_PATH | ||
50 | #define PID_FILE_PATH CONFIG_PID_FILE_PATH | ||
51 | #else | ||
52 | #define PID_FILE_PATH "/var/run" | ||
53 | #endif | ||
54 | |||
49 | /* globals */ | 55 | /* globals */ |
50 | #define g_leases ((struct dyn_lease*)ptr_to_globals) | 56 | #define g_leases ((struct dyn_lease*)ptr_to_globals) |
51 | /* struct server_data_t server_data is in bb_common_bufsiz1 */ | 57 | /* struct server_data_t server_data is in bb_common_bufsiz1 */ |
@@ -406,7 +412,7 @@ static const struct config_keyword keywords[] = { | |||
406 | {"offer_time" , read_u32 , OFS(offer_time ), "60"}, | 412 | {"offer_time" , read_u32 , OFS(offer_time ), "60"}, |
407 | {"min_lease" , read_u32 , OFS(min_lease_sec), "60"}, | 413 | {"min_lease" , read_u32 , OFS(min_lease_sec), "60"}, |
408 | {"lease_file" , read_str , OFS(lease_file ), LEASES_FILE}, | 414 | {"lease_file" , read_str , OFS(lease_file ), LEASES_FILE}, |
409 | {"pidfile" , read_str , OFS(pidfile ), "/var/run/udhcpd.pid"}, | 415 | {"pidfile" , read_str , OFS(pidfile ), PID_FILE_PATH "/udhcpd.pid"}, |
410 | {"siaddr" , udhcp_str2nip , OFS(siaddr_nip ), "0.0.0.0"}, | 416 | {"siaddr" , udhcp_str2nip , OFS(siaddr_nip ), "0.0.0.0"}, |
411 | /* keywords with no defaults must be last! */ | 417 | /* keywords with no defaults must be last! */ |
412 | {"option" , read_optset , OFS(options ), ""}, | 418 | {"option" , read_optset , OFS(options ), ""}, |
diff --git a/networking/udhcp/domain_codec.c b/networking/udhcp/domain_codec.c index b7a3a5353..752c0a863 100644 --- a/networking/udhcp/domain_codec.c +++ b/networking/udhcp/domain_codec.c | |||
@@ -109,11 +109,11 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre) | |||
109 | return ret; | 109 | return ret; |
110 | } | 110 | } |
111 | 111 | ||
112 | /* Convert a domain name (src) from human-readable "foo.blah.com" format into | 112 | /* Convert a domain name (src) from human-readable "foo.BLAH.com" format into |
113 | * RFC1035 encoding "\003foo\004blah\003com\000". Return allocated string, or | 113 | * RFC1035 encoding "\003foo\004blah\003com\000". Return allocated string, or |
114 | * NULL if an error occurs. | 114 | * NULL if an error occurs. |
115 | */ | 115 | */ |
116 | static uint8_t *convert_dname(const char *src) | 116 | static uint8_t *convert_dname(const char *src, int *retlen) |
117 | { | 117 | { |
118 | uint8_t c, *res, *lenptr, *dst; | 118 | uint8_t c, *res, *lenptr, *dst; |
119 | int len; | 119 | int len; |
@@ -129,6 +129,7 @@ static uint8_t *convert_dname(const char *src) | |||
129 | /* label too long, too short, or two '.'s in a row? abort */ | 129 | /* label too long, too short, or two '.'s in a row? abort */ |
130 | if (len > NS_MAXLABEL || len == 0 || (c == '.' && *src == '.')) { | 130 | if (len > NS_MAXLABEL || len == 0 || (c == '.' && *src == '.')) { |
131 | free(res); | 131 | free(res); |
132 | *retlen = 0; | ||
132 | return NULL; | 133 | return NULL; |
133 | } | 134 | } |
134 | *lenptr = len; | 135 | *lenptr = len; |
@@ -144,13 +145,16 @@ static uint8_t *convert_dname(const char *src) | |||
144 | 145 | ||
145 | if (dst - res >= NS_MAXCDNAME) { /* dname too long? abort */ | 146 | if (dst - res >= NS_MAXCDNAME) { /* dname too long? abort */ |
146 | free(res); | 147 | free(res); |
148 | *retlen = 0; | ||
147 | return NULL; | 149 | return NULL; |
148 | } | 150 | } |
149 | 151 | ||
150 | *dst = 0; | 152 | *dst++ = 0; |
153 | *retlen = dst - res; | ||
151 | return res; | 154 | return res; |
152 | } | 155 | } |
153 | 156 | ||
157 | #if 0 //UNUSED | ||
154 | /* Returns the offset within cstr at which dname can be found, or -1 */ | 158 | /* Returns the offset within cstr at which dname can be found, or -1 */ |
155 | static int find_offset(const uint8_t *cstr, int clen, const uint8_t *dname) | 159 | static int find_offset(const uint8_t *cstr, int clen, const uint8_t *dname) |
156 | { | 160 | { |
@@ -188,28 +192,27 @@ static int find_offset(const uint8_t *cstr, int clen, const uint8_t *dname) | |||
188 | 192 | ||
189 | return -1; | 193 | return -1; |
190 | } | 194 | } |
195 | #endif | ||
191 | 196 | ||
197 | uint8_t* FAST_FUNC dname_enc(/*const uint8_t *cstr, int clen,*/ const char *src, int *retlen) | ||
198 | { | ||
199 | #if 0 //UNUSED, was intended for long, repetitive DHCP_DOMAIN_SEARCH options? | ||
200 | uint8_t *d, *dname; | ||
192 | /* Computes string to be appended to cstr so that src would be added to | 201 | /* Computes string to be appended to cstr so that src would be added to |
193 | * the compression (best case, it's a 2-byte pointer to some offset within | 202 | * the compression (best case, it's a 2-byte pointer to some offset within |
194 | * cstr; worst case, it's all of src, converted to <4>host<3>com<0> format). | 203 | * cstr; worst case, it's all of src, converted to <4>host<3>com<0> format). |
195 | * The computed string is returned directly; its length is returned via retlen; | 204 | * The computed string is returned directly; its length is returned via retlen; |
196 | * NULL and 0, respectively, are returned if an error occurs. | 205 | * NULL and 0, respectively, are returned if an error occurs. |
197 | */ | 206 | */ |
198 | uint8_t* FAST_FUNC dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen) | 207 | dname = convert_dname(src, retlen); |
199 | { | ||
200 | uint8_t *d, *dname; | ||
201 | int off; | ||
202 | |||
203 | dname = convert_dname(src); | ||
204 | if (dname == NULL) { | 208 | if (dname == NULL) { |
205 | *retlen = 0; | ||
206 | return NULL; | 209 | return NULL; |
207 | } | 210 | } |
208 | 211 | ||
209 | d = dname; | 212 | d = dname; |
210 | while (*d) { | 213 | while (*d) { |
211 | if (cstr) { | 214 | if (cstr) { |
212 | off = find_offset(cstr, clen, d); | 215 | int off = find_offset(cstr, clen, d); |
213 | if (off >= 0) { /* found a match, add pointer and return */ | 216 | if (off >= 0) { /* found a match, add pointer and return */ |
214 | *d++ = NS_CMPRSFLGS | (off >> 8); | 217 | *d++ = NS_CMPRSFLGS | (off >> 8); |
215 | *d = off; | 218 | *d = off; |
@@ -221,6 +224,8 @@ uint8_t* FAST_FUNC dname_enc(const uint8_t *cstr, int clen, const char *src, int | |||
221 | 224 | ||
222 | *retlen = d - dname + 1; | 225 | *retlen = d - dname + 1; |
223 | return dname; | 226 | return dname; |
227 | #endif | ||
228 | return convert_dname(src, retlen); | ||
224 | } | 229 | } |
225 | 230 | ||
226 | #ifdef DNS_COMPR_TESTING | 231 | #ifdef DNS_COMPR_TESTING |
diff --git a/networking/wget.c b/networking/wget.c index bc237c4a8..8a967fe20 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
@@ -679,7 +679,8 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) | |||
679 | pid = xvfork(); | 679 | pid = xvfork(); |
680 | if (pid == 0) { | 680 | if (pid == 0) { |
681 | /* Child */ | 681 | /* Child */ |
682 | char *argv[9]; | 682 | char *argv[13]; |
683 | char **argp; | ||
683 | 684 | ||
684 | close(sp[0]); | 685 | close(sp[0]); |
685 | xmove_fd(sp[1], 0); | 686 | xmove_fd(sp[1], 0); |
@@ -702,13 +703,25 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) | |||
702 | * TLS server_name (SNI) field are FQDNs (DNS hostnames). | 703 | * TLS server_name (SNI) field are FQDNs (DNS hostnames). |
703 | * IPv4 and IPv6 addresses, port numbers are not allowed. | 704 | * IPv4 and IPv6 addresses, port numbers are not allowed. |
704 | */ | 705 | */ |
706 | argp = &argv[5]; | ||
705 | if (!is_ip_address(servername)) { | 707 | if (!is_ip_address(servername)) { |
706 | argv[5] = (char*)"-servername"; | 708 | *argp++ = (char*)"-servername"; //[5] |
707 | argv[6] = (char*)servername; | 709 | *argp++ = (char*)servername; //[6] |
708 | } | 710 | } |
709 | if (!(option_mask32 & WGET_OPT_NO_CHECK_CERT)) { | 711 | if (!(option_mask32 & WGET_OPT_NO_CHECK_CERT)) { |
710 | argv[7] = (char*)"-verify_return_error"; | 712 | /* Abort on bad server certificate */ |
713 | *argp++ = (char*)"-verify"; //[7] | ||
714 | *argp++ = (char*)"100"; //[8] | ||
715 | *argp++ = (char*)"-verify_return_error"; //[9] | ||
716 | if (!is_ip_address(servername)) { | ||
717 | *argp++ = (char*)"-verify_hostname"; //[10] | ||
718 | *argp++ = (char*)servername; //[11] | ||
719 | } else { | ||
720 | *argp++ = (char*)"-verify_ip"; //[10] | ||
721 | *argp++ = (char*)host; //[11] | ||
722 | } | ||
711 | } | 723 | } |
724 | //[12] (or earlier) is NULL terminator | ||
712 | 725 | ||
713 | BB_EXECVP(argv[0], argv); | 726 | BB_EXECVP(argv[0], argv); |
714 | xmove_fd(3, 2); | 727 | xmove_fd(3, 2); |
diff --git a/procps/nmeter.c b/procps/nmeter.c index ae16d8548..856ce0202 100644 --- a/procps/nmeter.c +++ b/procps/nmeter.c | |||
@@ -37,6 +37,7 @@ | |||
37 | //usage: "\n %[pn] # of processes" | 37 | //usage: "\n %[pn] # of processes" |
38 | //usage: "\n %b Block io" | 38 | //usage: "\n %b Block io" |
39 | //usage: "\n %Nt Time (with N decimal points)" | 39 | //usage: "\n %Nt Time (with N decimal points)" |
40 | //usage: "\n %NT Zero-based timestamp (with N decimal points)" | ||
40 | //usage: "\n %r Print <cr> instead of <lf> at EOL" | 41 | //usage: "\n %r Print <cr> instead of <lf> at EOL" |
41 | 42 | ||
42 | //TODO: | 43 | //TODO: |
@@ -88,6 +89,7 @@ struct globals { | |||
88 | int delta; | 89 | int delta; |
89 | unsigned deltanz; | 90 | unsigned deltanz; |
90 | struct timeval tv; | 91 | struct timeval tv; |
92 | struct timeval start; | ||
91 | #define first_proc_file proc_stat | 93 | #define first_proc_file proc_stat |
92 | proc_file proc_stat; // Must match the order of proc_name's! | 94 | proc_file proc_stat; // Must match the order of proc_name's! |
93 | proc_file proc_loadavg; | 95 | proc_file proc_loadavg; |
@@ -101,7 +103,6 @@ struct globals { | |||
101 | #define is26 (G.is26 ) | 103 | #define is26 (G.is26 ) |
102 | #define need_seconds (G.need_seconds ) | 104 | #define need_seconds (G.need_seconds ) |
103 | #define cur_outbuf (G.cur_outbuf ) | 105 | #define cur_outbuf (G.cur_outbuf ) |
104 | #define tv (G.tv ) | ||
105 | #define proc_stat (G.proc_stat ) | 106 | #define proc_stat (G.proc_stat ) |
106 | #define proc_loadavg (G.proc_loadavg ) | 107 | #define proc_loadavg (G.proc_loadavg ) |
107 | #define proc_net_dev (G.proc_net_dev ) | 108 | #define proc_net_dev (G.proc_net_dev ) |
@@ -754,25 +755,53 @@ S_STAT(time_stat) | |||
754 | unsigned scale; | 755 | unsigned scale; |
755 | S_STAT_END(time_stat) | 756 | S_STAT_END(time_stat) |
756 | 757 | ||
757 | static void FAST_FUNC collect_time(time_stat *s) | 758 | static void FAST_FUNC collect_tv(time_stat *s, struct timeval *tv, int local) |
758 | { | 759 | { |
759 | char buf[sizeof("12:34:56.123456")]; | 760 | char buf[sizeof("12:34:56.123456")]; |
760 | struct tm* tm; | 761 | struct tm* tm; |
761 | unsigned us = tv.tv_usec + s->scale/2; | 762 | unsigned us = tv->tv_usec + s->scale/2; |
762 | time_t t = tv.tv_sec; | 763 | time_t t = tv->tv_sec; |
763 | 764 | ||
764 | if (us >= 1000000) { | 765 | if (us >= 1000000) { |
765 | t++; | 766 | t++; |
766 | us -= 1000000; | 767 | us -= 1000000; |
767 | } | 768 | } |
768 | tm = localtime(&t); | 769 | if (local) |
770 | tm = localtime(&t); | ||
771 | else | ||
772 | tm = gmtime(&t); | ||
769 | 773 | ||
770 | sprintf(buf, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); | 774 | sprintf(buf, "%02u:%02u:%02u", tm->tm_hour, tm->tm_min, tm->tm_sec); |
771 | if (s->prec) | 775 | if (s->prec) |
772 | sprintf(buf+8, ".%0*d", s->prec, us / s->scale); | 776 | sprintf(buf+8, ".%0*u", s->prec, us / s->scale); |
773 | put(buf); | 777 | put(buf); |
774 | } | 778 | } |
775 | 779 | ||
780 | static void FAST_FUNC collect_time(time_stat *s) | ||
781 | { | ||
782 | collect_tv(s, &G.tv, /*local:*/ 1); | ||
783 | } | ||
784 | |||
785 | static void FAST_FUNC collect_monotonic(time_stat *s) | ||
786 | { | ||
787 | struct timeval tv_mono; | ||
788 | |||
789 | tv_mono.tv_sec = G.tv.tv_sec - G.start.tv_sec; | ||
790 | #if 0 /* Do we want this? */ | ||
791 | if (tv_mono.tv_sec < 0) { | ||
792 | /* Time went backwards, reset start time to "now" */ | ||
793 | tv_mono.tv_sec = 0; | ||
794 | G.start = G.tv; | ||
795 | } | ||
796 | #endif | ||
797 | tv_mono.tv_usec = G.tv.tv_usec - G.start.tv_usec; | ||
798 | if ((int32_t)tv_mono.tv_usec < 0) { | ||
799 | tv_mono.tv_usec += 1000000; | ||
800 | tv_mono.tv_sec--; | ||
801 | } | ||
802 | collect_tv(s, &tv_mono, /*local:*/ 0); | ||
803 | } | ||
804 | |||
776 | static s_stat* init_time(const char *param) | 805 | static s_stat* init_time(const char *param) |
777 | { | 806 | { |
778 | int prec; | 807 | int prec; |
@@ -789,6 +818,13 @@ static s_stat* init_time(const char *param) | |||
789 | return (s_stat*)s; | 818 | return (s_stat*)s; |
790 | } | 819 | } |
791 | 820 | ||
821 | static s_stat* init_monotonic(const char *param) | ||
822 | { | ||
823 | time_stat *s = (void*)init_time(param); | ||
824 | s->collect = collect_monotonic; | ||
825 | return (s_stat*)s; | ||
826 | } | ||
827 | |||
792 | static void FAST_FUNC collect_info(s_stat *s) | 828 | static void FAST_FUNC collect_info(s_stat *s) |
793 | { | 829 | { |
794 | gen ^= 1; | 830 | gen ^= 1; |
@@ -801,7 +837,7 @@ static void FAST_FUNC collect_info(s_stat *s) | |||
801 | 837 | ||
802 | typedef s_stat* init_func(const char *param); | 838 | typedef s_stat* init_func(const char *param); |
803 | 839 | ||
804 | static const char options[] ALIGN1 = "ncmsfixptbr"; | 840 | static const char options[] ALIGN1 = "ncmsfixptTbr"; |
805 | static init_func *const init_functions[] = { | 841 | static init_func *const init_functions[] = { |
806 | init_if, | 842 | init_if, |
807 | init_cpu, | 843 | init_cpu, |
@@ -812,6 +848,7 @@ static init_func *const init_functions[] = { | |||
812 | init_ctx, | 848 | init_ctx, |
813 | init_fork, | 849 | init_fork, |
814 | init_time, | 850 | init_time, |
851 | init_monotonic, | ||
815 | init_blk, | 852 | init_blk, |
816 | init_cr | 853 | init_cr |
817 | }; | 854 | }; |
@@ -913,13 +950,15 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv) | |||
913 | // Generate first samples but do not print them, they're bogus | 950 | // Generate first samples but do not print them, they're bogus |
914 | collect_info(first); | 951 | collect_info(first); |
915 | reset_outbuf(); | 952 | reset_outbuf(); |
953 | |||
916 | if (G.delta >= 0) { | 954 | if (G.delta >= 0) { |
917 | gettimeofday(&tv, NULL); | 955 | gettimeofday(&G.tv, NULL); |
918 | usleep(G.delta > 1000000 ? 1000000 : G.delta - tv.tv_usec % G.deltanz); | 956 | usleep(G.delta > 1000000 ? 1000000 : G.delta - G.tv.tv_usec % G.deltanz); |
919 | } | 957 | } |
920 | 958 | ||
959 | gettimeofday(&G.start, NULL); | ||
960 | G.tv = G.start; | ||
921 | while (1) { | 961 | while (1) { |
922 | gettimeofday(&tv, NULL); | ||
923 | collect_info(first); | 962 | collect_info(first); |
924 | put_c(G.final_char); | 963 | put_c(G.final_char); |
925 | print_outbuf(); | 964 | print_outbuf(); |
@@ -932,11 +971,11 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv) | |||
932 | if (G.delta >= 0) { | 971 | if (G.delta >= 0) { |
933 | int rem; | 972 | int rem; |
934 | // can be commented out, will sacrifice sleep time precision a bit | 973 | // can be commented out, will sacrifice sleep time precision a bit |
935 | gettimeofday(&tv, NULL); | 974 | gettimeofday(&G.tv, NULL); |
936 | if (need_seconds) | 975 | if (need_seconds) |
937 | rem = G.delta - ((ullong)tv.tv_sec*1000000 + tv.tv_usec) % G.deltanz; | 976 | rem = G.delta - ((ullong)G.tv.tv_sec*1000000 + G.tv.tv_usec) % G.deltanz; |
938 | else | 977 | else |
939 | rem = G.delta - (unsigned)tv.tv_usec % G.deltanz; | 978 | rem = G.delta - (unsigned)G.tv.tv_usec % G.deltanz; |
940 | // Sometimes kernel wakes us up just a tiny bit earlier than asked | 979 | // Sometimes kernel wakes us up just a tiny bit earlier than asked |
941 | // Do not go to very short sleep in this case | 980 | // Do not go to very short sleep in this case |
942 | if (rem < (unsigned)G.delta / 128) { | 981 | if (rem < (unsigned)G.delta / 128) { |
@@ -944,6 +983,7 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv) | |||
944 | } | 983 | } |
945 | usleep(rem); | 984 | usleep(rem); |
946 | } | 985 | } |
986 | gettimeofday(&G.tv, NULL); | ||
947 | } | 987 | } |
948 | 988 | ||
949 | /*return 0;*/ | 989 | /*return 0;*/ |
diff --git a/procps/sysctl.c b/procps/sysctl.c index 6d77185ca..e16b119e9 100644 --- a/procps/sysctl.c +++ b/procps/sysctl.c | |||
@@ -169,13 +169,15 @@ static int sysctl_act_on_setting(char *setting) | |||
169 | 169 | ||
170 | if (fd < 0) { | 170 | if (fd < 0) { |
171 | switch (errno) { | 171 | switch (errno) { |
172 | case EACCES: | ||
173 | /* Happens for write-only settings, e.g. net.ipv6.route.flush */ | ||
174 | goto end; | ||
175 | case ENOENT: | 172 | case ENOENT: |
176 | if (option_mask32 & FLAG_SHOW_KEY_ERRORS) | 173 | if (option_mask32 & FLAG_SHOW_KEY_ERRORS) |
177 | bb_error_msg("error: '%s' is an unknown key", outname); | 174 | bb_error_msg("error: '%s' is an unknown key", outname); |
178 | break; | 175 | break; |
176 | case EACCES: | ||
177 | /* Happens for write-only settings, e.g. net.ipv6.route.flush */ | ||
178 | if (!writing) | ||
179 | goto end; | ||
180 | /* fall through */ | ||
179 | default: | 181 | default: |
180 | bb_perror_msg("error %sing key '%s'", | 182 | bb_perror_msg("error %sing key '%s'", |
181 | writing ? | 183 | writing ? |
@@ -236,6 +238,7 @@ static int sysctl_act_recursive(const char *path) | |||
236 | int retval = 0; | 238 | int retval = 0; |
237 | 239 | ||
238 | if (!(option_mask32 & FLAG_WRITE) | 240 | if (!(option_mask32 & FLAG_WRITE) |
241 | && !strchr(path, '=') /* do not try to resurse on "var=val" */ | ||
239 | && stat(path, &buf) == 0 | 242 | && stat(path, &buf) == 0 |
240 | && S_ISDIR(buf.st_mode) | 243 | && S_ISDIR(buf.st_mode) |
241 | ) { | 244 | ) { |
diff --git a/procps/top.c b/procps/top.c index 5c41e8e10..8d39526ff 100644 --- a/procps/top.c +++ b/procps/top.c | |||
@@ -979,9 +979,11 @@ static unsigned handle_input(unsigned scan_mask, duration_t interval) | |||
979 | IF_FEATURE_TOPMEM(&& scan_mask != TOPMEM_MASK) | 979 | IF_FEATURE_TOPMEM(&& scan_mask != TOPMEM_MASK) |
980 | ) { | 980 | ) { |
981 | scan_mask ^= PSSCAN_TASKS; | 981 | scan_mask ^= PSSCAN_TASKS; |
982 | # if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE | ||
982 | free(prev_hist); | 983 | free(prev_hist); |
983 | prev_hist = NULL; | 984 | prev_hist = NULL; |
984 | prev_hist_count = 0; | 985 | prev_hist_count = 0; |
986 | # endif | ||
985 | continue; | 987 | continue; |
986 | } | 988 | } |
987 | # endif | 989 | # endif |
diff --git a/scripts/randomtest b/scripts/randomtest index 94709a99f..76550d267 100755 --- a/scripts/randomtest +++ b/scripts/randomtest | |||
@@ -113,6 +113,31 @@ if test x"$LIBC" = x"uclibc"; then | |||
113 | echo 'CONFIG_ASH_INTERNAL_GLOB=y' >>.config | 113 | echo 'CONFIG_ASH_INTERNAL_GLOB=y' >>.config |
114 | fi | 114 | fi |
115 | 115 | ||
116 | # If musl | ||
117 | if test x"$LIBC" = x"musl"; then | ||
118 | cat .config \ | ||
119 | | grep -v CONFIG_STATIC \ | ||
120 | | grep -v CONFIG_DEBUG_SANITIZE \ | ||
121 | | grep -v CONFIG_LFS \ | ||
122 | | grep -v CONFIG_EXTRA_COMPAT \ | ||
123 | | grep -v CONFIG_FEATURE_2_4_MODULES \ | ||
124 | | grep -v CONFIG_FEATURE_VI_REGEX_SEARCH \ | ||
125 | | grep -v CONFIG_FEATURE_MOUNT_NFS \ | ||
126 | | grep -v CONFIG_FEATURE_INETD_RPC \ | ||
127 | >.config.new | ||
128 | mv .config.new .config | ||
129 | echo 'CONFIG_STATIC=y' >>.config | ||
130 | # "error: cannot specify -static with -fsanitize=address": | ||
131 | echo '# CONFIG_DEBUG_SANITIZE is not set' >>.config | ||
132 | # with LFS off, uoff_t will have wrong width: | ||
133 | echo 'CONFIG_LFS=y' >>.config | ||
134 | echo '# CONFIG_EXTRA_COMPAT is not set' >>.config | ||
135 | echo '# CONFIG_FEATURE_2_4_MODULES is not set' >>.config | ||
136 | echo '# CONFIG_FEATURE_VI_REGEX_SEARCH is not set' >>.config | ||
137 | echo '# CONFIG_FEATURE_MOUNT_NFS is not set' >>.config | ||
138 | echo '# CONFIG_FEATURE_INETD_RPC is not set' >>.config | ||
139 | fi | ||
140 | |||
116 | # If STATIC, remove some things. | 141 | # If STATIC, remove some things. |
117 | # PAM with static linking is probably pointless | 142 | # PAM with static linking is probably pointless |
118 | # (but I need to try - now I don't have libpam.a on my system, only libpam.so) | 143 | # (but I need to try - now I don't have libpam.a on my system, only libpam.so) |
diff --git a/shell/Config.src b/shell/Config.src index d7623f774..5efbf9995 100644 --- a/shell/Config.src +++ b/shell/Config.src | |||
@@ -17,6 +17,7 @@ choice | |||
17 | config SH_IS_ASH | 17 | config SH_IS_ASH |
18 | depends on !NOMMU | 18 | depends on !NOMMU |
19 | bool "ash" | 19 | bool "ash" |
20 | select SHELL_ASH | ||
20 | help | 21 | help |
21 | Choose ash to be the shell executed by 'sh' name. | 22 | Choose ash to be the shell executed by 'sh' name. |
22 | The ash code will be built into busybox. If you don't select | 23 | The ash code will be built into busybox. If you don't select |
@@ -25,6 +26,7 @@ config SH_IS_ASH | |||
25 | 26 | ||
26 | config SH_IS_HUSH | 27 | config SH_IS_HUSH |
27 | bool "hush" | 28 | bool "hush" |
29 | select SHELL_HUSH | ||
28 | help | 30 | help |
29 | Choose hush to be the shell executed by 'sh' name. | 31 | Choose hush to be the shell executed by 'sh' name. |
30 | The hush code will be built into busybox. If you don't select | 32 | The hush code will be built into busybox. If you don't select |
@@ -57,6 +59,7 @@ choice | |||
57 | config BASH_IS_ASH | 59 | config BASH_IS_ASH |
58 | depends on !NOMMU | 60 | depends on !NOMMU |
59 | bool "ash" | 61 | bool "ash" |
62 | select SHELL_ASH | ||
60 | help | 63 | help |
61 | Choose ash to be the shell executed by 'bash' name. | 64 | Choose ash to be the shell executed by 'bash' name. |
62 | The ash code will be built into busybox. If you don't select | 65 | The ash code will be built into busybox. If you don't select |
@@ -65,6 +68,7 @@ config BASH_IS_ASH | |||
65 | 68 | ||
66 | config BASH_IS_HUSH | 69 | config BASH_IS_HUSH |
67 | bool "hush" | 70 | bool "hush" |
71 | select SHELL_HUSH | ||
68 | help | 72 | help |
69 | Choose hush to be the shell executed by 'bash' name. | 73 | Choose hush to be the shell executed by 'bash' name. |
70 | The hush code will be built into busybox. If you don't select | 74 | The hush code will be built into busybox. If you don't select |
@@ -81,12 +85,12 @@ INSERT | |||
81 | 85 | ||
82 | 86 | ||
83 | comment "Options common to all shells" | 87 | comment "Options common to all shells" |
84 | if ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH | 88 | if SHELL_ASH || SHELL_HUSH |
85 | 89 | ||
86 | config FEATURE_SH_MATH | 90 | config FEATURE_SH_MATH |
87 | bool "POSIX math support" | 91 | bool "POSIX math support" |
88 | default y | 92 | default y |
89 | depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH | 93 | depends on SHELL_ASH || SHELL_HUSH |
90 | help | 94 | help |
91 | Enable math support in the shell via $((...)) syntax. | 95 | Enable math support in the shell via $((...)) syntax. |
92 | 96 | ||
@@ -107,14 +111,14 @@ config FEATURE_SH_MATH_BASE | |||
107 | config FEATURE_SH_EXTRA_QUIET | 111 | config FEATURE_SH_EXTRA_QUIET |
108 | bool "Hide message on interactive shell startup" | 112 | bool "Hide message on interactive shell startup" |
109 | default y | 113 | default y |
110 | depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH | 114 | depends on SHELL_ASH || SHELL_HUSH |
111 | help | 115 | help |
112 | Remove the busybox introduction when starting a shell. | 116 | Remove the busybox introduction when starting a shell. |
113 | 117 | ||
114 | config FEATURE_SH_STANDALONE | 118 | config FEATURE_SH_STANDALONE |
115 | bool "Standalone shell" | 119 | bool "Standalone shell" |
116 | default n | 120 | default n |
117 | depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH | 121 | depends on SHELL_ASH || SHELL_HUSH |
118 | help | 122 | help |
119 | This option causes busybox shells to use busybox applets | 123 | This option causes busybox shells to use busybox applets |
120 | in preference to executables in the PATH whenever possible. For | 124 | in preference to executables in the PATH whenever possible. For |
@@ -135,7 +139,7 @@ config FEATURE_SH_STANDALONE | |||
135 | config FEATURE_SH_NOFORK | 139 | config FEATURE_SH_NOFORK |
136 | bool "Run 'nofork' applets directly" | 140 | bool "Run 'nofork' applets directly" |
137 | default n | 141 | default n |
138 | depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH | 142 | depends on SHELL_ASH || SHELL_HUSH |
139 | help | 143 | help |
140 | This option causes busybox shells to not execute typical | 144 | This option causes busybox shells to not execute typical |
141 | fork/exec/wait sequence, but call <applet>_main directly, | 145 | fork/exec/wait sequence, but call <applet>_main directly, |
@@ -153,14 +157,14 @@ config FEATURE_SH_NOFORK | |||
153 | config FEATURE_SH_READ_FRAC | 157 | config FEATURE_SH_READ_FRAC |
154 | bool "read -t N.NNN support (+110 bytes)" | 158 | bool "read -t N.NNN support (+110 bytes)" |
155 | default y | 159 | default y |
156 | depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH | 160 | depends on SHELL_ASH || SHELL_HUSH |
157 | help | 161 | help |
158 | Enable support for fractional second timeout in read builtin. | 162 | Enable support for fractional second timeout in read builtin. |
159 | 163 | ||
160 | config FEATURE_SH_HISTFILESIZE | 164 | config FEATURE_SH_HISTFILESIZE |
161 | bool "Use $HISTFILESIZE" | 165 | bool "Use $HISTFILESIZE" |
162 | default y | 166 | default y |
163 | depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH | 167 | depends on SHELL_ASH || SHELL_HUSH |
164 | help | 168 | help |
165 | This option makes busybox shells to use $HISTFILESIZE variable | 169 | This option makes busybox shells to use $HISTFILESIZE variable |
166 | to set shell history size. Note that its max value is capped | 170 | to set shell history size. Note that its max value is capped |
@@ -169,7 +173,7 @@ config FEATURE_SH_HISTFILESIZE | |||
169 | config FEATURE_SH_EMBEDDED_SCRIPTS | 173 | config FEATURE_SH_EMBEDDED_SCRIPTS |
170 | bool "Embed scripts in the binary" | 174 | bool "Embed scripts in the binary" |
171 | default y | 175 | default y |
172 | depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH | 176 | depends on SHELL_ASH || SHELL_HUSH |
173 | help | 177 | help |
174 | Allow scripts to be compressed and embedded in the busybox | 178 | Allow scripts to be compressed and embedded in the busybox |
175 | binary. The scripts should be placed in the 'embed' directory | 179 | binary. The scripts should be placed in the 'embed' directory |
diff --git a/shell/ash.c b/shell/ash.c index 9c5fbf5ff..d35ae027f 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -29,10 +29,15 @@ | |||
29 | * - fake $PPID | 29 | * - fake $PPID |
30 | */ | 30 | */ |
31 | 31 | ||
32 | //config:config SHELL_ASH | ||
33 | //config: bool #hidden option | ||
34 | //config: depends on !NOMMU | ||
35 | //config: | ||
32 | //config:config ASH | 36 | //config:config ASH |
33 | //config: bool "ash (78 kb)" | 37 | //config: bool "ash (78 kb)" |
34 | //config: default y | 38 | //config: default y |
35 | //config: depends on !NOMMU | 39 | //config: depends on !NOMMU |
40 | //config: select SHELL_ASH | ||
36 | //config: help | 41 | //config: help |
37 | //config: The most complete and most pedantically correct shell included with | 42 | //config: The most complete and most pedantically correct shell included with |
38 | //config: busybox. This shell is actually a derivative of the Debian 'dash' | 43 | //config: busybox. This shell is actually a derivative of the Debian 'dash' |
@@ -42,17 +47,17 @@ | |||
42 | //config:# ash options | 47 | //config:# ash options |
43 | //config:# note: Don't remove !NOMMU part in the next line; it would break | 48 | //config:# note: Don't remove !NOMMU part in the next line; it would break |
44 | //config:# menuconfig's indenting. | 49 | //config:# menuconfig's indenting. |
45 | //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH) | 50 | //config:if !NOMMU && (SHELL_ASH || ASH || SH_IS_ASH || BASH_IS_ASH) |
46 | //config: | 51 | //config: |
47 | //config:config ASH_OPTIMIZE_FOR_SIZE | 52 | //config:config ASH_OPTIMIZE_FOR_SIZE |
48 | //config: bool "Optimize for size instead of speed" | 53 | //config: bool "Optimize for size instead of speed" |
49 | //config: default y | 54 | //config: default y |
50 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH | 55 | //config: depends on SHELL_ASH |
51 | //config: | 56 | //config: |
52 | //config:config ASH_INTERNAL_GLOB | 57 | //config:config ASH_INTERNAL_GLOB |
53 | //config: bool "Use internal glob() implementation" | 58 | //config: bool "Use internal glob() implementation" |
54 | //config: default y # Y is bigger, but because of uclibc glob() bug, let Y be default for now | 59 | //config: default y # Y is bigger, but because of uclibc glob() bug, let Y be default for now |
55 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH | 60 | //config: depends on SHELL_ASH |
56 | //config: help | 61 | //config: help |
57 | //config: Do not use glob() function from libc, use internal implementation. | 62 | //config: Do not use glob() function from libc, use internal implementation. |
58 | //config: Use this if you are getting "glob.h: No such file or directory" | 63 | //config: Use this if you are getting "glob.h: No such file or directory" |
@@ -63,7 +68,7 @@ | |||
63 | //config:config ASH_BASH_COMPAT | 68 | //config:config ASH_BASH_COMPAT |
64 | //config: bool "bash-compatible extensions" | 69 | //config: bool "bash-compatible extensions" |
65 | //config: default y | 70 | //config: default y |
66 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH | 71 | //config: depends on SHELL_ASH |
67 | //config: | 72 | //config: |
68 | //config:config ASH_BASH_SOURCE_CURDIR | 73 | //config:config ASH_BASH_SOURCE_CURDIR |
69 | //config: bool "'source' and '.' builtins search current directory after $PATH" | 74 | //config: bool "'source' and '.' builtins search current directory after $PATH" |
@@ -84,17 +89,17 @@ | |||
84 | //config:config ASH_JOB_CONTROL | 89 | //config:config ASH_JOB_CONTROL |
85 | //config: bool "Job control" | 90 | //config: bool "Job control" |
86 | //config: default y | 91 | //config: default y |
87 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH | 92 | //config: depends on SHELL_ASH |
88 | //config: | 93 | //config: |
89 | //config:config ASH_ALIAS | 94 | //config:config ASH_ALIAS |
90 | //config: bool "Alias support" | 95 | //config: bool "Alias support" |
91 | //config: default y | 96 | //config: default y |
92 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH | 97 | //config: depends on SHELL_ASH |
93 | //config: | 98 | //config: |
94 | //config:config ASH_RANDOM_SUPPORT | 99 | //config:config ASH_RANDOM_SUPPORT |
95 | //config: bool "Pseudorandom generator and $RANDOM variable" | 100 | //config: bool "Pseudorandom generator and $RANDOM variable" |
96 | //config: default y | 101 | //config: default y |
97 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH | 102 | //config: depends on SHELL_ASH |
98 | //config: help | 103 | //config: help |
99 | //config: Enable pseudorandom generator and dynamic variable "$RANDOM". | 104 | //config: Enable pseudorandom generator and dynamic variable "$RANDOM". |
100 | //config: Each read of "$RANDOM" will generate a new pseudorandom value. | 105 | //config: Each read of "$RANDOM" will generate a new pseudorandom value. |
@@ -105,7 +110,7 @@ | |||
105 | //config:config ASH_EXPAND_PRMT | 110 | //config:config ASH_EXPAND_PRMT |
106 | //config: bool "Expand prompt string" | 111 | //config: bool "Expand prompt string" |
107 | //config: default y | 112 | //config: default y |
108 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH | 113 | //config: depends on SHELL_ASH |
109 | //config: help | 114 | //config: help |
110 | //config: $PS# may contain volatile content, such as backquote commands. | 115 | //config: $PS# may contain volatile content, such as backquote commands. |
111 | //config: This option recreates the prompt string from the environment | 116 | //config: This option recreates the prompt string from the environment |
@@ -114,14 +119,14 @@ | |||
114 | //config:config ASH_IDLE_TIMEOUT | 119 | //config:config ASH_IDLE_TIMEOUT |
115 | //config: bool "Idle timeout variable $TMOUT" | 120 | //config: bool "Idle timeout variable $TMOUT" |
116 | //config: default y | 121 | //config: default y |
117 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH | 122 | //config: depends on SHELL_ASH |
118 | //config: help | 123 | //config: help |
119 | //config: Enable bash-like auto-logout after $TMOUT seconds of idle time. | 124 | //config: Enable bash-like auto-logout after $TMOUT seconds of idle time. |
120 | //config: | 125 | //config: |
121 | //config:config ASH_MAIL | 126 | //config:config ASH_MAIL |
122 | //config: bool "Check for new mail in interactive shell" | 127 | //config: bool "Check for new mail in interactive shell" |
123 | //config: default y | 128 | //config: default y |
124 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH | 129 | //config: depends on SHELL_ASH |
125 | //config: help | 130 | //config: help |
126 | //config: Enable "check for new mail" function: | 131 | //config: Enable "check for new mail" function: |
127 | //config: if set, $MAIL file and $MAILPATH list of files | 132 | //config: if set, $MAIL file and $MAILPATH list of files |
@@ -131,32 +136,32 @@ | |||
131 | //config:config ASH_ECHO | 136 | //config:config ASH_ECHO |
132 | //config: bool "echo builtin" | 137 | //config: bool "echo builtin" |
133 | //config: default y | 138 | //config: default y |
134 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH | 139 | //config: depends on SHELL_ASH |
135 | //config: | 140 | //config: |
136 | //config:config ASH_PRINTF | 141 | //config:config ASH_PRINTF |
137 | //config: bool "printf builtin" | 142 | //config: bool "printf builtin" |
138 | //config: default y | 143 | //config: default y |
139 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH | 144 | //config: depends on SHELL_ASH |
140 | //config: | 145 | //config: |
141 | //config:config ASH_TEST | 146 | //config:config ASH_TEST |
142 | //config: bool "test builtin" | 147 | //config: bool "test builtin" |
143 | //config: default y | 148 | //config: default y |
144 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH | 149 | //config: depends on SHELL_ASH |
145 | //config: | 150 | //config: |
146 | //config:config ASH_HELP | 151 | //config:config ASH_HELP |
147 | //config: bool "help builtin" | 152 | //config: bool "help builtin" |
148 | //config: default y | 153 | //config: default y |
149 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH | 154 | //config: depends on SHELL_ASH |
150 | //config: | 155 | //config: |
151 | //config:config ASH_GETOPTS | 156 | //config:config ASH_GETOPTS |
152 | //config: bool "getopts builtin" | 157 | //config: bool "getopts builtin" |
153 | //config: default y | 158 | //config: default y |
154 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH | 159 | //config: depends on SHELL_ASH |
155 | //config: | 160 | //config: |
156 | //config:config ASH_CMDCMD | 161 | //config:config ASH_CMDCMD |
157 | //config: bool "command builtin" | 162 | //config: bool "command builtin" |
158 | //config: default y | 163 | //config: default y |
159 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH | 164 | //config: depends on SHELL_ASH |
160 | //config: help | 165 | //config: help |
161 | //config: Enable support for the 'command' builtin, which allows | 166 | //config: Enable support for the 'command' builtin, which allows |
162 | //config: you to run the specified command or builtin, | 167 | //config: you to run the specified command or builtin, |
@@ -188,9 +193,7 @@ | |||
188 | //applet:IF_SH_IS_ASH( APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, ash)) | 193 | //applet:IF_SH_IS_ASH( APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, ash)) |
189 | //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash)) | 194 | //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash)) |
190 | 195 | ||
191 | //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o | 196 | //kbuild:lib-$(CONFIG_SHELL_ASH) += ash.o ash_ptr_hack.o shell_common.o |
192 | //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o | ||
193 | //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o | ||
194 | //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o | 197 | //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o |
195 | 198 | ||
196 | /* | 199 | /* |
diff --git a/shell/hush.c b/shell/hush.c index cab7ea5b0..e9cec1cc9 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -95,6 +95,7 @@ | |||
95 | //config:config HUSH | 95 | //config:config HUSH |
96 | //config: bool "hush (68 kb)" | 96 | //config: bool "hush (68 kb)" |
97 | //config: default y | 97 | //config: default y |
98 | //config: select SHELL_HUSH | ||
98 | //config: help | 99 | //config: help |
99 | //config: hush is a small shell. It handles the normal flow control | 100 | //config: hush is a small shell. It handles the normal flow control |
100 | //config: constructs such as if/then/elif/else/fi, for/in/do/done, while loops, | 101 | //config: constructs such as if/then/elif/else/fi, for/in/do/done, while loops, |
@@ -106,10 +107,20 @@ | |||
106 | //config: It does not handle select, aliases, tilde expansion, | 107 | //config: It does not handle select, aliases, tilde expansion, |
107 | //config: &>file and >&file redirection of stdout+stderr. | 108 | //config: &>file and >&file redirection of stdout+stderr. |
108 | //config: | 109 | //config: |
110 | // This option is visible (has a description) to make it possible to select | ||
111 | // a "scripted" applet (such as NOLOGIN) but avoid selecting any shells: | ||
112 | //config:config SHELL_HUSH | ||
113 | //config: bool "Internal shell for embedded script support" | ||
114 | //config: default n | ||
115 | //config: | ||
116 | //config:# hush options | ||
117 | //config:# It's only needed to get "nice" menuconfig indenting. | ||
118 | //config:if SHELL_HUSH || HUSH || SH_IS_HUSH || BASH_IS_HUSH | ||
119 | //config: | ||
109 | //config:config HUSH_BASH_COMPAT | 120 | //config:config HUSH_BASH_COMPAT |
110 | //config: bool "bash-compatible extensions" | 121 | //config: bool "bash-compatible extensions" |
111 | //config: default y | 122 | //config: default y |
112 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 123 | //config: depends on SHELL_HUSH |
113 | //config: | 124 | //config: |
114 | //config:config HUSH_BRACE_EXPANSION | 125 | //config:config HUSH_BRACE_EXPANSION |
115 | //config: bool "Brace expansion" | 126 | //config: bool "Brace expansion" |
@@ -133,7 +144,7 @@ | |||
133 | //config:config HUSH_INTERACTIVE | 144 | //config:config HUSH_INTERACTIVE |
134 | //config: bool "Interactive mode" | 145 | //config: bool "Interactive mode" |
135 | //config: default y | 146 | //config: default y |
136 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 147 | //config: depends on SHELL_HUSH |
137 | //config: help | 148 | //config: help |
138 | //config: Enable interactive mode (prompt and command editing). | 149 | //config: Enable interactive mode (prompt and command editing). |
139 | //config: Without this, hush simply reads and executes commands | 150 | //config: Without this, hush simply reads and executes commands |
@@ -159,31 +170,31 @@ | |||
159 | //config:config HUSH_TICK | 170 | //config:config HUSH_TICK |
160 | //config: bool "Support command substitution" | 171 | //config: bool "Support command substitution" |
161 | //config: default y | 172 | //config: default y |
162 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 173 | //config: depends on SHELL_HUSH |
163 | //config: help | 174 | //config: help |
164 | //config: Enable `command` and $(command). | 175 | //config: Enable `command` and $(command). |
165 | //config: | 176 | //config: |
166 | //config:config HUSH_IF | 177 | //config:config HUSH_IF |
167 | //config: bool "Support if/then/elif/else/fi" | 178 | //config: bool "Support if/then/elif/else/fi" |
168 | //config: default y | 179 | //config: default y |
169 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 180 | //config: depends on SHELL_HUSH |
170 | //config: | 181 | //config: |
171 | //config:config HUSH_LOOPS | 182 | //config:config HUSH_LOOPS |
172 | //config: bool "Support for, while and until loops" | 183 | //config: bool "Support for, while and until loops" |
173 | //config: default y | 184 | //config: default y |
174 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 185 | //config: depends on SHELL_HUSH |
175 | //config: | 186 | //config: |
176 | //config:config HUSH_CASE | 187 | //config:config HUSH_CASE |
177 | //config: bool "Support case ... esac statement" | 188 | //config: bool "Support case ... esac statement" |
178 | //config: default y | 189 | //config: default y |
179 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 190 | //config: depends on SHELL_HUSH |
180 | //config: help | 191 | //config: help |
181 | //config: Enable case ... esac statement. +400 bytes. | 192 | //config: Enable case ... esac statement. +400 bytes. |
182 | //config: | 193 | //config: |
183 | //config:config HUSH_FUNCTIONS | 194 | //config:config HUSH_FUNCTIONS |
184 | //config: bool "Support funcname() { commands; } syntax" | 195 | //config: bool "Support funcname() { commands; } syntax" |
185 | //config: default y | 196 | //config: default y |
186 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 197 | //config: depends on SHELL_HUSH |
187 | //config: help | 198 | //config: help |
188 | //config: Enable support for shell functions. +800 bytes. | 199 | //config: Enable support for shell functions. +800 bytes. |
189 | //config: | 200 | //config: |
@@ -197,7 +208,7 @@ | |||
197 | //config:config HUSH_RANDOM_SUPPORT | 208 | //config:config HUSH_RANDOM_SUPPORT |
198 | //config: bool "Pseudorandom generator and $RANDOM variable" | 209 | //config: bool "Pseudorandom generator and $RANDOM variable" |
199 | //config: default y | 210 | //config: default y |
200 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 211 | //config: depends on SHELL_HUSH |
201 | //config: help | 212 | //config: help |
202 | //config: Enable pseudorandom generator and dynamic variable "$RANDOM". | 213 | //config: Enable pseudorandom generator and dynamic variable "$RANDOM". |
203 | //config: Each read of "$RANDOM" will generate a new pseudorandom value. | 214 | //config: Each read of "$RANDOM" will generate a new pseudorandom value. |
@@ -205,7 +216,7 @@ | |||
205 | //config:config HUSH_MODE_X | 216 | //config:config HUSH_MODE_X |
206 | //config: bool "Support 'hush -x' option and 'set -x' command" | 217 | //config: bool "Support 'hush -x' option and 'set -x' command" |
207 | //config: default y | 218 | //config: default y |
208 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 219 | //config: depends on SHELL_HUSH |
209 | //config: help | 220 | //config: help |
210 | //config: This instructs hush to print commands before execution. | 221 | //config: This instructs hush to print commands before execution. |
211 | //config: Adds ~300 bytes. | 222 | //config: Adds ~300 bytes. |
@@ -213,27 +224,27 @@ | |||
213 | //config:config HUSH_ECHO | 224 | //config:config HUSH_ECHO |
214 | //config: bool "echo builtin" | 225 | //config: bool "echo builtin" |
215 | //config: default y | 226 | //config: default y |
216 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 227 | //config: depends on SHELL_HUSH |
217 | //config: | 228 | //config: |
218 | //config:config HUSH_PRINTF | 229 | //config:config HUSH_PRINTF |
219 | //config: bool "printf builtin" | 230 | //config: bool "printf builtin" |
220 | //config: default y | 231 | //config: default y |
221 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 232 | //config: depends on SHELL_HUSH |
222 | //config: | 233 | //config: |
223 | //config:config HUSH_TEST | 234 | //config:config HUSH_TEST |
224 | //config: bool "test builtin" | 235 | //config: bool "test builtin" |
225 | //config: default y | 236 | //config: default y |
226 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 237 | //config: depends on SHELL_HUSH |
227 | //config: | 238 | //config: |
228 | //config:config HUSH_HELP | 239 | //config:config HUSH_HELP |
229 | //config: bool "help builtin" | 240 | //config: bool "help builtin" |
230 | //config: default y | 241 | //config: default y |
231 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 242 | //config: depends on SHELL_HUSH |
232 | //config: | 243 | //config: |
233 | //config:config HUSH_EXPORT | 244 | //config:config HUSH_EXPORT |
234 | //config: bool "export builtin" | 245 | //config: bool "export builtin" |
235 | //config: default y | 246 | //config: default y |
236 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 247 | //config: depends on SHELL_HUSH |
237 | //config: | 248 | //config: |
238 | //config:config HUSH_EXPORT_N | 249 | //config:config HUSH_EXPORT_N |
239 | //config: bool "Support 'export -n' option" | 250 | //config: bool "Support 'export -n' option" |
@@ -245,83 +256,83 @@ | |||
245 | //config:config HUSH_READONLY | 256 | //config:config HUSH_READONLY |
246 | //config: bool "readonly builtin" | 257 | //config: bool "readonly builtin" |
247 | //config: default y | 258 | //config: default y |
248 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 259 | //config: depends on SHELL_HUSH |
249 | //config: help | 260 | //config: help |
250 | //config: Enable support for read-only variables. | 261 | //config: Enable support for read-only variables. |
251 | //config: | 262 | //config: |
252 | //config:config HUSH_KILL | 263 | //config:config HUSH_KILL |
253 | //config: bool "kill builtin (supports kill %jobspec)" | 264 | //config: bool "kill builtin (supports kill %jobspec)" |
254 | //config: default y | 265 | //config: default y |
255 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 266 | //config: depends on SHELL_HUSH |
256 | //config: | 267 | //config: |
257 | //config:config HUSH_WAIT | 268 | //config:config HUSH_WAIT |
258 | //config: bool "wait builtin" | 269 | //config: bool "wait builtin" |
259 | //config: default y | 270 | //config: default y |
260 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 271 | //config: depends on SHELL_HUSH |
261 | //config: | 272 | //config: |
262 | //config:config HUSH_COMMAND | 273 | //config:config HUSH_COMMAND |
263 | //config: bool "command builtin" | 274 | //config: bool "command builtin" |
264 | //config: default y | 275 | //config: default y |
265 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 276 | //config: depends on SHELL_HUSH |
266 | //config: | 277 | //config: |
267 | //config:config HUSH_TRAP | 278 | //config:config HUSH_TRAP |
268 | //config: bool "trap builtin" | 279 | //config: bool "trap builtin" |
269 | //config: default y | 280 | //config: default y |
270 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 281 | //config: depends on SHELL_HUSH |
271 | //config: | 282 | //config: |
272 | //config:config HUSH_TYPE | 283 | //config:config HUSH_TYPE |
273 | //config: bool "type builtin" | 284 | //config: bool "type builtin" |
274 | //config: default y | 285 | //config: default y |
275 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 286 | //config: depends on SHELL_HUSH |
276 | //config: | 287 | //config: |
277 | //config:config HUSH_TIMES | 288 | //config:config HUSH_TIMES |
278 | //config: bool "times builtin" | 289 | //config: bool "times builtin" |
279 | //config: default y | 290 | //config: default y |
280 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 291 | //config: depends on SHELL_HUSH |
281 | //config: | 292 | //config: |
282 | //config:config HUSH_READ | 293 | //config:config HUSH_READ |
283 | //config: bool "read builtin" | 294 | //config: bool "read builtin" |
284 | //config: default y | 295 | //config: default y |
285 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 296 | //config: depends on SHELL_HUSH |
286 | //config: | 297 | //config: |
287 | //config:config HUSH_SET | 298 | //config:config HUSH_SET |
288 | //config: bool "set builtin" | 299 | //config: bool "set builtin" |
289 | //config: default y | 300 | //config: default y |
290 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 301 | //config: depends on SHELL_HUSH |
291 | //config: | 302 | //config: |
292 | //config:config HUSH_UNSET | 303 | //config:config HUSH_UNSET |
293 | //config: bool "unset builtin" | 304 | //config: bool "unset builtin" |
294 | //config: default y | 305 | //config: default y |
295 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 306 | //config: depends on SHELL_HUSH |
296 | //config: | 307 | //config: |
297 | //config:config HUSH_ULIMIT | 308 | //config:config HUSH_ULIMIT |
298 | //config: bool "ulimit builtin" | 309 | //config: bool "ulimit builtin" |
299 | //config: default y | 310 | //config: default y |
300 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 311 | //config: depends on SHELL_HUSH |
301 | //config: | 312 | //config: |
302 | //config:config HUSH_UMASK | 313 | //config:config HUSH_UMASK |
303 | //config: bool "umask builtin" | 314 | //config: bool "umask builtin" |
304 | //config: default y | 315 | //config: default y |
305 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 316 | //config: depends on SHELL_HUSH |
306 | //config: | 317 | //config: |
307 | //config:config HUSH_GETOPTS | 318 | //config:config HUSH_GETOPTS |
308 | //config: bool "getopts builtin" | 319 | //config: bool "getopts builtin" |
309 | //config: default y | 320 | //config: default y |
310 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 321 | //config: depends on SHELL_HUSH |
311 | //config: | 322 | //config: |
312 | //config:config HUSH_MEMLEAK | 323 | //config:config HUSH_MEMLEAK |
313 | //config: bool "memleak builtin (debugging)" | 324 | //config: bool "memleak builtin (debugging)" |
314 | //config: default n | 325 | //config: default n |
315 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH | 326 | //config: depends on SHELL_HUSH |
327 | //config: | ||
328 | //config:endif # hush options | ||
316 | 329 | ||
317 | //applet:IF_HUSH(APPLET(hush, BB_DIR_BIN, BB_SUID_DROP)) | 330 | //applet:IF_HUSH(APPLET(hush, BB_DIR_BIN, BB_SUID_DROP)) |
318 | // APPLET_ODDNAME:name main location suid_type help | 331 | // APPLET_ODDNAME:name main location suid_type help |
319 | //applet:IF_SH_IS_HUSH( APPLET_ODDNAME(sh, hush, BB_DIR_BIN, BB_SUID_DROP, hush)) | 332 | //applet:IF_SH_IS_HUSH( APPLET_ODDNAME(sh, hush, BB_DIR_BIN, BB_SUID_DROP, hush)) |
320 | //applet:IF_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, hush)) | 333 | //applet:IF_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, hush)) |
321 | 334 | ||
322 | //kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o | 335 | //kbuild:lib-$(CONFIG_SHELL_HUSH) += hush.o match.o shell_common.o |
323 | //kbuild:lib-$(CONFIG_SH_IS_HUSH) += hush.o match.o shell_common.o | ||
324 | //kbuild:lib-$(CONFIG_BASH_IS_HUSH) += hush.o match.o shell_common.o | ||
325 | //kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o | 336 | //kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o |
326 | 337 | ||
327 | /* -i (interactive) is also accepted, | 338 | /* -i (interactive) is also accepted, |
@@ -7917,7 +7928,7 @@ static const struct built_in_command *find_builtin(const char *name) | |||
7917 | return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]); | 7928 | return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]); |
7918 | } | 7929 | } |
7919 | 7930 | ||
7920 | #if EDITING_HAS_get_exe_name | 7931 | #if ENABLE_HUSH_JOB && EDITING_HAS_get_exe_name |
7921 | static const char * FAST_FUNC get_builtin_name(int i) | 7932 | static const char * FAST_FUNC get_builtin_name(int i) |
7922 | { | 7933 | { |
7923 | if (/*i >= 0 && */ i < ARRAY_SIZE(bltins1)) { | 7934 | if (/*i >= 0 && */ i < ARRAY_SIZE(bltins1)) { |
diff --git a/testsuite/awk.tests b/testsuite/awk.tests index b5008290f..87f6b5007 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests | |||
@@ -390,5 +390,13 @@ testing 'awk negative field access' \ | |||
390 | '' \ | 390 | '' \ |
391 | 'anything' | 391 | 'anything' |
392 | 392 | ||
393 | # was misinterpreted as (("str"++) i) instead of ("str" (++i)) | ||
394 | # (and was executed: "str"++ is "0", thus concatenating "0" and "1"): | ||
395 | testing 'awk do not allow "str"++' \ | ||
396 | 'awk -v i=1 "BEGIN {print \"str\" ++i}"' \ | ||
397 | "str2\n" \ | ||
398 | '' \ | ||
399 | 'anything' | ||
400 | |||
393 | 401 | ||
394 | exit $FAILCOUNT | 402 | exit $FAILCOUNT |
diff --git a/testsuite/cpio.tests b/testsuite/cpio.tests index 88ec086b6..85e746589 100755 --- a/testsuite/cpio.tests +++ b/testsuite/cpio.tests | |||
@@ -129,7 +129,7 @@ SKIP= | |||
129 | 129 | ||
130 | optional FEATURE_CPIO_O | 130 | optional FEATURE_CPIO_O |
131 | testing "cpio uses by default uid/gid" \ | 131 | testing "cpio uses by default uid/gid" \ |
132 | "echo $0 | cpio -o -H newc | cpio -tv 2>&1 | tail -n +2 | awk ' { print \$2 } '; echo \$?" \ | 132 | "echo $0 | cpio -o -H newc | cpio -tv 2>&1 | head -n1 | awk ' { print \$2 } '; echo \$?" \ |
133 | "\ | 133 | "\ |
134 | $user/$group | 134 | $user/$group |
135 | 0 | 135 | 0 |
@@ -138,7 +138,7 @@ SKIP= | |||
138 | 138 | ||
139 | optional FEATURE_CPIO_O | 139 | optional FEATURE_CPIO_O |
140 | testing "cpio -R with create" \ | 140 | testing "cpio -R with create" \ |
141 | "echo $0 | cpio -o -H newc -R 1234:5678 | cpio -tv 2>&1 | tail -n +2 | awk ' { print \$2 } '; echo \$?" \ | 141 | "echo $0 | cpio -o -H newc -R 1234:5678 | cpio -tv 2>&1 | head -n1 | awk ' { print \$2 } '; echo \$?" \ |
142 | "\ | 142 | "\ |
143 | 1234/5678 | 143 | 1234/5678 |
144 | 0 | 144 | 0 |
@@ -147,7 +147,7 @@ SKIP= | |||
147 | 147 | ||
148 | optional FEATURE_CPIO_O | 148 | optional FEATURE_CPIO_O |
149 | testing "cpio -R with extract" \ | 149 | testing "cpio -R with extract" \ |
150 | "echo $0 | cpio -o -H newc | cpio -tv -R 8765:4321 2>&1 | tail -n +2 | awk ' { print \$2 } '; echo \$?" \ | 150 | "echo $0 | cpio -o -H newc | cpio -tv -R 8765:4321 2>&1 | head -n1 | awk ' { print \$2 } '; echo \$?" \ |
151 | "\ | 151 | "\ |
152 | 8765/4321 | 152 | 8765/4321 |
153 | 0 | 153 | 0 |
diff --git a/testsuite/mdev.tests b/testsuite/mdev.tests index 8e53ec564..44a723024 100755 --- a/testsuite/mdev.tests +++ b/testsuite/mdev.tests | |||
@@ -93,7 +93,7 @@ SKIP= | |||
93 | # continuing to use directory structure from prev test | 93 | # continuing to use directory structure from prev test |
94 | rm -rf mdev.testdir/dev/* | 94 | rm -rf mdev.testdir/dev/* |
95 | echo "sda 0:0 444 >disk/scsiA" >mdev.testdir/etc/mdev.conf | 95 | echo "sda 0:0 444 >disk/scsiA" >mdev.testdir/etc/mdev.conf |
96 | optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME | 96 | optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_LS_SORTFILES |
97 | testing "mdev move/symlink rule '>bar/baz'" \ | 97 | testing "mdev move/symlink rule '>bar/baz'" \ |
98 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; | 98 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; |
99 | ls -lnR mdev.testdir/dev | $FILTER_LS2" \ | 99 | ls -lnR mdev.testdir/dev | $FILTER_LS2" \ |
@@ -111,7 +111,7 @@ SKIP= | |||
111 | # continuing to use directory structure from prev test | 111 | # continuing to use directory structure from prev test |
112 | rm -rf mdev.testdir/dev/* | 112 | rm -rf mdev.testdir/dev/* |
113 | echo "sda 0:0 444 >disk/" >mdev.testdir/etc/mdev.conf | 113 | echo "sda 0:0 444 >disk/" >mdev.testdir/etc/mdev.conf |
114 | optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME | 114 | optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_LS_SORTFILES |
115 | testing "mdev move/symlink rule '>bar/'" \ | 115 | testing "mdev move/symlink rule '>bar/'" \ |
116 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; | 116 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; |
117 | ls -lnR mdev.testdir/dev | $FILTER_LS2" \ | 117 | ls -lnR mdev.testdir/dev | $FILTER_LS2" \ |
diff --git a/testsuite/patch.tests b/testsuite/patch.tests index 39205242c..1d48e90be 100755 --- a/testsuite/patch.tests +++ b/testsuite/patch.tests | |||
@@ -75,12 +75,12 @@ zxc | |||
75 | testing "patch detects already applied hunk" \ | 75 | testing "patch detects already applied hunk" \ |
76 | 'patch 2>&1; echo $?; cat input' \ | 76 | 'patch 2>&1; echo $?; cat input' \ |
77 | "\ | 77 | "\ |
78 | patching file input | ||
78 | Possibly reversed hunk 1 at 4 | 79 | Possibly reversed hunk 1 at 4 |
79 | Hunk 1 FAILED 1/1. | 80 | Hunk 1 FAILED 1/1. |
80 | abc | 81 | abc |
81 | +def | 82 | +def |
82 | 123 | 83 | 123 |
83 | patching file input | ||
84 | 1 | 84 | 1 |
85 | abc | 85 | abc |
86 | def | 86 | def |
@@ -103,12 +103,12 @@ def | |||
103 | testing "patch detects already applied hunk at the EOF" \ | 103 | testing "patch detects already applied hunk at the EOF" \ |
104 | 'patch 2>&1; echo $?; cat input' \ | 104 | 'patch 2>&1; echo $?; cat input' \ |
105 | "\ | 105 | "\ |
106 | patching file input | ||
106 | Possibly reversed hunk 1 at 4 | 107 | Possibly reversed hunk 1 at 4 |
107 | Hunk 1 FAILED 1/1. | 108 | Hunk 1 FAILED 1/1. |
108 | abc | 109 | abc |
109 | 123 | 110 | 123 |
110 | +456 | 111 | +456 |
111 | patching file input | ||
112 | 1 | 112 | 1 |
113 | abc | 113 | abc |
114 | 123 | 114 | 123 |
diff --git a/testsuite/unexpand.tests b/testsuite/unexpand.tests index 7b326dc2c..aeaae13f0 100755 --- a/testsuite/unexpand.tests +++ b/testsuite/unexpand.tests | |||
@@ -31,6 +31,39 @@ testing "unexpand case 7" "unexpand" \ | |||
31 | testing "unexpand case 8" "unexpand" \ | 31 | testing "unexpand case 8" "unexpand" \ |
32 | "a b\n" "" "a b\n" \ | 32 | "a b\n" "" "a b\n" \ |
33 | 33 | ||
34 | testcase() | ||
35 | { | ||
36 | testing "unexpand flags $*" "unexpand $*" \ | ||
37 | "$want" "" ' a b c' | ||
38 | } | ||
39 | |||
40 | # tabs=8, Convert only leading sequences of blanks | ||
41 | want='\ta b c' | ||
42 | testcase | ||
43 | testcase -f | ||
44 | testcase -f -t8 | ||
45 | testcase -t8 -f | ||
46 | testcase -t8 --first-only | ||
47 | |||
48 | # tabs=8, Convert all blanks | ||
49 | want='\ta\tb c' | ||
50 | testcase -a | ||
51 | testcase -t8 | ||
52 | testcase -a -t8 | ||
53 | |||
54 | # tabs=4, Convert all blanks | ||
55 | want='\t\ta\t\tb\t c' | ||
56 | testcase -t4 | ||
57 | testcase -a -t4 | ||
58 | testcase -t4 -a | ||
59 | |||
60 | # tabs=4, Convert only leading sequences of blanks | ||
61 | want='\t\ta b c' | ||
62 | testcase -t4 -f | ||
63 | testcase -f -t4 | ||
64 | testcase -t4 --first-only | ||
65 | testcase --first-only -t4 | ||
66 | |||
34 | test x"$CONFIG_UNICODE_SUPPORT" = x"y" \ | 67 | test x"$CONFIG_UNICODE_SUPPORT" = x"y" \ |
35 | && test x"$CONFIG_UNICODE_USING_LOCALE" != x"y" \ | 68 | && test x"$CONFIG_UNICODE_USING_LOCALE" != x"y" \ |
36 | && testing "unexpand with unicode characher 0x394" "unexpand" \ | 69 | && testing "unexpand with unicode characher 0x394" "unexpand" \ |
diff --git a/util-linux/acpid.c b/util-linux/acpid.c index 95f8150e2..fc8215cce 100644 --- a/util-linux/acpid.c +++ b/util-linux/acpid.c | |||
@@ -42,7 +42,9 @@ | |||
42 | //usage: "\n -c DIR Config directory [/etc/acpi]" | 42 | //usage: "\n -c DIR Config directory [/etc/acpi]" |
43 | //usage: "\n -e FILE /proc event file [/proc/acpi/event]" | 43 | //usage: "\n -e FILE /proc event file [/proc/acpi/event]" |
44 | //usage: "\n -l FILE Log file [/var/log/acpid.log]" | 44 | //usage: "\n -l FILE Log file [/var/log/acpid.log]" |
45 | //usage: "\n -p FILE Pid file [/var/run/acpid.pid]" | 45 | //usage: IF_FEATURE_PIDFILE( |
46 | //usage: "\n -p FILE Pid file [" CONFIG_PID_FILE_PATH "/acpid.pid]" | ||
47 | //usage: ) | ||
46 | //usage: "\n -a FILE Action file [/etc/acpid.conf]" | 48 | //usage: "\n -a FILE Action file [/etc/acpid.conf]" |
47 | //usage: "\n -M FILE Map file [/etc/acpi.map]" | 49 | //usage: "\n -M FILE Map file [/etc/acpi.map]" |
48 | //usage: IF_FEATURE_ACPID_COMPAT( | 50 | //usage: IF_FEATURE_ACPID_COMPAT( |
diff --git a/util-linux/nologin.c b/util-linux/nologin.c index 5e5e42305..5a8b047a5 100644 --- a/util-linux/nologin.c +++ b/util-linux/nologin.c | |||
@@ -7,7 +7,7 @@ | |||
7 | //config: | 7 | //config: |
8 | //config:config NOLOGIN_DEPENDENCIES | 8 | //config:config NOLOGIN_DEPENDENCIES |
9 | //config: bool "Enable dependencies for nologin" | 9 | //config: bool "Enable dependencies for nologin" |
10 | //config: default y | 10 | //config: default n # Y default makes it harder to select single-applet test |
11 | //config: depends on NOLOGIN | 11 | //config: depends on NOLOGIN |
12 | //config: select CAT | 12 | //config: select CAT |
13 | //config: select ECHO | 13 | //config: select ECHO |