diff options
author | Ron Yorston <rmy@pobox.com> | 2018-07-25 10:41:42 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-07-25 10:41:42 +0100 |
commit | 59873514f17cefd6ba3997dad5779f75433fd4e6 (patch) | |
tree | 1c9d0a3450ed95f0b820285b9f9fc217c902e652 | |
parent | 779fd5745ac11bf752f5f4b977a274a39c192f90 (diff) | |
parent | 81de30de05beebabfa72f2a01ec4f33e9a1923e3 (diff) | |
download | busybox-w32-59873514f17cefd6ba3997dad5779f75433fd4e6.tar.gz busybox-w32-59873514f17cefd6ba3997dad5779f75433fd4e6.tar.bz2 busybox-w32-59873514f17cefd6ba3997dad5779f75433fd4e6.zip |
Merge branch 'busybox'
213 files changed, 2877 insertions, 1398 deletions
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | mainmenu "Configuration" | 6 | mainmenu "Configuration" |
@@ -1,5 +1,5 @@ | |||
1 | VERSION = 1 | 1 | VERSION = 1 |
2 | PATCHLEVEL = 29 | 2 | PATCHLEVEL = 30 |
3 | SUBLEVEL = 0 | 3 | SUBLEVEL = 0 |
4 | EXTRAVERSION = .git | 4 | EXTRAVERSION = .git |
5 | NAME = Unnamed | 5 | NAME = Unnamed |
diff --git a/archival/Config.src b/archival/Config.src index 449914565..6f4f30c43 100644 --- a/archival/Config.src +++ b/archival/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "Archival Utilities" | 6 | menu "Archival Utilities" |
diff --git a/archival/cpio.c b/archival/cpio.c index 308ec1b25..9cacf9de6 100644 --- a/archival/cpio.c +++ b/archival/cpio.c | |||
@@ -64,15 +64,17 @@ | |||
64 | //usage: "\n -p DIR Copy files to DIR" | 64 | //usage: "\n -p DIR Copy files to DIR" |
65 | //usage: ) | 65 | //usage: ) |
66 | //usage: "\nOptions:" | 66 | //usage: "\nOptions:" |
67 | //usage: IF_FEATURE_CPIO_O( | ||
68 | //usage: "\n -H newc Archive format" | ||
69 | //usage: ) | ||
67 | //usage: "\n -d Make leading directories" | 70 | //usage: "\n -d Make leading directories" |
68 | //usage: "\n -m Preserve mtime" | 71 | //usage: "\n -m Preserve mtime" |
69 | //usage: "\n -v Verbose" | 72 | //usage: "\n -v Verbose" |
70 | //usage: "\n -u Overwrite" | 73 | //usage: "\n -u Overwrite" |
71 | //usage: "\n -F FILE Input (-t,-i,-p) or output (-o) file" | 74 | //usage: "\n -F FILE Input (-t,-i,-p) or output (-o) file" |
72 | //usage: "\n -R USER[:GRP] Set owner of created files" | 75 | //usage: "\n -R USER[:GRP] Set owner of created files" |
73 | //usage: IF_FEATURE_CPIO_O( | 76 | //usage: "\n -L Dereference symlinks" |
74 | //usage: "\n -H newc Archive format" | 77 | //usage: "\n -0 Input is separated by NULs" |
75 | //usage: ) | ||
76 | 78 | ||
77 | /* GNU cpio 2.9 --help (abridged): | 79 | /* GNU cpio 2.9 --help (abridged): |
78 | 80 | ||
@@ -374,6 +376,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) | |||
374 | #endif | 376 | #endif |
375 | "owner\0" Required_argument "R" | 377 | "owner\0" Required_argument "R" |
376 | "verbose\0" No_argument "v" | 378 | "verbose\0" No_argument "v" |
379 | "null\0" No_argument "0" | ||
377 | "quiet\0" No_argument "\xff" | 380 | "quiet\0" No_argument "\xff" |
378 | "to-stdout\0" No_argument "\xfe" | 381 | "to-stdout\0" No_argument "\xfe" |
379 | ; | 382 | ; |
@@ -508,7 +511,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) | |||
508 | while (get_header_cpio(archive_handle) == EXIT_SUCCESS) | 511 | while (get_header_cpio(archive_handle) == EXIT_SUCCESS) |
509 | continue; | 512 | continue; |
510 | 513 | ||
511 | create_symlinks_from_list(archive_handle->symlink_placeholders); | 514 | create_links_from_list(archive_handle->link_placeholders); |
512 | 515 | ||
513 | if (archive_handle->cpio__blocks != (off_t)-1 | 516 | if (archive_handle->cpio__blocks != (off_t)-1 |
514 | && !(opt & OPT_QUIET) | 517 | && !(opt & OPT_QUIET) |
diff --git a/archival/gzip.c b/archival/gzip.c index c5a1fe9b4..74d5d685f 100644 --- a/archival/gzip.c +++ b/archival/gzip.c | |||
@@ -333,12 +333,6 @@ struct globals { | |||
333 | /* DECLARE(Pos, head, 1<<HASH_BITS); */ | 333 | /* DECLARE(Pos, head, 1<<HASH_BITS); */ |
334 | #define head (G1.prev + WSIZE) /* hash head (see deflate.c) */ | 334 | #define head (G1.prev + WSIZE) /* hash head (see deflate.c) */ |
335 | 335 | ||
336 | /* =========================================================================== */ | ||
337 | /* all members below are zeroed out in pack_gzip() for each next file */ | ||
338 | |||
339 | uint32_t crc; /* shift register contents */ | ||
340 | /*uint32_t *crc_32_tab;*/ | ||
341 | |||
342 | #if ENABLE_FEATURE_GZIP_LEVELS | 336 | #if ENABLE_FEATURE_GZIP_LEVELS |
343 | unsigned max_chain_length; | 337 | unsigned max_chain_length; |
344 | unsigned max_lazy_match; | 338 | unsigned max_lazy_match; |
@@ -350,6 +344,12 @@ struct globals { | |||
350 | #define nice_match (G1.nice_match) | 344 | #define nice_match (G1.nice_match) |
351 | #endif | 345 | #endif |
352 | 346 | ||
347 | /* =========================================================================== */ | ||
348 | /* all members below are zeroed out in pack_gzip() for each next file */ | ||
349 | |||
350 | uint32_t crc; /* shift register contents */ | ||
351 | /*uint32_t *crc_32_tab;*/ | ||
352 | |||
353 | /* window position at the beginning of the current output block. Gets | 353 | /* window position at the beginning of the current output block. Gets |
354 | * negative when the window is moved backwards. | 354 | * negative when the window is moved backwards. |
355 | */ | 355 | */ |
diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c index 8fa69ffaf..4c95db4a6 100644 --- a/archival/libarchive/data_extract_all.c +++ b/archival/libarchive/data_extract_all.c | |||
@@ -122,13 +122,10 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |||
122 | 122 | ||
123 | /* Handle hard links separately */ | 123 | /* Handle hard links separately */ |
124 | if (hard_link) { | 124 | if (hard_link) { |
125 | res = link(hard_link, dst_name); | 125 | create_or_remember_link(&archive_handle->link_placeholders, |
126 | if (res != 0) { | 126 | hard_link, |
127 | /* shared message */ | 127 | dst_name, |
128 | bb_perror_msg("can't create %slink '%s' to '%s'", | 128 | 1); |
129 | "hard", dst_name, hard_link | ||
130 | ); | ||
131 | } | ||
132 | /* Hardlinks have no separate mode/ownership, skip chown/chmod */ | 129 | /* Hardlinks have no separate mode/ownership, skip chown/chmod */ |
133 | goto ret; | 130 | goto ret; |
134 | } | 131 | } |
@@ -195,9 +192,10 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |||
195 | * | 192 | * |
196 | * Untarring bug.tar would otherwise place evil.py in '/tmp'. | 193 | * Untarring bug.tar would otherwise place evil.py in '/tmp'. |
197 | */ | 194 | */ |
198 | create_or_remember_symlink(&archive_handle->symlink_placeholders, | 195 | create_or_remember_link(&archive_handle->link_placeholders, |
199 | file_header->link_target, | 196 | file_header->link_target, |
200 | dst_name); | 197 | dst_name, |
198 | 0); | ||
201 | break; | 199 | break; |
202 | case S_IFSOCK: | 200 | case S_IFSOCK: |
203 | case S_IFBLK: | 201 | case S_IFBLK: |
diff --git a/archival/libarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c index 446319e7b..6886239d0 100644 --- a/archival/libarchive/decompress_unlzma.c +++ b/archival/libarchive/decompress_unlzma.c | |||
@@ -350,8 +350,12 @@ unpack_lzma_stream(transformer_state_t *xstate) | |||
350 | state = state < LZMA_NUM_LIT_STATES ? 9 : 11; | 350 | state = state < LZMA_NUM_LIT_STATES ? 9 : 11; |
351 | 351 | ||
352 | pos = buffer_pos - rep0; | 352 | pos = buffer_pos - rep0; |
353 | if ((int32_t)pos < 0) | 353 | if ((int32_t)pos < 0) { |
354 | pos += header.dict_size; | 354 | pos += header.dict_size; |
355 | /* see unzip_bad_lzma_2.zip: */ | ||
356 | if (pos >= buffer_size) | ||
357 | goto bad; | ||
358 | } | ||
355 | previous_byte = buffer[pos]; | 359 | previous_byte = buffer[pos]; |
356 | goto one_byte1; | 360 | goto one_byte1; |
357 | #else | 361 | #else |
diff --git a/archival/libarchive/get_header_ar.c b/archival/libarchive/get_header_ar.c index adcde46d5..7ce9c615c 100644 --- a/archival/libarchive/get_header_ar.c +++ b/archival/libarchive/get_header_ar.c | |||
@@ -126,7 +126,7 @@ char FAST_FUNC get_header_ar(archive_handle_t *archive_handle) | |||
126 | struct archive_handle_t *sa = archive_handle->dpkg__sub_archive; | 126 | struct archive_handle_t *sa = archive_handle->dpkg__sub_archive; |
127 | while (archive_handle->dpkg__action_data_subarchive(sa) == EXIT_SUCCESS) | 127 | while (archive_handle->dpkg__action_data_subarchive(sa) == EXIT_SUCCESS) |
128 | continue; | 128 | continue; |
129 | create_symlinks_from_list(sa->symlink_placeholders); | 129 | create_links_from_list(sa->link_placeholders); |
130 | } else | 130 | } else |
131 | #endif | 131 | #endif |
132 | archive_handle->action_data(archive_handle); | 132 | archive_handle->action_data(archive_handle); |
diff --git a/archival/libarchive/unsafe_symlink_target.c b/archival/libarchive/unsafe_symlink_target.c index 0ad4c9392..f53881f2f 100644 --- a/archival/libarchive/unsafe_symlink_target.c +++ b/archival/libarchive/unsafe_symlink_target.c | |||
@@ -5,15 +5,16 @@ | |||
5 | #include "libbb.h" | 5 | #include "libbb.h" |
6 | #include "bb_archive.h" | 6 | #include "bb_archive.h" |
7 | 7 | ||
8 | void FAST_FUNC create_or_remember_symlink(llist_t **symlink_placeholders | 8 | void FAST_FUNC create_or_remember_link(llist_t **link_placeholders |
9 | IF_PLATFORM_MINGW32(UNUSED_PARAM), | 9 | IF_PLATFORM_MINGW32(UNUSED_PARAM), |
10 | const char *target, | 10 | const char *target, |
11 | const char *linkname) | 11 | const char *linkname, |
12 | int hard_link IF_PLATFORM_MINGW32(UNUSED_PARAM)) | ||
12 | { | 13 | { |
13 | #if !ENABLE_PLATFORM_MINGW32 | 14 | #if !ENABLE_PLATFORM_MINGW32 |
14 | if (target[0] == '/' || strstr(target, "..")) { | 15 | if (hard_link || target[0] == '/' || strstr(target, "..")) { |
15 | llist_add_to(symlink_placeholders, | 16 | llist_add_to_end(link_placeholders, |
16 | xasprintf("%s%c%s", linkname, '\0', target) | 17 | xasprintf("%c%s%c%s", hard_link, linkname, '\0', target) |
17 | ); | 18 | ); |
18 | return; | 19 | return; |
19 | } | 20 | } |
@@ -30,17 +31,17 @@ void FAST_FUNC create_or_remember_symlink(llist_t **symlink_placeholders | |||
30 | } | 31 | } |
31 | 32 | ||
32 | #if !ENABLE_PLATFORM_MINGW32 | 33 | #if !ENABLE_PLATFORM_MINGW32 |
33 | void FAST_FUNC create_symlinks_from_list(llist_t *list) | 34 | void FAST_FUNC create_links_from_list(llist_t *list) |
34 | { | 35 | { |
35 | while (list) { | 36 | while (list) { |
36 | char *target; | 37 | char *target; |
37 | 38 | ||
38 | target = list->data + strlen(list->data) + 1; | 39 | target = list->data + 1 + strlen(list->data + 1) + 1; |
39 | if (symlink(target, list->data)) { | 40 | if ((*list->data ? link : symlink) (target, list->data + 1)) { |
40 | /* shared message */ | 41 | /* shared message */ |
41 | bb_error_msg_and_die("can't create %slink '%s' to '%s'", | 42 | bb_error_msg_and_die("can't create %slink '%s' to '%s'", |
42 | "sym", | 43 | *list->data ? "hard" : "sym", |
43 | list->data, target | 44 | list->data + 1, target |
44 | ); | 45 | ); |
45 | } | 46 | } |
46 | list = list->link; | 47 | list = list->link; |
diff --git a/archival/tar.c b/archival/tar.c index afd8cfec5..e1af27401 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -1279,7 +1279,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv) | |||
1279 | while (get_header_tar(tar_handle) == EXIT_SUCCESS) | 1279 | while (get_header_tar(tar_handle) == EXIT_SUCCESS) |
1280 | bb_got_signal = EXIT_SUCCESS; /* saw at least one header, good */ | 1280 | bb_got_signal = EXIT_SUCCESS; /* saw at least one header, good */ |
1281 | 1281 | ||
1282 | create_symlinks_from_list(tar_handle->symlink_placeholders); | 1282 | create_links_from_list(tar_handle->link_placeholders); |
1283 | 1283 | ||
1284 | /* Check that every file that should have been extracted was */ | 1284 | /* Check that every file that should have been extracted was */ |
1285 | while (tar_handle->accept) { | 1285 | while (tar_handle->accept) { |
diff --git a/archival/unzip.c b/archival/unzip.c index 369c6c028..a9b7dc10f 100644 --- a/archival/unzip.c +++ b/archival/unzip.c | |||
@@ -375,9 +375,10 @@ static void unzip_extract_symlink(llist_t **symlink_placeholders, | |||
375 | target[xstate.mem_output_size] = '\0'; | 375 | target[xstate.mem_output_size] = '\0'; |
376 | #endif | 376 | #endif |
377 | } | 377 | } |
378 | create_or_remember_symlink(symlink_placeholders, | 378 | create_or_remember_link(symlink_placeholders, |
379 | target, | 379 | target, |
380 | dst_fn); | 380 | dst_fn, |
381 | 0); | ||
381 | free(target); | 382 | free(target); |
382 | } | 383 | } |
383 | #endif | 384 | #endif |
@@ -993,7 +994,7 @@ int unzip_main(int argc, char **argv) | |||
993 | } | 994 | } |
994 | 995 | ||
995 | #if ENABLE_FEATURE_UNZIP_CDF | 996 | #if ENABLE_FEATURE_UNZIP_CDF |
996 | create_symlinks_from_list(symlink_placeholders); | 997 | create_links_from_list(symlink_placeholders); |
997 | #endif | 998 | #endif |
998 | 999 | ||
999 | if ((opts & OPT_l) && quiet <= 1) { | 1000 | if ((opts & OPT_l) && quiet <= 1) { |
diff --git a/console-tools/Config.src b/console-tools/Config.src index e6587ade4..c30caf0e1 100644 --- a/console-tools/Config.src +++ b/console-tools/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "Console Utilities" | 6 | menu "Console Utilities" |
diff --git a/coreutils/Config.src b/coreutils/Config.src index 7a8a3a634..1bded03a6 100644 --- a/coreutils/Config.src +++ b/coreutils/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "Coreutils" | 6 | menu "Coreutils" |
diff --git a/coreutils/cp.c b/coreutils/cp.c index 455bffbba..ae60623d3 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c | |||
@@ -24,6 +24,11 @@ | |||
24 | //config: help | 24 | //config: help |
25 | //config: Enable long options. | 25 | //config: Enable long options. |
26 | //config: Also add support for --parents option. | 26 | //config: Also add support for --parents option. |
27 | //config: | ||
28 | //config:config FEATURE_CP_REFLINK | ||
29 | //config: bool "Enable --reflink[=auto]" | ||
30 | //config: default y | ||
31 | //config: depends on FEATURE_CP_LONG_OPTIONS | ||
27 | 32 | ||
28 | //applet:IF_CP(APPLET_NOEXEC(cp, cp, BB_DIR_BIN, BB_SUID_DROP, cp)) | 33 | //applet:IF_CP(APPLET_NOEXEC(cp, cp, BB_DIR_BIN, BB_SUID_DROP, cp)) |
29 | /* NOEXEC despite cases when it can be a "runner" (cp -r LARGE_DIR NEW_DIR) */ | 34 | /* NOEXEC despite cases when it can be a "runner" (cp -r LARGE_DIR NEW_DIR) */ |
@@ -72,10 +77,14 @@ int cp_main(int argc, char **argv) | |||
72 | #if ENABLE_FEATURE_CP_LONG_OPTIONS | 77 | #if ENABLE_FEATURE_CP_LONG_OPTIONS |
73 | /*OPT_rmdest = FILEUTILS_RMDEST = 1 << FILEUTILS_CP_OPTNUM */ | 78 | /*OPT_rmdest = FILEUTILS_RMDEST = 1 << FILEUTILS_CP_OPTNUM */ |
74 | OPT_parents = 1 << (FILEUTILS_CP_OPTNUM+1), | 79 | OPT_parents = 1 << (FILEUTILS_CP_OPTNUM+1), |
80 | OPT_reflink = 1 << (FILEUTILS_CP_OPTNUM+2), | ||
75 | #endif | 81 | #endif |
76 | }; | 82 | }; |
77 | 83 | ||
78 | #if ENABLE_FEATURE_CP_LONG_OPTIONS | 84 | #if ENABLE_FEATURE_CP_LONG_OPTIONS |
85 | # if ENABLE_FEATURE_CP_REFLINK | ||
86 | char *reflink = NULL; | ||
87 | # endif | ||
79 | flags = getopt32long(argv, "^" | 88 | flags = getopt32long(argv, "^" |
80 | FILEUTILS_CP_OPTSTR | 89 | FILEUTILS_CP_OPTSTR |
81 | "\0" | 90 | "\0" |
@@ -99,7 +108,22 @@ int cp_main(int argc, char **argv) | |||
99 | "update\0" No_argument "u" | 108 | "update\0" No_argument "u" |
100 | "remove-destination\0" No_argument "\xff" | 109 | "remove-destination\0" No_argument "\xff" |
101 | "parents\0" No_argument "\xfe" | 110 | "parents\0" No_argument "\xfe" |
111 | # if ENABLE_FEATURE_CP_REFLINK | ||
112 | "reflink\0" Optional_argument "\xfd" | ||
113 | , &reflink | ||
114 | # endif | ||
102 | ); | 115 | ); |
116 | # if ENABLE_FEATURE_CP_REFLINK | ||
117 | BUILD_BUG_ON(OPT_reflink != FILEUTILS_REFLINK); | ||
118 | if (flags & FILEUTILS_REFLINK) { | ||
119 | if (!reflink) | ||
120 | flags |= FILEUTILS_REFLINK_ALWAYS; | ||
121 | else if (strcmp(reflink, "always") == 0) | ||
122 | flags |= FILEUTILS_REFLINK_ALWAYS; | ||
123 | else if (strcmp(reflink, "auto") != 0) | ||
124 | bb_show_usage(); | ||
125 | } | ||
126 | # endif | ||
103 | #else | 127 | #else |
104 | flags = getopt32(argv, "^" | 128 | flags = getopt32(argv, "^" |
105 | FILEUTILS_CP_OPTSTR | 129 | FILEUTILS_CP_OPTSTR |
diff --git a/coreutils/install.c b/coreutils/install.c index 2e4dc257f..8270490bd 100644 --- a/coreutils/install.c +++ b/coreutils/install.c | |||
@@ -214,7 +214,11 @@ int install_main(int argc, char **argv) | |||
214 | dest = last; | 214 | dest = last; |
215 | if (opts & OPT_MKDIR_LEADING) { | 215 | if (opts & OPT_MKDIR_LEADING) { |
216 | char *ddir = xstrdup(dest); | 216 | char *ddir = xstrdup(dest); |
217 | bb_make_directory(dirname(ddir), 0755, mkdir_flags); | 217 | /* |
218 | * -D -t DIR1/DIR2/F3 FILE: create DIR1/DIR2/F3, copy FILE there | ||
219 | * -D FILE DIR1/DIR2/F3: create DIR1/DIR2, copy FILE there as F3 | ||
220 | */ | ||
221 | bb_make_directory((opts & OPT_TARGET) ? ddir : dirname(ddir), 0755, mkdir_flags); | ||
218 | /* errors are not checked. copy_file | 222 | /* errors are not checked. copy_file |
219 | * will fail if dir is not created. | 223 | * will fail if dir is not created. |
220 | */ | 224 | */ |
diff --git a/coreutils/nproc.c b/coreutils/nproc.c index 336b176ca..0ea8d1001 100644 --- a/coreutils/nproc.c +++ b/coreutils/nproc.c | |||
@@ -14,10 +14,14 @@ | |||
14 | //kbuild:lib-$(CONFIG_NPROC) += nproc.o | 14 | //kbuild:lib-$(CONFIG_NPROC) += nproc.o |
15 | 15 | ||
16 | //usage:#define nproc_trivial_usage | 16 | //usage:#define nproc_trivial_usage |
17 | //usage: "" | 17 | //usage: ""IF_LONG_OPTS("--all --ignore=N") |
18 | //TODO: "[--all] [--ignore=N]" | ||
19 | //usage:#define nproc_full_usage "\n\n" | 18 | //usage:#define nproc_full_usage "\n\n" |
20 | //usage: "Print number of CPUs" | 19 | //usage: "Print number of available CPUs" |
20 | //usage: IF_LONG_OPTS( | ||
21 | //usage: "\n" | ||
22 | //usage: "\n --all Number of installed CPUs" | ||
23 | //usage: "\n --ignore=N Exclude N CPUs" | ||
24 | //usage: ) | ||
21 | 25 | ||
22 | #include <sched.h> | 26 | #include <sched.h> |
23 | #include "libbb.h" | 27 | #include "libbb.h" |
@@ -26,13 +30,30 @@ int nproc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |||
26 | int nproc_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | 30 | int nproc_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) |
27 | { | 31 | { |
28 | unsigned long mask[1024]; | 32 | unsigned long mask[1024]; |
29 | unsigned i, count = 0; | 33 | int count = 0; |
30 | 34 | #if ENABLE_LONG_OPTS | |
31 | //getopt32(argv, ""); | 35 | int ignore = 0; |
32 | 36 | int opts = getopt32long(argv, "\xfe:+", | |
33 | //if --all, count /sys/devices/system/cpu/cpuN dirs, else: | 37 | "ignore\0" Required_argument "\xfe" |
38 | "all\0" No_argument "\xff" | ||
39 | , &ignore | ||
40 | ); | ||
34 | 41 | ||
42 | if (opts & (1 << 1)) { | ||
43 | DIR *cpusd = opendir("/sys/devices/system/cpu"); | ||
44 | if (cpusd) { | ||
45 | struct dirent *de; | ||
46 | while (NULL != (de = readdir(cpusd))) { | ||
47 | char *cpuid = strstr(de->d_name, "cpu"); | ||
48 | if (cpuid && isdigit(cpuid[strlen(cpuid) - 1])) | ||
49 | count++; | ||
50 | } | ||
51 | closedir(cpusd); | ||
52 | } | ||
53 | } else | ||
54 | #endif | ||
35 | if (sched_getaffinity(0, sizeof(mask), (void*)mask) == 0) { | 55 | if (sched_getaffinity(0, sizeof(mask), (void*)mask) == 0) { |
56 | int i; | ||
36 | for (i = 0; i < ARRAY_SIZE(mask); i++) { | 57 | for (i = 0; i < ARRAY_SIZE(mask); i++) { |
37 | unsigned long m = mask[i]; | 58 | unsigned long m = mask[i]; |
38 | while (m) { | 59 | while (m) { |
@@ -42,8 +63,11 @@ int nproc_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
42 | } | 63 | } |
43 | } | 64 | } |
44 | } | 65 | } |
45 | if (count == 0) | 66 | |
46 | count++; | 67 | IF_LONG_OPTS(count -= ignore;) |
68 | if (count <= 0) | ||
69 | count = 1; | ||
70 | |||
47 | printf("%u\n", count); | 71 | printf("%u\n", count); |
48 | 72 | ||
49 | return 0; | 73 | return 0; |
diff --git a/coreutils/readlink.c b/coreutils/readlink.c index b8e327d11..49361cea0 100644 --- a/coreutils/readlink.c +++ b/coreutils/readlink.c | |||
@@ -86,7 +86,7 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) | |||
86 | 86 | ||
87 | /* NOFORK: only one alloc is allowed; must free */ | 87 | /* NOFORK: only one alloc is allowed; must free */ |
88 | if (opt & 1) { /* -f */ | 88 | if (opt & 1) { /* -f */ |
89 | buf = xmalloc_realpath(fname); | 89 | buf = xmalloc_realpath_coreutils(fname); |
90 | } else { | 90 | } else { |
91 | buf = xmalloc_readlink_or_warn(fname); | 91 | buf = xmalloc_readlink_or_warn(fname); |
92 | } | 92 | } |
diff --git a/coreutils/realpath.c b/coreutils/realpath.c index aa878fcd2..43923681c 100644 --- a/coreutils/realpath.c +++ b/coreutils/realpath.c | |||
@@ -38,7 +38,7 @@ int realpath_main(int argc UNUSED_PARAM, char **argv) | |||
38 | 38 | ||
39 | do { | 39 | do { |
40 | /* NOFORK: only one alloc is allowed; must free */ | 40 | /* NOFORK: only one alloc is allowed; must free */ |
41 | char *resolved_path = xmalloc_realpath(*argv); | 41 | char *resolved_path = xmalloc_realpath_coreutils(*argv); |
42 | if (resolved_path != NULL) { | 42 | if (resolved_path != NULL) { |
43 | puts(resolved_path); | 43 | puts(resolved_path); |
44 | free(resolved_path); | 44 | free(resolved_path); |
diff --git a/coreutils/sort.c b/coreutils/sort.c index 4d741e76d..05e5c9071 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c | |||
@@ -60,6 +60,7 @@ | |||
60 | //usage: IF_FEATURE_SORT_BIG( | 60 | //usage: IF_FEATURE_SORT_BIG( |
61 | //usage: "\n -g General numerical sort" | 61 | //usage: "\n -g General numerical sort" |
62 | //usage: "\n -M Sort month" | 62 | //usage: "\n -M Sort month" |
63 | //usage: "\n -V Sort version" | ||
63 | //usage: "\n -t CHAR Field separator" | 64 | //usage: "\n -t CHAR Field separator" |
64 | //usage: "\n -k N[,M] Sort by Nth field" | 65 | //usage: "\n -k N[,M] Sort by Nth field" |
65 | //usage: ) | 66 | //usage: ) |
@@ -91,32 +92,33 @@ | |||
91 | 92 | ||
92 | /* These are sort types */ | 93 | /* These are sort types */ |
93 | enum { | 94 | enum { |
94 | FLAG_n = 1, /* Numeric sort */ | 95 | FLAG_n = 1 << 0, /* Numeric sort */ |
95 | FLAG_g = 2, /* Sort using strtod() */ | 96 | FLAG_g = 1 << 1, /* Sort using strtod() */ |
96 | FLAG_M = 4, /* Sort date */ | 97 | FLAG_M = 1 << 2, /* Sort date */ |
98 | FLAG_V = 1 << 3, /* Sort version */ | ||
97 | /* ucsz apply to root level only, not keys. b at root level implies bb */ | 99 | /* ucsz apply to root level only, not keys. b at root level implies bb */ |
98 | FLAG_u = 8, /* Unique */ | 100 | FLAG_u = 1 << 4, /* Unique */ |
99 | FLAG_c = 0x10, /* Check: no output, exit(!ordered) */ | 101 | FLAG_c = 1 << 5, /* Check: no output, exit(!ordered) */ |
100 | FLAG_s = 0x20, /* Stable sort, no ascii fallback at end */ | 102 | FLAG_s = 1 << 6, /* Stable sort, no ascii fallback at end */ |
101 | FLAG_z = 0x40, /* Input and output is NUL terminated, not \n */ | 103 | FLAG_z = 1 << 7, /* Input and output is NUL terminated, not \n */ |
102 | /* These can be applied to search keys, the previous four can't */ | 104 | /* These can be applied to search keys, the previous four can't */ |
103 | FLAG_b = 0x80, /* Ignore leading blanks */ | 105 | FLAG_b = 1 << 8, /* Ignore leading blanks */ |
104 | FLAG_r = 0x100, /* Reverse */ | 106 | FLAG_r = 1 << 9, /* Reverse */ |
105 | FLAG_d = 0x200, /* Ignore !(isalnum()|isspace()) */ | 107 | FLAG_d = 1 << 10, /* Ignore !(isalnum()|isspace()) */ |
106 | FLAG_f = 0x400, /* Force uppercase */ | 108 | FLAG_f = 1 << 11, /* Force uppercase */ |
107 | FLAG_i = 0x800, /* Ignore !isprint() */ | 109 | FLAG_i = 1 << 12, /* Ignore !isprint() */ |
108 | FLAG_m = 0x1000, /* ignored: merge already sorted files; do not sort */ | 110 | FLAG_m = 1 << 13, /* ignored: merge already sorted files; do not sort */ |
109 | FLAG_S = 0x2000, /* ignored: -S, --buffer-size=SIZE */ | 111 | FLAG_S = 1 << 14, /* ignored: -S, --buffer-size=SIZE */ |
110 | FLAG_T = 0x4000, /* ignored: -T, --temporary-directory=DIR */ | 112 | FLAG_T = 1 << 15, /* ignored: -T, --temporary-directory=DIR */ |
111 | FLAG_o = 0x8000, | 113 | FLAG_o = 1 << 16, |
112 | FLAG_k = 0x10000, | 114 | FLAG_k = 1 << 17, |
113 | FLAG_t = 0x20000, | 115 | FLAG_t = 1 << 18, |
114 | FLAG_bb = 0x80000000, /* Ignore trailing blanks */ | 116 | FLAG_bb = 0x80000000, /* Ignore trailing blanks */ |
115 | FLAG_no_tie_break = 0x40000000, | 117 | FLAG_no_tie_break = 0x40000000, |
116 | }; | 118 | }; |
117 | 119 | ||
118 | static const char sort_opt_str[] ALIGN1 = "^" | 120 | static const char sort_opt_str[] ALIGN1 = "^" |
119 | "ngMucszbrdfimS:T:o:k:*t:" | 121 | "ngMVucszbrdfimS:T:o:k:*t:" |
120 | "\0" "o--o:t--t"/*-t, -o: at most one of each*/; | 122 | "\0" "o--o:t--t"/*-t, -o: at most one of each*/; |
121 | /* | 123 | /* |
122 | * OPT_STR must not be string literal, needs to have stable address: | 124 | * OPT_STR must not be string literal, needs to have stable address: |
@@ -273,10 +275,15 @@ static int compare_keys(const void *xarg, const void *yarg) | |||
273 | y = *(char **)yarg; | 275 | y = *(char **)yarg; |
274 | #endif | 276 | #endif |
275 | /* Perform actual comparison */ | 277 | /* Perform actual comparison */ |
276 | switch (flags & (FLAG_n | FLAG_M | FLAG_g)) { | 278 | switch (flags & (FLAG_n | FLAG_g | FLAG_M | FLAG_V)) { |
277 | default: | 279 | default: |
278 | bb_error_msg_and_die("unknown sort type"); | 280 | bb_error_msg_and_die("unknown sort type"); |
279 | break; | 281 | break; |
282 | #if defined(HAVE_STRVERSCMP) && HAVE_STRVERSCMP == 1 | ||
283 | case FLAG_V: | ||
284 | retval = strverscmp(x, y); | ||
285 | break; | ||
286 | #endif | ||
280 | /* Ascii sort */ | 287 | /* Ascii sort */ |
281 | case 0: | 288 | case 0: |
282 | #if ENABLE_LOCALE_SUPPORT | 289 | #if ENABLE_LOCALE_SUPPORT |
diff --git a/debianutils/Config.src b/debianutils/Config.src index 61daeb047..17b0d8945 100644 --- a/debianutils/Config.src +++ b/debianutils/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "Debian Utilities" | 6 | menu "Debian Utilities" |
diff --git a/docs/Kconfig-language.txt b/docs/Kconfig-language.txt new file mode 100644 index 000000000..0ba8932ba --- /dev/null +++ b/docs/Kconfig-language.txt | |||
@@ -0,0 +1,255 @@ | |||
1 | Introduction | ||
2 | ------------ | ||
3 | |||
4 | The configuration database is collection of configuration options | ||
5 | organized in a tree structure: | ||
6 | |||
7 | +- Code maturity level options | ||
8 | | +- Prompt for development and/or incomplete code/drivers | ||
9 | +- General setup | ||
10 | | +- Networking support | ||
11 | | +- System V IPC | ||
12 | | +- BSD Process Accounting | ||
13 | | +- Sysctl support | ||
14 | +- Loadable module support | ||
15 | | +- Enable loadable module support | ||
16 | | +- Set version information on all module symbols | ||
17 | | +- Kernel module loader | ||
18 | +- ... | ||
19 | |||
20 | Every entry has its own dependencies. These dependencies are used | ||
21 | to determine the visible of an entry. Any child entry is only | ||
22 | visible if its parent entry is also visible. | ||
23 | |||
24 | Menu entries | ||
25 | ------------ | ||
26 | |||
27 | Most entries define a config option, all other entries help to organize | ||
28 | them. A single configuration option is defined like this: | ||
29 | |||
30 | config MODVERSIONS | ||
31 | bool "Set version information on all module symbols" | ||
32 | depends MODULES | ||
33 | help | ||
34 | Usually, modules have to be recompiled whenever you switch to a new | ||
35 | kernel. ... | ||
36 | |||
37 | Every line starts with a key word and can be followed by multiple | ||
38 | arguments. "config" starts a new config entry. The following lines | ||
39 | define attributes for this config option. Attributes can be the type of | ||
40 | the config option, input prompt, dependencies, help text and default | ||
41 | values. A config option can be defined multiple times with the same | ||
42 | name, but every definition can have only a single input prompt and the | ||
43 | type must not conflict. | ||
44 | |||
45 | Menu attributes | ||
46 | --------------- | ||
47 | |||
48 | A menu entry can have a number of attributes. Not all of them are | ||
49 | applicable everywhere (see syntax). | ||
50 | |||
51 | - type definition: "bool"/"tristate"/"string"/"hex"/"integer" | ||
52 | Every config option must have a type. There are only two basic types: | ||
53 | tristate and string, the other types base on these two. The type | ||
54 | definition optionally accepts an input prompt, so these two examples | ||
55 | are equivalent: | ||
56 | |||
57 | bool "Networking support" | ||
58 | and | ||
59 | bool | ||
60 | prompt "Networking support" | ||
61 | |||
62 | - input prompt: "prompt" <prompt> ["if" <expr>] | ||
63 | Every menu entry can have at most one prompt, which is used to display | ||
64 | to the user. Optionally dependencies only for this prompt can be added | ||
65 | with "if". | ||
66 | |||
67 | - default value: "default" <symbol> ["if" <expr>] | ||
68 | A config option can have any number of default values. If multiple | ||
69 | default values are visible, only the first defined one is active. | ||
70 | Default values are not limited to the menu entry, where they are | ||
71 | defined, this means the default can be defined somewhere else or be | ||
72 | overridden by an earlier definition. | ||
73 | The default value is only assigned to the config symbol if no other | ||
74 | value was set by the user (via the input prompt above). If an input | ||
75 | prompt is visible the default value is presented to the user and can | ||
76 | be overridden by him. | ||
77 | Optionally dependencies only for this default value can be added with | ||
78 | "if". | ||
79 | |||
80 | - dependencies: "depends on"/"requires" <expr> | ||
81 | This defines a dependency for this menu entry. If multiple | ||
82 | dependencies are defined they are connected with '&&'. Dependencies | ||
83 | are applied to all other options within this menu entry (which also | ||
84 | accept "if" expression), so these two examples are equivalent: | ||
85 | |||
86 | bool "foo" if BAR | ||
87 | default y if BAR | ||
88 | and | ||
89 | depends on BAR | ||
90 | bool "foo" | ||
91 | default y | ||
92 | |||
93 | - help text: "help" | ||
94 | This defines a help text. The end of the help text is determined by | ||
95 | the level indentation, this means it ends at the first line which has | ||
96 | a smaller indentation than the first line of the help text. | ||
97 | |||
98 | |||
99 | Menu dependencies | ||
100 | ----------------- | ||
101 | |||
102 | Dependencies define the visibility of a menu entry and can also reduce | ||
103 | the input range of tristate symbols. The tristate logic used in the | ||
104 | expressions uses one more state than normal boolean logic to express the | ||
105 | module state. Dependency expressions have the following syntax: | ||
106 | |||
107 | <expr> ::= <symbol> (1) | ||
108 | <symbol> '=' <symbol> (2) | ||
109 | <symbol> '!=' <symbol> (3) | ||
110 | '(' <expr> ')' (4) | ||
111 | '!' <expr> (5) | ||
112 | <expr> '||' <expr> (6) | ||
113 | <expr> '&&' <expr> (7) | ||
114 | |||
115 | Expressions are listed in decreasing order of precedence. | ||
116 | |||
117 | (1) Convert the symbol into an expression. Boolean and tristate symbols | ||
118 | are simply converted into the respective expression values. All | ||
119 | other symbol types result in 'n'. | ||
120 | (2) If the values of both symbols are equal, it returns 'y', | ||
121 | otherwise 'n'. | ||
122 | (3) If the values of both symbols are equal, it returns 'n', | ||
123 | otherwise 'y'. | ||
124 | (4) Returns the value of the expression. Used to override precedence. | ||
125 | (5) Returns the result of (2-/expr/). | ||
126 | (6) Returns the result of min(/expr/, /expr/). | ||
127 | (7) Returns the result of max(/expr/, /expr/). | ||
128 | |||
129 | An expression can have a value of 'n', 'm' or 'y' (or 0, 1, 2 | ||
130 | respectively for calculations). A menu entry becomes visible when it's | ||
131 | expression evaluates to 'm' or 'y'. | ||
132 | |||
133 | There are two type of symbols: constant and nonconstant symbols. | ||
134 | Nonconstant symbols are the most common ones and are defined with the | ||
135 | 'config' statement. Nonconstant symbols consist entirely of alphanumeric | ||
136 | characters or underscores. | ||
137 | Constant symbols are only part of expressions. Constant symbols are | ||
138 | always surrounded by single or double quotes. Within the quote any | ||
139 | other character is allowed and the quotes can be escaped using '\'. | ||
140 | |||
141 | Menu structure | ||
142 | -------------- | ||
143 | |||
144 | The position of a menu entry in the tree is determined in two ways. First | ||
145 | it can be specified explicitely: | ||
146 | |||
147 | menu "Network device support" | ||
148 | depends NET | ||
149 | |||
150 | config NETDEVICES | ||
151 | ... | ||
152 | |||
153 | endmenu | ||
154 | |||
155 | All entries within the "menu" ... "endmenu" block become a submenu of | ||
156 | "Network device support". All subentries inherit the dependencies from | ||
157 | the menu entry, e.g. this means the dependency "NET" is added to the | ||
158 | dependency list of the config option NETDEVICES. | ||
159 | |||
160 | The other way to generate the menu structure is done by analyzing the | ||
161 | dependencies. If a menu entry somehow depends on the previous entry, it | ||
162 | can be made a submenu of it. First the the previous (parent) symbol must | ||
163 | be part of the dependency list and then one of these two condititions | ||
164 | must be true: | ||
165 | - the child entry must become invisible, if the parent is set to 'n' | ||
166 | - the child entry must only be visible, if the parent is visible | ||
167 | |||
168 | config MODULES | ||
169 | bool "Enable loadable module support" | ||
170 | |||
171 | config MODVERSIONS | ||
172 | bool "Set version information on all module symbols" | ||
173 | depends MODULES | ||
174 | |||
175 | comment "module support disabled" | ||
176 | depends !MODULES | ||
177 | |||
178 | MODVERSIONS directly depends on MODULES, this means it's only visible if | ||
179 | MODULES is different from 'n'. The comment on the other hand is always | ||
180 | visible when MODULES it's visible (the (empty) dependency of MODULES is | ||
181 | also part of the comment dependencies). | ||
182 | |||
183 | |||
184 | Kconfig syntax | ||
185 | -------------- | ||
186 | |||
187 | The configuration file describes a series of menu entries, where every | ||
188 | line starts with a keyword (except help texts). The following keywords | ||
189 | end a menu entry: | ||
190 | - config | ||
191 | - choice/endchoice | ||
192 | - comment | ||
193 | - menu/endmenu | ||
194 | - if/endif | ||
195 | - source | ||
196 | The first four also start the definition of a menu entry. | ||
197 | |||
198 | config: | ||
199 | |||
200 | "config" <symbol> | ||
201 | <config options> | ||
202 | |||
203 | This defines a config symbol <symbol> and accepts any of above | ||
204 | attributes as options. | ||
205 | |||
206 | choices: | ||
207 | |||
208 | "choice" | ||
209 | <choice options> | ||
210 | <choice block> | ||
211 | "endchoice" | ||
212 | |||
213 | This defines a choice group and accepts any of above attributes as | ||
214 | options. A choice can only be of type bool or tristate, while a boolean | ||
215 | choice only allows a single config entry to be selected, a tristate | ||
216 | choice also allows any number of config entries to be set to 'm'. This | ||
217 | can be used if multiple drivers for a single hardware exists and only a | ||
218 | single driver can be compiled/loaded into the kernel, but all drivers | ||
219 | can be compiled as modules. | ||
220 | A choice accepts another option "optional", which allows to set the | ||
221 | choice to 'n' and no entry needs to be selected. | ||
222 | |||
223 | comment: | ||
224 | |||
225 | "comment" <prompt> | ||
226 | <comment options> | ||
227 | |||
228 | This defines a comment which is displayed to the user during the | ||
229 | configuration process and is also echoed to the output files. The only | ||
230 | possible options are dependencies. | ||
231 | |||
232 | menu: | ||
233 | |||
234 | "menu" <prompt> | ||
235 | <menu options> | ||
236 | <menu block> | ||
237 | "endmenu" | ||
238 | |||
239 | This defines a menu block, see "Menu structure" above for more | ||
240 | information. The only possible options are dependencies. | ||
241 | |||
242 | if: | ||
243 | |||
244 | "if" <expr> | ||
245 | <if block> | ||
246 | "endif" | ||
247 | |||
248 | This defines an if block. The dependency expression <expr> is appended | ||
249 | to all enclosed menu entries. | ||
250 | |||
251 | source: | ||
252 | |||
253 | "source" <prompt> | ||
254 | |||
255 | This reads the specified configuration file. This file is always parsed. | ||
diff --git a/e2fsprogs/Config.src b/e2fsprogs/Config.src index a20d849e6..ad15f470c 100644 --- a/e2fsprogs/Config.src +++ b/e2fsprogs/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "Linux Ext2 FS Progs" | 6 | menu "Linux Ext2 FS Progs" |
diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c index 1c285bb92..f5aa3dbe4 100644 --- a/e2fsprogs/fsck.c +++ b/e2fsprogs/fsck.c | |||
@@ -414,7 +414,7 @@ static void kill_all_if_got_signal(void) | |||
414 | static int wait_one(int flags) | 414 | static int wait_one(int flags) |
415 | { | 415 | { |
416 | int status; | 416 | int status; |
417 | int sig; | 417 | int exitcode; |
418 | struct fsck_instance *inst, *prev; | 418 | struct fsck_instance *inst, *prev; |
419 | pid_t pid; | 419 | pid_t pid; |
420 | 420 | ||
@@ -448,15 +448,16 @@ static int wait_one(int flags) | |||
448 | } | 448 | } |
449 | child_died: | 449 | child_died: |
450 | 450 | ||
451 | status = WEXITSTATUS(status); | 451 | exitcode = WEXITSTATUS(status); |
452 | if (WIFSIGNALED(status)) { | 452 | if (WIFSIGNALED(status)) { |
453 | unsigned sig; | ||
453 | sig = WTERMSIG(status); | 454 | sig = WTERMSIG(status); |
454 | status = EXIT_UNCORRECTED; | 455 | exitcode = EXIT_UNCORRECTED; |
455 | if (sig != SIGINT) { | 456 | if (sig != SIGINT) { |
456 | printf("Warning: %s %s terminated " | 457 | printf("Warning: %s %s terminated " |
457 | "by signal %d\n", | 458 | "by signal %u\n", |
458 | inst->prog, inst->device, sig); | 459 | inst->prog, inst->device, sig); |
459 | status = EXIT_ERROR; | 460 | exitcode = EXIT_ERROR; |
460 | } | 461 | } |
461 | } | 462 | } |
462 | 463 | ||
@@ -492,12 +493,12 @@ static int wait_one(int flags) | |||
492 | else | 493 | else |
493 | G.instance_list = inst->next; | 494 | G.instance_list = inst->next; |
494 | if (G.verbose > 1) | 495 | if (G.verbose > 1) |
495 | printf("Finished with %s (exit status %d)\n", | 496 | printf("Finished with %s (exit status %u)\n", |
496 | inst->device, status); | 497 | inst->device, exitcode); |
497 | G.num_running--; | 498 | G.num_running--; |
498 | free_instance(inst); | 499 | free_instance(inst); |
499 | 500 | ||
500 | return status; | 501 | return exitcode; |
501 | } | 502 | } |
502 | 503 | ||
503 | /* | 504 | /* |
diff --git a/editors/Config.src b/editors/Config.src index 0920bc494..3b2e4a6c0 100644 --- a/editors/Config.src +++ b/editors/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "Editors" | 6 | menu "Editors" |
diff --git a/editors/vi.c b/editors/vi.c index 26487bee6..e79787977 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -752,7 +752,10 @@ static int query_screen_dimensions(void) | |||
752 | return err; | 752 | return err; |
753 | } | 753 | } |
754 | #else | 754 | #else |
755 | # define query_screen_dimensions() (0) | 755 | static ALWAYS_INLINE int query_screen_dimensions(void) |
756 | { | ||
757 | return 0; | ||
758 | } | ||
756 | #endif | 759 | #endif |
757 | 760 | ||
758 | static void edit_file(char *fn) | 761 | static void edit_file(char *fn) |
@@ -1069,10 +1072,13 @@ static void colon(char *buf) | |||
1069 | not_implemented(p); | 1072 | not_implemented(p); |
1070 | #else | 1073 | #else |
1071 | 1074 | ||
1072 | char c, *orig_buf, *buf1, *q, *r; | 1075 | char c, *buf1, *q, *r; |
1073 | char *fn, cmd[MAX_INPUT_LEN], args[MAX_INPUT_LEN]; | 1076 | char *fn, cmd[MAX_INPUT_LEN], args[MAX_INPUT_LEN]; |
1074 | int i, l, li, b, e; | 1077 | int i, l, li, b, e; |
1075 | int useforce; | 1078 | int useforce; |
1079 | # if ENABLE_FEATURE_VI_SEARCH || ENABLE_FEATURE_ALLOW_EXEC | ||
1080 | char *orig_buf; | ||
1081 | # endif | ||
1076 | 1082 | ||
1077 | // :3154 // if (-e line 3154) goto it else stay put | 1083 | // :3154 // if (-e line 3154) goto it else stay put |
1078 | // :4,33w! foo // write a portion of buffer to file "foo" | 1084 | // :4,33w! foo // write a portion of buffer to file "foo" |
@@ -1104,8 +1110,10 @@ static void colon(char *buf) | |||
1104 | // look for optional address(es) :. :1 :1,9 :'q,'a :% | 1110 | // look for optional address(es) :. :1 :1,9 :'q,'a :% |
1105 | buf = get_address(buf, &b, &e); | 1111 | buf = get_address(buf, &b, &e); |
1106 | 1112 | ||
1113 | # if ENABLE_FEATURE_VI_SEARCH || ENABLE_FEATURE_ALLOW_EXEC | ||
1107 | // remember orig command line | 1114 | // remember orig command line |
1108 | orig_buf = buf; | 1115 | orig_buf = buf; |
1116 | # endif | ||
1109 | 1117 | ||
1110 | // get the COMMAND into cmd[] | 1118 | // get the COMMAND into cmd[] |
1111 | buf1 = cmd; | 1119 | buf1 = cmd; |
@@ -1149,7 +1157,7 @@ static void colon(char *buf) | |||
1149 | dot_skip_over_ws(); | 1157 | dot_skip_over_ws(); |
1150 | } | 1158 | } |
1151 | } | 1159 | } |
1152 | #if ENABLE_FEATURE_ALLOW_EXEC | 1160 | # if ENABLE_FEATURE_ALLOW_EXEC |
1153 | else if (cmd[0] == '!') { // run a cmd | 1161 | else if (cmd[0] == '!') { // run a cmd |
1154 | int retcode; | 1162 | int retcode; |
1155 | // :!ls run the <cmd> | 1163 | // :!ls run the <cmd> |
@@ -1161,7 +1169,7 @@ static void colon(char *buf) | |||
1161 | rawmode(); | 1169 | rawmode(); |
1162 | Hit_Return(); // let user see results | 1170 | Hit_Return(); // let user see results |
1163 | } | 1171 | } |
1164 | #endif | 1172 | # endif |
1165 | else if (cmd[0] == '=' && !cmd[1]) { // where is the address | 1173 | else if (cmd[0] == '=' && !cmd[1]) { // where is the address |
1166 | if (b < 0) { // no addr given- use defaults | 1174 | if (b < 0) { // no addr given- use defaults |
1167 | b = e = count_lines(text, dot); | 1175 | b = e = count_lines(text, dot); |
@@ -1196,7 +1204,7 @@ static void colon(char *buf) | |||
1196 | 1204 | ||
1197 | size = init_text_buffer(fn); | 1205 | size = init_text_buffer(fn); |
1198 | 1206 | ||
1199 | #if ENABLE_FEATURE_VI_YANKMARK | 1207 | # if ENABLE_FEATURE_VI_YANKMARK |
1200 | if (Ureg >= 0 && Ureg < 28) { | 1208 | if (Ureg >= 0 && Ureg < 28) { |
1201 | free(reg[Ureg]); // free orig line reg- for 'U' | 1209 | free(reg[Ureg]); // free orig line reg- for 'U' |
1202 | reg[Ureg] = NULL; | 1210 | reg[Ureg] = NULL; |
@@ -1205,7 +1213,7 @@ static void colon(char *buf) | |||
1205 | free(reg[YDreg]); // free default yank/delete register | 1213 | free(reg[YDreg]); // free default yank/delete register |
1206 | reg[YDreg] = NULL; | 1214 | reg[YDreg] = NULL; |
1207 | } | 1215 | } |
1208 | #endif | 1216 | # endif |
1209 | // how many lines in text[]? | 1217 | // how many lines in text[]? |
1210 | li = count_lines(text, end - 1); | 1218 | li = count_lines(text, end - 1); |
1211 | status_line("'%s'%s" | 1219 | status_line("'%s'%s" |
@@ -1352,16 +1360,16 @@ static void colon(char *buf) | |||
1352 | optind = -1; /* start from 0th file */ | 1360 | optind = -1; /* start from 0th file */ |
1353 | editing = 0; | 1361 | editing = 0; |
1354 | } | 1362 | } |
1355 | #if ENABLE_FEATURE_VI_SET | 1363 | # if ENABLE_FEATURE_VI_SET |
1356 | } else if (strncmp(cmd, "set", i) == 0) { // set or clear features | 1364 | } else if (strncmp(cmd, "set", i) == 0) { // set or clear features |
1357 | #if ENABLE_FEATURE_VI_SETOPTS | 1365 | # if ENABLE_FEATURE_VI_SETOPTS |
1358 | char *argp; | 1366 | char *argp; |
1359 | #endif | 1367 | # endif |
1360 | i = 0; // offset into args | 1368 | i = 0; // offset into args |
1361 | // only blank is regarded as args delimiter. What about tab '\t'? | 1369 | // only blank is regarded as args delimiter. What about tab '\t'? |
1362 | if (!args[0] || strcasecmp(args, "all") == 0) { | 1370 | if (!args[0] || strcasecmp(args, "all") == 0) { |
1363 | // print out values of all options | 1371 | // print out values of all options |
1364 | #if ENABLE_FEATURE_VI_SETOPTS | 1372 | # if ENABLE_FEATURE_VI_SETOPTS |
1365 | status_line_bold( | 1373 | status_line_bold( |
1366 | "%sautoindent " | 1374 | "%sautoindent " |
1367 | "%sflash " | 1375 | "%sflash " |
@@ -1374,10 +1382,10 @@ static void colon(char *buf) | |||
1374 | showmatch ? "" : "no", | 1382 | showmatch ? "" : "no", |
1375 | tabstop | 1383 | tabstop |
1376 | ); | 1384 | ); |
1377 | #endif | 1385 | # endif |
1378 | goto ret; | 1386 | goto ret; |
1379 | } | 1387 | } |
1380 | #if ENABLE_FEATURE_VI_SETOPTS | 1388 | # if ENABLE_FEATURE_VI_SETOPTS |
1381 | argp = args; | 1389 | argp = args; |
1382 | while (*argp) { | 1390 | while (*argp) { |
1383 | if (strncmp(argp, "no", 2) == 0) | 1391 | if (strncmp(argp, "no", 2) == 0) |
@@ -1395,16 +1403,17 @@ static void colon(char *buf) | |||
1395 | argp = skip_non_whitespace(argp); | 1403 | argp = skip_non_whitespace(argp); |
1396 | argp = skip_whitespace(argp); | 1404 | argp = skip_whitespace(argp); |
1397 | } | 1405 | } |
1398 | #endif /* FEATURE_VI_SETOPTS */ | 1406 | # endif /* FEATURE_VI_SETOPTS */ |
1399 | #endif /* FEATURE_VI_SET */ | 1407 | # endif /* FEATURE_VI_SET */ |
1400 | #if ENABLE_FEATURE_VI_SEARCH | 1408 | |
1409 | # if ENABLE_FEATURE_VI_SEARCH | ||
1401 | } else if (cmd[0] == 's') { // substitute a pattern with a replacement pattern | 1410 | } else if (cmd[0] == 's') { // substitute a pattern with a replacement pattern |
1402 | char *F, *R, *flags; | 1411 | char *F, *R, *flags; |
1403 | size_t len_F, len_R; | 1412 | size_t len_F, len_R; |
1404 | int gflag; // global replace flag | 1413 | int gflag; // global replace flag |
1405 | #if ENABLE_FEATURE_VI_UNDO | 1414 | # if ENABLE_FEATURE_VI_UNDO |
1406 | int dont_chain_first_item = ALLOW_UNDO; | 1415 | int dont_chain_first_item = ALLOW_UNDO; |
1407 | #endif | 1416 | # endif |
1408 | 1417 | ||
1409 | // F points to the "find" pattern | 1418 | // F points to the "find" pattern |
1410 | // R points to the "replace" pattern | 1419 | // R points to the "replace" pattern |
@@ -1441,9 +1450,9 @@ static void colon(char *buf) | |||
1441 | // we found the "find" pattern - delete it | 1450 | // we found the "find" pattern - delete it |
1442 | // For undo support, the first item should not be chained | 1451 | // For undo support, the first item should not be chained |
1443 | text_hole_delete(found, found + len_F - 1, dont_chain_first_item); | 1452 | text_hole_delete(found, found + len_F - 1, dont_chain_first_item); |
1444 | #if ENABLE_FEATURE_VI_UNDO | 1453 | # if ENABLE_FEATURE_VI_UNDO |
1445 | dont_chain_first_item = ALLOW_UNDO_CHAIN; | 1454 | dont_chain_first_item = ALLOW_UNDO_CHAIN; |
1446 | #endif | 1455 | # endif |
1447 | // insert the "replace" patern | 1456 | // insert the "replace" patern |
1448 | bias = string_insert(found, R, ALLOW_UNDO_CHAIN); | 1457 | bias = string_insert(found, R, ALLOW_UNDO_CHAIN); |
1449 | found += bias; | 1458 | found += bias; |
@@ -1459,7 +1468,7 @@ static void colon(char *buf) | |||
1459 | } | 1468 | } |
1460 | q = next_line(ls); | 1469 | q = next_line(ls); |
1461 | } | 1470 | } |
1462 | #endif /* FEATURE_VI_SEARCH */ | 1471 | # endif /* FEATURE_VI_SEARCH */ |
1463 | } else if (strncmp(cmd, "version", i) == 0) { // show software version | 1472 | } else if (strncmp(cmd, "version", i) == 0) { // show software version |
1464 | status_line(BB_VER); | 1473 | status_line(BB_VER); |
1465 | } else if (strncmp(cmd, "write", i) == 0 // write text to file | 1474 | } else if (strncmp(cmd, "write", i) == 0 // write text to file |
@@ -1474,12 +1483,12 @@ static void colon(char *buf) | |||
1474 | if (args[0]) { | 1483 | if (args[0]) { |
1475 | fn = args; | 1484 | fn = args; |
1476 | } | 1485 | } |
1477 | #if ENABLE_FEATURE_VI_READONLY | 1486 | # if ENABLE_FEATURE_VI_READONLY |
1478 | if (readonly_mode && !useforce) { | 1487 | if (readonly_mode && !useforce) { |
1479 | status_line_bold("'%s' is read only", fn); | 1488 | status_line_bold("'%s' is read only", fn); |
1480 | goto ret; | 1489 | goto ret; |
1481 | } | 1490 | } |
1482 | #endif | 1491 | # endif |
1483 | //if (useforce) { | 1492 | //if (useforce) { |
1484 | // if "fn" is not write-able, chmod u+w | 1493 | // if "fn" is not write-able, chmod u+w |
1485 | // sprintf(syscmd, "chmod u+w %s", fn); | 1494 | // sprintf(syscmd, "chmod u+w %s", fn); |
@@ -1519,7 +1528,7 @@ static void colon(char *buf) | |||
1519 | } | 1528 | } |
1520 | } | 1529 | } |
1521 | } | 1530 | } |
1522 | #if ENABLE_FEATURE_VI_YANKMARK | 1531 | # if ENABLE_FEATURE_VI_YANKMARK |
1523 | } else if (strncmp(cmd, "yank", i) == 0) { // yank lines | 1532 | } else if (strncmp(cmd, "yank", i) == 0) { // yank lines |
1524 | if (b < 0) { // no addr given- use defaults | 1533 | if (b < 0) { // no addr given- use defaults |
1525 | q = begin_line(dot); // assume .,. for the range | 1534 | q = begin_line(dot); // assume .,. for the range |
@@ -1529,7 +1538,7 @@ static void colon(char *buf) | |||
1529 | li = count_lines(q, r); | 1538 | li = count_lines(q, r); |
1530 | status_line("Yank %d lines (%d chars) into [%c]", | 1539 | status_line("Yank %d lines (%d chars) into [%c]", |
1531 | li, strlen(reg[YDreg]), what_reg()); | 1540 | li, strlen(reg[YDreg]), what_reg()); |
1532 | #endif | 1541 | # endif |
1533 | } else { | 1542 | } else { |
1534 | // cmd unknown | 1543 | // cmd unknown |
1535 | not_implemented(cmd); | 1544 | not_implemented(cmd); |
@@ -1537,10 +1546,10 @@ static void colon(char *buf) | |||
1537 | ret: | 1546 | ret: |
1538 | dot = bound_dot(dot); // make sure "dot" is valid | 1547 | dot = bound_dot(dot); // make sure "dot" is valid |
1539 | return; | 1548 | return; |
1540 | #if ENABLE_FEATURE_VI_SEARCH | 1549 | # if ENABLE_FEATURE_VI_SEARCH |
1541 | colon_s_fail: | 1550 | colon_s_fail: |
1542 | status_line(":s expression missing delimiters"); | 1551 | status_line(":s expression missing delimiters"); |
1543 | #endif | 1552 | # endif |
1544 | #endif /* FEATURE_VI_COLON */ | 1553 | #endif /* FEATURE_VI_COLON */ |
1545 | } | 1554 | } |
1546 | 1555 | ||
diff --git a/examples/var_service/dhcp_if/README b/examples/var_service/dhcp_if/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/dhcp_if/README +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | The real README file is one directory up. | ||
2 | |||
3 | This directory's run script can have useful comments. | ||
4 | If it doesn't but you feel it should, please send a patch | ||
5 | to busybox's mailing list. | ||
diff --git a/examples/var_service/dhcp_if/dhcp_handler b/examples/var_service/dhcp_if/dhcp_handler index 3d44a6022..6a97e8543 100755 --- a/examples/var_service/dhcp_if/dhcp_handler +++ b/examples/var_service/dhcp_if/dhcp_handler | |||
@@ -52,7 +52,7 @@ if test x"$1" != x"bound" && test x"$1" != x"renew" ; then | |||
52 | rm "$file_ntpconf" | 52 | rm "$file_ntpconf" |
53 | rm "$dir_ipconf/$file_ipconf" | 53 | rm "$dir_ipconf/$file_ipconf" |
54 | rm "$dir_ntpconf/$file_ntpconf" | 54 | rm "$dir_ntpconf/$file_ntpconf" |
55 | sv u /var/service/fw | 55 | svc -u fw |
56 | exit | 56 | exit |
57 | fi | 57 | fi |
58 | 58 | ||
@@ -67,10 +67,10 @@ if test $? != 0; then | |||
67 | echo "Reconfiguring fw" | 67 | echo "Reconfiguring fw" |
68 | mkdir -p "$dir_ipconf" 2>/dev/null | 68 | mkdir -p "$dir_ipconf" 2>/dev/null |
69 | cp "$file_ipconf" "$dir_ipconf/$file_ipconf" | 69 | cp "$file_ipconf" "$dir_ipconf/$file_ipconf" |
70 | sv u /var/service/fw | 70 | svc -u fw |
71 | fi | 71 | fi |
72 | 72 | ||
73 | if test -d /var/service/ntpd; then | 73 | if test -d ../ntpd; then |
74 | ./convert2ntpconf "$file_ntpconf" | 74 | ./convert2ntpconf "$file_ntpconf" |
75 | # Reconfigure ntp server addresses if needed | 75 | # Reconfigure ntp server addresses if needed |
76 | diff --brief "$file_ntpconf" "$dir_ntpconf/$file_ntpconf" >/dev/null 2>&1 | 76 | diff --brief "$file_ntpconf" "$dir_ntpconf/$file_ntpconf" >/dev/null 2>&1 |
@@ -78,7 +78,7 @@ if test -d /var/service/ntpd; then | |||
78 | echo "Reconfiguring ntp" | 78 | echo "Reconfiguring ntp" |
79 | mkdir -p "$dir_ntpconf" 2>/dev/null | 79 | mkdir -p "$dir_ntpconf" 2>/dev/null |
80 | cp "$file_ntpconf" "$dir_ntpconf/$file_ntpconf" | 80 | cp "$file_ntpconf" "$dir_ntpconf/$file_ntpconf" |
81 | sv t /var/service/ntpd | 81 | svc -t ntpd |
82 | sv u /var/service/ntpd | 82 | svc -u ntpd |
83 | fi | 83 | fi |
84 | fi | 84 | fi |
diff --git a/examples/var_service/dhcp_if/finish b/examples/var_service/dhcp_if/finish index 5e7667a2d..8ce188336 100755 --- a/examples/var_service/dhcp_if/finish +++ b/examples/var_service/dhcp_if/finish | |||
@@ -14,4 +14,4 @@ rm "$file_ipconf" | |||
14 | rm "$file_ntpconf" | 14 | rm "$file_ntpconf" |
15 | rm "$dir_ipconf/$file_ipconf" | 15 | rm "$dir_ipconf/$file_ipconf" |
16 | rm "$dir_ntpconf/$file_ntpconf" | 16 | rm "$dir_ntpconf/$file_ntpconf" |
17 | sv u /var/service/fw | 17 | svc -u fw |
diff --git a/examples/var_service/dhcp_if/log/run b/examples/var_service/dhcp_if/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/dhcp_if/log/run +++ b/examples/var_service/dhcp_if/log/run | |||
@@ -1,21 +1,2 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | exec std_service_logger | |
3 | user=logger | ||
4 | |||
5 | logdir="/var/log/service/`(cd ..;basename $PWD)`" | ||
6 | mkdir -p "$logdir" 2>/dev/null | ||
7 | chown -R "$user": "$logdir" | ||
8 | chmod -R go-rwxst,u+rwX "$logdir" | ||
9 | rm -rf logdir | ||
10 | ln -s "$logdir" logdir | ||
11 | |||
12 | # make this dir accessible to logger | ||
13 | chmod a+rX . | ||
14 | |||
15 | exec >/dev/null | ||
16 | exec 2>&1 | ||
17 | exec \ | ||
18 | env - PATH="$PATH" \ | ||
19 | softlimit \ | ||
20 | setuidgid "$user" \ | ||
21 | svlogd -tt "$logdir" | ||
diff --git a/examples/var_service/dhcp_if/p_log b/examples/var_service/dhcp_if/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/dhcp_if/p_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | cat @* current | $PAGER | ||
diff --git a/examples/var_service/dhcp_if/w_log b/examples/var_service/dhcp_if/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/dhcp_if/w_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' | ||
diff --git a/examples/var_service/dhcp_if_pinger/README b/examples/var_service/dhcp_if_pinger/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/dhcp_if_pinger/README +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | The real README file is one directory up. | ||
2 | |||
3 | This directory's run script can have useful comments. | ||
4 | If it doesn't but you feel it should, please send a patch | ||
5 | to busybox's mailing list. | ||
diff --git a/examples/var_service/dhcp_if_pinger/run b/examples/var_service/dhcp_if_pinger/run index 8aca90c1a..25341243f 100755 --- a/examples/var_service/dhcp_if_pinger/run +++ b/examples/var_service/dhcp_if_pinger/run | |||
@@ -21,9 +21,9 @@ if test -f "$0.log"; then | |||
21 | mv "$0.log.new" "$0.log" | 21 | mv "$0.log.new" "$0.log" |
22 | fi | 22 | fi |
23 | 23 | ||
24 | test -f "/var/service/dhcp_$if/env.out" || exec env - sleep "$ping_time" | 24 | test -f "../dhcp_$if/env.out" || exec env - sleep "$ping_time" |
25 | 25 | ||
26 | . "/var/service/dhcp_$if/env.out" | 26 | . "../dhcp_$if/env.out" |
27 | test x"$router" != x"" || exec env - sleep "$ping_time" | 27 | test x"$router" != x"" || exec env - sleep "$ping_time" |
28 | 28 | ||
29 | #msg "Pinging $router" | 29 | #msg "Pinging $router" |
@@ -36,12 +36,12 @@ while true; do | |||
36 | env - sleep "$retry_time" | 36 | env - sleep "$retry_time" |
37 | done | 37 | done |
38 | 38 | ||
39 | test -d "/var/service/dhcp_$if" && { | 39 | test -d "../dhcp_$if" && { |
40 | msg "Restarting /var/service/dhcp_$if" | 40 | msg "Restarting dhcp_$if" |
41 | sv t "/var/service/dhcp_$if" | 41 | svc -t "dhcp_$if" |
42 | } | 42 | } |
43 | test -d "/var/service/supplicant_$if" && { | 43 | test -d "../supplicant_$if" && { |
44 | msg "Restarting /var/service/supplicant_$if" | 44 | msg "Restarting supplicant_$if" |
45 | sv t "/var/service/supplicant_$if" | 45 | svc -t "supplicant_$if" |
46 | } | 46 | } |
47 | exec env - sleep "$ping_time" | 47 | exec env - sleep "$ping_time" |
diff --git a/examples/var_service/dhcpd_if/README b/examples/var_service/dhcpd_if/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/dhcpd_if/README +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | The real README file is one directory up. | ||
2 | |||
3 | This directory's run script can have useful comments. | ||
4 | If it doesn't but you feel it should, please send a patch | ||
5 | to busybox's mailing list. | ||
diff --git a/examples/var_service/dhcpd_if/log/run b/examples/var_service/dhcpd_if/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/dhcpd_if/log/run +++ b/examples/var_service/dhcpd_if/log/run | |||
@@ -1,21 +1,2 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | exec std_service_logger | |
3 | user=logger | ||
4 | |||
5 | logdir="/var/log/service/`(cd ..;basename $PWD)`" | ||
6 | mkdir -p "$logdir" 2>/dev/null | ||
7 | chown -R "$user": "$logdir" | ||
8 | chmod -R go-rwxst,u+rwX "$logdir" | ||
9 | rm -rf logdir | ||
10 | ln -s "$logdir" logdir | ||
11 | |||
12 | # make this dir accessible to logger | ||
13 | chmod a+rX . | ||
14 | |||
15 | exec >/dev/null | ||
16 | exec 2>&1 | ||
17 | exec \ | ||
18 | env - PATH="$PATH" \ | ||
19 | softlimit \ | ||
20 | setuidgid "$user" \ | ||
21 | svlogd -tt "$logdir" | ||
diff --git a/examples/var_service/dhcpd_if/p_log b/examples/var_service/dhcpd_if/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/dhcpd_if/p_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | cat @* current | $PAGER | ||
diff --git a/examples/var_service/dhcpd_if/w_log b/examples/var_service/dhcpd_if/w_log deleted file mode 100755 index dba76c69b..000000000 --- a/examples/var_service/dhcpd_if/w_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir | ||
4 | watch -n1 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b0-$((w-2))' | ||
diff --git a/examples/var_service/dnsmasq/log/run b/examples/var_service/dnsmasq/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/dnsmasq/log/run +++ b/examples/var_service/dnsmasq/log/run | |||
@@ -1,21 +1,2 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | exec std_service_logger | |
3 | user=logger | ||
4 | |||
5 | logdir="/var/log/service/`(cd ..;basename $PWD)`" | ||
6 | mkdir -p "$logdir" 2>/dev/null | ||
7 | chown -R "$user": "$logdir" | ||
8 | chmod -R go-rwxst,u+rwX "$logdir" | ||
9 | rm -rf logdir | ||
10 | ln -s "$logdir" logdir | ||
11 | |||
12 | # make this dir accessible to logger | ||
13 | chmod a+rX . | ||
14 | |||
15 | exec >/dev/null | ||
16 | exec 2>&1 | ||
17 | exec \ | ||
18 | env - PATH="$PATH" \ | ||
19 | softlimit \ | ||
20 | setuidgid "$user" \ | ||
21 | svlogd -tt "$logdir" | ||
diff --git a/examples/var_service/dnsmasq/p_log b/examples/var_service/dnsmasq/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/dnsmasq/p_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | cat @* current | $PAGER | ||
diff --git a/examples/var_service/dnsmasq/w_log b/examples/var_service/dnsmasq/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/dnsmasq/w_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' | ||
diff --git a/examples/var_service/ftpd/README b/examples/var_service/ftpd/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/ftpd/README +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | The real README file is one directory up. | ||
2 | |||
3 | This directory's run script can have useful comments. | ||
4 | If it doesn't but you feel it should, please send a patch | ||
5 | to busybox's mailing list. | ||
diff --git a/examples/var_service/ftpd/log/run b/examples/var_service/ftpd/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/ftpd/log/run +++ b/examples/var_service/ftpd/log/run | |||
@@ -1,21 +1,2 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | exec std_service_logger | |
3 | user=logger | ||
4 | |||
5 | logdir="/var/log/service/`(cd ..;basename $PWD)`" | ||
6 | mkdir -p "$logdir" 2>/dev/null | ||
7 | chown -R "$user": "$logdir" | ||
8 | chmod -R go-rwxst,u+rwX "$logdir" | ||
9 | rm -rf logdir | ||
10 | ln -s "$logdir" logdir | ||
11 | |||
12 | # make this dir accessible to logger | ||
13 | chmod a+rX . | ||
14 | |||
15 | exec >/dev/null | ||
16 | exec 2>&1 | ||
17 | exec \ | ||
18 | env - PATH="$PATH" \ | ||
19 | softlimit \ | ||
20 | setuidgid "$user" \ | ||
21 | svlogd -tt "$logdir" | ||
diff --git a/examples/var_service/ftpd/p_log b/examples/var_service/ftpd/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/ftpd/p_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | cat @* current | $PAGER | ||
diff --git a/examples/var_service/ftpd/w_log b/examples/var_service/ftpd/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/ftpd/w_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' | ||
diff --git a/examples/var_service/fw/README b/examples/var_service/fw/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/fw/README +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | The real README file is one directory up. | ||
2 | |||
3 | This directory's run script can have useful comments. | ||
4 | If it doesn't but you feel it should, please send a patch | ||
5 | to busybox's mailing list. | ||
diff --git a/examples/var_service/fw/etc/dnsmasq_servers.conf b/examples/var_service/fw/etc/dnsmasq_servers.conf index 68313605f..c39fe6e43 100644 --- a/examples/var_service/fw/etc/dnsmasq_servers.conf +++ b/examples/var_service/fw/etc/dnsmasq_servers.conf | |||
@@ -35,4 +35,4 @@ $empty && echo "server=8.8.8.8" | |||
35 | $empty && echo "server=8.8.4.4" | 35 | $empty && echo "server=8.8.4.4" |
36 | 36 | ||
37 | # SIGHUP: make dnsmasq reload config | 37 | # SIGHUP: make dnsmasq reload config |
38 | sv h dnsmasq | 38 | svc -h dnsmasq |
diff --git a/examples/var_service/fw/run b/examples/var_service/fw/run index 1fd71cc01..41078d0ab 100755 --- a/examples/var_service/fw/run +++ b/examples/var_service/fw/run | |||
@@ -8,7 +8,7 @@ extif="if" | |||
8 | ext_open_tcp="22 80 88" # space-separated | 8 | ext_open_tcp="22 80 88" # space-separated |
9 | 9 | ||
10 | # Make ourself one-shot | 10 | # Make ourself one-shot |
11 | sv o . | 11 | svc -o . |
12 | # Debug | 12 | # Debug |
13 | #date '+%Y-%m-%d %H:%M:%S' >>"$0.log" | 13 | #date '+%Y-%m-%d %H:%M:%S' >>"$0.log" |
14 | 14 | ||
diff --git a/examples/var_service/getty_tty1/README b/examples/var_service/getty_tty1/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/getty_tty1/README +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | The real README file is one directory up. | ||
2 | |||
3 | This directory's run script can have useful comments. | ||
4 | If it doesn't but you feel it should, please send a patch | ||
5 | to busybox's mailing list. | ||
diff --git a/examples/var_service/getty_tty1/cfg b/examples/var_service/getty_tty1/cfg index 0f63e5233..ab973f738 100755 --- a/examples/var_service/getty_tty1/cfg +++ b/examples/var_service/getty_tty1/cfg | |||
@@ -10,7 +10,7 @@ ttyname=`tty` | |||
10 | ttybase="${ttyname%%[0123456789]*}" # strip numeric tail | 10 | ttybase="${ttyname%%[0123456789]*}" # strip numeric tail |
11 | 11 | ||
12 | if test x"$ttybase" = x"/dev/vc/" -o x"$ttybase" = x"/dev/tty"; then | 12 | if test x"$ttybase" = x"/dev/vc/" -o x"$ttybase" = x"/dev/tty"; then |
13 | echo "* Activating Cyrillic KOI8-R -> CP866 font map" | 13 | echo "* Activating font map" |
14 | echo -ne "\033(K" >"$ttyname" | 14 | echo -ne "\033(K" >"$ttyname" |
15 | 15 | ||
16 | echo "* Loading screen font" | 16 | echo "* Loading screen font" |
@@ -18,9 +18,9 @@ if test x"$ttybase" = x"/dev/vc/" -o x"$ttybase" = x"/dev/tty"; then | |||
18 | -C "$ttyname" \ | 18 | -C "$ttyname" \ |
19 | -m "$PWD/koi8r_to_uni.trans" \ | 19 | -m "$PWD/koi8r_to_uni.trans" \ |
20 | "$PWD/alt08x16+unimap.fnt" \ | 20 | "$PWD/alt08x16+unimap.fnt" \ |
21 | || echo "! setfont failure" | 21 | || echo "setfont exit code: $?" |
22 | 22 | ||
23 | echo "* Loading keymap" | 23 | echo "* Loading keymap" |
24 | loadkeys "$PWD/ru_koi8r.keymap" \ | 24 | loadkeys "$PWD/unicode_cyrillic.keymap" \ |
25 | || echo "! loadkeys failure" | 25 | || echo "loadkeys exit code: $?" |
26 | fi | 26 | fi |
diff --git a/examples/var_service/getty_tty1/login.sh b/examples/var_service/getty_tty1/login.sh index d69b6fd55..f8b53fc03 100755 --- a/examples/var_service/getty_tty1/login.sh +++ b/examples/var_service/getty_tty1/login.sh | |||
@@ -6,7 +6,8 @@ ttybase="${ttyname%%[0123456789]*}" # strip numeric tail | |||
6 | if test "$ttybase" = "/dev/tty"; then | 6 | if test "$ttybase" = "/dev/tty"; then |
7 | tail="${ttyname:8}" | 7 | tail="${ttyname:8}" |
8 | echo "* Setting terminal device's owner to $LOGIN_UID:$LOGIN_GID" | 8 | echo "* Setting terminal device's owner to $LOGIN_UID:$LOGIN_GID" |
9 | chown "$LOGIN_UID:$LOGIN_GID" "/dev/vcs$tail" "/dev/vcsa$tail" | 9 | test -c "/dev/vcs$tail" && chown "$LOGIN_UID:$LOGIN_GID" "/dev/vcs$tail" |
10 | test -c "/dev/vcsa$tail" && chown "$LOGIN_UID:$LOGIN_GID" "/dev/vcsa$tail" | ||
10 | fi | 11 | fi |
11 | # We can do this also, but login does it itself | 12 | # We can do this also, but login does it itself |
12 | # chown "$LOGIN_UID:$LOGIN_GID" "$ttyname" | 13 | # chown "$LOGIN_UID:$LOGIN_GID" "$ttyname" |
diff --git a/examples/var_service/getty_tty1/ru_koi8r.keymap b/examples/var_service/getty_tty1/ru_koi8r.keymap deleted file mode 100644 index 6c811539c..000000000 --- a/examples/var_service/getty_tty1/ru_koi8r.keymap +++ /dev/null | |||
@@ -1,183 +0,0 @@ | |||
1 | keymaps 0,1, 2,3, 4,6, 8,10, 12,14 | ||
2 | # | ||
3 | # This one is for generating koi8r Russian chars | ||
4 | # Cyr/Lat switches: RightAlt, Shift+Ctrl, Ctrl+Shift | ||
5 | # (last one does not work for dark and obscure reasons 8( ) | ||
6 | # | ||
7 | # plain,shift, plain,shift, ctrl,ctrl alt,alt ctrlalt,ctrlalt | ||
8 | # lat-------- cyr-------- lat cyr lat cyr lat cyr | ||
9 | # | ||
10 | #Shift 1 | ||
11 | #AltGr (cyr) 2 | ||
12 | #Control 4 | ||
13 | #Alt 8 | ||
14 | #ShiftL 16 | ||
15 | #ShiftR 32 | ||
16 | #CtrlL 64 | ||
17 | #CtrlR 128 | ||
18 | #============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== | ||
19 | keycode 1 = Escape Escape Escape Escape Escape Escape Meta_Escape Meta_Escape SAK SAK | ||
20 | keycode 2 = one exclam one exclam exclam exclam Meta_one Meta_one | ||
21 | keycode 3 = two at two at nul nul Meta_two Meta_two | ||
22 | keycode 4 = three numbersign three numbersign three three Meta_three Meta_three | ||
23 | keycode 5 = four dollar four dollar Control_backslash Control_backslash Meta_four Meta_four | ||
24 | keycode 6 = five percent five percent Control_bracketright Control_bracketright Meta_five Meta_five | ||
25 | keycode 7 = six asciicircum six asciicircum Control_asciicircum Control_asciicircum Meta_six Meta_six | ||
26 | keycode 8 = seven ampersand seven ampersand Control_underscore Control_underscore Meta_seven Meta_seven | ||
27 | keycode 9 = eight asterisk eight asterisk eight eight Meta_eight Meta_eight | ||
28 | keycode 10 = nine parenleft nine parenleft nine nine Meta_nine Meta_nine | ||
29 | keycode 11 = zero parenright zero parenright zero zero Meta_zero Meta_zero | ||
30 | keycode 12 = minus underscore minus underscore Control_underscore Control_underscore Meta_minus Meta_minus | ||
31 | keycode 13 = equal plus equal plus equal equal Meta_equal Meta_equal | ||
32 | keycode 14 = Delete Delete Delete Delete BackSpace BackSpace Meta_Delete Meta_Delete | ||
33 | keycode 15 = Tab Tab Tab Tab Tab Tab Meta_Tab Meta_Tab | ||
34 | keycode 16 = q Q 202 234 Control_q Control_q Meta_q Meta_q Meta_Control_q Meta_Control_q | ||
35 | keycode 17 = w W 195 227 Control_w Control_w Meta_w Meta_w Meta_Control_w Meta_Control_w | ||
36 | keycode 18 = e E 213 245 Control_e Control_e Meta_e Meta_e Meta_Control_e Meta_Control_e | ||
37 | keycode 19 = r R 203 235 Control_r Control_r Meta_r Meta_r Meta_Control_r Meta_Control_r | ||
38 | keycode 20 = t T 197 229 Control_t Control_t Meta_t Meta_t Meta_Control_t Meta_Control_t | ||
39 | #============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== | ||
40 | keycode 21 = y Y 206 238 Control_y Control_y Meta_y Meta_y Meta_Control_y Meta_Control_y | ||
41 | keycode 22 = u U 199 231 Control_u Control_u Meta_u Meta_u Meta_Control_u Meta_Control_u | ||
42 | keycode 23 = i I 219 251 Control_i Control_i Meta_i Meta_i Meta_Control_i Meta_Control_i | ||
43 | keycode 24 = o O 221 253 Control_o Control_o Meta_o Meta_o Meta_Control_o Meta_Control_o | ||
44 | keycode 25 = p P 218 250 Control_p Control_p Meta_p Meta_p Meta_Control_p Meta_Control_p | ||
45 | keycode 26 = bracketleft braceleft 200 232 Escape Escape Meta_bracketleft Meta_bracketleft | ||
46 | keycode 27 = bracketright braceright 223 255 Control_bracketright Control_bracketright | ||
47 | keycode 28 = Return | ||
48 | # Shift+Ctrl - Cyrillic | ||
49 | keycode 29 = Control AltGr_Lock Control AltGr_Lock Control Control Control Control Control Control | ||
50 | keycode 30 = a A 198 230 Control_a Control_a Meta_a Meta_a Meta_Control_a Meta_Control_a | ||
51 | keycode 31 = s S 217 249 Control_s Control_s Meta_s Meta_s Meta_Control_s Meta_Control_s | ||
52 | keycode 32 = d D 215 247 Control_d Control_d Meta_d Meta_d Meta_Control_d Meta_Control_d | ||
53 | keycode 33 = f F 193 225 Control_f Control_f Meta_f Meta_f Meta_Control_f Meta_Control_f | ||
54 | keycode 34 = g G 208 240 Control_g Control_g Meta_g Meta_g Meta_Control_g Meta_Control_g | ||
55 | keycode 35 = h H 210 242 Control_h Control_h Meta_h Meta_h Meta_Control_h Meta_Control_h | ||
56 | keycode 36 = j J 207 239 Control_j Control_j Meta_j Meta_j Meta_Control_j Meta_Control_j | ||
57 | keycode 37 = k K 204 236 Control_k Control_k Meta_k Meta_k Meta_Control_k Meta_Control_k | ||
58 | keycode 38 = l L 196 228 Control_l Control_l Meta_l Meta_l Meta_Control_l Meta_Control_l | ||
59 | keycode 39 = semicolon colon 214 246 semicolon semicolon Meta_semicolon Meta_semicolon | ||
60 | keycode 40 = apostrophe quotedbl 220 252 Control_g Control_g Meta_apostrophe Meta_apostrophe | ||
61 | #============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== | ||
62 | keycode 41 = grave asciitilde grave asciitilde nul nul Meta_grave Meta_grave | ||
63 | keycode 42 = Shift | ||
64 | keycode 43 = backslash bar backslash bar Control_backslash Control_backslash Meta_backslash Meta_backslash | ||
65 | keycode 44 = z Z 209 241 Control_z Control_z Meta_z Meta_z Meta_Control_z Meta_Control_z | ||
66 | keycode 45 = x X 222 254 Control_x Control_x Meta_x Meta_x Meta_Control_x Meta_Control_x | ||
67 | keycode 46 = c C 211 243 Control_c Control_c Meta_c Meta_c Meta_Control_c Meta_Control_c | ||
68 | keycode 47 = v V 205 237 Control_v Control_v Meta_v Meta_v Meta_Control_v Meta_Control_v | ||
69 | keycode 48 = b B 201 233 Control_b Control_b Meta_b Meta_b Meta_Control_b Meta_Control_b | ||
70 | keycode 49 = n N 212 244 Control_n Control_n Meta_n Meta_n Meta_Control_n Meta_Control_n | ||
71 | keycode 50 = m M 216 248 Control_m Control_m Meta_m Meta_m Meta_Control_m Meta_Control_m | ||
72 | keycode 51 = comma less 194 226 comma comma Meta_comma Meta_comma | ||
73 | keycode 52 = period greater 192 224 Compose Compose Meta_period Meta_period | ||
74 | keycode 53 = slash question slash question Delete Delete Meta_slash Meta_slash Meta_question Meta_question | ||
75 | # Ctrl+Shift - Cyrillic (not working???) | ||
76 | keycode 54 = Shift Shift Shift Shift AltGr_Lock AltGr_Lock Shift Shift Shift Shift | ||
77 | keycode 55 = KP_Multiply | ||
78 | keycode 56 = Alt | ||
79 | keycode 57 = space space space space nul nul Meta_space Meta_space | ||
80 | keycode 58 = Caps_Lock | ||
81 | keycode 59 = F1 F11 F1 F11 F1 F1 Console_1 Console_1 Console_1 Console_1 | ||
82 | keycode 60 = F2 F12 F2 F12 F2 F2 Console_2 Console_2 Console_2 Console_2 | ||
83 | #============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== | ||
84 | keycode 61 = F3 F13 F3 F13 F3 F3 Console_3 Console_3 Console_3 Console_3 | ||
85 | keycode 62 = F4 F14 F4 F14 F4 F4 Console_4 Console_4 Console_4 Console_4 | ||
86 | keycode 63 = F5 F15 F5 F15 F5 F5 Console_5 Console_5 Console_5 Console_5 | ||
87 | keycode 64 = F6 F16 F6 F16 F6 F6 Console_6 Console_6 Console_6 Console_6 | ||
88 | keycode 65 = F7 F17 F7 F17 F7 F7 Console_7 Console_7 Console_7 Console_7 | ||
89 | keycode 66 = F8 F18 F8 F18 F8 F8 Console_8 Console_8 Console_8 Console_8 | ||
90 | keycode 67 = F9 F19 F9 F19 F9 F9 Console_9 Console_9 Console_9 Console_9 | ||
91 | keycode 68 = F10 F20 F10 F20 F10 F10 Console_10 Console_10 Console_10 Console_10 | ||
92 | keycode 69 = Num_Lock Bare_Num_Lock Num_Lock Bare_Num_Lock | ||
93 | keycode 70 = Scroll_Lock Show_Memory Scroll_Lock Show_Memory Show_State Show_State | ||
94 | keycode 71 = KP_7 KP_7 KP_7 KP_7 KP_7 KP_7 Ascii_7 Ascii_7 | ||
95 | keycode 72 = KP_8 KP_8 KP_8 KP_8 KP_8 KP_8 Ascii_8 Ascii_8 | ||
96 | keycode 73 = KP_9 KP_9 KP_9 KP_9 KP_9 KP_9 Ascii_9 Ascii_9 | ||
97 | keycode 74 = KP_Subtract KP_Subtract KP_Subtract KP_Subtract KP_Subtract KP_Subtract KP_Subtract KP_Subtract | ||
98 | keycode 75 = KP_4 KP_4 KP_4 KP_4 KP_4 KP_4 Ascii_4 Ascii_4 | ||
99 | keycode 76 = KP_5 KP_5 KP_5 KP_5 KP_5 KP_5 Ascii_5 Ascii_5 | ||
100 | keycode 77 = KP_6 KP_6 KP_6 KP_6 KP_6 KP_6 Ascii_6 Ascii_6 | ||
101 | keycode 78 = KP_Add KP_Add KP_Add KP_Add KP_Add KP_Add KP_Add KP_Add | ||
102 | keycode 79 = KP_1 KP_1 KP_1 KP_1 KP_1 KP_1 Ascii_1 Ascii_1 | ||
103 | keycode 80 = KP_2 KP_2 KP_2 KP_2 KP_2 KP_2 Ascii_2 Ascii_2 | ||
104 | #============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== | ||
105 | keycode 81 = KP_3 KP_3 KP_3 KP_3 KP_3 KP_3 Ascii_3 Ascii_3 | ||
106 | keycode 82 = KP_0 KP_0 KP_0 KP_0 KP_0 KP_0 Ascii_0 Ascii_0 | ||
107 | keycode 83 = KP_Period KP_Period KP_Period KP_Period KP_Period KP_Period KP_Period KP_Period Boot Boot | ||
108 | keycode 84 = Last_Console | ||
109 | keycode 85 = | ||
110 | keycode 86 = less greater less greater less less Meta_less Meta_less | ||
111 | keycode 87 = F11 F11 F11 F11 F11 F11 Console_11 Console_11 Console_11 Console_11 | ||
112 | keycode 88 = F12 F12 F12 F12 F12 F12 Console_12 Console_12 Console_12 Console_12 | ||
113 | keycode 89 = | ||
114 | keycode 90 = | ||
115 | keycode 91 = | ||
116 | keycode 92 = | ||
117 | keycode 93 = | ||
118 | keycode 94 = | ||
119 | keycode 95 = | ||
120 | keycode 96 = KP_Enter | ||
121 | keycode 97 = Control | ||
122 | keycode 98 = KP_Divide | ||
123 | keycode 99 = Control_backslash | ||
124 | # Right Alt - Cyrillic | ||
125 | keycode 100 = AltGr_Lock | ||
126 | #============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== | ||
127 | keycode 101 = Break | ||
128 | keycode 102 = Find | ||
129 | keycode 103 = Up | ||
130 | keycode 104 = Prior Scroll_Backward Prior Scroll_Backward Prior Prior Prior Prior Prior Prior | ||
131 | keycode 105 = Left Left Left Left Left Left Left Left Decr_Console Decr_Console | ||
132 | keycode 106 = Right Right Right Right Right Right Right Right Incr_Console Incr_Console | ||
133 | keycode 107 = Select | ||
134 | keycode 108 = Down | ||
135 | keycode 109 = Next Scroll_Forward Next Scroll_Forward Next Next Next Next Next Next | ||
136 | keycode 110 = Insert | ||
137 | keycode 111 = Remove Remove Remove Remove Remove Remove Remove Remove Boot Boot | ||
138 | keycode 112 = Macro | ||
139 | keycode 113 = F13 | ||
140 | keycode 114 = F14 | ||
141 | keycode 115 = Help | ||
142 | keycode 116 = Do | ||
143 | keycode 117 = F17 | ||
144 | keycode 118 = KP_MinPlus | ||
145 | keycode 119 = Pause | ||
146 | keycode 120 = | ||
147 | #============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== | ||
148 | keycode 121 = | ||
149 | keycode 122 = | ||
150 | keycode 123 = | ||
151 | keycode 124 = | ||
152 | keycode 125 = | ||
153 | keycode 126 = | ||
154 | keycode 127 = | ||
155 | |||
156 | string F1 = "\033[[A" | ||
157 | string F2 = "\033[[B" | ||
158 | string F3 = "\033[[C" | ||
159 | string F4 = "\033[[D" | ||
160 | string F5 = "\033[[E" | ||
161 | string F6 = "\033[17~" | ||
162 | string F7 = "\033[18~" | ||
163 | string F8 = "\033[19~" | ||
164 | string F9 = "\033[20~" | ||
165 | string F10 = "\033[21~" | ||
166 | string F11 = "\033[23~" | ||
167 | string F12 = "\033[24~" | ||
168 | string F13 = "\033[25~" | ||
169 | string F14 = "\033[26~" | ||
170 | string F15 = "\033[28~" | ||
171 | string F16 = "\033[29~" | ||
172 | string F17 = "\033[31~" | ||
173 | string F18 = "\033[32~" | ||
174 | string F19 = "\033[33~" | ||
175 | string F20 = "\033[34~" | ||
176 | string Find = "\033[1~" | ||
177 | string Insert = "\033[2~" | ||
178 | string Remove = "\033[3~" | ||
179 | string Select = "\033[4~" | ||
180 | string Prior = "\033[5~" | ||
181 | string Next = "\033[6~" | ||
182 | string Macro = "\033[M" | ||
183 | string Pause = "\033[P" | ||
diff --git a/examples/var_service/getty_tty1/run b/examples/var_service/getty_tty1/run index c7c413ba4..c5b291b4d 100755 --- a/examples/var_service/getty_tty1/run +++ b/examples/var_service/getty_tty1/run | |||
@@ -1,9 +1,5 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | ||
3 | exec >/dev/null | ||
4 | exec 2>&1 | ||
5 | exec </dev/null | ||
6 | |||
7 | user=root | 3 | user=root |
8 | baud=38400 | 4 | baud=38400 |
9 | delay=3 | 5 | delay=3 |
@@ -25,6 +21,4 @@ test -x ./cfg && . ./cfg | |||
25 | 21 | ||
26 | exec \ | 22 | exec \ |
27 | env - "TERM=$TERM" PATH="$PATH" LOGIN_PRE_SUID_SCRIPT="$PWD/login.sh" \ | 23 | env - "TERM=$TERM" PATH="$PATH" LOGIN_PRE_SUID_SCRIPT="$PWD/login.sh" \ |
28 | softlimit \ | ||
29 | setuidgid "$user" \ | ||
30 | getty "$baud" "$tty" "$TERM" | 24 | getty "$baud" "$tty" "$TERM" |
diff --git a/examples/var_service/getty_tty1/unicode_cyrillic.keymap b/examples/var_service/getty_tty1/unicode_cyrillic.keymap new file mode 100644 index 000000000..49911cd10 --- /dev/null +++ b/examples/var_service/getty_tty1/unicode_cyrillic.keymap | |||
@@ -0,0 +1,200 @@ | |||
1 | keymaps 0,1, 2,3, 4,6, 8,9, 10,11, 12,14 | ||
2 | # | ||
3 | # This one is for generating Unicode Curillic chars | ||
4 | # Cyr/Lat switches: RightAlt, Shift+Ctrl, Ctrl+Shift, Win keys | ||
5 | # | ||
6 | # plain,shift, plain,shift, ctrl,ctrl alt,shiftalt alt,shiftalt ctrlalt,ctrlalt | ||
7 | # lat-------- cyr-------- lat cyr lat--------- cyr--------- lat cyr | ||
8 | # | ||
9 | #Shift 1 | ||
10 | #AltGr (cyr) 2 | ||
11 | #Control 4 | ||
12 | #Alt 8 | ||
13 | #ShiftL 16 | ||
14 | #ShiftR 32 | ||
15 | #CtrlL 64 | ||
16 | #CtrlR 128 | ||
17 | |||
18 | # L/R Ctrl: Shift+Ctrl - Cyrillic | ||
19 | keycode 29 = Control AltGr_Lock Control AltGr_Lock Control Control Control Control Control Control Control Control | ||
20 | keycode 97 = Control AltGr_Lock Control AltGr_Lock Control Control Control Control Control Control Control Control | ||
21 | # L/R Shift: Ctrl+Shift - Cyrillic | ||
22 | keycode 42 = Shift Shift Shift Shift AltGr_Lock AltGr_Lock Shift Shift Shift Shift Shift Shift | ||
23 | keycode 54 = Shift Shift Shift Shift AltGr_Lock AltGr_Lock Shift Shift Shift Shift Shift Shift | ||
24 | # Right Alt: Cyrillic | ||
25 | keycode 100 = AltGr_Lock | ||
26 | # L/R Win: Cyrillic | ||
27 | keycode 125 = AltGr_Lock | ||
28 | keycode 126 = AltGr_Lock | ||
29 | |||
30 | #============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt shift ============= alt cyr =============== alt shift cur ========= ctrlalt =============== ctrlalt cyr =========== | ||
31 | keycode 1 = Escape Escape Escape Escape Escape Escape Meta_Escape Meta_Escape Meta_Escape Meta_Escape SAK SAK | ||
32 | keycode 2 = one exclam one exclam exclam exclam Meta_one Meta_one Meta_one Meta_one | ||
33 | keycode 3 = two at two at nul nul Meta_two Meta_two Meta_two Meta_two | ||
34 | keycode 4 = three numbersign three numbersign three three Meta_three Meta_three Meta_three Meta_three | ||
35 | keycode 5 = four dollar four dollar Control_backslash Control_backslash Meta_four Meta_four Meta_four Meta_four | ||
36 | keycode 6 = five percent five percent Control_bracketright Control_bracketright Meta_five Meta_five Meta_five Meta_five | ||
37 | keycode 7 = six asciicircum six asciicircum Control_asciicircum Control_asciicircum Meta_six Meta_six Meta_six Meta_six | ||
38 | keycode 8 = seven ampersand seven ampersand Control_underscore Control_underscore Meta_seven Meta_seven Meta_seven Meta_seven | ||
39 | keycode 9 = eight asterisk eight asterisk eight eight Meta_eight Meta_eight Meta_eight Meta_eight | ||
40 | keycode 10 = nine parenleft nine parenleft nine nine Meta_nine Meta_nine Meta_nine Meta_nine | ||
41 | keycode 11 = zero parenright zero parenright zero zero Meta_zero Meta_zero Meta_zero Meta_zero | ||
42 | keycode 12 = minus underscore minus underscore Control_underscore Control_underscore Meta_minus Meta_minus Meta_minus Meta_minus | ||
43 | keycode 13 = equal plus equal plus equal equal Meta_equal Meta_equal Meta_equal Meta_equal | ||
44 | keycode 14 = Delete Delete Delete Delete BackSpace BackSpace Meta_Delete Meta_Delete Meta_Delete Meta_Delete | ||
45 | keycode 15 = Tab Tab Tab Tab Tab Tab Meta_Tab Meta_Tab Meta_Tab Meta_Tab | ||
46 | keycode 16 = +q +Q +U+0439 +U+0419 Control_q Control_q Meta_q Meta_q Meta_q Meta_q Meta_Control_q Meta_Control_q | ||
47 | keycode 17 = +w +W +U+0446 +U+0426 Control_w Control_w Meta_w Meta_w Meta_w Meta_w Meta_Control_w Meta_Control_w | ||
48 | keycode 18 = +e +E +U+0443 +U+0423 Control_e Control_e Meta_e Meta_e Meta_e Meta_e Meta_Control_e Meta_Control_e | ||
49 | keycode 19 = +r +R +U+043a +U+041a Control_r Control_r Meta_r Meta_r Meta_r Meta_r Meta_Control_r Meta_Control_r | ||
50 | keycode 20 = +t +T +U+0435 +U+0415 Control_t Control_t Meta_t Meta_t Meta_t Meta_t Meta_Control_t Meta_Control_t | ||
51 | #============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt =================== alt cyr =============== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== | ||
52 | keycode 21 = +y +Y +U+043d +U+041d Control_y Control_y Meta_y Meta_y Meta_y Meta_y Meta_Control_y Meta_Control_y | ||
53 | keycode 22 = +u +U +U+0433 +U+0413 Control_u Control_u Meta_u Meta_u Meta_u Meta_u Meta_Control_u Meta_Control_u | ||
54 | keycode 23 = +i +I +U+0448 +U+0428 Control_i Control_i Meta_i Meta_i Meta_i Meta_i Meta_Control_i Meta_Control_i | ||
55 | keycode 24 = +o +O +U+0449 +U+0429 Control_o Control_o Meta_o Meta_o Meta_o Meta_o Meta_Control_o Meta_Control_o | ||
56 | keycode 25 = +p +P +U+0437 +U+0417 Control_p Control_p Meta_p Meta_p Meta_p Meta_p Meta_Control_p Meta_Control_p | ||
57 | keycode 26 = bracketleft braceleft +U+0445 +U+0425 Escape Escape Meta_bracketleft Meta_bracketleft Meta_bracketleft Meta_bracketleft | ||
58 | keycode 27 = bracketright braceright +U+044a +U+042a Control_bracketright Control_bracketright | ||
59 | keycode 28 = Return | ||
60 | # LCtrl | ||
61 | #keycode 29 = | ||
62 | keycode 30 = +a +A +U+0444 +U+0424 Control_a Control_a Meta_a Meta_a Meta_a Meta_a Meta_Control_a Meta_Control_a | ||
63 | keycode 31 = +s +S +U+044b +U+042b Control_s Control_s Meta_s Meta_s Meta_s Meta_s Meta_Control_s Meta_Control_s | ||
64 | keycode 32 = +d +D +U+0432 +U+0412 Control_d Control_d Meta_d Meta_d Meta_d Meta_d Meta_Control_d Meta_Control_d | ||
65 | keycode 33 = +f +F +U+0430 +U+0410 Control_f Control_f Meta_f Meta_f Meta_f Meta_f Meta_Control_f Meta_Control_f | ||
66 | keycode 34 = +g +G +U+043f +U+041f Control_g Control_g Meta_g Meta_g Meta_g Meta_g Meta_Control_g Meta_Control_g | ||
67 | keycode 35 = +h +H +U+0440 +U+0420 Control_h Control_h Meta_h Meta_h Meta_h Meta_h Meta_Control_h Meta_Control_h | ||
68 | keycode 36 = +j +J +U+043e +U+041e Control_j Control_j Meta_j Meta_j Meta_j Meta_j Meta_Control_j Meta_Control_j | ||
69 | keycode 37 = +k +K +U+043b +U+041b Control_k Control_k Meta_k Meta_k Meta_k Meta_k Meta_Control_k Meta_Control_k | ||
70 | keycode 38 = +l +L +U+0434 +U+0414 Control_l Control_l Meta_l Meta_l Meta_l Meta_l Meta_Control_l Meta_Control_l | ||
71 | keycode 39 = semicolon colon +U+0436 +U+0416 semicolon semicolon Meta_semicolon Meta_semicolon Meta_semicolon Meta_semicolon | ||
72 | keycode 40 = apostrophe quotedbl +U+044d +U+042d Control_g Control_g Meta_apostrophe Meta_apostrophe Meta_apostrophe Meta_apostrophe | ||
73 | #============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt =================== alt cyr =============== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== | ||
74 | keycode 41 = grave asciitilde grave asciitilde nul nul Meta_grave Meta_grave Meta_grave Meta_grave | ||
75 | # LShift | ||
76 | #keycode 42 = | ||
77 | keycode 43 = backslash bar backslash bar Control_backslash Control_backslash Meta_backslash Meta_backslash Meta_backslash Meta_backslash | ||
78 | keycode 44 = +z +Z +U+044f +U+042f Control_z Control_z Meta_z Meta_z Meta_z Meta_z Meta_Control_z Meta_Control_z | ||
79 | keycode 45 = +x +X +U+0447 +U+0427 Control_x Control_x Meta_x Meta_x Meta_x Meta_x Meta_Control_x Meta_Control_x | ||
80 | keycode 46 = +c +C +U+0441 +U+0421 Control_c Control_c Meta_c Meta_c Meta_c Meta_c Meta_Control_c Meta_Control_c | ||
81 | keycode 47 = +v +V +U+043c +U+041c Control_v Control_v Meta_v Meta_v Meta_v Meta_v Meta_Control_v Meta_Control_v | ||
82 | keycode 48 = +b +B +U+0438 +U+0418 Control_b Control_b Meta_b Meta_b Meta_b Meta_b Meta_Control_b Meta_Control_b | ||
83 | keycode 49 = +n +N +U+0442 +U+0422 Control_n Control_n Meta_n Meta_n Meta_n Meta_n Meta_Control_n Meta_Control_n | ||
84 | keycode 50 = +m +M +U+044c +U+042c Control_m Control_m Meta_m Meta_m Meta_m Meta_m Meta_Control_m Meta_Control_m | ||
85 | keycode 51 = comma less +U+0431 +U+0411 comma comma Meta_comma Meta_comma Meta_comma Meta_comma | ||
86 | keycode 52 = period greater +U+044e +U+042e Compose Compose Meta_period Meta_period Meta_period Meta_period | ||
87 | keycode 53 = slash question slash question Delete Delete Meta_slash Meta_question Meta_slash Meta_question Meta_question Meta_question | ||
88 | # RShift | ||
89 | #keycode 54 = | ||
90 | keycode 55 = KP_Multiply | ||
91 | keycode 56 = Alt | ||
92 | keycode 57 = space space space space nul nul Meta_space Meta_space Meta_space Meta_space | ||
93 | keycode 58 = Caps_Lock | ||
94 | keycode 59 = F1 F11 F1 F11 F1 F1 Console_1 Console_1 Console_1 Console_1 Console_1 Console_1 | ||
95 | keycode 60 = F2 F12 F2 F12 F2 F2 Console_2 Console_2 Console_2 Console_2 Console_2 Console_2 | ||
96 | #============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt =================== alt cyr =============== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== | ||
97 | keycode 61 = F3 F13 F3 F13 F3 F3 Console_3 Console_3 Console_3 Console_3 Console_3 Console_3 | ||
98 | keycode 62 = F4 F14 F4 F14 F4 F4 Console_4 Console_4 Console_4 Console_4 Console_4 Console_4 | ||
99 | keycode 63 = F5 F15 F5 F15 F5 F5 Console_5 Console_5 Console_5 Console_5 Console_5 Console_5 | ||
100 | keycode 64 = F6 F16 F6 F16 F6 F6 Console_6 Console_6 Console_6 Console_6 Console_6 Console_6 | ||
101 | keycode 65 = F7 F17 F7 F17 F7 F7 Console_7 Console_7 Console_7 Console_7 Console_7 Console_7 | ||
102 | keycode 66 = F8 F18 F8 F18 F8 F8 Console_8 Console_8 Console_8 Console_8 Console_8 Console_8 | ||
103 | keycode 67 = F9 F19 F9 F19 F9 F9 Console_9 Console_9 Console_9 Console_9 Console_9 Console_9 | ||
104 | keycode 68 = F10 F20 F10 F20 F10 F10 Console_10 Console_10 Console_10 Console_10 Console_10 Console_10 | ||
105 | keycode 69 = Num_Lock Bare_Num_Lock Num_Lock Bare_Num_Lock | ||
106 | keycode 70 = Scroll_Lock Show_Memory Scroll_Lock Show_Memory Show_State Show_State | ||
107 | keycode 71 = KP_7 KP_7 KP_7 KP_7 KP_7 KP_7 Ascii_7 Ascii_7 Ascii_7 Ascii_7 | ||
108 | keycode 72 = KP_8 KP_8 KP_8 KP_8 KP_8 KP_8 Ascii_8 Ascii_8 Ascii_8 Ascii_8 | ||
109 | keycode 73 = KP_9 KP_9 KP_9 KP_9 KP_9 KP_9 Ascii_9 Ascii_9 Ascii_9 Ascii_9 | ||
110 | keycode 74 = KP_Subtract KP_Subtract KP_Subtract KP_Subtract KP_Subtract KP_Subtract KP_Subtract KP_Subtract KP_Subtract KP_Subtract | ||
111 | keycode 75 = KP_4 KP_4 KP_4 KP_4 KP_4 KP_4 Ascii_4 Ascii_4 Ascii_4 Ascii_4 | ||
112 | keycode 76 = KP_5 KP_5 KP_5 KP_5 KP_5 KP_5 Ascii_5 Ascii_5 Ascii_5 Ascii_5 | ||
113 | keycode 77 = KP_6 KP_6 KP_6 KP_6 KP_6 KP_6 Ascii_6 Ascii_6 Ascii_6 Ascii_6 | ||
114 | keycode 78 = KP_Add KP_Add KP_Add KP_Add KP_Add KP_Add KP_Add KP_Add KP_Add KP_Add | ||
115 | keycode 79 = KP_1 KP_1 KP_1 KP_1 KP_1 KP_1 Ascii_1 Ascii_1 Ascii_1 Ascii_1 | ||
116 | keycode 80 = KP_2 KP_2 KP_2 KP_2 KP_2 KP_2 Ascii_2 Ascii_2 Ascii_2 Ascii_2 | ||
117 | #============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt =================== alt cyr =============== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== | ||
118 | keycode 81 = KP_3 KP_3 KP_3 KP_3 KP_3 KP_3 Ascii_3 Ascii_3 Ascii_3 Ascii_3 | ||
119 | keycode 82 = KP_0 KP_0 KP_0 KP_0 KP_0 KP_0 Ascii_0 Ascii_0 Ascii_0 Ascii_0 | ||
120 | keycode 83 = KP_Period KP_Period KP_Period KP_Period KP_Period KP_Period KP_Period KP_Period KP_Period KP_Period Boot Boot | ||
121 | keycode 84 = Last_Console | ||
122 | keycode 85 = | ||
123 | keycode 86 = less greater less greater less less Meta_less Meta_less Meta_less Meta_less | ||
124 | keycode 87 = F11 F11 F11 F11 F11 F11 Console_11 Console_11 Console_11 Console_11 Console_11 Console_11 | ||
125 | keycode 88 = F12 F12 F12 F12 F12 F12 Console_12 Console_12 Console_12 Console_12 Console_12 Console_12 | ||
126 | keycode 89 = | ||
127 | keycode 90 = | ||
128 | keycode 91 = | ||
129 | keycode 92 = | ||
130 | keycode 93 = | ||
131 | keycode 94 = | ||
132 | keycode 95 = | ||
133 | keycode 96 = KP_Enter | ||
134 | # RControl | ||
135 | #keycode 97 = | ||
136 | keycode 98 = KP_Divide | ||
137 | keycode 99 = Control_backslash | ||
138 | # RAlt | ||
139 | #keycode 100 = | ||
140 | #============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt shift ============= alt cyr =============== alt shift cyr ========= ctrlalt =============== ctrlalt cyr =========== | ||
141 | keycode 101 = Break | ||
142 | keycode 102 = Find | ||
143 | keycode 103 = Up | ||
144 | keycode 104 = Prior Scroll_Backward Prior Scroll_Backward Prior Prior Prior Prior Prior Prior Prior Prior | ||
145 | keycode 105 = Left Left Left Left Left Left Left Left Left Left Decr_Console Decr_Console | ||
146 | keycode 106 = Right Right Right Right Right Right Right Right Right Right Incr_Console Incr_Console | ||
147 | keycode 107 = Select | ||
148 | keycode 108 = Down | ||
149 | keycode 109 = Next Scroll_Forward Next Scroll_Forward Next Next Next Next Next Next Next Next | ||
150 | keycode 110 = Insert | ||
151 | keycode 111 = Remove Remove Remove Remove Remove Remove Remove Remove Remove Remove Boot Boot | ||
152 | keycode 112 = Macro | ||
153 | keycode 113 = F13 | ||
154 | keycode 114 = F14 | ||
155 | keycode 115 = Help | ||
156 | keycode 116 = Do | ||
157 | keycode 117 = F17 | ||
158 | keycode 118 = KP_MinPlus | ||
159 | keycode 119 = Pause | ||
160 | keycode 120 = | ||
161 | #============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt =================== alt cyr =============== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== | ||
162 | keycode 121 = | ||
163 | keycode 122 = | ||
164 | keycode 123 = | ||
165 | keycode 124 = | ||
166 | # LWin | ||
167 | #keycode 125 = | ||
168 | # RWin | ||
169 | #keycode 126 = | ||
170 | # RMenu | ||
171 | keycode 127 = | ||
172 | |||
173 | string F1 = "\033[[A" | ||
174 | string F2 = "\033[[B" | ||
175 | string F3 = "\033[[C" | ||
176 | string F4 = "\033[[D" | ||
177 | string F5 = "\033[[E" | ||
178 | string F6 = "\033[17~" | ||
179 | string F7 = "\033[18~" | ||
180 | string F8 = "\033[19~" | ||
181 | string F9 = "\033[20~" | ||
182 | string F10 = "\033[21~" | ||
183 | string F11 = "\033[23~" | ||
184 | string F12 = "\033[24~" | ||
185 | string F13 = "\033[25~" | ||
186 | string F14 = "\033[26~" | ||
187 | string F15 = "\033[28~" | ||
188 | string F16 = "\033[29~" | ||
189 | string F17 = "\033[31~" | ||
190 | string F18 = "\033[32~" | ||
191 | string F19 = "\033[33~" | ||
192 | string F20 = "\033[34~" | ||
193 | string Find = "\033[1~" | ||
194 | string Insert = "\033[2~" | ||
195 | string Remove = "\033[3~" | ||
196 | string Select = "\033[4~" | ||
197 | string Prior = "\033[5~" | ||
198 | string Next = "\033[6~" | ||
199 | string Macro = "\033[M" | ||
200 | string Pause = "\033[P" | ||
diff --git a/examples/var_service/gpm/README b/examples/var_service/gpm/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/gpm/README +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | The real README file is one directory up. | ||
2 | |||
3 | This directory's run script can have useful comments. | ||
4 | If it doesn't but you feel it should, please send a patch | ||
5 | to busybox's mailing list. | ||
diff --git a/examples/var_service/httpd/README b/examples/var_service/httpd/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/httpd/README +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | The real README file is one directory up. | ||
2 | |||
3 | This directory's run script can have useful comments. | ||
4 | If it doesn't but you feel it should, please send a patch | ||
5 | to busybox's mailing list. | ||
diff --git a/examples/var_service/httpd/log/run b/examples/var_service/httpd/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/httpd/log/run +++ b/examples/var_service/httpd/log/run | |||
@@ -1,21 +1,2 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | exec std_service_logger | |
3 | user=logger | ||
4 | |||
5 | logdir="/var/log/service/`(cd ..;basename $PWD)`" | ||
6 | mkdir -p "$logdir" 2>/dev/null | ||
7 | chown -R "$user": "$logdir" | ||
8 | chmod -R go-rwxst,u+rwX "$logdir" | ||
9 | rm -rf logdir | ||
10 | ln -s "$logdir" logdir | ||
11 | |||
12 | # make this dir accessible to logger | ||
13 | chmod a+rX . | ||
14 | |||
15 | exec >/dev/null | ||
16 | exec 2>&1 | ||
17 | exec \ | ||
18 | env - PATH="$PATH" \ | ||
19 | softlimit \ | ||
20 | setuidgid "$user" \ | ||
21 | svlogd -tt "$logdir" | ||
diff --git a/examples/var_service/httpd/p_log b/examples/var_service/httpd/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/httpd/p_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | cat @* current | $PAGER | ||
diff --git a/examples/var_service/httpd/w_log b/examples/var_service/httpd/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/httpd/w_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' | ||
diff --git a/examples/var_service/ifplugd_if/README b/examples/var_service/ifplugd_if/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/ifplugd_if/README +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | The real README file is one directory up. | ||
2 | |||
3 | This directory's run script can have useful comments. | ||
4 | If it doesn't but you feel it should, please send a patch | ||
5 | to busybox's mailing list. | ||
diff --git a/examples/var_service/ifplugd_if/ifplugd_handler b/examples/var_service/ifplugd_if/ifplugd_handler index 4962fcf98..0749019f1 100755 --- a/examples/var_service/ifplugd_if/ifplugd_handler +++ b/examples/var_service/ifplugd_if/ifplugd_handler | |||
@@ -3,13 +3,18 @@ | |||
3 | # $1: interface | 3 | # $1: interface |
4 | # $2: state | 4 | # $2: state |
5 | 5 | ||
6 | if test -d "/var/service/dhcp_$1"; then | 6 | if test x"$2" = x"down"; then |
7 | if test x"$2" = x"down"; then | 7 | echo "Downing dhcp_$1" |
8 | echo "Downing /var/service/dhcp_$1" | 8 | svc -d "dhcp_$1" |
9 | sv d "/var/service/dhcp_$1" | 9 | echo "Downing zcip_$1" |
10 | fi | 10 | svc -d "zcip_$1" |
11 | if test x"$2" = x"up"; then | ||
12 | echo "Upping /var/service/dhcp_$1" | ||
13 | sv u "/var/service/dhcp_$1" | ||
14 | fi | ||
15 | fi | 11 | fi |
12 | if test x"$2" = x"up"; then | ||
13 | echo "Upping dhcp_$1" | ||
14 | svc -u "dhcp_$1" | ||
15 | echo "Upping zcip_$1" | ||
16 | svc -u "zcip_$1" | ||
17 | fi | ||
18 | # Parent ifplugd exits if we exit with nonzero. | ||
19 | # Do not startle it: | ||
20 | exit 0 | ||
diff --git a/examples/var_service/ifplugd_if/log/run b/examples/var_service/ifplugd_if/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/ifplugd_if/log/run +++ b/examples/var_service/ifplugd_if/log/run | |||
@@ -1,21 +1,2 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | exec std_service_logger | |
3 | user=logger | ||
4 | |||
5 | logdir="/var/log/service/`(cd ..;basename $PWD)`" | ||
6 | mkdir -p "$logdir" 2>/dev/null | ||
7 | chown -R "$user": "$logdir" | ||
8 | chmod -R go-rwxst,u+rwX "$logdir" | ||
9 | rm -rf logdir | ||
10 | ln -s "$logdir" logdir | ||
11 | |||
12 | # make this dir accessible to logger | ||
13 | chmod a+rX . | ||
14 | |||
15 | exec >/dev/null | ||
16 | exec 2>&1 | ||
17 | exec \ | ||
18 | env - PATH="$PATH" \ | ||
19 | softlimit \ | ||
20 | setuidgid "$user" \ | ||
21 | svlogd -tt "$logdir" | ||
diff --git a/examples/var_service/ifplugd_if/p_log b/examples/var_service/ifplugd_if/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/ifplugd_if/p_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | cat @* current | $PAGER | ||
diff --git a/examples/var_service/ifplugd_if/w_log b/examples/var_service/ifplugd_if/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/ifplugd_if/w_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' | ||
diff --git a/examples/var_service/inetd/README b/examples/var_service/inetd/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/inetd/README +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | The real README file is one directory up. | ||
2 | |||
3 | This directory's run script can have useful comments. | ||
4 | If it doesn't but you feel it should, please send a patch | ||
5 | to busybox's mailing list. | ||
diff --git a/examples/var_service/inetd/log/run b/examples/var_service/inetd/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/inetd/log/run +++ b/examples/var_service/inetd/log/run | |||
@@ -1,21 +1,2 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | exec std_service_logger | |
3 | user=logger | ||
4 | |||
5 | logdir="/var/log/service/`(cd ..;basename $PWD)`" | ||
6 | mkdir -p "$logdir" 2>/dev/null | ||
7 | chown -R "$user": "$logdir" | ||
8 | chmod -R go-rwxst,u+rwX "$logdir" | ||
9 | rm -rf logdir | ||
10 | ln -s "$logdir" logdir | ||
11 | |||
12 | # make this dir accessible to logger | ||
13 | chmod a+rX . | ||
14 | |||
15 | exec >/dev/null | ||
16 | exec 2>&1 | ||
17 | exec \ | ||
18 | env - PATH="$PATH" \ | ||
19 | softlimit \ | ||
20 | setuidgid "$user" \ | ||
21 | svlogd -tt "$logdir" | ||
diff --git a/examples/var_service/inetd/p_log b/examples/var_service/inetd/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/inetd/p_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | cat @* current | $PAGER | ||
diff --git a/examples/var_service/inetd/w_log b/examples/var_service/inetd/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/inetd/w_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' | ||
diff --git a/examples/var_service/nmeter/README b/examples/var_service/nmeter/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/nmeter/README +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | The real README file is one directory up. | ||
2 | |||
3 | This directory's run script can have useful comments. | ||
4 | If it doesn't but you feel it should, please send a patch | ||
5 | to busybox's mailing list. | ||
diff --git a/examples/var_service/ntpd/README b/examples/var_service/ntpd/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/ntpd/README +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | The real README file is one directory up. | ||
2 | |||
3 | This directory's run script can have useful comments. | ||
4 | If it doesn't but you feel it should, please send a patch | ||
5 | to busybox's mailing list. | ||
diff --git a/examples/var_service/ntpd/log/run b/examples/var_service/ntpd/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/ntpd/log/run +++ b/examples/var_service/ntpd/log/run | |||
@@ -1,21 +1,2 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | exec std_service_logger | |
3 | user=logger | ||
4 | |||
5 | logdir="/var/log/service/`(cd ..;basename $PWD)`" | ||
6 | mkdir -p "$logdir" 2>/dev/null | ||
7 | chown -R "$user": "$logdir" | ||
8 | chmod -R go-rwxst,u+rwX "$logdir" | ||
9 | rm -rf logdir | ||
10 | ln -s "$logdir" logdir | ||
11 | |||
12 | # make this dir accessible to logger | ||
13 | chmod a+rX . | ||
14 | |||
15 | exec >/dev/null | ||
16 | exec 2>&1 | ||
17 | exec \ | ||
18 | env - PATH="$PATH" \ | ||
19 | softlimit \ | ||
20 | setuidgid "$user" \ | ||
21 | svlogd -tt "$logdir" | ||
diff --git a/examples/var_service/ntpd/p_log b/examples/var_service/ntpd/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/ntpd/p_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | cat @* current | $PAGER | ||
diff --git a/examples/var_service/ntpd/run b/examples/var_service/ntpd/run index 6f2a68188..5c90aad41 100755 --- a/examples/var_service/ntpd/run +++ b/examples/var_service/ntpd/run | |||
@@ -6,12 +6,22 @@ exec 2>&1 | |||
6 | exec </dev/null | 6 | exec </dev/null |
7 | 7 | ||
8 | user=root | 8 | user=root |
9 | start_delay=15 | ||
10 | net_down_delay=5 | ||
9 | pool="us.pool.ntp.org" # replace "us" with your country code | 11 | pool="us.pool.ntp.org" # replace "us" with your country code |
10 | 12 | ||
11 | service="${PWD##*/}" | 13 | service="${PWD##*/}" |
12 | rundir="/var/run/service/$service" | 14 | rundir="/var/run/service/$service" |
13 | default_p_opt="-p 0.$pool -p 1.$pool -p 2.$pool -p 3.$pool" | 15 | default_p_opt="-p 0.$pool -p 1.$pool -p 2.$pool -p 3.$pool" |
14 | 16 | ||
17 | echo "* Checking network" | ||
18 | test -f /var/run/service/fw/up || exec sleep $net_down_delay | ||
19 | |||
20 | # With multiple interfaces (e.g. wired+wireless) going up, | ||
21 | # networking scripts may restart ntpd service several times | ||
22 | # in quick succession. Do not be too eager to start sending | ||
23 | # NTP requests: | ||
24 | sleep $start_delay | ||
15 | 25 | ||
16 | # Make sure rundir/ exists | 26 | # Make sure rundir/ exists |
17 | mkdir -p "$rundir" 2>/dev/null | 27 | mkdir -p "$rundir" 2>/dev/null |
@@ -20,30 +30,25 @@ chmod -R a=rX "$rundir" | |||
20 | rm -rf rundir 2>/dev/null | 30 | rm -rf rundir 2>/dev/null |
21 | ln -s "$rundir" rundir | 31 | ln -s "$rundir" rundir |
22 | 32 | ||
23 | |||
24 | echo "* Checking network" | ||
25 | test -f /var/run/service/fw/up || exec sleep 7 | ||
26 | sleep 5 # to let it settle | ||
27 | |||
28 | # Grab config from dhcp | 33 | # Grab config from dhcp |
29 | cfg=-1 | 34 | cfg=-1 |
30 | for f in rundir/*.ntpconf; do | 35 | for f in rundir/*.ntpconf; do |
31 | test -f "$f" || continue | 36 | test -f "$f" || continue |
32 | . "$f" | 37 | . "$f" |
33 | done | 38 | done |
34 | 39 | ||
35 | # Select peers | 40 | # Select peers |
36 | p_opt="" | 41 | p_opt="" |
37 | cfg=0 | 42 | cfg=0 |
38 | while test x"${ntpip[$cfg]}" != x""; do | 43 | while test x"${ntpip[$cfg]}" != x""; do |
39 | p_opt="$p_opt -p ${ntpip[$cfg]}" | 44 | p_opt="$p_opt -p ${ntpip[$cfg]}" |
40 | let cfg=cfg+1 | 45 | let cfg=cfg+1 |
41 | done | 46 | done |
42 | test x"$p_opt" == x"" && p_opt="$default_p_opt" | 47 | test x"$p_opt" == x"" && p_opt="$default_p_opt" |
43 | 48 | ||
44 | if test x"$p_opt" == x""; then | 49 | if test x"$p_opt" == x""; then |
45 | echo "* No NTP peers configured, stopping" | 50 | echo "* No NTP peers configured, stopping" |
46 | sv o . | 51 | svc -o . |
47 | exec sleep 1 | 52 | exec sleep 1 |
48 | fi | 53 | fi |
49 | 54 | ||
diff --git a/examples/var_service/ntpd/w_log b/examples/var_service/ntpd/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/ntpd/w_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' | ||
diff --git a/examples/var_service/std_service_logger b/examples/var_service/std_service_logger new file mode 100755 index 000000000..ee68ad12b --- /dev/null +++ b/examples/var_service/std_service_logger | |||
@@ -0,0 +1,32 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | user=logger | ||
4 | |||
5 | exec >/dev/null 2>&1 | ||
6 | |||
7 | service="${PWD%/log}" | ||
8 | service="${service##*/}" | ||
9 | logdir="/var/log/service/$service" | ||
10 | |||
11 | mkdir -p "$logdir" | ||
12 | chown -R "$user": "$logdir" | ||
13 | chmod -R go-rwxst,u+rwX "$logdir" | ||
14 | # TODO: if "$logdir/config" does not exist, | ||
15 | # based on service's preferences, write some setup in it: | ||
16 | # e.g. smaller nNUM directive ("I'm not that important, | ||
17 | # save 2 rather than default 10 one-megabyte log files") | ||
18 | |||
19 | # Convenience symlink in this log/ directory: | ||
20 | rm logdir | ||
21 | ln -s "$logdir" logdir | ||
22 | |||
23 | # Make current dir accessible to logger: | ||
24 | chmod a+rX . | ||
25 | |||
26 | args="" | ||
27 | test "$LOG_NOTIMESTAMP" || args="-tt" | ||
28 | |||
29 | exec \ | ||
30 | env - PATH="$PATH" \ | ||
31 | chpst -u "$user" -m $((20 * 1024*1024)) \ | ||
32 | svlogd $args "$logdir" | ||
diff --git a/examples/var_service/supplicant_if/README b/examples/var_service/supplicant_if/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/supplicant_if/README +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | The real README file is one directory up. | ||
2 | |||
3 | This directory's run script can have useful comments. | ||
4 | If it doesn't but you feel it should, please send a patch | ||
5 | to busybox's mailing list. | ||
diff --git a/examples/var_service/supplicant_if/log/run b/examples/var_service/supplicant_if/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/supplicant_if/log/run +++ b/examples/var_service/supplicant_if/log/run | |||
@@ -1,21 +1,2 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | exec std_service_logger | |
3 | user=logger | ||
4 | |||
5 | logdir="/var/log/service/`(cd ..;basename $PWD)`" | ||
6 | mkdir -p "$logdir" 2>/dev/null | ||
7 | chown -R "$user": "$logdir" | ||
8 | chmod -R go-rwxst,u+rwX "$logdir" | ||
9 | rm -rf logdir | ||
10 | ln -s "$logdir" logdir | ||
11 | |||
12 | # make this dir accessible to logger | ||
13 | chmod a+rX . | ||
14 | |||
15 | exec >/dev/null | ||
16 | exec 2>&1 | ||
17 | exec \ | ||
18 | env - PATH="$PATH" \ | ||
19 | softlimit \ | ||
20 | setuidgid "$user" \ | ||
21 | svlogd -tt "$logdir" | ||
diff --git a/examples/var_service/supplicant_if/p_log b/examples/var_service/supplicant_if/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/supplicant_if/p_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | cat @* current | $PAGER | ||
diff --git a/examples/var_service/supplicant_if/w_log b/examples/var_service/supplicant_if/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/supplicant_if/w_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' | ||
diff --git a/examples/var_service/sview b/examples/var_service/sview new file mode 100755 index 000000000..716c1079c --- /dev/null +++ b/examples/var_service/sview | |||
@@ -0,0 +1,19 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | test "$1" || { | ||
4 | echo "Syntax: ${0##*/} SERVICE" | ||
5 | exit 1 | ||
6 | } | ||
7 | |||
8 | test x"$1" = x"${1#*/}" -a x"$1" != x"." && { | ||
9 | # has no slashes and is not a "." | ||
10 | cd "/var/service/$1" || exit $? | ||
11 | set -- "." | ||
12 | } | ||
13 | |||
14 | test -x "$1/view" && exec "$1/view" | ||
15 | |||
16 | cd "log/logdir" || exit $? | ||
17 | |||
18 | h=`ttysize h` | ||
19 | exec tail -n $((h-1)) -F current 2>&1 | ||
diff --git a/examples/var_service/svpage b/examples/var_service/svpage new file mode 100755 index 000000000..31c3d6dd7 --- /dev/null +++ b/examples/var_service/svpage | |||
@@ -0,0 +1,19 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | test "$1" || { | ||
4 | echo "Syntax: ${0##*/} SERVICE" | ||
5 | exit 1 | ||
6 | } | ||
7 | |||
8 | test x"$1" = x"${1#*/}" -a x"$1" != x"." && { | ||
9 | # has no slashes and is not a "." | ||
10 | cd "/var/service/$1" || exit $? | ||
11 | set -- "." | ||
12 | } | ||
13 | |||
14 | test -x "$1/page" && exec "$1/page" | ||
15 | |||
16 | cd "log/logdir" || exit $? | ||
17 | |||
18 | test "$PAGER" || PAGER=less | ||
19 | cat @* current | $PAGER | ||
diff --git a/examples/var_service/tftpd/README b/examples/var_service/tftpd/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/tftpd/README +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | The real README file is one directory up. | ||
2 | |||
3 | This directory's run script can have useful comments. | ||
4 | If it doesn't but you feel it should, please send a patch | ||
5 | to busybox's mailing list. | ||
diff --git a/examples/var_service/tftpd/log/run b/examples/var_service/tftpd/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/tftpd/log/run +++ b/examples/var_service/tftpd/log/run | |||
@@ -1,21 +1,2 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | exec std_service_logger | |
3 | user=logger | ||
4 | |||
5 | logdir="/var/log/service/`(cd ..;basename $PWD)`" | ||
6 | mkdir -p "$logdir" 2>/dev/null | ||
7 | chown -R "$user": "$logdir" | ||
8 | chmod -R go-rwxst,u+rwX "$logdir" | ||
9 | rm -rf logdir | ||
10 | ln -s "$logdir" logdir | ||
11 | |||
12 | # make this dir accessible to logger | ||
13 | chmod a+rX . | ||
14 | |||
15 | exec >/dev/null | ||
16 | exec 2>&1 | ||
17 | exec \ | ||
18 | env - PATH="$PATH" \ | ||
19 | softlimit \ | ||
20 | setuidgid "$user" \ | ||
21 | svlogd -tt "$logdir" | ||
diff --git a/examples/var_service/tftpd/p_log b/examples/var_service/tftpd/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/tftpd/p_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | cat @* current | $PAGER | ||
diff --git a/examples/var_service/tftpd/w_log b/examples/var_service/tftpd/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/tftpd/w_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' | ||
diff --git a/examples/var_service/zcip_if/README b/examples/var_service/zcip_if/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/zcip_if/README +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | The real README file is one directory up. | ||
2 | |||
3 | This directory's run script can have useful comments. | ||
4 | If it doesn't but you feel it should, please send a patch | ||
5 | to busybox's mailing list. | ||
diff --git a/examples/var_service/zcip_if/finish b/examples/var_service/zcip_if/finish index 95995cf5f..7955cf3b8 100755 --- a/examples/var_service/zcip_if/finish +++ b/examples/var_service/zcip_if/finish | |||
@@ -1,5 +1,5 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | # executed when service is taken down ("sv d .") | 2 | # executed when service is taken down |
3 | 3 | ||
4 | service=${PWD##*/} | 4 | service=${PWD##*/} |
5 | file_ipconf="$service.ipconf" | 5 | file_ipconf="$service.ipconf" |
@@ -10,4 +10,4 @@ echo "Finish: deconfiguring" | |||
10 | rm "env.out" | 10 | rm "env.out" |
11 | rm "$file_ipconf" | 11 | rm "$file_ipconf" |
12 | rm "$dir_ipconf/$file_ipconf" | 12 | rm "$dir_ipconf/$file_ipconf" |
13 | sv u /var/service/fw | 13 | svc -u fw |
diff --git a/examples/var_service/zcip_if/log/run b/examples/var_service/zcip_if/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/zcip_if/log/run +++ b/examples/var_service/zcip_if/log/run | |||
@@ -1,21 +1,2 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | exec std_service_logger | |
3 | user=logger | ||
4 | |||
5 | logdir="/var/log/service/`(cd ..;basename $PWD)`" | ||
6 | mkdir -p "$logdir" 2>/dev/null | ||
7 | chown -R "$user": "$logdir" | ||
8 | chmod -R go-rwxst,u+rwX "$logdir" | ||
9 | rm -rf logdir | ||
10 | ln -s "$logdir" logdir | ||
11 | |||
12 | # make this dir accessible to logger | ||
13 | chmod a+rX . | ||
14 | |||
15 | exec >/dev/null | ||
16 | exec 2>&1 | ||
17 | exec \ | ||
18 | env - PATH="$PATH" \ | ||
19 | softlimit \ | ||
20 | setuidgid "$user" \ | ||
21 | svlogd -tt "$logdir" | ||
diff --git a/examples/var_service/zcip_if/p_log b/examples/var_service/zcip_if/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/zcip_if/p_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | cat @* current | $PAGER | ||
diff --git a/examples/var_service/zcip_if/w_log b/examples/var_service/zcip_if/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/zcip_if/w_log +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' | ||
diff --git a/examples/var_service/zcip_if/zcip_handler b/examples/var_service/zcip_if/zcip_handler index 3c6ca788b..625450f7b 100755 --- a/examples/var_service/zcip_if/zcip_handler +++ b/examples/var_service/zcip_if/zcip_handler | |||
@@ -28,7 +28,7 @@ if test x"$1" != x"config"; then | |||
28 | echo "Deconfiguring" | 28 | echo "Deconfiguring" |
29 | rm "$file_ipconf" | 29 | rm "$file_ipconf" |
30 | rm "$dir_ipconf/$file_ipconf" | 30 | rm "$dir_ipconf/$file_ipconf" |
31 | sv u /var/service/fw | 31 | svc -u fw |
32 | exit | 32 | exit |
33 | fi | 33 | fi |
34 | 34 | ||
@@ -43,5 +43,5 @@ if test $? != 0; then | |||
43 | echo "Reconfiguring fw" | 43 | echo "Reconfiguring fw" |
44 | mkdir -p "$dir_ipconf" 2>/dev/null | 44 | mkdir -p "$dir_ipconf" 2>/dev/null |
45 | cp "$file_ipconf" "$dir_ipconf/$file_ipconf" | 45 | cp "$file_ipconf" "$dir_ipconf/$file_ipconf" |
46 | sv u /var/service/fw | 46 | svc -u fw |
47 | fi | 47 | fi |
diff --git a/findutils/Config.src b/findutils/Config.src index 9ee71a845..c28c5844e 100644 --- a/findutils/Config.src +++ b/findutils/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "Finding Utilities" | 6 | menu "Finding Utilities" |
diff --git a/findutils/find.c b/findutils/find.c index 07321c81a..6407c6c5a 100644 --- a/findutils/find.c +++ b/findutils/find.c | |||
@@ -95,6 +95,11 @@ | |||
95 | //config: Enable searching based on file type (file, | 95 | //config: Enable searching based on file type (file, |
96 | //config: directory, socket, device, etc.). | 96 | //config: directory, socket, device, etc.). |
97 | //config: | 97 | //config: |
98 | //config:config FEATURE_FIND_EXECUTABLE | ||
99 | //config: bool "Enable -executable: file is executable" | ||
100 | //config: default y | ||
101 | //config: depends on FIND | ||
102 | //config: | ||
98 | //config:config FEATURE_FIND_XDEV | 103 | //config:config FEATURE_FIND_XDEV |
99 | //config: bool "Enable -xdev: 'stay in filesystem'" | 104 | //config: bool "Enable -xdev: 'stay in filesystem'" |
100 | //config: default y | 105 | //config: default y |
@@ -182,6 +187,13 @@ | |||
182 | //config: If the file is a directory, don't descend into it. Useful for | 187 | //config: If the file is a directory, don't descend into it. Useful for |
183 | //config: exclusion .svn and CVS directories. | 188 | //config: exclusion .svn and CVS directories. |
184 | //config: | 189 | //config: |
190 | //config:config FEATURE_FIND_QUIT | ||
191 | //config: bool "Enable -quit: exit" | ||
192 | //config: default y | ||
193 | //config: depends on FIND | ||
194 | //config: help | ||
195 | //config: If this action is reached, 'find' exits. | ||
196 | //config: | ||
185 | //config:config FEATURE_FIND_DELETE | 197 | //config:config FEATURE_FIND_DELETE |
186 | //config: bool "Enable -delete: delete files/dirs" | 198 | //config: bool "Enable -delete: delete files/dirs" |
187 | //config: default y | 199 | //config: default y |
@@ -265,6 +277,9 @@ | |||
265 | //usage: IF_FEATURE_FIND_TYPE( | 277 | //usage: IF_FEATURE_FIND_TYPE( |
266 | //usage: "\n -type X File type is X (one of: f,d,l,b,c,s,p)" | 278 | //usage: "\n -type X File type is X (one of: f,d,l,b,c,s,p)" |
267 | //usage: ) | 279 | //usage: ) |
280 | //usage: IF_FEATURE_FIND_EXECUTABLE( | ||
281 | //usage: "\n -executable File is executable" | ||
282 | //usage: ) | ||
268 | //usage: IF_FEATURE_FIND_PERM( | 283 | //usage: IF_FEATURE_FIND_PERM( |
269 | //usage: "\n -perm MASK At least one mask bit (+MASK), all bits (-MASK)," | 284 | //usage: "\n -perm MASK At least one mask bit (+MASK), all bits (-MASK)," |
270 | //usage: "\n or exactly MASK bits are set in file's mode" | 285 | //usage: "\n or exactly MASK bits are set in file's mode" |
@@ -318,6 +333,9 @@ | |||
318 | //usage: IF_FEATURE_FIND_DELETE( | 333 | //usage: IF_FEATURE_FIND_DELETE( |
319 | //usage: "\n -delete Delete current file/directory. Turns on -depth option" | 334 | //usage: "\n -delete Delete current file/directory. Turns on -depth option" |
320 | //usage: ) | 335 | //usage: ) |
336 | //usage: IF_FEATURE_FIND_QUIT( | ||
337 | //usage: "\n -quit Exit" | ||
338 | //usage: ) | ||
321 | //usage: | 339 | //usage: |
322 | //usage:#define find_example_usage | 340 | //usage:#define find_example_usage |
323 | //usage: "$ find / -name passwd\n" | 341 | //usage: "$ find / -name passwd\n" |
@@ -365,6 +383,7 @@ IF_FEATURE_FIND_PATH( ACTS(path, const char *pattern; bool ipath;)) | |||
365 | IF_FEATURE_FIND_REGEX( ACTS(regex, regex_t compiled_pattern;)) | 383 | IF_FEATURE_FIND_REGEX( ACTS(regex, regex_t compiled_pattern;)) |
366 | IF_FEATURE_FIND_PRINT0( ACTS(print0)) | 384 | IF_FEATURE_FIND_PRINT0( ACTS(print0)) |
367 | IF_FEATURE_FIND_TYPE( ACTS(type, int type_mask;)) | 385 | IF_FEATURE_FIND_TYPE( ACTS(type, int type_mask;)) |
386 | IF_FEATURE_FIND_EXECUTABLE(ACTS(executable)) | ||
368 | IF_FEATURE_FIND_PERM( ACTS(perm, char perm_char; mode_t perm_mask;)) | 387 | IF_FEATURE_FIND_PERM( ACTS(perm, char perm_char; mode_t perm_mask;)) |
369 | IF_FEATURE_FIND_MTIME( ACTS(mtime, char mtime_char; unsigned mtime_days;)) | 388 | IF_FEATURE_FIND_MTIME( ACTS(mtime, char mtime_char; unsigned mtime_days;)) |
370 | IF_FEATURE_FIND_MMIN( ACTS(mmin, char mmin_char; unsigned mmin_mins;)) | 389 | IF_FEATURE_FIND_MMIN( ACTS(mmin, char mmin_char; unsigned mmin_mins;)) |
@@ -375,6 +394,7 @@ IF_FEATURE_FIND_SIZE( ACTS(size, char size_char; off_t size;)) | |||
375 | IF_FEATURE_FIND_CONTEXT(ACTS(context, security_context_t context;)) | 394 | IF_FEATURE_FIND_CONTEXT(ACTS(context, security_context_t context;)) |
376 | IF_FEATURE_FIND_PAREN( ACTS(paren, action ***subexpr;)) | 395 | IF_FEATURE_FIND_PAREN( ACTS(paren, action ***subexpr;)) |
377 | IF_FEATURE_FIND_PRUNE( ACTS(prune)) | 396 | IF_FEATURE_FIND_PRUNE( ACTS(prune)) |
397 | IF_FEATURE_FIND_QUIT( ACTS(quit)) | ||
378 | IF_FEATURE_FIND_DELETE( ACTS(delete)) | 398 | IF_FEATURE_FIND_DELETE( ACTS(delete)) |
379 | IF_FEATURE_FIND_EXEC( ACTS(exec, | 399 | IF_FEATURE_FIND_EXEC( ACTS(exec, |
380 | char **exec_argv; /* -exec ARGS */ | 400 | char **exec_argv; /* -exec ARGS */ |
@@ -402,6 +422,7 @@ struct globals { | |||
402 | action ***actions; | 422 | action ***actions; |
403 | smallint need_print; | 423 | smallint need_print; |
404 | smallint xdev_on; | 424 | smallint xdev_on; |
425 | smalluint exitstatus; | ||
405 | recurse_flags_t recurse_flags; | 426 | recurse_flags_t recurse_flags; |
406 | IF_FEATURE_FIND_EXEC_PLUS(unsigned max_argv_len;) | 427 | IF_FEATURE_FIND_EXEC_PLUS(unsigned max_argv_len;) |
407 | } FIX_ALIASING; | 428 | } FIX_ALIASING; |
@@ -566,6 +587,12 @@ ACTF(type) | |||
566 | return ((statbuf->st_mode & S_IFMT) == ap->type_mask); | 587 | return ((statbuf->st_mode & S_IFMT) == ap->type_mask); |
567 | } | 588 | } |
568 | #endif | 589 | #endif |
590 | #if ENABLE_FEATURE_FIND_EXECUTABLE | ||
591 | ACTF(executable) | ||
592 | { | ||
593 | return access(fileName, X_OK) == 0; | ||
594 | } | ||
595 | #endif | ||
569 | #if ENABLE_FEATURE_FIND_PERM | 596 | #if ENABLE_FEATURE_FIND_PERM |
570 | ACTF(perm) | 597 | ACTF(perm) |
571 | { | 598 | { |
@@ -774,6 +801,12 @@ ACTF(prune) | |||
774 | return SKIP + TRUE; | 801 | return SKIP + TRUE; |
775 | } | 802 | } |
776 | #endif | 803 | #endif |
804 | #if ENABLE_FEATURE_FIND_QUIT | ||
805 | ACTF(quit) | ||
806 | { | ||
807 | exit(G.exitstatus); | ||
808 | } | ||
809 | #endif | ||
777 | #if ENABLE_FEATURE_FIND_DELETE | 810 | #if ENABLE_FEATURE_FIND_DELETE |
778 | ACTF(delete) | 811 | ACTF(delete) |
779 | { | 812 | { |
@@ -954,8 +987,10 @@ static action*** parse_params(char **argv) | |||
954 | PARM_print , | 987 | PARM_print , |
955 | IF_FEATURE_FIND_PRINT0( PARM_print0 ,) | 988 | IF_FEATURE_FIND_PRINT0( PARM_print0 ,) |
956 | IF_FEATURE_FIND_PRUNE( PARM_prune ,) | 989 | IF_FEATURE_FIND_PRUNE( PARM_prune ,) |
990 | IF_FEATURE_FIND_QUIT( PARM_quit ,) | ||
957 | IF_FEATURE_FIND_DELETE( PARM_delete ,) | 991 | IF_FEATURE_FIND_DELETE( PARM_delete ,) |
958 | IF_FEATURE_FIND_EXEC( PARM_exec ,) | 992 | IF_FEATURE_FIND_EXEC( PARM_exec ,) |
993 | IF_FEATURE_FIND_EXECUTABLE(PARM_executable,) | ||
959 | IF_FEATURE_FIND_PAREN( PARM_char_brace,) | 994 | IF_FEATURE_FIND_PAREN( PARM_char_brace,) |
960 | /* All options/actions starting from here require argument */ | 995 | /* All options/actions starting from here require argument */ |
961 | PARM_name , | 996 | PARM_name , |
@@ -997,8 +1032,10 @@ static action*** parse_params(char **argv) | |||
997 | "-print\0" | 1032 | "-print\0" |
998 | IF_FEATURE_FIND_PRINT0( "-print0\0" ) | 1033 | IF_FEATURE_FIND_PRINT0( "-print0\0" ) |
999 | IF_FEATURE_FIND_PRUNE( "-prune\0" ) | 1034 | IF_FEATURE_FIND_PRUNE( "-prune\0" ) |
1035 | IF_FEATURE_FIND_QUIT( "-quit\0" ) | ||
1000 | IF_FEATURE_FIND_DELETE( "-delete\0" ) | 1036 | IF_FEATURE_FIND_DELETE( "-delete\0" ) |
1001 | IF_FEATURE_FIND_EXEC( "-exec\0" ) | 1037 | IF_FEATURE_FIND_EXEC( "-exec\0" ) |
1038 | IF_FEATURE_FIND_EXECUTABLE("-executable\0") | ||
1002 | IF_FEATURE_FIND_PAREN( "(\0" ) | 1039 | IF_FEATURE_FIND_PAREN( "(\0" ) |
1003 | /* All options/actions starting from here require argument */ | 1040 | /* All options/actions starting from here require argument */ |
1004 | "-name\0" | 1041 | "-name\0" |
@@ -1152,6 +1189,12 @@ static action*** parse_params(char **argv) | |||
1152 | (void) ALLOC_ACTION(prune); | 1189 | (void) ALLOC_ACTION(prune); |
1153 | } | 1190 | } |
1154 | #endif | 1191 | #endif |
1192 | #if ENABLE_FEATURE_FIND_QUIT | ||
1193 | else if (parm == PARM_quit) { | ||
1194 | dbg("%d", __LINE__); | ||
1195 | (void) ALLOC_ACTION(quit); | ||
1196 | } | ||
1197 | #endif | ||
1155 | #if ENABLE_FEATURE_FIND_DELETE | 1198 | #if ENABLE_FEATURE_FIND_DELETE |
1156 | else if (parm == PARM_delete) { | 1199 | else if (parm == PARM_delete) { |
1157 | dbg("%d", __LINE__); | 1200 | dbg("%d", __LINE__); |
@@ -1262,6 +1305,11 @@ static action*** parse_params(char **argv) | |||
1262 | dbg("created:type mask:%x", ap->type_mask); | 1305 | dbg("created:type mask:%x", ap->type_mask); |
1263 | } | 1306 | } |
1264 | #endif | 1307 | #endif |
1308 | #if ENABLE_FEATURE_FIND_EXECUTABLE | ||
1309 | else if (parm == PARM_executable) { | ||
1310 | (void) ALLOC_ACTION(executable); | ||
1311 | } | ||
1312 | #endif | ||
1265 | #if ENABLE_FEATURE_FIND_PERM | 1313 | #if ENABLE_FEATURE_FIND_PERM |
1266 | /* -perm BITS File's mode bits are exactly BITS (octal or symbolic). | 1314 | /* -perm BITS File's mode bits are exactly BITS (octal or symbolic). |
1267 | * Symbolic modes use mode 0 as a point of departure. | 1315 | * Symbolic modes use mode 0 as a point of departure. |
@@ -1401,7 +1449,7 @@ static action*** parse_params(char **argv) | |||
1401 | int find_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 1449 | int find_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
1402 | int find_main(int argc UNUSED_PARAM, char **argv) | 1450 | int find_main(int argc UNUSED_PARAM, char **argv) |
1403 | { | 1451 | { |
1404 | int i, firstopt, status = EXIT_SUCCESS; | 1452 | int i, firstopt; |
1405 | char **past_HLP, *saved; | 1453 | char **past_HLP, *saved; |
1406 | 1454 | ||
1407 | INIT_G(); | 1455 | INIT_G(); |
@@ -1475,10 +1523,10 @@ int find_main(int argc UNUSED_PARAM, char **argv) | |||
1475 | NULL, /* user data */ | 1523 | NULL, /* user data */ |
1476 | 0) /* depth */ | 1524 | 0) /* depth */ |
1477 | ) { | 1525 | ) { |
1478 | status |= EXIT_FAILURE; | 1526 | G.exitstatus |= EXIT_FAILURE; |
1479 | } | 1527 | } |
1480 | } | 1528 | } |
1481 | 1529 | ||
1482 | IF_FEATURE_FIND_EXEC_PLUS(status |= flush_exec_plus();) | 1530 | IF_FEATURE_FIND_EXEC_PLUS(G.exitstatus |= flush_exec_plus();) |
1483 | return status; | 1531 | return G.exitstatus; |
1484 | } | 1532 | } |
diff --git a/findutils/grep.c b/findutils/grep.c index 88de0d4ef..3e8ea9239 100644 --- a/findutils/grep.c +++ b/findutils/grep.c | |||
@@ -704,10 +704,15 @@ int grep_main(int argc UNUSED_PARAM, char **argv) | |||
704 | /* do normal option parsing */ | 704 | /* do normal option parsing */ |
705 | #if ENABLE_FEATURE_GREP_CONTEXT | 705 | #if ENABLE_FEATURE_GREP_CONTEXT |
706 | /* -H unsets -h; -C unsets -A,-B */ | 706 | /* -H unsets -h; -C unsets -A,-B */ |
707 | opts = getopt32(argv, | 707 | opts = getopt32long(argv, "^" |
708 | "^" OPTSTR_GREP "\0" "H-h:C-AB", | 708 | OPTSTR_GREP |
709 | "\0" | ||
710 | "H-h:C-AB", | ||
711 | "color\0" Optional_argument "\xff", | ||
709 | &pattern_head, &fopt, &max_matches, | 712 | &pattern_head, &fopt, &max_matches, |
710 | &lines_after, &lines_before, &Copt); | 713 | &lines_after, &lines_before, &Copt |
714 | , NULL | ||
715 | ); | ||
711 | 716 | ||
712 | if (opts & OPT_C) { | 717 | if (opts & OPT_C) { |
713 | /* -C unsets prev -A and -B, but following -A or -B | 718 | /* -C unsets prev -A and -B, but following -A or -B |
diff --git a/findutils/xargs.c b/findutils/xargs.c index df2300207..4399783ea 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c | |||
@@ -606,7 +606,7 @@ static int xargs_ask_confirmation(void) | |||
606 | //usage: ) | 606 | //usage: ) |
607 | //usage: "\n -r Don't run command if input is empty" | 607 | //usage: "\n -r Don't run command if input is empty" |
608 | //usage: IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( | 608 | //usage: IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( |
609 | //usage: "\n -0 Input is separated by NUL characters" | 609 | //usage: "\n -0 Input is separated by NULs" |
610 | //usage: ) | 610 | //usage: ) |
611 | //usage: IF_FEATURE_XARGS_SUPPORT_ARGS_FILE( | 611 | //usage: IF_FEATURE_XARGS_SUPPORT_ARGS_FILE( |
612 | //usage: "\n -a FILE Read from FILE instead of stdin" | 612 | //usage: "\n -a FILE Read from FILE instead of stdin" |
diff --git a/include/bb_archive.h b/include/bb_archive.h index 2182fcc3c..ace9c8e23 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h | |||
@@ -74,8 +74,8 @@ typedef struct archive_handle_t { | |||
74 | /* Currently processed file's header */ | 74 | /* Currently processed file's header */ |
75 | file_header_t *file_header; | 75 | file_header_t *file_header; |
76 | 76 | ||
77 | /* List of symlink placeholders */ | 77 | /* List of link placeholders */ |
78 | llist_t *symlink_placeholders; | 78 | llist_t *link_placeholders; |
79 | 79 | ||
80 | /* Process the header component, e.g. tar -t */ | 80 | /* Process the header component, e.g. tar -t */ |
81 | void FAST_FUNC (*action_header)(const file_header_t *); | 81 | void FAST_FUNC (*action_header)(const file_header_t *); |
@@ -126,10 +126,10 @@ typedef struct archive_handle_t { | |||
126 | #if ENABLE_FEATURE_AR_CREATE | 126 | #if ENABLE_FEATURE_AR_CREATE |
127 | const char *ar__name; | 127 | const char *ar__name; |
128 | struct archive_handle_t *ar__out; | 128 | struct archive_handle_t *ar__out; |
129 | # if ENABLE_FEATURE_AR_LONG_FILENAMES | 129 | #endif |
130 | #if ENABLE_FEATURE_AR_LONG_FILENAMES | ||
130 | char *ar__long_names; | 131 | char *ar__long_names; |
131 | unsigned ar__long_name_size; | 132 | unsigned ar__long_name_size; |
132 | # endif | ||
133 | #endif | 133 | #endif |
134 | } archive_handle_t; | 134 | } archive_handle_t; |
135 | /* bits in ah_flags */ | 135 | /* bits in ah_flags */ |
@@ -213,13 +213,14 @@ void seek_by_jump(int fd, off_t amount) FAST_FUNC; | |||
213 | void seek_by_read(int fd, off_t amount) FAST_FUNC; | 213 | void seek_by_read(int fd, off_t amount) FAST_FUNC; |
214 | 214 | ||
215 | const char *strip_unsafe_prefix(const char *str) FAST_FUNC; | 215 | const char *strip_unsafe_prefix(const char *str) FAST_FUNC; |
216 | void create_or_remember_symlink(llist_t **symlink_placeholders, | 216 | void create_or_remember_link(llist_t **link_placeholders, |
217 | const char *target, | 217 | const char *target, |
218 | const char *linkname) FAST_FUNC; | 218 | const char *linkname, |
219 | int hard_link) FAST_FUNC; | ||
219 | #if !ENABLE_PLATFORM_MINGW32 | 220 | #if !ENABLE_PLATFORM_MINGW32 |
220 | void create_symlinks_from_list(llist_t *list) FAST_FUNC; | 221 | void create_links_from_list(llist_t *list) FAST_FUNC; |
221 | #else | 222 | #else |
222 | #define create_symlinks_from_list(l) (void)0 | 223 | #define create_links_from_list(l) (void)0 |
223 | #endif | 224 | #endif |
224 | 225 | ||
225 | void data_align(archive_handle_t *archive_handle, unsigned boundary) FAST_FUNC; | 226 | void data_align(archive_handle_t *archive_handle, unsigned boundary) FAST_FUNC; |
diff --git a/include/libbb.h b/include/libbb.h index fb9167ce3..0264282dd 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -428,6 +428,9 @@ enum { /* cp.c, mv.c, install.c depend on these values. CAREFUL when changing th | |||
428 | FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 15, /* -c */ | 428 | FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 15, /* -c */ |
429 | #endif | 429 | #endif |
430 | FILEUTILS_RMDEST = 1 << (16 - !ENABLE_SELINUX), /* --remove-destination */ | 430 | FILEUTILS_RMDEST = 1 << (16 - !ENABLE_SELINUX), /* --remove-destination */ |
431 | /* bit 17 skipped for "cp --parents" */ | ||
432 | FILEUTILS_REFLINK = 1 << (18 - !ENABLE_SELINUX), /* cp --reflink=auto */ | ||
433 | FILEUTILS_REFLINK_ALWAYS = 1 << (19 - !ENABLE_SELINUX), /* cp --reflink[=always] */ | ||
431 | /* | 434 | /* |
432 | * Hole. cp may have some bits set here, | 435 | * Hole. cp may have some bits set here, |
433 | * they should not affect remove_file()/copy_file() | 436 | * they should not affect remove_file()/copy_file() |
@@ -503,6 +506,7 @@ DIR *xopendir(const char *path) FAST_FUNC; | |||
503 | DIR *warn_opendir(const char *path) FAST_FUNC; | 506 | DIR *warn_opendir(const char *path) FAST_FUNC; |
504 | 507 | ||
505 | char *xmalloc_realpath(const char *path) FAST_FUNC RETURNS_MALLOC; | 508 | char *xmalloc_realpath(const char *path) FAST_FUNC RETURNS_MALLOC; |
509 | char *xmalloc_realpath_coreutils(const char *path) FAST_FUNC RETURNS_MALLOC; | ||
506 | char *xmalloc_readlink(const char *path) FAST_FUNC RETURNS_MALLOC; | 510 | char *xmalloc_readlink(const char *path) FAST_FUNC RETURNS_MALLOC; |
507 | char *xmalloc_readlink_or_warn(const char *path) FAST_FUNC RETURNS_MALLOC; | 511 | char *xmalloc_readlink_or_warn(const char *path) FAST_FUNC RETURNS_MALLOC; |
508 | /* !RETURNS_MALLOC: it's a realloc-like function */ | 512 | /* !RETURNS_MALLOC: it's a realloc-like function */ |
diff --git a/init/Config.src b/init/Config.src index 5767c93f0..b19b0bea1 100644 --- a/init/Config.src +++ b/init/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "Init Utilities" | 6 | menu "Init Utilities" |
diff --git a/klibc-utils/Config.src b/klibc-utils/Config.src index fe7cb1315..cf4552e51 100644 --- a/klibc-utils/Config.src +++ b/klibc-utils/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "klibc-utils" | 6 | menu "klibc-utils" |
diff --git a/libbb/Config.src b/libbb/Config.src index 16e16480b..312aa1831 100644 --- a/libbb/Config.src +++ b/libbb/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | comment "Library Tuning" | 6 | comment "Library Tuning" |
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index f250264d9..7df75c665 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -177,8 +177,11 @@ void FAST_FUNC bb_show_usage(void) | |||
177 | else { | 177 | else { |
178 | full_write2_str("\nUsage: "); | 178 | full_write2_str("\nUsage: "); |
179 | full_write2_str(applet_name); | 179 | full_write2_str(applet_name); |
180 | full_write2_str(" "); | 180 | if (p[0]) { |
181 | full_write2_str(p); | 181 | if (p[0] != '\n') |
182 | full_write2_str(" "); | ||
183 | full_write2_str(p); | ||
184 | } | ||
182 | full_write2_str("\n"); | 185 | full_write2_str("\n"); |
183 | } | 186 | } |
184 | if (ENABLE_FEATURE_CLEAN_UP) | 187 | if (ENABLE_FEATURE_CLEAN_UP) |
@@ -747,7 +750,7 @@ static void install_links(const char *busybox, int use_symbolic_links, | |||
747 | * busybox.h::bb_install_loc_t, or else... */ | 750 | * busybox.h::bb_install_loc_t, or else... */ |
748 | int (*lf)(const char *, const char *); | 751 | int (*lf)(const char *, const char *); |
749 | char *fpc; | 752 | char *fpc; |
750 | const char *appname = applet_names; | 753 | const char *appname = applet_names; |
751 | unsigned i; | 754 | unsigned i; |
752 | int rc; | 755 | int rc; |
753 | 756 | ||
diff --git a/libbb/copy_file.c b/libbb/copy_file.c index c60765d95..7cd9cd978 100644 --- a/libbb/copy_file.c +++ b/libbb/copy_file.c | |||
@@ -343,8 +343,27 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) | |||
343 | } | 343 | } |
344 | } | 344 | } |
345 | #endif | 345 | #endif |
346 | #if ENABLE_FEATURE_CP_REFLINK | ||
347 | # undef BTRFS_IOCTL_MAGIC | ||
348 | # define BTRFS_IOCTL_MAGIC 0x94 | ||
349 | # undef BTRFS_IOC_CLONE | ||
350 | # define BTRFS_IOC_CLONE _IOW (BTRFS_IOCTL_MAGIC, 9, int) | ||
351 | if (flags & FILEUTILS_REFLINK) { | ||
352 | retval = ioctl(dst_fd, BTRFS_IOC_CLONE, src_fd); | ||
353 | if (retval == 0) | ||
354 | goto do_close; | ||
355 | /* reflink did not work */ | ||
356 | if (flags & FILEUTILS_REFLINK_ALWAYS) { | ||
357 | bb_perror_msg("failed to clone '%s' from '%s'", dest, source); | ||
358 | goto do_close; | ||
359 | } | ||
360 | /* fall through to standard copy */ | ||
361 | retval = 0; | ||
362 | } | ||
363 | #endif | ||
346 | if (bb_copyfd_eof(src_fd, dst_fd) == -1) | 364 | if (bb_copyfd_eof(src_fd, dst_fd) == -1) |
347 | retval = -1; | 365 | retval = -1; |
366 | IF_FEATURE_CP_REFLINK(do_close:) | ||
348 | /* Careful with writing... */ | 367 | /* Careful with writing... */ |
349 | if (close(dst_fd) < 0) { | 368 | if (close(dst_fd) < 0) { |
350 | bb_perror_msg("error writing to '%s'", dest); | 369 | bb_perror_msg("error writing to '%s'", dest); |
diff --git a/libbb/dump.c b/libbb/dump.c index 5941ef902..b4b49d709 100644 --- a/libbb/dump.c +++ b/libbb/dump.c | |||
@@ -387,7 +387,10 @@ static unsigned char *get(priv_dumper_t *dumper) | |||
387 | if (need == blocksize) { | 387 | if (need == blocksize) { |
388 | return NULL; | 388 | return NULL; |
389 | } | 389 | } |
390 | if (dumper->pub.dump_vflag != ALL && !memcmp(dumper->get__curp, dumper->get__savp, nread)) { | 390 | if (dumper->pub.dump_vflag != ALL /* not "show all"? */ |
391 | && dumper->pub.dump_vflag != FIRST /* not first line? */ | ||
392 | && memcmp(dumper->get__curp, dumper->get__savp, nread) == 0 /* same data? */ | ||
393 | ) { | ||
391 | if (dumper->pub.dump_vflag != DUP) { | 394 | if (dumper->pub.dump_vflag != DUP) { |
392 | puts("*"); | 395 | puts("*"); |
393 | } | 396 | } |
@@ -399,7 +402,7 @@ static unsigned char *get(priv_dumper_t *dumper) | |||
399 | } | 402 | } |
400 | n = fread(dumper->get__curp + nread, sizeof(unsigned char), | 403 | n = fread(dumper->get__curp + nread, sizeof(unsigned char), |
401 | dumper->pub.dump_length == -1 ? need : MIN(dumper->pub.dump_length, need), stdin); | 404 | dumper->pub.dump_length == -1 ? need : MIN(dumper->pub.dump_length, need), stdin); |
402 | if (!n) { | 405 | if (n == 0) { |
403 | if (ferror(stdin)) { | 406 | if (ferror(stdin)) { |
404 | bb_simple_perror_msg(dumper->argv[-1]); | 407 | bb_simple_perror_msg(dumper->argv[-1]); |
405 | } | 408 | } |
@@ -411,9 +414,10 @@ static unsigned char *get(priv_dumper_t *dumper) | |||
411 | dumper->pub.dump_length -= n; | 414 | dumper->pub.dump_length -= n; |
412 | } | 415 | } |
413 | need -= n; | 416 | need -= n; |
414 | if (!need) { | 417 | if (need == 0) { |
415 | if (dumper->pub.dump_vflag == ALL || dumper->pub.dump_vflag == FIRST | 418 | if (dumper->pub.dump_vflag == ALL /* "show all"? */ |
416 | || memcmp(dumper->get__curp, dumper->get__savp, blocksize) | 419 | || dumper->pub.dump_vflag == FIRST /* first line? */ |
420 | || memcmp(dumper->get__curp, dumper->get__savp, blocksize) != 0 /* not same data? */ | ||
417 | ) { | 421 | ) { |
418 | if (dumper->pub.dump_vflag == DUP || dumper->pub.dump_vflag == FIRST) { | 422 | if (dumper->pub.dump_vflag == DUP || dumper->pub.dump_vflag == FIRST) { |
419 | dumper->pub.dump_vflag = WAIT; | 423 | dumper->pub.dump_vflag = WAIT; |
diff --git a/libbb/loop.c b/libbb/loop.c index f0d4296ae..c78535a20 100644 --- a/libbb/loop.c +++ b/libbb/loop.c | |||
@@ -106,6 +106,10 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse | |||
106 | return -errno; | 106 | return -errno; |
107 | } | 107 | } |
108 | 108 | ||
109 | //TODO: use LOOP_CTL_GET_FREE instead of trying every loopN in sequence? a-la: | ||
110 | // fd = open("/dev/loop-control", O_RDWR); | ||
111 | // loopN = ioctl(fd, LOOP_CTL_GET_FREE); | ||
112 | // | ||
109 | /* Find a loop device. */ | 113 | /* Find a loop device. */ |
110 | try = *device ? *device : dev; | 114 | try = *device ? *device : dev; |
111 | /* 1048575 (0xfffff) is a max possible minor number in Linux circa 2010 */ | 115 | /* 1048575 (0xfffff) is a max possible minor number in Linux circa 2010 */ |
diff --git a/libbb/nuke_str.c b/libbb/nuke_str.c index 240e68004..b5385e956 100644 --- a/libbb/nuke_str.c +++ b/libbb/nuke_str.c | |||
@@ -12,7 +12,7 @@ | |||
12 | 12 | ||
13 | void FAST_FUNC nuke_str(char *str) | 13 | void FAST_FUNC nuke_str(char *str) |
14 | { | 14 | { |
15 | if (str) { | 15 | if (str) { |
16 | while (*str) | 16 | while (*str) |
17 | *str++ = 0; | 17 | *str++ = 0; |
18 | /* or: memset(str, 0, strlen(str)); - not as small as above */ | 18 | /* or: memset(str, 0, strlen(str)); - not as small as above */ |
diff --git a/libbb/pw_encrypt.c b/libbb/pw_encrypt.c index 1edf4b6f0..86455cd0d 100644 --- a/libbb/pw_encrypt.c +++ b/libbb/pw_encrypt.c | |||
@@ -6,6 +6,7 @@ | |||
6 | * | 6 | * |
7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
8 | */ | 8 | */ |
9 | #include <crypt.h> | ||
9 | #include "libbb.h" | 10 | #include "libbb.h" |
10 | 11 | ||
11 | /* static const uint8_t ascii64[] ALIGN1 = | 12 | /* static const uint8_t ascii64[] ALIGN1 = |
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index 21263ccfe..a0db2b86e 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c | |||
@@ -222,6 +222,7 @@ void FAST_FUNC xdup2(int from, int to) | |||
222 | { | 222 | { |
223 | if (dup2(from, to) != to) | 223 | if (dup2(from, to) != to) |
224 | bb_perror_msg_and_die("can't duplicate file descriptor"); | 224 | bb_perror_msg_and_die("can't duplicate file descriptor"); |
225 | // " %d to %d", from, to); | ||
225 | } | 226 | } |
226 | 227 | ||
227 | // "Renumber" opened fd | 228 | // "Renumber" opened fd |
diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c index b3118b433..9ae70de99 100644 --- a/libbb/xreadlink.c +++ b/libbb/xreadlink.c | |||
@@ -122,3 +122,33 @@ char* FAST_FUNC xmalloc_realpath(const char *path) | |||
122 | return xstrdup(realpath(path, buf)); | 122 | return xstrdup(realpath(path, buf)); |
123 | #endif | 123 | #endif |
124 | } | 124 | } |
125 | |||
126 | char* FAST_FUNC xmalloc_realpath_coreutils(const char *path) | ||
127 | { | ||
128 | char *buf; | ||
129 | |||
130 | errno = 0; | ||
131 | buf = xmalloc_realpath(path); | ||
132 | /* | ||
133 | * There is one case when "readlink -f" and | ||
134 | * "realpath" from coreutils succeed, | ||
135 | * even though file does not exist, such as: | ||
136 | * /tmp/file_does_not_exist | ||
137 | * (the directory must exist). | ||
138 | */ | ||
139 | if (!buf && errno == ENOENT) { | ||
140 | char *last_slash = strrchr(path, '/'); | ||
141 | if (last_slash) { | ||
142 | *last_slash++ = '\0'; | ||
143 | buf = xmalloc_realpath(path); | ||
144 | if (buf) { | ||
145 | unsigned len = strlen(buf); | ||
146 | buf = xrealloc(buf, len + strlen(last_slash) + 2); | ||
147 | buf[len++] = '/'; | ||
148 | strcpy(buf + len, last_slash); | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | |||
153 | return buf; | ||
154 | } | ||
diff --git a/loginutils/Config.src b/loginutils/Config.src index 680f42118..cbb09646b 100644 --- a/loginutils/Config.src +++ b/loginutils/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "Login/Password Management Utilities" | 6 | menu "Login/Password Management Utilities" |
diff --git a/mailutils/popmaildir.c b/mailutils/popmaildir.c index a4aad3662..589456715 100644 --- a/mailutils/popmaildir.c +++ b/mailutils/popmaildir.c | |||
@@ -265,7 +265,7 @@ int popmaildir_main(int argc UNUSED_PARAM, char **argv) | |||
265 | 265 | ||
266 | // atomically move message to ./new/ | 266 | // atomically move message to ./new/ |
267 | target = xstrdup(filename); | 267 | target = xstrdup(filename); |
268 | strncpy(target, "new", 3); | 268 | memcpy(target, "new", 3); |
269 | // ... or just stop receiving on failure | 269 | // ... or just stop receiving on failure |
270 | if (rename_or_warn(filename, target)) | 270 | if (rename_or_warn(filename, target)) |
271 | break; | 271 | break; |
diff --git a/mailutils/sendmail.c b/mailutils/sendmail.c index 4ca91fad8..0170f2870 100644 --- a/mailutils/sendmail.c +++ b/mailutils/sendmail.c | |||
@@ -173,7 +173,7 @@ static char *angle_address(char *str) | |||
173 | char *s, *e; | 173 | char *s, *e; |
174 | 174 | ||
175 | e = trim(str); | 175 | e = trim(str); |
176 | if (e != str && e[-1] == '>') { | 176 | if (e != str && *--e == '>') { |
177 | s = strrchr(str, '<'); | 177 | s = strrchr(str, '<'); |
178 | if (s) { | 178 | if (s) { |
179 | *e = '\0'; | 179 | *e = '\0'; |
diff --git a/miscutils/Config.src b/miscutils/Config.src index 7325fb8fa..d10b00b28 100644 --- a/miscutils/Config.src +++ b/miscutils/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "Miscellaneous Utilities" | 6 | menu "Miscellaneous Utilities" |
diff --git a/miscutils/hexedit.c b/miscutils/hexedit.c index 95c930d12..298eb8149 100644 --- a/miscutils/hexedit.c +++ b/miscutils/hexedit.c | |||
@@ -153,7 +153,8 @@ static void redraw(unsigned cursor) | |||
153 | i++; | 153 | i++; |
154 | } | 154 | } |
155 | 155 | ||
156 | printf(ESC"[%u;%uH", 1 + cursor / 16, 1 + pos + (cursor & 0xf) * 3); | 156 | G.row = cursor / 16; |
157 | printf(ESC"[%u;%uH", 1 + G.row, 1 + pos + (cursor & 0xf) * 3); | ||
157 | } | 158 | } |
158 | 159 | ||
159 | static void redraw_cur_line(void) | 160 | static void redraw_cur_line(void) |
@@ -367,6 +368,8 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv) | |||
367 | if (G.current_byte > G.eof_byte) { | 368 | if (G.current_byte > G.eof_byte) { |
368 | /* _after_ eof - don't allow this */ | 369 | /* _after_ eof - don't allow this */ |
369 | G.current_byte -= 16; | 370 | G.current_byte -= 16; |
371 | if (G.current_byte < G.baseaddr) | ||
372 | move_mapping_lower(); | ||
370 | break; | 373 | break; |
371 | } | 374 | } |
372 | } | 375 | } |
diff --git a/modutils/Config.src b/modutils/Config.src index e413702bb..188296814 100644 --- a/modutils/Config.src +++ b/modutils/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "Linux Module Utilities" | 6 | menu "Linux Module Utilities" |
diff --git a/networking/Config.src b/networking/Config.src index 492c60da4..2ce5287de 100644 --- a/networking/Config.src +++ b/networking/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "Networking Utilities" | 6 | menu "Networking Utilities" |
diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c index 64098648a..42c84de45 100644 --- a/networking/nc_bloaty.c +++ b/networking/nc_bloaty.c | |||
@@ -791,7 +791,7 @@ int nc_main(int argc UNUSED_PARAM, char **argv) | |||
791 | "np:s:uvw:+"/* -w N */ IF_NC_SERVER("lk") | 791 | "np:s:uvw:+"/* -w N */ IF_NC_SERVER("lk") |
792 | IF_NC_EXTRA("i:o:z") | 792 | IF_NC_EXTRA("i:o:z") |
793 | "\0" | 793 | "\0" |
794 | "?2:vv:ll", /* max 2 params; -v and -l are counters */ | 794 | "?2:vv"IF_NC_SERVER(":ll"), /* max 2 params; -v and -l are counters */ |
795 | &str_p, &str_s, &o_wait | 795 | &str_p, &str_s, &o_wait |
796 | IF_NC_EXTRA(, &str_i, &str_o) | 796 | IF_NC_EXTRA(, &str_i, &str_o) |
797 | , &o_verbose IF_NC_SERVER(, &cnt_l) | 797 | , &o_verbose IF_NC_SERVER(, &cnt_l) |
diff --git a/networking/nslookup.c b/networking/nslookup.c index fd241a5ca..3a614b0c6 100644 --- a/networking/nslookup.c +++ b/networking/nslookup.c | |||
@@ -712,11 +712,11 @@ static void add_query(int type, const char *dname) | |||
712 | static char *make_ptr(const char *addrstr) | 712 | static char *make_ptr(const char *addrstr) |
713 | { | 713 | { |
714 | unsigned char addr[16]; | 714 | unsigned char addr[16]; |
715 | int i; | ||
716 | 715 | ||
717 | #if ENABLE_FEATURE_IPV6 | 716 | #if ENABLE_FEATURE_IPV6 |
718 | if (inet_pton(AF_INET6, addrstr, addr)) { | 717 | if (inet_pton(AF_INET6, addrstr, addr)) { |
719 | if (memcmp(addr, v4_mapped, 12) != 0) { | 718 | if (memcmp(addr, v4_mapped, 12) != 0) { |
719 | int i; | ||
720 | char resbuf[80]; | 720 | char resbuf[80]; |
721 | char *ptr = resbuf; | 721 | char *ptr = resbuf; |
722 | for (i = 0; i < 16; i++) { | 722 | for (i = 0; i < 16; i++) { |
diff --git a/networking/ntpd.c b/networking/ntpd.c index 6cd497090..7b800369e 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c | |||
@@ -93,10 +93,10 @@ | |||
93 | 93 | ||
94 | #include "libbb.h" | 94 | #include "libbb.h" |
95 | #include <math.h> | 95 | #include <math.h> |
96 | #include <netinet/ip.h> /* For IPTOS_LOWDELAY definition */ | 96 | #include <netinet/ip.h> /* For IPTOS_DSCP_AF21 definition */ |
97 | #include <sys/timex.h> | 97 | #include <sys/timex.h> |
98 | #ifndef IPTOS_LOWDELAY | 98 | #ifndef IPTOS_DSCP_AF21 |
99 | # define IPTOS_LOWDELAY 0x10 | 99 | # define IPTOS_DSCP_AF21 0x48 |
100 | #endif | 100 | #endif |
101 | 101 | ||
102 | 102 | ||
@@ -149,6 +149,7 @@ | |||
149 | */ | 149 | */ |
150 | 150 | ||
151 | #define INITIAL_SAMPLES 4 /* how many samples do we want for init */ | 151 | #define INITIAL_SAMPLES 4 /* how many samples do we want for init */ |
152 | #define MIN_FREQHOLD 10 /* adjust offset, but not freq in this many first adjustments */ | ||
152 | #define BAD_DELAY_GROWTH 4 /* drop packet if its delay grew by more than this */ | 153 | #define BAD_DELAY_GROWTH 4 /* drop packet if its delay grew by more than this */ |
153 | 154 | ||
154 | #define RETRY_INTERVAL 32 /* on send/recv error, retry in N secs (need to be power of 2) */ | 155 | #define RETRY_INTERVAL 32 /* on send/recv error, retry in N secs (need to be power of 2) */ |
@@ -910,7 +911,7 @@ send_query_to_peer(peer_t *p) | |||
910 | #if ENABLE_FEATURE_IPV6 | 911 | #if ENABLE_FEATURE_IPV6 |
911 | if (family == AF_INET) | 912 | if (family == AF_INET) |
912 | #endif | 913 | #endif |
913 | setsockopt_int(fd, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY); | 914 | setsockopt_int(fd, IPPROTO_IP, IP_TOS, IPTOS_DSCP_AF21); |
914 | free(local_lsa); | 915 | free(local_lsa); |
915 | } | 916 | } |
916 | 917 | ||
@@ -1753,7 +1754,7 @@ update_local_clock(peer_t *p) | |||
1753 | //15:19:39.114 update from:<IP> offset:+0.327022 delay:0.158384 jitter:0.108538 clock drift:-1.393ppm tc:4 | 1754 | //15:19:39.114 update from:<IP> offset:+0.327022 delay:0.158384 jitter:0.108538 clock drift:-1.393ppm tc:4 |
1754 | //15:20:12.715 update from:<IP> offset:+0.275596 delay:0.158297 jitter:0.097292 clock drift:-1.393ppm tc:4 | 1755 | //15:20:12.715 update from:<IP> offset:+0.275596 delay:0.158297 jitter:0.097292 clock drift:-1.393ppm tc:4 |
1755 | //15:20:45.111 update from:<IP> offset:+0.225715 delay:0.158271 jitter:0.087841 clock drift:-1.393ppm tc:4 | 1756 | //15:20:45.111 update from:<IP> offset:+0.225715 delay:0.158271 jitter:0.087841 clock drift:-1.393ppm tc:4 |
1756 | // If allwed to continue, it would start increasing tmx.freq now. | 1757 | // If allowed to continue, it would start increasing tmx.freq now. |
1757 | // Instead, it was ^Ced, and started anew: | 1758 | // Instead, it was ^Ced, and started anew: |
1758 | //15:21:15.043 no valid datapoints, no peer selected | 1759 | //15:21:15.043 no valid datapoints, no peer selected |
1759 | //15:21:17.408 update from:<IP> offset:+0.175910 delay:0.158314 jitter:0.076683 clock drift:-1.393ppm tc:4 | 1760 | //15:21:17.408 update from:<IP> offset:+0.175910 delay:0.158314 jitter:0.076683 clock drift:-1.393ppm tc:4 |
@@ -1776,9 +1777,9 @@ update_local_clock(peer_t *p) | |||
1776 | //15:31:53.473 update from:<IP> offset:+0.000007 delay:0.158142 jitter:0.010922 clock drift:+9.343ppm tc:6 | 1777 | //15:31:53.473 update from:<IP> offset:+0.000007 delay:0.158142 jitter:0.010922 clock drift:+9.343ppm tc:6 |
1777 | //15:32:58.902 update from:<IP> offset:-0.000728 delay:0.158222 jitter:0.009454 clock drift:+9.298ppm tc:6 | 1778 | //15:32:58.902 update from:<IP> offset:-0.000728 delay:0.158222 jitter:0.009454 clock drift:+9.298ppm tc:6 |
1778 | /* | 1779 | /* |
1779 | * This expression would choose 15 in the above example. | 1780 | * This expression would choose MIN_FREQHOLD + 7 in the above example. |
1780 | */ | 1781 | */ |
1781 | G.FREQHOLD_cnt = 8 + ((unsigned)(abs(tmx.offset)) >> 16); | 1782 | G.FREQHOLD_cnt = MIN_FREQHOLD + ((unsigned)(abs(tmx.offset)) >> 16); |
1782 | } | 1783 | } |
1783 | G.FREQHOLD_cnt--; | 1784 | G.FREQHOLD_cnt--; |
1784 | tmx.status |= STA_FREQHOLD; | 1785 | tmx.status |= STA_FREQHOLD; |
@@ -2320,7 +2321,7 @@ static NOINLINE void ntp_init(char **argv) | |||
2320 | xfunc_die(); | 2321 | xfunc_die(); |
2321 | } | 2322 | } |
2322 | socket_want_pktinfo(G_listen_fd); | 2323 | socket_want_pktinfo(G_listen_fd); |
2323 | setsockopt_int(G_listen_fd, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY); | 2324 | setsockopt_int(G_listen_fd, IPPROTO_IP, IP_TOS, IPTOS_DSCP_AF21); |
2324 | } | 2325 | } |
2325 | #endif | 2326 | #endif |
2326 | /* I hesitate to set -20 prio. -15 should be high enough for timekeeping */ | 2327 | /* I hesitate to set -20 prio. -15 should be high enough for timekeeping */ |
diff --git a/networking/tls.c b/networking/tls.c index ec5a56d57..fce1d0ea6 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
@@ -1088,6 +1088,8 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) | |||
1088 | * We need Certificate.tbsCertificate.subjectPublicKeyInfo.publicKey | 1088 | * We need Certificate.tbsCertificate.subjectPublicKeyInfo.publicKey |
1089 | */ | 1089 | */ |
1090 | uint8_t *end = der + len; | 1090 | uint8_t *end = der + len; |
1091 | uint8_t tag_class, pc, tag_number; | ||
1092 | int version_present; | ||
1091 | 1093 | ||
1092 | /* enter "Certificate" item: [der, end) will be only Cert */ | 1094 | /* enter "Certificate" item: [der, end) will be only Cert */ |
1093 | der = enter_der_item(der, &end); | 1095 | der = enter_der_item(der, &end); |
@@ -1095,8 +1097,24 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) | |||
1095 | /* enter "tbsCertificate" item: [der, end) will be only tbsCert */ | 1097 | /* enter "tbsCertificate" item: [der, end) will be only tbsCert */ |
1096 | der = enter_der_item(der, &end); | 1098 | der = enter_der_item(der, &end); |
1097 | 1099 | ||
1100 | /* | ||
1101 | * Skip version field only if it is present. For a v1 certificate, the | ||
1102 | * version field won't be present since v1 is the default value for the | ||
1103 | * version field and fields with default values should be omitted (see | ||
1104 | * RFC 5280 sections 4.1 and 4.1.2.1). If the version field is present | ||
1105 | * it will have a tag class of 2 (context-specific), bit 6 as 1 | ||
1106 | * (constructed), and a tag number of 0 (see ITU-T X.690 sections 8.1.2 | ||
1107 | * and 8.14). | ||
1108 | */ | ||
1109 | tag_class = der[0] >> 6; /* bits 8-7 */ | ||
1110 | pc = (der[0] & 32) >> 5; /* bit 6 */ | ||
1111 | tag_number = der[0] & 31; /* bits 5-1 */ | ||
1112 | version_present = tag_class == 2 && pc == 1 && tag_number == 0; | ||
1113 | if (version_present) { | ||
1114 | der = skip_der_item(der, end); /* version */ | ||
1115 | } | ||
1116 | |||
1098 | /* skip up to subjectPublicKeyInfo */ | 1117 | /* skip up to subjectPublicKeyInfo */ |
1099 | der = skip_der_item(der, end); /* version */ | ||
1100 | der = skip_der_item(der, end); /* serialNumber */ | 1118 | der = skip_der_item(der, end); /* serialNumber */ |
1101 | der = skip_der_item(der, end); /* signatureAlgo */ | 1119 | der = skip_der_item(der, end); /* signatureAlgo */ |
1102 | der = skip_der_item(der, end); /* issuer */ | 1120 | der = skip_der_item(der, end); /* issuer */ |
diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src index 50bff2e8c..e5958804b 100644 --- a/networking/udhcp/Config.src +++ b/networking/udhcp/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | config UDHCPD | 6 | config UDHCPD |
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index fbf9c6878..e5fd74f91 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c | |||
@@ -65,6 +65,7 @@ const struct dhcp_optflag dhcp_optflags[] = { | |||
65 | #endif | 65 | #endif |
66 | { OPTION_STRING , 0xd1 }, /* DHCP_PXE_CONF_FILE */ | 66 | { OPTION_STRING , 0xd1 }, /* DHCP_PXE_CONF_FILE */ |
67 | { OPTION_STRING , 0xd2 }, /* DHCP_PXE_PATH_PREFIX */ | 67 | { OPTION_STRING , 0xd2 }, /* DHCP_PXE_PATH_PREFIX */ |
68 | { OPTION_U32 , 0xd3 }, /* DHCP_REBOOT_TIME */ | ||
68 | { OPTION_6RD , 0xd4 }, /* DHCP_6RD */ | 69 | { OPTION_6RD , 0xd4 }, /* DHCP_6RD */ |
69 | { OPTION_STATIC_ROUTES | OPTION_LIST , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ | 70 | { OPTION_STATIC_ROUTES | OPTION_LIST , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ |
70 | { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ | 71 | { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ |
@@ -92,50 +93,51 @@ const struct dhcp_optflag dhcp_optflags[] = { | |||
92 | */ | 93 | */ |
93 | /* Must match dhcp_optflags[] order */ | 94 | /* Must match dhcp_optflags[] order */ |
94 | const char dhcp_option_strings[] ALIGN1 = | 95 | const char dhcp_option_strings[] ALIGN1 = |
95 | "subnet" "\0" /* DHCP_SUBNET */ | 96 | "subnet" "\0" /* DHCP_SUBNET */ |
96 | "timezone" "\0" /* DHCP_TIME_OFFSET */ | 97 | "timezone" "\0" /* DHCP_TIME_OFFSET */ |
97 | "router" "\0" /* DHCP_ROUTER */ | 98 | "router" "\0" /* DHCP_ROUTER */ |
98 | // "timesrv" "\0" /* DHCP_TIME_SERVER */ | 99 | // "timesrv" "\0" /* DHCP_TIME_SERVER */ |
99 | // "namesrv" "\0" /* DHCP_NAME_SERVER */ | 100 | // "namesrv" "\0" /* DHCP_NAME_SERVER */ |
100 | "dns" "\0" /* DHCP_DNS_SERVER */ | 101 | "dns" "\0" /* DHCP_DNS_SERVER */ |
101 | // "logsrv" "\0" /* DHCP_LOG_SERVER */ | 102 | // "logsrv" "\0" /* DHCP_LOG_SERVER */ |
102 | // "cookiesrv" "\0" /* DHCP_COOKIE_SERVER */ | 103 | // "cookiesrv" "\0" /* DHCP_COOKIE_SERVER */ |
103 | "lprsrv" "\0" /* DHCP_LPR_SERVER */ | 104 | "lprsrv" "\0" /* DHCP_LPR_SERVER */ |
104 | "hostname" "\0" /* DHCP_HOST_NAME */ | 105 | "hostname" "\0" /* DHCP_HOST_NAME */ |
105 | "bootsize" "\0" /* DHCP_BOOT_SIZE */ | 106 | "bootsize" "\0" /* DHCP_BOOT_SIZE */ |
106 | "domain" "\0" /* DHCP_DOMAIN_NAME */ | 107 | "domain" "\0" /* DHCP_DOMAIN_NAME */ |
107 | "swapsrv" "\0" /* DHCP_SWAP_SERVER */ | 108 | "swapsrv" "\0" /* DHCP_SWAP_SERVER */ |
108 | "rootpath" "\0" /* DHCP_ROOT_PATH */ | 109 | "rootpath" "\0" /* DHCP_ROOT_PATH */ |
109 | "ipttl" "\0" /* DHCP_IP_TTL */ | 110 | "ipttl" "\0" /* DHCP_IP_TTL */ |
110 | "mtu" "\0" /* DHCP_MTU */ | 111 | "mtu" "\0" /* DHCP_MTU */ |
111 | "broadcast" "\0" /* DHCP_BROADCAST */ | 112 | "broadcast" "\0" /* DHCP_BROADCAST */ |
112 | "routes" "\0" /* DHCP_ROUTES */ | 113 | "routes" "\0" /* DHCP_ROUTES */ |
113 | "nisdomain" "\0" /* DHCP_NIS_DOMAIN */ | 114 | "nisdomain" "\0" /* DHCP_NIS_DOMAIN */ |
114 | "nissrv" "\0" /* DHCP_NIS_SERVER */ | 115 | "nissrv" "\0" /* DHCP_NIS_SERVER */ |
115 | "ntpsrv" "\0" /* DHCP_NTP_SERVER */ | 116 | "ntpsrv" "\0" /* DHCP_NTP_SERVER */ |
116 | "wins" "\0" /* DHCP_WINS_SERVER */ | 117 | "wins" "\0" /* DHCP_WINS_SERVER */ |
117 | "lease" "\0" /* DHCP_LEASE_TIME */ | 118 | "lease" "\0" /* DHCP_LEASE_TIME */ |
118 | "serverid" "\0" /* DHCP_SERVER_ID */ | 119 | "serverid" "\0" /* DHCP_SERVER_ID */ |
119 | "message" "\0" /* DHCP_ERR_MESSAGE */ | 120 | "message" "\0" /* DHCP_ERR_MESSAGE */ |
120 | "tftp" "\0" /* DHCP_TFTP_SERVER_NAME */ | 121 | "tftp" "\0" /* DHCP_TFTP_SERVER_NAME*/ |
121 | "bootfile" "\0" /* DHCP_BOOT_FILE */ | 122 | "bootfile" "\0" /* DHCP_BOOT_FILE */ |
122 | // "userclass" "\0" /* DHCP_USER_CLASS */ | 123 | // "userclass" "\0" /* DHCP_USER_CLASS */ |
123 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 124 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
124 | "search" "\0" /* DHCP_DOMAIN_SEARCH */ | 125 | "search" "\0" /* DHCP_DOMAIN_SEARCH */ |
125 | // doesn't work in udhcpd.conf since OPTION_SIP_SERVERS | 126 | // doesn't work in udhcpd.conf since OPTION_SIP_SERVERS |
126 | // is not handled yet by "string->option" conversion code: | 127 | // is not handled yet by "string->option" conversion code: |
127 | "sipsrv" "\0" /* DHCP_SIP_SERVERS */ | 128 | "sipsrv" "\0" /* DHCP_SIP_SERVERS */ |
128 | #endif | 129 | #endif |
129 | "staticroutes" "\0"/* DHCP_STATIC_ROUTES */ | 130 | "staticroutes" "\0" /* DHCP_STATIC_ROUTES */ |
130 | #if ENABLE_FEATURE_UDHCP_8021Q | 131 | #if ENABLE_FEATURE_UDHCP_8021Q |
131 | "vlanid" "\0" /* DHCP_VLAN_ID */ | 132 | "vlanid" "\0" /* DHCP_VLAN_ID */ |
132 | "vlanpriority" "\0"/* DHCP_VLAN_PRIORITY */ | 133 | "vlanpriority" "\0" /* DHCP_VLAN_PRIORITY */ |
133 | #endif | 134 | #endif |
134 | "pxeconffile" "\0" /* DHCP_PXE_CONF_FILE */ | 135 | "pxeconffile" "\0" /* DHCP_PXE_CONF_FILE */ |
135 | "pxepathprefix" "\0" /* DHCP_PXE_PATH_PREFIX */ | 136 | "pxepathprefix" "\0" /* DHCP_PXE_PATH_PREFIX */ |
136 | "ip6rd" "\0" /* DHCP_6RD */ | 137 | "reboottime" "\0" /* DHCP_REBOOT_TIME */ |
137 | "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */ | 138 | "ip6rd" "\0" /* DHCP_6RD */ |
138 | "wpad" "\0" /* DHCP_WPAD */ | 139 | "msstaticroutes" "\0" /* DHCP_MS_STATIC_ROUTES*/ |
140 | "wpad" "\0" /* DHCP_WPAD */ | ||
139 | ; | 141 | ; |
140 | #endif | 142 | #endif |
141 | 143 | ||
@@ -379,12 +381,18 @@ int FAST_FUNC udhcp_str2nip(const char *str, void *arg) | |||
379 | * and to parse udhcpd.conf's "opt OPTNAME OPTVAL" directives. | 381 | * and to parse udhcpd.conf's "opt OPTNAME OPTVAL" directives. |
380 | */ | 382 | */ |
381 | /* helper: add an option to the opt_list */ | 383 | /* helper: add an option to the opt_list */ |
384 | #if !ENABLE_UDHCPC6 | ||
385 | #define attach_option(opt_list, optflag, buffer, length, dhcpv6) \ | ||
386 | attach_option(opt_list, optflag, buffer, length) | ||
387 | #endif | ||
382 | static NOINLINE void attach_option( | 388 | static NOINLINE void attach_option( |
383 | struct option_set **opt_list, | 389 | struct option_set **opt_list, |
384 | const struct dhcp_optflag *optflag, | 390 | const struct dhcp_optflag *optflag, |
385 | char *buffer, | 391 | char *buffer, |
386 | int length) | 392 | int length, |
393 | bool dhcpv6) | ||
387 | { | 394 | { |
395 | IF_NOT_UDHCPC6(bool dhcpv6 = 0;) | ||
388 | struct option_set *existing; | 396 | struct option_set *existing; |
389 | char *allocated = NULL; | 397 | char *allocated = NULL; |
390 | 398 | ||
@@ -410,10 +418,21 @@ static NOINLINE void attach_option( | |||
410 | /* make a new option */ | 418 | /* make a new option */ |
411 | log2("attaching option %02x to list", optflag->code); | 419 | log2("attaching option %02x to list", optflag->code); |
412 | new = xmalloc(sizeof(*new)); | 420 | new = xmalloc(sizeof(*new)); |
413 | new->data = xmalloc(length + OPT_DATA); | 421 | if (!dhcpv6) { |
414 | new->data[OPT_CODE] = optflag->code; | 422 | new->data = xmalloc(length + OPT_DATA); |
415 | new->data[OPT_LEN] = length; | 423 | new->data[OPT_CODE] = optflag->code; |
416 | memcpy(new->data + OPT_DATA, (allocated ? allocated : buffer), length); | 424 | new->data[OPT_LEN] = length; |
425 | memcpy(new->data + OPT_DATA, (allocated ? allocated : buffer), | ||
426 | length); | ||
427 | } else { | ||
428 | new->data = xmalloc(length + D6_OPT_DATA); | ||
429 | new->data[D6_OPT_CODE] = optflag->code >> 8; | ||
430 | new->data[D6_OPT_CODE + 1] = optflag->code & 0xff; | ||
431 | new->data[D6_OPT_LEN] = length >> 8; | ||
432 | new->data[D6_OPT_LEN + 1] = length & 0xff; | ||
433 | memcpy(new->data + D6_OPT_DATA, (allocated ? allocated : buffer), | ||
434 | length); | ||
435 | } | ||
417 | 436 | ||
418 | curr = opt_list; | 437 | curr = opt_list; |
419 | while (*curr && (*curr)->data[OPT_CODE] < optflag->code) | 438 | while (*curr && (*curr)->data[OPT_CODE] < optflag->code) |
@@ -450,7 +469,9 @@ static NOINLINE void attach_option( | |||
450 | free(allocated); | 469 | free(allocated); |
451 | } | 470 | } |
452 | 471 | ||
453 | int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, const struct dhcp_optflag *optflags, const char *option_strings) | 472 | int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, |
473 | const struct dhcp_optflag *optflags, const char *option_strings, | ||
474 | bool dhcpv6) | ||
454 | { | 475 | { |
455 | struct option_set **opt_list = arg; | 476 | struct option_set **opt_list = arg; |
456 | char *opt; | 477 | char *opt; |
@@ -489,9 +510,10 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, const struct dh | |||
489 | int length; | 510 | int length; |
490 | char *val; | 511 | char *val; |
491 | 512 | ||
492 | if (optflag->flags == OPTION_BIN) | 513 | if (optflag->flags == OPTION_BIN) { |
493 | val = trim(strtok(NULL, "")); /* do not split "'q w e'" */ | 514 | val = strtok(NULL, ""); /* do not split "'q w e'" */ |
494 | else | 515 | trim(val); |
516 | } else | ||
495 | val = strtok(NULL, ", \t"); | 517 | val = strtok(NULL, ", \t"); |
496 | if (!val) | 518 | if (!val) |
497 | break; | 519 | break; |
@@ -601,7 +623,7 @@ case_OPTION_STRING: | |||
601 | } | 623 | } |
602 | 624 | ||
603 | if (retval) | 625 | if (retval) |
604 | attach_option(opt_list, optflag, opt, length); | 626 | attach_option(opt_list, optflag, opt, length, dhcpv6); |
605 | } while (retval && (optflag->flags & OPTION_LIST)); | 627 | } while (retval && (optflag->flags & OPTION_LIST)); |
606 | 628 | ||
607 | return retval; | 629 | return retval; |
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 13059f106..7ad603d33 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
@@ -122,9 +122,9 @@ enum { | |||
122 | //#define DHCP_LOG_SERVER 0x07 /* port 704 UDP log (not syslog) | 122 | //#define DHCP_LOG_SERVER 0x07 /* port 704 UDP log (not syslog) |
123 | //#define DHCP_COOKIE_SERVER 0x08 /* "quote of the day" server */ | 123 | //#define DHCP_COOKIE_SERVER 0x08 /* "quote of the day" server */ |
124 | //#define DHCP_LPR_SERVER 0x09 | 124 | //#define DHCP_LPR_SERVER 0x09 |
125 | #define DHCP_HOST_NAME 0x0c /* either client informs server or server gives name to client */ | 125 | #define DHCP_HOST_NAME 0x0c /* 12: either client informs server or server gives name to client */ |
126 | //#define DHCP_BOOT_SIZE 0x0d | 126 | //#define DHCP_BOOT_SIZE 0x0d |
127 | //#define DHCP_DOMAIN_NAME 0x0f /* server gives domain suffix */ | 127 | //#define DHCP_DOMAIN_NAME 0x0f /* 15: server gives domain suffix */ |
128 | //#define DHCP_SWAP_SERVER 0x10 | 128 | //#define DHCP_SWAP_SERVER 0x10 |
129 | //#define DHCP_ROOT_PATH 0x11 | 129 | //#define DHCP_ROOT_PATH 0x11 |
130 | //#define DHCP_IP_TTL 0x17 | 130 | //#define DHCP_IP_TTL 0x17 |
@@ -135,35 +135,40 @@ enum { | |||
135 | //#define DHCP_NIS_SERVER 0x29 | 135 | //#define DHCP_NIS_SERVER 0x29 |
136 | //#define DHCP_NTP_SERVER 0x2a | 136 | //#define DHCP_NTP_SERVER 0x2a |
137 | //#define DHCP_WINS_SERVER 0x2c | 137 | //#define DHCP_WINS_SERVER 0x2c |
138 | #define DHCP_REQUESTED_IP 0x32 /* sent by client if specific IP is wanted */ | 138 | #define DHCP_REQUESTED_IP 0x32 /* 50: sent by client if specific IP is wanted */ |
139 | #define DHCP_LEASE_TIME 0x33 | 139 | #define DHCP_LEASE_TIME 0x33 /* 51: */ |
140 | #define DHCP_OPTION_OVERLOAD 0x34 | 140 | #define DHCP_OPTION_OVERLOAD 0x34 /* 52: */ |
141 | #define DHCP_MESSAGE_TYPE 0x35 | 141 | #define DHCP_MESSAGE_TYPE 0x35 /* 53: */ |
142 | #define DHCP_SERVER_ID 0x36 /* by default server's IP */ | 142 | #define DHCP_SERVER_ID 0x36 /* 54: server's IP */ |
143 | #define DHCP_PARAM_REQ 0x37 /* list of options client wants */ | 143 | #define DHCP_PARAM_REQ 0x37 /* 55: list of options client wants */ |
144 | //#define DHCP_ERR_MESSAGE 0x38 /* error message when sending NAK etc */ | 144 | //#define DHCP_ERR_MESSAGE 0x38 /* 56: error message when sending NAK etc */ |
145 | #define DHCP_MAX_SIZE 0x39 | 145 | #define DHCP_MAX_SIZE 0x39 /* 57: */ |
146 | #define DHCP_VENDOR 0x3c /* client's vendor (a string) */ | 146 | #define DHCP_VENDOR 0x3c /* 60: client's vendor (a string) */ |
147 | #define DHCP_CLIENT_ID 0x3d /* by default client's MAC addr, but may be arbitrarily long */ | 147 | #define DHCP_CLIENT_ID 0x3d /* 61: by default client's MAC addr, but may be arbitrarily long */ |
148 | //#define DHCP_TFTP_SERVER_NAME 0x42 /* same as 'sname' field */ | 148 | //#define DHCP_TFTP_SERVER_NAME 0x42 /* 66: same as 'sname' field */ |
149 | //#define DHCP_BOOT_FILE 0x43 /* same as 'file' field */ | 149 | //#define DHCP_BOOT_FILE 0x43 /* 67: same as 'file' field */ |
150 | //#define DHCP_USER_CLASS 0x4d /* RFC 3004. set of LASCII strings. "I am a printer" etc */ | 150 | //#define DHCP_USER_CLASS 0x4d /* 77: RFC 3004. set of LASCII strings. "I am a printer" etc */ |
151 | #define DHCP_FQDN 0x51 /* client asks to update DNS to map its FQDN to its new IP */ | 151 | #define DHCP_FQDN 0x51 /* 81: client asks to update DNS to map its FQDN to its new IP */ |
152 | //#define DHCP_DOMAIN_SEARCH 0x77 /* RFC 3397. set of ASCIZ string, DNS-style compressed */ | 152 | //#define DHCP_DOMAIN_SEARCH 0x77 /* 119: RFC 3397. set of ASCIZ string, DNS-style compressed */ |
153 | //#define DHCP_SIP_SERVERS 0x78 /* RFC 3361. flag byte, then: 0: domain names, 1: IP addrs */ | 153 | //#define DHCP_SIP_SERVERS 0x78 /* 120: RFC 3361. flag byte, then: 0: domain names, 1: IP addrs */ |
154 | //#define DHCP_STATIC_ROUTES 0x79 /* RFC 3442. (mask,ip,router) tuples */ | 154 | //#define DHCP_STATIC_ROUTES 0x79 /* 121: RFC 3442. (mask,ip,router) tuples */ |
155 | //#define DHCP_VLAN_ID 0x84 /* 802.1P VLAN ID */ | 155 | //#define DHCP_VLAN_ID 0x84 /* 132: 802.1P VLAN ID */ |
156 | //#define DHCP_VLAN_PRIORITY 0x85 /* 802.1Q VLAN priority */ | 156 | //#define DHCP_VLAN_PRIORITY 0x85 /* 133: 802.1Q VLAN priority */ |
157 | //#define DHCP_PXE_CONF_FILE 0xd1 /* RFC 5071 Configuration File */ | 157 | //#define DHCP_PXE_CONF_FILE 0xd1 /* 209: RFC 5071 Configuration File */ |
158 | //#define DHCP_PXE_PATH_PREFIX 0xd2 /* RFC 5071 Configuration File */ | 158 | //#define DHCP_PXE_PATH_PREFIX 0xd2 /* 210: RFC 5071 Configuration File */ |
159 | //#define DHCP_MS_STATIC_ROUTES 0xf9 /* Microsoft's pre-RFC 3442 code for 0x79? */ | 159 | //#define DHCP_REBOOT_TIME 0xd3 /* 211: RFC 5071 Reboot time */ |
160 | //#define DHCP_WPAD 0xfc /* MSIE's Web Proxy Autodiscovery Protocol */ | 160 | //#define DHCP_MS_STATIC_ROUTES 0xf9 /* 249: Microsoft's pre-RFC 3442 code for 0x79? */ |
161 | #define DHCP_END 0xff | 161 | //#define DHCP_WPAD 0xfc /* 252: MSIE's Web Proxy Autodiscovery Protocol */ |
162 | #define DHCP_END 0xff /* 255: */ | ||
162 | 163 | ||
163 | /* Offsets in option byte sequence */ | 164 | /* Offsets in option byte sequence */ |
164 | #define OPT_CODE 0 | 165 | #define OPT_CODE 0 |
165 | #define OPT_LEN 1 | 166 | #define OPT_LEN 1 |
166 | #define OPT_DATA 2 | 167 | #define OPT_DATA 2 |
168 | /* Offsets in option byte sequence for DHCPv6 */ | ||
169 | #define D6_OPT_CODE 0 | ||
170 | #define D6_OPT_LEN 2 | ||
171 | #define D6_OPT_DATA 4 | ||
167 | /* Bits in "overload" option */ | 172 | /* Bits in "overload" option */ |
168 | #define OPTION_FIELD 0 | 173 | #define OPTION_FIELD 0 |
169 | #define FILE_FIELD 1 | 174 | #define FILE_FIELD 1 |
@@ -290,10 +295,15 @@ void udhcp_dump_packet(struct dhcp_packet *packet) FAST_FUNC; | |||
290 | /* 2nd param is "uint32_t*" */ | 295 | /* 2nd param is "uint32_t*" */ |
291 | int FAST_FUNC udhcp_str2nip(const char *str, void *arg); | 296 | int FAST_FUNC udhcp_str2nip(const char *str, void *arg); |
292 | /* 2nd param is "struct option_set**" */ | 297 | /* 2nd param is "struct option_set**" */ |
298 | #if !ENABLE_UDHCPC6 | ||
299 | #define udhcp_str2optset(str, arg, optflags, option_strings, dhcpv6) \ | ||
300 | udhcp_str2optset(str, arg, optflags, option_strings) | ||
301 | #endif | ||
293 | int FAST_FUNC udhcp_str2optset(const char *str, | 302 | int FAST_FUNC udhcp_str2optset(const char *str, |
294 | void *arg, | 303 | void *arg, |
295 | const struct dhcp_optflag *optflags, | 304 | const struct dhcp_optflag *optflags, |
296 | const char *option_strings); | 305 | const char *option_strings, |
306 | bool dhcpv6); | ||
297 | 307 | ||
298 | #if ENABLE_UDHCPC || ENABLE_UDHCPD | 308 | #if ENABLE_UDHCPC || ENABLE_UDHCPD |
299 | void udhcp_init_header(struct dhcp_packet *packet, char type) FAST_FUNC; | 309 | void udhcp_init_header(struct dhcp_packet *packet, char type) FAST_FUNC; |
@@ -308,9 +318,7 @@ int udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, | |||
308 | 318 | ||
309 | int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, | 319 | int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, |
310 | uint32_t source_nip, int source_port, | 320 | uint32_t source_nip, int source_port, |
311 | uint32_t dest_nip, int dest_port, | 321 | uint32_t dest_nip, int dest_port) FAST_FUNC; |
312 | int send_flags | ||
313 | ) FAST_FUNC; | ||
314 | 322 | ||
315 | void udhcp_sp_setup(void) FAST_FUNC; | 323 | void udhcp_sp_setup(void) FAST_FUNC; |
316 | void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; | 324 | void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; |
diff --git a/networking/udhcp/d6_common.h b/networking/udhcp/d6_common.h index e9c0397ae..d0506e2bb 100644 --- a/networking/udhcp/d6_common.h +++ b/networking/udhcp/d6_common.h | |||
@@ -128,6 +128,9 @@ struct d6_option { | |||
128 | #define D6_OPT_TZ_POSIX 41 | 128 | #define D6_OPT_TZ_POSIX 41 |
129 | #define D6_OPT_TZ_NAME 42 | 129 | #define D6_OPT_TZ_NAME 42 |
130 | 130 | ||
131 | #define D6_OPT_BOOT_URL 59 | ||
132 | #define D6_OPT_BOOT_PARAM 60 | ||
133 | |||
131 | /*** Other shared functions ***/ | 134 | /*** Other shared functions ***/ |
132 | 135 | ||
133 | struct client6_data_t { | 136 | struct client6_data_t { |
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 85d9da724..ed2255ef3 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c | |||
@@ -38,6 +38,14 @@ | |||
38 | //config: help | 38 | //config: help |
39 | //config: You can request POSIX timezone with "-O tz" and timezone name | 39 | //config: You can request POSIX timezone with "-O tz" and timezone name |
40 | //config: with "-O timezone". | 40 | //config: with "-O timezone". |
41 | //config: | ||
42 | //config:config FEATURE_UDHCPC6_RFC5970 | ||
43 | //config: bool "Support RFC 5970 (Network Boot)" | ||
44 | //config: default y | ||
45 | //config: depends on UDHCPC6 | ||
46 | //config: help | ||
47 | //config: You can request bootfile-url with "-O bootfile_url" and | ||
48 | //config: bootfile-params with "-O bootfile_params". | ||
41 | 49 | ||
42 | //applet:IF_UDHCPC6(APPLET(udhcpc6, BB_DIR_USR_BIN, BB_SUID_DROP)) | 50 | //applet:IF_UDHCPC6(APPLET(udhcpc6, BB_DIR_USR_BIN, BB_SUID_DROP)) |
43 | 51 | ||
@@ -71,6 +79,12 @@ static const struct dhcp_optflag d6_optflags[] = { | |||
71 | { OPTION_STRING, D6_OPT_TZ_POSIX }, | 79 | { OPTION_STRING, D6_OPT_TZ_POSIX }, |
72 | { OPTION_STRING, D6_OPT_TZ_NAME }, | 80 | { OPTION_STRING, D6_OPT_TZ_NAME }, |
73 | #endif | 81 | #endif |
82 | #if ENABLE_FEATURE_UDHCPC6_RFC5970 | ||
83 | { OPTION_STRING, D6_OPT_BOOT_URL }, | ||
84 | { OPTION_STRING, D6_OPT_BOOT_PARAM }, | ||
85 | #endif | ||
86 | { OPTION_STRING, 0xd1 }, /* DHCP_PXE_CONF_FILE */ | ||
87 | { OPTION_STRING, 0xd2 }, /* DHCP_PXE_PATH_PREFIX */ | ||
74 | { 0, 0 } | 88 | { 0, 0 } |
75 | }; | 89 | }; |
76 | /* Must match d6_optflags[] order */ | 90 | /* Must match d6_optflags[] order */ |
@@ -86,6 +100,12 @@ static const char d6_option_strings[] ALIGN1 = | |||
86 | "tz" "\0" /* D6_OPT_TZ_POSIX */ | 100 | "tz" "\0" /* D6_OPT_TZ_POSIX */ |
87 | "timezone" "\0" /* D6_OPT_TZ_NAME */ | 101 | "timezone" "\0" /* D6_OPT_TZ_NAME */ |
88 | #endif | 102 | #endif |
103 | #if ENABLE_FEATURE_UDHCPC6_RFC5970 | ||
104 | "bootfile_url" "\0" /* D6_OPT_BOOT_URL */ | ||
105 | "bootfile_param" "\0" /* D6_OPT_BOOT_PARAM */ | ||
106 | #endif | ||
107 | "pxeconffile" "\0" /* DHCP_PXE_CONF_FILE */ | ||
108 | "pxepathprefix" "\0" /* DHCP_PXE_PATH_PREFIX */ | ||
89 | "\0"; | 109 | "\0"; |
90 | 110 | ||
91 | #if ENABLE_LONG_OPTS | 111 | #if ENABLE_LONG_OPTS |
@@ -195,8 +215,37 @@ static char** new_env(void) | |||
195 | return &client6_data.env_ptr[client6_data.env_idx++]; | 215 | return &client6_data.env_ptr[client6_data.env_idx++]; |
196 | } | 216 | } |
197 | 217 | ||
218 | static char *string_option_to_env(const uint8_t *option, | ||
219 | const uint8_t *option_end) | ||
220 | { | ||
221 | const char *ptr, *name = NULL; | ||
222 | unsigned val_len; | ||
223 | int i; | ||
224 | |||
225 | ptr = d6_option_strings; | ||
226 | i = 0; | ||
227 | while (*ptr) { | ||
228 | if (d6_optflags[i].code == option[1]) { | ||
229 | name = ptr; | ||
230 | goto found; | ||
231 | } | ||
232 | ptr += strlen(ptr) + 1; | ||
233 | i++; | ||
234 | } | ||
235 | bb_error_msg("can't find option name for 0x%x, skipping", option[1]); | ||
236 | return NULL; | ||
237 | |||
238 | found: | ||
239 | val_len = (option[2] << 8) | option[3]; | ||
240 | if (val_len + &option[D6_OPT_DATA] > option_end) { | ||
241 | bb_error_msg("option data exceeds option length"); | ||
242 | return NULL; | ||
243 | } | ||
244 | return xasprintf("%s=%.*s", name, val_len, (char*)option + 4); | ||
245 | } | ||
246 | |||
198 | /* put all the parameters into the environment */ | 247 | /* put all the parameters into the environment */ |
199 | static void option_to_env(uint8_t *option, uint8_t *option_end) | 248 | static void option_to_env(const uint8_t *option, const uint8_t *option_end) |
200 | { | 249 | { |
201 | #if ENABLE_FEATURE_UDHCPC6_RFC3646 | 250 | #if ENABLE_FEATURE_UDHCPC6_RFC3646 |
202 | int addrs, option_offset; | 251 | int addrs, option_offset; |
@@ -239,6 +288,10 @@ static void option_to_env(uint8_t *option, uint8_t *option_end) | |||
239 | * | valid-lifetime | | 288 | * | valid-lifetime | |
240 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 289 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
241 | */ | 290 | */ |
291 | /* Make sure payload contains an address */ | ||
292 | if (option[3] < 24) | ||
293 | break; | ||
294 | |||
242 | sprint_nip6(ipv6str, option + 4); | 295 | sprint_nip6(ipv6str, option + 4); |
243 | *new_env() = xasprintf("ipv6=%s", ipv6str); | 296 | *new_env() = xasprintf("ipv6=%s", ipv6str); |
244 | 297 | ||
@@ -354,13 +407,23 @@ static void option_to_env(uint8_t *option, uint8_t *option_end) | |||
354 | *new_env() = xasprintf("tz_name=%.*s", (int)option[3], (char*)option + 4); | 407 | *new_env() = xasprintf("tz_name=%.*s", (int)option[3], (char*)option + 4); |
355 | break; | 408 | break; |
356 | #endif | 409 | #endif |
410 | case D6_OPT_BOOT_URL: | ||
411 | case D6_OPT_BOOT_PARAM: | ||
412 | case 0xd1: /* DHCP_PXE_CONF_FILE */ | ||
413 | case 0xd2: /* DHCP_PXE_PATH_PREFIX */ | ||
414 | { | ||
415 | char *tmp = string_option_to_env(option, option_end); | ||
416 | if (tmp) | ||
417 | *new_env() = tmp; | ||
418 | break; | ||
419 | } | ||
357 | } | 420 | } |
358 | len_m4 -= 4 + option[3]; | 421 | len_m4 -= 4 + option[3]; |
359 | option += 4 + option[3]; | 422 | option += 4 + option[3]; |
360 | } | 423 | } |
361 | } | 424 | } |
362 | 425 | ||
363 | static char **fill_envp(struct d6_packet *packet) | 426 | static char **fill_envp(const uint8_t *option, const uint8_t *option_end) |
364 | { | 427 | { |
365 | char **envp, **curr; | 428 | char **envp, **curr; |
366 | 429 | ||
@@ -369,8 +432,8 @@ static char **fill_envp(struct d6_packet *packet) | |||
369 | 432 | ||
370 | *new_env() = xasprintf("interface=%s", client_config.interface); | 433 | *new_env() = xasprintf("interface=%s", client_config.interface); |
371 | 434 | ||
372 | if (packet) | 435 | if (option) |
373 | option_to_env(packet->d6_options, packet->d6_options + sizeof(packet->d6_options)); | 436 | option_to_env(option, option_end); |
374 | 437 | ||
375 | envp = curr = client6_data.env_ptr; | 438 | envp = curr = client6_data.env_ptr; |
376 | while (*curr) | 439 | while (*curr) |
@@ -380,12 +443,13 @@ static char **fill_envp(struct d6_packet *packet) | |||
380 | } | 443 | } |
381 | 444 | ||
382 | /* Call a script with a par file and env vars */ | 445 | /* Call a script with a par file and env vars */ |
383 | static void d6_run_script(struct d6_packet *packet, const char *name) | 446 | static void d6_run_script(const uint8_t *option, const uint8_t *option_end, |
447 | const char *name) | ||
384 | { | 448 | { |
385 | char **envp, **curr; | 449 | char **envp, **curr; |
386 | char *argv[3]; | 450 | char *argv[3]; |
387 | 451 | ||
388 | envp = fill_envp(packet); | 452 | envp = fill_envp(option, option_end); |
389 | 453 | ||
390 | /* call script */ | 454 | /* call script */ |
391 | log1("executing %s %s", client_config.script, name); | 455 | log1("executing %s %s", client_config.script, name); |
@@ -401,6 +465,11 @@ static void d6_run_script(struct d6_packet *packet, const char *name) | |||
401 | free(envp); | 465 | free(envp); |
402 | } | 466 | } |
403 | 467 | ||
468 | /* Call a script with a par file and no env var */ | ||
469 | static void d6_run_script_no_option(const char *name) | ||
470 | { | ||
471 | d6_run_script(NULL, NULL, name); | ||
472 | } | ||
404 | 473 | ||
405 | /*** Sending/receiving packets ***/ | 474 | /*** Sending/receiving packets ***/ |
406 | 475 | ||
@@ -426,8 +495,10 @@ static uint8_t *init_d6_packet(struct d6_packet *packet, char type, uint32_t xid | |||
426 | 495 | ||
427 | static uint8_t *add_d6_client_options(uint8_t *ptr) | 496 | static uint8_t *add_d6_client_options(uint8_t *ptr) |
428 | { | 497 | { |
498 | struct option_set *curr; | ||
429 | uint8_t *start = ptr; | 499 | uint8_t *start = ptr; |
430 | unsigned option; | 500 | unsigned option; |
501 | uint16_t len; | ||
431 | 502 | ||
432 | ptr += 4; | 503 | ptr += 4; |
433 | for (option = 1; option < 256; option++) { | 504 | for (option = 1; option < 256; option++) { |
@@ -450,7 +521,12 @@ static uint8_t *add_d6_client_options(uint8_t *ptr) | |||
450 | ptr = mempcpy(ptr, &opt_fqdn_req, sizeof(opt_fqdn_req)); | 521 | ptr = mempcpy(ptr, &opt_fqdn_req, sizeof(opt_fqdn_req)); |
451 | #endif | 522 | #endif |
452 | /* Add -x options if any */ | 523 | /* Add -x options if any */ |
453 | //... | 524 | curr = client_config.options; |
525 | while (curr) { | ||
526 | len = (curr->data[D6_OPT_LEN] << 8) | curr->data[D6_OPT_LEN + 1]; | ||
527 | ptr = mempcpy(ptr, curr->data, D6_OPT_DATA + len); | ||
528 | curr = curr->next; | ||
529 | } | ||
454 | 530 | ||
455 | return ptr; | 531 | return ptr; |
456 | } | 532 | } |
@@ -727,15 +803,13 @@ static NOINLINE int send_d6_renew(uint32_t xid, struct in6_addr *server_ipv6, st | |||
727 | opt_ptr = add_d6_client_options(opt_ptr); | 803 | opt_ptr = add_d6_client_options(opt_ptr); |
728 | 804 | ||
729 | bb_error_msg("sending %s", "renew"); | 805 | bb_error_msg("sending %s", "renew"); |
730 | if (server_ipv6) { | 806 | if (server_ipv6) |
731 | return d6_send_kernel_packet( | 807 | return d6_send_kernel_packet( |
732 | &packet, (opt_ptr - (uint8_t*) &packet), | 808 | &packet, (opt_ptr - (uint8_t*) &packet), |
733 | our_cur_ipv6, CLIENT_PORT6, | 809 | our_cur_ipv6, CLIENT_PORT6, |
734 | server_ipv6, SERVER_PORT6, | 810 | server_ipv6, SERVER_PORT6, |
735 | client_config.ifindex | 811 | client_config.ifindex |
736 | /* TODO? send_flags: MSG_DONTROUTE (see IPv4 code for reason why) */ | ||
737 | ); | 812 | ); |
738 | } | ||
739 | return d6_mcast_from_client_config_ifindex(&packet, opt_ptr); | 813 | return d6_mcast_from_client_config_ifindex(&packet, opt_ptr); |
740 | } | 814 | } |
741 | 815 | ||
@@ -969,7 +1043,7 @@ static void perform_renew(void) | |||
969 | state = RENEW_REQUESTED; | 1043 | state = RENEW_REQUESTED; |
970 | break; | 1044 | break; |
971 | case RENEW_REQUESTED: /* impatient are we? fine, square 1 */ | 1045 | case RENEW_REQUESTED: /* impatient are we? fine, square 1 */ |
972 | d6_run_script(NULL, "deconfig"); | 1046 | d6_run_script_no_option("deconfig"); |
973 | case REQUESTING: | 1047 | case REQUESTING: |
974 | case RELEASED: | 1048 | case RELEASED: |
975 | change_listen_mode(LISTEN_RAW); | 1049 | change_listen_mode(LISTEN_RAW); |
@@ -998,7 +1072,7 @@ static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *ou | |||
998 | * Users requested to be notified in all cases, even if not in one | 1072 | * Users requested to be notified in all cases, even if not in one |
999 | * of the states above. | 1073 | * of the states above. |
1000 | */ | 1074 | */ |
1001 | d6_run_script(NULL, "deconfig"); | 1075 | d6_run_script_no_option("deconfig"); |
1002 | change_listen_mode(LISTEN_NONE); | 1076 | change_listen_mode(LISTEN_NONE); |
1003 | state = RELEASED; | 1077 | state = RELEASED; |
1004 | } | 1078 | } |
@@ -1157,7 +1231,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1157 | } | 1231 | } |
1158 | while (list_x) { | 1232 | while (list_x) { |
1159 | char *optstr = xstrdup(llist_pop(&list_x)); | 1233 | char *optstr = xstrdup(llist_pop(&list_x)); |
1160 | udhcp_str2optset(optstr, &client_config.options, d6_optflags, d6_option_strings); | 1234 | udhcp_str2optset(optstr, &client_config.options, |
1235 | d6_optflags, d6_option_strings, | ||
1236 | /*dhcpv6:*/ 1 | ||
1237 | ); | ||
1161 | free(optstr); | 1238 | free(optstr); |
1162 | } | 1239 | } |
1163 | 1240 | ||
@@ -1204,7 +1281,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1204 | udhcp_sp_setup(); | 1281 | udhcp_sp_setup(); |
1205 | 1282 | ||
1206 | state = INIT_SELECTING; | 1283 | state = INIT_SELECTING; |
1207 | d6_run_script(NULL, "deconfig"); | 1284 | d6_run_script_no_option("deconfig"); |
1208 | change_listen_mode(LISTEN_RAW); | 1285 | change_listen_mode(LISTEN_RAW); |
1209 | packet_num = 0; | 1286 | packet_num = 0; |
1210 | timeout = 0; | 1287 | timeout = 0; |
@@ -1285,7 +1362,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1285 | continue; | 1362 | continue; |
1286 | } | 1363 | } |
1287 | leasefail: | 1364 | leasefail: |
1288 | d6_run_script(NULL, "leasefail"); | 1365 | d6_run_script_no_option("leasefail"); |
1289 | #if BB_MMU /* -b is not supported on NOMMU */ | 1366 | #if BB_MMU /* -b is not supported on NOMMU */ |
1290 | if (opt & OPT_b) { /* background if no lease */ | 1367 | if (opt & OPT_b) { /* background if no lease */ |
1291 | bb_error_msg("no lease, forking to background"); | 1368 | bb_error_msg("no lease, forking to background"); |
@@ -1359,7 +1436,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1359 | } | 1436 | } |
1360 | /* Timed out, enter init state */ | 1437 | /* Timed out, enter init state */ |
1361 | bb_error_msg("lease lost, entering init state"); | 1438 | bb_error_msg("lease lost, entering init state"); |
1362 | d6_run_script(NULL, "deconfig"); | 1439 | d6_run_script_no_option("deconfig"); |
1363 | state = INIT_SELECTING; | 1440 | state = INIT_SELECTING; |
1364 | client_config.first_secs = 0; /* make secs field count from 0 */ | 1441 | client_config.first_secs = 0; /* make secs field count from 0 */ |
1365 | /*timeout = 0; - already is */ | 1442 | /*timeout = 0; - already is */ |
@@ -1466,9 +1543,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1466 | if (option && (option->data[0] | option->data[1]) != 0) { | 1543 | if (option && (option->data[0] | option->data[1]) != 0) { |
1467 | /* return to init state */ | 1544 | /* return to init state */ |
1468 | bb_error_msg("received DHCP NAK (%u)", option->data[4]); | 1545 | bb_error_msg("received DHCP NAK (%u)", option->data[4]); |
1469 | d6_run_script(&packet, "nak"); | 1546 | d6_run_script(packet.d6_options, |
1547 | packet_end, "nak"); | ||
1470 | if (state != REQUESTING) | 1548 | if (state != REQUESTING) |
1471 | d6_run_script(NULL, "deconfig"); | 1549 | d6_run_script_no_option("deconfig"); |
1472 | change_listen_mode(LISTEN_RAW); | 1550 | change_listen_mode(LISTEN_RAW); |
1473 | sleep(3); /* avoid excessive network traffic */ | 1551 | sleep(3); /* avoid excessive network traffic */ |
1474 | state = INIT_SELECTING; | 1552 | state = INIT_SELECTING; |
@@ -1665,7 +1743,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1665 | if (timeout < 0x10) | 1743 | if (timeout < 0x10) |
1666 | timeout = 0x10; | 1744 | timeout = 0x10; |
1667 | /* enter bound state */ | 1745 | /* enter bound state */ |
1668 | d6_run_script(&packet, state == REQUESTING ? "bound" : "renew"); | 1746 | d6_run_script(packet.d6_options, packet_end, |
1747 | (state == REQUESTING ? "bound" : "renew")); | ||
1669 | 1748 | ||
1670 | state = BOUND; | 1749 | state = BOUND; |
1671 | change_listen_mode(LISTEN_NONE); | 1750 | change_listen_mode(LISTEN_NONE); |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index bd9e8fdc2..c2805a009 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -693,16 +693,10 @@ static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet, uint | |||
693 | 693 | ||
694 | static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server) | 694 | static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server) |
695 | { | 695 | { |
696 | if (server) { | 696 | if (server) |
697 | /* Without MSG_DONTROUTE, the packet was seen routed over | ||
698 | * _other interface_ if server ID is bogus (example: 1.1.1.1). | ||
699 | */ | ||
700 | return udhcp_send_kernel_packet(packet, | 697 | return udhcp_send_kernel_packet(packet, |
701 | ciaddr, CLIENT_PORT, | 698 | ciaddr, CLIENT_PORT, |
702 | server, SERVER_PORT, | 699 | server, SERVER_PORT); |
703 | /*send_flags: "to hosts only on directly connected networks" */ MSG_DONTROUTE | ||
704 | ); | ||
705 | } | ||
706 | return raw_bcast_from_client_config_ifindex(packet, ciaddr); | 700 | return raw_bcast_from_client_config_ifindex(packet, ciaddr); |
707 | } | 701 | } |
708 | 702 | ||
@@ -1337,7 +1331,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1337 | } | 1331 | } |
1338 | while (list_x) { | 1332 | while (list_x) { |
1339 | char *optstr = xstrdup(llist_pop(&list_x)); | 1333 | char *optstr = xstrdup(llist_pop(&list_x)); |
1340 | udhcp_str2optset(optstr, &client_config.options, dhcp_optflags, dhcp_option_strings); | 1334 | udhcp_str2optset(optstr, &client_config.options, |
1335 | dhcp_optflags, dhcp_option_strings, | ||
1336 | /*dhcpv6:*/ 0 | ||
1337 | ); | ||
1341 | free(optstr); | 1338 | free(optstr); |
1342 | } | 1339 | } |
1343 | 1340 | ||
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 19f94a2d7..a8cd3f03b 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
@@ -362,7 +362,10 @@ static int FAST_FUNC read_staticlease(const char *const_line, void *arg) | |||
362 | } | 362 | } |
363 | 363 | ||
364 | static int FAST_FUNC read_optset(const char *line, void *arg) { | 364 | static int FAST_FUNC read_optset(const char *line, void *arg) { |
365 | return udhcp_str2optset(line, arg, dhcp_optflags, dhcp_option_strings); | 365 | return udhcp_str2optset(line, arg, |
366 | dhcp_optflags, dhcp_option_strings, | ||
367 | /*dhcpv6:*/ 0 | ||
368 | ); | ||
366 | } | 369 | } |
367 | 370 | ||
368 | struct config_keyword { | 371 | struct config_keyword { |
@@ -588,9 +591,7 @@ static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt) | |||
588 | 591 | ||
589 | udhcp_send_kernel_packet(dhcp_pkt, | 592 | udhcp_send_kernel_packet(dhcp_pkt, |
590 | server_config.server_nip, SERVER_PORT, | 593 | server_config.server_nip, SERVER_PORT, |
591 | dhcp_pkt->gateway_nip, SERVER_PORT, | 594 | dhcp_pkt->gateway_nip, SERVER_PORT); |
592 | /*send_flags:*/ 0 | ||
593 | ); | ||
594 | } | 595 | } |
595 | 596 | ||
596 | static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast) | 597 | static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast) |
diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c index fc2bb5416..ff16904f7 100644 --- a/networking/udhcp/packet.c +++ b/networking/udhcp/packet.c | |||
@@ -189,8 +189,7 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, | |||
189 | /* Let the kernel do all the work for packet generation */ | 189 | /* Let the kernel do all the work for packet generation */ |
190 | int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, | 190 | int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, |
191 | uint32_t source_nip, int source_port, | 191 | uint32_t source_nip, int source_port, |
192 | uint32_t dest_nip, int dest_port, | 192 | uint32_t dest_nip, int dest_port) |
193 | int send_flags) | ||
194 | { | 193 | { |
195 | struct sockaddr_in sa; | 194 | struct sockaddr_in sa; |
196 | unsigned padding; | 195 | unsigned padding; |
@@ -227,8 +226,8 @@ int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, | |||
227 | padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(dhcp_pkt->options); | 226 | padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(dhcp_pkt->options); |
228 | if (padding > DHCP_SIZE - 300) | 227 | if (padding > DHCP_SIZE - 300) |
229 | padding = DHCP_SIZE - 300; | 228 | padding = DHCP_SIZE - 300; |
230 | result = send(fd, dhcp_pkt, DHCP_SIZE - padding, send_flags); | 229 | result = safe_write(fd, dhcp_pkt, DHCP_SIZE - padding); |
231 | msg = "send"; | 230 | msg = "write"; |
232 | ret_close: | 231 | ret_close: |
233 | close(fd); | 232 | close(fd); |
234 | if (result < 0) { | 233 | if (result < 0) { |
diff --git a/networking/wget.c b/networking/wget.c index 85eae061b..bd2f4edcf 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
@@ -137,6 +137,7 @@ | |||
137 | //usage: "Retrieve files via HTTP or FTP\n" | 137 | //usage: "Retrieve files via HTTP or FTP\n" |
138 | //usage: IF_FEATURE_WGET_LONG_OPTIONS( | 138 | //usage: IF_FEATURE_WGET_LONG_OPTIONS( |
139 | //usage: "\n --spider Only check URL existence: $? is 0 if exists" | 139 | //usage: "\n --spider Only check URL existence: $? is 0 if exists" |
140 | ///////: "\n --no-check-certificate Don't validate the server's certificate" | ||
140 | //usage: ) | 141 | //usage: ) |
141 | //usage: "\n -c Continue retrieval of aborted transfer" | 142 | //usage: "\n -c Continue retrieval of aborted transfer" |
142 | //usage: "\n -q Quiet" | 143 | //usage: "\n -q Quiet" |
@@ -271,6 +272,7 @@ enum { | |||
271 | WGET_OPT_HEADER = (1 << 10) * ENABLE_FEATURE_WGET_LONG_OPTIONS, | 272 | WGET_OPT_HEADER = (1 << 10) * ENABLE_FEATURE_WGET_LONG_OPTIONS, |
272 | WGET_OPT_POST_DATA = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS, | 273 | WGET_OPT_POST_DATA = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS, |
273 | WGET_OPT_SPIDER = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS, | 274 | WGET_OPT_SPIDER = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS, |
275 | WGET_OPT_NO_CHECK_CERT = (1 << 13) * ENABLE_FEATURE_WGET_LONG_OPTIONS, | ||
274 | }; | 276 | }; |
275 | 277 | ||
276 | enum { | 278 | enum { |
@@ -721,6 +723,9 @@ static void spawn_ssl_client(const char *host, int network_fd, int flags) | |||
721 | int pid; | 723 | int pid; |
722 | char *servername, *p; | 724 | char *servername, *p; |
723 | 725 | ||
726 | if (!(option_mask32 & WGET_OPT_NO_CHECK_CERT)) | ||
727 | bb_error_msg("note: TLS certificate validation not implemented"); | ||
728 | |||
724 | servername = xstrdup(host); | 729 | servername = xstrdup(host); |
725 | p = strrchr(servername, ':'); | 730 | p = strrchr(servername, ':'); |
726 | if (p) *p = '\0'; | 731 | if (p) *p = '\0'; |
@@ -1362,6 +1367,7 @@ However, in real world it was observed that some web servers | |||
1362 | /* server.user remains untouched */ | 1367 | /* server.user remains untouched */ |
1363 | free(server.allocated); | 1368 | free(server.allocated); |
1364 | server.allocated = NULL; | 1369 | server.allocated = NULL; |
1370 | server.protocol = target.protocol; | ||
1365 | server.host = target.host; | 1371 | server.host = target.host; |
1366 | /* strip_ipv6_scope_id(target.host); - no! */ | 1372 | /* strip_ipv6_scope_id(target.host); - no! */ |
1367 | /* we assume remote never gives us IPv6 addr with scope id */ | 1373 | /* we assume remote never gives us IPv6 addr with scope id */ |
@@ -1434,10 +1440,9 @@ IF_DESKTOP( "tries\0" Required_argument "t") | |||
1434 | "header\0" Required_argument "\xff" | 1440 | "header\0" Required_argument "\xff" |
1435 | "post-data\0" Required_argument "\xfe" | 1441 | "post-data\0" Required_argument "\xfe" |
1436 | "spider\0" No_argument "\xfd" | 1442 | "spider\0" No_argument "\xfd" |
1443 | "no-check-certificate\0" No_argument "\xfc" | ||
1437 | /* Ignored (we always use PASV): */ | 1444 | /* Ignored (we always use PASV): */ |
1438 | IF_DESKTOP( "passive-ftp\0" No_argument "\xf0") | 1445 | IF_DESKTOP( "passive-ftp\0" No_argument "\xf0") |
1439 | /* Ignored (we don't do ssl) */ | ||
1440 | IF_DESKTOP( "no-check-certificate\0" No_argument "\xf0") | ||
1441 | /* Ignored (we don't support caching) */ | 1446 | /* Ignored (we don't support caching) */ |
1442 | IF_DESKTOP( "no-cache\0" No_argument "\xf0") | 1447 | IF_DESKTOP( "no-cache\0" No_argument "\xf0") |
1443 | IF_DESKTOP( "no-verbose\0" No_argument "\xf0") | 1448 | IF_DESKTOP( "no-verbose\0" No_argument "\xf0") |
@@ -1497,6 +1502,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0") | |||
1497 | if (option_mask32 & WGET_OPT_HEADER) bb_error_msg("--header"); | 1502 | if (option_mask32 & WGET_OPT_HEADER) bb_error_msg("--header"); |
1498 | if (option_mask32 & WGET_OPT_POST_DATA) bb_error_msg("--post-data"); | 1503 | if (option_mask32 & WGET_OPT_POST_DATA) bb_error_msg("--post-data"); |
1499 | if (option_mask32 & WGET_OPT_SPIDER) bb_error_msg("--spider"); | 1504 | if (option_mask32 & WGET_OPT_SPIDER) bb_error_msg("--spider"); |
1505 | if (option_mask32 & WGET_OPT_NO_CHECK_CERT) bb_error_msg("--no-check-certificate"); | ||
1500 | exit(0); | 1506 | exit(0); |
1501 | #endif | 1507 | #endif |
1502 | argv += optind; | 1508 | argv += optind; |
diff --git a/printutils/Config.src b/printutils/Config.src index e53b9d093..5f1d65f6c 100644 --- a/printutils/Config.src +++ b/printutils/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "Print Utilities" | 6 | menu "Print Utilities" |
diff --git a/procps/Config.src b/procps/Config.src index 515d79938..2b1b8ab11 100644 --- a/procps/Config.src +++ b/procps/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "Process Utilities" | 6 | menu "Process Utilities" |
diff --git a/runit/Config.src b/runit/Config.src index 8cde89680..403ec8724 100644 --- a/runit/Config.src +++ b/runit/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "Runit Utilities" | 6 | menu "Runit Utilities" |
diff --git a/scripts/bb_release b/scripts/bb_release index 8aa380438..2e146bf84 100755 --- a/scripts/bb_release +++ b/scripts/bb_release | |||
@@ -15,20 +15,8 @@ VERSION=`ls busybox-*.tar.gz | sed 's/busybox-\(.*\)\.tar\.gz/\1/'` | |||
15 | 15 | ||
16 | zcat busybox-$VERSION.tar.gz | bzip2 > busybox-$VERSION.tar.bz2 | 16 | zcat busybox-$VERSION.tar.gz | bzip2 > busybox-$VERSION.tar.bz2 |
17 | 17 | ||
18 | test -f busybox-$VERSION.tar.gz || { echo "no busybox-$VERSION.tar.gz"; exit 1; } | 18 | for releasefile in busybox-$VERSION.tar.gz busybox-$VERSION.tar.bz2; do |
19 | test -f busybox-$VERSION.tar.bz2 || { echo "no busybox-$VERSION.tar.bz2"; exit 1; } | 19 | test -f $releasefile || { echo "no $releasefile"; exit 1; } |
20 | 20 | gpg --detach-sign $releasefile | |
21 | signit() | 21 | sha256sum $releasefile > $releasefile.sha256 |
22 | { | 22 | done |
23 | echo "$1 released `date -r $1 -R` | ||
24 | |||
25 | MD5: `md5sum $1` | ||
26 | SHA1: `sha1sum $1` | ||
27 | |||
28 | To verify this signature, you can obtain my public key | ||
29 | from http://busybox.net/~vda/vda_pubkey.gpg | ||
30 | " | gpg --clearsign > "$1.sign" | ||
31 | } | ||
32 | |||
33 | signit busybox-$VERSION.tar.gz | ||
34 | signit busybox-$VERSION.tar.bz2 | ||
diff --git a/scripts/randomtest b/scripts/randomtest index 635978338..94709a99f 100755 --- a/scripts/randomtest +++ b/scripts/randomtest | |||
@@ -57,6 +57,8 @@ if test x"$LIBC" = x"glibc"; then | |||
57 | | grep -v CONFIG_FEATURE_2_4_MODULES \ | 57 | | grep -v CONFIG_FEATURE_2_4_MODULES \ |
58 | | grep -v CONFIG_FEATURE_USE_BSS_TAIL \ | 58 | | grep -v CONFIG_FEATURE_USE_BSS_TAIL \ |
59 | | grep -v CONFIG_DEBUG_SANITIZE \ | 59 | | grep -v CONFIG_DEBUG_SANITIZE \ |
60 | | grep -v CONFIG_FEATURE_MOUNT_NFS \ | ||
61 | | grep -v CONFIG_FEATURE_INETD_RPC \ | ||
60 | >.config.new | 62 | >.config.new |
61 | mv .config.new .config | 63 | mv .config.new .config |
62 | echo '# CONFIG_STATIC is not set' >>.config | 64 | echo '# CONFIG_STATIC is not set' >>.config |
@@ -66,6 +68,9 @@ if test x"$LIBC" = x"glibc"; then | |||
66 | echo '# CONFIG_FEATURE_2_4_MODULES is not set' >>.config | 68 | echo '# CONFIG_FEATURE_2_4_MODULES is not set' >>.config |
67 | echo '# CONFIG_FEATURE_USE_BSS_TAIL is not set' >>.config | 69 | echo '# CONFIG_FEATURE_USE_BSS_TAIL is not set' >>.config |
68 | echo '# CONFIG_DEBUG_SANITIZE is not set' >>.config | 70 | echo '# CONFIG_DEBUG_SANITIZE is not set' >>.config |
71 | # 2018: current glibc versions no longer include rpc/rpc.h | ||
72 | echo '# CONFIG_FEATURE_MOUNT_NFS is not set' >>.config | ||
73 | echo '# CONFIG_FEATURE_INETD_RPC is not set' >>.config | ||
69 | fi | 74 | fi |
70 | 75 | ||
71 | # If uclibc, build static, and remove some things | 76 | # If uclibc, build static, and remove some things |
@@ -86,6 +91,7 @@ if test x"$LIBC" = x"uclibc"; then | |||
86 | | grep -v CONFIG_UNSHARE \ | 91 | | grep -v CONFIG_UNSHARE \ |
87 | | grep -v CONFIG_FALLOCATE \ | 92 | | grep -v CONFIG_FALLOCATE \ |
88 | | grep -v CONFIG_UDHCPC6 \ | 93 | | grep -v CONFIG_UDHCPC6 \ |
94 | | grep -v CONFIG_NSLOOKUP \ | ||
89 | | grep -v CONFIG_ASH_INTERNAL_GLOB \ | 95 | | grep -v CONFIG_ASH_INTERNAL_GLOB \ |
90 | >.config.new | 96 | >.config.new |
91 | mv .config.new .config | 97 | mv .config.new .config |
@@ -103,6 +109,7 @@ if test x"$LIBC" = x"uclibc"; then | |||
103 | echo '# CONFIG_UNSHARE is not set' >>.config | 109 | echo '# CONFIG_UNSHARE is not set' >>.config |
104 | echo '# CONFIG_FALLOCATE is not set' >>.config | 110 | echo '# CONFIG_FALLOCATE is not set' >>.config |
105 | echo '# CONFIG_UDHCPC6 is not set' >>.config | 111 | echo '# CONFIG_UDHCPC6 is not set' >>.config |
112 | echo '# CONFIG_NSLOOKUP is not set' >>.config | ||
106 | echo 'CONFIG_ASH_INTERNAL_GLOB=y' >>.config | 113 | echo 'CONFIG_ASH_INTERNAL_GLOB=y' >>.config |
107 | fi | 114 | fi |
108 | 115 | ||
diff --git a/selinux/Config.src b/selinux/Config.src index 9cb755a0f..f8fcdadf9 100644 --- a/selinux/Config.src +++ b/selinux/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "SELinux Utilities" | 6 | menu "SELinux Utilities" |
diff --git a/shell/Config.src b/shell/Config.src index 81c4ec874..959d3cb42 100644 --- a/shell/Config.src +++ b/shell/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "Shells" | 6 | menu "Shells" |
diff --git a/shell/ash.c b/shell/ash.c index 7fa9dae21..4bd1c2c9d 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -8929,7 +8929,8 @@ describe_command(char *command, const char *path, int describe_command_verbose) | |||
8929 | 8929 | ||
8930 | case CMDFUNCTION: | 8930 | case CMDFUNCTION: |
8931 | if (describe_command_verbose) { | 8931 | if (describe_command_verbose) { |
8932 | out1str(" is a shell function"); | 8932 | /*out1str(" is a shell function");*/ |
8933 | out1str(" is a function"); /* bash says this */ | ||
8933 | } else { | 8934 | } else { |
8934 | out1str(command); | 8935 | out1str(command); |
8935 | } | 8936 | } |
diff --git a/shell/ash_test/ash-glob/glob_altvalue1.right b/shell/ash_test/ash-glob/glob_altvalue1.right new file mode 100644 index 000000000..bd3592229 --- /dev/null +++ b/shell/ash_test/ash-glob/glob_altvalue1.right | |||
@@ -0,0 +1,7 @@ | |||
1 | 1u: glob_altvalue1.tests | ||
2 | 2u: glob_altvalue1.t* | ||
3 | 3u: glob_altvalue1.t* | ||
4 | 4u: glob_altvalue1.t* | ||
5 | 1q: glob_altvalue1.t* | ||
6 | 2q: 'glob_altvalue1.t*' | ||
7 | 3q: glob_altvalue1.t* | ||
diff --git a/shell/ash_test/ash-glob/glob_altvalue1.tests b/shell/ash_test/ash-glob/glob_altvalue1.tests new file mode 100755 index 000000000..5483d63e6 --- /dev/null +++ b/shell/ash_test/ash-glob/glob_altvalue1.tests | |||
@@ -0,0 +1,13 @@ | |||
1 | x=x | ||
2 | |||
3 | echo 1u: ${x:+glob_altvalue1.t*} | ||
4 | echo 2u: ${x:+'glob_altvalue1.t*'} | ||
5 | echo 3u: ${x:+"glob_altvalue1.t*"} | ||
6 | echo 4u: ${x:+glob_altvalue1.t\*} | ||
7 | ##echo 5u: ${x:+"glob_altvalue1.t\*"} | ||
8 | |||
9 | echo 1q: "${x:+glob_altvalue1.t*}" | ||
10 | echo 2q: "${x:+'glob_altvalue1.t*'}" | ||
11 | echo 3q: "${x:+"glob_altvalue1.t*"}" | ||
12 | ##echo 4q: "${x:+glob_altvalue1.t\*}" | ||
13 | ##echo 5q: "${x:+"glob_altvalue1.t\*"}" | ||
diff --git a/shell/ash_test/ash-heredoc/heredoc.right b/shell/ash_test/ash-heredoc/heredoc.right index baf115166..85d36dae9 100644 --- a/shell/ash_test/ash-heredoc/heredoc.right +++ b/shell/ash_test/ash-heredoc/heredoc.right | |||
@@ -16,6 +16,6 @@ tab 3 | |||
16 | abc | 16 | abc |
17 | def ghi | 17 | def ghi |
18 | jkl mno | 18 | jkl mno |
19 | fff is a shell function | 19 | fff is a function |
20 | hi | 20 | hi |
21 | there | 21 | there |
diff --git a/shell/ash_test/ash-heredoc/heredocA.right b/shell/ash_test/ash-heredoc/heredocA.right new file mode 100644 index 000000000..7326d9603 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredocA.right | |||
@@ -0,0 +1 @@ | |||
Ok | |||
diff --git a/shell/ash_test/ash-heredoc/heredocA.tests b/shell/ash_test/ash-heredoc/heredocA.tests new file mode 100755 index 000000000..440aaf906 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredocA.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | { cat <<EOF ; | ||
2 | Ok | ||
3 | EOF | ||
4 | } | ||
diff --git a/shell/ash_test/ash-heredoc/heredocB.right b/shell/ash_test/ash-heredoc/heredocB.right new file mode 100644 index 000000000..43ba0b4f9 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredocB.right | |||
@@ -0,0 +1,3 @@ | |||
1 | one - alpha | ||
2 | two - beta | ||
3 | three - gamma | ||
diff --git a/shell/ash_test/ash-heredoc/heredocB.tests b/shell/ash_test/ash-heredoc/heredocB.tests new file mode 100755 index 000000000..45ea4687f --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredocB.tests | |||
@@ -0,0 +1,12 @@ | |||
1 | while read line1; do | ||
2 | read line2 <&3 | ||
3 | echo $line1 - $line2 | ||
4 | done <<EOF1 3<<EOF2 | ||
5 | one | ||
6 | two | ||
7 | three | ||
8 | EOF1 | ||
9 | alpha | ||
10 | beta | ||
11 | gamma | ||
12 | EOF2 | ||
diff --git a/shell/ash_test/ash-heredoc/heredoc_after_compound1.right b/shell/ash_test/ash-heredoc/heredoc_after_compound1.right new file mode 100644 index 000000000..9052f7d1f --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_after_compound1.right | |||
@@ -0,0 +1,2 @@ | |||
1 | Ok1 | ||
2 | Ok2 | ||
diff --git a/shell/ash_test/ash-heredoc/heredoc_after_compound1.tests b/shell/ash_test/ash-heredoc/heredoc_after_compound1.tests new file mode 100755 index 000000000..e7cfb5be1 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_after_compound1.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | { cat <<EOF; }; echo Ok2 | ||
2 | Ok1 | ||
3 | EOF | ||
diff --git a/shell/ash_test/ash-heredoc/heredoc_bkslash_newline2.right b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline2.right new file mode 100644 index 000000000..3d79316d7 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline2.right | |||
@@ -0,0 +1 @@ | |||
Ok1 | |||
diff --git a/shell/ash_test/ash-heredoc/heredoc_bkslash_newline2.tests b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline2.tests new file mode 100755 index 000000000..1d2a26504 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline2.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | cat <<EOF | ||
2 | Ok1 | ||
3 | EO\ | ||
4 | F | ||
diff --git a/shell/ash_test/ash-heredoc/heredoc_empty3.right b/shell/ash_test/ash-heredoc/heredoc_empty3.right new file mode 100644 index 000000000..0b54a9c93 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_empty3.right | |||
@@ -0,0 +1,2 @@ | |||
1 | |||
2 | Ok | ||
diff --git a/shell/ash_test/ash-heredoc/heredoc_empty3.tests b/shell/ash_test/ash-heredoc/heredoc_empty3.tests new file mode 100755 index 000000000..828c2dd89 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_empty3.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | cat <<EOF | ||
2 | |||
3 | Ok | ||
4 | EOF | ||
diff --git a/shell/ash_test/ash-quoting/dollar_altvalue1.right b/shell/ash_test/ash-quoting/dollar_altvalue1.right new file mode 100644 index 000000000..5cd495d3b --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_altvalue1.right | |||
@@ -0,0 +1,16 @@ | |||
1 | Unquoted b c d | ||
2 | |b| | ||
3 | |c| | ||
4 | |d| | ||
5 | Unquoted 'b c' d | ||
6 | |b c| | ||
7 | |d| | ||
8 | Unquoted "b c" d | ||
9 | |b c| | ||
10 | |d| | ||
11 | Quoted b c d | ||
12 | |b c d| | ||
13 | Quoted 'b c' d | ||
14 | |'b c' d| | ||
15 | Quoted "b c" d | ||
16 | |b c d| | ||
diff --git a/shell/ash_test/ash-quoting/dollar_altvalue1.tests b/shell/ash_test/ash-quoting/dollar_altvalue1.tests new file mode 100755 index 000000000..f4dc8caec --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_altvalue1.tests | |||
@@ -0,0 +1,16 @@ | |||
1 | f() { for i; do echo "|$i|"; done; } | ||
2 | x=a | ||
3 | |||
4 | echo Unquoted b c d | ||
5 | f ${x:+b c d} | ||
6 | echo Unquoted "'b c' d" | ||
7 | f ${x:+'b c' d} | ||
8 | echo Unquoted '"b c" d' | ||
9 | f ${x:+"b c" d} | ||
10 | |||
11 | echo Quoted b c d | ||
12 | f "${x:+b c d}" | ||
13 | echo Quoted "'b c' d" | ||
14 | f "${x:+'b c' d}" | ||
15 | echo Quoted '"b c" d' | ||
16 | f "${x:+"b c" d}" | ||
diff --git a/shell/ash_test/ash-quoting/dollar_altvalue2.right b/shell/ash_test/ash-quoting/dollar_altvalue2.right new file mode 100644 index 000000000..7cf37e379 --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_altvalue2.right | |||
@@ -0,0 +1,69 @@ | |||
1 | Unquoted '': | ||
2 | start: | ||
3 | || | ||
4 | end | ||
5 | start: | ||
6 | || | ||
7 | end | ||
8 | start: | ||
9 | || | ||
10 | end | ||
11 | start: | ||
12 | || | ||
13 | end | ||
14 | start: | ||
15 | || | ||
16 | || | ||
17 | end | ||
18 | |||
19 | Unquoted "": | ||
20 | start: | ||
21 | || | ||
22 | end | ||
23 | start: | ||
24 | || | ||
25 | end | ||
26 | start: | ||
27 | || | ||
28 | end | ||
29 | start: | ||
30 | || | ||
31 | end | ||
32 | start: | ||
33 | || | ||
34 | || | ||
35 | end | ||
36 | |||
37 | Quoted '': | ||
38 | start: | ||
39 | |''| | ||
40 | end | ||
41 | start: | ||
42 | |'' | | ||
43 | end | ||
44 | start: | ||
45 | | ''| | ||
46 | end | ||
47 | start: | ||
48 | | '' | | ||
49 | end | ||
50 | start: | ||
51 | |'' ''| | ||
52 | end | ||
53 | |||
54 | Quoted "": | ||
55 | start: | ||
56 | || | ||
57 | end | ||
58 | start: | ||
59 | | | | ||
60 | end | ||
61 | start: | ||
62 | | | | ||
63 | end | ||
64 | start: | ||
65 | | | | ||
66 | end | ||
67 | start: | ||
68 | | | | ||
69 | end | ||
diff --git a/shell/ash_test/ash-quoting/dollar_altvalue2.tests b/shell/ash_test/ash-quoting/dollar_altvalue2.tests new file mode 100755 index 000000000..3377eb27f --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_altvalue2.tests | |||
@@ -0,0 +1,33 @@ | |||
1 | f() { echo start:; for i; do echo "|$i|"; done; echo end; } | ||
2 | x=a | ||
3 | |||
4 | echo "Unquoted '':" | ||
5 | f ${x:+''} | ||
6 | f ${x:+'' } | ||
7 | f ${x:+ ''} | ||
8 | f ${x:+ '' } | ||
9 | f ${x:+'' ''} | ||
10 | |||
11 | echo | ||
12 | echo 'Unquoted "":' | ||
13 | f ${x:+""} | ||
14 | f ${x:+"" } | ||
15 | f ${x:+ ""} | ||
16 | f ${x:+ "" } | ||
17 | f ${x:+"" ""} | ||
18 | |||
19 | echo | ||
20 | echo "Quoted '':" | ||
21 | f "${x:+''}" | ||
22 | f "${x:+'' }" | ||
23 | f "${x:+ ''}" | ||
24 | f "${x:+ '' }" | ||
25 | f "${x:+'' ''}" | ||
26 | |||
27 | echo | ||
28 | echo 'Quoted "":' | ||
29 | f "${x:+""}" | ||
30 | f "${x:+"" }" | ||
31 | f "${x:+ ""}" | ||
32 | f "${x:+ "" }" | ||
33 | f "${x:+"" ""}" | ||
diff --git a/shell/ash_test/ash-quoting/dollar_altvalue9.right b/shell/ash_test/ash-quoting/dollar_altvalue9.right new file mode 100644 index 000000000..39342fe7c --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_altvalue9.right | |||
@@ -0,0 +1,26 @@ | |||
1 | Unquoted 1: | ||
2 | |a| | ||
3 | |x y| | ||
4 | |1| | ||
5 | |2| | ||
6 | || | ||
7 | |1 2| | ||
8 | |A| | ||
9 | |B| | ||
10 | |C D| | ||
11 | |zb| | ||
12 | Quoted 1: | ||
13 | |a 'x y' 1 2 '' 1 2 A B C D zb| | ||
14 | Unquoted 2: | ||
15 | |ax y| | ||
16 | |1| | ||
17 | |2| | ||
18 | || | ||
19 | |1 2| | ||
20 | |A| | ||
21 | |B| | ||
22 | |C D| | ||
23 | |z| | ||
24 | |b| | ||
25 | Quoted 2: | ||
26 | |a 'x y' 1 2 '' 1 2 A B C D z b| | ||
diff --git a/shell/ash_test/ash-quoting/dollar_altvalue9.tests b/shell/ash_test/ash-quoting/dollar_altvalue9.tests new file mode 100755 index 000000000..27a6f4f3c --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_altvalue9.tests | |||
@@ -0,0 +1,17 @@ | |||
1 | f() { for i; do echo "|$i|"; done; } | ||
2 | |||
3 | echo Unquoted 1: | ||
4 | x='1 2'; f a${x:+ 'x y' $x '' "$x" `echo A B` "`echo C D`" z}b | ||
5 | echo Quoted 1: | ||
6 | x='1 2'; f "a${x:+ 'x y' $x '' "$x" `echo A B` "`echo C D`" z}b" | ||
7 | |||
8 | echo Unquoted 2: | ||
9 | x='1 2'; f a${x:+'x y' $x '' "$x" `echo A B` "`echo C D`" z }b | ||
10 | echo Quoted 2: | ||
11 | x='1 2'; f "a${x:+ 'x y' $x '' "$x" `echo A B` "`echo C D`" z }b" | ||
12 | |||
13 | #echo Unquoted 3: | ||
14 | #e= | ||
15 | #x='1 2'; f a${x:+'x y' $x '' "$x" $e $e "$e" $e `echo A B` "`echo C D`" z }b | ||
16 | #echo Quoted 3: | ||
17 | #x='1 2'; f "a${x:+ 'x y' $x '' "$x" $e $e "$e" $e `echo A B` "`echo C D`" z }b" | ||
diff --git a/shell/ash_test/ash-quoting/dollar_repl_bash1.right b/shell/ash_test/ash-quoting/dollar_repl_bash1.right new file mode 100644 index 000000000..f5e9309f4 --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_repl_bash1.right | |||
@@ -0,0 +1,14 @@ | |||
1 | |y| | ||
2 | |zx| | ||
3 | |y| | ||
4 | |zx| | ||
5 | |y zx| | ||
6 | |y zx| | ||
7 | |y| | ||
8 | |zy| | ||
9 | |z| | ||
10 | |y| | ||
11 | |zy| | ||
12 | |z| | ||
13 | |y zy z| | ||
14 | |y zy z| | ||
diff --git a/shell/ash_test/ash-quoting/dollar_repl_bash1.tests b/shell/ash_test/ash-quoting/dollar_repl_bash1.tests new file mode 100755 index 000000000..912635925 --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_repl_bash1.tests | |||
@@ -0,0 +1,12 @@ | |||
1 | f() { for i; do echo "|$i|"; done; } | ||
2 | v=xx | ||
3 | |||
4 | f ${v/'x'/"y z"} | ||
5 | f ${v/"x"/'y z'} | ||
6 | f "${v/'x'/"y z"}" | ||
7 | f "${v/"x"/'y z'}" | ||
8 | |||
9 | f ${v//'x'/"y z"} | ||
10 | f ${v//"x"/'y z'} | ||
11 | f "${v//'x'/"y z"}" | ||
12 | f "${v//"x"/'y z'}" | ||
diff --git a/shell/ash_test/ash-quoting/squote_in_varexp.right b/shell/ash_test/ash-quoting/squote_in_varexp.right index a75c0bfd6..4a457021b 100644 --- a/shell/ash_test/ash-quoting/squote_in_varexp.right +++ b/shell/ash_test/ash-quoting/squote_in_varexp.right | |||
@@ -1,5 +1,9 @@ | |||
1 | z | 1 | z |
2 | z | 2 | z |
3 | z | ||
4 | z | ||
5 | y | ||
6 | y | ||
3 | y | 7 | y |
4 | y | 8 | y |
5 | Ok:0 | 9 | Ok:0 |
diff --git a/shell/ash_test/ash-quoting/squote_in_varexp.tests b/shell/ash_test/ash-quoting/squote_in_varexp.tests index a2d05a246..4afc52107 100755 --- a/shell/ash_test/ash-quoting/squote_in_varexp.tests +++ b/shell/ash_test/ash-quoting/squote_in_varexp.tests | |||
@@ -1,6 +1,10 @@ | |||
1 | x=yz | 1 | x=yz |
2 | echo ${x#'y'} | 2 | echo ${x#'y'} |
3 | echo "${x#'y'}" | 3 | echo "${x#'y'}" |
4 | echo ${x#"y"} | ||
5 | echo "${x#"y"}" | ||
4 | echo ${x%'z'} | 6 | echo ${x%'z'} |
5 | echo "${x%'z'}" | 7 | echo "${x%'z'}" |
8 | echo ${x%"z"} | ||
9 | echo "${x%"z"}" | ||
6 | echo Ok:$? | 10 | echo Ok:$? |
diff --git a/shell/ash_test/ash-quoting/squote_in_varexp2.right b/shell/ash_test/ash-quoting/squote_in_varexp2.right index 9d0add3c5..d03047024 100644 --- a/shell/ash_test/ash-quoting/squote_in_varexp2.right +++ b/shell/ash_test/ash-quoting/squote_in_varexp2.right | |||
@@ -1,3 +1,5 @@ | |||
1 | Nothing: | 1 | Nothing: |
2 | Nothing: | 2 | Nothing: |
3 | Nothing: | ||
4 | Nothing: | ||
3 | Ok:0 | 5 | Ok:0 |
diff --git a/shell/ash_test/ash-quoting/squote_in_varexp2.tests b/shell/ash_test/ash-quoting/squote_in_varexp2.tests index 806ad12b9..2797725cc 100755 --- a/shell/ash_test/ash-quoting/squote_in_varexp2.tests +++ b/shell/ash_test/ash-quoting/squote_in_varexp2.tests | |||
@@ -1,4 +1,6 @@ | |||
1 | x='\\\\' | 1 | x='\\\\' |
2 | printf Nothing:'%s\n' ${x#'\\\\'} | 2 | printf Nothing:'%s\n' ${x#'\\\\'} |
3 | printf Nothing:'%s\n' "${x#'\\\\'}" | 3 | printf Nothing:'%s\n' "${x#'\\\\'}" |
4 | printf Nothing:'%s\n' ${x#"\\\\\\\\"} | ||
5 | printf Nothing:'%s\n' "${x#"\\\\\\\\"}" | ||
4 | echo Ok:$? | 6 | echo Ok:$? |
diff --git a/shell/ash_test/ash-redir/redir_script.tests b/shell/ash_test/ash-redir/redir_script.tests index 740daa461..a8d93ce4f 100755 --- a/shell/ash_test/ash-redir/redir_script.tests +++ b/shell/ash_test/ash-redir/redir_script.tests | |||
@@ -27,6 +27,10 @@ test x"$fds1" = x"$fds" \ | |||
27 | test x"$fds1" = x" 10>&- 3>&-" && \ | 27 | test x"$fds1" = x" 10>&- 3>&-" && \ |
28 | test x"$fds" = x" 11>&- 3>&-" \ | 28 | test x"$fds" = x" 11>&- 3>&-" \ |
29 | && { echo "Ok: script fd is not closed"; exit 0; } | 29 | && { echo "Ok: script fd is not closed"; exit 0; } |
30 | # or we see that fd 3 moved to fd 10: | ||
31 | test x"$fds1" = x" 3>&- 4>&-" && \ | ||
32 | test x"$fds" = x" 10>&- 3>&-" \ | ||
33 | && { echo "Ok: script fd is not closed"; exit 0; } | ||
30 | 34 | ||
31 | echo "Bug: script fd is closed" | 35 | echo "Bug: script fd is closed" |
32 | echo "fds1:$fds1" | 36 | echo "fds1:$fds1" |
diff --git a/shell/ash_test/ash-z_slow/many_ifs.tests b/shell/ash_test/ash-z_slow/many_ifs.tests index 1f5b1b3a6..cf9a89874 100755 --- a/shell/ash_test/ash-z_slow/many_ifs.tests +++ b/shell/ash_test/ash-z_slow/many_ifs.tests | |||
@@ -229,8 +229,8 @@ do | |||
229 | '') split "$d0$f1$d1$f2$d2$f3$d3" "[2]($f1)($f2)" "($f1)($f2)" ;; | 229 | '') split "$d0$f1$d1$f2$d2$f3$d3" "[2]($f1)($f2)" "($f1)($f2)" ;; |
230 | ' ') ;; | 230 | ' ') ;; |
231 | *) x=$f2$d2$f3$d3 | 231 | *) x=$f2$d2$f3$d3 |
232 | x=${x# } #was x=${x#' '} hush needs fixing for this to work | 232 | x=${x#' '} |
233 | x=${x% } #was x=${x%' '} | 233 | x=${x%' '} |
234 | split "$d0$f1$d1$f2$d2$f3$d3" "[3]($f1)($f2)($f3)" "($f1)($x)" | 234 | split "$d0$f1$d1$f2$d2$f3$d3" "[3]($f1)($f2)($f3)" "($f1)($x)" |
235 | ;; | 235 | ;; |
236 | esac | 236 | esac |
diff --git a/shell/hush.c b/shell/hush.c index c77700175..e3c6e2de9 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -357,6 +357,9 @@ | |||
357 | #else | 357 | #else |
358 | # define CLEAR_RANDOM_T(rnd) ((void)0) | 358 | # define CLEAR_RANDOM_T(rnd) ((void)0) |
359 | #endif | 359 | #endif |
360 | #ifndef O_CLOEXEC | ||
361 | # define O_CLOEXEC 0 | ||
362 | #endif | ||
360 | #ifndef F_DUPFD_CLOEXEC | 363 | #ifndef F_DUPFD_CLOEXEC |
361 | # define F_DUPFD_CLOEXEC F_DUPFD | 364 | # define F_DUPFD_CLOEXEC F_DUPFD |
362 | #endif | 365 | #endif |
@@ -439,21 +442,22 @@ | |||
439 | 442 | ||
440 | /* If you comment out one of these below, it will be #defined later | 443 | /* If you comment out one of these below, it will be #defined later |
441 | * to perform debug printfs to stderr: */ | 444 | * to perform debug printfs to stderr: */ |
442 | #define debug_printf(...) do {} while (0) | 445 | #define debug_printf(...) do {} while (0) |
443 | /* Finer-grained debug switches */ | 446 | /* Finer-grained debug switches */ |
444 | #define debug_printf_parse(...) do {} while (0) | 447 | #define debug_printf_parse(...) do {} while (0) |
445 | #define debug_print_tree(a, b) do {} while (0) | 448 | #define debug_printf_heredoc(...) do {} while (0) |
446 | #define debug_printf_exec(...) do {} while (0) | 449 | #define debug_print_tree(a, b) do {} while (0) |
447 | #define debug_printf_env(...) do {} while (0) | 450 | #define debug_printf_exec(...) do {} while (0) |
448 | #define debug_printf_jobs(...) do {} while (0) | 451 | #define debug_printf_env(...) do {} while (0) |
449 | #define debug_printf_expand(...) do {} while (0) | 452 | #define debug_printf_jobs(...) do {} while (0) |
450 | #define debug_printf_varexp(...) do {} while (0) | 453 | #define debug_printf_expand(...) do {} while (0) |
451 | #define debug_printf_glob(...) do {} while (0) | 454 | #define debug_printf_varexp(...) do {} while (0) |
452 | #define debug_printf_redir(...) do {} while (0) | 455 | #define debug_printf_glob(...) do {} while (0) |
453 | #define debug_printf_list(...) do {} while (0) | 456 | #define debug_printf_redir(...) do {} while (0) |
454 | #define debug_printf_subst(...) do {} while (0) | 457 | #define debug_printf_list(...) do {} while (0) |
455 | #define debug_printf_prompt(...) do {} while (0) | 458 | #define debug_printf_subst(...) do {} while (0) |
456 | #define debug_printf_clean(...) do {} while (0) | 459 | #define debug_printf_prompt(...) do {} while (0) |
460 | #define debug_printf_clean(...) do {} while (0) | ||
457 | 461 | ||
458 | #define ERR_PTR ((void*)(long)1) | 462 | #define ERR_PTR ((void*)(long)1) |
459 | 463 | ||
@@ -534,6 +538,7 @@ typedef struct o_string { | |||
534 | * possibly empty one: word"", wo''rd etc. */ | 538 | * possibly empty one: word"", wo''rd etc. */ |
535 | smallint has_quoted_part; | 539 | smallint has_quoted_part; |
536 | smallint has_empty_slot; | 540 | smallint has_empty_slot; |
541 | smallint ended_in_ifs; | ||
537 | } o_string; | 542 | } o_string; |
538 | enum { | 543 | enum { |
539 | EXP_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */ | 544 | EXP_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */ |
@@ -554,11 +559,27 @@ static const char *const assignment_flag[] = { | |||
554 | }; | 559 | }; |
555 | #endif | 560 | #endif |
556 | 561 | ||
562 | /* We almost can use standard FILE api, but we need an ability to move | ||
563 | * its fd when redirects coincide with it. No api exists for that | ||
564 | * (RFE for it at https://sourceware.org/bugzilla/show_bug.cgi?id=21902). | ||
565 | * HFILE is our internal alternative. Only supports reading. | ||
566 | * Since we now can, we incorporate linked list of all opened HFILEs | ||
567 | * into the struct (used to be a separate mini-list). | ||
568 | */ | ||
569 | typedef struct HFILE { | ||
570 | char *cur; | ||
571 | char *end; | ||
572 | struct HFILE *next_hfile; | ||
573 | int is_stdin; | ||
574 | int fd; | ||
575 | char buf[1024]; | ||
576 | } HFILE; | ||
577 | |||
557 | typedef struct in_str { | 578 | typedef struct in_str { |
558 | const char *p; | 579 | const char *p; |
559 | int peek_buf[2]; | 580 | int peek_buf[2]; |
560 | int last_char; | 581 | int last_char; |
561 | FILE *file; | 582 | HFILE *file; |
562 | } in_str; | 583 | } in_str; |
563 | 584 | ||
564 | /* The descrip member of this structure is only used to make | 585 | /* The descrip member of this structure is only used to make |
@@ -812,14 +833,6 @@ enum { | |||
812 | NUM_OPT_O | 833 | NUM_OPT_O |
813 | }; | 834 | }; |
814 | 835 | ||
815 | |||
816 | struct FILE_list { | ||
817 | struct FILE_list *next; | ||
818 | FILE *fp; | ||
819 | int fd; | ||
820 | }; | ||
821 | |||
822 | |||
823 | /* "Globals" within this file */ | 836 | /* "Globals" within this file */ |
824 | /* Sorted roughly by size (smaller offsets == smaller code) */ | 837 | /* Sorted roughly by size (smaller offsets == smaller code) */ |
825 | struct globals { | 838 | struct globals { |
@@ -952,7 +965,7 @@ struct globals { | |||
952 | unsigned lineno; | 965 | unsigned lineno; |
953 | char *lineno_var; | 966 | char *lineno_var; |
954 | #endif | 967 | #endif |
955 | struct FILE_list *FILE_list; | 968 | HFILE *HFILE_list; |
956 | /* Which signals have non-DFL handler (even with no traps set)? | 969 | /* Which signals have non-DFL handler (even with no traps set)? |
957 | * Set at the start to: | 970 | * Set at the start to: |
958 | * (SIGQUIT + maybe SPECIAL_INTERACTIVE_SIGS + maybe SPECIAL_JOBSTOP_SIGS) | 971 | * (SIGQUIT + maybe SPECIAL_INTERACTIVE_SIGS + maybe SPECIAL_JOBSTOP_SIGS) |
@@ -1218,6 +1231,10 @@ static const struct built_in_command bltins2[] = { | |||
1218 | # define debug_printf_parse(...) (indent(), fdprintf(2, __VA_ARGS__)) | 1231 | # define debug_printf_parse(...) (indent(), fdprintf(2, __VA_ARGS__)) |
1219 | #endif | 1232 | #endif |
1220 | 1233 | ||
1234 | #ifndef debug_printf_heredoc | ||
1235 | # define debug_printf_heredoc(...) (indent(), fdprintf(2, __VA_ARGS__)) | ||
1236 | #endif | ||
1237 | |||
1221 | #ifndef debug_printf_exec | 1238 | #ifndef debug_printf_exec |
1222 | #define debug_printf_exec(...) (indent(), fdprintf(2, __VA_ARGS__)) | 1239 | #define debug_printf_exec(...) (indent(), fdprintf(2, __VA_ARGS__)) |
1223 | #endif | 1240 | #endif |
@@ -1557,83 +1574,115 @@ static int xdup_CLOEXEC_and_close(int fd, int avoid_fd) | |||
1557 | } | 1574 | } |
1558 | 1575 | ||
1559 | 1576 | ||
1560 | /* Manipulating the list of open FILEs */ | 1577 | /* Manipulating HFILEs */ |
1561 | static FILE *remember_FILE(FILE *fp) | 1578 | static HFILE *hfopen(const char *name) |
1562 | { | 1579 | { |
1563 | if (fp) { | 1580 | HFILE *fp; |
1564 | struct FILE_list *n = xmalloc(sizeof(*n)); | 1581 | int fd; |
1565 | n->next = G.FILE_list; | 1582 | |
1566 | G.FILE_list = n; | 1583 | fd = STDIN_FILENO; |
1567 | n->fp = fp; | 1584 | if (name) { |
1568 | n->fd = fileno(fp); | 1585 | fd = open(name, O_RDONLY | O_CLOEXEC); |
1569 | close_on_exec_on(n->fd); | 1586 | if (fd < 0) |
1587 | return NULL; | ||
1588 | if (O_CLOEXEC == 0) /* ancient libc */ | ||
1589 | close_on_exec_on(fd); | ||
1570 | } | 1590 | } |
1591 | |||
1592 | fp = xmalloc(sizeof(*fp)); | ||
1593 | fp->is_stdin = (name == NULL); | ||
1594 | fp->fd = fd; | ||
1595 | fp->cur = fp->end = fp->buf; | ||
1596 | fp->next_hfile = G.HFILE_list; | ||
1597 | G.HFILE_list = fp; | ||
1571 | return fp; | 1598 | return fp; |
1572 | } | 1599 | } |
1573 | static void fclose_and_forget(FILE *fp) | 1600 | static void hfclose(HFILE *fp) |
1574 | { | 1601 | { |
1575 | struct FILE_list **pp = &G.FILE_list; | 1602 | HFILE **pp = &G.HFILE_list; |
1576 | while (*pp) { | 1603 | while (*pp) { |
1577 | struct FILE_list *cur = *pp; | 1604 | HFILE *cur = *pp; |
1578 | if (cur->fp == fp) { | 1605 | if (cur == fp) { |
1579 | *pp = cur->next; | 1606 | *pp = cur->next_hfile; |
1580 | free(cur); | ||
1581 | break; | 1607 | break; |
1582 | } | 1608 | } |
1583 | pp = &cur->next; | 1609 | pp = &cur->next_hfile; |
1584 | } | 1610 | } |
1585 | fclose(fp); | 1611 | if (fp->fd >= 0) |
1612 | close(fp->fd); | ||
1613 | free(fp); | ||
1586 | } | 1614 | } |
1587 | static int save_FILEs_on_redirect(int fd, int avoid_fd) | 1615 | static int refill_HFILE_and_getc(HFILE *fp) |
1588 | { | 1616 | { |
1589 | struct FILE_list *fl = G.FILE_list; | 1617 | int n; |
1618 | |||
1619 | if (fp->fd < 0) { | ||
1620 | /* Already saw EOF */ | ||
1621 | return EOF; | ||
1622 | } | ||
1623 | /* Try to buffer more input */ | ||
1624 | fp->cur = fp->buf; | ||
1625 | n = safe_read(fp->fd, fp->buf, sizeof(fp->buf)); | ||
1626 | if (n < 0) { | ||
1627 | bb_perror_msg("read error"); | ||
1628 | n = 0; | ||
1629 | } | ||
1630 | fp->end = fp->buf + n; | ||
1631 | if (n == 0) { | ||
1632 | /* EOF/error */ | ||
1633 | close(fp->fd); | ||
1634 | fp->fd = -1; | ||
1635 | return EOF; | ||
1636 | } | ||
1637 | return (unsigned char)(*fp->cur++); | ||
1638 | } | ||
1639 | /* Inlined for common case of non-empty buffer. | ||
1640 | */ | ||
1641 | static ALWAYS_INLINE int hfgetc(HFILE *fp) | ||
1642 | { | ||
1643 | if (fp->cur < fp->end) | ||
1644 | return (unsigned char)(*fp->cur++); | ||
1645 | /* Buffer empty */ | ||
1646 | return refill_HFILE_and_getc(fp); | ||
1647 | } | ||
1648 | static int move_HFILEs_on_redirect(int fd, int avoid_fd) | ||
1649 | { | ||
1650 | HFILE *fl = G.HFILE_list; | ||
1590 | while (fl) { | 1651 | while (fl) { |
1591 | if (fd == fl->fd) { | 1652 | if (fd == fl->fd) { |
1592 | /* We use it only on script files, they are all CLOEXEC */ | 1653 | /* We use it only on script files, they are all CLOEXEC */ |
1593 | fl->fd = xdup_CLOEXEC_and_close(fd, avoid_fd); | 1654 | fl->fd = xdup_CLOEXEC_and_close(fd, avoid_fd); |
1594 | debug_printf_redir("redirect_fd %d: matches a script fd, moving it to %d\n", fd, fl->fd); | 1655 | debug_printf_redir("redirect_fd %d: matches a script fd, moving it to %d\n", fd, fl->fd); |
1595 | return 1; | 1656 | return 1; /* "found and moved" */ |
1596 | } | 1657 | } |
1597 | fl = fl->next; | 1658 | fl = fl->next_hfile; |
1598 | } | ||
1599 | return 0; | ||
1600 | } | ||
1601 | static void restore_redirected_FILEs(void) | ||
1602 | { | ||
1603 | struct FILE_list *fl = G.FILE_list; | ||
1604 | while (fl) { | ||
1605 | int should_be = fileno(fl->fp); | ||
1606 | if (fl->fd != should_be) { | ||
1607 | debug_printf_redir("restoring script fd from %d to %d\n", fl->fd, should_be); | ||
1608 | xmove_fd(fl->fd, should_be); | ||
1609 | fl->fd = should_be; | ||
1610 | } | ||
1611 | fl = fl->next; | ||
1612 | } | 1659 | } |
1660 | return 0; /* "not in the list" */ | ||
1613 | } | 1661 | } |
1614 | #if ENABLE_FEATURE_SH_STANDALONE && BB_MMU | 1662 | #if ENABLE_FEATURE_SH_STANDALONE && BB_MMU |
1615 | static void close_all_FILE_list(void) | 1663 | static void close_all_HFILE_list(void) |
1616 | { | 1664 | { |
1617 | struct FILE_list *fl = G.FILE_list; | 1665 | HFILE *fl = G.HFILE_list; |
1618 | while (fl) { | 1666 | while (fl) { |
1619 | /* fclose would also free FILE object. | 1667 | /* hfclose would also free HFILE object. |
1620 | * It is disastrous if we share memory with a vforked parent. | 1668 | * It is disastrous if we share memory with a vforked parent. |
1621 | * I'm not sure we never come here after vfork. | 1669 | * I'm not sure we never come here after vfork. |
1622 | * Therefore just close fd, nothing more. | 1670 | * Therefore just close fd, nothing more. |
1623 | */ | 1671 | */ |
1624 | /*fclose(fl->fp); - unsafe */ | 1672 | /*hfclose(fl); - unsafe */ |
1625 | close(fl->fd); | 1673 | if (fl->fd >= 0) |
1626 | fl = fl->next; | 1674 | close(fl->fd); |
1675 | fl = fl->next_hfile; | ||
1627 | } | 1676 | } |
1628 | } | 1677 | } |
1629 | #endif | 1678 | #endif |
1630 | static int fd_in_FILEs(int fd) | 1679 | static int fd_in_HFILEs(int fd) |
1631 | { | 1680 | { |
1632 | struct FILE_list *fl = G.FILE_list; | 1681 | HFILE *fl = G.HFILE_list; |
1633 | while (fl) { | 1682 | while (fl) { |
1634 | if (fl->fd == fd) | 1683 | if (fl->fd == fd) |
1635 | return 1; | 1684 | return 1; |
1636 | fl = fl->next; | 1685 | fl = fl->next_hfile; |
1637 | } | 1686 | } |
1638 | return 0; | 1687 | return 0; |
1639 | } | 1688 | } |
@@ -2333,6 +2382,7 @@ static void set_pwd_var(unsigned flag) | |||
2333 | set_local_var(xasprintf("PWD=%s", get_cwd(/*force:*/ 1)), flag); | 2382 | set_local_var(xasprintf("PWD=%s", get_cwd(/*force:*/ 1)), flag); |
2334 | } | 2383 | } |
2335 | 2384 | ||
2385 | #if ENABLE_HUSH_UNSET || ENABLE_HUSH_GETOPTS | ||
2336 | static int unset_local_var_len(const char *name, int name_len) | 2386 | static int unset_local_var_len(const char *name, int name_len) |
2337 | { | 2387 | { |
2338 | struct variable *cur; | 2388 | struct variable *cur; |
@@ -2366,14 +2416,14 @@ static int unset_local_var_len(const char *name, int name_len) | |||
2366 | return EXIT_SUCCESS; | 2416 | return EXIT_SUCCESS; |
2367 | } | 2417 | } |
2368 | 2418 | ||
2369 | #if ENABLE_HUSH_UNSET || ENABLE_HUSH_GETOPTS | ||
2370 | static int unset_local_var(const char *name) | 2419 | static int unset_local_var(const char *name) |
2371 | { | 2420 | { |
2372 | return unset_local_var_len(name, strlen(name)); | 2421 | return unset_local_var_len(name, strlen(name)); |
2373 | } | 2422 | } |
2374 | #endif | 2423 | #endif |
2375 | 2424 | ||
2376 | #if BASH_HOSTNAME_VAR || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_READ || ENABLE_HUSH_GETOPTS | 2425 | #if BASH_HOSTNAME_VAR || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_READ || ENABLE_HUSH_GETOPTS \ |
2426 | || (ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT) | ||
2377 | static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val) | 2427 | static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val) |
2378 | { | 2428 | { |
2379 | char *var = xasprintf("%s=%s", name, val); | 2429 | char *var = xasprintf("%s=%s", name, val); |
@@ -2422,35 +2472,33 @@ static void set_vars_and_save_old(char **strings) | |||
2422 | char *eq; | 2472 | char *eq; |
2423 | 2473 | ||
2424 | eq = strchr(*s, '='); | 2474 | eq = strchr(*s, '='); |
2425 | if (eq) { | 2475 | if (HUSH_DEBUG && !eq) |
2426 | var_pp = get_ptr_to_local_var(*s, eq - *s); | ||
2427 | if (var_pp) { | ||
2428 | var_p = *var_pp; | ||
2429 | if (var_p->flg_read_only) { | ||
2430 | char **p; | ||
2431 | bb_error_msg("%s: readonly variable", *s); | ||
2432 | /* | ||
2433 | * "VAR=V BLTIN" unsets VARs after BLTIN completes. | ||
2434 | * If VAR is readonly, leaving it in the list | ||
2435 | * after asssignment error (msg above) | ||
2436 | * causes doubled error message later, on unset. | ||
2437 | */ | ||
2438 | debug_printf_env("removing/freeing '%s' element\n", *s); | ||
2439 | free(*s); | ||
2440 | p = s; | ||
2441 | do { *p = p[1]; p++; } while (*p); | ||
2442 | goto next; | ||
2443 | } | ||
2444 | /* below, set_local_var() with nest level will | ||
2445 | * "shadow" (remove) this variable from | ||
2446 | * global linked list. | ||
2447 | */ | ||
2448 | } | ||
2449 | debug_printf_env("%s: env override '%s'/%u\n", __func__, *s, G.var_nest_level); | ||
2450 | set_local_var(*s, (G.var_nest_level << SETFLAG_VARLVL_SHIFT) | SETFLAG_EXPORT); | ||
2451 | } else if (HUSH_DEBUG) { | ||
2452 | bb_error_msg_and_die("BUG in varexp4"); | 2476 | bb_error_msg_and_die("BUG in varexp4"); |
2477 | var_pp = get_ptr_to_local_var(*s, eq - *s); | ||
2478 | if (var_pp) { | ||
2479 | var_p = *var_pp; | ||
2480 | if (var_p->flg_read_only) { | ||
2481 | char **p; | ||
2482 | bb_error_msg("%s: readonly variable", *s); | ||
2483 | /* | ||
2484 | * "VAR=V BLTIN" unsets VARs after BLTIN completes. | ||
2485 | * If VAR is readonly, leaving it in the list | ||
2486 | * after asssignment error (msg above) | ||
2487 | * causes doubled error message later, on unset. | ||
2488 | */ | ||
2489 | debug_printf_env("removing/freeing '%s' element\n", *s); | ||
2490 | free(*s); | ||
2491 | p = s; | ||
2492 | do { *p = p[1]; p++; } while (*p); | ||
2493 | goto next; | ||
2494 | } | ||
2495 | /* below, set_local_var() with nest level will | ||
2496 | * "shadow" (remove) this variable from | ||
2497 | * global linked list. | ||
2498 | */ | ||
2453 | } | 2499 | } |
2500 | debug_printf_env("%s: env override '%s'/%u\n", __func__, *s, G.var_nest_level); | ||
2501 | set_local_var(*s, (G.var_nest_level << SETFLAG_VARLVL_SHIFT) | SETFLAG_EXPORT); | ||
2454 | s++; | 2502 | s++; |
2455 | next: ; | 2503 | next: ; |
2456 | } | 2504 | } |
@@ -2469,7 +2517,7 @@ static void reinit_unicode_for_hush(void) | |||
2469 | */ | 2517 | */ |
2470 | if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV | 2518 | if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV |
2471 | || ENABLE_UNICODE_USING_LOCALE | 2519 | || ENABLE_UNICODE_USING_LOCALE |
2472 | ) { | 2520 | ) { |
2473 | const char *s = get_local_var_value("LC_ALL"); | 2521 | const char *s = get_local_var_value("LC_ALL"); |
2474 | if (!s) s = get_local_var_value("LC_CTYPE"); | 2522 | if (!s) s = get_local_var_value("LC_CTYPE"); |
2475 | if (!s) s = get_local_var_value("LANG"); | 2523 | if (!s) s = get_local_var_value("LANG"); |
@@ -2575,7 +2623,7 @@ static int get_user_input(struct in_str *i) | |||
2575 | } | 2623 | } |
2576 | fflush_all(); | 2624 | fflush_all(); |
2577 | //FIXME: here ^C or SIGINT will have effect only after <Enter> | 2625 | //FIXME: here ^C or SIGINT will have effect only after <Enter> |
2578 | r = fgetc(i->file); | 2626 | r = hfgetc(i->file); |
2579 | /* In !ENABLE_FEATURE_EDITING we don't use read_line_input, | 2627 | /* In !ENABLE_FEATURE_EDITING we don't use read_line_input, |
2580 | * no ^C masking happens during fgetc, no special code for ^C: | 2628 | * no ^C masking happens during fgetc, no special code for ^C: |
2581 | * it generates SIGINT as usual. | 2629 | * it generates SIGINT as usual. |
@@ -2595,22 +2643,22 @@ static int fgetc_interactive(struct in_str *i) | |||
2595 | { | 2643 | { |
2596 | int ch; | 2644 | int ch; |
2597 | /* If it's interactive stdin, get new line. */ | 2645 | /* If it's interactive stdin, get new line. */ |
2598 | if (G_interactive_fd && i->file == stdin) { | 2646 | if (G_interactive_fd && i->file->is_stdin) { |
2599 | /* Returns first char (or EOF), the rest is in i->p[] */ | 2647 | /* Returns first char (or EOF), the rest is in i->p[] */ |
2600 | ch = get_user_input(i); | 2648 | ch = get_user_input(i); |
2601 | G.promptmode = 1; /* PS2 */ | 2649 | G.promptmode = 1; /* PS2 */ |
2602 | debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode); | 2650 | debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode); |
2603 | } else { | 2651 | } else { |
2604 | /* Not stdin: script file, sourced file, etc */ | 2652 | /* Not stdin: script file, sourced file, etc */ |
2605 | do ch = fgetc(i->file); while (ch == '\0'); | 2653 | do ch = hfgetc(i->file); while (ch == '\0'); |
2606 | } | 2654 | } |
2607 | return ch; | 2655 | return ch; |
2608 | } | 2656 | } |
2609 | #else | 2657 | #else |
2610 | static inline int fgetc_interactive(struct in_str *i) | 2658 | static ALWAYS_INLINE int fgetc_interactive(struct in_str *i) |
2611 | { | 2659 | { |
2612 | int ch; | 2660 | int ch; |
2613 | do ch = fgetc(i->file); while (ch == '\0'); | 2661 | do ch = hfgetc(i->file); while (ch == '\0'); |
2614 | return ch; | 2662 | return ch; |
2615 | } | 2663 | } |
2616 | #endif /* INTERACTIVE */ | 2664 | #endif /* INTERACTIVE */ |
@@ -2725,7 +2773,7 @@ static int i_peek2(struct in_str *i) | |||
2725 | ch = i->peek_buf[1]; | 2773 | ch = i->peek_buf[1]; |
2726 | if (ch == 0) { | 2774 | if (ch == 0) { |
2727 | /* We did not read it yet, get it now */ | 2775 | /* We did not read it yet, get it now */ |
2728 | do ch = fgetc(i->file); while (ch == '\0'); | 2776 | do ch = hfgetc(i->file); while (ch == '\0'); |
2729 | i->peek_buf[1] = ch; | 2777 | i->peek_buf[1] = ch; |
2730 | } | 2778 | } |
2731 | 2779 | ||
@@ -2769,10 +2817,10 @@ static int i_peek_and_eat_bkslash_nl(struct in_str *input) | |||
2769 | } | 2817 | } |
2770 | } | 2818 | } |
2771 | 2819 | ||
2772 | static void setup_file_in_str(struct in_str *i, FILE *f) | 2820 | static void setup_file_in_str(struct in_str *i, HFILE *fp) |
2773 | { | 2821 | { |
2774 | memset(i, 0, sizeof(*i)); | 2822 | memset(i, 0, sizeof(*i)); |
2775 | i->file = f; | 2823 | i->file = fp; |
2776 | /* i->p = NULL; */ | 2824 | /* i->p = NULL; */ |
2777 | } | 2825 | } |
2778 | 2826 | ||
@@ -2797,13 +2845,13 @@ static void o_reset_to_empty_unquoted(o_string *o) | |||
2797 | o->data[0] = '\0'; | 2845 | o->data[0] = '\0'; |
2798 | } | 2846 | } |
2799 | 2847 | ||
2800 | static void o_free(o_string *o) | 2848 | static void o_free_and_set_NULL(o_string *o) |
2801 | { | 2849 | { |
2802 | free(o->data); | 2850 | free(o->data); |
2803 | memset(o, 0, sizeof(*o)); | 2851 | memset(o, 0, sizeof(*o)); |
2804 | } | 2852 | } |
2805 | 2853 | ||
2806 | static ALWAYS_INLINE void o_free_unsafe(o_string *o) | 2854 | static ALWAYS_INLINE void o_free(o_string *o) |
2807 | { | 2855 | { |
2808 | free(o->data); | 2856 | free(o->data); |
2809 | } | 2857 | } |
@@ -3342,7 +3390,6 @@ static char **o_finalize_list(o_string *o, int n) | |||
3342 | char **list; | 3390 | char **list; |
3343 | int string_start; | 3391 | int string_start; |
3344 | 3392 | ||
3345 | n = o_save_ptr(o, n); /* force growth for list[n] if necessary */ | ||
3346 | if (DEBUG_EXPAND) | 3393 | if (DEBUG_EXPAND) |
3347 | debug_print_list("finalized", o, n); | 3394 | debug_print_list("finalized", o, n); |
3348 | debug_printf_expand("finalized n:%d\n", n); | 3395 | debug_printf_expand("finalized n:%d\n", n); |
@@ -3530,6 +3577,8 @@ static void debug_print_tree(struct pipe *pi, int lvl) | |||
3530 | fdprintf(2, " '%s'", *argv); | 3577 | fdprintf(2, " '%s'", *argv); |
3531 | argv++; | 3578 | argv++; |
3532 | } | 3579 | } |
3580 | if (command->redirects) | ||
3581 | fdprintf(2, " {redir}"); | ||
3533 | fdprintf(2, "\n"); | 3582 | fdprintf(2, "\n"); |
3534 | prn++; | 3583 | prn++; |
3535 | } | 3584 | } |
@@ -3853,7 +3902,7 @@ static const struct reserved_combo* reserved_word(struct parse_context *ctx) | |||
3853 | int len = old->as_string.length; | 3902 | int len = old->as_string.length; |
3854 | /* Concatenate halves */ | 3903 | /* Concatenate halves */ |
3855 | o_addstr(&old->as_string, ctx->as_string.data); | 3904 | o_addstr(&old->as_string, ctx->as_string.data); |
3856 | o_free_unsafe(&ctx->as_string); | 3905 | o_free(&ctx->as_string); |
3857 | /* Find where leading keyword starts in first half */ | 3906 | /* Find where leading keyword starts in first half */ |
3858 | str = old->as_string.data + len; | 3907 | str = old->as_string.data + len; |
3859 | if (str > old->as_string.data) | 3908 | if (str > old->as_string.data) |
@@ -4227,6 +4276,14 @@ static char *fetch_till_str(o_string *as_string, | |||
4227 | int prev = 0; /* not \ */ | 4276 | int prev = 0; /* not \ */ |
4228 | int ch; | 4277 | int ch; |
4229 | 4278 | ||
4279 | /* Starting with "" is necessary for this case: | ||
4280 | * cat <<EOF | ||
4281 | * | ||
4282 | * xxx | ||
4283 | * EOF | ||
4284 | */ | ||
4285 | heredoc.data = xzalloc(1); /* start as "", not as NULL */ | ||
4286 | |||
4230 | goto jump_in; | 4287 | goto jump_in; |
4231 | 4288 | ||
4232 | while (1) { | 4289 | while (1) { |
@@ -4236,9 +4293,10 @@ static char *fetch_till_str(o_string *as_string, | |||
4236 | if (ch == '\n' || ch == EOF) { | 4293 | if (ch == '\n' || ch == EOF) { |
4237 | check_heredoc_end: | 4294 | check_heredoc_end: |
4238 | if ((heredoc_flags & HEREDOC_QUOTED) || prev != '\\') { | 4295 | if ((heredoc_flags & HEREDOC_QUOTED) || prev != '\\') { |
4296 | /* End-of-line, and not a line continuation */ | ||
4239 | if (strcmp(heredoc.data + past_EOL, word) == 0) { | 4297 | if (strcmp(heredoc.data + past_EOL, word) == 0) { |
4240 | heredoc.data[past_EOL] = '\0'; | 4298 | heredoc.data[past_EOL] = '\0'; |
4241 | debug_printf_parse("parsed heredoc '%s'\n", heredoc.data); | 4299 | debug_printf_heredoc("parsed '%s' heredoc '%s'\n", word, heredoc.data); |
4242 | return heredoc.data; | 4300 | return heredoc.data; |
4243 | } | 4301 | } |
4244 | if (ch == '\n') { | 4302 | if (ch == '\n') { |
@@ -4261,17 +4319,32 @@ static char *fetch_till_str(o_string *as_string, | |||
4261 | if (ch == '\n') | 4319 | if (ch == '\n') |
4262 | goto check_heredoc_end; | 4320 | goto check_heredoc_end; |
4263 | } | 4321 | } |
4322 | } else { | ||
4323 | /* Backslash-line continuation in an unquoted | ||
4324 | * heredoc. This does not need special handling | ||
4325 | * for heredoc body (unquoted heredocs are | ||
4326 | * expanded on "execution" and that would take | ||
4327 | * care of this case too), but not the case | ||
4328 | * of line continuation *in terminator*: | ||
4329 | * cat <<EOF | ||
4330 | * Ok1 | ||
4331 | * EO\ | ||
4332 | * F | ||
4333 | */ | ||
4334 | heredoc.data[--heredoc.length] = '\0'; | ||
4335 | prev = 0; /* not '\' */ | ||
4336 | continue; | ||
4264 | } | 4337 | } |
4265 | } | 4338 | } |
4266 | if (ch == EOF) { | 4339 | if (ch == EOF) { |
4267 | o_free_unsafe(&heredoc); | 4340 | o_free(&heredoc); |
4268 | return NULL; | 4341 | return NULL; /* error */ |
4269 | } | 4342 | } |
4270 | o_addchr(&heredoc, ch); | 4343 | o_addchr(&heredoc, ch); |
4271 | nommu_addchr(as_string, ch); | 4344 | nommu_addchr(as_string, ch); |
4272 | if (prev == '\\' && ch == '\\') | 4345 | if (prev == '\\' && ch == '\\') |
4273 | /* Correctly handle foo\\<eol> (not a line cont.) */ | 4346 | /* Correctly handle foo\\<eol> (not a line cont.) */ |
4274 | prev = 0; /* not \ */ | 4347 | prev = 0; /* not '\' */ |
4275 | else | 4348 | else |
4276 | prev = ch; | 4349 | prev = ch; |
4277 | } | 4350 | } |
@@ -4280,21 +4353,24 @@ static char *fetch_till_str(o_string *as_string, | |||
4280 | /* Look at entire parse tree for not-yet-loaded REDIRECT_HEREDOCs | 4353 | /* Look at entire parse tree for not-yet-loaded REDIRECT_HEREDOCs |
4281 | * and load them all. There should be exactly heredoc_cnt of them. | 4354 | * and load them all. There should be exactly heredoc_cnt of them. |
4282 | */ | 4355 | */ |
4283 | static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_str *input) | 4356 | #if BB_MMU |
4357 | #define fetch_heredocs(as_string, pi, heredoc_cnt, input) \ | ||
4358 | fetch_heredocs(pi, heredoc_cnt, input) | ||
4359 | #endif | ||
4360 | static int fetch_heredocs(o_string *as_string, struct pipe *pi, int heredoc_cnt, struct in_str *input) | ||
4284 | { | 4361 | { |
4285 | struct pipe *pi = ctx->list_head; | ||
4286 | |||
4287 | while (pi && heredoc_cnt) { | 4362 | while (pi && heredoc_cnt) { |
4288 | int i; | 4363 | int i; |
4289 | struct command *cmd = pi->cmds; | 4364 | struct command *cmd = pi->cmds; |
4290 | 4365 | ||
4291 | debug_printf_parse("fetch_heredocs: num_cmds:%d cmd argv0:'%s'\n", | 4366 | debug_printf_heredoc("fetch_heredocs: num_cmds:%d cmd argv0:'%s'\n", |
4292 | pi->num_cmds, | 4367 | pi->num_cmds, |
4293 | cmd->argv ? cmd->argv[0] : "NONE"); | 4368 | cmd->argv ? cmd->argv[0] : "NONE" |
4369 | ); | ||
4294 | for (i = 0; i < pi->num_cmds; i++) { | 4370 | for (i = 0; i < pi->num_cmds; i++) { |
4295 | struct redir_struct *redir = cmd->redirects; | 4371 | struct redir_struct *redir = cmd->redirects; |
4296 | 4372 | ||
4297 | debug_printf_parse("fetch_heredocs: %d cmd argv0:'%s'\n", | 4373 | debug_printf_heredoc("fetch_heredocs: %d cmd argv0:'%s'\n", |
4298 | i, cmd->argv ? cmd->argv[0] : "NONE"); | 4374 | i, cmd->argv ? cmd->argv[0] : "NONE"); |
4299 | while (redir) { | 4375 | while (redir) { |
4300 | if (redir->rd_type == REDIRECT_HEREDOC) { | 4376 | if (redir->rd_type == REDIRECT_HEREDOC) { |
@@ -4302,11 +4378,11 @@ static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_ | |||
4302 | 4378 | ||
4303 | redir->rd_type = REDIRECT_HEREDOC2; | 4379 | redir->rd_type = REDIRECT_HEREDOC2; |
4304 | /* redir->rd_dup is (ab)used to indicate <<- */ | 4380 | /* redir->rd_dup is (ab)used to indicate <<- */ |
4305 | p = fetch_till_str(&ctx->as_string, input, | 4381 | p = fetch_till_str(as_string, input, |
4306 | redir->rd_filename, redir->rd_dup); | 4382 | redir->rd_filename, redir->rd_dup); |
4307 | if (!p) { | 4383 | if (!p) { |
4308 | syntax_error("unexpected EOF in here document"); | 4384 | syntax_error("unexpected EOF in here document"); |
4309 | return 1; | 4385 | return -1; |
4310 | } | 4386 | } |
4311 | free(redir->rd_filename); | 4387 | free(redir->rd_filename); |
4312 | redir->rd_filename = p; | 4388 | redir->rd_filename = p; |
@@ -4314,31 +4390,36 @@ static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_ | |||
4314 | } | 4390 | } |
4315 | redir = redir->next; | 4391 | redir = redir->next; |
4316 | } | 4392 | } |
4393 | if (cmd->group) { | ||
4394 | //bb_error_msg("%s:%u heredoc_cnt:%d", __func__, __LINE__, heredoc_cnt); | ||
4395 | heredoc_cnt = fetch_heredocs(as_string, cmd->group, heredoc_cnt, input); | ||
4396 | //bb_error_msg("%s:%u heredoc_cnt:%d", __func__, __LINE__, heredoc_cnt); | ||
4397 | if (heredoc_cnt < 0) | ||
4398 | return heredoc_cnt; /* error */ | ||
4399 | } | ||
4317 | cmd++; | 4400 | cmd++; |
4318 | } | 4401 | } |
4319 | pi = pi->next; | 4402 | pi = pi->next; |
4320 | } | 4403 | } |
4321 | #if 0 | 4404 | return heredoc_cnt; |
4322 | /* Should be 0. If it isn't, it's a parse error */ | ||
4323 | if (heredoc_cnt) | ||
4324 | bb_error_msg_and_die("heredoc BUG 2"); | ||
4325 | #endif | ||
4326 | return 0; | ||
4327 | } | 4405 | } |
4328 | 4406 | ||
4329 | 4407 | ||
4330 | static int run_list(struct pipe *pi); | 4408 | static int run_list(struct pipe *pi); |
4331 | #if BB_MMU | 4409 | #if BB_MMU |
4332 | #define parse_stream(pstring, input, end_trigger) \ | 4410 | #define parse_stream(pstring, heredoc_cnt_ptr, input, end_trigger) \ |
4333 | parse_stream(input, end_trigger) | 4411 | parse_stream(heredoc_cnt_ptr, input, end_trigger) |
4334 | #endif | 4412 | #endif |
4335 | static struct pipe *parse_stream(char **pstring, | 4413 | static struct pipe *parse_stream(char **pstring, |
4414 | int *heredoc_cnt_ptr, | ||
4336 | struct in_str *input, | 4415 | struct in_str *input, |
4337 | int end_trigger); | 4416 | int end_trigger); |
4338 | 4417 | ||
4339 | 4418 | /* Returns number of heredocs not yet consumed, | |
4419 | * or -1 on error. | ||
4420 | */ | ||
4340 | static int parse_group(struct parse_context *ctx, | 4421 | static int parse_group(struct parse_context *ctx, |
4341 | struct in_str *input, int ch) | 4422 | struct in_str *input, int ch) |
4342 | { | 4423 | { |
4343 | /* ctx->word contains characters seen prior to ( or {. | 4424 | /* ctx->word contains characters seen prior to ( or {. |
4344 | * Typically it's empty, but for function defs, | 4425 | * Typically it's empty, but for function defs, |
@@ -4349,6 +4430,7 @@ static int parse_group(struct parse_context *ctx, | |||
4349 | char *as_string = NULL; | 4430 | char *as_string = NULL; |
4350 | #endif | 4431 | #endif |
4351 | struct pipe *pipe_list; | 4432 | struct pipe *pipe_list; |
4433 | int heredoc_cnt = 0; | ||
4352 | int endch; | 4434 | int endch; |
4353 | struct command *command = ctx->command; | 4435 | struct command *command = ctx->command; |
4354 | 4436 | ||
@@ -4357,12 +4439,12 @@ static int parse_group(struct parse_context *ctx, | |||
4357 | if (ch == '(' && !ctx->word.has_quoted_part) { | 4439 | if (ch == '(' && !ctx->word.has_quoted_part) { |
4358 | if (ctx->word.length) | 4440 | if (ctx->word.length) |
4359 | if (done_word(ctx)) | 4441 | if (done_word(ctx)) |
4360 | return 1; | 4442 | return -1; |
4361 | if (!command->argv) | 4443 | if (!command->argv) |
4362 | goto skip; /* (... */ | 4444 | goto skip; /* (... */ |
4363 | if (command->argv[1]) { /* word word ... (... */ | 4445 | if (command->argv[1]) { /* word word ... (... */ |
4364 | syntax_error_unexpected_ch('('); | 4446 | syntax_error_unexpected_ch('('); |
4365 | return 1; | 4447 | return -1; |
4366 | } | 4448 | } |
4367 | /* it is "word(..." or "word (..." */ | 4449 | /* it is "word(..." or "word (..." */ |
4368 | do | 4450 | do |
@@ -4370,7 +4452,7 @@ static int parse_group(struct parse_context *ctx, | |||
4370 | while (ch == ' ' || ch == '\t'); | 4452 | while (ch == ' ' || ch == '\t'); |
4371 | if (ch != ')') { | 4453 | if (ch != ')') { |
4372 | syntax_error_unexpected_ch(ch); | 4454 | syntax_error_unexpected_ch(ch); |
4373 | return 1; | 4455 | return -1; |
4374 | } | 4456 | } |
4375 | nommu_addchr(&ctx->as_string, ch); | 4457 | nommu_addchr(&ctx->as_string, ch); |
4376 | do | 4458 | do |
@@ -4378,7 +4460,7 @@ static int parse_group(struct parse_context *ctx, | |||
4378 | while (ch == ' ' || ch == '\t' || ch == '\n'); | 4460 | while (ch == ' ' || ch == '\t' || ch == '\n'); |
4379 | if (ch != '{' && ch != '(') { | 4461 | if (ch != '{' && ch != '(') { |
4380 | syntax_error_unexpected_ch(ch); | 4462 | syntax_error_unexpected_ch(ch); |
4381 | return 1; | 4463 | return -1; |
4382 | } | 4464 | } |
4383 | nommu_addchr(&ctx->as_string, ch); | 4465 | nommu_addchr(&ctx->as_string, ch); |
4384 | command->cmd_type = CMD_FUNCDEF; | 4466 | command->cmd_type = CMD_FUNCDEF; |
@@ -4392,9 +4474,9 @@ static int parse_group(struct parse_context *ctx, | |||
4392 | || ctx->word.has_quoted_part /* ""{... */ | 4474 | || ctx->word.has_quoted_part /* ""{... */ |
4393 | ) { | 4475 | ) { |
4394 | syntax_error(NULL); | 4476 | syntax_error(NULL); |
4395 | debug_printf_parse("parse_group return 1: " | 4477 | debug_printf_parse("parse_group return -1: " |
4396 | "syntax error, groups and arglists don't mix\n"); | 4478 | "syntax error, groups and arglists don't mix\n"); |
4397 | return 1; | 4479 | return -1; |
4398 | } | 4480 | } |
4399 | #endif | 4481 | #endif |
4400 | 4482 | ||
@@ -4412,7 +4494,7 @@ static int parse_group(struct parse_context *ctx, | |||
4412 | && ch != '(' /* but "{(..." is allowed (without whitespace) */ | 4494 | && ch != '(' /* but "{(..." is allowed (without whitespace) */ |
4413 | ) { | 4495 | ) { |
4414 | syntax_error_unexpected_ch(ch); | 4496 | syntax_error_unexpected_ch(ch); |
4415 | return 1; | 4497 | return -1; |
4416 | } | 4498 | } |
4417 | if (ch != '(') { | 4499 | if (ch != '(') { |
4418 | ch = i_getch(input); | 4500 | ch = i_getch(input); |
@@ -4420,7 +4502,9 @@ static int parse_group(struct parse_context *ctx, | |||
4420 | } | 4502 | } |
4421 | } | 4503 | } |
4422 | 4504 | ||
4423 | pipe_list = parse_stream(&as_string, input, endch); | 4505 | debug_printf_heredoc("calling parse_stream, heredoc_cnt:%d\n", heredoc_cnt); |
4506 | pipe_list = parse_stream(&as_string, &heredoc_cnt, input, endch); | ||
4507 | debug_printf_heredoc("parse_stream returned: heredoc_cnt:%d\n", heredoc_cnt); | ||
4424 | #if !BB_MMU | 4508 | #if !BB_MMU |
4425 | if (as_string) | 4509 | if (as_string) |
4426 | o_addstr(&ctx->as_string, as_string); | 4510 | o_addstr(&ctx->as_string, as_string); |
@@ -4431,9 +4515,9 @@ static int parse_group(struct parse_context *ctx, | |||
4431 | /* parse_stream already emitted error msg */ | 4515 | /* parse_stream already emitted error msg */ |
4432 | if (!BB_MMU) | 4516 | if (!BB_MMU) |
4433 | free(as_string); | 4517 | free(as_string); |
4434 | debug_printf_parse("parse_group return 1: " | 4518 | debug_printf_parse("parse_group return -1: " |
4435 | "parse_stream returned %p\n", pipe_list); | 4519 | "parse_stream returned %p\n", pipe_list); |
4436 | return 1; | 4520 | return -1; |
4437 | } | 4521 | } |
4438 | #if !BB_MMU | 4522 | #if !BB_MMU |
4439 | as_string[strlen(as_string) - 1] = '\0'; /* plink ')' or '}' */ | 4523 | as_string[strlen(as_string) - 1] = '\0'; /* plink ')' or '}' */ |
@@ -4464,15 +4548,14 @@ static int parse_group(struct parse_context *ctx, | |||
4464 | 4548 | ||
4465 | command->group = pipe_list; | 4549 | command->group = pipe_list; |
4466 | 4550 | ||
4467 | debug_printf_parse("parse_group return 0\n"); | 4551 | debug_printf_parse("parse_group return %d\n", heredoc_cnt); |
4468 | return 0; | 4552 | return heredoc_cnt; |
4469 | /* command remains "open", available for possible redirects */ | 4553 | /* command remains "open", available for possible redirects */ |
4470 | #undef as_string | 4554 | #undef as_string |
4471 | } | 4555 | } |
4472 | 4556 | ||
4473 | #if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS | 4557 | #if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS |
4474 | /* Subroutines for copying $(...) and `...` things */ | 4558 | /* Subroutines for copying $(...) and `...` things */ |
4475 | static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote); | ||
4476 | /* '...' */ | 4559 | /* '...' */ |
4477 | static int add_till_single_quote(o_string *dest, struct in_str *input) | 4560 | static int add_till_single_quote(o_string *dest, struct in_str *input) |
4478 | { | 4561 | { |
@@ -4487,7 +4570,21 @@ static int add_till_single_quote(o_string *dest, struct in_str *input) | |||
4487 | o_addchr(dest, ch); | 4570 | o_addchr(dest, ch); |
4488 | } | 4571 | } |
4489 | } | 4572 | } |
4573 | static int add_till_single_quote_dquoted(o_string *dest, struct in_str *input) | ||
4574 | { | ||
4575 | while (1) { | ||
4576 | int ch = i_getch(input); | ||
4577 | if (ch == EOF) { | ||
4578 | syntax_error_unterm_ch('\''); | ||
4579 | return 0; | ||
4580 | } | ||
4581 | if (ch == '\'') | ||
4582 | return 1; | ||
4583 | o_addqchr(dest, ch); | ||
4584 | } | ||
4585 | } | ||
4490 | /* "...\"...`..`...." - do we need to handle "...$(..)..." too? */ | 4586 | /* "...\"...`..`...." - do we need to handle "...$(..)..." too? */ |
4587 | static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote); | ||
4491 | static int add_till_double_quote(o_string *dest, struct in_str *input) | 4588 | static int add_till_double_quote(o_string *dest, struct in_str *input) |
4492 | { | 4589 | { |
4493 | while (1) { | 4590 | while (1) { |
@@ -4577,7 +4674,9 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign | |||
4577 | # endif | 4674 | # endif |
4578 | end_ch &= (DOUBLE_CLOSE_CHAR_FLAG - 1); | 4675 | end_ch &= (DOUBLE_CLOSE_CHAR_FLAG - 1); |
4579 | 4676 | ||
4677 | #if ENABLE_HUSH_INTERACTIVE | ||
4580 | G.promptmode = 1; /* PS2 */ | 4678 | G.promptmode = 1; /* PS2 */ |
4679 | #endif | ||
4581 | debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode); | 4680 | debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode); |
4582 | 4681 | ||
4583 | while (1) { | 4682 | while (1) { |
@@ -4885,34 +4984,15 @@ static int parse_dollar(o_string *as_string, | |||
4885 | } | 4984 | } |
4886 | 4985 | ||
4887 | #if BB_MMU | 4986 | #if BB_MMU |
4888 | # if BASH_PATTERN_SUBST | 4987 | #define encode_string(as_string, dest, input, dquote_end) \ |
4889 | #define encode_string(as_string, dest, input, dquote_end, process_bkslash) \ | ||
4890 | encode_string(dest, input, dquote_end, process_bkslash) | ||
4891 | # else | ||
4892 | /* only ${var/pattern/repl} (its pattern part) needs additional mode */ | ||
4893 | #define encode_string(as_string, dest, input, dquote_end, process_bkslash) \ | ||
4894 | encode_string(dest, input, dquote_end) | 4988 | encode_string(dest, input, dquote_end) |
4895 | # endif | ||
4896 | #define as_string NULL | 4989 | #define as_string NULL |
4897 | |||
4898 | #else /* !MMU */ | ||
4899 | |||
4900 | # if BASH_PATTERN_SUBST | ||
4901 | /* all parameters are needed, no macro tricks */ | ||
4902 | # else | ||
4903 | #define encode_string(as_string, dest, input, dquote_end, process_bkslash) \ | ||
4904 | encode_string(as_string, dest, input, dquote_end) | ||
4905 | # endif | ||
4906 | #endif | 4990 | #endif |
4907 | static int encode_string(o_string *as_string, | 4991 | static int encode_string(o_string *as_string, |
4908 | o_string *dest, | 4992 | o_string *dest, |
4909 | struct in_str *input, | 4993 | struct in_str *input, |
4910 | int dquote_end, | 4994 | int dquote_end) |
4911 | int process_bkslash) | ||
4912 | { | 4995 | { |
4913 | #if !BASH_PATTERN_SUBST | ||
4914 | const int process_bkslash = 1; | ||
4915 | #endif | ||
4916 | int ch; | 4996 | int ch; |
4917 | int next; | 4997 | int next; |
4918 | 4998 | ||
@@ -4935,7 +5015,7 @@ static int encode_string(o_string *as_string, | |||
4935 | } | 5015 | } |
4936 | debug_printf_parse("\" ch=%c (%d) escape=%d\n", | 5016 | debug_printf_parse("\" ch=%c (%d) escape=%d\n", |
4937 | ch, ch, !!(dest->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); | 5017 | ch, ch, !!(dest->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); |
4938 | if (process_bkslash && ch == '\\') { | 5018 | if (ch == '\\') { |
4939 | if (next == EOF) { | 5019 | if (next == EOF) { |
4940 | /* Testcase: in interactive shell a file with | 5020 | /* Testcase: in interactive shell a file with |
4941 | * echo "unterminated string\<eof> | 5021 | * echo "unterminated string\<eof> |
@@ -4995,6 +5075,7 @@ static int encode_string(o_string *as_string, | |||
4995 | * or return ERR_PTR. | 5075 | * or return ERR_PTR. |
4996 | */ | 5076 | */ |
4997 | static struct pipe *parse_stream(char **pstring, | 5077 | static struct pipe *parse_stream(char **pstring, |
5078 | int *heredoc_cnt_ptr, | ||
4998 | struct in_str *input, | 5079 | struct in_str *input, |
4999 | int end_trigger) | 5080 | int end_trigger) |
5000 | { | 5081 | { |
@@ -5013,8 +5094,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5013 | /* If very first arg is "" or '', ctx.word.data may end up NULL. | 5094 | /* If very first arg is "" or '', ctx.word.data may end up NULL. |
5014 | * Preventing this: | 5095 | * Preventing this: |
5015 | */ | 5096 | */ |
5016 | o_addchr(&ctx.word, '\0'); | 5097 | ctx.word.data = xzalloc(1); /* start as "", not as NULL */ |
5017 | ctx.word.length = 0; | ||
5018 | 5098 | ||
5019 | /* We used to separate words on $IFS here. This was wrong. | 5099 | /* We used to separate words on $IFS here. This was wrong. |
5020 | * $IFS is used only for word splitting when $var is expanded, | 5100 | * $IFS is used only for word splitting when $var is expanded, |
@@ -5052,7 +5132,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5052 | if (done_word(&ctx)) { | 5132 | if (done_word(&ctx)) { |
5053 | goto parse_error; | 5133 | goto parse_error; |
5054 | } | 5134 | } |
5055 | o_free(&ctx.word); | 5135 | o_free_and_set_NULL(&ctx.word); |
5056 | done_pipe(&ctx, PIPE_SEQ); | 5136 | done_pipe(&ctx, PIPE_SEQ); |
5057 | pi = ctx.list_head; | 5137 | pi = ctx.list_head; |
5058 | /* If we got nothing... */ | 5138 | /* If we got nothing... */ |
@@ -5069,9 +5149,13 @@ static struct pipe *parse_stream(char **pstring, | |||
5069 | if (pstring) | 5149 | if (pstring) |
5070 | *pstring = ctx.as_string.data; | 5150 | *pstring = ctx.as_string.data; |
5071 | else | 5151 | else |
5072 | o_free_unsafe(&ctx.as_string); | 5152 | o_free(&ctx.as_string); |
5073 | #endif | 5153 | #endif |
5154 | // heredoc_cnt must be 0 here anyway | ||
5155 | //if (heredoc_cnt_ptr) | ||
5156 | // *heredoc_cnt_ptr = heredoc_cnt; | ||
5074 | debug_leave(); | 5157 | debug_leave(); |
5158 | debug_printf_heredoc("parse_stream return heredoc_cnt:%d\n", heredoc_cnt); | ||
5075 | debug_printf_parse("parse_stream return %p\n", pi); | 5159 | debug_printf_parse("parse_stream return %p\n", pi); |
5076 | return pi; | 5160 | return pi; |
5077 | } | 5161 | } |
@@ -5198,7 +5282,9 @@ static struct pipe *parse_stream(char **pstring, | |||
5198 | * "case ... in <newline> word) ..." | 5282 | * "case ... in <newline> word) ..." |
5199 | */ | 5283 | */ |
5200 | if (IS_NULL_CMD(ctx.command) | 5284 | if (IS_NULL_CMD(ctx.command) |
5201 | && ctx.word.length == 0 && !ctx.word.has_quoted_part | 5285 | && ctx.word.length == 0 |
5286 | && !ctx.word.has_quoted_part | ||
5287 | && heredoc_cnt == 0 | ||
5202 | ) { | 5288 | ) { |
5203 | /* This newline can be ignored. But... | 5289 | /* This newline can be ignored. But... |
5204 | * Without check #1, interactive shell | 5290 | * Without check #1, interactive shell |
@@ -5226,12 +5312,11 @@ static struct pipe *parse_stream(char **pstring, | |||
5226 | } | 5312 | } |
5227 | /* Treat newline as a command separator. */ | 5313 | /* Treat newline as a command separator. */ |
5228 | done_pipe(&ctx, PIPE_SEQ); | 5314 | done_pipe(&ctx, PIPE_SEQ); |
5229 | debug_printf_parse("heredoc_cnt:%d\n", heredoc_cnt); | 5315 | debug_printf_heredoc("heredoc_cnt:%d\n", heredoc_cnt); |
5230 | if (heredoc_cnt) { | 5316 | if (heredoc_cnt) { |
5231 | if (fetch_heredocs(heredoc_cnt, &ctx, input)) { | 5317 | heredoc_cnt = fetch_heredocs(&ctx.as_string, ctx.list_head, heredoc_cnt, input); |
5318 | if (heredoc_cnt != 0) | ||
5232 | goto parse_error; | 5319 | goto parse_error; |
5233 | } | ||
5234 | heredoc_cnt = 0; | ||
5235 | } | 5320 | } |
5236 | ctx.is_assignment = MAYBE_ASSIGNMENT; | 5321 | ctx.is_assignment = MAYBE_ASSIGNMENT; |
5237 | debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]); | 5322 | debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]); |
@@ -5280,19 +5365,6 @@ static struct pipe *parse_stream(char **pstring, | |||
5280 | ) | 5365 | ) |
5281 | #endif | 5366 | #endif |
5282 | ) { | 5367 | ) { |
5283 | if (heredoc_cnt) { | ||
5284 | /* This is technically valid: | ||
5285 | * { cat <<HERE; }; echo Ok | ||
5286 | * heredoc | ||
5287 | * heredoc | ||
5288 | * HERE | ||
5289 | * but we don't support this. | ||
5290 | * We require heredoc to be in enclosing {}/(), | ||
5291 | * if any. | ||
5292 | */ | ||
5293 | syntax_error_unterm_str("here document"); | ||
5294 | goto parse_error; | ||
5295 | } | ||
5296 | if (done_word(&ctx)) { | 5368 | if (done_word(&ctx)) { |
5297 | goto parse_error; | 5369 | goto parse_error; |
5298 | } | 5370 | } |
@@ -5303,13 +5375,13 @@ static struct pipe *parse_stream(char **pstring, | |||
5303 | if (!HAS_KEYWORDS | 5375 | if (!HAS_KEYWORDS |
5304 | IF_HAS_KEYWORDS(|| (ctx.ctx_res_w == RES_NONE && ctx.old_flag == 0)) | 5376 | IF_HAS_KEYWORDS(|| (ctx.ctx_res_w == RES_NONE && ctx.old_flag == 0)) |
5305 | ) { | 5377 | ) { |
5306 | o_free(&ctx.word); | 5378 | o_free_and_set_NULL(&ctx.word); |
5307 | #if !BB_MMU | 5379 | #if !BB_MMU |
5308 | debug_printf_parse("as_string2 '%s'\n", ctx.as_string.data); | 5380 | debug_printf_parse("as_string2 '%s'\n", ctx.as_string.data); |
5309 | if (pstring) | 5381 | if (pstring) |
5310 | *pstring = ctx.as_string.data; | 5382 | *pstring = ctx.as_string.data; |
5311 | else | 5383 | else |
5312 | o_free_unsafe(&ctx.as_string); | 5384 | o_free(&ctx.as_string); |
5313 | #endif | 5385 | #endif |
5314 | if (ch != ';' && IS_NULL_PIPE(ctx.list_head)) { | 5386 | if (ch != ';' && IS_NULL_PIPE(ctx.list_head)) { |
5315 | /* Example: bare "{ }", "()" */ | 5387 | /* Example: bare "{ }", "()" */ |
@@ -5317,6 +5389,9 @@ static struct pipe *parse_stream(char **pstring, | |||
5317 | syntax_error_unexpected_ch(ch); | 5389 | syntax_error_unexpected_ch(ch); |
5318 | goto parse_error2; | 5390 | goto parse_error2; |
5319 | } | 5391 | } |
5392 | if (heredoc_cnt_ptr) | ||
5393 | *heredoc_cnt_ptr = heredoc_cnt; | ||
5394 | debug_printf_heredoc("parse_stream return heredoc_cnt:%d\n", heredoc_cnt); | ||
5320 | debug_printf_parse("parse_stream return %p: " | 5395 | debug_printf_parse("parse_stream return %p: " |
5321 | "end_trigger char found\n", | 5396 | "end_trigger char found\n", |
5322 | ctx.list_head); | 5397 | ctx.list_head); |
@@ -5360,7 +5435,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5360 | if (next == '<') { | 5435 | if (next == '<') { |
5361 | redir_style = REDIRECT_HEREDOC; | 5436 | redir_style = REDIRECT_HEREDOC; |
5362 | heredoc_cnt++; | 5437 | heredoc_cnt++; |
5363 | debug_printf_parse("++heredoc_cnt=%d\n", heredoc_cnt); | 5438 | debug_printf_heredoc("++heredoc_cnt=%d\n", heredoc_cnt); |
5364 | ch = i_getch(input); | 5439 | ch = i_getch(input); |
5365 | nommu_addchr(&ctx.as_string, ch); | 5440 | nommu_addchr(&ctx.as_string, ch); |
5366 | } else if (next == '>') { | 5441 | } else if (next == '>') { |
@@ -5444,7 +5519,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5444 | } | 5519 | } |
5445 | if (ctx.is_assignment == NOT_ASSIGNMENT) | 5520 | if (ctx.is_assignment == NOT_ASSIGNMENT) |
5446 | ctx.word.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS; | 5521 | ctx.word.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS; |
5447 | if (!encode_string(&ctx.as_string, &ctx.word, input, '"', /*process_bkslash:*/ 1)) | 5522 | if (!encode_string(&ctx.as_string, &ctx.word, input, '"')) |
5448 | goto parse_error; | 5523 | goto parse_error; |
5449 | ctx.word.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS; | 5524 | ctx.word.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS; |
5450 | continue; /* get next char */ | 5525 | continue; /* get next char */ |
@@ -5538,16 +5613,22 @@ static struct pipe *parse_stream(char **pstring, | |||
5538 | continue; /* get next char */ | 5613 | continue; /* get next char */ |
5539 | } | 5614 | } |
5540 | #endif | 5615 | #endif |
5541 | case '{': | 5616 | /* fall through */ |
5542 | if (parse_group(&ctx, input, ch) != 0) { | 5617 | case '{': { |
5618 | int n = parse_group(&ctx, input, ch); | ||
5619 | if (n < 0) { | ||
5543 | goto parse_error; | 5620 | goto parse_error; |
5544 | } | 5621 | } |
5622 | debug_printf_heredoc("parse_group done, needs heredocs:%d\n", n); | ||
5623 | heredoc_cnt += n; | ||
5545 | goto new_cmd; | 5624 | goto new_cmd; |
5625 | } | ||
5546 | case ')': | 5626 | case ')': |
5547 | #if ENABLE_HUSH_CASE | 5627 | #if ENABLE_HUSH_CASE |
5548 | if (ctx.ctx_res_w == RES_MATCH) | 5628 | if (ctx.ctx_res_w == RES_MATCH) |
5549 | goto case_semi; | 5629 | goto case_semi; |
5550 | #endif | 5630 | #endif |
5631 | |||
5551 | case '}': | 5632 | case '}': |
5552 | /* proper use of this character is caught by end_trigger: | 5633 | /* proper use of this character is caught by end_trigger: |
5553 | * if we see {, we call parse_group(..., end_trigger='}') | 5634 | * if we see {, we call parse_group(..., end_trigger='}') |
@@ -5587,7 +5668,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5587 | free_pipe_list(pctx->list_head); | 5668 | free_pipe_list(pctx->list_head); |
5588 | debug_printf_clean("freed list %p\n", pctx->list_head); | 5669 | debug_printf_clean("freed list %p\n", pctx->list_head); |
5589 | #if !BB_MMU | 5670 | #if !BB_MMU |
5590 | o_free_unsafe(&pctx->as_string); | 5671 | o_free(&pctx->as_string); |
5591 | #endif | 5672 | #endif |
5592 | IF_HAS_KEYWORDS(p2 = pctx->stack;) | 5673 | IF_HAS_KEYWORDS(p2 = pctx->stack;) |
5593 | if (pctx != &ctx) { | 5674 | if (pctx != &ctx) { |
@@ -5618,6 +5699,7 @@ static char *expand_string_to_string(const char *str, int EXP_flags, int do_unba | |||
5618 | #if ENABLE_HUSH_TICK | 5699 | #if ENABLE_HUSH_TICK |
5619 | static int process_command_subs(o_string *dest, const char *s); | 5700 | static int process_command_subs(o_string *dest, const char *s); |
5620 | #endif | 5701 | #endif |
5702 | static int expand_vars_to_list(o_string *output, int n, char *arg); | ||
5621 | 5703 | ||
5622 | /* expand_strvec_to_strvec() takes a list of strings, expands | 5704 | /* expand_strvec_to_strvec() takes a list of strings, expands |
5623 | * all variable references within and returns a pointer to | 5705 | * all variable references within and returns a pointer to |
@@ -5662,10 +5744,10 @@ static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len | |||
5662 | /* Store given string, finalizing the word and starting new one whenever | 5744 | /* Store given string, finalizing the word and starting new one whenever |
5663 | * we encounter IFS char(s). This is used for expanding variable values. | 5745 | * we encounter IFS char(s). This is used for expanding variable values. |
5664 | * End-of-string does NOT finalize word: think about 'echo -$VAR-'. | 5746 | * End-of-string does NOT finalize word: think about 'echo -$VAR-'. |
5665 | * Return in *ended_with_ifs: | 5747 | * Return in output->ended_in_ifs: |
5666 | * 1 - ended with IFS char, else 0 (this includes case of empty str). | 5748 | * 1 - ended with IFS char, else 0 (this includes case of empty str). |
5667 | */ | 5749 | */ |
5668 | static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const char *str) | 5750 | static int expand_on_ifs(o_string *output, int n, const char *str) |
5669 | { | 5751 | { |
5670 | int last_is_ifs = 0; | 5752 | int last_is_ifs = 0; |
5671 | 5753 | ||
@@ -5728,8 +5810,7 @@ static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const cha | |||
5728 | } | 5810 | } |
5729 | } | 5811 | } |
5730 | 5812 | ||
5731 | if (ended_with_ifs) | 5813 | output->ended_in_ifs = last_is_ifs; |
5732 | *ended_with_ifs = last_is_ifs; | ||
5733 | debug_print_list("expand_on_ifs[1]", output, n); | 5814 | debug_print_list("expand_on_ifs[1]", output, n); |
5734 | return n; | 5815 | return n; |
5735 | } | 5816 | } |
@@ -5741,45 +5822,288 @@ static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const cha | |||
5741 | * Returns malloced string. | 5822 | * Returns malloced string. |
5742 | * As an optimization, we return NULL if expansion is not needed. | 5823 | * As an optimization, we return NULL if expansion is not needed. |
5743 | */ | 5824 | */ |
5744 | #if !BASH_PATTERN_SUBST | 5825 | static char *encode_then_expand_string(const char *str) |
5745 | /* only ${var/pattern/repl} (its pattern part) needs additional mode */ | ||
5746 | #define encode_then_expand_string(str, process_bkslash, do_unbackslash) \ | ||
5747 | encode_then_expand_string(str) | ||
5748 | #endif | ||
5749 | static char *encode_then_expand_string(const char *str, int process_bkslash, int do_unbackslash) | ||
5750 | { | 5826 | { |
5751 | #if !BASH_PATTERN_SUBST | ||
5752 | enum { do_unbackslash = 1 }; | ||
5753 | #endif | ||
5754 | char *exp_str; | 5827 | char *exp_str; |
5755 | struct in_str input; | 5828 | struct in_str input; |
5756 | o_string dest = NULL_O_STRING; | 5829 | o_string dest = NULL_O_STRING; |
5830 | const char *cp; | ||
5757 | 5831 | ||
5758 | if (!strchr(str, '$') | 5832 | cp = str; |
5759 | && !strchr(str, '\\') | 5833 | for (;;) { |
5834 | if (!*cp) return NULL; /* string has no special chars */ | ||
5835 | if (*cp == '$') break; | ||
5836 | if (*cp == '\\') break; | ||
5760 | #if ENABLE_HUSH_TICK | 5837 | #if ENABLE_HUSH_TICK |
5761 | && !strchr(str, '`') | 5838 | if (*cp == '`') break; |
5762 | #endif | 5839 | #endif |
5763 | ) { | 5840 | cp++; |
5764 | return NULL; | ||
5765 | } | 5841 | } |
5766 | 5842 | ||
5767 | /* We need to expand. Example: | 5843 | /* We need to expand. Example: |
5768 | * echo $(($a + `echo 1`)) $((1 + $((2)) )) | 5844 | * echo $(($a + `echo 1`)) $((1 + $((2)) )) |
5769 | */ | 5845 | */ |
5770 | setup_string_in_str(&input, str); | 5846 | setup_string_in_str(&input, str); |
5771 | encode_string(NULL, &dest, &input, EOF, process_bkslash); | 5847 | encode_string(NULL, &dest, &input, EOF); |
5772 | //TODO: error check (encode_string returns 0 on error)? | 5848 | //TODO: error check (encode_string returns 0 on error)? |
5773 | //bb_error_msg("'%s' -> '%s'", str, dest.data); | 5849 | //bb_error_msg("'%s' -> '%s'", str, dest.data); |
5774 | exp_str = expand_string_to_string(dest.data, | 5850 | exp_str = expand_string_to_string(dest.data, |
5851 | EXP_FLAG_ESC_GLOB_CHARS, | ||
5852 | /*unbackslash:*/ 1 | ||
5853 | ); | ||
5854 | //bb_error_msg("'%s' -> '%s'", dest.data, exp_str); | ||
5855 | o_free(&dest); | ||
5856 | return exp_str; | ||
5857 | } | ||
5858 | |||
5859 | /* Expanding ARG in ${var#ARG}, ${var%ARG}, or ${var/ARG/ARG}. | ||
5860 | * These can contain single- and double-quoted strings, | ||
5861 | * and treated as if the ARG string is initially unquoted. IOW: | ||
5862 | * ${var#ARG} and "${var#ARG}" treat ARG the same (ARG can even be | ||
5863 | * a dquoted string: "${var#"zz"}"), the difference only comes later | ||
5864 | * (word splitting and globbing of the ${var...} result). | ||
5865 | */ | ||
5866 | #if !BASH_PATTERN_SUBST | ||
5867 | #define encode_then_expand_vararg(str, handle_squotes, do_unbackslash) \ | ||
5868 | encode_then_expand_vararg(str, handle_squotes) | ||
5869 | #endif | ||
5870 | static char *encode_then_expand_vararg(const char *str, int handle_squotes, int do_unbackslash) | ||
5871 | { | ||
5872 | #if !BASH_PATTERN_SUBST | ||
5873 | const int do_unbackslash = 0; | ||
5874 | #endif | ||
5875 | char *exp_str; | ||
5876 | struct in_str input; | ||
5877 | o_string dest = NULL_O_STRING; | ||
5878 | const char *cp; | ||
5879 | |||
5880 | cp = str; | ||
5881 | for (;;) { | ||
5882 | if (!*cp) return NULL; /* string has no special chars */ | ||
5883 | if (*cp == '$') break; | ||
5884 | if (*cp == '\\') break; | ||
5885 | if (*cp == '\'') break; | ||
5886 | if (*cp == '"') break; | ||
5887 | #if ENABLE_HUSH_TICK | ||
5888 | if (*cp == '`') break; | ||
5889 | #endif | ||
5890 | cp++; | ||
5891 | } | ||
5892 | |||
5893 | setup_string_in_str(&input, str); | ||
5894 | dest.data = xzalloc(1); /* start as "", not as NULL */ | ||
5895 | exp_str = NULL; | ||
5896 | |||
5897 | for (;;) { | ||
5898 | int ch; | ||
5899 | |||
5900 | ch = i_getch(&input); | ||
5901 | debug_printf_parse("%s: ch=%c (%d) escape=%d\n", | ||
5902 | __func__, ch, ch, !!dest.o_expflags); | ||
5903 | |||
5904 | if (!dest.o_expflags) { | ||
5905 | if (ch == EOF) | ||
5906 | break; | ||
5907 | if (handle_squotes && ch == '\'') { | ||
5908 | if (!add_till_single_quote_dquoted(&dest, &input)) | ||
5909 | goto ret; /* error */ | ||
5910 | continue; | ||
5911 | } | ||
5912 | } | ||
5913 | if (ch == EOF) { | ||
5914 | syntax_error_unterm_ch('"'); | ||
5915 | goto ret; /* error */ | ||
5916 | } | ||
5917 | if (ch == '"') { | ||
5918 | dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS; | ||
5919 | continue; | ||
5920 | } | ||
5921 | if (ch == '\\') { | ||
5922 | ch = i_getch(&input); | ||
5923 | if (ch == EOF) { | ||
5924 | //example? error message? syntax_error_unterm_ch('"'); | ||
5925 | debug_printf_parse("%s: error: \\<eof>\n", __func__); | ||
5926 | goto ret; | ||
5927 | } | ||
5928 | o_addqchr(&dest, ch); | ||
5929 | continue; | ||
5930 | } | ||
5931 | if (ch == '$') { | ||
5932 | if (!parse_dollar(NULL, &dest, &input, /*quote_mask:*/ 0x80)) { | ||
5933 | debug_printf_parse("%s: error: parse_dollar returned 0 (error)\n", __func__); | ||
5934 | goto ret; | ||
5935 | } | ||
5936 | continue; | ||
5937 | } | ||
5938 | #if ENABLE_HUSH_TICK | ||
5939 | if (ch == '`') { | ||
5940 | //unsigned pos = dest->length; | ||
5941 | o_addchr(&dest, SPECIAL_VAR_SYMBOL); | ||
5942 | o_addchr(&dest, 0x80 | '`'); | ||
5943 | if (!add_till_backquote(&dest, &input, | ||
5944 | /*in_dquote:*/ dest.o_expflags /* nonzero if EXP_FLAG_ESC_GLOB_CHARS set */ | ||
5945 | ) | ||
5946 | ) { | ||
5947 | goto ret; /* error */ | ||
5948 | } | ||
5949 | o_addchr(&dest, SPECIAL_VAR_SYMBOL); | ||
5950 | //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos); | ||
5951 | continue; | ||
5952 | } | ||
5953 | #endif | ||
5954 | o_addQchr(&dest, ch); | ||
5955 | } /* for (;;) */ | ||
5956 | |||
5957 | debug_printf_parse("encode: '%s' -> '%s'\n", str, dest.data); | ||
5958 | exp_str = expand_string_to_string(dest.data, | ||
5775 | do_unbackslash ? EXP_FLAG_ESC_GLOB_CHARS : 0, | 5959 | do_unbackslash ? EXP_FLAG_ESC_GLOB_CHARS : 0, |
5776 | do_unbackslash | 5960 | do_unbackslash |
5777 | ); | 5961 | ); |
5778 | //bb_error_msg("'%s' -> '%s'", dest.data, exp_str); | 5962 | ret: |
5779 | o_free_unsafe(&dest); | 5963 | debug_printf_parse("expand: '%s' -> '%s'\n", dest.data, exp_str); |
5964 | o_free(&dest); | ||
5780 | return exp_str; | 5965 | return exp_str; |
5781 | } | 5966 | } |
5782 | 5967 | ||
5968 | /* Expanding ARG in ${var+ARG}, ${var-ARG} | ||
5969 | */ | ||
5970 | static int encode_then_append_var_plusminus(o_string *output, int n, | ||
5971 | const char *str, int dquoted) | ||
5972 | { | ||
5973 | struct in_str input; | ||
5974 | o_string dest = NULL_O_STRING; | ||
5975 | |||
5976 | #if 0 //todo? | ||
5977 | const char *cp; | ||
5978 | cp = str; | ||
5979 | for (;;) { | ||
5980 | if (!*cp) return NULL; /* string has no special chars */ | ||
5981 | if (*cp == '$') break; | ||
5982 | if (*cp == '\\') break; | ||
5983 | if (*cp == '\'') break; | ||
5984 | if (*cp == '"') break; | ||
5985 | #if ENABLE_HUSH_TICK | ||
5986 | if (*cp == '`') break; | ||
5987 | #endif | ||
5988 | cp++; | ||
5989 | } | ||
5990 | #endif | ||
5991 | |||
5992 | setup_string_in_str(&input, str); | ||
5993 | |||
5994 | for (;;) { | ||
5995 | int ch; | ||
5996 | |||
5997 | ch = i_getch(&input); | ||
5998 | debug_printf_parse("%s: ch=%c (%d) escape=%x\n", | ||
5999 | __func__, ch, ch, dest.o_expflags); | ||
6000 | |||
6001 | if (!dest.o_expflags) { | ||
6002 | if (ch == EOF) | ||
6003 | break; | ||
6004 | if (!dquoted && strchr(G.ifs, ch)) { | ||
6005 | /* PREFIX${x:d${e}f ...} and we met space: expand "d${e}f" and start new word. | ||
6006 | * do not assume we are at the start of the word (PREFIX above). | ||
6007 | */ | ||
6008 | if (dest.data) { | ||
6009 | n = expand_vars_to_list(output, n, dest.data); | ||
6010 | o_free_and_set_NULL(&dest); | ||
6011 | o_addchr(output, '\0'); | ||
6012 | n = o_save_ptr(output, n); /* create next word */ | ||
6013 | } else | ||
6014 | if (output->length != o_get_last_ptr(output, n) | ||
6015 | || output->has_quoted_part | ||
6016 | ) { | ||
6017 | /* For these cases: | ||
6018 | * f() { for i; do echo "|$i|"; done; }; x=x | ||
6019 | * f a${x:+ }b # 1st condition | ||
6020 | * |a| | ||
6021 | * |b| | ||
6022 | * f ""${x:+ }b # 2nd condition | ||
6023 | * || | ||
6024 | * |b| | ||
6025 | */ | ||
6026 | o_addchr(output, '\0'); | ||
6027 | n = o_save_ptr(output, n); /* create next word */ | ||
6028 | } | ||
6029 | continue; | ||
6030 | } | ||
6031 | if (!dquoted && ch == '\'') { | ||
6032 | if (!add_till_single_quote_dquoted(&dest, &input)) | ||
6033 | goto ret; /* error */ | ||
6034 | o_addchr(&dest, SPECIAL_VAR_SYMBOL); | ||
6035 | o_addchr(&dest, SPECIAL_VAR_SYMBOL); | ||
6036 | continue; | ||
6037 | } | ||
6038 | } | ||
6039 | if (ch == EOF) { | ||
6040 | syntax_error_unterm_ch('"'); | ||
6041 | goto ret; /* error */ | ||
6042 | } | ||
6043 | if (ch == '"') { | ||
6044 | dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS; | ||
6045 | if (dest.o_expflags) { | ||
6046 | o_addchr(&dest, SPECIAL_VAR_SYMBOL); | ||
6047 | o_addchr(&dest, SPECIAL_VAR_SYMBOL); | ||
6048 | } | ||
6049 | continue; | ||
6050 | } | ||
6051 | if (ch == '\\') { | ||
6052 | ch = i_getch(&input); | ||
6053 | if (ch == EOF) { | ||
6054 | //example? error message? syntax_error_unterm_ch('"'); | ||
6055 | debug_printf_parse("%s: error: \\<eof>\n", __func__); | ||
6056 | goto ret; | ||
6057 | } | ||
6058 | o_addqchr(&dest, ch); | ||
6059 | continue; | ||
6060 | } | ||
6061 | if (ch == '$') { | ||
6062 | if (!parse_dollar(NULL, &dest, &input, /*quote_mask:*/ (dest.o_expflags || dquoted) ? 0x80 : 0)) { | ||
6063 | debug_printf_parse("%s: error: parse_dollar returned 0 (error)\n", __func__); | ||
6064 | goto ret; | ||
6065 | } | ||
6066 | continue; | ||
6067 | } | ||
6068 | #if ENABLE_HUSH_TICK | ||
6069 | if (ch == '`') { | ||
6070 | //unsigned pos = dest->length; | ||
6071 | o_addchr(&dest, SPECIAL_VAR_SYMBOL); | ||
6072 | o_addchr(&dest, (dest.o_expflags || dquoted) ? 0x80 | '`' : '`'); | ||
6073 | if (!add_till_backquote(&dest, &input, | ||
6074 | /*in_dquote:*/ dest.o_expflags /* nonzero if EXP_FLAG_ESC_GLOB_CHARS set */ | ||
6075 | ) | ||
6076 | ) { | ||
6077 | goto ret; /* error */ | ||
6078 | } | ||
6079 | o_addchr(&dest, SPECIAL_VAR_SYMBOL); | ||
6080 | //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos); | ||
6081 | continue; | ||
6082 | } | ||
6083 | #endif | ||
6084 | if (dquoted) { | ||
6085 | /* Always glob-protect if in dquotes: | ||
6086 | * x=x; echo "${x:+/bin/c*}" - prints: /bin/c* | ||
6087 | * x=x; echo "${x:+"/bin/c*"}" - prints: /bin/c* | ||
6088 | */ | ||
6089 | o_addqchr(&dest, ch); | ||
6090 | } else { | ||
6091 | /* Glob-protect only if char is quoted: | ||
6092 | * x=x; echo ${x:+/bin/c*} - prints many filenames | ||
6093 | * x=x; echo ${x:+"/bin/c*"} - prints: /bin/c* | ||
6094 | */ | ||
6095 | o_addQchr(&dest, ch); | ||
6096 | } | ||
6097 | } /* for (;;) */ | ||
6098 | |||
6099 | if (dest.data) { | ||
6100 | n = expand_vars_to_list(output, n, dest.data); | ||
6101 | } | ||
6102 | ret: | ||
6103 | o_free(&dest); | ||
6104 | return n; | ||
6105 | } | ||
6106 | |||
5783 | #if ENABLE_FEATURE_SH_MATH | 6107 | #if ENABLE_FEATURE_SH_MATH |
5784 | static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) | 6108 | static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) |
5785 | { | 6109 | { |
@@ -5790,7 +6114,7 @@ static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) | |||
5790 | math_state.lookupvar = get_local_var_value; | 6114 | math_state.lookupvar = get_local_var_value; |
5791 | math_state.setvar = set_local_var_from_halves; | 6115 | math_state.setvar = set_local_var_from_halves; |
5792 | //math_state.endofname = endofname; | 6116 | //math_state.endofname = endofname; |
5793 | exp_str = encode_then_expand_string(arg, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); | 6117 | exp_str = encode_then_expand_string(arg); |
5794 | res = arith(&math_state, exp_str ? exp_str : arg); | 6118 | res = arith(&math_state, exp_str ? exp_str : arg); |
5795 | free(exp_str); | 6119 | free(exp_str); |
5796 | if (errmsg_p) | 6120 | if (errmsg_p) |
@@ -5857,16 +6181,33 @@ static char *replace_pattern(char *val, const char *pattern, const char *repl, c | |||
5857 | } | 6181 | } |
5858 | #endif /* BASH_PATTERN_SUBST */ | 6182 | #endif /* BASH_PATTERN_SUBST */ |
5859 | 6183 | ||
5860 | /* Helper: | 6184 | static int append_str_maybe_ifs_split(o_string *output, int n, |
5861 | * Handles <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct. | 6185 | int first_ch, const char *val) |
6186 | { | ||
6187 | if (!(first_ch & 0x80)) { /* unquoted $VAR */ | ||
6188 | debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val, | ||
6189 | !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); | ||
6190 | if (val && val[0]) | ||
6191 | n = expand_on_ifs(output, n, val); | ||
6192 | } else { /* quoted "$VAR" */ | ||
6193 | output->has_quoted_part = 1; | ||
6194 | debug_printf_expand("quoted '%s', output->o_escape:%d\n", val, | ||
6195 | !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); | ||
6196 | if (val && val[0]) | ||
6197 | o_addQstr(output, val); | ||
6198 | } | ||
6199 | return n; | ||
6200 | } | ||
6201 | |||
6202 | /* Handle <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct. | ||
5862 | */ | 6203 | */ |
5863 | static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, char **pp) | 6204 | static NOINLINE int expand_one_var(o_string *output, int n, |
6205 | int first_ch, char *arg, char **pp) | ||
5864 | { | 6206 | { |
5865 | const char *val; | 6207 | const char *val; |
5866 | char *to_be_freed; | 6208 | char *to_be_freed; |
5867 | char *p; | 6209 | char *p; |
5868 | char *var; | 6210 | char *var; |
5869 | char first_char; | ||
5870 | char exp_op; | 6211 | char exp_op; |
5871 | char exp_save = exp_save; /* for compiler */ | 6212 | char exp_save = exp_save; /* for compiler */ |
5872 | char *exp_saveptr; /* points to expansion operator */ | 6213 | char *exp_saveptr; /* points to expansion operator */ |
@@ -5880,10 +6221,10 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |||
5880 | var = arg; | 6221 | var = arg; |
5881 | exp_saveptr = arg[1] ? strchr(VAR_ENCODED_SUBST_OPS, arg[1]) : NULL; | 6222 | exp_saveptr = arg[1] ? strchr(VAR_ENCODED_SUBST_OPS, arg[1]) : NULL; |
5882 | arg0 = arg[0]; | 6223 | arg0 = arg[0]; |
5883 | first_char = arg[0] = arg0 & 0x7f; | 6224 | arg[0] = (arg0 & 0x7f); |
5884 | exp_op = 0; | 6225 | exp_op = 0; |
5885 | 6226 | ||
5886 | if (first_char == '#' && arg[1] /* ${#...} but not ${#} */ | 6227 | if (arg[0] == '#' && arg[1] /* ${#...} but not ${#} */ |
5887 | && (!exp_saveptr /* and ( not(${#<op_char>...}) */ | 6228 | && (!exp_saveptr /* and ( not(${#<op_char>...}) */ |
5888 | || (arg[2] == '\0' && strchr(SPECIAL_VARS_STR, arg[1])) /* or ${#C} "len of $C" ) */ | 6229 | || (arg[2] == '\0' && strchr(SPECIAL_VARS_STR, arg[1])) /* or ${#C} "len of $C" ) */ |
5889 | ) /* NB: skipping ^^^specvar check mishandles ${#::2} */ | 6230 | ) /* NB: skipping ^^^specvar check mishandles ${#::2} */ |
@@ -5894,7 +6235,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |||
5894 | } else { | 6235 | } else { |
5895 | /* Maybe handle parameter expansion */ | 6236 | /* Maybe handle parameter expansion */ |
5896 | if (exp_saveptr /* if 2nd char is one of expansion operators */ | 6237 | if (exp_saveptr /* if 2nd char is one of expansion operators */ |
5897 | && strchr(NUMERIC_SPECVARS_STR, first_char) /* 1st char is special variable */ | 6238 | && strchr(NUMERIC_SPECVARS_STR, arg[0]) /* 1st char is special variable */ |
5898 | ) { | 6239 | ) { |
5899 | /* ${?:0}, ${#[:]%0} etc */ | 6240 | /* ${?:0}, ${#[:]%0} etc */ |
5900 | exp_saveptr = var + 1; | 6241 | exp_saveptr = var + 1; |
@@ -5923,9 +6264,9 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |||
5923 | /* Look up the variable in question */ | 6264 | /* Look up the variable in question */ |
5924 | if (isdigit(var[0])) { | 6265 | if (isdigit(var[0])) { |
5925 | /* parse_dollar should have vetted var for us */ | 6266 | /* parse_dollar should have vetted var for us */ |
5926 | int n = xatoi_positive(var); | 6267 | int nn = xatoi_positive(var); |
5927 | if (n < G.global_argc) | 6268 | if (nn < G.global_argc) |
5928 | val = G.global_argv[n]; | 6269 | val = G.global_argv[nn]; |
5929 | /* else val remains NULL: $N with too big N */ | 6270 | /* else val remains NULL: $N with too big N */ |
5930 | } else { | 6271 | } else { |
5931 | switch (var[0]) { | 6272 | switch (var[0]) { |
@@ -5963,6 +6304,9 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |||
5963 | * Word is expanded to produce a glob pattern. | 6304 | * Word is expanded to produce a glob pattern. |
5964 | * Then var's value is matched to it and matching part removed. | 6305 | * Then var's value is matched to it and matching part removed. |
5965 | */ | 6306 | */ |
6307 | //FIXME: ${x#...${...}...} | ||
6308 | //should evaluate inner ${...} even if x is "" and no shrinking of it is possible - | ||
6309 | //inner ${...} may have side effects! | ||
5966 | if (val && val[0]) { | 6310 | if (val && val[0]) { |
5967 | char *t; | 6311 | char *t; |
5968 | char *exp_exp_word; | 6312 | char *exp_exp_word; |
@@ -5971,20 +6315,16 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |||
5971 | if (exp_op == *exp_word) /* ## or %% */ | 6315 | if (exp_op == *exp_word) /* ## or %% */ |
5972 | exp_word++; | 6316 | exp_word++; |
5973 | debug_printf_expand("expand: exp_word:'%s'\n", exp_word); | 6317 | debug_printf_expand("expand: exp_word:'%s'\n", exp_word); |
5974 | /* | 6318 | exp_exp_word = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ 1, /*unbackslash:*/ 0); |
5975 | * process_bkslash:1 unbackslash:1 breaks this: | ||
5976 | * a='a\\'; echo ${a%\\\\} # correct output is: a | ||
5977 | * process_bkslash:1 unbackslash:0 breaks this: | ||
5978 | * a='a}'; echo ${a%\}} # correct output is: a | ||
5979 | */ | ||
5980 | exp_exp_word = encode_then_expand_string(exp_word, /*process_bkslash:*/ 0, /*unbackslash:*/ 0); | ||
5981 | if (exp_exp_word) | 6319 | if (exp_exp_word) |
5982 | exp_word = exp_exp_word; | 6320 | exp_word = exp_exp_word; |
5983 | debug_printf_expand("expand: exp_exp_word:'%s'\n", exp_word); | 6321 | debug_printf_expand("expand: exp_word:'%s'\n", exp_word); |
5984 | /* HACK ALERT. We depend here on the fact that | 6322 | /* |
6323 | * HACK ALERT. We depend here on the fact that | ||
5985 | * G.global_argv and results of utoa and get_local_var_value | 6324 | * G.global_argv and results of utoa and get_local_var_value |
5986 | * are actually in writable memory: | 6325 | * are actually in writable memory: |
5987 | * scan_and_match momentarily stores NULs there. */ | 6326 | * scan_and_match momentarily stores NULs there. |
6327 | */ | ||
5988 | t = (char*)val; | 6328 | t = (char*)val; |
5989 | loc = scan_and_match(t, exp_word, scan_flags); | 6329 | loc = scan_and_match(t, exp_word, scan_flags); |
5990 | debug_printf_expand("op:%c str:'%s' pat:'%s' res:'%s'\n", exp_op, t, exp_word, loc); | 6330 | debug_printf_expand("op:%c str:'%s' pat:'%s' res:'%s'\n", exp_op, t, exp_word, loc); |
@@ -6017,7 +6357,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |||
6017 | * (note that a*z _pattern_ is never globbed!) | 6357 | * (note that a*z _pattern_ is never globbed!) |
6018 | */ | 6358 | */ |
6019 | char *pattern, *repl, *t; | 6359 | char *pattern, *repl, *t; |
6020 | pattern = encode_then_expand_string(exp_word, /*process_bkslash:*/ 0, /*unbackslash:*/ 0); | 6360 | pattern = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ 1, /*unbackslash:*/ 0); |
6021 | if (!pattern) | 6361 | if (!pattern) |
6022 | pattern = xstrdup(exp_word); | 6362 | pattern = xstrdup(exp_word); |
6023 | debug_printf_varexp("pattern:'%s'->'%s'\n", exp_word, pattern); | 6363 | debug_printf_varexp("pattern:'%s'->'%s'\n", exp_word, pattern); |
@@ -6025,7 +6365,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |||
6025 | exp_word = p; | 6365 | exp_word = p; |
6026 | p = strchr(p, SPECIAL_VAR_SYMBOL); | 6366 | p = strchr(p, SPECIAL_VAR_SYMBOL); |
6027 | *p = '\0'; | 6367 | *p = '\0'; |
6028 | repl = encode_then_expand_string(exp_word, /*process_bkslash:*/ 0, /*unbackslash:*/ 1); | 6368 | repl = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ 1, /*unbackslash:*/ 1); |
6029 | debug_printf_varexp("repl:'%s'->'%s'\n", exp_word, repl); | 6369 | debug_printf_varexp("repl:'%s'->'%s'\n", exp_word, repl); |
6030 | /* HACK ALERT. We depend here on the fact that | 6370 | /* HACK ALERT. We depend here on the fact that |
6031 | * G.global_argv and results of utoa and get_local_var_value | 6371 | * G.global_argv and results of utoa and get_local_var_value |
@@ -6121,6 +6461,34 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |||
6121 | * | 6461 | * |
6122 | * Colon forms (${var:-word}, ${var:=word} etc) do the same, | 6462 | * Colon forms (${var:-word}, ${var:=word} etc) do the same, |
6123 | * but also treat null var as if it is unset. | 6463 | * but also treat null var as if it is unset. |
6464 | * | ||
6465 | * Word-splitting and single quote behavior: | ||
6466 | * | ||
6467 | * $ f() { for i; do echo "|$i|"; done; }; | ||
6468 | * | ||
6469 | * $ x=; f ${x:?'x y' z} | ||
6470 | * bash: x: x y z #BUG: does not abort, ${} results in empty expansion | ||
6471 | * $ x=; f "${x:?'x y' z}" | ||
6472 | * bash: x: x y z # dash prints: dash: x: 'x y' z #BUG: does not abort, ${} results in "" | ||
6473 | * | ||
6474 | * $ x=; f ${x:='x y' z} | ||
6475 | * |x| | ||
6476 | * |y| | ||
6477 | * |z| | ||
6478 | * $ x=; f "${x:='x y' z}" | ||
6479 | * |'x y' z| | ||
6480 | * | ||
6481 | * $ x=x; f ${x:+'x y' z} | ||
6482 | * |x y| | ||
6483 | * |z| | ||
6484 | * $ x=x; f "${x:+'x y' z}" | ||
6485 | * |'x y' z| | ||
6486 | * | ||
6487 | * $ x=; f ${x:-'x y' z} | ||
6488 | * |x y| | ||
6489 | * |z| | ||
6490 | * $ x=; f "${x:-'x y' z}" | ||
6491 | * |'x y' z| | ||
6124 | */ | 6492 | */ |
6125 | int use_word = (!val || ((exp_save == ':') && !val[0])); | 6493 | int use_word = (!val || ((exp_save == ':') && !val[0])); |
6126 | if (exp_op == '+') | 6494 | if (exp_op == '+') |
@@ -6128,33 +6496,51 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |||
6128 | debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op, | 6496 | debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op, |
6129 | (exp_save == ':') ? "true" : "false", use_word); | 6497 | (exp_save == ':') ? "true" : "false", use_word); |
6130 | if (use_word) { | 6498 | if (use_word) { |
6131 | to_be_freed = encode_then_expand_string(exp_word, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); | 6499 | if (exp_op == '+' || exp_op == '-') { |
6132 | if (to_be_freed) | 6500 | /* ${var+word} - use alternative value */ |
6133 | exp_word = to_be_freed; | 6501 | /* ${var-word} - use default value */ |
6134 | if (exp_op == '?') { | 6502 | n = encode_then_append_var_plusminus(output, n, exp_word, |
6135 | /* mimic bash message */ | 6503 | /*dquoted:*/ (arg0 & 0x80) |
6136 | msg_and_die_if_script("%s: %s", | ||
6137 | var, | ||
6138 | exp_word[0] | ||
6139 | ? exp_word | ||
6140 | : "parameter null or not set" | ||
6141 | /* ash has more specific messages, a-la: */ | ||
6142 | /*: (exp_save == ':' ? "parameter null or not set" : "parameter not set")*/ | ||
6143 | ); | 6504 | ); |
6144 | //TODO: how interactive bash aborts expansion mid-command? | 6505 | val = NULL; |
6145 | } else { | 6506 | } else { |
6146 | val = exp_word; | 6507 | /* ${var?word} - indicate error if unset */ |
6147 | } | 6508 | /* ${var=word} - assign and use default value */ |
6148 | 6509 | to_be_freed = encode_then_expand_vararg(exp_word, | |
6149 | if (exp_op == '=') { | 6510 | /*handle_squotes:*/ !(arg0 & 0x80), |
6150 | /* ${var=[word]} or ${var:=[word]} */ | 6511 | /*unbackslash:*/ 0 |
6151 | if (isdigit(var[0]) || var[0] == '#') { | 6512 | ); |
6513 | if (to_be_freed) | ||
6514 | exp_word = to_be_freed; | ||
6515 | if (exp_op == '?') { | ||
6152 | /* mimic bash message */ | 6516 | /* mimic bash message */ |
6153 | msg_and_die_if_script("$%s: cannot assign in this way", var); | 6517 | msg_and_die_if_script("%s: %s", |
6154 | val = NULL; | 6518 | var, |
6519 | exp_word[0] | ||
6520 | ? exp_word | ||
6521 | : "parameter null or not set" | ||
6522 | /* ash has more specific messages, a-la: */ | ||
6523 | /*: (exp_save == ':' ? "parameter null or not set" : "parameter not set")*/ | ||
6524 | ); | ||
6525 | //TODO: how interactive bash aborts expansion mid-command? | ||
6526 | //It aborts the entire line, returns to prompt: | ||
6527 | // $ f() { for i; do echo "|$i|"; done; }; x=; f "${x:?'x y' z}"; echo YO | ||
6528 | // bash: x: x y z | ||
6529 | // $ | ||
6530 | // ("echo YO" is not executed, neither the f function call) | ||
6155 | } else { | 6531 | } else { |
6156 | char *new_var = xasprintf("%s=%s", var, val); | 6532 | val = exp_word; |
6157 | set_local_var(new_var, /*flag:*/ 0); | 6533 | } |
6534 | if (exp_op == '=') { | ||
6535 | /* ${var=[word]} or ${var:=[word]} */ | ||
6536 | if (isdigit(var[0]) || var[0] == '#') { | ||
6537 | /* mimic bash message */ | ||
6538 | msg_and_die_if_script("$%s: cannot assign in this way", var); | ||
6539 | val = NULL; | ||
6540 | } else { | ||
6541 | char *new_var = xasprintf("%s=%s", var, val); | ||
6542 | set_local_var(new_var, /*flag:*/ 0); | ||
6543 | } | ||
6158 | } | 6544 | } |
6159 | } | 6545 | } |
6160 | } | 6546 | } |
@@ -6164,10 +6550,12 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |||
6164 | } /* if (exp_op) */ | 6550 | } /* if (exp_op) */ |
6165 | 6551 | ||
6166 | arg[0] = arg0; | 6552 | arg[0] = arg0; |
6167 | |||
6168 | *pp = p; | 6553 | *pp = p; |
6169 | *to_be_freed_pp = to_be_freed; | 6554 | |
6170 | return val; | 6555 | n = append_str_maybe_ifs_split(output, n, first_ch, val); |
6556 | |||
6557 | free(to_be_freed); | ||
6558 | return n; | ||
6171 | } | 6559 | } |
6172 | 6560 | ||
6173 | /* Expand all variable references in given string, adding words to list[] | 6561 | /* Expand all variable references in given string, adding words to list[] |
@@ -6181,30 +6569,22 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
6181 | * expansion of right-hand side of assignment == 1-element expand. | 6569 | * expansion of right-hand side of assignment == 1-element expand. |
6182 | */ | 6570 | */ |
6183 | char cant_be_null = 0; /* only bit 0x80 matters */ | 6571 | char cant_be_null = 0; /* only bit 0x80 matters */ |
6184 | int ended_in_ifs = 0; /* did last unquoted expansion end with IFS chars? */ | ||
6185 | char *p; | 6572 | char *p; |
6186 | 6573 | ||
6187 | debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg, | 6574 | debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg, |
6188 | !!(output->o_expflags & EXP_FLAG_SINGLEWORD)); | 6575 | !!(output->o_expflags & EXP_FLAG_SINGLEWORD)); |
6189 | debug_print_list("expand_vars_to_list", output, n); | ||
6190 | n = o_save_ptr(output, n); | ||
6191 | debug_print_list("expand_vars_to_list[0]", output, n); | 6576 | debug_print_list("expand_vars_to_list[0]", output, n); |
6192 | 6577 | ||
6193 | while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) { | 6578 | while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) { |
6194 | char first_ch; | 6579 | char first_ch; |
6195 | char *to_be_freed = NULL; | ||
6196 | const char *val = NULL; | ||
6197 | #if ENABLE_HUSH_TICK | ||
6198 | o_string subst_result = NULL_O_STRING; | ||
6199 | #endif | ||
6200 | #if ENABLE_FEATURE_SH_MATH | 6580 | #if ENABLE_FEATURE_SH_MATH |
6201 | char arith_buf[sizeof(arith_t)*3 + 2]; | 6581 | char arith_buf[sizeof(arith_t)*3 + 2]; |
6202 | #endif | 6582 | #endif |
6203 | 6583 | ||
6204 | if (ended_in_ifs) { | 6584 | if (output->ended_in_ifs) { |
6205 | o_addchr(output, '\0'); | 6585 | o_addchr(output, '\0'); |
6206 | n = o_save_ptr(output, n); | 6586 | n = o_save_ptr(output, n); |
6207 | ended_in_ifs = 0; | 6587 | output->ended_in_ifs = 0; |
6208 | } | 6588 | } |
6209 | 6589 | ||
6210 | o_addblock(output, arg, p - arg); | 6590 | o_addblock(output, arg, p - arg); |
@@ -6235,7 +6615,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
6235 | cant_be_null |= first_ch; /* do it for "$@" _now_, when we know it's not empty */ | 6615 | cant_be_null |= first_ch; /* do it for "$@" _now_, when we know it's not empty */ |
6236 | if (!(first_ch & 0x80)) { /* unquoted $* or $@ */ | 6616 | if (!(first_ch & 0x80)) { /* unquoted $* or $@ */ |
6237 | while (G.global_argv[i]) { | 6617 | while (G.global_argv[i]) { |
6238 | n = expand_on_ifs(NULL, output, n, G.global_argv[i]); | 6618 | n = expand_on_ifs(output, n, G.global_argv[i]); |
6239 | debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1); | 6619 | debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1); |
6240 | if (G.global_argv[i++][0] && G.global_argv[i]) { | 6620 | if (G.global_argv[i++][0] && G.global_argv[i]) { |
6241 | /* this argv[] is not empty and not last: | 6621 | /* this argv[] is not empty and not last: |
@@ -6272,19 +6652,25 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
6272 | } | 6652 | } |
6273 | break; | 6653 | break; |
6274 | } | 6654 | } |
6275 | case SPECIAL_VAR_SYMBOL: /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_SYMBOL> */ | 6655 | case SPECIAL_VAR_SYMBOL: { |
6656 | /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_SYMBOL> */ | ||
6276 | /* "Empty variable", used to make "" etc to not disappear */ | 6657 | /* "Empty variable", used to make "" etc to not disappear */ |
6277 | output->has_quoted_part = 1; | 6658 | output->has_quoted_part = 1; |
6278 | arg++; | ||
6279 | cant_be_null = 0x80; | 6659 | cant_be_null = 0x80; |
6660 | arg++; | ||
6280 | break; | 6661 | break; |
6662 | } | ||
6281 | case SPECIAL_VAR_QUOTED_SVS: | 6663 | case SPECIAL_VAR_QUOTED_SVS: |
6282 | /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_QUOTED_SVS><SPECIAL_VAR_SYMBOL> */ | 6664 | /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_QUOTED_SVS><SPECIAL_VAR_SYMBOL> */ |
6665 | /* "^C variable", represents literal ^C char (possible in scripts) */ | ||
6666 | o_addchr(output, SPECIAL_VAR_SYMBOL); | ||
6283 | arg++; | 6667 | arg++; |
6284 | val = SPECIAL_VAR_SYMBOL_STR; | ||
6285 | break; | 6668 | break; |
6286 | #if ENABLE_HUSH_TICK | 6669 | #if ENABLE_HUSH_TICK |
6287 | case '`': /* <SPECIAL_VAR_SYMBOL>`cmd<SPECIAL_VAR_SYMBOL> */ | 6670 | case '`': { |
6671 | /* <SPECIAL_VAR_SYMBOL>`cmd<SPECIAL_VAR_SYMBOL> */ | ||
6672 | o_string subst_result = NULL_O_STRING; | ||
6673 | |||
6288 | *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */ | 6674 | *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */ |
6289 | arg++; | 6675 | arg++; |
6290 | /* Can't just stuff it into output o_string, | 6676 | /* Can't just stuff it into output o_string, |
@@ -6294,11 +6680,14 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
6294 | G.last_exitcode = process_command_subs(&subst_result, arg); | 6680 | G.last_exitcode = process_command_subs(&subst_result, arg); |
6295 | G.expand_exitcode = G.last_exitcode; | 6681 | G.expand_exitcode = G.last_exitcode; |
6296 | debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data); | 6682 | debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data); |
6297 | val = subst_result.data; | 6683 | n = append_str_maybe_ifs_split(output, n, first_ch, subst_result.data); |
6298 | goto store_val; | 6684 | o_free(&subst_result); |
6685 | break; | ||
6686 | } | ||
6299 | #endif | 6687 | #endif |
6300 | #if ENABLE_FEATURE_SH_MATH | 6688 | #if ENABLE_FEATURE_SH_MATH |
6301 | case '+': { /* <SPECIAL_VAR_SYMBOL>+cmd<SPECIAL_VAR_SYMBOL> */ | 6689 | case '+': { |
6690 | /* <SPECIAL_VAR_SYMBOL>+arith<SPECIAL_VAR_SYMBOL> */ | ||
6302 | arith_t res; | 6691 | arith_t res; |
6303 | 6692 | ||
6304 | arg++; /* skip '+' */ | 6693 | arg++; /* skip '+' */ |
@@ -6307,62 +6696,43 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
6307 | res = expand_and_evaluate_arith(arg, NULL); | 6696 | res = expand_and_evaluate_arith(arg, NULL); |
6308 | debug_printf_subst("ARITH RES '"ARITH_FMT"'\n", res); | 6697 | debug_printf_subst("ARITH RES '"ARITH_FMT"'\n", res); |
6309 | sprintf(arith_buf, ARITH_FMT, res); | 6698 | sprintf(arith_buf, ARITH_FMT, res); |
6310 | val = arith_buf; | 6699 | o_addstr(output, arith_buf); |
6311 | break; | 6700 | break; |
6312 | } | 6701 | } |
6313 | #endif | 6702 | #endif |
6314 | default: | 6703 | default: |
6315 | val = expand_one_var(&to_be_freed, arg, &p); | 6704 | /* <SPECIAL_VAR_SYMBOL>varname[ops]<SPECIAL_VAR_SYMBOL> */ |
6316 | IF_HUSH_TICK(store_val:) | 6705 | n = expand_one_var(output, n, first_ch, arg, &p); |
6317 | if (!(first_ch & 0x80)) { /* unquoted $VAR */ | ||
6318 | debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val, | ||
6319 | !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); | ||
6320 | if (val && val[0]) { | ||
6321 | n = expand_on_ifs(&ended_in_ifs, output, n, val); | ||
6322 | val = NULL; | ||
6323 | } | ||
6324 | } else { /* quoted $VAR, val will be appended below */ | ||
6325 | output->has_quoted_part = 1; | ||
6326 | debug_printf_expand("quoted '%s', output->o_escape:%d\n", val, | ||
6327 | !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); | ||
6328 | } | ||
6329 | break; | 6706 | break; |
6330 | } /* switch (char after <SPECIAL_VAR_SYMBOL>) */ | 6707 | } /* switch (char after <SPECIAL_VAR_SYMBOL>) */ |
6331 | 6708 | ||
6332 | if (val && val[0]) { | ||
6333 | o_addQstr(output, val); | ||
6334 | } | ||
6335 | free(to_be_freed); | ||
6336 | |||
6337 | /* Restore NULL'ed SPECIAL_VAR_SYMBOL. | 6709 | /* Restore NULL'ed SPECIAL_VAR_SYMBOL. |
6338 | * Do the check to avoid writing to a const string. */ | 6710 | * Do the check to avoid writing to a const string. */ |
6339 | if (*p != SPECIAL_VAR_SYMBOL) | 6711 | if (*p != SPECIAL_VAR_SYMBOL) |
6340 | *p = SPECIAL_VAR_SYMBOL; | 6712 | *p = SPECIAL_VAR_SYMBOL; |
6341 | |||
6342 | #if ENABLE_HUSH_TICK | ||
6343 | o_free(&subst_result); | ||
6344 | #endif | ||
6345 | arg = ++p; | 6713 | arg = ++p; |
6346 | } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */ | 6714 | } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */ |
6347 | 6715 | ||
6348 | if (arg[0]) { | 6716 | if (*arg) { |
6349 | if (ended_in_ifs) { | 6717 | /* handle trailing string */ |
6718 | if (output->ended_in_ifs) { | ||
6350 | o_addchr(output, '\0'); | 6719 | o_addchr(output, '\0'); |
6351 | n = o_save_ptr(output, n); | 6720 | n = o_save_ptr(output, n); |
6352 | } | 6721 | } |
6353 | debug_print_list("expand_vars_to_list[a]", output, n); | 6722 | debug_print_list("expand_vars_to_list[a]", output, n); |
6354 | /* this part is literal, and it was already pre-quoted | 6723 | /* this part is literal, and it was already pre-quoted |
6355 | * if needed (much earlier), do not use o_addQstr here! */ | 6724 | * if needed (much earlier), do not use o_addQstr here! |
6356 | o_addstr_with_NUL(output, arg); | 6725 | */ |
6726 | o_addstr(output, arg); | ||
6357 | debug_print_list("expand_vars_to_list[b]", output, n); | 6727 | debug_print_list("expand_vars_to_list[b]", output, n); |
6358 | } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */ | 6728 | } else |
6359 | && !(cant_be_null & 0x80) /* and all vars were not quoted. */ | 6729 | if (output->length == o_get_last_ptr(output, n) /* expansion is empty */ |
6730 | && !(cant_be_null & 0x80) /* and all vars were not quoted */ | ||
6731 | && !output->has_quoted_part | ||
6360 | ) { | 6732 | ) { |
6361 | n--; | 6733 | n--; |
6362 | /* allow to reuse list[n] later without re-growth */ | 6734 | /* allow to reuse list[n] later without re-growth */ |
6363 | output->has_empty_slot = 1; | 6735 | output->has_empty_slot = 1; |
6364 | } else { | ||
6365 | o_addchr(output, '\0'); | ||
6366 | } | 6736 | } |
6367 | 6737 | ||
6368 | return n; | 6738 | return n; |
@@ -6377,9 +6747,18 @@ static char **expand_variables(char **argv, unsigned expflags) | |||
6377 | output.o_expflags = expflags; | 6747 | output.o_expflags = expflags; |
6378 | 6748 | ||
6379 | n = 0; | 6749 | n = 0; |
6380 | while (*argv) { | 6750 | for (;;) { |
6381 | n = expand_vars_to_list(&output, n, *argv); | 6751 | /* go to next list[n] */ |
6382 | argv++; | 6752 | output.ended_in_ifs = 0; |
6753 | n = o_save_ptr(&output, n); | ||
6754 | |||
6755 | if (!*argv) | ||
6756 | break; | ||
6757 | |||
6758 | /* expand argv[i] */ | ||
6759 | n = expand_vars_to_list(&output, n, *argv++); | ||
6760 | /* if (!output->has_empty_slot) -- need this?? */ | ||
6761 | o_addchr(&output, '\0'); | ||
6383 | } | 6762 | } |
6384 | debug_print_list("expand_variables", &output, n); | 6763 | debug_print_list("expand_variables", &output, n); |
6385 | 6764 | ||
@@ -6429,13 +6808,20 @@ static char *expand_string_to_string(const char *str, int EXP_flags, int do_unba | |||
6429 | argv[0] = (char*)str; | 6808 | argv[0] = (char*)str; |
6430 | argv[1] = NULL; | 6809 | argv[1] = NULL; |
6431 | list = expand_variables(argv, EXP_flags | EXP_FLAG_SINGLEWORD); | 6810 | list = expand_variables(argv, EXP_flags | EXP_FLAG_SINGLEWORD); |
6432 | if (HUSH_DEBUG) | 6811 | if (!list[0]) { |
6433 | if (!list[0] || list[1]) | 6812 | /* Example where it happens: |
6434 | bb_error_msg_and_die("BUG in varexp2"); | 6813 | * x=; echo ${x:-"$@"} |
6435 | /* actually, just move string 2*sizeof(char*) bytes back */ | 6814 | */ |
6436 | overlapping_strcpy((char*)list, list[0]); | 6815 | ((char*)list)[0] = '\0'; |
6437 | if (do_unbackslash) | 6816 | } else { |
6438 | unbackslash((char*)list); | 6817 | if (HUSH_DEBUG) |
6818 | if (list[1]) | ||
6819 | bb_error_msg_and_die("BUG in varexp2"); | ||
6820 | /* actually, just move string 2*sizeof(char*) bytes back */ | ||
6821 | overlapping_strcpy((char*)list, list[0]); | ||
6822 | if (do_unbackslash) | ||
6823 | unbackslash((char*)list); | ||
6824 | } | ||
6439 | debug_printf_expand("string_to_string=>'%s'\n", (char*)list); | 6825 | debug_printf_expand("string_to_string=>'%s'\n", (char*)list); |
6440 | return (char*)list; | 6826 | return (char*)list; |
6441 | } | 6827 | } |
@@ -6722,7 +7108,7 @@ static void parse_and_run_stream(struct in_str *inp, int end_trigger) | |||
6722 | debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode); | 7108 | debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode); |
6723 | } | 7109 | } |
6724 | #endif | 7110 | #endif |
6725 | pipe_list = parse_stream(NULL, inp, end_trigger); | 7111 | pipe_list = parse_stream(NULL, NULL, inp, end_trigger); |
6726 | if (!pipe_list || pipe_list == ERR_PTR) { /* EOF/error */ | 7112 | if (!pipe_list || pipe_list == ERR_PTR) { /* EOF/error */ |
6727 | /* If we are in "big" script | 7113 | /* If we are in "big" script |
6728 | * (not in `cmd` or something similar)... | 7114 | * (not in `cmd` or something similar)... |
@@ -6763,19 +7149,19 @@ static void parse_and_run_string(const char *s) | |||
6763 | //IF_HUSH_LINENO_VAR(G.lineno = sv;) | 7149 | //IF_HUSH_LINENO_VAR(G.lineno = sv;) |
6764 | } | 7150 | } |
6765 | 7151 | ||
6766 | static void parse_and_run_file(FILE *f) | 7152 | static void parse_and_run_file(HFILE *fp) |
6767 | { | 7153 | { |
6768 | struct in_str input; | 7154 | struct in_str input; |
6769 | IF_HUSH_LINENO_VAR(unsigned sv = G.lineno;) | 7155 | IF_HUSH_LINENO_VAR(unsigned sv = G.lineno;) |
6770 | 7156 | ||
6771 | IF_HUSH_LINENO_VAR(G.lineno = 1;) | 7157 | IF_HUSH_LINENO_VAR(G.lineno = 1;) |
6772 | setup_file_in_str(&input, f); | 7158 | setup_file_in_str(&input, fp); |
6773 | parse_and_run_stream(&input, ';'); | 7159 | parse_and_run_stream(&input, ';'); |
6774 | IF_HUSH_LINENO_VAR(G.lineno = sv;) | 7160 | IF_HUSH_LINENO_VAR(G.lineno = sv;) |
6775 | } | 7161 | } |
6776 | 7162 | ||
6777 | #if ENABLE_HUSH_TICK | 7163 | #if ENABLE_HUSH_TICK |
6778 | static FILE *generate_stream_from_string(const char *s, pid_t *pid_p) | 7164 | static int generate_stream_from_string(const char *s, pid_t *pid_p) |
6779 | { | 7165 | { |
6780 | pid_t pid; | 7166 | pid_t pid; |
6781 | int channel[2]; | 7167 | int channel[2]; |
@@ -6877,7 +7263,7 @@ static FILE *generate_stream_from_string(const char *s, pid_t *pid_p) | |||
6877 | free(to_free); | 7263 | free(to_free); |
6878 | # endif | 7264 | # endif |
6879 | close(channel[1]); | 7265 | close(channel[1]); |
6880 | return remember_FILE(xfdopen_for_read(channel[0])); | 7266 | return channel[0]; |
6881 | } | 7267 | } |
6882 | 7268 | ||
6883 | /* Return code is exit status of the process that is run. */ | 7269 | /* Return code is exit status of the process that is run. */ |
@@ -6887,7 +7273,7 @@ static int process_command_subs(o_string *dest, const char *s) | |||
6887 | pid_t pid; | 7273 | pid_t pid; |
6888 | int status, ch, eol_cnt; | 7274 | int status, ch, eol_cnt; |
6889 | 7275 | ||
6890 | fp = generate_stream_from_string(s, &pid); | 7276 | fp = xfdopen_for_read(generate_stream_from_string(s, &pid)); |
6891 | 7277 | ||
6892 | /* Now send results of command back into original context */ | 7278 | /* Now send results of command back into original context */ |
6893 | eol_cnt = 0; | 7279 | eol_cnt = 0; |
@@ -6906,7 +7292,7 @@ static int process_command_subs(o_string *dest, const char *s) | |||
6906 | } | 7292 | } |
6907 | 7293 | ||
6908 | debug_printf("done reading from `cmd` pipe, closing it\n"); | 7294 | debug_printf("done reading from `cmd` pipe, closing it\n"); |
6909 | fclose_and_forget(fp); | 7295 | fclose(fp); |
6910 | /* We need to extract exitcode. Test case | 7296 | /* We need to extract exitcode. Test case |
6911 | * "true; echo `sleep 1; false` $?" | 7297 | * "true; echo `sleep 1; false` $?" |
6912 | * should print 1 */ | 7298 | * should print 1 */ |
@@ -6931,7 +7317,7 @@ static void setup_heredoc(struct redir_struct *redir) | |||
6931 | 7317 | ||
6932 | expanded = NULL; | 7318 | expanded = NULL; |
6933 | if (!(redir->rd_dup & HEREDOC_QUOTED)) { | 7319 | if (!(redir->rd_dup & HEREDOC_QUOTED)) { |
6934 | expanded = encode_then_expand_string(heredoc, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); | 7320 | expanded = encode_then_expand_string(heredoc); |
6935 | if (expanded) | 7321 | if (expanded) |
6936 | heredoc = expanded; | 7322 | heredoc = expanded; |
6937 | } | 7323 | } |
@@ -7084,19 +7470,54 @@ static int save_fd_on_redirect(int fd, int avoid_fd, struct squirrel **sqp) | |||
7084 | return 1; /* "we closed fd" */ | 7470 | return 1; /* "we closed fd" */ |
7085 | } | 7471 | } |
7086 | #endif | 7472 | #endif |
7087 | /* Are we called from setup_redirects(squirrel==NULL)? Two cases: | 7473 | /* Are we called from setup_redirects(squirrel==NULL) |
7088 | * (1) Redirect in a forked child. No need to save FILEs' fds, | 7474 | * in redirect in a [v]forked child? |
7089 | * we aren't going to use them anymore, ok to trash. | ||
7090 | * (2) "exec 3>FILE". Bummer. We can save script FILEs' fds, | ||
7091 | * but how are we doing to restore them? | ||
7092 | * "fileno(fd) = new_fd" can't be done. | ||
7093 | */ | 7475 | */ |
7094 | if (!sqp) | 7476 | if (sqp == NULL) { |
7477 | /* No need to move script fds. | ||
7478 | * For NOMMU case, it's actively wrong: we'd change ->fd | ||
7479 | * fields in memory for the parent, but parent's fds | ||
7480 | * aren't be moved, it would use wrong fd! | ||
7481 | * Reproducer: "cmd 3>FILE" in script. | ||
7482 | * If we would call move_HFILEs_on_redirect(), child would: | ||
7483 | * fcntl64(3, F_DUPFD_CLOEXEC, 10) = 10 | ||
7484 | * close(3) = 0 | ||
7485 | * and change ->fd to 10 if fd#3 is a script fd. WRONG. | ||
7486 | */ | ||
7487 | //bb_error_msg("sqp == NULL: [v]forked child"); | ||
7095 | return 0; | 7488 | return 0; |
7489 | } | ||
7096 | 7490 | ||
7097 | /* If this one of script's fds? */ | 7491 | /* If this one of script's fds? */ |
7098 | if (save_FILEs_on_redirect(fd, avoid_fd)) | 7492 | if (move_HFILEs_on_redirect(fd, avoid_fd)) |
7099 | return 1; /* yes. "we closed fd" */ | 7493 | return 1; /* yes. "we closed fd" (actually moved it) */ |
7494 | |||
7495 | /* Are we called for "exec 3>FILE"? Came through | ||
7496 | * redirect_and_varexp_helper(squirrel=ERR_PTR) -> setup_redirects(ERR_PTR) | ||
7497 | * This case used to fail for this script: | ||
7498 | * exec 3>FILE | ||
7499 | * echo Ok | ||
7500 | * ...100000 more lines... | ||
7501 | * echo Ok | ||
7502 | * as follows: | ||
7503 | * read(3, "exec 3>FILE\necho Ok\necho Ok"..., 1024) = 1024 | ||
7504 | * open("FILE", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 4 | ||
7505 | * dup2(4, 3) = 3 | ||
7506 | * ^^^^^^^^ oops, we lost fd#3 opened to our script! | ||
7507 | * close(4) = 0 | ||
7508 | * write(1, "Ok\n", 3) = 3 | ||
7509 | * ... = 3 | ||
7510 | * write(1, "Ok\n", 3) = 3 | ||
7511 | * read(3, 0x94fbc08, 1024) = -1 EBADF (Bad file descriptor) | ||
7512 | * ^^^^^^^^ oops, wrong fd!!! | ||
7513 | * With this case separate from sqp == NULL and *after* move_HFILEs, | ||
7514 | * it now works: | ||
7515 | */ | ||
7516 | if (sqp == ERR_PTR) { | ||
7517 | /* Don't preserve redirected fds: exec is _meant_ to change these */ | ||
7518 | //bb_error_msg("sqp == ERR_PTR: exec >FILE"); | ||
7519 | return 0; | ||
7520 | } | ||
7100 | 7521 | ||
7101 | /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */ | 7522 | /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */ |
7102 | *sqp = add_squirrel(*sqp, fd, avoid_fd); | 7523 | *sqp = add_squirrel(*sqp, fd, avoid_fd); |
@@ -7122,8 +7543,6 @@ static void restore_redirects(struct squirrel *sq) | |||
7122 | } | 7543 | } |
7123 | 7544 | ||
7124 | /* If moved, G.interactive_fd stays on new fd, not restoring it */ | 7545 | /* If moved, G.interactive_fd stays on new fd, not restoring it */ |
7125 | |||
7126 | restore_redirected_FILEs(); | ||
7127 | } | 7546 | } |
7128 | 7547 | ||
7129 | #if ENABLE_FEATURE_SH_STANDALONE && BB_MMU | 7548 | #if ENABLE_FEATURE_SH_STANDALONE && BB_MMU |
@@ -7131,7 +7550,7 @@ static void close_saved_fds_and_FILE_fds(void) | |||
7131 | { | 7550 | { |
7132 | if (G_interactive_fd) | 7551 | if (G_interactive_fd) |
7133 | close(G_interactive_fd); | 7552 | close(G_interactive_fd); |
7134 | close_all_FILE_list(); | 7553 | close_all_HFILE_list(); |
7135 | } | 7554 | } |
7136 | #endif | 7555 | #endif |
7137 | 7556 | ||
@@ -7144,7 +7563,7 @@ static int internally_opened_fd(int fd, struct squirrel *sq) | |||
7144 | return 1; | 7563 | return 1; |
7145 | #endif | 7564 | #endif |
7146 | /* If this one of script's fds? */ | 7565 | /* If this one of script's fds? */ |
7147 | if (fd_in_FILEs(fd)) | 7566 | if (fd_in_HFILEs(fd)) |
7148 | return 1; | 7567 | return 1; |
7149 | 7568 | ||
7150 | if (sq) for (i = 0; sq[i].orig_fd >= 0; i++) { | 7569 | if (sq) for (i = 0; sq[i].orig_fd >= 0; i++) { |
@@ -7169,7 +7588,7 @@ static int setup_redirects(struct command *prog, struct squirrel **sqp) | |||
7169 | save_fd_on_redirect(redir->rd_fd, /*avoid:*/ 0, sqp); | 7588 | save_fd_on_redirect(redir->rd_fd, /*avoid:*/ 0, sqp); |
7170 | /* for REDIRECT_HEREDOC2, rd_filename holds _contents_ | 7589 | /* for REDIRECT_HEREDOC2, rd_filename holds _contents_ |
7171 | * of the heredoc */ | 7590 | * of the heredoc */ |
7172 | debug_printf_parse("set heredoc '%s'\n", | 7591 | debug_printf_redir("set heredoc '%s'\n", |
7173 | redir->rd_filename); | 7592 | redir->rd_filename); |
7174 | setup_heredoc(redir); | 7593 | setup_heredoc(redir); |
7175 | continue; | 7594 | continue; |
@@ -7181,8 +7600,7 @@ static int setup_redirects(struct command *prog, struct squirrel **sqp) | |||
7181 | int mode; | 7600 | int mode; |
7182 | 7601 | ||
7183 | if (redir->rd_filename == NULL) { | 7602 | if (redir->rd_filename == NULL) { |
7184 | /* | 7603 | /* Examples: |
7185 | * Examples: | ||
7186 | * "cmd >" (no filename) | 7604 | * "cmd >" (no filename) |
7187 | * "cmd > <file" (2nd redirect starts too early) | 7605 | * "cmd > <file" (2nd redirect starts too early) |
7188 | */ | 7606 | */ |
@@ -7238,7 +7656,7 @@ static int setup_redirects(struct command *prog, struct squirrel **sqp) | |||
7238 | */ | 7656 | */ |
7239 | } else { | 7657 | } else { |
7240 | /* if newfd is a script fd or saved fd, simulate EBADF */ | 7658 | /* if newfd is a script fd or saved fd, simulate EBADF */ |
7241 | if (internally_opened_fd(newfd, sqp ? *sqp : NULL)) { | 7659 | if (internally_opened_fd(newfd, sqp && sqp != ERR_PTR ? *sqp : NULL)) { |
7242 | //errno = EBADF; | 7660 | //errno = EBADF; |
7243 | //bb_perror_msg_and_die("can't duplicate file descriptor"); | 7661 | //bb_perror_msg_and_die("can't duplicate file descriptor"); |
7244 | newfd = -1; /* same effect as code above */ | 7662 | newfd = -1; /* same effect as code above */ |
@@ -7312,6 +7730,58 @@ static const struct built_in_command *find_builtin(const char *name) | |||
7312 | return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]); | 7730 | return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]); |
7313 | } | 7731 | } |
7314 | 7732 | ||
7733 | static void remove_nested_vars(void) | ||
7734 | { | ||
7735 | struct variable *cur; | ||
7736 | struct variable **cur_pp; | ||
7737 | |||
7738 | cur_pp = &G.top_var; | ||
7739 | while ((cur = *cur_pp) != NULL) { | ||
7740 | if (cur->var_nest_level <= G.var_nest_level) { | ||
7741 | cur_pp = &cur->next; | ||
7742 | continue; | ||
7743 | } | ||
7744 | /* Unexport */ | ||
7745 | if (cur->flg_export) { | ||
7746 | debug_printf_env("unexporting nested '%s'/%u\n", cur->varstr, cur->var_nest_level); | ||
7747 | bb_unsetenv(cur->varstr); | ||
7748 | } | ||
7749 | /* Remove from global list */ | ||
7750 | *cur_pp = cur->next; | ||
7751 | /* Free */ | ||
7752 | if (!cur->max_len) { | ||
7753 | debug_printf_env("freeing nested '%s'/%u\n", cur->varstr, cur->var_nest_level); | ||
7754 | free(cur->varstr); | ||
7755 | } | ||
7756 | free(cur); | ||
7757 | } | ||
7758 | } | ||
7759 | |||
7760 | static void enter_var_nest_level(void) | ||
7761 | { | ||
7762 | G.var_nest_level++; | ||
7763 | debug_printf_env("var_nest_level++ %u\n", G.var_nest_level); | ||
7764 | |||
7765 | /* Try: f() { echo -n .; f; }; f | ||
7766 | * struct variable::var_nest_level is uint16_t, | ||
7767 | * thus limiting recursion to < 2^16. | ||
7768 | * In any case, with 8 Mbyte stack SEGV happens | ||
7769 | * not too long after 2^16 recursions anyway. | ||
7770 | */ | ||
7771 | if (G.var_nest_level > 0xff00) | ||
7772 | bb_error_msg_and_die("fatal recursion (depth %u)", G.var_nest_level); | ||
7773 | } | ||
7774 | |||
7775 | static void leave_var_nest_level(void) | ||
7776 | { | ||
7777 | G.var_nest_level--; | ||
7778 | debug_printf_env("var_nest_level-- %u\n", G.var_nest_level); | ||
7779 | if (HUSH_DEBUG && (int)G.var_nest_level < 0) | ||
7780 | bb_error_msg_and_die("BUG: nesting underflow"); | ||
7781 | |||
7782 | remove_nested_vars(); | ||
7783 | } | ||
7784 | |||
7315 | #if ENABLE_HUSH_FUNCTIONS | 7785 | #if ENABLE_HUSH_FUNCTIONS |
7316 | static struct function **find_function_slot(const char *name) | 7786 | static struct function **find_function_slot(const char *name) |
7317 | { | 7787 | { |
@@ -7398,58 +7868,6 @@ static void unset_func(const char *name) | |||
7398 | } | 7868 | } |
7399 | # endif | 7869 | # endif |
7400 | 7870 | ||
7401 | static void remove_nested_vars(void) | ||
7402 | { | ||
7403 | struct variable *cur; | ||
7404 | struct variable **cur_pp; | ||
7405 | |||
7406 | cur_pp = &G.top_var; | ||
7407 | while ((cur = *cur_pp) != NULL) { | ||
7408 | if (cur->var_nest_level <= G.var_nest_level) { | ||
7409 | cur_pp = &cur->next; | ||
7410 | continue; | ||
7411 | } | ||
7412 | /* Unexport */ | ||
7413 | if (cur->flg_export) { | ||
7414 | debug_printf_env("unexporting nested '%s'/%u\n", cur->varstr, cur->var_nest_level); | ||
7415 | bb_unsetenv(cur->varstr); | ||
7416 | } | ||
7417 | /* Remove from global list */ | ||
7418 | *cur_pp = cur->next; | ||
7419 | /* Free */ | ||
7420 | if (!cur->max_len) { | ||
7421 | debug_printf_env("freeing nested '%s'/%u\n", cur->varstr, cur->var_nest_level); | ||
7422 | free(cur->varstr); | ||
7423 | } | ||
7424 | free(cur); | ||
7425 | } | ||
7426 | } | ||
7427 | |||
7428 | static void enter_var_nest_level(void) | ||
7429 | { | ||
7430 | G.var_nest_level++; | ||
7431 | debug_printf_env("var_nest_level++ %u\n", G.var_nest_level); | ||
7432 | |||
7433 | /* Try: f() { echo -n .; f; }; f | ||
7434 | * struct variable::var_nest_level is uint16_t, | ||
7435 | * thus limiting recursion to < 2^16. | ||
7436 | * In any case, with 8 Mbyte stack SEGV happens | ||
7437 | * not too long after 2^16 recursions anyway. | ||
7438 | */ | ||
7439 | if (G.var_nest_level > 0xff00) | ||
7440 | bb_error_msg_and_die("fatal recursion (depth %u)", G.var_nest_level); | ||
7441 | } | ||
7442 | |||
7443 | static void leave_var_nest_level(void) | ||
7444 | { | ||
7445 | G.var_nest_level--; | ||
7446 | debug_printf_env("var_nest_level-- %u\n", G.var_nest_level); | ||
7447 | if (HUSH_DEBUG && (int)G.var_nest_level < 0) | ||
7448 | bb_error_msg_and_die("BUG: nesting underflow"); | ||
7449 | |||
7450 | remove_nested_vars(); | ||
7451 | } | ||
7452 | |||
7453 | # if BB_MMU | 7871 | # if BB_MMU |
7454 | #define exec_function(to_free, funcp, argv) \ | 7872 | #define exec_function(to_free, funcp, argv) \ |
7455 | exec_function(funcp, argv) | 7873 | exec_function(funcp, argv) |
@@ -8253,8 +8671,8 @@ static int checkjobs_and_fg_shell(struct pipe *fg_pipe) | |||
8253 | * subshell: ( list ) [&] | 8671 | * subshell: ( list ) [&] |
8254 | */ | 8672 | */ |
8255 | #if !ENABLE_HUSH_MODE_X | 8673 | #if !ENABLE_HUSH_MODE_X |
8256 | #define redirect_and_varexp_helper(old_vars_p, command, squirrel, argv_expanded) \ | 8674 | #define redirect_and_varexp_helper(command, sqp, argv_expanded) \ |
8257 | redirect_and_varexp_helper(old_vars_p, command, squirrel) | 8675 | redirect_and_varexp_helper(command, sqp) |
8258 | #endif | 8676 | #endif |
8259 | static int redirect_and_varexp_helper( | 8677 | static int redirect_and_varexp_helper( |
8260 | struct command *command, | 8678 | struct command *command, |
@@ -8271,10 +8689,6 @@ static int redirect_and_varexp_helper( | |||
8271 | /* this takes ownership of new_env[i] elements, and frees new_env: */ | 8689 | /* this takes ownership of new_env[i] elements, and frees new_env: */ |
8272 | set_vars_and_save_old(new_env); | 8690 | set_vars_and_save_old(new_env); |
8273 | 8691 | ||
8274 | /* setup_redirects acts on file descriptors, not FILEs. | ||
8275 | * This is perfect for work that comes after exec(). | ||
8276 | * Is it really safe for inline use? Experimentally, | ||
8277 | * things seem to work. */ | ||
8278 | return setup_redirects(command, sqp); | 8692 | return setup_redirects(command, sqp); |
8279 | } | 8693 | } |
8280 | static NOINLINE int run_pipe(struct pipe *pi) | 8694 | static NOINLINE int run_pipe(struct pipe *pi) |
@@ -8363,7 +8777,7 @@ static NOINLINE int run_pipe(struct pipe *pi) | |||
8363 | } | 8777 | } |
8364 | #endif | 8778 | #endif |
8365 | /* { list } */ | 8779 | /* { list } */ |
8366 | debug_printf("non-subshell group\n"); | 8780 | debug_printf_exec("non-subshell group\n"); |
8367 | rcode = 1; /* exitcode if redir failed */ | 8781 | rcode = 1; /* exitcode if redir failed */ |
8368 | if (setup_redirects(command, &squirrel) == 0) { | 8782 | if (setup_redirects(command, &squirrel) == 0) { |
8369 | debug_printf_exec(": run_list\n"); | 8783 | debug_printf_exec(": run_list\n"); |
@@ -8475,7 +8889,10 @@ static NOINLINE int run_pipe(struct pipe *pi) | |||
8475 | */ | 8889 | */ |
8476 | enter_var_nest_level(); | 8890 | enter_var_nest_level(); |
8477 | G.shadowed_vars_pp = &old_vars; | 8891 | G.shadowed_vars_pp = &old_vars; |
8478 | rcode = redirect_and_varexp_helper(command, /*squirrel:*/ NULL, argv_expanded); | 8892 | rcode = redirect_and_varexp_helper(command, |
8893 | /*squirrel:*/ ERR_PTR, | ||
8894 | argv_expanded | ||
8895 | ); | ||
8479 | G.shadowed_vars_pp = sv_shadowed; | 8896 | G.shadowed_vars_pp = sv_shadowed; |
8480 | /* rcode=1 can be if redir file can't be opened */ | 8897 | /* rcode=1 can be if redir file can't be opened */ |
8481 | 8898 | ||
@@ -9528,14 +9945,13 @@ int hush_main(int argc, char **argv) | |||
9528 | 9945 | ||
9529 | /* If we are login shell... */ | 9946 | /* If we are login shell... */ |
9530 | if (flags & OPT_login) { | 9947 | if (flags & OPT_login) { |
9531 | FILE *input; | 9948 | HFILE *input; |
9532 | debug_printf("sourcing /etc/profile\n"); | 9949 | debug_printf("sourcing /etc/profile\n"); |
9533 | input = fopen_for_read("/etc/profile"); | 9950 | input = hfopen("/etc/profile"); |
9534 | if (input != NULL) { | 9951 | if (input != NULL) { |
9535 | remember_FILE(input); | ||
9536 | install_special_sighandlers(); | 9952 | install_special_sighandlers(); |
9537 | parse_and_run_file(input); | 9953 | parse_and_run_file(input); |
9538 | fclose_and_forget(input); | 9954 | hfclose(input); |
9539 | } | 9955 | } |
9540 | /* bash: after sourcing /etc/profile, | 9956 | /* bash: after sourcing /etc/profile, |
9541 | * tries to source (in the given order): | 9957 | * tries to source (in the given order): |
@@ -9548,7 +9964,7 @@ int hush_main(int argc, char **argv) | |||
9548 | 9964 | ||
9549 | /* -s is: hush -s ARGV1 ARGV2 (no SCRIPT) */ | 9965 | /* -s is: hush -s ARGV1 ARGV2 (no SCRIPT) */ |
9550 | if (!(flags & OPT_s) && G.global_argv[1]) { | 9966 | if (!(flags & OPT_s) && G.global_argv[1]) { |
9551 | FILE *input; | 9967 | HFILE *input; |
9552 | /* | 9968 | /* |
9553 | * "bash <script>" (which is never interactive (unless -i?)) | 9969 | * "bash <script>" (which is never interactive (unless -i?)) |
9554 | * sources $BASH_ENV here (without scanning $PATH). | 9970 | * sources $BASH_ENV here (without scanning $PATH). |
@@ -9559,13 +9975,15 @@ int hush_main(int argc, char **argv) | |||
9559 | G.global_argv++; | 9975 | G.global_argv++; |
9560 | debug_printf("running script '%s'\n", G.global_argv[0]); | 9976 | debug_printf("running script '%s'\n", G.global_argv[0]); |
9561 | xfunc_error_retval = 127; /* for "hush /does/not/exist" case */ | 9977 | xfunc_error_retval = 127; /* for "hush /does/not/exist" case */ |
9562 | input = xfopen_for_read(G.global_argv[0]); | 9978 | input = hfopen(G.global_argv[0]); |
9979 | if (!input) { | ||
9980 | bb_simple_perror_msg_and_die(G.global_argv[0]); | ||
9981 | } | ||
9563 | xfunc_error_retval = 1; | 9982 | xfunc_error_retval = 1; |
9564 | remember_FILE(input); | ||
9565 | install_special_sighandlers(); | 9983 | install_special_sighandlers(); |
9566 | parse_and_run_file(input); | 9984 | parse_and_run_file(input); |
9567 | #if ENABLE_FEATURE_CLEAN_UP | 9985 | #if ENABLE_FEATURE_CLEAN_UP |
9568 | fclose_and_forget(input); | 9986 | hfclose(input); |
9569 | #endif | 9987 | #endif |
9570 | goto final_return; | 9988 | goto final_return; |
9571 | } | 9989 | } |
@@ -9666,7 +10084,7 @@ int hush_main(int argc, char **argv) | |||
9666 | G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254); | 10084 | G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254); |
9667 | if (G_interactive_fd < 0) { | 10085 | if (G_interactive_fd < 0) { |
9668 | /* try to dup to any fd */ | 10086 | /* try to dup to any fd */ |
9669 | G_interactive_fd = dup_CLOEXEC(STDIN_FILENO); | 10087 | G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, -1); |
9670 | if (G_interactive_fd < 0) | 10088 | if (G_interactive_fd < 0) |
9671 | /* give up */ | 10089 | /* give up */ |
9672 | G_interactive_fd = 0; | 10090 | G_interactive_fd = 0; |
@@ -9695,7 +10113,7 @@ int hush_main(int argc, char **argv) | |||
9695 | ); | 10113 | ); |
9696 | } | 10114 | } |
9697 | 10115 | ||
9698 | parse_and_run_file(stdin); | 10116 | parse_and_run_file(hfopen(NULL)); /* stdin */ |
9699 | 10117 | ||
9700 | final_return: | 10118 | final_return: |
9701 | hush_exit(G.last_exitcode); | 10119 | hush_exit(G.last_exitcode); |
@@ -9803,41 +10221,41 @@ static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM) | |||
9803 | 10221 | ||
9804 | static int FAST_FUNC builtin_eval(char **argv) | 10222 | static int FAST_FUNC builtin_eval(char **argv) |
9805 | { | 10223 | { |
9806 | int rcode = EXIT_SUCCESS; | ||
9807 | |||
9808 | argv = skip_dash_dash(argv); | 10224 | argv = skip_dash_dash(argv); |
9809 | if (argv[0]) { | ||
9810 | char *str = NULL; | ||
9811 | 10225 | ||
9812 | if (argv[1]) { | 10226 | if (!argv[0]) |
9813 | /* "The eval utility shall construct a command by | 10227 | return EXIT_SUCCESS; |
9814 | * concatenating arguments together, separating | ||
9815 | * each with a <space> character." | ||
9816 | */ | ||
9817 | char *p; | ||
9818 | unsigned len = 0; | ||
9819 | char **pp = argv; | ||
9820 | do | ||
9821 | len += strlen(*pp) + 1; | ||
9822 | while (*++pp); | ||
9823 | str = p = xmalloc(len); | ||
9824 | pp = argv; | ||
9825 | do { | ||
9826 | p = stpcpy(p, *pp); | ||
9827 | *p++ = ' '; | ||
9828 | } while (*++pp); | ||
9829 | p[-1] = '\0'; | ||
9830 | } | ||
9831 | 10228 | ||
10229 | if (!argv[1]) { | ||
9832 | /* bash: | 10230 | /* bash: |
9833 | * eval "echo Hi; done" ("done" is syntax error): | 10231 | * eval "echo Hi; done" ("done" is syntax error): |
9834 | * "echo Hi" will not execute too. | 10232 | * "echo Hi" will not execute too. |
9835 | */ | 10233 | */ |
9836 | parse_and_run_string(str ? str : argv[0]); | 10234 | parse_and_run_string(argv[0]); |
10235 | } else { | ||
10236 | /* "The eval utility shall construct a command by | ||
10237 | * concatenating arguments together, separating | ||
10238 | * each with a <space> character." | ||
10239 | */ | ||
10240 | char *str, *p; | ||
10241 | unsigned len = 0; | ||
10242 | char **pp = argv; | ||
10243 | do | ||
10244 | len += strlen(*pp) + 1; | ||
10245 | while (*++pp); | ||
10246 | str = p = xmalloc(len); | ||
10247 | pp = argv; | ||
10248 | for (;;) { | ||
10249 | p = stpcpy(p, *pp); | ||
10250 | pp++; | ||
10251 | if (!*pp) | ||
10252 | break; | ||
10253 | *p++ = ' '; | ||
10254 | } | ||
10255 | parse_and_run_string(str); | ||
9837 | free(str); | 10256 | free(str); |
9838 | rcode = G.last_exitcode; | ||
9839 | } | 10257 | } |
9840 | return rcode; | 10258 | return G.last_exitcode; |
9841 | } | 10259 | } |
9842 | 10260 | ||
9843 | static int FAST_FUNC builtin_exec(char **argv) | 10261 | static int FAST_FUNC builtin_exec(char **argv) |
@@ -10506,7 +10924,7 @@ Test that VAR is a valid variable name? | |||
10506 | static int FAST_FUNC builtin_source(char **argv) | 10924 | static int FAST_FUNC builtin_source(char **argv) |
10507 | { | 10925 | { |
10508 | char *arg_path, *filename; | 10926 | char *arg_path, *filename; |
10509 | FILE *input; | 10927 | HFILE *input; |
10510 | save_arg_t sv; | 10928 | save_arg_t sv; |
10511 | char *args_need_save; | 10929 | char *args_need_save; |
10512 | #if ENABLE_HUSH_FUNCTIONS | 10930 | #if ENABLE_HUSH_FUNCTIONS |
@@ -10530,10 +10948,10 @@ static int FAST_FUNC builtin_source(char **argv) | |||
10530 | return EXIT_FAILURE; | 10948 | return EXIT_FAILURE; |
10531 | } | 10949 | } |
10532 | } | 10950 | } |
10533 | input = remember_FILE(fopen_or_warn(filename, "r")); | 10951 | input = hfopen(filename); |
10534 | free(arg_path); | 10952 | free(arg_path); |
10535 | if (!input) { | 10953 | if (!input) { |
10536 | /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */ | 10954 | bb_perror_msg("%s", filename); |
10537 | /* POSIX: non-interactive shell should abort here, | 10955 | /* POSIX: non-interactive shell should abort here, |
10538 | * not merely fail. So far no one complained :) | 10956 | * not merely fail. So far no one complained :) |
10539 | */ | 10957 | */ |
@@ -10552,7 +10970,7 @@ static int FAST_FUNC builtin_source(char **argv) | |||
10552 | /* "false; . ./empty_line; echo Zero:$?" should print 0 */ | 10970 | /* "false; . ./empty_line; echo Zero:$?" should print 0 */ |
10553 | G.last_exitcode = 0; | 10971 | G.last_exitcode = 0; |
10554 | parse_and_run_file(input); | 10972 | parse_and_run_file(input); |
10555 | fclose_and_forget(input); | 10973 | hfclose(input); |
10556 | 10974 | ||
10557 | if (args_need_save) /* can't use argv[1] instead: "shift" can mangle it */ | 10975 | if (args_need_save) /* can't use argv[1] instead: "shift" can mangle it */ |
10558 | restore_G_args(&sv, argv); | 10976 | restore_G_args(&sv, argv); |
diff --git a/shell/hush_test/hush-glob/glob_altvalue1.right b/shell/hush_test/hush-glob/glob_altvalue1.right new file mode 100644 index 000000000..bd3592229 --- /dev/null +++ b/shell/hush_test/hush-glob/glob_altvalue1.right | |||
@@ -0,0 +1,7 @@ | |||
1 | 1u: glob_altvalue1.tests | ||
2 | 2u: glob_altvalue1.t* | ||
3 | 3u: glob_altvalue1.t* | ||
4 | 4u: glob_altvalue1.t* | ||
5 | 1q: glob_altvalue1.t* | ||
6 | 2q: 'glob_altvalue1.t*' | ||
7 | 3q: glob_altvalue1.t* | ||
diff --git a/shell/hush_test/hush-glob/glob_altvalue1.tests b/shell/hush_test/hush-glob/glob_altvalue1.tests new file mode 100755 index 000000000..5483d63e6 --- /dev/null +++ b/shell/hush_test/hush-glob/glob_altvalue1.tests | |||
@@ -0,0 +1,13 @@ | |||
1 | x=x | ||
2 | |||
3 | echo 1u: ${x:+glob_altvalue1.t*} | ||
4 | echo 2u: ${x:+'glob_altvalue1.t*'} | ||
5 | echo 3u: ${x:+"glob_altvalue1.t*"} | ||
6 | echo 4u: ${x:+glob_altvalue1.t\*} | ||
7 | ##echo 5u: ${x:+"glob_altvalue1.t\*"} | ||
8 | |||
9 | echo 1q: "${x:+glob_altvalue1.t*}" | ||
10 | echo 2q: "${x:+'glob_altvalue1.t*'}" | ||
11 | echo 3q: "${x:+"glob_altvalue1.t*"}" | ||
12 | ##echo 4q: "${x:+glob_altvalue1.t\*}" | ||
13 | ##echo 5q: "${x:+"glob_altvalue1.t\*"}" | ||
diff --git a/shell/hush_test/hush-heredoc/heredoc.right b/shell/hush_test/hush-heredoc/heredoc.right new file mode 100644 index 000000000..9b9e2aae9 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc.right | |||
@@ -0,0 +1,20 @@ | |||
1 | there | ||
2 | one - alpha | ||
3 | two - beta | ||
4 | three - gamma | ||
5 | hi\ | ||
6 | there$a | ||
7 | stuff | ||
8 | hi\ | ||
9 | there | ||
10 | EO\ | ||
11 | F | ||
12 | hi | ||
13 | hi | ||
14 | tab 1 | ||
15 | tab 2 | ||
16 | tab 3 | ||
17 | abc | ||
18 | def ghi | ||
19 | jkl mno | ||
20 | fff is a function | ||
diff --git a/shell/hush_test/hush-heredoc/heredoc.tests b/shell/hush_test/hush-heredoc/heredoc.tests new file mode 100755 index 000000000..39345c51b --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc.tests | |||
@@ -0,0 +1,97 @@ | |||
1 | # check order and content of multiple here docs | ||
2 | |||
3 | cat << EOF1 << EOF2 | ||
4 | hi | ||
5 | EOF1 | ||
6 | there | ||
7 | EOF2 | ||
8 | |||
9 | while read line1; do | ||
10 | read line2 <&3 | ||
11 | echo $line1 - $line2 | ||
12 | done <<EOF1 3<<EOF2 | ||
13 | one | ||
14 | two | ||
15 | three | ||
16 | EOF1 | ||
17 | alpha | ||
18 | beta | ||
19 | gamma | ||
20 | EOF2 | ||
21 | |||
22 | |||
23 | # check quoted here-doc is protected | ||
24 | |||
25 | a=foo | ||
26 | cat << 'EOF' | ||
27 | hi\ | ||
28 | there$a | ||
29 | stuff | ||
30 | EOF | ||
31 | |||
32 | # check that quoted here-documents don't have \newline processing done | ||
33 | |||
34 | cat << 'EOF' | ||
35 | hi\ | ||
36 | there | ||
37 | EO\ | ||
38 | F | ||
39 | EOF | ||
40 | true | ||
41 | |||
42 | # check that \newline is removed at start of here-doc | ||
43 | cat << EO\ | ||
44 | F | ||
45 | hi | ||
46 | EOF | ||
47 | |||
48 | # check that \newline removal works for here-doc delimiter | ||
49 | cat << EOF | ||
50 | hi | ||
51 | EO\ | ||
52 | F | ||
53 | |||
54 | # check operation of tab removal in here documents | ||
55 | cat <<- EOF | ||
56 | tab 1 | ||
57 | tab 2 | ||
58 | tab 3 | ||
59 | EOF | ||
60 | |||
61 | # check appending of text to file from here document | ||
62 | rm -f /tmp/bash-zzz | ||
63 | cat > /tmp/bash-zzz << EOF | ||
64 | abc | ||
65 | EOF | ||
66 | cat >> /tmp/bash-zzz << EOF | ||
67 | def ghi | ||
68 | jkl mno | ||
69 | EOF | ||
70 | cat /tmp/bash-zzz | ||
71 | rm -f /tmp/bash-zzz | ||
72 | |||
73 | # make sure command printing puts the here-document as the last redirection | ||
74 | # on the line, and the function export code preserves syntactic correctness | ||
75 | fff() | ||
76 | { | ||
77 | ed /tmp/foo <<ENDOFINPUT >/dev/null | ||
78 | /^name/d | ||
79 | w | ||
80 | q | ||
81 | ENDOFINPUT | ||
82 | aa=1 | ||
83 | } | ||
84 | |||
85 | type fff | ||
86 | #ash# export -f fff | ||
87 | #ash# ${THIS_SH} -c 'type fff' | ||
88 | |||
89 | #hush# bash warns: "here-document at line N delimited by end-of-file", | ||
90 | #hush# ash allows it, | ||
91 | #hush# hush errors out for now: | ||
92 | #hush# # check that end of file delimits a here-document | ||
93 | #hush# # THIS MUST BE LAST! | ||
94 | #hush# | ||
95 | #hush# cat << EOF | ||
96 | #hush# hi | ||
97 | #hush# there | ||
diff --git a/shell/hush_test/hush-heredoc/heredoc9.right b/shell/hush_test/hush-heredoc/heredoc9.right new file mode 100644 index 000000000..ce0136250 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc9.right | |||
@@ -0,0 +1 @@ | |||
hello | |||
diff --git a/shell/hush_test/hush-heredoc/heredoc9.tests b/shell/hush_test/hush-heredoc/heredoc9.tests new file mode 100755 index 000000000..96c227cc1 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc9.tests | |||
@@ -0,0 +1,9 @@ | |||
1 | echo hello >greeting | ||
2 | cat <<EOF && | ||
3 | $(cat greeting) | ||
4 | EOF | ||
5 | { | ||
6 | echo $? | ||
7 | cat greeting | ||
8 | } >/dev/null | ||
9 | rm greeting | ||
diff --git a/shell/hush_test/hush-heredoc/heredocA.right b/shell/hush_test/hush-heredoc/heredocA.right new file mode 100644 index 000000000..7326d9603 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredocA.right | |||
@@ -0,0 +1 @@ | |||
Ok | |||
diff --git a/shell/hush_test/hush-heredoc/heredocA.tests b/shell/hush_test/hush-heredoc/heredocA.tests new file mode 100755 index 000000000..440aaf906 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredocA.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | { cat <<EOF ; | ||
2 | Ok | ||
3 | EOF | ||
4 | } | ||
diff --git a/shell/hush_test/hush-heredoc/heredocB.right b/shell/hush_test/hush-heredoc/heredocB.right new file mode 100644 index 000000000..43ba0b4f9 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredocB.right | |||
@@ -0,0 +1,3 @@ | |||
1 | one - alpha | ||
2 | two - beta | ||
3 | three - gamma | ||
diff --git a/shell/hush_test/hush-heredoc/heredocB.tests b/shell/hush_test/hush-heredoc/heredocB.tests new file mode 100755 index 000000000..45ea4687f --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredocB.tests | |||
@@ -0,0 +1,12 @@ | |||
1 | while read line1; do | ||
2 | read line2 <&3 | ||
3 | echo $line1 - $line2 | ||
4 | done <<EOF1 3<<EOF2 | ||
5 | one | ||
6 | two | ||
7 | three | ||
8 | EOF1 | ||
9 | alpha | ||
10 | beta | ||
11 | gamma | ||
12 | EOF2 | ||
diff --git a/shell/hush_test/hush-heredoc/heredoc_after_compound1.right b/shell/hush_test/hush-heredoc/heredoc_after_compound1.right new file mode 100644 index 000000000..9052f7d1f --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_after_compound1.right | |||
@@ -0,0 +1,2 @@ | |||
1 | Ok1 | ||
2 | Ok2 | ||
diff --git a/shell/hush_test/hush-heredoc/heredoc_after_compound1.tests b/shell/hush_test/hush-heredoc/heredoc_after_compound1.tests new file mode 100755 index 000000000..e7cfb5be1 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_after_compound1.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | { cat <<EOF; }; echo Ok2 | ||
2 | Ok1 | ||
3 | EOF | ||
diff --git a/shell/hush_test/hush-heredoc/heredoc_bkslash_newline2.right b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline2.right new file mode 100644 index 000000000..3d79316d7 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline2.right | |||
@@ -0,0 +1 @@ | |||
Ok1 | |||
diff --git a/shell/hush_test/hush-heredoc/heredoc_bkslash_newline2.tests b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline2.tests new file mode 100755 index 000000000..1d2a26504 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline2.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | cat <<EOF | ||
2 | Ok1 | ||
3 | EO\ | ||
4 | F | ||
diff --git a/shell/hush_test/hush-heredoc/heredoc_empty3.right b/shell/hush_test/hush-heredoc/heredoc_empty3.right new file mode 100644 index 000000000..0b54a9c93 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_empty3.right | |||
@@ -0,0 +1,2 @@ | |||
1 | |||
2 | Ok | ||
diff --git a/shell/hush_test/hush-heredoc/heredoc_empty3.tests b/shell/hush_test/hush-heredoc/heredoc_empty3.tests new file mode 100755 index 000000000..828c2dd89 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_empty3.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | cat <<EOF | ||
2 | |||
3 | Ok | ||
4 | EOF | ||
diff --git a/shell/hush_test/hush-heredoc/heredoc_var_expand1.right b/shell/hush_test/hush-heredoc/heredoc_var_expand1.right new file mode 100644 index 000000000..eb221832d --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_var_expand1.right | |||
@@ -0,0 +1,4 @@ | |||
1 | |||
2 | Ok1:0 | ||
3 | |||
4 | Ok2:0 | ||
diff --git a/shell/hush_test/hush-heredoc/heredoc_var_expand1.tests b/shell/hush_test/hush-heredoc/heredoc_var_expand1.tests new file mode 100755 index 000000000..3b00bab7b --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_var_expand1.tests | |||
@@ -0,0 +1,11 @@ | |||
1 | x='*' | ||
2 | |||
3 | cat <<- EOF | ||
4 | ${x#'*'} | ||
5 | EOF | ||
6 | echo Ok1:$? | ||
7 | |||
8 | cat <<EOF | ||
9 | ${x#'*'} | ||
10 | EOF | ||
11 | echo Ok2:$? | ||
diff --git a/shell/hush_test/hush-quoting/dollar_altvalue1.right b/shell/hush_test/hush-quoting/dollar_altvalue1.right new file mode 100644 index 000000000..5cd495d3b --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_altvalue1.right | |||
@@ -0,0 +1,16 @@ | |||
1 | Unquoted b c d | ||
2 | |b| | ||
3 | |c| | ||
4 | |d| | ||
5 | Unquoted 'b c' d | ||
6 | |b c| | ||
7 | |d| | ||
8 | Unquoted "b c" d | ||
9 | |b c| | ||
10 | |d| | ||
11 | Quoted b c d | ||
12 | |b c d| | ||
13 | Quoted 'b c' d | ||
14 | |'b c' d| | ||
15 | Quoted "b c" d | ||
16 | |b c d| | ||
diff --git a/shell/hush_test/hush-quoting/dollar_altvalue1.tests b/shell/hush_test/hush-quoting/dollar_altvalue1.tests new file mode 100755 index 000000000..f4dc8caec --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_altvalue1.tests | |||
@@ -0,0 +1,16 @@ | |||
1 | f() { for i; do echo "|$i|"; done; } | ||
2 | x=a | ||
3 | |||
4 | echo Unquoted b c d | ||
5 | f ${x:+b c d} | ||
6 | echo Unquoted "'b c' d" | ||
7 | f ${x:+'b c' d} | ||
8 | echo Unquoted '"b c" d' | ||
9 | f ${x:+"b c" d} | ||
10 | |||
11 | echo Quoted b c d | ||
12 | f "${x:+b c d}" | ||
13 | echo Quoted "'b c' d" | ||
14 | f "${x:+'b c' d}" | ||
15 | echo Quoted '"b c" d' | ||
16 | f "${x:+"b c" d}" | ||
diff --git a/shell/hush_test/hush-quoting/dollar_altvalue2.right b/shell/hush_test/hush-quoting/dollar_altvalue2.right new file mode 100644 index 000000000..7cf37e379 --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_altvalue2.right | |||
@@ -0,0 +1,69 @@ | |||
1 | Unquoted '': | ||
2 | start: | ||
3 | || | ||
4 | end | ||
5 | start: | ||
6 | || | ||
7 | end | ||
8 | start: | ||
9 | || | ||
10 | end | ||
11 | start: | ||
12 | || | ||
13 | end | ||
14 | start: | ||
15 | || | ||
16 | || | ||
17 | end | ||
18 | |||
19 | Unquoted "": | ||
20 | start: | ||
21 | || | ||
22 | end | ||
23 | start: | ||
24 | || | ||
25 | end | ||
26 | start: | ||
27 | || | ||
28 | end | ||
29 | start: | ||
30 | || | ||
31 | end | ||
32 | start: | ||
33 | || | ||
34 | || | ||
35 | end | ||
36 | |||
37 | Quoted '': | ||
38 | start: | ||
39 | |''| | ||
40 | end | ||
41 | start: | ||
42 | |'' | | ||
43 | end | ||
44 | start: | ||
45 | | ''| | ||
46 | end | ||
47 | start: | ||
48 | | '' | | ||
49 | end | ||
50 | start: | ||
51 | |'' ''| | ||
52 | end | ||
53 | |||
54 | Quoted "": | ||
55 | start: | ||
56 | || | ||
57 | end | ||
58 | start: | ||
59 | | | | ||
60 | end | ||
61 | start: | ||
62 | | | | ||
63 | end | ||
64 | start: | ||
65 | | | | ||
66 | end | ||
67 | start: | ||
68 | | | | ||
69 | end | ||
diff --git a/shell/hush_test/hush-quoting/dollar_altvalue2.tests b/shell/hush_test/hush-quoting/dollar_altvalue2.tests new file mode 100755 index 000000000..3377eb27f --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_altvalue2.tests | |||
@@ -0,0 +1,33 @@ | |||
1 | f() { echo start:; for i; do echo "|$i|"; done; echo end; } | ||
2 | x=a | ||
3 | |||
4 | echo "Unquoted '':" | ||
5 | f ${x:+''} | ||
6 | f ${x:+'' } | ||
7 | f ${x:+ ''} | ||
8 | f ${x:+ '' } | ||
9 | f ${x:+'' ''} | ||
10 | |||
11 | echo | ||
12 | echo 'Unquoted "":' | ||
13 | f ${x:+""} | ||
14 | f ${x:+"" } | ||
15 | f ${x:+ ""} | ||
16 | f ${x:+ "" } | ||
17 | f ${x:+"" ""} | ||
18 | |||
19 | echo | ||
20 | echo "Quoted '':" | ||
21 | f "${x:+''}" | ||
22 | f "${x:+'' }" | ||
23 | f "${x:+ ''}" | ||
24 | f "${x:+ '' }" | ||
25 | f "${x:+'' ''}" | ||
26 | |||
27 | echo | ||
28 | echo 'Quoted "":' | ||
29 | f "${x:+""}" | ||
30 | f "${x:+"" }" | ||
31 | f "${x:+ ""}" | ||
32 | f "${x:+ "" }" | ||
33 | f "${x:+"" ""}" | ||
diff --git a/shell/hush_test/hush-quoting/dollar_altvalue9.right b/shell/hush_test/hush-quoting/dollar_altvalue9.right new file mode 100644 index 000000000..39342fe7c --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_altvalue9.right | |||
@@ -0,0 +1,26 @@ | |||
1 | Unquoted 1: | ||
2 | |a| | ||
3 | |x y| | ||
4 | |1| | ||
5 | |2| | ||
6 | || | ||
7 | |1 2| | ||
8 | |A| | ||
9 | |B| | ||
10 | |C D| | ||
11 | |zb| | ||
12 | Quoted 1: | ||
13 | |a 'x y' 1 2 '' 1 2 A B C D zb| | ||
14 | Unquoted 2: | ||
15 | |ax y| | ||
16 | |1| | ||
17 | |2| | ||
18 | || | ||
19 | |1 2| | ||
20 | |A| | ||
21 | |B| | ||
22 | |C D| | ||
23 | |z| | ||
24 | |b| | ||
25 | Quoted 2: | ||
26 | |a 'x y' 1 2 '' 1 2 A B C D z b| | ||
diff --git a/shell/hush_test/hush-quoting/dollar_altvalue9.tests b/shell/hush_test/hush-quoting/dollar_altvalue9.tests new file mode 100755 index 000000000..27a6f4f3c --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_altvalue9.tests | |||
@@ -0,0 +1,17 @@ | |||
1 | f() { for i; do echo "|$i|"; done; } | ||
2 | |||
3 | echo Unquoted 1: | ||
4 | x='1 2'; f a${x:+ 'x y' $x '' "$x" `echo A B` "`echo C D`" z}b | ||
5 | echo Quoted 1: | ||
6 | x='1 2'; f "a${x:+ 'x y' $x '' "$x" `echo A B` "`echo C D`" z}b" | ||
7 | |||
8 | echo Unquoted 2: | ||
9 | x='1 2'; f a${x:+'x y' $x '' "$x" `echo A B` "`echo C D`" z }b | ||
10 | echo Quoted 2: | ||
11 | x='1 2'; f "a${x:+ 'x y' $x '' "$x" `echo A B` "`echo C D`" z }b" | ||
12 | |||
13 | #echo Unquoted 3: | ||
14 | #e= | ||
15 | #x='1 2'; f a${x:+'x y' $x '' "$x" $e $e "$e" $e `echo A B` "`echo C D`" z }b | ||
16 | #echo Quoted 3: | ||
17 | #x='1 2'; f "a${x:+ 'x y' $x '' "$x" $e $e "$e" $e `echo A B` "`echo C D`" z }b" | ||
diff --git a/shell/hush_test/hush-quoting/dollar_repl_bash1.right b/shell/hush_test/hush-quoting/dollar_repl_bash1.right new file mode 100644 index 000000000..f5e9309f4 --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_repl_bash1.right | |||
@@ -0,0 +1,14 @@ | |||
1 | |y| | ||
2 | |zx| | ||
3 | |y| | ||
4 | |zx| | ||
5 | |y zx| | ||
6 | |y zx| | ||
7 | |y| | ||
8 | |zy| | ||
9 | |z| | ||
10 | |y| | ||
11 | |zy| | ||
12 | |z| | ||
13 | |y zy z| | ||
14 | |y zy z| | ||
diff --git a/shell/hush_test/hush-quoting/dollar_repl_bash1.tests b/shell/hush_test/hush-quoting/dollar_repl_bash1.tests new file mode 100755 index 000000000..912635925 --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_repl_bash1.tests | |||
@@ -0,0 +1,12 @@ | |||
1 | f() { for i; do echo "|$i|"; done; } | ||
2 | v=xx | ||
3 | |||
4 | f ${v/'x'/"y z"} | ||
5 | f ${v/"x"/'y z'} | ||
6 | f "${v/'x'/"y z"}" | ||
7 | f "${v/"x"/'y z'}" | ||
8 | |||
9 | f ${v//'x'/"y z"} | ||
10 | f ${v//"x"/'y z'} | ||
11 | f "${v//'x'/"y z"}" | ||
12 | f "${v//"x"/'y z'}" | ||
diff --git a/shell/hush_test/hush-quoting/squote_in_varexp.right b/shell/hush_test/hush-quoting/squote_in_varexp.right index a75c0bfd6..4a457021b 100644 --- a/shell/hush_test/hush-quoting/squote_in_varexp.right +++ b/shell/hush_test/hush-quoting/squote_in_varexp.right | |||
@@ -1,5 +1,9 @@ | |||
1 | z | 1 | z |
2 | z | 2 | z |
3 | z | ||
4 | z | ||
5 | y | ||
6 | y | ||
3 | y | 7 | y |
4 | y | 8 | y |
5 | Ok:0 | 9 | Ok:0 |
diff --git a/shell/hush_test/hush-quoting/squote_in_varexp.tests b/shell/hush_test/hush-quoting/squote_in_varexp.tests index a2d05a246..4afc52107 100755 --- a/shell/hush_test/hush-quoting/squote_in_varexp.tests +++ b/shell/hush_test/hush-quoting/squote_in_varexp.tests | |||
@@ -1,6 +1,10 @@ | |||
1 | x=yz | 1 | x=yz |
2 | echo ${x#'y'} | 2 | echo ${x#'y'} |
3 | echo "${x#'y'}" | 3 | echo "${x#'y'}" |
4 | echo ${x#"y"} | ||
5 | echo "${x#"y"}" | ||
4 | echo ${x%'z'} | 6 | echo ${x%'z'} |
5 | echo "${x%'z'}" | 7 | echo "${x%'z'}" |
8 | echo ${x%"z"} | ||
9 | echo "${x%"z"}" | ||
6 | echo Ok:$? | 10 | echo Ok:$? |
diff --git a/shell/hush_test/hush-quoting/squote_in_varexp2.right b/shell/hush_test/hush-quoting/squote_in_varexp2.right index 9d0add3c5..d03047024 100644 --- a/shell/hush_test/hush-quoting/squote_in_varexp2.right +++ b/shell/hush_test/hush-quoting/squote_in_varexp2.right | |||
@@ -1,3 +1,5 @@ | |||
1 | Nothing: | 1 | Nothing: |
2 | Nothing: | 2 | Nothing: |
3 | Nothing: | ||
4 | Nothing: | ||
3 | Ok:0 | 5 | Ok:0 |
diff --git a/shell/hush_test/hush-quoting/squote_in_varexp2.tests b/shell/hush_test/hush-quoting/squote_in_varexp2.tests index 806ad12b9..2797725cc 100755 --- a/shell/hush_test/hush-quoting/squote_in_varexp2.tests +++ b/shell/hush_test/hush-quoting/squote_in_varexp2.tests | |||
@@ -1,4 +1,6 @@ | |||
1 | x='\\\\' | 1 | x='\\\\' |
2 | printf Nothing:'%s\n' ${x#'\\\\'} | 2 | printf Nothing:'%s\n' ${x#'\\\\'} |
3 | printf Nothing:'%s\n' "${x#'\\\\'}" | 3 | printf Nothing:'%s\n' "${x#'\\\\'}" |
4 | printf Nothing:'%s\n' ${x#"\\\\\\\\"} | ||
5 | printf Nothing:'%s\n' "${x#"\\\\\\\\"}" | ||
4 | echo Ok:$? | 6 | echo Ok:$? |
diff --git a/shell/hush_test/hush-redir/redir_script.tests b/shell/hush_test/hush-redir/redir_script.tests index 740daa461..a8d93ce4f 100755 --- a/shell/hush_test/hush-redir/redir_script.tests +++ b/shell/hush_test/hush-redir/redir_script.tests | |||
@@ -27,6 +27,10 @@ test x"$fds1" = x"$fds" \ | |||
27 | test x"$fds1" = x" 10>&- 3>&-" && \ | 27 | test x"$fds1" = x" 10>&- 3>&-" && \ |
28 | test x"$fds" = x" 11>&- 3>&-" \ | 28 | test x"$fds" = x" 11>&- 3>&-" \ |
29 | && { echo "Ok: script fd is not closed"; exit 0; } | 29 | && { echo "Ok: script fd is not closed"; exit 0; } |
30 | # or we see that fd 3 moved to fd 10: | ||
31 | test x"$fds1" = x" 3>&- 4>&-" && \ | ||
32 | test x"$fds" = x" 10>&- 3>&-" \ | ||
33 | && { echo "Ok: script fd is not closed"; exit 0; } | ||
30 | 34 | ||
31 | echo "Bug: script fd is closed" | 35 | echo "Bug: script fd is closed" |
32 | echo "fds1:$fds1" | 36 | echo "fds1:$fds1" |
diff --git a/shell/hush_test/hush-z_slow/many_ifs.tests b/shell/hush_test/hush-z_slow/many_ifs.tests index 1f5b1b3a6..cf9a89874 100755 --- a/shell/hush_test/hush-z_slow/many_ifs.tests +++ b/shell/hush_test/hush-z_slow/many_ifs.tests | |||
@@ -229,8 +229,8 @@ do | |||
229 | '') split "$d0$f1$d1$f2$d2$f3$d3" "[2]($f1)($f2)" "($f1)($f2)" ;; | 229 | '') split "$d0$f1$d1$f2$d2$f3$d3" "[2]($f1)($f2)" "($f1)($f2)" ;; |
230 | ' ') ;; | 230 | ' ') ;; |
231 | *) x=$f2$d2$f3$d3 | 231 | *) x=$f2$d2$f3$d3 |
232 | x=${x# } #was x=${x#' '} hush needs fixing for this to work | 232 | x=${x#' '} |
233 | x=${x% } #was x=${x%' '} | 233 | x=${x%' '} |
234 | split "$d0$f1$d1$f2$d2$f3$d3" "[3]($f1)($f2)($f3)" "($f1)($x)" | 234 | split "$d0$f1$d1$f2$d2$f3$d3" "[3]($f1)($f2)($f3)" "($f1)($x)" |
235 | ;; | 235 | ;; |
236 | esac | 236 | esac |
diff --git a/shell/random.c b/shell/random.c index 614172279..ffe0cc937 100644 --- a/shell/random.c +++ b/shell/random.c | |||
@@ -57,11 +57,11 @@ next_random(random_t *rnd) | |||
57 | * Choices for a,b,c: 10,13,10; 8,9,22; 2,7,3; 23,3,24 | 57 | * Choices for a,b,c: 10,13,10; 8,9,22; 2,7,3; 23,3,24 |
58 | * (given by algorithm author) | 58 | * (given by algorithm author) |
59 | */ | 59 | */ |
60 | enum { | 60 | enum { |
61 | a = 2, | 61 | a = 2, |
62 | b = 7, | 62 | b = 7, |
63 | c = 3, | 63 | c = 3, |
64 | }; | 64 | }; |
65 | 65 | ||
66 | uint32_t t; | 66 | uint32_t t; |
67 | 67 | ||
@@ -165,7 +165,7 @@ int main(int argc, char **argv) | |||
165 | write(1, buf, sizeof(buf)); | 165 | write(1, buf, sizeof(buf)); |
166 | } | 166 | } |
167 | 167 | ||
168 | return 0; | 168 | return 0; |
169 | } | 169 | } |
170 | 170 | ||
171 | #endif | 171 | #endif |
diff --git a/sysklogd/Config.src b/sysklogd/Config.src index 684e7d414..321be0117 100644 --- a/sysklogd/Config.src +++ b/sysklogd/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "System Logging Utilities" | 6 | menu "System Logging Utilities" |
diff --git a/testsuite/bzcat.tests b/testsuite/bzcat.tests index 32c1c5d7f..ad05dcb2c 100755 --- a/testsuite/bzcat.tests +++ b/testsuite/bzcat.tests | |||
@@ -30,10 +30,11 @@ hello_bz2() { | |||
30 | $ECHO -ne "\x17\x72\x45\x38\x50\x90\x5b\xb8\xe8\xa3" | 30 | $ECHO -ne "\x17\x72\x45\x38\x50\x90\x5b\xb8\xe8\xa3" |
31 | } | 31 | } |
32 | 32 | ||
33 | test x"$CONFIG_ZCAT" = x"y" && \ | ||
33 | for ext in \ | 34 | for ext in \ |
34 | `test x"$CONFIG_GUNZIP" = x"y" && echo gz` \ | 35 | `test x"$CONFIG_FEATURE_SEAMLESS_GZ" = x"y" && echo gz` \ |
35 | `test x"$CONFIG_BUNZIP2" = x"y" && echo bz2` \ | 36 | `test x"$CONFIG_FEATURE_SEAMLESS_BZ2" = x"y" && echo bz2` \ |
36 | `test x"$CONFIG_UNCOMPRESS" = x"y" && echo Z` | 37 | `test x"$CONFIG_FEATURE_SEAMLESS_Z" = x"y" && echo Z` |
37 | do | 38 | do |
38 | prep() { | 39 | prep() { |
39 | rm -f t1.$ext t2.$ext t_actual | 40 | rm -f t1.$ext t2.$ext t_actual |
@@ -47,6 +48,8 @@ do | |||
47 | echo "PASS: $1" | 48 | echo "PASS: $1" |
48 | else | 49 | else |
49 | echo "FAIL: $1" | 50 | echo "FAIL: $1" |
51 | #echo "t_actual:" | ||
52 | #cat t_actual | ||
50 | FAILCOUNT=$((FAILCOUNT + 1)) | 53 | FAILCOUNT=$((FAILCOUNT + 1)) |
51 | fi | 54 | fi |
52 | } | 55 | } |
@@ -95,7 +98,8 @@ testing "bzcat can handle compressed zero-length bzip2 files" \ | |||
95 | ## compress algorithm | 98 | ## compress algorithm |
96 | 99 | ||
97 | # "input" file is compressed (.Z) file with "a\n" data | 100 | # "input" file is compressed (.Z) file with "a\n" data |
98 | test x"$CONFIG_UNCOMPRESS" = x"y" && \ | 101 | test x"$CONFIG_ZCAT" = x"y" && \ |
102 | test x"$CONFIG_FEATURE_SEAMLESS_Z" = x"y" && \ | ||
99 | testing "zcat can print many files" \ | 103 | testing "zcat can print many files" \ |
100 | "zcat input input; echo \$?" \ | 104 | "zcat input input; echo \$?" \ |
101 | "\ | 105 | "\ |
@@ -107,7 +111,8 @@ a | |||
107 | " "" | 111 | " "" |
108 | 112 | ||
109 | # "input" file is compressed (.Z) zero byte file | 113 | # "input" file is compressed (.Z) zero byte file |
110 | test x"$CONFIG_UNCOMPRESS" = x"y" && \ | 114 | test x"$CONFIG_ZCAT" = x"y" && \ |
115 | test x"$CONFIG_FEATURE_SEAMLESS_Z" = x"y" && \ | ||
111 | testing "zcat can handle compressed zero-length (.Z) files" \ | 116 | testing "zcat can handle compressed zero-length (.Z) files" \ |
112 | "zcat input input; echo \$?" \ | 117 | "zcat input input; echo \$?" \ |
113 | "0\n" \ | 118 | "0\n" \ |
diff --git a/testsuite/cat.tests b/testsuite/cat.tests index 404ebedeb..10970dc90 100755 --- a/testsuite/cat.tests +++ b/testsuite/cat.tests | |||
@@ -6,16 +6,20 @@ | |||
6 | . ./testing.sh | 6 | . ./testing.sh |
7 | 7 | ||
8 | # testing "description" "command" "result" "infile" "stdin" | 8 | # testing "description" "command" "result" "infile" "stdin" |
9 | optional FEATURE_CATV | ||
9 | testing 'cat -e' \ | 10 | testing 'cat -e' \ |
10 | 'cat -e' \ | 11 | 'cat -e' \ |
11 | 'foo$\n' \ | 12 | 'foo$\n' \ |
12 | '' \ | 13 | '' \ |
13 | 'foo\n' | 14 | 'foo\n' |
15 | SKIP= | ||
14 | 16 | ||
17 | optional FEATURE_CATV | ||
15 | testing 'cat -v' \ | 18 | testing 'cat -v' \ |
16 | 'cat -v' \ | 19 | 'cat -v' \ |
17 | 'foo\n' \ | 20 | 'foo\n' \ |
18 | '' \ | 21 | '' \ |
19 | 'foo\n' | 22 | 'foo\n' |
23 | SKIP= | ||
20 | 24 | ||
21 | exit $FAILCOUNT | 25 | exit $FAILCOUNT |
diff --git a/testsuite/hexdump.tests b/testsuite/hexdump.tests new file mode 100755 index 000000000..45a0c1300 --- /dev/null +++ b/testsuite/hexdump.tests | |||
@@ -0,0 +1,18 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | # Copyright 2018 by Denys Vlasenko <vda.linux@googlemail.com> | ||
4 | # Licensed under GPLv2, see file LICENSE in this source tree. | ||
5 | |||
6 | . ./testing.sh | ||
7 | |||
8 | # testing "description" "command" "result" "infile" "stdin" | ||
9 | testing 'hexdump -C with four NULs' \ | ||
10 | 'hexdump -C' \ | ||
11 | "\ | ||
12 | 00000000 00 00 00 00 |....| | ||
13 | 00000004 | ||
14 | " \ | ||
15 | '' \ | ||
16 | '\0\0\0\0' | ||
17 | |||
18 | exit $FAILCOUNT | ||
diff --git a/testsuite/mount.tests b/testsuite/mount.tests index a0bc50888..91c2e8b42 100755 --- a/testsuite/mount.tests +++ b/testsuite/mount.tests | |||
@@ -10,9 +10,11 @@ test "`id -u`" = 0 || { | |||
10 | exit 0 | 10 | exit 0 |
11 | } | 11 | } |
12 | 12 | ||
13 | # Without MOUNT_LOOP_CREATE, the test will fail if /dev/loopN's do not exist | ||
13 | if test x"$CONFIG_MKFS_MINIX" != x"y" \ | 14 | if test x"$CONFIG_MKFS_MINIX" != x"y" \ |
14 | || test x"$CONFIG_FEATURE_MINIX2" != x"y" \ | 15 | || test x"$CONFIG_FEATURE_MINIX2" != x"y" \ |
15 | || test x"$CONFIG_FEATURE_MOUNT_LOOP" != x"y" \ | 16 | || test x"$CONFIG_FEATURE_MOUNT_LOOP" != x"y" \ |
17 | || test x"$CONFIG_FEATURE_MOUNT_LOOP_CREATE" != x"y" \ | ||
16 | || test x"$CONFIG_FEATURE_MOUNT_FLAGS" != x"y" \ | 18 | || test x"$CONFIG_FEATURE_MOUNT_FLAGS" != x"y" \ |
17 | || test x"$CONFIG_FEATURE_DEVFS" = x"y" \ | 19 | || test x"$CONFIG_FEATURE_DEVFS" = x"y" \ |
18 | ; then | 20 | ; then |
diff --git a/testsuite/pidof.tests b/testsuite/pidof.tests index 2a06d2b1c..cd10de4e0 100755 --- a/testsuite/pidof.tests +++ b/testsuite/pidof.tests | |||
@@ -18,15 +18,22 @@ testing "pidof (exit with success)" "pidof pidof > /dev/null; echo \$?" \ | |||
18 | 18 | ||
19 | testing "pidof this" "pidof pidof.tests | grep -o -w $$" "$$\n" "" "" | 19 | testing "pidof this" "pidof pidof.tests | grep -o -w $$" "$$\n" "" "" |
20 | 20 | ||
21 | test x"`cat /proc/1/comm`" = x"init" && { | ||
21 | optional FEATURE_PIDOF_SINGLE | 22 | optional FEATURE_PIDOF_SINGLE |
22 | testing "pidof -s" "pidof -s init" "1\n" "" "" | 23 | testing "pidof -s" "pidof -s init" "1\n" "" "" |
23 | SKIP= | 24 | SKIP= |
25 | } | ||
24 | 26 | ||
27 | test x"`cat /proc/1/comm`" = x"init" && { | ||
25 | optional FEATURE_PIDOF_OMIT FEATURE_PIDOF_SINGLE | 28 | optional FEATURE_PIDOF_OMIT FEATURE_PIDOF_SINGLE |
26 | # This test fails now because process name matching logic has changed, | 29 | # This test fails now because process name matching logic has changed, |
27 | # but new logic is not "wrong" either... see find_pid_by_name.c comments | 30 | # but new logic is not "wrong" either... see find_pid_by_name.c comments |
28 | #testing "pidof -o %PPID" "pidof -o %PPID pidof.tests | grep -o -w $$" "" "" "" | 31 | #testing "pidof -o %PPID" "pidof -o %PPID pidof.tests | grep -o -w $$" "" "" "" |
29 | testing "pidof -o %PPID NOP" "pidof -o %PPID -s init" "1\n" "" "" | 32 | testing "pidof -o %PPID NOP" "pidof -o %PPID -s init" "1\n" "" "" |
33 | SKIP= | ||
34 | } | ||
35 | |||
36 | optional FEATURE_PIDOF_OMIT | ||
30 | testing "pidof -o init" "pidof -o 1 init | grep -o -w 1" "" "" "" | 37 | testing "pidof -o init" "pidof -o 1 init | grep -o -w 1" "" "" "" |
31 | SKIP= | 38 | SKIP= |
32 | 39 | ||
diff --git a/testsuite/tar.tests b/testsuite/tar.tests index 1675b07b1..d71a34910 100755 --- a/testsuite/tar.tests +++ b/testsuite/tar.tests | |||
@@ -336,7 +336,7 @@ SKIP= | |||
336 | cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null | 336 | cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null |
337 | 337 | ||
338 | mkdir tar.tempdir && cd tar.tempdir || exit 1 | 338 | mkdir tar.tempdir && cd tar.tempdir || exit 1 |
339 | optional FEATURE_SEAMLESS_BZ2 FEATURE_TAR_AUTODETECT | 339 | optional FEATURE_SEAMLESS_BZ2 FEATURE_TAR_AUTODETECT LS |
340 | testing "Symlink attack: create symlink and then write through it" '\ | 340 | testing "Symlink attack: create symlink and then write through it" '\ |
341 | exec 2>&1 | 341 | exec 2>&1 |
342 | uudecode -o input && tar xvf input; echo $? | 342 | uudecode -o input && tar xvf input; echo $? |
@@ -365,4 +365,22 @@ n8fYaKlioCTzL2oXYczyUUIP4u5IpwoSEwWdtoA= | |||
365 | SKIP= | 365 | SKIP= |
366 | cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null | 366 | cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null |
367 | 367 | ||
368 | mkdir tar.tempdir && cd tar.tempdir || exit 1 | ||
369 | optional FEATURE_TAR_CREATE | ||
370 | testing "Symlinks and hardlinks coexist" '\ | ||
371 | mkdir dir | ||
372 | >dir/a | ||
373 | ln -s ../dir/a dir/b | ||
374 | ln dir/b dir/c | ||
375 | mkdir new | ||
376 | tar cf - dir/* | tar -C new -xvf - 2>&1 | ||
377 | ' "\ | ||
378 | dir/a | ||
379 | dir/b | ||
380 | dir/c | ||
381 | " \ | ||
382 | "" "" | ||
383 | SKIP= | ||
384 | cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null | ||
385 | |||
368 | exit $FAILCOUNT | 386 | exit $FAILCOUNT |
diff --git a/testsuite/unexpand/unexpand-works-like-GNU b/testsuite/unexpand/unexpand-works-like-GNU index a5258363f..111b277b5 100644 --- a/testsuite/unexpand/unexpand-works-like-GNU +++ b/testsuite/unexpand/unexpand-works-like-GNU | |||
@@ -1,3 +1,7 @@ | |||
1 | # coreutils 8.25 often says "input line is too long" | ||
2 | # on ELF executables. In this case, do not run the test: | ||
3 | unexpand ../../busybox >/dev/null || exit 0 | ||
4 | |||
1 | rm -f foo bar | 5 | rm -f foo bar |
2 | echo " y" | unexpand ../../busybox > foo | 6 | echo " y" | unexpand ../../busybox > foo |
3 | echo " y" | busybox unexpand ../../busybox > bar | 7 | echo " y" | busybox unexpand ../../busybox > bar |
diff --git a/testsuite/unzip.tests b/testsuite/unzip.tests index 6bcb6b3a2..af53de9df 100755 --- a/testsuite/unzip.tests +++ b/testsuite/unzip.tests | |||
@@ -14,7 +14,7 @@ | |||
14 | # Create a scratch directory | 14 | # Create a scratch directory |
15 | 15 | ||
16 | mkdir temp | 16 | mkdir temp |
17 | cd temp || exit 90 | 17 | cd temp || exit $? |
18 | 18 | ||
19 | # Create test file to work with. | 19 | # Create test file to work with. |
20 | 20 | ||
@@ -54,9 +54,22 @@ SKIP= | |||
54 | 54 | ||
55 | rm -f * | 55 | rm -f * |
56 | 56 | ||
57 | optional CONFIG_FEATURE_UNZIP_LZMA | 57 | optional FEATURE_UNZIP_LZMA |
58 | testing "unzip (archive with corrupted lzma)" "unzip -p ../unzip_bad_lzma_1.zip 2>&1; echo \$?" \ | 58 | testing "unzip (archive with corrupted lzma 1)" "unzip -p ../unzip_bad_lzma_1.zip 2>&1; echo \$?" \ |
59 | "unzip: removing leading '/' from member names | 59 | "unzip: removing leading '/' from member names |
60 | unzip: corrupted data | ||
61 | unzip: inflate error | ||
62 | 1 | ||
63 | " \ | ||
64 | "" "" | ||
65 | SKIP= | ||
66 | |||
67 | rm -f * | ||
68 | |||
69 | optional FEATURE_UNZIP_LZMA | ||
70 | testing "unzip (archive with corrupted lzma 2)" "unzip -p ../unzip_bad_lzma_2.zip 2>&1; echo \$?" \ | ||
71 | "unzip: removing leading '/' from member names | ||
72 | unzip: corrupted data | ||
60 | unzip: inflate error | 73 | unzip: inflate error |
61 | 1 | 74 | 1 |
62 | " \ | 75 | " \ |
diff --git a/testsuite/unzip_bad_lzma_2.zip b/testsuite/unzip_bad_lzma_2.zip new file mode 100644 index 000000000..cdb917088 --- /dev/null +++ b/testsuite/unzip_bad_lzma_2.zip | |||
Binary files differ | |||
diff --git a/util-linux/Config.src b/util-linux/Config.src index 68fcc266f..0fad3e5c0 100644 --- a/util-linux/Config.src +++ b/util-linux/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | menu "Linux System Utilities" | 6 | menu "Linux System Utilities" |
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c index 7275535e6..cdcba0a03 100644 --- a/util-linux/fdisk.c +++ b/util-linux/fdisk.c | |||
@@ -2004,12 +2004,6 @@ check_consistency(const struct partition *p, int partition) | |||
2004 | printf(" phys=(%u,%u,%u) ", pec, peh, pes); | 2004 | printf(" phys=(%u,%u,%u) ", pec, peh, pes); |
2005 | printf("logical=(%u,%u,%u)\n", lec, leh, les); | 2005 | printf("logical=(%u,%u,%u)\n", lec, leh, les); |
2006 | } | 2006 | } |
2007 | |||
2008 | /* Ending on cylinder boundary? */ | ||
2009 | if (peh != (g_heads - 1) || pes != g_sectors) { | ||
2010 | printf("Partition %u does not end on cylinder boundary\n", | ||
2011 | partition + 1); | ||
2012 | } | ||
2013 | } | 2007 | } |
2014 | 2008 | ||
2015 | static void | 2009 | static void |
diff --git a/util-linux/fdisk_sgi.c b/util-linux/fdisk_sgi.c index 30def09c6..1cf0af5cc 100644 --- a/util-linux/fdisk_sgi.c +++ b/util-linux/fdisk_sgi.c | |||
@@ -425,7 +425,7 @@ create_sgiinfo(void) | |||
425 | /* I keep SGI's habit to write the sgilabel to the second block */ | 425 | /* I keep SGI's habit to write the sgilabel to the second block */ |
426 | sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2); | 426 | sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2); |
427 | sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo)); | 427 | sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo)); |
428 | strncpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8); | 428 | memcpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8); |
429 | } | 429 | } |
430 | 430 | ||
431 | static sgiinfo *fill_sgiinfo(void); | 431 | static sgiinfo *fill_sgiinfo(void); |
diff --git a/util-linux/mkfs_vfat.c b/util-linux/mkfs_vfat.c index 26a919536..92f0e3b1a 100644 --- a/util-linux/mkfs_vfat.c +++ b/util-linux/mkfs_vfat.c | |||
@@ -522,7 +522,7 @@ int mkfs_vfat_main(int argc UNUSED_PARAM, char **argv) | |||
522 | //STORE_LE(boot_blk->reserved2[3], 0,0,0); | 522 | //STORE_LE(boot_blk->reserved2[3], 0,0,0); |
523 | STORE_LE(boot_blk->vi.ext_boot_sign, 0x29); | 523 | STORE_LE(boot_blk->vi.ext_boot_sign, 0x29); |
524 | STORE_LE(boot_blk->vi.volume_id32, volume_id); | 524 | STORE_LE(boot_blk->vi.volume_id32, volume_id); |
525 | strncpy(boot_blk->vi.fs_type, "FAT32 ", sizeof(boot_blk->vi.fs_type)); | 525 | memcpy(boot_blk->vi.fs_type, "FAT32 ", sizeof(boot_blk->vi.fs_type)); |
526 | strncpy(boot_blk->vi.volume_label, volume_label, sizeof(boot_blk->vi.volume_label)); | 526 | strncpy(boot_blk->vi.volume_label, volume_label, sizeof(boot_blk->vi.volume_label)); |
527 | memcpy(boot_blk->boot_code, boot_code, sizeof(boot_code)); | 527 | memcpy(boot_blk->boot_code, boot_code, sizeof(boot_code)); |
528 | STORE_LE(boot_blk->boot_sign, BOOT_SIGN); | 528 | STORE_LE(boot_blk->boot_sign, BOOT_SIGN); |
diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c index c6933c8d5..ae8103a52 100644 --- a/util-linux/nsenter.c +++ b/util-linux/nsenter.c | |||
@@ -105,14 +105,14 @@ static const struct namespace_descr ns_list[] = { | |||
105 | /* | 105 | /* |
106 | * Upstream nsenter doesn't support the short option for --preserve-credentials | 106 | * Upstream nsenter doesn't support the short option for --preserve-credentials |
107 | */ | 107 | */ |
108 | static const char opt_str[] ALIGN1 = "U::i::u::n::p::m::""t+S+G+r::w::F"; | 108 | static const char opt_str[] ALIGN1 = "U::i::u::n::p::m::""t:+S:+G:+r::w::F"; |
109 | 109 | ||
110 | #if ENABLE_LONG_OPTS | 110 | #if ENABLE_LONG_OPTS |
111 | static const char nsenter_longopts[] ALIGN1 = | 111 | static const char nsenter_longopts[] ALIGN1 = |
112 | "user\0" Optional_argument "U" | 112 | "user\0" Optional_argument "U" |
113 | "ipc\0" Optional_argument "i" | 113 | "ipc\0" Optional_argument "i" |
114 | "uts\0" Optional_argument "u" | 114 | "uts\0" Optional_argument "u" |
115 | "network\0" Optional_argument "n" | 115 | "net\0" Optional_argument "n" |
116 | "pid\0" Optional_argument "p" | 116 | "pid\0" Optional_argument "p" |
117 | "mount\0" Optional_argument "m" | 117 | "mount\0" Optional_argument "m" |
118 | "target\0" Required_argument "t" | 118 | "target\0" Required_argument "t" |
diff --git a/util-linux/unshare.c b/util-linux/unshare.c index 7c295da1f..fffee28a0 100644 --- a/util-linux/unshare.c +++ b/util-linux/unshare.c | |||
@@ -73,7 +73,7 @@ | |||
73 | #include "libbb.h" | 73 | #include "libbb.h" |
74 | 74 | ||
75 | static void mount_or_die(const char *source, const char *target, | 75 | static void mount_or_die(const char *source, const char *target, |
76 | const char *fstype, unsigned long mountflags) | 76 | const char *fstype, unsigned long mountflags) |
77 | { | 77 | { |
78 | if (mount(source, target, fstype, mountflags, NULL)) { | 78 | if (mount(source, target, fstype, mountflags, NULL)) { |
79 | bb_perror_msg_and_die("can't mount %s on %s (flags:0x%lx)", | 79 | bb_perror_msg_and_die("can't mount %s on %s (flags:0x%lx)", |
diff --git a/util-linux/volume_id/Config.src b/util-linux/volume_id/Config.src index ac208c9cc..fe3b14a71 100644 --- a/util-linux/volume_id/Config.src +++ b/util-linux/volume_id/Config.src | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # For a description of the syntax of this configuration file, | 2 | # For a description of the syntax of this configuration file, |
3 | # see scripts/kbuild/config-language.txt. | 3 | # see docs/Kconfig-language.txt. |
4 | # | 4 | # |
5 | 5 | ||
6 | config VOLUMEID | 6 | config VOLUMEID |