Commit graph

303 commits

Author SHA1 Message Date
Denys Vlasenko
106546961d ash: implement <<<here_string syntax
function                                             old     new   delta
write2pipe                                             -     133    +133
.rodata                                           105992  106009     +17
readtoken1                                          3101    3111     +10
cmdtxt                                               631     641     +10
nodesize                                              27      28      +1
redirect                                             961     916     -45
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 4/1 up/down: 171/-45)           Total: 126 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2025-09-02 11:46:11 +02:00
Denys Vlasenko
b4cedd4c9a hush: fix several syntax corner cases with function definitions
function                                             old     new   delta
parse_stream                                        3063    3075     +12
done_word                                            777     784      +7
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 19/0)               Total: 19 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2025-08-18 14:52:46 +02:00
Denys Vlasenko
6cc3380105 hush: undo incorrect change which allows a'b'=c to be assignment
While at it, remove now-unused WORD_IS_KEYWORD

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2025-08-14 16:19:58 +02:00
Denys Vlasenko
0da6c813e1 hush: fix var_backslash1.tests
function                                             old     new   delta
o_addqblock                                            -     131    +131
append_str_maybe_ifs_split                            53     100     +47
expand_one_var                                      1872    1897     +25
encode_then_expand_vararg                            380     399     +19
sig_unblock                                           41      43      +2
sig_block                                             41      40      -1
sigprocmask_allsigs                                   33      31      -2
expand_vars_to_list                                 1080    1077      -3
wait_for_child_or_signal                             202     193      -9
o_addQstr                                            175      42    -133
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 4/5 up/down: 224/-148)           Total: 76 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2025-08-11 17:36:02 +02:00
Denys Vlasenko
d18c9eadf0 shells: testcase: add another test for EINTR on fifo open
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2025-08-11 14:10:17 +02:00
Denys Vlasenko
9b67dde8cd ash: redir: Retry open on EINTR
Upstream commit:

    Date: Thu, 28 May 2020 21:31:45 +1000
    redir: Retry open64 on EINTR

    It is possible for open64 to block on named pipes, and therefore
    it can be interrupted by signals and return EINTR.  We should only
    let it fail with EINTR if real signals are pending (i.e., it should
    not fail on SIGCHLD if SIGCHLD has not been trapped).

    This patch adds a new helper sh_open to retry the open64 call if
    necessary.  It also calls sh_error when appropriate.

    Fixes: 3800d4934391 ("[JOBS] Fix dowait signal race")

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2025-08-09 20:17:31 +02:00
Denys Vlasenko
c92755133b shells: fix a typo in var_backslash1.tests, expand it while at it
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2025-08-09 13:00:55 +02:00
Denys Vlasenko
fa82ef1a2e shells: add testsuite item
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2025-08-09 01:48:12 +02:00
Denys Vlasenko
7648dc721e ash,hush: fix corner cases with backslash-newlines in heredocs
function                                             old     new   delta
fetch_heredocs                                       477     485      +8

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2025-08-07 01:30:57 +02:00
Ron Yorston
dcd8df258a shell: improve bash compatibility of read built-in
Make the read built-in more compatible with bash:

- Return an exit code of 142 on timeout.

- When the timeout expires before a newline is detected in the
  input bash captures the partial input.  This behaviour is new
  since bash version 4.4.  BusyBox shells had the pre-4.4 behaviour
  where the input was lost.

Update the tests to suit and fix a couple of compiler errors in
the testsuite.

function                                             old     new   delta
builtin_read                                         154     174     +20
readcmd                                              213     228     +15
shell_builtin_read                                  1364    1370      +6
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/0 up/down: 41/0)               Total: 41 bytes

Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2025-07-01 20:21:37 +02:00
Denys Vlasenko
23da5c4b71 hush: do not exit interactive shell on some redirection errors
$ echo >&99
hush: dup2(99,1): Bad file descriptor
$ echo >&9999
hush: fcntl(1,F_DUPFD,10000): Invalid argument
$ echo 2>/dev/tty 10>&9999
hush: fcntl(10,F_DUPFD,10000): Invalid argument
$ still alive!_

