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 |
