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 |