function                                             old     new   delta
static.setup_redirects                               334     394     +60
.rodata                                           105661  105712     +51
dup_CLOEXEC                                           49      79     +30
save_fd_on_redirect                                  263     277     +14
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 4/0 up/down: 155/0)             Total: 155 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2024-07-13 02:13:28 +02:00
Denys Vlasenko
14e28c18ca hush: fix "exec 3>FILE" aborting if 3 is exactly the next free fd
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2024-07-13 00:59:02 +02:00
Denys Vlasenko
c5a1be25ba ash: fix handling of single-quoted strings in pattern substitution
function                                             old     new   delta
subevalvar                                          1576    1588     +12

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2024-02-26 16:27:53 +01:00
Denys Vlasenko
758b21402a hush: detect when terminating "done"/"fi" is missing
function                                             old     new   delta
parse_stream                                        2271    2292     +21
.rodata                                           105408  105427     +19
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 40/0)               Total: 40 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2024-02-25 17:53:25 +01:00
Denys Vlasenko
c1c267fd36 shell/math: bash-compatible handling of too large numbers
function                                             old     new   delta
parse_with_base                                        -     170    +170
evaluate_string                                     1477    1309    -168
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 0/1 up/down: 170/-168)            Total: 2 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2023-06-25 17:42:05 +02:00
Denys Vlasenko
b61fd8ec5a shell: typo fix in tests
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2023-06-18 18:49:00 +02:00
Denys Vlasenko
e127985839 shell/math: fix ?: to not evaluate not-taken branches
This fixes ash-arith-arith-ternary1/2.tests

function                                             old     new   delta
evaluate_string                                     1271    1432    +161
arith_apply                                          968    1000     +32
arith                                                 22      36     +14
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/0 up/down: 207/0)             Total: 207 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2023-06-16 19:51:01 +02:00
Denys Vlasenko
22cb0d573a shell: document another arithmetic discrepancy with bash
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2023-06-15 12:44:43 +02:00
Denys Vlasenko
61a4959251 shell/math: remove special code to handle a?b?c:d:e, it works without it now
The "hack" to virtually parenthesize ? EXPR : made this unnecessary.
The expression is effectively a?(b?(c):d):e and thus b?c:d is evaluated
before continuing with the second :

function                                             old     new   delta
evaluate_string                                     1148    1132     -16

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2023-06-15 11:22:13 +02:00
Denys Vlasenko
5f56a03882 shell/math: fix parsing of ?: and explain why it's parsed that way
This fixes arith-precedence1.tests.

This breaks arith-ternary2.tests again (we now evaluate variables
on not-taken branches). We need a better logic here anyway:
not only bare variables should not evaluate when not-taken:
	1 ? eval_me : do_not_eval
but any (arbitrarily complex) expressions shouldn't
evaluate as well!
	1 ? var_is_set=1 : ((var_is_not_set=2,var2*=4))

function                                             old     new   delta
evaluate_string                                     1097    1148     +51

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2023-06-15 10:14:43 +02:00
Denys Vlasenko
2ff01bb699 shell: sync ash/hush test scripts
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2023-06-14 15:19:02 +02:00
Denys Vlasenko
46dccd2ec0 shell/math: fix nested ?: and do not parse variables in not-taken branch
Fixes arith-ternary1.tests and arith-ternary_nested.tests

function                                             old     new   delta
evaluate_string                                     1043    1101     +58
arith_apply                                         1087    1137     +50
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 108/0)             Total: 108 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2023-06-14 11:07:30 +02:00
Denys Vlasenko
8acbf31708 shell/math: document ternary ?: op's weirdness, add code comments
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2023-06-14 00:41:18 +02:00
Denys Vlasenko
8ccb3f7b13 shell: add a few yet-failing arithmentic tests
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2023-06-13 15:21:22 +02:00
Denys Vlasenko
bab8828b0d hush: fix expansion of space in "a=${a:+$a }c" construct
function                                             old     new   delta
encode_then_append_var_plusminus                     554     552      -2

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2023-06-12 16:39:32 +02:00
Denys Vlasenko
6824298ab4 hush: fix ELIF cmd1;cmd2 THEN ... not executing cmd2, closes 15571
function                                             old     new   delta
run_list                                            1012    1024     +12

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2023-05-25 14:22:10 +02:00
Ron Yorston
098cd7ece4 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 <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2023-03-31 14:22:56 +02:00
Denys Vlasenko
1c54552842 ash: fix ifs cleanup on error paths
Patch by Alex Gorinson <algore3698@gmail.com>

