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(-) (limited to 'shell') 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 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(-) (limited to 'shell') 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(-) (limited to 'shell') 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(-) (limited to 'shell') 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(+) (limited to 'shell') 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(-) (limited to 'shell') 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(+) (limited to 'shell') 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(-) (limited to 'shell') 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(-) (limited to 'shell') 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(-) (limited to 'shell') 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(-) (limited to 'shell') 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(-) (limited to 'shell') 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