From 669c40ed8ebf480c95ce36135104e474e361a7e6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 13 Feb 2023 15:04:11 +0100 Subject: top: stop using div() from libc, compilers now do it better function old new delta div 23 - -23 display_process_list 1237 1178 -59 ------------------------------------------------------------------------------ (add/remove: 0/2 grow/shrink: 0/1 up/down: 0/-82) Total: -82 bytes Signed-off-by: Denys Vlasenko --- procps/top.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/procps/top.c b/procps/top.c index ff775422c..6d25d9633 100644 --- a/procps/top.c +++ b/procps/top.c @@ -619,17 +619,15 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width) unsigned busy_jifs; #endif - /* what info of the processes is shown */ - printf(OPT_BATCH_MODE ? "%.*s" : ESC"[7m" "%.*s" ESC"[m", scr_width, - " PID PPID USER STAT VSZ %VSZ" - IF_FEATURE_TOP_SMP_PROCESS(" CPU") - IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(" %CPU") - " COMMAND"); - lines_rem--; - #if ENABLE_FEATURE_TOP_DECIMALS # define UPSCALE 1000 -# define CALC_STAT(name, val) div_t name = div((val), 10) +typedef struct { unsigned quot, rem; } bb_div_t; +/* Used to have "div_t name = div((val), 10)" here + * (IOW: intended to use libc-compatible way to divide and use + * both result and remainder, but musl does not inline div()...) + * Oh well. Modern compilers detect "N/d, N%d" idiom by themselves: + */ +# define CALC_STAT(name, val) bb_div_t name = { (val) / 10, (val) % 10 } # define SHOW_STAT(name) name.quot, '0'+name.rem # define FMT "%3u.%c" #else @@ -638,6 +636,15 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width) # define SHOW_STAT(name) name # define FMT "%4u%%" #endif + + /* what info of the processes is shown */ + printf(OPT_BATCH_MODE ? "%.*s" : ESC"[7m" "%.*s" ESC"[m", scr_width, + " PID PPID USER STAT VSZ %VSZ" + IF_FEATURE_TOP_SMP_PROCESS(" CPU") + IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(" %CPU") + " COMMAND"); + lines_rem--; + /* * %VSZ = s->vsz/MemTotal */ -- cgit v1.2.3-55-g6feb From 75197998c22b0760a1a6d5e94f750b12855ef82f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 22 Feb 2023 10:50:14 +0100 Subject: unzip: clear SUID/GID bits, implement -K to not clear them function old new delta unzip_main 2656 2715 +59 packed_usage 34517 34552 +35 .rodata 105250 105251 +1 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 95/0) Total: 95 bytes Signed-off-by: Denys Vlasenko --- archival/unzip.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/archival/unzip.c b/archival/unzip.c index b27dd2187..691a2d81b 100644 --- a/archival/unzip.c +++ b/archival/unzip.c @@ -56,7 +56,7 @@ //kbuild:lib-$(CONFIG_UNZIP) += unzip.o //usage:#define unzip_trivial_usage -//usage: "[-lnojpq] FILE[.zip] [FILE]... [-x FILE]... [-d DIR]" +//usage: "[-lnojpqK] FILE[.zip] [FILE]... [-x FILE]... [-d DIR]" //usage:#define unzip_full_usage "\n\n" //usage: "Extract FILEs from ZIP archive\n" //usage: "\n -l List contents (with -q for short form)" @@ -66,6 +66,7 @@ //usage: "\n -p Write to stdout" //usage: "\n -t Test" //usage: "\n -q Quiet" +//usage: "\n -K Do not clear SUID bit" //usage: "\n -x FILE Exclude FILEs" //usage: "\n -d DIR Extract into DIR" @@ -494,6 +495,7 @@ int unzip_main(int argc, char **argv) OPT_l = (1 << 0), OPT_x = (1 << 1), OPT_j = (1 << 2), + OPT_K = (1 << 3), }; unsigned opts; smallint quiet = 0; @@ -559,7 +561,7 @@ int unzip_main(int argc, char **argv) opts = 0; /* '-' makes getopt return 1 for non-options */ - while ((i = getopt(argc, argv, "-d:lnotpqxjv")) != -1) { + while ((i = getopt(argc, argv, "-d:lnotpqxjvK")) != -1) { switch (i) { case 'd': /* Extract to base directory */ base_dir = optarg; @@ -602,6 +604,10 @@ int unzip_main(int argc, char **argv) opts |= OPT_j; break; + case 'K': + opts |= OPT_K; + break; + case 1: if (!src_fn) { /* The zip file */ @@ -819,7 +825,10 @@ int unzip_main(int argc, char **argv) # endif if ((cdf.fmt.version_made_by >> 8) == 3) { /* This archive is created on Unix */ - dir_mode = file_mode = (cdf.fmt.external_attributes >> 16); + file_mode = (cdf.fmt.external_attributes >> 16); + if (!(opts & OPT_K)) + file_mode &= ~(mode_t)(S_ISUID | S_ISGID); + dir_mode = file_mode; } } #endif -- cgit v1.2.3-55-g6feb From 029740a3e43835d2a71696449baba5250a346e0a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 23 Feb 2023 12:00:36 +0100 Subject: unzip: document some options we might support Signed-off-by: Denys Vlasenko --- archival/unzip.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/archival/unzip.c b/archival/unzip.c index 691a2d81b..71a302915 100644 --- a/archival/unzip.c +++ b/archival/unzip.c @@ -559,6 +559,11 @@ int unzip_main(int argc, char **argv) * 204372 1 file */ +//TODO: accept and ignore these? +// -a convert to text files with 't' label, -aa: all files +// -b do not convert to text - bbox: we don't convert anything +// -D skip restoration of timestamps for extracted items - bbox: we don't restore these (yet?) +// -X restore user:group ownership opts = 0; /* '-' makes getopt return 1 for non-options */ while ((i = getopt(argc, argv, "-d:lnotpqxjvK")) != -1) { @@ -583,6 +588,7 @@ int unzip_main(int argc, char **argv) xmove_fd(xopen("/dev/null", O_WRONLY), STDOUT_FILENO); /*fallthrough*/ +// NB: -c extract files to stdout/screen (unlike -p, also prints .zip and file names to stdout) case 'p': /* Extract files to stdout */ dst_fd = STDOUT_FILENO; /*fallthrough*/ @@ -853,6 +859,7 @@ int unzip_main(int argc, char **argv) unzip_skip(zip.fmt.extra_len); /* Guard against "/abspath", "/../" and similar attacks */ +// NB: UnZip 6.00 has option -: to disable this overlapping_strcpy(dst_fn, strip_unsafe_prefix(dst_fn)); /* Filter zip entries */ -- cgit v1.2.3-55-g6feb From 2d4a3d9e6c1493a9520b907e07a41aca90cdfd94 Mon Sep 17 00:00:00 2001 From: Arsen Arsenović Date: Tue, 21 Feb 2023 20:20:31 +0100 Subject: fixdep: avoid underflow when end of entry doesn't coincide with EOF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: https://bugs.gentoo.org/893776 Closes: https://bugs.busybox.net/show_bug.cgi?id=15326 Signed-off-by: Arsen Arsenović Signed-off-by: Denys Vlasenko --- scripts/basic/fixdep.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c index 426b4888b..66be73aad 100644 --- a/scripts/basic/fixdep.c +++ b/scripts/basic/fixdep.c @@ -338,6 +338,11 @@ void parse_dep_file(void *map, size_t len) do p--; while (!isalnum((unsigned char)*p)); p++; } + if (p < m) { + /* we've consumed the last filename of this list + already. */ + break; + } memcpy(s, m, p-m); s[p-m] = 0; if (strrcmp(s, "include/autoconf.h") && strrcmp(s, "arch/um/include/uml-config.h") && -- cgit v1.2.3-55-g6feb From d8a33603801476dd870ea66c36cf7c64d852d674 Mon Sep 17 00:00:00 2001 From: David Leonard Date: Sun, 29 Jan 2023 12:07:08 +1000 Subject: find: implement -ok MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html -ok utility_name [argument ...] ; The -ok primary shall be equivalent to -exec, except that the use of a to punctuate the end of the primary expression need not be supported, and find shall request affirmation of the invocation of utility_name using the current file as an argument by writing to standard error as described in the STDERR section. If the response on standard input is affirmative, the utility shall be invoked. Otherwise, the command shall not be invoked and the value of the -ok operand shall be false. function old new delta do_exec 438 517 +79 parse_params 1833 1845 +12 static.params 288 292 +4 .rodata 100771 100775 +4 packed_usage 34543 34541 -2 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/1 up/down: 99/-2) Total: 97 bytes Signed-off-by: David Leonard Signed-off-by: Denys Vlasenko --- findutils/find.c | 39 ++++++++++++++++++++++++++++++++++++--- testsuite/find.tests | 6 ++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/findutils/find.c b/findutils/find.c index bb6ad31e5..136ca0d21 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -180,6 +180,13 @@ //config: Without this option, -exec + is a synonym for -exec ; //config: (IOW: it works correctly, but without expected speedup) //config: +//config:config FEATURE_FIND_EXEC_OK +//config: bool "Enable -ok: execute confirmed commands" +//config: default y +//config: depends on FEATURE_FIND_EXEC +//config: help +//config: Support the 'find -ok' option which prompts before executing. +//config: //config:config FEATURE_FIND_USER //config: bool "Enable -user: username/uid matching" //config: default y @@ -395,6 +402,9 @@ //usage: IF_FEATURE_FIND_EXEC_PLUS( //usage: "\n -exec CMD ARG + Run CMD with {} replaced by list of file names" //usage: ) +//usage: IF_FEATURE_FIND_EXEC_OK( +//usage: "\n -ok CMD ARG ; Prompt and run CMD with {} replaced" +//usage: ) //usage: IF_FEATURE_FIND_DELETE( //usage: "\n -delete Delete current file/directory. Turns on -depth option" //usage: ) @@ -467,6 +477,9 @@ IF_FEATURE_FIND_EXEC( ACTS(exec, char **exec_argv; /* -exec ARGS */ unsigned *subst_count; int exec_argc; /* count of ARGS */ + IF_FEATURE_FIND_EXEC_OK( + int ok; /* -ok */ + ) IF_FEATURE_FIND_EXEC_PLUS( /* * filelist is NULL if "exec ;" @@ -802,10 +815,24 @@ static int do_exec(action_exec *ap, const char *fileName) } # endif +# if ENABLE_FEATURE_FIND_EXEC_OK + if (ap->ok) { + for (i = 0; argv[i]; i++) + fprintf(stderr, "%s ", argv[i]); + fprintf(stderr, "?"); + if (!bb_ask_y_confirmation()) { + rc = 1; /* "false" */ + goto not_ok; + } + } +# endif rc = spawn_and_wait(argv); if (rc < 0) bb_simple_perror_msg(argv[0]); +# if ENABLE_FEATURE_FIND_EXEC_OK + not_ok: +# endif i = 0; while (argv[i]) free(argv[i++]); @@ -1120,6 +1147,7 @@ static action*** parse_params(char **argv) IF_FEATURE_FIND_DELETE( PARM_delete ,) IF_FEATURE_FIND_EMPTY( PARM_empty ,) IF_FEATURE_FIND_EXEC( PARM_exec ,) + IF_FEATURE_FIND_EXEC_OK(PARM_ok ,) IF_FEATURE_FIND_EXECUTABLE(PARM_executable,) IF_FEATURE_FIND_PAREN( PARM_char_brace,) /* All options/actions starting from here require argument */ @@ -1171,6 +1199,7 @@ static action*** parse_params(char **argv) IF_FEATURE_FIND_DELETE( "-delete\0" ) IF_FEATURE_FIND_EMPTY( "-empty\0" ) IF_FEATURE_FIND_EXEC( "-exec\0" ) + IF_FEATURE_FIND_EXEC_OK("-ok\0" ) IF_FEATURE_FIND_EXECUTABLE("-executable\0") IF_FEATURE_FIND_PAREN( "(\0" ) /* All options/actions starting from here require argument */ @@ -1351,23 +1380,27 @@ static action*** parse_params(char **argv) } #endif #if ENABLE_FEATURE_FIND_EXEC - else if (parm == PARM_exec) { + else if (parm == PARM_exec IF_FEATURE_FIND_EXEC_OK(|| parm == PARM_ok)) { int i; action_exec *ap; IF_FEATURE_FIND_EXEC_PLUS(int all_subst = 0;) dbg("%d", __LINE__); G.need_print = 0; ap = ALLOC_ACTION(exec); + IF_FEATURE_FIND_EXEC_OK(ap->ok = (parm == PARM_ok);) ap->exec_argv = ++argv; /* first arg after -exec */ /*ap->exec_argc = 0; - ALLOC_ACTION did it */ while (1) { if (!*argv) /* did not see ';' or '+' until end */ - bb_error_msg_and_die(bb_msg_requires_arg, "-exec"); + bb_error_msg_and_die(bb_msg_requires_arg, arg); // find -exec echo Foo ">{}<" ";" // executes "echo Foo >FILENAME<", // find -exec echo Foo ">{}<" "+" // executes "echo Foo FILENAME1 FILENAME2 FILENAME3...". - if ((argv[0][0] == ';' || argv[0][0] == '+') + if ((argv[0][0] == ';' + || (argv[0][0] == '+' IF_FEATURE_FIND_EXEC_OK(&& parm != PARM_ok)) + /* -ok CMD + syntax is not accepted, only with ';' */ + ) && argv[0][1] == '\0' ) { # if ENABLE_FEATURE_FIND_EXEC_PLUS diff --git a/testsuite/find.tests b/testsuite/find.tests index 138236c81..d763ca6f2 100755 --- a/testsuite/find.tests +++ b/testsuite/find.tests @@ -28,6 +28,12 @@ testing "find -exec exitcode 2" \ "0\n" \ "" "" SKIP= +optional FEATURE_FIND_EXEC_OK +testing "find -ok" \ + "cd find.tempdir && find testfile -ok true {} ';' 2>&1; echo \$?" \ + "true testfile ?0\n" \ + "" "y" +SKIP= # Surprisingly, "-exec false ;" results in exitcode 0! "-exec false +" is different!!! optional FEATURE_FIND_EXEC testing "find -exec exitcode 3" \ -- cgit v1.2.3-55-g6feb From 3253d7fe0097ff15797ee4918e927b0c9d6863a9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 28 Mar 2023 18:53:07 +0200 Subject: httpd: do not mangle cgi-bin/SCRIPT/params URLs If cgi-bin/ prefix is seen, do not test the rest for existence, whether it's a dir, and such. function old new delta handle_incoming_and_exit 2200 2212 +12 Reported here: https://lists.zx2c4.com/pipermail/cgit/2023-March/004825.html Signed-off-by: Denys Vlasenko --- networking/httpd.c | 74 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/networking/httpd.c b/networking/httpd.c index ffc58e10b..252ad6c2d 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -2405,50 +2405,52 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) send_headers_and_exit(HTTP_FORBIDDEN); } cgi_type = CGI_NORMAL; - } + } /* why "else": do not check "cgi-bin/SCRIPT/something" for cases below: */ + else #endif - - if (urlp[-1] == '/') { - /* When index_page string is appended to / URL, it overwrites - * the query string. If we fall back to call /cgi-bin/index.cgi, - * query string would be lost and not available to the CGI. - * Work around it by making a deep copy. - */ - if (ENABLE_FEATURE_HTTPD_CGI) - g_query = xstrdup(g_query); /* ok for NULL too */ - strcpy(urlp, index_page); - } - if (stat(tptr, &sb) == 0) { - /* If URL is a directory with no slash, set up - * "HTTP/1.1 302 Found" "Location: /dir/" reply */ - if (urlp[-1] != '/' && S_ISDIR(sb.st_mode)) { - found_moved_temporarily = urlcopy; - } else { + { + if (urlp[-1] == '/') { + /* When index_page string is appended to / URL, it overwrites + * the query string. If we fall back to call /cgi-bin/index.cgi, + * query string would be lost and not available to the CGI. + * Work around it by making a deep copy. + */ + if (ENABLE_FEATURE_HTTPD_CGI) + g_query = xstrdup(g_query); /* ok for NULL too */ + strcpy(urlp, index_page); + } + if (stat(tptr, &sb) == 0) { + /* If URL is a directory with no slash, set up + * "HTTP/1.1 302 Found" "Location: /dir/" reply */ + if (urlp[-1] != '/' && S_ISDIR(sb.st_mode)) { + found_moved_temporarily = urlcopy; + } else { #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR - char *suffix = strrchr(tptr, '.'); - if (suffix) { - Htaccess *cur; - for (cur = script_i; cur; cur = cur->next) { - if (strcmp(cur->before_colon + 1, suffix) == 0) { - cgi_type = CGI_INTERPRETER; - break; + char *suffix = strrchr(tptr, '.'); + if (suffix) { + Htaccess *cur; + for (cur = script_i; cur; cur = cur->next) { + if (strcmp(cur->before_colon + 1, suffix) == 0) { + cgi_type = CGI_INTERPRETER; + break; + } } } - } #endif - file_size = sb.st_size; - last_mod = sb.st_mtime; + file_size = sb.st_size; + last_mod = sb.st_mtime; + } } - } #if ENABLE_FEATURE_HTTPD_CGI - else if (urlp[-1] == '/') { - /* It's a dir URL and there is no index.html */ - /* Is there cgi-bin/index.cgi? */ - if (access("/cgi-bin/index.cgi"+1, X_OK) != 0) - send_headers_and_exit(HTTP_NOT_FOUND); /* no */ - cgi_type = CGI_INDEX; - } + else if (urlp[-1] == '/') { + /* It's a dir URL and there is no index.html */ + /* Is there cgi-bin/index.cgi? */ + if (access("/cgi-bin/index.cgi"+1, X_OK) != 0) + send_headers_and_exit(HTTP_NOT_FOUND); /* no */ + cgi_type = CGI_INDEX; + } #endif + } #if ENABLE_FEATURE_HTTPD_BASIC_AUTH || ENABLE_FEATURE_HTTPD_CGI /* check_user_passwd() would be confused by added .../index.html, truncate it */ -- cgit v1.2.3-55-g6feb From bd76b75f72f717150b909e8c64edfda725cabe11 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 29 Mar 2023 15:17:00 +0200 Subject: libbb/sha: fix sha-NI instruction detection Signed-off-by: Denys Vlasenko --- libbb/hash_md5_sha.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c index 880ffab01..bbe58c77b 100644 --- a/libbb/hash_md5_sha.c +++ b/libbb/hash_md5_sha.c @@ -1178,7 +1178,7 @@ void FAST_FUNC sha1_begin(sha1_ctx_t *ctx) if (!shaNI) { unsigned eax = 7, ebx = ebx, ecx = 0, edx = edx; cpuid(&eax, &ebx, &ecx, &edx); - shaNI = ((ebx >> 29) << 1) - 1; + shaNI = ((ebx >> 28) & 2) - 1; /* bit 29 -> 1 or -1 */ } if (shaNI > 0) ctx->process_block = sha1_process_block64_shaNI; @@ -1232,7 +1232,7 @@ void FAST_FUNC sha256_begin(sha256_ctx_t *ctx) if (!shaNI) { unsigned eax = 7, ebx = ebx, ecx = 0, edx = edx; cpuid(&eax, &ebx, &ecx, &edx); - shaNI = ((ebx >> 29) << 1) - 1; + shaNI = ((ebx >> 28) & 2) - 1; /* bit 29 -> 1 or -1 */ } if (shaNI > 0) ctx->process_block = sha256_process_block64_shaNI; -- cgit v1.2.3-55-g6feb From a59e5a7d08cb26ec029d00dd11e693765aca17be Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 29 Mar 2023 15:44:08 +0200 Subject: libbb/sha: do not read shaNI variable twice, and factor out its setting My gcc inlines both calls, so instead of "-20 bytes" I get only this: function old new delta sha256_begin 84 83 -1 sha1_begin 114 111 -3 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-4) Total: -4 bytes Signed-off-by: Denys Vlasenko --- libbb/hash_md5_sha.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c index bbe58c77b..88baf51dc 100644 --- a/libbb/hash_md5_sha.c +++ b/libbb/hash_md5_sha.c @@ -23,6 +23,14 @@ static void cpuid(unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx) ); } static smallint shaNI; +static int get_shaNI(void) +{ + unsigned eax = 7, ebx = ebx, ecx = 0, edx = edx; + cpuid(&eax, &ebx, &ecx, &edx); + ebx = ((ebx >> 28) & 2) - 1; /* bit 29 -> 1 or -1 */ + shaNI = (int)ebx; + return (int)ebx; +} void FAST_FUNC sha1_process_block64_shaNI(sha1_ctx_t *ctx); void FAST_FUNC sha256_process_block64_shaNI(sha256_ctx_t *ctx); # if defined(__i386__) @@ -1175,12 +1183,10 @@ void FAST_FUNC sha1_begin(sha1_ctx_t *ctx) #if ENABLE_SHA1_HWACCEL # if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) { - if (!shaNI) { - unsigned eax = 7, ebx = ebx, ecx = 0, edx = edx; - cpuid(&eax, &ebx, &ecx, &edx); - shaNI = ((ebx >> 28) & 2) - 1; /* bit 29 -> 1 or -1 */ - } - if (shaNI > 0) + int ni = shaNI; + if (!ni) + ni = get_shaNI(); + if (ni > 0) ctx->process_block = sha1_process_block64_shaNI; } # endif @@ -1229,12 +1235,10 @@ void FAST_FUNC sha256_begin(sha256_ctx_t *ctx) #if ENABLE_SHA256_HWACCEL # if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) { - if (!shaNI) { - unsigned eax = 7, ebx = ebx, ecx = 0, edx = edx; - cpuid(&eax, &ebx, &ecx, &edx); - shaNI = ((ebx >> 28) & 2) - 1; /* bit 29 -> 1 or -1 */ - } - if (shaNI > 0) + int ni = shaNI; + if (!ni) + ni = get_shaNI(); + if (ni > 0) ctx->process_block = sha256_process_block64_shaNI; } # endif -- cgit v1.2.3-55-g6feb From f2e659415ad59906124fca963040c8884746feed Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 24 Mar 2023 15:16:35 +0000 Subject: lineedit: fix matching of directories when searching PATH Commit 8baa643a3 (lineedit: match local directories when searching PATH) included subdirectories of the current directory in the search when tab-completing commands. Unfortunately a short time later commit 1d180cd74 (lineedit: use strncmp instead of is_prefixed_with (we know the length)) broke this feature by returning an incorrect length for the array of paths. Fix the length and reinstate matching of subdirectories. Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index b942f540a..625884adf 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -825,8 +825,8 @@ static unsigned path_parse(char ***p) res[npth++] = tmp; } /* special case: "match subdirectories of the current directory" */ - /*res[npth++] = NULL; - filled by xzalloc() */ - return npth; + /*res[npth] = NULL; - filled by xzalloc() */ + return npth + 1; } /* Complete command, directory or file name. -- cgit v1.2.3-55-g6feb From 470fa7b3648da2ea120d65fa7cde69cad0421353 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 26 Mar 2023 11:20:46 +0100 Subject: ash: make EPOCH variables work if RANDOM is disabled Commit 1d37186fe2 (ash: add bash-compatible EPOCH variables) added support for the EPOCHSECONDS and EPOCHREALTIME variables. These variables are dynamic and therefore require the VDYNAMIC flag to be non-zero. However, this is only the case if support for the RANDOM variable is enabled. Give VDYNAMIC a non-zero value if either EPOCH variables or RANDOM are enabled. Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index 5f8c8ea19..559566b58 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2087,7 +2087,7 @@ struct localvar { #define VNOFUNC 0x40 /* don't call the callback function */ #define VNOSET 0x80 /* do not set variable - just readonly test */ #define VNOSAVE 0x100 /* when text is on the heap before setvareq */ -#if ENABLE_ASH_RANDOM_SUPPORT +#if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS # define VDYNAMIC 0x200 /* dynamic variable */ #else # define VDYNAMIC 0 -- cgit v1.2.3-55-g6feb From af5277f883e8fc2e0236aa9ecc5115ecaffd0ccb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 31 Mar 2023 13:15:58 +0200 Subject: modprobe: call finit_module with MODULE_INIT_COMPRESSED_FILE if module name doesn't end with .ko IOW: if name doesn't end with .ko, assume it's .gz/.xz or similar, and ask kernel to uncompress it. If finit_module(MODULE_INIT_COMPRESSED_FILE) fails, retry with finit_module(0). function old new delta bb_init_module 151 197 +46 Signed-off-by: Denys Vlasenko --- modutils/modprobe-small.c | 12 +++++++++++- modutils/modutils.c | 12 +++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index b61651621..77e42e3fb 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -33,6 +33,9 @@ #define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags) #ifdef __NR_finit_module # define finit_module(fd, uargs, flags) syscall(__NR_finit_module, fd, uargs, flags) +# ifndef MODULE_INIT_COMPRESSED_FILE +# define MODULE_INIT_COMPRESSED_FILE 4 +# endif #endif /* linux/include/linux/module.h has limit of 64 chars on module names */ #undef MODULE_NAME_LEN @@ -272,7 +275,14 @@ static int load_module(const char *fname, const char *options) { int fd = open(fname, O_RDONLY | O_CLOEXEC); if (fd >= 0) { - r = finit_module(fd, options, 0) != 0; + int flags = is_suffixed_with(fname, ".ko") ? 0 : MODULE_INIT_COMPRESSED_FILE; + for (;;) { + r = finit_module(fd, options, flags); + if (r == 0 || flags == 0) + break; + /* Loading non-.ko named uncompressed module? Not likely, but let's try it */ + flags = 0; + } close(fd); } } diff --git a/modutils/modutils.c b/modutils/modutils.c index f7ad5e805..cbff20961 100644 --- a/modutils/modutils.c +++ b/modutils/modutils.c @@ -12,6 +12,9 @@ #define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts) #if defined(__NR_finit_module) # define finit_module(fd, uargs, flags) syscall(__NR_finit_module, fd, uargs, flags) +# ifndef MODULE_INIT_COMPRESSED_FILE +# define MODULE_INIT_COMPRESSED_FILE 4 +# endif #endif #define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags) @@ -217,7 +220,14 @@ int FAST_FUNC bb_init_module(const char *filename, const char *options) { int fd = open(filename, O_RDONLY | O_CLOEXEC); if (fd >= 0) { - rc = finit_module(fd, options, 0) != 0; + int flags = is_suffixed_with(filename, ".ko") ? 0 : MODULE_INIT_COMPRESSED_FILE; + for (;;) { + rc = finit_module(fd, options, flags); + if (rc == 0 || flags == 0) + break; + /* Loading non-.ko named uncompressed module? Not likely, but let's try it */ + flags = 0; + } close(fd); if (rc == 0) return rc; -- cgit v1.2.3-55-g6feb From 098cd7ece44bf7ab7ae38dc00dd574af79a9bad8 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Thu, 30 Mar 2023 11:05:04 +0100 Subject: ash: improve trap and jobs builtins in child shells The trap and jobs builtins can be used to report information about traps and jobs. This works when they're called from the current shell but in a child shell the required information is usually cleared. Special hacks allow: - trap to work with command substitution; - jobs to work with command substitution or in a pipeline. Neither works with process substitution. - Relax the test for the trap hack so it also supports pipelines. - Pass the command to be evaluated to forkshell() in evalbackcmd() so trap and jobs both work with process substitution. function old new delta forkchild 629 640 +11 argstr 1502 1496 -6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 11/-6) Total: 5 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash.c | 13 +++++++------ shell/ash_test/ash-signals/usage.right | 12 ++++++++++++ shell/ash_test/ash-signals/usage.tests | 12 ++++++++++++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 559566b58..40b921be1 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5190,8 +5190,7 @@ forkchild(struct job *jp, union node *n, int mode) closescript(); - if (mode == FORK_NOJOB /* is it `xxx` ? */ - && n && n->type == NCMD /* is it single cmd? */ + if (n && n->type == NCMD /* is it single cmd? */ /* && n->ncmd.args->type == NARG - always true? */ && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0 && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */ @@ -5285,10 +5284,12 @@ forkchild(struct job *jp, union node *n, int mode) ) { TRACE(("Job hack\n")); /* "jobs": we do not want to clear job list for it, - * instead we remove only _its_ own_ job from job list. + * instead we remove only _its_ own_ job from job list + * (if it has one). * This makes "jobs .... | cat" more useful. */ - freejob(curjob); + if (jp) + freejob(curjob); return; } #endif @@ -6607,9 +6608,9 @@ evalbackcmd(union node *n, struct backcmd *result if (pipe(pip) < 0) ash_msg_and_raise_perror("can't create pipe"); - /* process substitution uses NULL job/node, like openhere() */ + /* process substitution uses NULL job, like openhere() */ jp = (ctl == CTLBACKQ) ? makejob(/*n,*/ 1) : NULL; - if (forkshell(jp, (ctl == CTLBACKQ) ? n : NULL, FORK_NOJOB) == 0) { + if (forkshell(jp, n, FORK_NOJOB) == 0) { /* child */ FORCE_INT_ON; close(pip[ip]); diff --git a/shell/ash_test/ash-signals/usage.right b/shell/ash_test/ash-signals/usage.right index c0dbd6c3c..df1ed2dd7 100644 --- a/shell/ash_test/ash-signals/usage.right +++ b/shell/ash_test/ash-signals/usage.right @@ -6,6 +6,18 @@ trap -- 'a' INT trap -- 'a' USR1 trap -- 'a' USR2 ___ +trap -- 'a' EXIT trap -- 'a' INT trap -- 'a' USR1 trap -- 'a' USR2 +___ +trap -- 'a' EXIT +trap -- 'a' INT +trap -- 'a' USR1 +trap -- 'a' USR2 +___ +trap -- 'a' EXIT +trap -- 'a' INT +trap -- 'a' USR1 +trap -- 'a' USR2 +___ ___ trap -- 'a' USR1 trap -- 'a' USR2 diff --git a/shell/ash_test/ash-signals/usage.tests b/shell/ash_test/ash-signals/usage.tests index d29c6e74a..34e24cceb 100755 --- a/shell/ash_test/ash-signals/usage.tests +++ b/shell/ash_test/ash-signals/usage.tests @@ -10,6 +10,18 @@ trap "a" EXIT INT USR1 USR2 echo ___ trap +# show them by command substitution +echo ___ +echo $(trap) + +# show them by pipe +echo ___ +trap | cat + +# show them by process substitution +echo ___ +cat <(trap) + # clear one echo ___ trap 0 INT -- cgit v1.2.3-55-g6feb From 262a84547798cf795d9748329f2ad251117801cc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 31 Mar 2023 21:35:50 +0200 Subject: ash: exec: Stricter pathopt parsing - lost chunk Signed-off-by: Denys Vlasenko --- shell/ash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index 40b921be1..45e552217 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2959,7 +2959,7 @@ cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) if (!*dest) dest = "."; path = bltinlookup("CDPATH"); - while (p = path, (len = padvance(&path, dest)) >= 0) { + while (p = path, (len = padvance_magic(&path, dest, 0)) >= 0) { c = *p; p = stalloc(len); -- cgit v1.2.3-55-g6feb From 00fc1368437f66c6e67ed45a17326e5f2573ea65 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 1 Apr 2023 11:11:20 +0200 Subject: ash: code shrink function old new delta describe_command 323 320 -3 dotcmd 324 309 -15 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-18) Total: -18 bytes Signed-off-by: Denys Vlasenko --- shell/ash.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 45e552217..2ec7cfb0e 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -8729,8 +8729,6 @@ describe_command(char *command, const char *path, int describe_command_verbose) const struct alias *ap; #endif - path = path ? path : pathval(); - if (describe_command_verbose) { out1str(command); } @@ -8755,6 +8753,7 @@ describe_command(char *command, const char *path, int describe_command_verbose) } #endif /* Brute force */ + path = path ? path : pathval(); find_command(command, &entry, DO_ABS, path); switch (entry.cmdtype) { @@ -13624,7 +13623,7 @@ static char * find_dot_file(char *basename) { char *fullname; - const char *path = pathval(); + const char *path; struct stat statb; int len; @@ -13632,6 +13631,7 @@ find_dot_file(char *basename) if (strchr(basename, '/')) return basename; + path = pathval(); while ((len = padvance(&path, basename)) >= 0) { fullname = stackblock(); if ((!pathopt || *pathopt == 'f') -- cgit v1.2.3-55-g6feb From 1409432d072e62c3838ef2e86b0d97637201dbd5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 1 Apr 2023 22:16:32 +0200 Subject: hush: add TODO comment Signed-off-by: Denys Vlasenko --- shell/hush.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/shell/hush.c b/shell/hush.c index e6be70078..e42de8762 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -11276,6 +11276,9 @@ static int FAST_FUNC builtin_local(char **argv) bb_error_msg("%s: not in a function", argv[0]); return EXIT_FAILURE; /* bash compat */ } +//TODO? ash and bash support "local -" special form, +//which saves/restores $- around function call (including async returns, such as ^C) +//(IOW: it makes "set +/-..." effects local) argv++; /* Since all builtins run in a nested variable level, * need to use level - 1 here. Or else the variable will be removed at once -- cgit v1.2.3-55-g6feb From fd5fb2d2b59640910addf5c946a39d4cc5c09003 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 1 Apr 2023 22:36:30 +0200 Subject: hush: speed up "big heredoc" code function old new delta hush_main 1810 1815 +5 .rodata 102723 102721 -2 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 5/-2) Total: 3 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index e42de8762..170edf415 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -10260,6 +10260,20 @@ int hush_main(int argc, char **argv) INIT_G(); if (EXIT_SUCCESS != 0) /* if EXIT_SUCCESS == 0, it is already done */ G.last_exitcode = EXIT_SUCCESS; +#if !BB_MMU + /* "Big heredoc" support via "sh -< STRING" invocation. + * Check it first (do not bother to run the usual init code, + * it is not needed for this case). + */ + if (argv[1] + && argv[1][0] == '-' && argv[1][1] == '<' /*&& !argv[1][2]*/ + /*&& argv[2] && !argv[3] - we don't check some conditions */ + ) { + full_write1_str(argv[2]); + _exit(0); + } + G.argv0_for_re_execing = argv[0]; +#endif #if ENABLE_HUSH_TRAP # if ENABLE_HUSH_FUNCTIONS G.return_exitcode = -1; @@ -10270,9 +10284,6 @@ int hush_main(int argc, char **argv) #if ENABLE_HUSH_FAST G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */ #endif -#if !BB_MMU - G.argv0_for_re_execing = argv[0]; -#endif cached_getpid = getpid(); /* for tcsetpgrp() during init */ G.root_pid = cached_getpid; /* for $PID (NOMMU can override via -$HEXPID:HEXPPID:...) */ @@ -10388,7 +10399,7 @@ int hush_main(int argc, char **argv) int opt = getopt(argc, argv, "+" /* stop at 1st non-option */ "cexinsl" #if !BB_MMU - "<:$:R:V:" + "$:R:V:" # if ENABLE_HUSH_FUNCTIONS "F:" # endif @@ -10438,9 +10449,6 @@ int hush_main(int argc, char **argv) flags |= OPT_login; break; #if !BB_MMU - case '<': /* "big heredoc" support */ - full_write1_str(optarg); - _exit(0); case '$': { unsigned long long empty_trap_mask; -- cgit v1.2.3-55-g6feb From 6748e6494c223b779a204b370e395f82c8e5247f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 1 Apr 2023 23:16:01 +0200 Subject: hush (NOMMU): fix LINENO in execed children function old new delta hush_main 1815 1851 +36 re_execute_shell 601 635 +34 .rodata 102721 102726 +5 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 75/0) Total: 75 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/shell/hush.c b/shell/hush.c index 170edf415..a938cc790 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -7468,6 +7468,9 @@ static void re_execute_shell(char ***to_free, const char *s, if (!cur->flg_export || cur->flg_read_only) cnt += 2; } +# if ENABLE_HUSH_LINENO_VAR + cnt += 2; +# endif # if ENABLE_HUSH_FUNCTIONS for (funcp = G.top_func; funcp; funcp = funcp->next) cnt += 3; @@ -7489,6 +7492,10 @@ static void re_execute_shell(char ***to_free, const char *s, *pp++ = cur->varstr; } } +# if ENABLE_HUSH_LINENO_VAR + *pp++ = (char *) "-L"; + *pp++ = utoa(G.execute_lineno); +# endif # if ENABLE_HUSH_FUNCTIONS for (funcp = G.top_func; funcp; funcp = funcp->next) { *pp++ = (char *) "-F"; @@ -10400,6 +10407,9 @@ int hush_main(int argc, char **argv) "cexinsl" #if !BB_MMU "$:R:V:" +# if ENABLE_HUSH_LINENO_VAR + "L:" +# endif # if ENABLE_HUSH_FUNCTIONS "F:" # endif @@ -10498,6 +10508,11 @@ int hush_main(int argc, char **argv) case 'V': set_local_var(xstrdup(optarg), opt == 'R' ? SETFLAG_MAKE_RO : 0); break; +# if ENABLE_HUSH_LINENO_VAR + case 'L': + G.parse_lineno = xatou(optarg); + break; +# endif # if ENABLE_HUSH_FUNCTIONS case 'F': { struct function *funcp = new_function(optarg); -- cgit v1.2.3-55-g6feb From 2860b2530e7391b52fc6f0d500981e78a4618551 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Apr 2023 14:01:36 +0200 Subject: ash: fix broken new mail detection Mea culpa, in "Do not allocate stack string in padvance" commit (I left an extraneous "break" statement). function old new delta cmdloop 329 398 +69 Signed-off-by: Denys Vlasenko --- shell/ash.c | 1 - 1 file changed, 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index 2ec7cfb0e..55c0acc16 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -11288,7 +11288,6 @@ chkmail(void) if (!len) break; p = stackblock(); - break; if (*p == '\0') continue; for (q = p; *q; q++) -- cgit v1.2.3-55-g6feb From 7ababc3e3cd44cb51ad1b0183f7fe30df0fb3cbf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Apr 2023 14:31:18 +0200 Subject: ash: fix still-broken new mail detection padvance() exit condition is return value < 0, not == 0. After MAIL changing twice, the logic erroneously concluded that "you have new mail". Signed-off-by: Denys Vlasenko --- shell/ash.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 55c0acc16..f057b8963 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -11265,8 +11265,8 @@ static smallint mail_var_path_changed; /* * Print appropriate message(s) if mail has arrived. * If mail_var_path_changed is set, - * then the value of MAIL has mail_var_path_changed, - * so we just update the values. + * then the value of MAIL has changed, + * so we just update the hash value. */ static void chkmail(void) @@ -11285,7 +11285,7 @@ chkmail(void) int len; len = padvance_magic(&mpath, nullstr, 2); - if (!len) + if (len < 0) break; p = stackblock(); if (*p == '\0') @@ -11306,8 +11306,8 @@ chkmail(void) if (!mail_var_path_changed && mailtime_hash != new_hash) { if (mailtime_hash != 0) out2str("you have mail\n"); - mailtime_hash = new_hash; } + mailtime_hash = new_hash; mail_var_path_changed = 0; popstackmark(&smark); } -- cgit v1.2.3-55-g6feb From 94780e3e8e926e7e9f384c4b70310b3e7e79abce Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Apr 2023 15:01:00 +0200 Subject: ash: get rid of separate mail_var_path_changed flag variable We can just clear mailtime_hash to zero and have the same effect. function old new delta changemail 8 11 +3 mail_var_path_changed 1 - -1 cmdloop 398 382 -16 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/1 up/down: 3/-17) Total: -14 bytes text data bss dec hex filename 1054786 559 5020 1060365 102e0d busybox_old 1054773 559 5020 1060352 102e00 busybox_unstripped Signed-off-by: Denys Vlasenko --- shell/ash.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index f057b8963..bd3afc0c8 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2110,10 +2110,7 @@ change_lc_ctype(const char *value) } #endif #if ENABLE_ASH_MAIL -static void chkmail(void); static void changemail(const char *var_value) FAST_FUNC; -#else -# define chkmail() ((void)0) #endif static void changepath(const char *) FAST_FUNC; #if ENABLE_ASH_RANDOM_SUPPORT @@ -11258,13 +11255,12 @@ setinputstring(char *string) #if ENABLE_ASH_MAIL /* Hash of mtimes of mailboxes */ +/* Cleared to 0 if MAIL or MAILPATH is changed */ static unsigned mailtime_hash; -/* Set if MAIL or MAILPATH is changed. */ -static smallint mail_var_path_changed; /* * Print appropriate message(s) if mail has arrived. - * If mail_var_path_changed is set, + * If mailtime_hash is zero, * then the value of MAIL has changed, * so we just update the hash value. */ @@ -11303,21 +11299,24 @@ chkmail(void) /* Very simplistic "hash": just a sum of all mtimes */ new_hash += (unsigned)statb.st_mtime; } - if (!mail_var_path_changed && mailtime_hash != new_hash) { + if (mailtime_hash != new_hash) { if (mailtime_hash != 0) out2str("you have mail\n"); + mailtime_hash = new_hash; } - mailtime_hash = new_hash; - mail_var_path_changed = 0; popstackmark(&smark); } static void FAST_FUNC changemail(const char *val UNUSED_PARAM) { - mail_var_path_changed = 1; + mailtime_hash = 0; } +#else + +# define chkmail() ((void)0) + #endif /* ASH_MAIL */ -- cgit v1.2.3-55-g6feb From a33d19eba8c614d113378ed07bbec0ce06227028 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Apr 2023 15:19:13 +0200 Subject: ash: code shrink - reuse is_prefixed_with() from libbb function old new delta changepath 67 68 +1 legal_pathopt 70 66 -4 prefix 34 13 -21 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/2 up/down: 1/-25) Total: -24 bytes Signed-off-by: Denys Vlasenko --- shell/ash.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index bd3afc0c8..cb674e69c 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -1852,16 +1852,18 @@ _STPUTC(int c, char *p) /* * prefix -- see if pfx is a prefix of string. */ -static char * +static ALWAYS_INLINE char * prefix(const char *string, const char *pfx) { + return is_prefixed_with(string, pfx); +#if 0 /* dash implementation: */ while (*pfx) { if (*pfx++ != *string++) return NULL; } return (char *) string; +#endif } - /* * Check for a valid number. This should be elsewhere. */ -- cgit v1.2.3-55-g6feb From 46e92e1e568021ecdfa30bfea0efabe72b85633b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Apr 2023 17:30:03 +0200 Subject: ash: code shrink: do not take address of prefix(), allowing it to inline function old new delta getjob 281 285 +4 prefix 13 - -13 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/0 up/down: 4/-13) Total: -9 bytes Signed-off-by: Denys Vlasenko --- shell/ash.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index cb674e69c..d4ee4c93e 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -3962,7 +3962,6 @@ getjob(const char *name, int getctl) unsigned num; int c; const char *p; - char *(*match)(const char *, const char *); jp = curjob; p = name; @@ -4003,15 +4002,12 @@ getjob(const char *name, int getctl) } } - match = prefix; - if (*p == '?') { - match = strstr; - p++; - } - found = NULL; while (jp) { - if (match(jp->ps[0].ps_cmd, p)) { + if (*p == '?' + ? strstr(jp->ps[0].ps_cmd, p + 1) + : prefix(jp->ps[0].ps_cmd, p) + ) { if (found) goto err; found = jp; -- cgit v1.2.3-55-g6feb From ff8fde111e11e973b269467dd86f235a27f653df Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Apr 2023 19:29:57 +0200 Subject: hush: printf builtin with no arguments should not exit Signed-off-by: Denys Vlasenko --- coreutils/printf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreutils/printf.c b/coreutils/printf.c index 2e672d15f..b89df67f9 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c @@ -428,7 +428,7 @@ int printf_main(int argc UNUSED_PARAM, char **argv) if (argv[1] && argv[1][0] == '-' && argv[1][1] == '-' && !argv[1][2]) argv++; if (!argv[1]) { - if (ENABLE_ASH_PRINTF + if ((ENABLE_ASH_PRINTF || ENABLE_HUSH_PRINTF) && applet_name[0] != 'p' ) { bb_simple_error_msg("usage: printf FORMAT [ARGUMENT...]"); -- cgit v1.2.3-55-g6feb From 05f2bedaebd694605abd1f199fc25d93ad73840b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Apr 2023 19:54:42 +0200 Subject: ash: sleep builtin with no arguments should not exit function old new delta sleep_main 116 143 +27 .rodata 105245 105268 +23 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 50/0) Total: 50 bytes Signed-off-by: Denys Vlasenko --- coreutils/sleep.c | 15 ++++++++++++++- procps/kill.c | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/coreutils/sleep.c b/coreutils/sleep.c index 442841210..667db558d 100644 --- a/coreutils/sleep.c +++ b/coreutils/sleep.c @@ -65,15 +65,28 @@ int sleep_main(int argc UNUSED_PARAM, char **argv) { duration_t duration; + /* Note: sleep_main may be directly called from ash as a builtin. + * This brings some complications: + * + we can't use xfunc here + * + we can't use bb_show_usage + * + applet_name can be the name of the shell + */ ++argv; - if (!*argv) + if (!*argv) { + /* Without this, bare "sleep" in ash shows _ash_ --help */ + if (ENABLE_ASH_SLEEP && applet_name[0] != 's') { + bb_simple_error_msg("sleep: missing operand"); + return EXIT_FAILURE; + } bb_show_usage(); + } /* GNU sleep accepts "inf", "INF", "infinity" and "INFINITY" */ if (strncasecmp(argv[0], "inf", 3) == 0) for (;;) sleep(INT_MAX); +//FIXME: in ash, "sleep 123qwerty" as a builtin aborts the shell #if ENABLE_FEATURE_FANCY_SLEEP duration = 0; do { diff --git a/procps/kill.c b/procps/kill.c index 8f10e21ab..208efebde 100644 --- a/procps/kill.c +++ b/procps/kill.c @@ -85,8 +85,8 @@ * This brings some complications: * * + we can't use xfunc here - * + we can't use applet_name * + we can't use bb_show_usage + * + applet_name can be the name of the shell * (doesn't apply for killall[5], still should be careful b/c NOFORK) * * kill %n gets translated into kill ' -' by shell (note space!) -- cgit v1.2.3-55-g6feb From a26711a2d1464167be4ebc990fe21a3809a2da34 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Apr 2023 21:20:28 +0200 Subject: libbb: consolidate NOMMU fix of restoring high bit in argv[0][0] function old new delta fork_or_rexec 46 56 +10 bootchartd_main 1087 1079 -8 cpio_main 674 661 -13 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/2 up/down: 10/-21) Total: -11 bytes Signed-off-by: Denys Vlasenko --- archival/cpio.c | 1 - include/libbb.h | 2 +- init/bootchartd.c | 2 -- libbb/vfork_daemon_rexec.c | 10 ++++++---- networking/httpd.c | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/archival/cpio.c b/archival/cpio.c index 7149782d7..839a15621 100644 --- a/archival/cpio.c +++ b/archival/cpio.c @@ -504,7 +504,6 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) goto dump; } /* parent */ - USE_FOR_NOMMU(argv[-optind][0] &= 0x7f); /* undo fork_or_rexec() damage */ xchdir(*argv++); close(pp.wr); xmove_fd(pp.rd, STDIN_FILENO); diff --git a/include/libbb.h b/include/libbb.h index cca33a177..6191debb1 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1319,7 +1319,7 @@ enum { # define bb_daemonize(flags) bb_daemonize_or_rexec(flags, bogus) #else extern bool re_execed; - /* Note: re_exec() and fork_or_rexec() do argv[0][0] |= 0x80 on NOMMU! + /* Note: re_exec() sets argv[0][0] |= 0x80 on NOMMU! * _Parent_ needs to undo it if it doesn't want to have argv[0] mangled. */ void re_exec(char **argv) NORETURN FAST_FUNC; diff --git a/init/bootchartd.c b/init/bootchartd.c index ae1ee9d9a..0929890a3 100644 --- a/init/bootchartd.c +++ b/init/bootchartd.c @@ -435,8 +435,6 @@ int bootchartd_main(int argc UNUSED_PARAM, char **argv) /* parent */ - USE_FOR_NOMMU(argv[0][0] &= 0x7f); /* undo fork_or_rexec() damage */ - if (DO_SIGNAL_SYNC) { /* Wait for logger child to set handlers, then unpause it. * Otherwise with short-lived PROG (e.g. "bootchartd start true") diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 79141936a..a570ddbf2 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -268,10 +268,12 @@ pid_t FAST_FUNC fork_or_rexec(char **argv) /* fflush_all(); ? - so far all callers had no buffered output to flush */ pid = xvfork(); - if (pid) /* parent */ - return pid; - /* child - re-exec ourself */ - re_exec(argv); + if (pid == 0) /* child - re-exec ourself */ + re_exec(argv); /* NORETURN */ + + /* parent */ + argv[0][0] &= 0x7f; /* undo re_rexec() damage */ + return pid; } #endif diff --git a/networking/httpd.c b/networking/httpd.c index 252ad6c2d..ddcb03bca 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -2713,8 +2713,8 @@ static void mini_httpd_nommu(int server_socket, int argc, char **argv) /* Run a copy of ourself in inetd mode */ re_exec(argv_copy); } - argv_copy[0][0] &= 0x7f; /* parent, or vfork failed */ + argv_copy[0][0] &= 0x7f; /* undo re_rexec() damage */ close(n); } /* while (1) */ /* never reached */ -- cgit v1.2.3-55-g6feb