function                                             old     new   delta
evalvar                                              477     495     +18
varvalue                                             603     618     +15
subevalvar                                          1557    1572     +15
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/0 up/down: 48/0)               Total: 48 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2022-08-02 11:18:11 +02:00
Sören Tempel
fa52ac9781 ash: don't read past end of var in subvareval for bash substitutions
Without this patch, BusyBox handles bash pattern substitutions without
a terminating '/' character incorrectly.

Consider the following shell script:

	_bootstrapver=5.0.211-r0
	_referencesdir="/usr/${_bootstrapver/-*}/Sources"
	echo $_referencesdir

This should output `/usr/5.0.211/Sources`. However, without this patch
it instead outputs `/usr/5.0.211Sources`. This is due to the fact that
BusyBox expects the bash pattern substitutions to always be terminated
with a '/' (at least in this part of subvareval) and thus reads passed
the substitution itself and consumes the '/' character which is part of
the literal string. If there is no '/' after the substitution then
BusyBox might perform an out-of-bounds read under certain circumstances.

When replacing the bash pattern substitution with `${_bootstrapver/-*/}`,
or with this patch applied, ash outputs the correct value.

Signed-off-by: Sören Tempel <soeren@soeren-tempel.net>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2022-03-01 08:47:43 +01:00
Denys Vlasenko
5acf5e1f87 shell: fix script's comm field if ENABLE_FEATURE_PREFER_APPLETS=y
function                                             old     new   delta
re_execed_comm                                         -      46     +46
main                                                  72      86     +14
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/0 up/down: 60/0)               Total: 60 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-10-11 18:44:00 +02:00
Denys Vlasenko
1be73dd9ad shell: fix parsing of $(( (v)++ + NUM ))
function                                             old     new   delta
evaluate_string                                      988    1011     +23

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-09-26 13:29:25 +02:00
Denys Vlasenko
62e433131b shell: enable more tests which are passing now
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-09-25 22:35:17 +02:00
Denys Vlasenko
d84a604830 shell: fix arithmentic evaluation of "++7" and such (it is + + 7, i.e. 7)
function                                             old     new   delta
evaluate_string                                      945     988     +43

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-09-25 22:04:45 +02:00
Denys Vlasenko
8c68ae8416 ash: parser: Fix alias expansion after heredoc or newlines
Upstream commit:

    Date: Wed, 29 Apr 2020 00:19:59 +1000
    parser: Fix alias expansion after heredoc or newlines

    This script should print OK:

        alias a="case x in " b=x
        a
        b) echo BAD;; esac

        alias BEGIN={ END=}
        BEGIN
    	cat <<- EOF > /dev/null
    		$(:)
    	EOF
        END
        : <<- EOF &&
    		$(:)
        EOF
        BEGIN
    	echo OK
        END

    However, because the value of checkkwd is either zeroed when it
    shouldn't, or isn't zeroed when it should, dash currently gets
    it wrong in every case.

    This patch fixes it by saving checkkwd and zeroing it where needed.

function                                             old     new   delta
readtoken                                            157     176     +19

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-09-08 01:43:12 +02:00
Denys Vlasenko
bcff3a7b5a shell/ash_test/run-all: unset locale/language variables
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-09-07 18:24:08 +02:00
Denys Vlasenko
64aa86b720 ash: LINENO starts from 0 in -c SCRIPT mode
The var_LINENO3.tests fails for hush: it does start from 0, but does not increment.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-09-07 18:16:45 +02:00
Denys Vlasenko
d6c9cbc072 ash: fix LINENO in functions
From larger patch by Roberto A. Foglietta <roberto.foglietta@gmail.com>

