From 0beee209778870888c3a80a9ae57e74888bc8e7b Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 12 Sep 2021 11:20:33 +0100 Subject: ash: fix ignoreeof option The ignoreeof option should prevent an interactive shell from exiting on EOF. This hasn't worked in BusyBox ash since commit 727752d2d (ash: better fix for ash -c 'echo 5&' and ash -c 'sleep 5&' with testcase). Commit 3b4d04b77e (ash: input: Allow two consecutive calls to pungetc) pulled in improved support for multiple calls to pungetc from dash, thus rendering much of commit 727752d2d obsolete. Removing this old code fixes the problem with ignoreeof. function old new delta __pgetc 605 587 -18 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-18) Total: -18 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 3524d046e..152b3b46a 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -10826,9 +10826,7 @@ preadfd(void) * Refill the input buffer and return the next input character: * * 1) If a string was pushed back on the input, pop it; - * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM) - * or we are reading from a string so we can't refill the buffer, - * return EOF. + * 2) If we are reading from a string we can't refill the buffer, return EOF. * 3) If there is more stuff in this buffer, use it else call read to fill it. * 4) Process input up to the next newline, deleting nul characters. */ @@ -10845,21 +10843,9 @@ preadbuffer(void) popstring(); return __pgetc(); } - /* on both branches above g_parsefile->left_in_line < 0. - * "pgetc" needs refilling. - */ - /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read", - * pungetc() may increment it a few times. - * Assuming it won't increment it to less than -90. - */ - if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) { + if (g_parsefile->buf == NULL) { pgetc_debug("preadbuffer PEOF1"); - /* even in failure keep left_in_line and next_to_pgetc - * in lock step, for correct multi-layer pungetc. - * left_in_line was decremented before preadbuffer(), - * must inc next_to_pgetc: */ - g_parsefile->next_to_pgetc++; return PEOF; } @@ -10869,10 +10855,8 @@ preadbuffer(void) again: more = preadfd(); if (more <= 0) { - /* don't try reading again */ - g_parsefile->left_in_line = -99; + g_parsefile->left_in_buffer = g_parsefile->left_in_line = 0; pgetc_debug("preadbuffer PEOF2"); - g_parsefile->next_to_pgetc++; return PEOF; } } -- cgit v1.2.3-55-g6feb From 50239a665c88f5a95ce41146804500f5da90b19e Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 12 Sep 2021 11:21:08 +0100 Subject: ash: stopped jobs should only prevent exit from interactive shell When the user tries to exit an interactive shell with stopped jobs present the shell issues a warning and only exits if the user insists by trying to exit again. This shouldn't apply to non-interactive shells. Reported-by: Roberto A. Foglietta 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 152b3b46a..5743b2377 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5451,7 +5451,7 @@ stoppedjobs(void) int retval; retval = 0; - if (job_warning) + if (!iflag || job_warning) goto out; jp = curjob; if (jp && jp->state == JOBSTOPPED) { -- cgit v1.2.3-55-g6feb From 5726df5f94f973eaa097d9853ceff2bd6b748d97 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 12 Sep 2021 11:21:48 +0100 Subject: ash: let ignoreeof only affect interactive shells Commit fb7d6c89 from Harald van Dijk's gwsh variant of ash (https://github.com/hvdijk/gwsh): ignoreeof is documented as only having an effect for interactive shells, but is implemented as having mostly the same effect for interactive shells as for non-interactive shells. Change the implementation to match the documentation. Test case: $SHELL -o ignoreeof /dev/null function old new delta cmdloop 359 361 +2 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/0 up/down: 2/0) Total: 2 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 5743b2377..b12b859d5 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -13508,12 +13508,13 @@ cmdloop(int top) if (!top || numeof >= 50) break; if (!stoppedjobs()) { + if (!iflag) + break; if (!Iflag) { - if (iflag) { - newline_and_flush(stderr); - } + newline_and_flush(stderr); break; } + /* "set -o ignoreeof" active, do not exit command loop on ^D */ out2str("\nUse \"exit\" to leave shell.\n"); } numeof++; -- cgit v1.2.3-55-g6feb From 704c596563a5b4da4349b272d0c9c71aacea34a7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 15 Sep 2021 19:31:44 +0200 Subject: ash: introduce bash-like $FUNCNAME Patch adapted from Roberto A. Foglietta work. function old new delta lookupvar 106 150 +44 evalfun 369 408 +39 ash_main 1218 1242 +24 varinit_data 156 168 +12 .rodata 104162 104172 +10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 5/0 up/down: 129/0) Total: 129 bytes Signed-off-by: Denys Vlasenko --- shell/ash.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index b12b859d5..4bc4f55d0 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2158,6 +2158,7 @@ static const struct { { VSTRFIXED|VTEXTFIXED , defoptindvar, getoptsreset }, #endif { VSTRFIXED|VTEXTFIXED , NULL /* inited to linenovar */, NULL }, + { VSTRFIXED|VTEXTFIXED , NULL /* inited to funcnamevar */, NULL }, #if ENABLE_ASH_RANDOM_SUPPORT { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random }, #endif @@ -2184,6 +2185,8 @@ struct globals_var { struct var varinit[ARRAY_SIZE(varinit_data)]; int lineno; char linenovar[sizeof("LINENO=") + sizeof(int)*3]; + char funcnamevar[sizeof("FUNCNAME=") + 64]; + char *funcname; unsigned trap_depth; bool in_trap_ERR; /* ERR cannot recurse, no need to be a counter */ }; @@ -2196,6 +2199,8 @@ extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var; #define varinit (G_var.varinit ) #define lineno (G_var.lineno ) #define linenovar (G_var.linenovar ) +#define funcnamevar (G_var.funcnamevar ) +#define funcname (G_var.funcname ) #define trap_depth (G_var.trap_depth ) #define in_trap_ERR (G_var.in_trap_ERR ) #define vifs varinit[0] @@ -2213,13 +2218,14 @@ extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var; #endif #define VAR_OFFSET2 (VAR_OFFSET1 + ENABLE_ASH_GETOPTS) #define vlineno varinit[VAR_OFFSET2 + 5] +#define vfuncname varinit[VAR_OFFSET2 + 6] #if ENABLE_ASH_RANDOM_SUPPORT -# define vrandom varinit[VAR_OFFSET2 + 6] +# define vrandom varinit[VAR_OFFSET2 + 7] #endif #define VAR_OFFSET3 (VAR_OFFSET2 + ENABLE_ASH_RANDOM_SUPPORT) #if BASH_EPOCH_VARS -# define vepochs varinit[VAR_OFFSET3 + 6] -# define vepochr varinit[VAR_OFFSET3 + 7] +# define vepochs varinit[VAR_OFFSET3 + 7] +# define vepochr varinit[VAR_OFFSET3 + 8] #endif #define INIT_G_var() do { \ unsigned i; \ @@ -2232,6 +2238,8 @@ extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var; } \ strcpy(linenovar, "LINENO="); \ vlineno.var_text = linenovar; \ + strcpy(funcnamevar, "FUNCNAME="); \ + vfuncname.var_text = funcnamevar; \ } while (0) /* @@ -2371,6 +2379,9 @@ lookupvar(const char *name) if (!(v->flags & VUNSET)) { if (v->var_text == linenovar) { fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno); + } else + if (v->var_text == funcnamevar) { + safe_strncpy(funcnamevar+9, funcname ? funcname : "", sizeof(funcnamevar)-9); } return var_end(v->var_text); } @@ -9875,6 +9886,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) int e; int savelineno; int savefuncline; + char *savefuncname; char *savetrap = NULL; if (!Eflag) { @@ -9884,6 +9896,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) savelineno = lineno; saveparam = shellparam; savefuncline = funcline; + savefuncname = funcname; savehandler = exception_handler; e = setjmp(jmploc.loc); if (e) { @@ -9893,6 +9906,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) exception_handler = &jmploc; shellparam.malloced = 0; func->count++; + funcname = func->n.ndefun.text; funcline = func->n.ndefun.linno; INT_ON; shellparam.nparam = argc - 1; @@ -9904,6 +9918,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) evaltree(func->n.ndefun.body, flags & EV_TESTED); funcdone: INT_OFF; + funcname = savefuncname; if (savetrap) { if (!trap[NTRAP_ERR]) trap[NTRAP_ERR] = savetrap; @@ -13639,6 +13654,12 @@ exitcmd(int argc UNUSED_PARAM, char **argv) if (argv[1]) savestatus = number(argv[1]); +//TODO: this script +// trap 'echo trap:$FUNCNAME' EXIT +// f() { exit; } +// f +//prints "trap:f" in bash. We can call exitshell() here to achieve this. +//For now, keeping dash code: raise_exception(EXEXIT); /* NOTREACHED */ } -- cgit v1.2.3-55-g6feb