function                                             old     new   delta
evalfun                                              348     369     +21
ash_main                                            1202    1218     +16
setinputstring                                        65      73      +8
lookupvar                                            116     106     -10
evaltree                                             772     753     -19
evalsubshell                                         192     173     -19
evalfor                                              175     156     -19
evalcase                                             273     254     -19
evalcommand                                         1560    1536     -24
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/6 up/down: 45/-110)           Total: -65 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-09-07 18:01:49 +02:00
Denys Vlasenko
0d7dfa9012 ash: support testsuite for !FEATURE_SUID_CONFIG_QUIET configs
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-09-07 17:34:58 +02:00
Denys Vlasenko
e53c7dbafc hush: fix set -n to act immediately, not just after run_list()
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-09-07 02:25:52 +02:00
Denys Vlasenko
f415e21a7d ash: eval: Do not cache value of eflag in evaltree
Upsteam commit:

    Date: Mon, 17 May 2021 15:19:23 +0800
    eval: Do not cache value of eflag in evaltree

    Patrick Brünn <P.Bruenn@beckhoff.com> wrote:
    > Since we are migrating to Debian bullseye, we discovered a new behavior
    > with our scripts, which look like this:
    >>cleanup() {
    >>        set +e
    >>        rmdir ""
    >>}
    >>set -eu
    >>trap 'cleanup' EXIT INT TERM
    >>echo 'Hello world!'
    >
    > With old dash v0.5.10.2 this script would return 0 as we expected it.
    > But since commit 62cf6955f8abe875752d7163f6f3adbc7e49ebae it returns
    > the last exit code of our cleanup function.
    ...
    Thanks for the report.  This is actually a fairly old bug with
    set -e that's just been exposed by the exit status change.  What's
    really happening is that cleanup itself is triggering a set -e
    exit incorrectly because evaltree cached the value of eflag prior
    to the function call.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-09-07 02:01:03 +02:00
Denys Vlasenko
41beb53787 ash: eval: Check nflag in evaltree instead of cmdloop
Upstream commit:

    Date: Thu, 4 Jun 2020 21:53:55 +1000
    eval: Check nflag in evaltree instead of cmdloop

    This patch moves the nflag check from cmdloop into evaltree.  This
    is so that nflag will be in force even if we enter the shell via a
    path other than cmdloop, e.g., through sh -c.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-09-07 01:52:21 +02:00
Denys Vlasenko
c450437a4e shell: update psubst testcases
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-07-27 04:20:32 +02:00
Denys Vlasenko
05c5d745f7 ahell: update testsuite
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-07-25 22:03:16 +02:00
Denys Vlasenko
97c3b5e3ff hush: fix bkslash+newline handling and number validation in ${NN} and ${#NN}
Entering "${1a}" into interactive shell was making it exit.

function                                             old     new   delta
parse_dollar                                         824     958    +134
i_getch_and_eat_bkslash_nl                             -      44     +44
parse_expr                                           917     938     +21
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 2/0 up/down: 199/0)             Total: 199 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-06-19 15:45:45 +02:00
Denys Vlasenko
1b7a9b68d0 hush: fix handling of \^C and "^C"
function                                             old     new   delta
parse_stream                                        2238    2252     +14
encode_string                                        243     256     +13
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 27/0)               Total: 27 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-06-15 16:46:30 +02:00
Ron Yorston
a1b0d3856d ash: add process substitution in bash-compatibility mode
Process substitution is a Korn shell feature that's also available
in bash and some other shells.  This patch implements process
substitution in ash when ASH_BASH_COMPAT is enabled.

function                                             old     new   delta
argstr                                              1386    1522    +136
strtodest                                              -      52     +52
readtoken1                                          3346    3392     +46
.rodata                                           183206  183250     +44
unwindredir                                            -      28     +28
cmdloop                                              365     372      +7
static.spclchars                                      10      12      +2
cmdputs                                              380     367     -13
exitreset                                             86      69     -17
evalcommand                                         1754    1737     -17
varvalue                                             675     634     -41
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 5/4 up/down: 315/-88)           Total: 227 bytes
   text	   data	    bss	    dec	    hex	filename
 953967	   4219	   1904	 960090	  ea65a	busybox_old
 954192	   4219	   1904	 960315	  ea73b	busybox_unstripped

v2: Replace array of file descriptors with a linked list.
    Include tests that were unaccountably omitted from v1.
v3: Update linked list code to the intended version.
v4: Change order of conditional code in cmdputs().
v5: Use existing popredir() mechanism to manage file descriptors.
v6: Rebase to latest version of BusyBox ash.  Reduce code churn.

Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-06-05 23:37:19 +02:00
Denys Vlasenko
2b7c1aa92c ash: match bash behavior for ${empty_var/*/repl}
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-01-09 08:46:54 +01:00
Denys Vlasenko
883cdb79a4 ash: fix ${unset_var/pattern/repl}
function                                             old     new   delta
subevalvar                                          1349    1353      +4

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2021-01-09 08:27:37 +01:00
Denys Vlasenko
cad20ced86 typo fix
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2020-12-25 19:08:16 +01:00
Denys Vlasenko
1237d627e9 hush: fix this case: echo "SCRIPT" | hush
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2020-12-25 19:01:49 +01:00