blob: 3407711cdd282a04df737b830f20470a25e7abbe [file] [log] [blame]
Eric Andersen25f27032001-04-26 23:22:31 +00001/* vi: set sw=4 ts=4: */
2/*
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003 * A prototype Bourne shell grammar parser.
4 * Intended to follow the original Thompson and Ritchie
5 * "small and simple is beautiful" philosophy, which
6 * incidentally is a good match to today's BusyBox.
Eric Andersen25f27032001-04-26 23:22:31 +00007 *
Denis Vlasenkoce4acbb2009-04-10 23:23:41 +00008 * Copyright (C) 2000,2001 Larry Doolittle <larry@doolittle.boa.org>
Denis Vlasenkoc8d27332009-04-06 10:47:21 +00009 * Copyright (C) 2008,2009 Denys Vlasenko <vda.linux@googlemail.com>
Eric Andersen25f27032001-04-26 23:22:31 +000010 *
Denys Vlasenkobbecd742010-10-03 17:22:52 +020011 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
12 *
Eric Andersen25f27032001-04-26 23:22:31 +000013 * Credits:
14 * The parser routines proper are all original material, first
Eric Andersencb81e642003-07-14 21:21:08 +000015 * written Dec 2000 and Jan 2001 by Larry Doolittle. The
16 * execution engine, the builtins, and much of the underlying
17 * support has been adapted from busybox-0.49pre's lash, which is
Eric Andersenc7bda1c2004-03-15 08:29:22 +000018 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
Eric Andersencb81e642003-07-14 21:21:08 +000019 * written by Erik Andersen <andersen@codepoet.org>. That, in turn,
20 * is based in part on ladsh.c, by Michael K. Johnson and Erik W.
21 * Troan, which they placed in the public domain. I don't know
22 * how much of the Johnson/Troan code has survived the repeated
23 * rewrites.
24 *
Eric Andersen25f27032001-04-26 23:22:31 +000025 * Other credits:
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +000026 * o_addchr derived from similar w_addchar function in glibc-2.2.
Denis Vlasenko50f3aa42009-04-07 10:52:40 +000027 * parse_redirect, redirect_opt_num, and big chunks of main
Denis Vlasenko424f79b2009-03-22 14:23:34 +000028 * and many builtins derived from contributions by Erik Andersen.
29 * Miscellaneous bugfixes from Matt Kraai.
Eric Andersen25f27032001-04-26 23:22:31 +000030 *
31 * There are two big (and related) architecture differences between
32 * this parser and the lash parser. One is that this version is
33 * actually designed from the ground up to understand nearly all
34 * of the Bourne grammar. The second, consequential change is that
35 * the parser and input reader have been turned inside out. Now,
36 * the parser is in control, and asks for input as needed. The old
37 * way had the input reader in control, and it asked for parsing to
38 * take place as needed. The new way makes it much easier to properly
39 * handle the recursion implicit in the various substitutions, especially
40 * across continuation lines.
41 *
Denys Vlasenko349ef962010-05-21 15:46:24 +020042 * TODOs:
43 * grep for "TODO" and fix (some of them are easy)
Denys Vlasenkoa6ad3972010-05-22 00:26:06 +020044 * make complex ${var%...} constructs support optional
45 * make here documents optional
Denys Vlasenko203fd7b2017-07-17 16:13:35 +020046 * special variables (done: PWD, PPID, RANDOM)
47 * follow IFS rules more precisely, including update semantics
48 * tilde expansion
49 * aliases
Denys Vlasenko57000292018-01-12 14:41:45 +010050 * "command" missing features:
51 * command -p CMD: run CMD using default $PATH
52 * (can use this to override standalone shell as well?)
Denys Vlasenko1e660422017-07-17 21:10:50 +020053 * command BLTIN: disables special-ness (e.g. errors do not abort)
Denys Vlasenko57000292018-01-12 14:41:45 +010054 * command -V CMD1 CMD2 CMD3 (multiple args) (not in standard)
55 * builtins mandated by standards we don't support:
56 * [un]alias, fc:
Denys Vlasenko203fd7b2017-07-17 16:13:35 +020057 * fc -l[nr] [BEG] [END]: list range of commands in history
58 * fc [-e EDITOR] [BEG] [END]: edit/rerun range of commands
59 * fc -s [PAT=REP] [CMD]: rerun CMD, replacing PAT with REP
Mike Frysinger25a6ca02009-03-28 13:59:26 +000060 *
Denys Vlasenkoadc0e202010-05-17 18:56:58 +020061 * Bash compat TODO:
62 * redirection of stdout+stderr: &> and >&
Denys Vlasenkoadc0e202010-05-17 18:56:58 +020063 * reserved words: function select
64 * advanced test: [[ ]]
Denys Vlasenkoadc0e202010-05-17 18:56:58 +020065 * process substitution: <(list) and >(list)
66 * =~: regex operator
Denys Vlasenko9ca656b2009-06-10 13:39:35 +020067 * let EXPR [EXPR...]
Denys Vlasenko349ef962010-05-21 15:46:24 +020068 * Each EXPR is an arithmetic expression (ARITHMETIC EVALUATION)
69 * If the last arg evaluates to 0, let returns 1; 0 otherwise.
70 * NB: let `echo 'a=a + 1'` - error (IOW: multi-word expansion is used)
Denys Vlasenko9ca656b2009-06-10 13:39:35 +020071 * ((EXPR))
Denys Vlasenko349ef962010-05-21 15:46:24 +020072 * The EXPR is evaluated according to ARITHMETIC EVALUATION.
73 * This is exactly equivalent to let "EXPR".
Denys Vlasenkoadc0e202010-05-17 18:56:58 +020074 * $[EXPR]: synonym for $((EXPR))
Denys Vlasenko203fd7b2017-07-17 16:13:35 +020075 * indirect expansion: ${!VAR}
76 * substring op on @: ${@:n:m}
Denys Vlasenkobbecd742010-10-03 17:22:52 +020077 *
78 * Won't do:
Denys Vlasenko203fd7b2017-07-17 16:13:35 +020079 * Some builtins mandated by standards:
80 * newgrp [GRP]: not a builtin in bash but a suid binary
81 * which spawns a new shell with new group ID
Denys Vlasenko3632cb12018-04-10 15:25:41 +020082 *
83 * Status of [[ support:
84 * [[ args ]] are CMD_SINGLEWORD_NOGLOB:
85 * v='a b'; [[ $v = 'a b' ]]; echo 0:$?
Denys Vlasenko89e9d552018-04-11 01:15:33 +020086 * [[ /bin/n* ]]; echo 0:$?
Denys Vlasenko3632cb12018-04-10 15:25:41 +020087 * TODO:
88 * &&/|| are AND/OR ops, -a/-o are not
89 * quoting needs to be considered (-f is an operator, "-f" and ""-f are not; etc)
90 * = is glob match operator, not equality operator: STR = GLOB
91 * (in GLOB, quoting is significant on char-by-char basis: a*cd"*")
92 * == same as =
93 * add =~ regex match operator: STR =~ REGEX
Eric Andersen25f27032001-04-26 23:22:31 +000094 */
Denys Vlasenko202a2d12010-07-16 12:36:14 +020095//config:config HUSH
Denys Vlasenko4eed2c62017-07-18 22:01:24 +020096//config: bool "hush (64 kb)"
Denys Vlasenko202a2d12010-07-16 12:36:14 +020097//config: default y
98//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +020099//config: hush is a small shell. It handles the normal flow control
100//config: constructs such as if/then/elif/else/fi, for/in/do/done, while loops,
101//config: case/esac. Redirections, here documents, $((arithmetic))
102//config: and functions are supported.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200103//config:
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200104//config: It will compile and work on no-mmu systems.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200105//config:
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200106//config: It does not handle select, aliases, tilde expansion,
107//config: &>file and >&file redirection of stdout+stderr.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200108//config:
109//config:config HUSH_BASH_COMPAT
110//config: bool "bash-compatible extensions"
111//config: default y
Denys Vlasenko0b883582016-12-23 16:49:07 +0100112//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200113//config:
Denys Vlasenko9e800222010-10-03 14:28:04 +0200114//config:config HUSH_BRACE_EXPANSION
115//config: bool "Brace expansion"
116//config: default y
117//config: depends on HUSH_BASH_COMPAT
118//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200119//config: Enable {abc,def} extension.
Denys Vlasenko9e800222010-10-03 14:28:04 +0200120//config:
Denys Vlasenko5807e182018-02-08 19:19:04 +0100121//config:config HUSH_LINENO_VAR
122//config: bool "$LINENO variable"
123//config: default y
124//config: depends on HUSH_BASH_COMPAT
125//config:
Denys Vlasenko54c21112018-01-27 20:46:45 +0100126//config:config HUSH_BASH_SOURCE_CURDIR
127//config: bool "'source' and '.' builtins search current directory after $PATH"
128//config: default n # do not encourage non-standard behavior
129//config: depends on HUSH_BASH_COMPAT
130//config: help
131//config: This is not compliant with standards. Avoid if possible.
132//config:
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200133//config:config HUSH_INTERACTIVE
134//config: bool "Interactive mode"
135//config: default y
Denys Vlasenko0b883582016-12-23 16:49:07 +0100136//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200137//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200138//config: Enable interactive mode (prompt and command editing).
139//config: Without this, hush simply reads and executes commands
140//config: from stdin just like a shell script from a file.
141//config: No prompt, no PS1/PS2 magic shell variables.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200142//config:
Denys Vlasenko99862cb2010-09-12 17:34:13 +0200143//config:config HUSH_SAVEHISTORY
144//config: bool "Save command history to .hush_history"
145//config: default y
146//config: depends on HUSH_INTERACTIVE && FEATURE_EDITING_SAVEHISTORY
Denys Vlasenko99862cb2010-09-12 17:34:13 +0200147//config:
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200148//config:config HUSH_JOB
149//config: bool "Job control"
150//config: default y
151//config: depends on HUSH_INTERACTIVE
152//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200153//config: Enable job control: Ctrl-Z backgrounds, Ctrl-C interrupts current
154//config: command (not entire shell), fg/bg builtins work. Without this option,
155//config: "cmd &" still works by simply spawning a process and immediately
156//config: prompting for next command (or executing next command in a script),
157//config: but no separate process group is formed.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200158//config:
159//config:config HUSH_TICK
Denys Vlasenkof5604222017-01-10 14:58:54 +0100160//config: bool "Support process substitution"
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200161//config: default y
Denys Vlasenko0b883582016-12-23 16:49:07 +0100162//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200163//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200164//config: Enable `command` and $(command).
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200165//config:
166//config:config HUSH_IF
167//config: bool "Support if/then/elif/else/fi"
168//config: default y
Denys Vlasenko0b883582016-12-23 16:49:07 +0100169//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200170//config:
171//config:config HUSH_LOOPS
172//config: bool "Support for, while and until loops"
173//config: default y
Denys Vlasenko0b883582016-12-23 16:49:07 +0100174//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200175//config:
176//config:config HUSH_CASE
177//config: bool "Support case ... esac statement"
178//config: default y
Denys Vlasenko0b883582016-12-23 16:49:07 +0100179//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200180//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200181//config: Enable case ... esac statement. +400 bytes.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200182//config:
183//config:config HUSH_FUNCTIONS
184//config: bool "Support funcname() { commands; } syntax"
185//config: default y
Denys Vlasenko0b883582016-12-23 16:49:07 +0100186//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200187//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200188//config: Enable support for shell functions. +800 bytes.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200189//config:
190//config:config HUSH_LOCAL
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100191//config: bool "local builtin"
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200192//config: default y
193//config: depends on HUSH_FUNCTIONS
194//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200195//config: Enable support for local variables in functions.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200196//config:
197//config:config HUSH_RANDOM_SUPPORT
198//config: bool "Pseudorandom generator and $RANDOM variable"
199//config: default y
Denys Vlasenko0b883582016-12-23 16:49:07 +0100200//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200201//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200202//config: Enable pseudorandom generator and dynamic variable "$RANDOM".
203//config: Each read of "$RANDOM" will generate a new pseudorandom value.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200204//config:
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200205//config:config HUSH_MODE_X
206//config: bool "Support 'hush -x' option and 'set -x' command"
207//config: default y
Denys Vlasenko0b883582016-12-23 16:49:07 +0100208//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200209//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200210//config: This instructs hush to print commands before execution.
211//config: Adds ~300 bytes.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200212//config:
Denys Vlasenko1cc68042017-01-09 17:10:04 +0100213//config:config HUSH_ECHO
214//config: bool "echo builtin"
215//config: default y
216//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko1cc68042017-01-09 17:10:04 +0100217//config:
218//config:config HUSH_PRINTF
219//config: bool "printf builtin"
220//config: default y
221//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenkof5604222017-01-10 14:58:54 +0100222//config:
Denys Vlasenko265062d2017-01-10 15:13:30 +0100223//config:config HUSH_TEST
224//config: bool "test builtin"
225//config: default y
226//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
227//config:
Denys Vlasenkof5604222017-01-10 14:58:54 +0100228//config:config HUSH_HELP
229//config: bool "help builtin"
230//config: default y
231//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko1cc68042017-01-09 17:10:04 +0100232//config:
Denys Vlasenko6ec76d82017-01-08 18:40:41 +0100233//config:config HUSH_EXPORT
234//config: bool "export builtin"
235//config: default y
236//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko6ec76d82017-01-08 18:40:41 +0100237//config:
238//config:config HUSH_EXPORT_N
239//config: bool "Support 'export -n' option"
240//config: default y
241//config: depends on HUSH_EXPORT
242//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200243//config: export -n unexports variables. It is a bash extension.
Denys Vlasenko6ec76d82017-01-08 18:40:41 +0100244//config:
Denys Vlasenko1e660422017-07-17 21:10:50 +0200245//config:config HUSH_READONLY
246//config: bool "readonly builtin"
247//config: default y
Denys Vlasenko6b0695b2017-07-17 21:47:27 +0200248//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko1e660422017-07-17 21:10:50 +0200249//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200250//config: Enable support for read-only variables.
Denys Vlasenko1e660422017-07-17 21:10:50 +0200251//config:
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100252//config:config HUSH_KILL
Denys Vlasenkof5604222017-01-10 14:58:54 +0100253//config: bool "kill builtin (supports kill %jobspec)"
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100254//config: default y
255//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100256//config:
257//config:config HUSH_WAIT
258//config: bool "wait builtin"
259//config: default y
260//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100261//config:
Denys Vlasenko3bb3e1d2018-01-11 18:05:05 +0100262//config:config HUSH_COMMAND
263//config: bool "command builtin"
264//config: default y
265//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
266//config:
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100267//config:config HUSH_TRAP
268//config: bool "trap builtin"
269//config: default y
270//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100271//config:
272//config:config HUSH_TYPE
273//config: bool "type builtin"
274//config: default y
275//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100276//config:
Denys Vlasenko11f2e992017-08-10 16:34:03 +0200277//config:config HUSH_TIMES
278//config: bool "times builtin"
279//config: default y
280//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
281//config:
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100282//config:config HUSH_READ
283//config: bool "read builtin"
284//config: default y
285//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100286//config:
Denys Vlasenko10d5ece2017-01-08 18:28:43 +0100287//config:config HUSH_SET
288//config: bool "set builtin"
289//config: default y
290//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko10d5ece2017-01-08 18:28:43 +0100291//config:
292//config:config HUSH_UNSET
293//config: bool "unset builtin"
294//config: default y
295//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenkof5604222017-01-10 14:58:54 +0100296//config:
297//config:config HUSH_ULIMIT
298//config: bool "ulimit builtin"
299//config: default y
300//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko10d5ece2017-01-08 18:28:43 +0100301//config:
Denys Vlasenkod5933b12017-01-08 18:31:39 +0100302//config:config HUSH_UMASK
303//config: bool "umask builtin"
304//config: default y
305//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenkod5933b12017-01-08 18:31:39 +0100306//config:
Denys Vlasenko74d40582017-08-11 01:32:46 +0200307//config:config HUSH_GETOPTS
308//config: bool "getopts builtin"
309//config: default y
310//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
311//config:
Denys Vlasenko44719692017-01-08 18:44:41 +0100312//config:config HUSH_MEMLEAK
313//config: bool "memleak builtin (debugging)"
314//config: default n
315//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200316
Denys Vlasenko20704f02011-03-23 17:59:27 +0100317//applet:IF_HUSH(APPLET(hush, BB_DIR_BIN, BB_SUID_DROP))
Denys Vlasenko205d48e2017-01-29 14:57:33 +0100318// APPLET_ODDNAME:name main location suid_type help
Denys Vlasenko205d48e2017-01-29 14:57:33 +0100319//applet:IF_SH_IS_HUSH( APPLET_ODDNAME(sh, hush, BB_DIR_BIN, BB_SUID_DROP, hush))
Denys Vlasenko0b883582016-12-23 16:49:07 +0100320//applet:IF_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, hush))
Denys Vlasenko20704f02011-03-23 17:59:27 +0100321
322//kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o
Denys Vlasenko0b883582016-12-23 16:49:07 +0100323//kbuild:lib-$(CONFIG_SH_IS_HUSH) += hush.o match.o shell_common.o
324//kbuild:lib-$(CONFIG_BASH_IS_HUSH) += hush.o match.o shell_common.o
Denys Vlasenko20704f02011-03-23 17:59:27 +0100325//kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o
326
Denys Vlasenkof2ed39b2018-04-05 16:46:49 +0200327/* -i (interactive) is also accepted,
328 * but does nothing, therefore not shown in help.
Dan Fandrich89ca2f92010-11-28 01:54:39 +0100329 * NOMMU-specific options are not meant to be used by users,
330 * therefore we don't show them either.
331 */
332//usage:#define hush_trivial_usage
Denys Vlasenkof2ed39b2018-04-05 16:46:49 +0200333//usage: "[-enxl] [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]"
Denys Vlasenkob0b83432011-03-07 12:34:59 +0100334//usage:#define hush_full_usage "\n\n"
335//usage: "Unix shell interpreter"
336
Denys Vlasenko67047462016-12-22 15:21:58 +0100337#if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
338 || defined(__APPLE__) \
339 )
340# include <malloc.h> /* for malloc_trim */
341#endif
342#include <glob.h>
343/* #include <dmalloc.h> */
344#if ENABLE_HUSH_CASE
345# include <fnmatch.h>
346#endif
Denys Vlasenko11f2e992017-08-10 16:34:03 +0200347#include <sys/times.h>
Denys Vlasenko67047462016-12-22 15:21:58 +0100348#include <sys/utsname.h> /* for setting $HOSTNAME */
349
350#include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */
351#include "unicode.h"
352#include "shell_common.h"
353#include "math.h"
354#include "match.h"
355#if ENABLE_HUSH_RANDOM_SUPPORT
356# include "random.h"
357#else
358# define CLEAR_RANDOM_T(rnd) ((void)0)
359#endif
Denys Vlasenko41ef41b2018-07-24 16:54:41 +0200360#ifndef O_CLOEXEC
361# define O_CLOEXEC 0
362#endif
Denys Vlasenko67047462016-12-22 15:21:58 +0100363#ifndef F_DUPFD_CLOEXEC
364# define F_DUPFD_CLOEXEC F_DUPFD
365#endif
366#ifndef PIPE_BUF
367# define PIPE_BUF 4096 /* amount of buffering in a pipe */
368#endif
369
Denis Vlasenko1943aec2009-04-09 14:15:57 +0000370
Kang-Che Sung027d3ab2017-01-11 14:18:15 +0100371/* So far, all bash compat is controlled by one config option */
372/* Separate defines document which part of code implements what */
373#define BASH_PATTERN_SUBST ENABLE_HUSH_BASH_COMPAT
374#define BASH_SUBSTR ENABLE_HUSH_BASH_COMPAT
Kang-Che Sung027d3ab2017-01-11 14:18:15 +0100375#define BASH_SOURCE ENABLE_HUSH_BASH_COMPAT
376#define BASH_HOSTNAME_VAR ENABLE_HUSH_BASH_COMPAT
Denys Vlasenko4ee824f2017-07-03 01:22:13 +0200377#define BASH_TEST2 (ENABLE_HUSH_BASH_COMPAT && ENABLE_HUSH_TEST)
Denys Vlasenko1f41c882017-08-09 13:52:36 +0200378#define BASH_READ_D ENABLE_HUSH_BASH_COMPAT
Kang-Che Sung027d3ab2017-01-11 14:18:15 +0100379
380
Denys Vlasenko8d7be232009-05-25 16:38:32 +0200381/* Build knobs */
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +0000382#define LEAK_HUNTING 0
383#define BUILD_AS_NOMMU 0
384/* Enable/disable sanity checks. Ok to enable in production,
385 * only adds a bit of bloat. Set to >1 to get non-production level verbosity.
386 * Keeping 1 for now even in released versions.
387 */
388#define HUSH_DEBUG 1
Denys Vlasenko8d7be232009-05-25 16:38:32 +0200389/* Slightly bigger (+200 bytes), but faster hush.
390 * So far it only enables a trick with counting SIGCHLDs and forks,
391 * which allows us to do fewer waitpid's.
392 * (we can detect a case where neither forks were done nor SIGCHLDs happened
393 * and therefore waitpid will return the same result as last time)
394 */
395#define ENABLE_HUSH_FAST 0
Denys Vlasenko9297dbc2010-07-05 21:37:12 +0200396/* TODO: implement simplified code for users which do not need ${var%...} ops
397 * So far ${var%...} ops are always enabled:
398 */
399#define ENABLE_HUSH_DOLLAR_OPS 1
Denis Vlasenko1943aec2009-04-09 14:15:57 +0000400
401
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +0000402#if BUILD_AS_NOMMU
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000403# undef BB_MMU
404# undef USE_FOR_NOMMU
405# undef USE_FOR_MMU
406# define BB_MMU 0
407# define USE_FOR_NOMMU(...) __VA_ARGS__
408# define USE_FOR_MMU(...)
409#endif
410
Denys Vlasenko1fcbff22010-06-26 02:40:08 +0200411#include "NUM_APPLETS.h"
Denys Vlasenko14974842010-03-23 01:08:26 +0100412#if NUM_APPLETS == 1
Denis Vlasenko61befda2008-11-25 01:36:03 +0000413/* STANDALONE does not make sense, and won't compile */
Denis Vlasenkoce4acbb2009-04-10 23:23:41 +0000414# undef CONFIG_FEATURE_SH_STANDALONE
415# undef ENABLE_FEATURE_SH_STANDALONE
Denis Vlasenko5e34ff22009-04-21 11:09:40 +0000416# undef IF_FEATURE_SH_STANDALONE
Denys Vlasenko14974842010-03-23 01:08:26 +0100417# undef IF_NOT_FEATURE_SH_STANDALONE
418# define ENABLE_FEATURE_SH_STANDALONE 0
Denis Vlasenko5e34ff22009-04-21 11:09:40 +0000419# define IF_FEATURE_SH_STANDALONE(...)
420# define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
Denis Vlasenko61befda2008-11-25 01:36:03 +0000421#endif
422
Denis Vlasenko05743d72008-02-10 12:10:08 +0000423#if !ENABLE_HUSH_INTERACTIVE
Denis Vlasenkoce4acbb2009-04-10 23:23:41 +0000424# undef ENABLE_FEATURE_EDITING
425# define ENABLE_FEATURE_EDITING 0
426# undef ENABLE_FEATURE_EDITING_FANCY_PROMPT
427# define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0
Denys Vlasenko8cab6672012-04-20 14:48:00 +0200428# undef ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
429# define ENABLE_FEATURE_EDITING_SAVE_ON_EXIT 0
Denis Vlasenko8412d792007-10-01 09:59:47 +0000430#endif
431
Denis Vlasenko424f79b2009-03-22 14:23:34 +0000432/* Do we support ANY keywords? */
433#if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
Denis Vlasenkoce4acbb2009-04-10 23:23:41 +0000434# define HAS_KEYWORDS 1
435# define IF_HAS_KEYWORDS(...) __VA_ARGS__
436# define IF_HAS_NO_KEYWORDS(...)
Denis Vlasenko424f79b2009-03-22 14:23:34 +0000437#else
Denis Vlasenkoce4acbb2009-04-10 23:23:41 +0000438# define HAS_KEYWORDS 0
439# define IF_HAS_KEYWORDS(...)
440# define IF_HAS_NO_KEYWORDS(...) __VA_ARGS__
Denis Vlasenko424f79b2009-03-22 14:23:34 +0000441#endif
Denis Vlasenko8412d792007-10-01 09:59:47 +0000442
Denis Vlasenkod01ff132007-05-02 21:40:23 +0000443/* If you comment out one of these below, it will be #defined later
444 * to perform debug printfs to stderr: */
Denys Vlasenko3675c372018-07-23 16:31:21 +0200445#define debug_printf(...) do {} while (0)
Denis Vlasenko400c5b62007-05-04 13:07:27 +0000446/* Finer-grained debug switches */
Denys Vlasenko3675c372018-07-23 16:31:21 +0200447#define debug_printf_parse(...) do {} while (0)
448#define debug_printf_heredoc(...) do {} while (0)
449#define debug_print_tree(a, b) do {} while (0)
450#define debug_printf_exec(...) do {} while (0)
451#define debug_printf_env(...) do {} while (0)
452#define debug_printf_jobs(...) do {} while (0)
453#define debug_printf_expand(...) do {} while (0)
454#define debug_printf_varexp(...) do {} while (0)
455#define debug_printf_glob(...) do {} while (0)
456#define debug_printf_redir(...) do {} while (0)
457#define debug_printf_list(...) do {} while (0)
458#define debug_printf_subst(...) do {} while (0)
459#define debug_printf_prompt(...) do {} while (0)
460#define debug_printf_clean(...) do {} while (0)
Denis Vlasenkod01ff132007-05-02 21:40:23 +0000461
Denis Vlasenkob6e65562009-04-03 16:49:04 +0000462#define ERR_PTR ((void*)(long)1)
463
Denys Vlasenkod5b5c2f2017-01-08 15:46:04 +0100464#define JOB_STATUS_FORMAT "[%u] %-22s %.40s\n"
Denis Vlasenko5ec61322008-06-24 00:50:07 +0000465
Denys Vlasenkoe85248a2010-05-22 06:20:26 +0200466#define _SPECIAL_VARS_STR "_*@$!?#"
467#define SPECIAL_VARS_STR ("_*@$!?#" + 1)
468#define NUMERIC_SPECVARS_STR ("_*@$!?#" + 3)
Kang-Che Sung027d3ab2017-01-11 14:18:15 +0100469#if BASH_PATTERN_SUBST
Denys Vlasenko36f774a2010-09-05 14:45:38 +0200470/* Support / and // replace ops */
471/* Note that // is stored as \ in "encoded" string representation */
472# define VAR_ENCODED_SUBST_OPS "\\/%#:-=+?"
473# define VAR_SUBST_OPS ("\\/%#:-=+?" + 1)
474# define MINUS_PLUS_EQUAL_QUESTION ("\\/%#:-=+?" + 5)
475#else
476# define VAR_ENCODED_SUBST_OPS "%#:-=+?"
477# define VAR_SUBST_OPS "%#:-=+?"
478# define MINUS_PLUS_EQUAL_QUESTION ("%#:-=+?" + 3)
479#endif
Denys Vlasenkoe85248a2010-05-22 06:20:26 +0200480
Denys Vlasenko932b9972018-01-11 12:39:48 +0100481#define SPECIAL_VAR_SYMBOL_STR "\3"
482#define SPECIAL_VAR_SYMBOL 3
483/* The "variable" with name "\1" emits string "\3". Testcase: "echo ^C" */
484#define SPECIAL_VAR_QUOTED_SVS 1
Eric Andersen25f27032001-04-26 23:22:31 +0000485
Denys Vlasenkocb6ff252009-05-04 00:14:30 +0200486struct variable;
487
Denis Vlasenkocc90f442009-04-08 16:40:34 +0000488static const char hush_version_str[] ALIGN1 = "HUSH_VERSION="BB_VER;
489
490/* This supports saving pointers malloced in vfork child,
Denis Vlasenkoc376db32009-04-15 21:49:48 +0000491 * to be freed in the parent.
Denis Vlasenkocc90f442009-04-08 16:40:34 +0000492 */
493#if !BB_MMU
494typedef struct nommu_save_t {
Denys Vlasenkocb6ff252009-05-04 00:14:30 +0200495 struct variable *old_vars;
Denis Vlasenkocc90f442009-04-08 16:40:34 +0000496 char **argv;
Denis Vlasenko27014ed2009-04-15 21:48:23 +0000497 char **argv_from_re_execing;
Denis Vlasenkocc90f442009-04-08 16:40:34 +0000498} nommu_save_t;
499#endif
500
Denys Vlasenko9b782552010-09-08 13:33:26 +0200501enum {
Eric Andersen25f27032001-04-26 23:22:31 +0000502 RES_NONE = 0,
Denis Vlasenko06810332007-05-21 23:30:54 +0000503#if ENABLE_HUSH_IF
Denis Vlasenko17f02e72008-07-14 04:32:29 +0000504 RES_IF ,
505 RES_THEN ,
506 RES_ELIF ,
507 RES_ELSE ,
508 RES_FI ,
Denis Vlasenko06810332007-05-21 23:30:54 +0000509#endif
510#if ENABLE_HUSH_LOOPS
Denis Vlasenko17f02e72008-07-14 04:32:29 +0000511 RES_FOR ,
512 RES_WHILE ,
513 RES_UNTIL ,
514 RES_DO ,
515 RES_DONE ,
Denis Vlasenkod91afa32008-07-29 11:10:01 +0000516#endif
517#if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
Denis Vlasenko17f02e72008-07-14 04:32:29 +0000518 RES_IN ,
Denis Vlasenko06810332007-05-21 23:30:54 +0000519#endif
Denis Vlasenko17f02e72008-07-14 04:32:29 +0000520#if ENABLE_HUSH_CASE
521 RES_CASE ,
Denys Vlasenkoe9bda902009-05-23 16:50:07 +0200522 /* three pseudo-keywords support contrived "case" syntax: */
523 RES_CASE_IN, /* "case ... IN", turns into RES_MATCH when IN is observed */
524 RES_MATCH , /* "word)" */
525 RES_CASE_BODY, /* "this command is inside CASE" */
Denis Vlasenko17f02e72008-07-14 04:32:29 +0000526 RES_ESAC ,
527#endif
528 RES_XXXX ,
529 RES_SNTX
Denys Vlasenko9b782552010-09-08 13:33:26 +0200530};
Denis Vlasenkoc7985b72008-06-17 05:43:38 +0000531
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000532typedef struct o_string {
533 char *data;
534 int length; /* position where data is appended */
535 int maxlen;
Denys Vlasenko5b686cb2010-09-08 13:44:34 +0200536 int o_expflags;
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +0000537 /* At least some part of the string was inside '' or "",
538 * possibly empty one: word"", wo''rd etc. */
Denys Vlasenko38292b62010-09-05 14:49:40 +0200539 smallint has_quoted_part;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000540 smallint has_empty_slot;
Denys Vlasenko168579a2018-07-19 13:45:54 +0200541 smallint ended_in_ifs;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000542} o_string;
543enum {
Denys Vlasenko0e13b402010-09-21 12:35:39 +0200544 EXP_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */
545 EXP_FLAG_GLOB = 0x2,
546 /* Protect newly added chars against globbing
547 * by prepending \ to *, ?, [, \ */
548 EXP_FLAG_ESC_GLOB_CHARS = 0x1,
549};
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000550/* Used for initialization: o_string foo = NULL_O_STRING; */
551#define NULL_O_STRING { NULL }
552
Denys Vlasenko29f9b722011-05-14 11:27:36 +0200553#ifndef debug_printf_parse
554static const char *const assignment_flag[] = {
555 "MAYBE_ASSIGNMENT",
556 "DEFINITELY_ASSIGNMENT",
557 "NOT_ASSIGNMENT",
558 "WORD_IS_KEYWORD",
559};
560#endif
561
Denys Vlasenko41ef41b2018-07-24 16:54:41 +0200562/* We almost can use standard FILE api, but we need an ability to move
563 * its fd when redirects coincide with it. No api exists for that
564 * (RFE for it at https://sourceware.org/bugzilla/show_bug.cgi?id=21902).
565 * HFILE is our internal alternative. Only supports reading.
566 * Since we now can, we incorporate linked list of all opened HFILEs
567 * into the struct (used to be a separate mini-list).
568 */
569typedef struct HFILE {
570 char *cur;
571 char *end;
572 struct HFILE *next_hfile;
573 int is_stdin;
574 int fd;
575 char buf[1024];
576} HFILE;
577
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000578typedef struct in_str {
579 const char *p;
Denys Vlasenkod17a91d2016-09-29 18:02:37 +0200580 int peek_buf[2];
Denys Vlasenkocecbc982011-03-30 18:54:52 +0200581 int last_char;
Denys Vlasenko41ef41b2018-07-24 16:54:41 +0200582 HFILE *file;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000583} in_str;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000584
Denys Vlasenko764b2f02009-06-07 16:05:04 +0200585/* The descrip member of this structure is only used to make
586 * debugging output pretty */
587static const struct {
588 int mode;
589 signed char default_fd;
590 char descrip[3];
591} redir_table[] = {
592 { O_RDONLY, 0, "<" },
593 { O_CREAT|O_TRUNC|O_WRONLY, 1, ">" },
594 { O_CREAT|O_APPEND|O_WRONLY, 1, ">>" },
595 { O_CREAT|O_RDWR, 1, "<>" },
596 { O_RDONLY, 0, "<<" },
597/* Should not be needed. Bogus default_fd helps in debugging */
598/* { O_RDONLY, 77, "<<" }, */
599};
600
Eric Andersen25f27032001-04-26 23:22:31 +0000601struct redir_struct {
Denis Vlasenko55789c62008-06-18 16:30:42 +0000602 struct redir_struct *next;
Denis Vlasenko5ec61322008-06-24 00:50:07 +0000603 char *rd_filename; /* filename */
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +0000604 int rd_fd; /* fd to redirect */
605 /* fd to redirect to, or -3 if rd_fd is to be closed (n>&-) */
606 int rd_dup;
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +0000607 smallint rd_type; /* (enum redir_type) */
608 /* note: for heredocs, rd_filename contains heredoc delimiter,
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +0000609 * and subsequently heredoc itself; and rd_dup is a bitmask:
Denys Vlasenko764b2f02009-06-07 16:05:04 +0200610 * bit 0: do we need to trim leading tabs?
611 * bit 1: is heredoc quoted (<<'delim' syntax) ?
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +0000612 */
Eric Andersen25f27032001-04-26 23:22:31 +0000613};
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +0000614typedef enum redir_type {
Denys Vlasenko764b2f02009-06-07 16:05:04 +0200615 REDIRECT_INPUT = 0,
616 REDIRECT_OVERWRITE = 1,
617 REDIRECT_APPEND = 2,
618 REDIRECT_IO = 3,
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +0000619 REDIRECT_HEREDOC = 4,
Denys Vlasenko764b2f02009-06-07 16:05:04 +0200620 REDIRECT_HEREDOC2 = 5, /* REDIRECT_HEREDOC after heredoc is loaded */
Denis Vlasenkoc96865f2009-04-10 00:20:58 +0000621
622 REDIRFD_CLOSE = -3,
623 REDIRFD_SYNTAX_ERR = -2,
Denis Vlasenko835fcfd2009-04-10 13:51:56 +0000624 REDIRFD_TO_FILE = -1,
625 /* otherwise, rd_fd is redirected to rd_dup */
Denis Vlasenkoc96865f2009-04-10 00:20:58 +0000626
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +0000627 HEREDOC_SKIPTABS = 1,
628 HEREDOC_QUOTED = 2,
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +0000629} redir_type;
630
Eric Andersen25f27032001-04-26 23:22:31 +0000631
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000632struct command {
Denis Vlasenko0c886c62007-01-30 22:30:09 +0000633 pid_t pid; /* 0 if exited */
Denys Vlasenko21b7f1b2018-04-05 15:15:53 +0200634 unsigned assignment_cnt; /* how many argv[i] are assignments? */
Denys Vlasenko5807e182018-02-08 19:19:04 +0100635#if ENABLE_HUSH_LINENO_VAR
Denys Vlasenko6aad1dd2018-01-19 15:37:04 +0100636 unsigned lineno;
637#endif
Denys Vlasenko9d617c42009-06-09 18:40:52 +0200638 smallint cmd_type; /* CMD_xxx */
639#define CMD_NORMAL 0
640#define CMD_SUBSHELL 1
Denys Vlasenko11752d42018-04-03 08:20:58 +0200641#if BASH_TEST2 || ENABLE_HUSH_LOCAL || ENABLE_HUSH_EXPORT || ENABLE_HUSH_READONLY
642/* used for "[[ EXPR ]]", and to prevent word splitting and globbing in
643 * "export v=t*"
644 */
Denys Vlasenko9ca656b2009-06-10 13:39:35 +0200645# define CMD_SINGLEWORD_NOGLOB 2
Denis Vlasenkoed055212009-04-11 10:37:10 +0000646#endif
Denys Vlasenko9ca656b2009-06-10 13:39:35 +0200647#if ENABLE_HUSH_FUNCTIONS
648# define CMD_FUNCDEF 3
649#endif
650
Denys Vlasenko6696eac2010-11-14 02:01:50 +0100651 smalluint cmd_exitcode;
Denys Vlasenkocb6ff252009-05-04 00:14:30 +0200652 /* if non-NULL, this "command" is { list }, ( list ), or a compound statement */
653 struct pipe *group;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000654#if !BB_MMU
655 char *group_as_string;
656#endif
Denis Vlasenkoed055212009-04-11 10:37:10 +0000657#if ENABLE_HUSH_FUNCTIONS
658 struct function *child_func;
659/* This field is used to prevent a bug here:
Denys Vlasenko9d617c42009-06-09 18:40:52 +0200660 * while...do f1() {a;}; f1; f1() {b;}; f1; done
Denis Vlasenkoed055212009-04-11 10:37:10 +0000661 * When we execute "f1() {a;}" cmd, we create new function and clear
662 * cmd->group, cmd->group_as_string, cmd->argv[0].
Denys Vlasenko9d617c42009-06-09 18:40:52 +0200663 * When we execute "f1() {b;}", we notice that f1 exists,
664 * and that its "parent cmd" struct is still "alive",
Denis Vlasenkoed055212009-04-11 10:37:10 +0000665 * we put those fields back into cmd->xxx
666 * (struct function has ->parent_cmd ptr to facilitate that).
667 * When we loop back, we can execute "f1() {a;}" again and set f1 correctly.
668 * Without this trick, loop would execute a;b;b;b;...
669 * instead of correct sequence a;b;a;b;...
670 * When command is freed, it severs the link
671 * (sets ->child_func->parent_cmd to NULL).
672 */
673#endif
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000674 char **argv; /* command name and arguments */
Denis Vlasenko03eb8bf2007-05-14 16:19:34 +0000675/* argv vector may contain variable references (^Cvar^C, ^C0^C etc)
676 * and on execution these are substituted with their values.
677 * Substitution can make _several_ words out of one argv[n]!
678 * Example: argv[0]=='.^C*^C.' here: echo .$*.
Denis Vlasenkoc7985b72008-06-17 05:43:38 +0000679 * References of the form ^C`cmd arg^C are `cmd arg` substitutions.
Denis Vlasenko03eb8bf2007-05-14 16:19:34 +0000680 */
Denis Vlasenkoed055212009-04-11 10:37:10 +0000681 struct redir_struct *redirects; /* I/O redirections */
682};
Denis Vlasenkof8c1f022009-04-17 11:55:42 +0000683/* Is there anything in this command at all? */
684#define IS_NULL_CMD(cmd) \
685 (!(cmd)->group && !(cmd)->argv && !(cmd)->redirects)
686
Eric Andersen25f27032001-04-26 23:22:31 +0000687struct pipe {
Denis Vlasenkob81b3df2007-04-28 16:48:04 +0000688 struct pipe *next;
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +0000689 int num_cmds; /* total number of commands in pipe */
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000690 int alive_cmds; /* number of commands running (not exited) */
691 int stopped_cmds; /* number of commands alive, but stopped */
Denis Vlasenkoe3f2f892007-04-28 16:48:27 +0000692#if ENABLE_HUSH_JOB
Denys Vlasenkod5b5c2f2017-01-08 15:46:04 +0100693 unsigned jobid; /* job number */
Denis Vlasenko0c886c62007-01-30 22:30:09 +0000694 pid_t pgrp; /* process group ID for the job */
Denis Vlasenko219e88d2007-05-21 10:18:23 +0000695 char *cmdtext; /* name of job */
Denis Vlasenkob81b3df2007-04-28 16:48:04 +0000696#endif
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000697 struct command *cmds; /* array of commands in pipe */
Denis Vlasenko219e88d2007-05-21 10:18:23 +0000698 smallint followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
Denis Vlasenko5ec61322008-06-24 00:50:07 +0000699 IF_HAS_KEYWORDS(smallint pi_inverted;) /* "! cmd | cmd" */
700 IF_HAS_KEYWORDS(smallint res_word;) /* needed for if, for, while, until... */
Eric Andersen25f27032001-04-26 23:22:31 +0000701};
Denis Vlasenkoa2b11e32009-04-06 14:11:13 +0000702typedef enum pipe_style {
Denys Vlasenko00a06b92016-11-08 20:35:53 +0100703 PIPE_SEQ = 0,
704 PIPE_AND = 1,
705 PIPE_OR = 2,
706 PIPE_BG = 3,
Denis Vlasenkoa2b11e32009-04-06 14:11:13 +0000707} pipe_style;
Denis Vlasenkof8c1f022009-04-17 11:55:42 +0000708/* Is there anything in this pipe at all? */
709#define IS_NULL_PIPE(pi) \
710 ((pi)->num_cmds == 0 IF_HAS_KEYWORDS( && (pi)->res_word == RES_NONE))
Eric Andersen25f27032001-04-26 23:22:31 +0000711
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000712/* This holds pointers to the various results of parsing */
713struct parse_context {
Denis Vlasenkof9f74292009-04-03 00:07:05 +0000714 /* linked list of pipes */
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000715 struct pipe *list_head;
Denis Vlasenkof9f74292009-04-03 00:07:05 +0000716 /* last pipe (being constructed right now) */
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000717 struct pipe *pipe;
Denis Vlasenkof9f74292009-04-03 00:07:05 +0000718 /* last command in pipe (being constructed right now) */
719 struct command *command;
720 /* last redirect in command->redirects list */
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000721 struct redir_struct *pending_redirect;
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +0200722 o_string word;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000723#if !BB_MMU
724 o_string as_string;
725#endif
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +0200726 smallint is_assignment; /* 0:maybe, 1:yes, 2:no, 3:keyword */
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000727#if HAS_KEYWORDS
728 smallint ctx_res_w;
729 smallint ctx_inverted; /* "! cmd | cmd" */
730#if ENABLE_HUSH_CASE
731 smallint ctx_dsemicolon; /* ";;" seen */
732#endif
Denis Vlasenkof9f74292009-04-03 00:07:05 +0000733 /* bitmask of FLAG_xxx, for figuring out valid reserved words */
734 int old_flag;
735 /* group we are enclosed in:
Denis Vlasenko34d4d892009-04-04 20:24:37 +0000736 * example: "if pipe1; pipe2; then pipe3; fi"
737 * when we see "if" or "then", we malloc and copy current context,
738 * and make ->stack point to it. then we parse pipeN.
739 * when closing "then" / fi" / whatever is found,
740 * we move list_head into ->stack->command->group,
741 * copy ->stack into current context, and delete ->stack.
742 * (parsing of { list } and ( list ) doesn't use this method)
Denis Vlasenkof9f74292009-04-03 00:07:05 +0000743 */
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000744 struct parse_context *stack;
745#endif
746};
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +0200747enum {
748 MAYBE_ASSIGNMENT = 0,
749 DEFINITELY_ASSIGNMENT = 1,
750 NOT_ASSIGNMENT = 2,
751 /* Not an assignment, but next word may be: "if v=xyz cmd;" */
752 WORD_IS_KEYWORD = 3,
753};
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000754
Denis Vlasenkod76c0492007-05-25 02:16:25 +0000755/* On program start, environ points to initial environment.
756 * putenv adds new pointers into it, unsetenv removes them.
757 * Neither of these (de)allocates the strings.
758 * setenv allocates new strings in malloc space and does putenv,
759 * and thus setenv is unusable (leaky) for shell's purposes */
760#define setenv(...) setenv_is_leaky_dont_use()
761struct variable {
762 struct variable *next;
Denis Vlasenko28c0f0f2007-05-25 02:46:01 +0000763 char *varstr; /* points to "name=" portion */
Denis Vlasenkod76c0492007-05-25 02:16:25 +0000764 int max_len; /* if > 0, name is part of initial env; else name is malloced */
Denys Vlasenko332e4112018-04-04 22:32:59 +0200765 uint16_t var_nest_level;
Denis Vlasenkod76c0492007-05-25 02:16:25 +0000766 smallint flg_export; /* putenv should be done on this var */
Denis Vlasenko219e88d2007-05-21 10:18:23 +0000767 smallint flg_read_only;
Eric Andersen9ffb7dd2001-05-19 03:00:46 +0000768};
769
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000770enum {
Denis Vlasenkobcb25532008-07-28 23:04:34 +0000771 BC_BREAK = 1,
772 BC_CONTINUE = 2,
773};
774
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +0000775#if ENABLE_HUSH_FUNCTIONS
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +0000776struct function {
777 struct function *next;
778 char *name;
Denis Vlasenkoed055212009-04-11 10:37:10 +0000779 struct command *parent_cmd;
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +0000780 struct pipe *body;
Denys Vlasenkoc1947f12009-10-23 01:30:26 +0200781# if !BB_MMU
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +0000782 char *body_as_string;
Denys Vlasenkoc1947f12009-10-23 01:30:26 +0200783# endif
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +0000784};
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +0000785#endif
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +0000786
Denis Vlasenkod76c0492007-05-25 02:16:25 +0000787
Denys Vlasenko6696eac2010-11-14 02:01:50 +0100788/* set -/+o OPT support. (TODO: make it optional)
789 * bash supports the following opts:
790 * allexport off
791 * braceexpand on
792 * emacs on
793 * errexit off
794 * errtrace off
795 * functrace off
796 * hashall on
797 * histexpand off
798 * history on
799 * ignoreeof off
800 * interactive-comments on
801 * keyword off
802 * monitor on
803 * noclobber off
804 * noexec off
805 * noglob off
806 * nolog off
807 * notify off
808 * nounset off
809 * onecmd off
810 * physical off
811 * pipefail off
812 * posix off
813 * privileged off
814 * verbose off
815 * vi off
816 * xtrace off
817 */
Dan Fandrich85c62472010-11-20 13:05:17 -0800818static const char o_opt_strings[] ALIGN1 =
819 "pipefail\0"
820 "noexec\0"
Denys Vlasenko9fda6092017-07-14 13:36:48 +0200821 "errexit\0"
Dan Fandrich85c62472010-11-20 13:05:17 -0800822#if ENABLE_HUSH_MODE_X
823 "xtrace\0"
824#endif
825 ;
Denys Vlasenko6696eac2010-11-14 02:01:50 +0100826enum {
827 OPT_O_PIPEFAIL,
Dan Fandrich85c62472010-11-20 13:05:17 -0800828 OPT_O_NOEXEC,
Denys Vlasenko9fda6092017-07-14 13:36:48 +0200829 OPT_O_ERREXIT,
Dan Fandrich85c62472010-11-20 13:05:17 -0800830#if ENABLE_HUSH_MODE_X
831 OPT_O_XTRACE,
832#endif
Denys Vlasenko6696eac2010-11-14 02:01:50 +0100833 NUM_OPT_O
834};
835
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000836/* "Globals" within this file */
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000837/* Sorted roughly by size (smaller offsets == smaller code) */
838struct globals {
Denis Vlasenkoc8653f62009-04-27 23:29:14 +0000839 /* interactive_fd != 0 means we are an interactive shell.
840 * If we are, then saved_tty_pgrp can also be != 0, meaning
841 * that controlling tty is available. With saved_tty_pgrp == 0,
842 * job control still works, but terminal signals
843 * (^C, ^Z, ^Y, ^\) won't work at all, and background
844 * process groups can only be created with "cmd &".
845 * With saved_tty_pgrp != 0, hush will use tcsetpgrp()
846 * to give tty to the foreground process group,
847 * and will take it back when the group is stopped (^Z)
848 * or killed (^C).
849 */
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000850#if ENABLE_HUSH_INTERACTIVE
851 /* 'interactive_fd' is a fd# open to ctty, if we have one
852 * _AND_ if we decided to act interactively */
853 int interactive_fd;
854 const char *PS1;
Denys Vlasenkof5018da2018-04-06 17:58:21 +0200855 IF_FEATURE_EDITING_FANCY_PROMPT(const char *PS2;)
Denis Vlasenkoc8653f62009-04-27 23:29:14 +0000856# define G_interactive_fd (G.interactive_fd)
Denis Vlasenko60b392f2009-04-03 19:14:32 +0000857#else
Denis Vlasenkoc8653f62009-04-27 23:29:14 +0000858# define G_interactive_fd 0
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000859#endif
860#if ENABLE_FEATURE_EDITING
861 line_input_t *line_input_state;
862#endif
Denis Vlasenkocc3f20b2008-06-23 22:31:52 +0000863 pid_t root_pid;
Denys Vlasenkodea47882009-10-09 15:40:49 +0200864 pid_t root_ppid;
Denis Vlasenko87a86552008-07-29 19:43:10 +0000865 pid_t last_bg_pid;
Denys Vlasenko20b3d142009-10-09 20:59:39 +0200866#if ENABLE_HUSH_RANDOM_SUPPORT
867 random_t random_gen;
868#endif
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000869#if ENABLE_HUSH_JOB
870 int run_list_level;
Denys Vlasenkod5b5c2f2017-01-08 15:46:04 +0100871 unsigned last_jobid;
Denis Vlasenkoc8653f62009-04-27 23:29:14 +0000872 pid_t saved_tty_pgrp;
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000873 struct pipe *job_list;
Mike Frysinger38478a62009-05-20 04:48:06 -0400874# define G_saved_tty_pgrp (G.saved_tty_pgrp)
875#else
876# define G_saved_tty_pgrp 0
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000877#endif
Denys Vlasenko9fda6092017-07-14 13:36:48 +0200878 /* How deeply are we in context where "set -e" is ignored */
879 int errexit_depth;
880 /* "set -e" rules (do we follow them correctly?):
881 * Exit if pipe, list, or compound command exits with a non-zero status.
882 * Shell does not exit if failed command is part of condition in
883 * if/while, part of && or || list except the last command, any command
884 * in a pipe but the last, or if the command's return value is being
885 * inverted with !. If a compound command other than a subshell returns a
886 * non-zero status because a command failed while -e was being ignored, the
887 * shell does not exit. A trap on ERR, if set, is executed before the shell
888 * exits [ERR is a bashism].
889 *
890 * If a compound command or function executes in a context where -e is
891 * ignored, none of the commands executed within are affected by the -e
892 * setting. If a compound command or function sets -e while executing in a
893 * context where -e is ignored, that setting does not have any effect until
894 * the compound command or the command containing the function call completes.
895 */
896
Denys Vlasenko26777aa2010-11-22 23:49:10 +0100897 char o_opt[NUM_OPT_O];
Denys Vlasenko57542eb2010-11-28 03:59:30 +0100898#if ENABLE_HUSH_MODE_X
899# define G_x_mode (G.o_opt[OPT_O_XTRACE])
900#else
901# define G_x_mode 0
902#endif
Denys Vlasenko8d6eab32018-04-07 17:01:31 +0200903#if ENABLE_HUSH_INTERACTIVE
904 smallint promptmode; /* 0: PS1, 1: PS2 */
905#endif
Denis Vlasenko422cd7c2009-03-31 12:41:52 +0000906 smallint flag_SIGINT;
Denis Vlasenkodadfb492008-07-29 10:16:05 +0000907#if ENABLE_HUSH_LOOPS
Denis Vlasenkobcb25532008-07-28 23:04:34 +0000908 smallint flag_break_continue;
Denis Vlasenkodadfb492008-07-29 10:16:05 +0000909#endif
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +0000910#if ENABLE_HUSH_FUNCTIONS
911 /* 0: outside of a function (or sourced file)
912 * -1: inside of a function, ok to use return builtin
Denis Vlasenkoc8653f62009-04-27 23:29:14 +0000913 * 1: return is invoked, skip all till end of func
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +0000914 */
915 smallint flag_return_in_progress;
Denys Vlasenko04b46bc2016-10-01 22:28:03 +0200916# define G_flag_return_in_progress (G.flag_return_in_progress)
917#else
918# define G_flag_return_in_progress 0
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +0000919#endif
Denis Vlasenkoefea9d22009-04-09 13:43:11 +0000920 smallint exiting; /* used to prevent EXIT trap recursion */
Denys Vlasenko5fa05052018-04-03 11:21:13 +0200921 /* These support $?, $#, and $1 */
Denis Vlasenkoab2b0642009-04-06 18:42:11 +0000922 smalluint last_exitcode;
Denys Vlasenko5fa05052018-04-03 11:21:13 +0200923 smalluint expand_exitcode;
Denys Vlasenko840a4352017-07-07 22:56:02 +0200924 smalluint last_bg_pid_exitcode;
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +0100925#if ENABLE_HUSH_SET
Denis Vlasenkocc4c6932009-04-05 07:38:48 +0000926 /* are global_argv and global_argv[1..n] malloced? (note: not [0]) */
Denis Vlasenko11fb7cf2009-03-20 10:13:08 +0000927 smalluint global_args_malloced;
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +0100928# define G_global_args_malloced (G.global_args_malloced)
929#else
930# define G_global_args_malloced 0
931#endif
Denis Vlasenkoe1300f62009-03-22 11:41:18 +0000932 /* how many non-NULL argv's we have. NB: $# + 1 */
933 int global_argc;
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000934 char **global_argv;
Denis Vlasenkocc4c6932009-04-05 07:38:48 +0000935#if !BB_MMU
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +0000936 char *argv0_for_re_execing;
Denis Vlasenkocc4c6932009-04-05 07:38:48 +0000937#endif
Denis Vlasenkodadfb492008-07-29 10:16:05 +0000938#if ENABLE_HUSH_LOOPS
Denis Vlasenko6a2d40f2008-07-28 23:07:06 +0000939 unsigned depth_break_continue;
Denis Vlasenkofcf37c32008-07-29 11:37:15 +0000940 unsigned depth_of_loop;
Denis Vlasenkodadfb492008-07-29 10:16:05 +0000941#endif
Denys Vlasenko238ff982017-08-29 13:38:30 +0200942#if ENABLE_HUSH_GETOPTS
943 unsigned getopt_count;
944#endif
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000945 const char *ifs;
Denys Vlasenko96786362018-04-11 16:02:58 +0200946 char *ifs_whitespace; /* = G.ifs or malloced */
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000947 const char *cwd;
Denys Vlasenko52e460b2010-09-16 16:12:00 +0200948 struct variable *top_var;
Denys Vlasenko29082232010-07-16 13:52:32 +0200949 char **expanded_assignments;
Denys Vlasenko295fef82009-06-03 12:47:26 +0200950 struct variable **shadowed_vars_pp;
Denys Vlasenko332e4112018-04-04 22:32:59 +0200951 unsigned var_nest_level;
952#if ENABLE_HUSH_FUNCTIONS
953# if ENABLE_HUSH_LOCAL
954 unsigned func_nest_level; /* solely to prevent "local v" in non-functions */
Denys Vlasenko295fef82009-06-03 12:47:26 +0200955# endif
Denys Vlasenko332e4112018-04-04 22:32:59 +0200956 struct function *top_func;
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +0000957#endif
Denis Vlasenkod5762932009-03-31 11:22:57 +0000958 /* Signal and trap handling */
Denys Vlasenko8d7be232009-05-25 16:38:32 +0200959#if ENABLE_HUSH_FAST
960 unsigned count_SIGCHLD;
961 unsigned handled_SIGCHLD;
Denys Vlasenkoe2df5f42009-05-26 14:34:10 +0200962 smallint we_have_children;
Denys Vlasenko8d7be232009-05-25 16:38:32 +0200963#endif
Denys Vlasenko5807e182018-02-08 19:19:04 +0100964#if ENABLE_HUSH_LINENO_VAR
Denys Vlasenko6aad1dd2018-01-19 15:37:04 +0100965 unsigned lineno;
966 char *lineno_var;
Denys Vlasenko6aad1dd2018-01-19 15:37:04 +0100967#endif
Denys Vlasenko41ef41b2018-07-24 16:54:41 +0200968 HFILE *HFILE_list;
Denys Vlasenko10c01312011-05-11 11:49:21 +0200969 /* Which signals have non-DFL handler (even with no traps set)?
970 * Set at the start to:
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +0200971 * (SIGQUIT + maybe SPECIAL_INTERACTIVE_SIGS + maybe SPECIAL_JOBSTOP_SIGS)
Denys Vlasenko10c01312011-05-11 11:49:21 +0200972 * SPECIAL_INTERACTIVE_SIGS are cleared after fork.
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +0200973 * The rest is cleared right before execv syscalls.
Denys Vlasenko10c01312011-05-11 11:49:21 +0200974 * Other than these two times, never modified.
975 */
976 unsigned special_sig_mask;
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +0200977#if ENABLE_HUSH_JOB
978 unsigned fatal_sig_mask;
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +0100979# define G_fatal_sig_mask (G.fatal_sig_mask)
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +0200980#else
Denys Vlasenko75e77de2011-05-12 13:12:47 +0200981# define G_fatal_sig_mask 0
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +0200982#endif
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100983#if ENABLE_HUSH_TRAP
Denis Vlasenko7566bae2009-03-31 17:24:49 +0000984 char **traps; /* char *traps[NSIG] */
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100985# define G_traps G.traps
986#else
987# define G_traps ((char**)NULL)
988#endif
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +0200989 sigset_t pending_set;
Denys Vlasenko44719692017-01-08 18:44:41 +0100990#if ENABLE_HUSH_MEMLEAK
Denis Vlasenkoc73b70c2009-04-08 11:48:57 +0000991 unsigned long memleak_value;
Denys Vlasenko44719692017-01-08 18:44:41 +0100992#endif
Denys Vlasenkoaa449c92018-07-28 12:13:58 +0200993#if ENABLE_HUSH_MODE_X
994 unsigned x_mode_depth;
995 /* "set -x" output should not be redirectable with subsequent 2>FILE.
996 * We dup fd#2 to x_mode_fd when "set -x" is executed, and use it
997 * for all subsequent output.
998 */
999 int x_mode_fd;
1000 o_string x_mode_buf;
1001#endif
Denys Vlasenkoa8e74412018-07-28 12:16:30 +02001002#if HUSH_DEBUG >= 2
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001003 int debug_indent;
Denis Vlasenkoc73b70c2009-04-08 11:48:57 +00001004#endif
Denys Vlasenko0806e402011-05-12 23:06:20 +02001005 struct sigaction sa;
Denys Vlasenko0448c552016-09-29 20:25:44 +02001006#if ENABLE_FEATURE_EDITING
1007 char user_input_buf[CONFIG_FEATURE_EDITING_MAX_LEN];
1008#endif
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +00001009};
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +00001010#define G (*ptr_to_globals)
Denis Vlasenko87a86552008-07-29 19:43:10 +00001011/* Not #defining name to G.name - this quickly gets unwieldy
1012 * (too many defines). Also, I actually prefer to see when a variable
1013 * is global, thus "G." prefix is a useful hint */
Denis Vlasenko574f2f42008-02-27 18:41:59 +00001014#define INIT_G() do { \
1015 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
Denys Vlasenko0806e402011-05-12 23:06:20 +02001016 /* memset(&G.sa, 0, sizeof(G.sa)); */ \
1017 sigfillset(&G.sa.sa_mask); \
1018 G.sa.sa_flags = SA_RESTART; \
Denis Vlasenko574f2f42008-02-27 18:41:59 +00001019} while (0)
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +00001020
1021
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001022/* Function prototypes for builtins */
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001023static int builtin_cd(char **argv) FAST_FUNC;
Denys Vlasenko1cc68042017-01-09 17:10:04 +01001024#if ENABLE_HUSH_ECHO
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001025static int builtin_echo(char **argv) FAST_FUNC;
Denys Vlasenko1cc68042017-01-09 17:10:04 +01001026#endif
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001027static int builtin_eval(char **argv) FAST_FUNC;
1028static int builtin_exec(char **argv) FAST_FUNC;
1029static int builtin_exit(char **argv) FAST_FUNC;
Denys Vlasenko6ec76d82017-01-08 18:40:41 +01001030#if ENABLE_HUSH_EXPORT
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001031static int builtin_export(char **argv) FAST_FUNC;
Denys Vlasenko6ec76d82017-01-08 18:40:41 +01001032#endif
Denys Vlasenko1e660422017-07-17 21:10:50 +02001033#if ENABLE_HUSH_READONLY
1034static int builtin_readonly(char **argv) FAST_FUNC;
1035#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001036#if ENABLE_HUSH_JOB
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001037static int builtin_fg_bg(char **argv) FAST_FUNC;
1038static int builtin_jobs(char **argv) FAST_FUNC;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001039#endif
Denys Vlasenko74d40582017-08-11 01:32:46 +02001040#if ENABLE_HUSH_GETOPTS
1041static int builtin_getopts(char **argv) FAST_FUNC;
1042#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001043#if ENABLE_HUSH_HELP
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001044static int builtin_help(char **argv) FAST_FUNC;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001045#endif
Denys Vlasenkoff463a82013-05-12 02:45:23 +02001046#if MAX_HISTORY && ENABLE_FEATURE_EDITING
Flemming Madsend96ffda2013-04-07 18:47:24 +02001047static int builtin_history(char **argv) FAST_FUNC;
1048#endif
Denys Vlasenko295fef82009-06-03 12:47:26 +02001049#if ENABLE_HUSH_LOCAL
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001050static int builtin_local(char **argv) FAST_FUNC;
Denys Vlasenko295fef82009-06-03 12:47:26 +02001051#endif
Denys Vlasenko44719692017-01-08 18:44:41 +01001052#if ENABLE_HUSH_MEMLEAK
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001053static int builtin_memleak(char **argv) FAST_FUNC;
Denis Vlasenkoc73b70c2009-04-08 11:48:57 +00001054#endif
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001055#if ENABLE_HUSH_PRINTF
Mike Frysinger4ebc76c2009-10-15 03:32:39 -04001056static int builtin_printf(char **argv) FAST_FUNC;
1057#endif
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001058static int builtin_pwd(char **argv) FAST_FUNC;
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001059#if ENABLE_HUSH_READ
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001060static int builtin_read(char **argv) FAST_FUNC;
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001061#endif
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01001062#if ENABLE_HUSH_SET
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001063static int builtin_set(char **argv) FAST_FUNC;
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01001064#endif
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001065static int builtin_shift(char **argv) FAST_FUNC;
1066static int builtin_source(char **argv) FAST_FUNC;
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01001067#if ENABLE_HUSH_TEST || BASH_TEST2
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001068static int builtin_test(char **argv) FAST_FUNC;
Denys Vlasenko265062d2017-01-10 15:13:30 +01001069#endif
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001070#if ENABLE_HUSH_TRAP
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001071static int builtin_trap(char **argv) FAST_FUNC;
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001072#endif
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001073#if ENABLE_HUSH_TYPE
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001074static int builtin_type(char **argv) FAST_FUNC;
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001075#endif
Denys Vlasenko11f2e992017-08-10 16:34:03 +02001076#if ENABLE_HUSH_TIMES
1077static int builtin_times(char **argv) FAST_FUNC;
1078#endif
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001079static int builtin_true(char **argv) FAST_FUNC;
Denys Vlasenkod5933b12017-01-08 18:31:39 +01001080#if ENABLE_HUSH_UMASK
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001081static int builtin_umask(char **argv) FAST_FUNC;
Denys Vlasenkod5933b12017-01-08 18:31:39 +01001082#endif
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01001083#if ENABLE_HUSH_UNSET
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001084static int builtin_unset(char **argv) FAST_FUNC;
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01001085#endif
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001086#if ENABLE_HUSH_KILL
1087static int builtin_kill(char **argv) FAST_FUNC;
1088#endif
1089#if ENABLE_HUSH_WAIT
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001090static int builtin_wait(char **argv) FAST_FUNC;
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001091#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001092#if ENABLE_HUSH_LOOPS
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001093static int builtin_break(char **argv) FAST_FUNC;
1094static int builtin_continue(char **argv) FAST_FUNC;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001095#endif
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +00001096#if ENABLE_HUSH_FUNCTIONS
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001097static int builtin_return(char **argv) FAST_FUNC;
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +00001098#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001099
1100/* Table of built-in functions. They can be forked or not, depending on
1101 * context: within pipes, they fork. As simple commands, they do not.
1102 * When used in non-forking context, they can change global variables
1103 * in the parent shell process. If forked, of course they cannot.
1104 * For example, 'unset foo | whatever' will parse and run, but foo will
1105 * still be set at the end. */
1106struct built_in_command {
Denys Vlasenko17323a62010-01-28 01:57:05 +01001107 const char *b_cmd;
1108 int (*b_function)(char **argv) FAST_FUNC;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001109#if ENABLE_HUSH_HELP
Denys Vlasenko17323a62010-01-28 01:57:05 +01001110 const char *b_descr;
Denys Vlasenko28a105d2009-06-01 11:26:30 +02001111# define BLTIN(cmd, func, help) { cmd, func, help }
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001112#else
Denys Vlasenko28a105d2009-06-01 11:26:30 +02001113# define BLTIN(cmd, func, help) { cmd, func }
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001114#endif
1115};
1116
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001117static const struct built_in_command bltins1[] = {
Denys Vlasenko80f806c2017-01-10 16:51:10 +01001118 BLTIN("." , builtin_source , "Run commands in file"),
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001119 BLTIN(":" , builtin_true , NULL),
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001120#if ENABLE_HUSH_JOB
Denys Vlasenko80f806c2017-01-10 16:51:10 +01001121 BLTIN("bg" , builtin_fg_bg , "Resume job in background"),
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001122#endif
1123#if ENABLE_HUSH_LOOPS
Denys Vlasenko80f806c2017-01-10 16:51:10 +01001124 BLTIN("break" , builtin_break , "Exit loop"),
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001125#endif
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001126 BLTIN("cd" , builtin_cd , "Change directory"),
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001127#if ENABLE_HUSH_LOOPS
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001128 BLTIN("continue" , builtin_continue, "Start new loop iteration"),
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001129#endif
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001130 BLTIN("eval" , builtin_eval , "Construct and run shell command"),
1131 BLTIN("exec" , builtin_exec , "Execute command, don't return to shell"),
Denys Vlasenko80f806c2017-01-10 16:51:10 +01001132 BLTIN("exit" , builtin_exit , NULL),
Denys Vlasenko6ec76d82017-01-08 18:40:41 +01001133#if ENABLE_HUSH_EXPORT
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001134 BLTIN("export" , builtin_export , "Set environment variables"),
Denys Vlasenko6ec76d82017-01-08 18:40:41 +01001135#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001136#if ENABLE_HUSH_JOB
Denys Vlasenkod2c15bc2017-07-18 18:14:42 +02001137 BLTIN("fg" , builtin_fg_bg , "Bring job to foreground"),
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001138#endif
Denys Vlasenko74d40582017-08-11 01:32:46 +02001139#if ENABLE_HUSH_GETOPTS
1140 BLTIN("getopts" , builtin_getopts , NULL),
1141#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001142#if ENABLE_HUSH_HELP
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001143 BLTIN("help" , builtin_help , NULL),
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001144#endif
Denys Vlasenkoff463a82013-05-12 02:45:23 +02001145#if MAX_HISTORY && ENABLE_FEATURE_EDITING
Denys Vlasenko80f806c2017-01-10 16:51:10 +01001146 BLTIN("history" , builtin_history , "Show history"),
Flemming Madsend96ffda2013-04-07 18:47:24 +02001147#endif
Denis Vlasenko34d4d892009-04-04 20:24:37 +00001148#if ENABLE_HUSH_JOB
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001149 BLTIN("jobs" , builtin_jobs , "List jobs"),
Denis Vlasenko34d4d892009-04-04 20:24:37 +00001150#endif
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001151#if ENABLE_HUSH_KILL
1152 BLTIN("kill" , builtin_kill , "Send signals to processes"),
1153#endif
Denys Vlasenko295fef82009-06-03 12:47:26 +02001154#if ENABLE_HUSH_LOCAL
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001155 BLTIN("local" , builtin_local , "Set local variables"),
Denys Vlasenko295fef82009-06-03 12:47:26 +02001156#endif
Denys Vlasenko44719692017-01-08 18:44:41 +01001157#if ENABLE_HUSH_MEMLEAK
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001158 BLTIN("memleak" , builtin_memleak , NULL),
Denis Vlasenkoc73b70c2009-04-08 11:48:57 +00001159#endif
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001160#if ENABLE_HUSH_READ
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001161 BLTIN("read" , builtin_read , "Input into variable"),
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001162#endif
Denys Vlasenko1e660422017-07-17 21:10:50 +02001163#if ENABLE_HUSH_READONLY
1164 BLTIN("readonly" , builtin_readonly, "Make variables read-only"),
1165#endif
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +00001166#if ENABLE_HUSH_FUNCTIONS
Denys Vlasenko80f806c2017-01-10 16:51:10 +01001167 BLTIN("return" , builtin_return , "Return from function"),
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +00001168#endif
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01001169#if ENABLE_HUSH_SET
Denys Vlasenko80f806c2017-01-10 16:51:10 +01001170 BLTIN("set" , builtin_set , "Set positional parameters"),
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01001171#endif
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001172 BLTIN("shift" , builtin_shift , "Shift positional parameters"),
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01001173#if BASH_SOURCE
Denys Vlasenko80f806c2017-01-10 16:51:10 +01001174 BLTIN("source" , builtin_source , NULL),
Denys Vlasenko82731b42010-05-17 17:49:52 +02001175#endif
Denys Vlasenko11f2e992017-08-10 16:34:03 +02001176#if ENABLE_HUSH_TIMES
1177 BLTIN("times" , builtin_times , NULL),
1178#endif
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001179#if ENABLE_HUSH_TRAP
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001180 BLTIN("trap" , builtin_trap , "Trap signals"),
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001181#endif
Denys Vlasenko2bba5912014-03-14 12:43:57 +01001182 BLTIN("true" , builtin_true , NULL),
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001183#if ENABLE_HUSH_TYPE
Denys Vlasenko651a2692010-03-23 16:25:17 +01001184 BLTIN("type" , builtin_type , "Show command type"),
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001185#endif
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001186#if ENABLE_HUSH_ULIMIT
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01001187 BLTIN("ulimit" , shell_builtin_ulimit, "Control resource limits"),
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001188#endif
Denys Vlasenkod5933b12017-01-08 18:31:39 +01001189#if ENABLE_HUSH_UMASK
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001190 BLTIN("umask" , builtin_umask , "Set file creation mask"),
Denys Vlasenkod5933b12017-01-08 18:31:39 +01001191#endif
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01001192#if ENABLE_HUSH_UNSET
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001193 BLTIN("unset" , builtin_unset , "Unset variables"),
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01001194#endif
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001195#if ENABLE_HUSH_WAIT
Denys Vlasenkod2c15bc2017-07-18 18:14:42 +02001196 BLTIN("wait" , builtin_wait , "Wait for process to finish"),
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001197#endif
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001198};
Denys Vlasenko80f806c2017-01-10 16:51:10 +01001199/* These builtins won't be used if we are on NOMMU and need to re-exec
1200 * (it's cheaper to run an external program in this case):
1201 */
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001202static const struct built_in_command bltins2[] = {
Denys Vlasenko265062d2017-01-10 15:13:30 +01001203#if ENABLE_HUSH_TEST
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001204 BLTIN("[" , builtin_test , NULL),
Denys Vlasenko265062d2017-01-10 15:13:30 +01001205#endif
Denys Vlasenko8944c672017-01-11 14:22:00 +01001206#if BASH_TEST2
1207 BLTIN("[[" , builtin_test , NULL),
1208#endif
Denys Vlasenko1cc68042017-01-09 17:10:04 +01001209#if ENABLE_HUSH_ECHO
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001210 BLTIN("echo" , builtin_echo , NULL),
Denys Vlasenko1cc68042017-01-09 17:10:04 +01001211#endif
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001212#if ENABLE_HUSH_PRINTF
Mike Frysinger4ebc76c2009-10-15 03:32:39 -04001213 BLTIN("printf" , builtin_printf , NULL),
1214#endif
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001215 BLTIN("pwd" , builtin_pwd , NULL),
Denys Vlasenko265062d2017-01-10 15:13:30 +01001216#if ENABLE_HUSH_TEST
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001217 BLTIN("test" , builtin_test , NULL),
Denys Vlasenko265062d2017-01-10 15:13:30 +01001218#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001219};
1220
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +00001221
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001222/* Debug printouts.
1223 */
Denys Vlasenkoa8e74412018-07-28 12:16:30 +02001224#if HUSH_DEBUG >= 2
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001225/* prevent disasters with G.debug_indent < 0 */
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001226# define indent() fdprintf(2, "%*s", (G.debug_indent * 2) & 0xff, "")
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001227# define debug_enter() (G.debug_indent++)
1228# define debug_leave() (G.debug_indent--)
1229#else
Denys Vlasenko28a105d2009-06-01 11:26:30 +02001230# define indent() ((void)0)
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001231# define debug_enter() ((void)0)
1232# define debug_leave() ((void)0)
1233#endif
1234
1235#ifndef debug_printf
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001236# define debug_printf(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001237#endif
1238
1239#ifndef debug_printf_parse
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001240# define debug_printf_parse(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001241#endif
1242
Denys Vlasenko3675c372018-07-23 16:31:21 +02001243#ifndef debug_printf_heredoc
1244# define debug_printf_heredoc(...) (indent(), fdprintf(2, __VA_ARGS__))
1245#endif
1246
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001247#ifndef debug_printf_exec
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001248#define debug_printf_exec(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001249#endif
1250
1251#ifndef debug_printf_env
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001252# define debug_printf_env(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001253#endif
1254
1255#ifndef debug_printf_jobs
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001256# define debug_printf_jobs(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001257# define DEBUG_JOBS 1
1258#else
1259# define DEBUG_JOBS 0
1260#endif
1261
1262#ifndef debug_printf_expand
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001263# define debug_printf_expand(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001264# define DEBUG_EXPAND 1
1265#else
1266# define DEBUG_EXPAND 0
1267#endif
1268
Denys Vlasenko1e811b12010-05-22 03:12:29 +02001269#ifndef debug_printf_varexp
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001270# define debug_printf_varexp(...) (indent(), fdprintf(2, __VA_ARGS__))
Denys Vlasenko1e811b12010-05-22 03:12:29 +02001271#endif
1272
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001273#ifndef debug_printf_glob
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001274# define debug_printf_glob(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001275# define DEBUG_GLOB 1
1276#else
1277# define DEBUG_GLOB 0
1278#endif
1279
Denys Vlasenko2db74612017-07-07 22:07:28 +02001280#ifndef debug_printf_redir
1281# define debug_printf_redir(...) (indent(), fdprintf(2, __VA_ARGS__))
1282#endif
1283
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001284#ifndef debug_printf_list
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001285# define debug_printf_list(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001286#endif
1287
1288#ifndef debug_printf_subst
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001289# define debug_printf_subst(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001290#endif
1291
Denys Vlasenko8d6eab32018-04-07 17:01:31 +02001292#ifndef debug_printf_prompt
1293# define debug_printf_prompt(...) (indent(), fdprintf(2, __VA_ARGS__))
1294#endif
1295
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001296#ifndef debug_printf_clean
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001297# define debug_printf_clean(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001298# define DEBUG_CLEAN 1
1299#else
1300# define DEBUG_CLEAN 0
1301#endif
1302
1303#if DEBUG_EXPAND
1304static void debug_print_strings(const char *prefix, char **vv)
1305{
1306 indent();
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001307 fdprintf(2, "%s:\n", prefix);
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001308 while (*vv)
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001309 fdprintf(2, " '%s'\n", *vv++);
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001310}
1311#else
Denys Vlasenko28a105d2009-06-01 11:26:30 +02001312# define debug_print_strings(prefix, vv) ((void)0)
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001313#endif
1314
1315
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001316/* Leak hunting. Use hush_leaktool.sh for post-processing.
1317 */
1318#if LEAK_HUNTING
1319static void *xxmalloc(int lineno, size_t size)
Denis Vlasenko90e485c2007-05-23 15:22:50 +00001320{
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001321 void *ptr = xmalloc((size + 0xff) & ~0xff);
1322 fdprintf(2, "line %d: malloc %p\n", lineno, ptr);
1323 return ptr;
1324}
1325static void *xxrealloc(int lineno, void *ptr, size_t size)
1326{
1327 ptr = xrealloc(ptr, (size + 0xff) & ~0xff);
1328 fdprintf(2, "line %d: realloc %p\n", lineno, ptr);
1329 return ptr;
1330}
1331static char *xxstrdup(int lineno, const char *str)
1332{
1333 char *ptr = xstrdup(str);
1334 fdprintf(2, "line %d: strdup %p\n", lineno, ptr);
1335 return ptr;
1336}
1337static void xxfree(void *ptr)
1338{
1339 fdprintf(2, "free %p\n", ptr);
1340 free(ptr);
1341}
Denys Vlasenko8391c482010-05-22 17:50:43 +02001342# define xmalloc(s) xxmalloc(__LINE__, s)
1343# define xrealloc(p, s) xxrealloc(__LINE__, p, s)
1344# define xstrdup(s) xxstrdup(__LINE__, s)
1345# define free(p) xxfree(p)
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001346#endif
1347
1348
1349/* Syntax and runtime errors. They always abort scripts.
1350 * In interactive use they usually discard unparsed and/or unexecuted commands
1351 * and return to the prompt.
1352 * HUSH_DEBUG >= 2 prints line number in this file where it was detected.
1353 */
1354#if HUSH_DEBUG < 2
Denys Vlasenko39701202017-08-02 19:44:05 +02001355# define msg_and_die_if_script(lineno, ...) msg_and_die_if_script(__VA_ARGS__)
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00001356# define syntax_error(lineno, msg) syntax_error(msg)
1357# define syntax_error_at(lineno, msg) syntax_error_at(msg)
1358# define syntax_error_unterm_ch(lineno, ch) syntax_error_unterm_ch(ch)
1359# define syntax_error_unterm_str(lineno, s) syntax_error_unterm_str(s)
1360# define syntax_error_unexpected_ch(lineno, ch) syntax_error_unexpected_ch(ch)
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001361#endif
1362
Denys Vlasenko39701202017-08-02 19:44:05 +02001363static void die_if_script(void)
1364{
1365 if (!G_interactive_fd) {
1366 if (G.last_exitcode) /* sometines it's 2, not 1 (bash compat) */
1367 xfunc_error_retval = G.last_exitcode;
1368 xfunc_die();
1369 }
1370}
1371
1372static void msg_and_die_if_script(unsigned lineno, const char *fmt, ...)
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001373{
Denis Vlasenkod68ae082009-04-09 20:41:34 +00001374 va_list p;
1375
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001376#if HUSH_DEBUG >= 2
1377 bb_error_msg("hush.c:%u", lineno);
1378#endif
Denis Vlasenkod68ae082009-04-09 20:41:34 +00001379 va_start(p, fmt);
1380 bb_verror_msg(fmt, p, NULL);
1381 va_end(p);
Denys Vlasenko39701202017-08-02 19:44:05 +02001382 die_if_script();
Mike Frysinger6379bb42009-03-28 18:55:03 +00001383}
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001384
Denys Vlasenkocecbc982011-03-30 18:54:52 +02001385static void syntax_error(unsigned lineno UNUSED_PARAM, const char *msg)
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001386{
1387 if (msg)
Denys Vlasenkocecbc982011-03-30 18:54:52 +02001388 bb_error_msg("syntax error: %s", msg);
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001389 else
Denys Vlasenkocecbc982011-03-30 18:54:52 +02001390 bb_error_msg("syntax error");
Denys Vlasenko39701202017-08-02 19:44:05 +02001391 die_if_script();
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001392}
1393
Denys Vlasenkocecbc982011-03-30 18:54:52 +02001394static void syntax_error_at(unsigned lineno UNUSED_PARAM, const char *msg)
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001395{
Denys Vlasenkocecbc982011-03-30 18:54:52 +02001396 bb_error_msg("syntax error at '%s'", msg);
Denys Vlasenko39701202017-08-02 19:44:05 +02001397 die_if_script();
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001398}
1399
Denys Vlasenkocecbc982011-03-30 18:54:52 +02001400static void syntax_error_unterm_str(unsigned lineno UNUSED_PARAM, const char *s)
Mike Frysinger6a46ab82009-06-01 14:14:36 -04001401{
Denys Vlasenkocecbc982011-03-30 18:54:52 +02001402 bb_error_msg("syntax error: unterminated %s", s);
Denys Vlasenko39701202017-08-02 19:44:05 +02001403//? source4.tests fails: in bash, echo ${^} in script does not terminate the script
1404// die_if_script();
Mike Frysinger6a46ab82009-06-01 14:14:36 -04001405}
1406
Denis Vlasenkod68ae082009-04-09 20:41:34 +00001407static void syntax_error_unterm_ch(unsigned lineno, char ch)
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001408{
Mike Frysinger6a46ab82009-06-01 14:14:36 -04001409 char msg[2] = { ch, '\0' };
1410 syntax_error_unterm_str(lineno, msg);
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001411}
1412
Denys Vlasenkocecbc982011-03-30 18:54:52 +02001413static void syntax_error_unexpected_ch(unsigned lineno UNUSED_PARAM, int ch)
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00001414{
1415 char msg[2];
1416 msg[0] = ch;
1417 msg[1] = '\0';
Denys Vlasenkob05bcaf2017-01-03 11:47:50 +01001418#if HUSH_DEBUG >= 2
1419 bb_error_msg("hush.c:%u", lineno);
1420#endif
Denys Vlasenkocecbc982011-03-30 18:54:52 +02001421 bb_error_msg("syntax error: unexpected %s", ch == EOF ? "EOF" : msg);
Denys Vlasenko39701202017-08-02 19:44:05 +02001422 die_if_script();
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00001423}
1424
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001425#if HUSH_DEBUG < 2
Denys Vlasenko39701202017-08-02 19:44:05 +02001426# undef msg_and_die_if_script
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001427# undef syntax_error
1428# undef syntax_error_at
Denis Vlasenkod68ae082009-04-09 20:41:34 +00001429# undef syntax_error_unterm_ch
1430# undef syntax_error_unterm_str
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00001431# undef syntax_error_unexpected_ch
Denis Vlasenko90e485c2007-05-23 15:22:50 +00001432#else
Denys Vlasenko39701202017-08-02 19:44:05 +02001433# define msg_and_die_if_script(...) msg_and_die_if_script(__LINE__, __VA_ARGS__)
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00001434# define syntax_error(msg) syntax_error(__LINE__, msg)
1435# define syntax_error_at(msg) syntax_error_at(__LINE__, msg)
1436# define syntax_error_unterm_ch(ch) syntax_error_unterm_ch(__LINE__, ch)
1437# define syntax_error_unterm_str(s) syntax_error_unterm_str(__LINE__, s)
1438# define syntax_error_unexpected_ch(ch) syntax_error_unexpected_ch(__LINE__, ch)
Denis Vlasenko90e485c2007-05-23 15:22:50 +00001439#endif
Eric Andersen25f27032001-04-26 23:22:31 +00001440
Denis Vlasenko552433b2009-04-04 19:29:21 +00001441
Denys Vlasenkof5018da2018-04-06 17:58:21 +02001442#if ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT
Mike Frysinger67c1c7b2009-04-24 06:26:18 +00001443static void cmdedit_update_prompt(void);
1444#else
Denys Vlasenko28a105d2009-06-01 11:26:30 +02001445# define cmdedit_update_prompt() ((void)0)
Mike Frysinger67c1c7b2009-04-24 06:26:18 +00001446#endif
1447
1448
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001449/* Utility functions
1450 */
Denis Vlasenko55789c62008-06-18 16:30:42 +00001451/* Replace each \x with x in place, return ptr past NUL. */
1452static char *unbackslash(char *src)
1453{
Denys Vlasenko71885402009-09-24 01:44:13 +02001454 char *dst = src = strchrnul(src, '\\');
Denis Vlasenko55789c62008-06-18 16:30:42 +00001455 while (1) {
Denys Vlasenko89e9d552018-04-11 01:15:33 +02001456 if (*src == '\\') {
Denis Vlasenko55789c62008-06-18 16:30:42 +00001457 src++;
Denys Vlasenko89e9d552018-04-11 01:15:33 +02001458 if (*src != '\0') {
1459 /* \x -> x */
1460 *dst++ = *src++;
1461 continue;
1462 }
1463 /* else: "\<nul>". Do not delete this backslash.
1464 * Testcase: eval 'echo ok\'
1465 */
1466 *dst++ = '\\';
1467 /* fallthrough */
1468 }
Denis Vlasenko55789c62008-06-18 16:30:42 +00001469 if ((*dst++ = *src++) == '\0')
1470 break;
1471 }
1472 return dst;
1473}
1474
Denis Vlasenko11fb7cf2009-03-20 10:13:08 +00001475static char **add_strings_to_strings(char **strings, char **add, int need_to_dup)
Denis Vlasenkod65ea392007-10-01 10:02:25 +00001476{
1477 int i;
1478 unsigned count1;
1479 unsigned count2;
1480 char **v;
1481
1482 v = strings;
1483 count1 = 0;
1484 if (v) {
1485 while (*v) {
1486 count1++;
1487 v++;
1488 }
1489 }
1490 count2 = 0;
1491 v = add;
1492 while (*v) {
1493 count2++;
1494 v++;
1495 }
1496 v = xrealloc(strings, (count1 + count2 + 1) * sizeof(char*));
1497 v[count1 + count2] = NULL;
1498 i = count2;
1499 while (--i >= 0)
Denis Vlasenko11fb7cf2009-03-20 10:13:08 +00001500 v[count1 + i] = (need_to_dup ? xstrdup(add[i]) : add[i]);
Denis Vlasenkod65ea392007-10-01 10:02:25 +00001501 return v;
1502}
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001503#if LEAK_HUNTING
Denis Vlasenkocc90f442009-04-08 16:40:34 +00001504static char **xx_add_strings_to_strings(int lineno, char **strings, char **add, int need_to_dup)
1505{
1506 char **ptr = add_strings_to_strings(strings, add, need_to_dup);
1507 fdprintf(2, "line %d: add_strings_to_strings %p\n", lineno, ptr);
1508 return ptr;
1509}
1510#define add_strings_to_strings(strings, add, need_to_dup) \
1511 xx_add_strings_to_strings(__LINE__, strings, add, need_to_dup)
1512#endif
Denis Vlasenkod65ea392007-10-01 10:02:25 +00001513
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02001514/* Note: takes ownership of "add" ptr (it is not strdup'ed) */
Denis Vlasenko22d10a02008-10-13 08:53:43 +00001515static char **add_string_to_strings(char **strings, char *add)
Denis Vlasenkod65ea392007-10-01 10:02:25 +00001516{
1517 char *v[2];
Denis Vlasenkod65ea392007-10-01 10:02:25 +00001518 v[0] = add;
1519 v[1] = NULL;
Denis Vlasenko11fb7cf2009-03-20 10:13:08 +00001520 return add_strings_to_strings(strings, v, /*dup:*/ 0);
Denis Vlasenko22d10a02008-10-13 08:53:43 +00001521}
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001522#if LEAK_HUNTING
Denis Vlasenkocc90f442009-04-08 16:40:34 +00001523static char **xx_add_string_to_strings(int lineno, char **strings, char *add)
1524{
1525 char **ptr = add_string_to_strings(strings, add);
1526 fdprintf(2, "line %d: add_string_to_strings %p\n", lineno, ptr);
1527 return ptr;
1528}
1529#define add_string_to_strings(strings, add) \
1530 xx_add_string_to_strings(__LINE__, strings, add)
1531#endif
Denis Vlasenkod65ea392007-10-01 10:02:25 +00001532
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02001533static void free_strings(char **strings)
Denis Vlasenkod65ea392007-10-01 10:02:25 +00001534{
Denis Vlasenkoafd7a8d2008-10-09 16:29:44 +00001535 char **v;
1536
1537 if (!strings)
1538 return;
Denis Vlasenkoafd7a8d2008-10-09 16:29:44 +00001539 v = strings;
1540 while (*v) {
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02001541 free(*v);
1542 v++;
Denis Vlasenkod65ea392007-10-01 10:02:25 +00001543 }
Denis Vlasenkoafd7a8d2008-10-09 16:29:44 +00001544 free(strings);
Denis Vlasenkod65ea392007-10-01 10:02:25 +00001545}
1546
Denys Vlasenko9acd63c2018-03-28 18:35:07 +02001547static int dup_CLOEXEC(int fd, int avoid_fd)
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001548{
Denys Vlasenko2db74612017-07-07 22:07:28 +02001549 int newfd;
1550 repeat:
Denys Vlasenko9acd63c2018-03-28 18:35:07 +02001551 newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
1552 if (newfd >= 0) {
1553 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
1554 fcntl(newfd, F_SETFD, FD_CLOEXEC);
1555 } else { /* newfd < 0 */
Denys Vlasenko2db74612017-07-07 22:07:28 +02001556 if (errno == EBUSY)
1557 goto repeat;
1558 if (errno == EINTR)
1559 goto repeat;
1560 }
1561 return newfd;
1562}
1563
Denys Vlasenko657e9002017-07-30 23:34:04 +02001564static int xdup_CLOEXEC_and_close(int fd, int avoid_fd)
Denys Vlasenko2db74612017-07-07 22:07:28 +02001565{
1566 int newfd;
1567 repeat:
Denys Vlasenko657e9002017-07-30 23:34:04 +02001568 newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
Denys Vlasenko2db74612017-07-07 22:07:28 +02001569 if (newfd < 0) {
1570 if (errno == EBUSY)
1571 goto repeat;
1572 if (errno == EINTR)
1573 goto repeat;
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001574 /* fd was not open? */
1575 if (errno == EBADF)
1576 return fd;
1577 xfunc_die();
1578 }
Denys Vlasenko657e9002017-07-30 23:34:04 +02001579 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
1580 fcntl(newfd, F_SETFD, FD_CLOEXEC);
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001581 close(fd);
1582 return newfd;
1583}
1584
1585
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001586/* Manipulating HFILEs */
1587static HFILE *hfopen(const char *name)
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02001588{
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001589 HFILE *fp;
1590 int fd;
1591
1592 fd = STDIN_FILENO;
1593 if (name) {
1594 fd = open(name, O_RDONLY | O_CLOEXEC);
1595 if (fd < 0)
1596 return NULL;
1597 if (O_CLOEXEC == 0) /* ancient libc */
1598 close_on_exec_on(fd);
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02001599 }
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001600
1601 fp = xmalloc(sizeof(*fp));
1602 fp->is_stdin = (name == NULL);
1603 fp->fd = fd;
1604 fp->cur = fp->end = fp->buf;
1605 fp->next_hfile = G.HFILE_list;
1606 G.HFILE_list = fp;
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02001607 return fp;
1608}
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001609static void hfclose(HFILE *fp)
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02001610{
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001611 HFILE **pp = &G.HFILE_list;
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02001612 while (*pp) {
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001613 HFILE *cur = *pp;
1614 if (cur == fp) {
1615 *pp = cur->next_hfile;
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02001616 break;
1617 }
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001618 pp = &cur->next_hfile;
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02001619 }
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001620 if (fp->fd >= 0)
1621 close(fp->fd);
1622 free(fp);
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02001623}
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001624static int refill_HFILE_and_getc(HFILE *fp)
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001625{
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001626 int n;
1627
1628 if (fp->fd < 0) {
1629 /* Already saw EOF */
1630 return EOF;
1631 }
1632 /* Try to buffer more input */
1633 fp->cur = fp->buf;
1634 n = safe_read(fp->fd, fp->buf, sizeof(fp->buf));
1635 if (n < 0) {
1636 bb_perror_msg("read error");
1637 n = 0;
1638 }
1639 fp->end = fp->buf + n;
1640 if (n == 0) {
1641 /* EOF/error */
1642 close(fp->fd);
1643 fp->fd = -1;
1644 return EOF;
1645 }
1646 return (unsigned char)(*fp->cur++);
1647}
1648/* Inlined for common case of non-empty buffer.
1649 */
1650static ALWAYS_INLINE int hfgetc(HFILE *fp)
1651{
1652 if (fp->cur < fp->end)
1653 return (unsigned char)(*fp->cur++);
1654 /* Buffer empty */
1655 return refill_HFILE_and_getc(fp);
1656}
1657static int move_HFILEs_on_redirect(int fd, int avoid_fd)
1658{
1659 HFILE *fl = G.HFILE_list;
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001660 while (fl) {
1661 if (fd == fl->fd) {
1662 /* We use it only on script files, they are all CLOEXEC */
Denys Vlasenko657e9002017-07-30 23:34:04 +02001663 fl->fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
Denys Vlasenko2db74612017-07-07 22:07:28 +02001664 debug_printf_redir("redirect_fd %d: matches a script fd, moving it to %d\n", fd, fl->fd);
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001665 return 1; /* "found and moved" */
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001666 }
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001667 fl = fl->next_hfile;
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001668 }
Denys Vlasenkoaa449c92018-07-28 12:13:58 +02001669#if ENABLE_HUSH_MODE_X
1670 if (G.x_mode_fd > 0 && fd == G.x_mode_fd) {
1671 G.x_mode_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
1672 return 1; /* "found and moved" */
1673 }
1674#endif
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001675 return 0; /* "not in the list" */
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001676}
Denys Vlasenko4ee824f2017-07-03 01:22:13 +02001677#if ENABLE_FEATURE_SH_STANDALONE && BB_MMU
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001678static void close_all_HFILE_list(void)
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001679{
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001680 HFILE *fl = G.HFILE_list;
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001681 while (fl) {
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001682 /* hfclose would also free HFILE object.
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001683 * It is disastrous if we share memory with a vforked parent.
1684 * I'm not sure we never come here after vfork.
1685 * Therefore just close fd, nothing more.
1686 */
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001687 /*hfclose(fl); - unsafe */
1688 if (fl->fd >= 0)
1689 close(fl->fd);
1690 fl = fl->next_hfile;
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001691 }
1692}
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02001693#endif
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001694static int fd_in_HFILEs(int fd)
Denys Vlasenko32fdf2f2017-07-31 04:32:06 +02001695{
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001696 HFILE *fl = G.HFILE_list;
Denys Vlasenko32fdf2f2017-07-31 04:32:06 +02001697 while (fl) {
1698 if (fl->fd == fd)
1699 return 1;
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02001700 fl = fl->next_hfile;
Denys Vlasenko32fdf2f2017-07-31 04:32:06 +02001701 }
1702 return 0;
1703}
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02001704
1705
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001706/* Helpers for setting new $n and restoring them back
1707 */
1708typedef struct save_arg_t {
1709 char *sv_argv0;
1710 char **sv_g_argv;
1711 int sv_g_argc;
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +01001712 IF_HUSH_SET(smallint sv_g_malloced;)
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001713} save_arg_t;
1714
1715static void save_and_replace_G_args(save_arg_t *sv, char **argv)
1716{
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001717 sv->sv_argv0 = argv[0];
1718 sv->sv_g_argv = G.global_argv;
1719 sv->sv_g_argc = G.global_argc;
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +01001720 IF_HUSH_SET(sv->sv_g_malloced = G.global_args_malloced;)
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001721
1722 argv[0] = G.global_argv[0]; /* retain $0 */
1723 G.global_argv = argv;
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +01001724 IF_HUSH_SET(G.global_args_malloced = 0;)
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001725
Denys Vlasenkod4e4fdb2017-07-03 21:31:16 +02001726 G.global_argc = 1 + string_array_len(argv + 1);
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001727}
1728
1729static void restore_G_args(save_arg_t *sv, char **argv)
1730{
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +01001731#if ENABLE_HUSH_SET
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001732 if (G.global_args_malloced) {
1733 /* someone ran "set -- arg1 arg2 ...", undo */
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +01001734 char **pp = G.global_argv;
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001735 while (*++pp) /* note: does not free $0 */
1736 free(*pp);
1737 free(G.global_argv);
1738 }
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +01001739#endif
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001740 argv[0] = sv->sv_argv0;
1741 G.global_argv = sv->sv_g_argv;
1742 G.global_argc = sv->sv_g_argc;
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +01001743 IF_HUSH_SET(G.global_args_malloced = sv->sv_g_malloced;)
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001744}
1745
1746
Denis Vlasenkod5762932009-03-31 11:22:57 +00001747/* Basic theory of signal handling in shell
1748 * ========================================
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001749 * This does not describe what hush does, rather, it is current understanding
1750 * what it _should_ do. If it doesn't, it's a bug.
Denis Vlasenkod5762932009-03-31 11:22:57 +00001751 * http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#trap
1752 *
1753 * Signals are handled only after each pipe ("cmd | cmd | cmd" thing)
1754 * is finished or backgrounded. It is the same in interactive and
1755 * non-interactive shells, and is the same regardless of whether
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001756 * a user trap handler is installed or a shell special one is in effect.
Denys Vlasenko69b1cef2009-09-21 10:21:44 +02001757 * ^C or ^Z from keyboard seems to execute "at once" because it usually
Denis Vlasenkod5762932009-03-31 11:22:57 +00001758 * backgrounds (i.e. stops) or kills all members of currently running
1759 * pipe.
1760 *
Denys Vlasenko8bd810b2013-11-28 01:50:01 +01001761 * Wait builtin is interruptible by signals for which user trap is set
Denis Vlasenkod5762932009-03-31 11:22:57 +00001762 * or by SIGINT in interactive shell.
1763 *
1764 * Trap handlers will execute even within trap handlers. (right?)
1765 *
Denys Vlasenkoe89a2412010-01-12 15:19:31 +01001766 * User trap handlers are forgotten when subshell ("(cmd)") is entered,
1767 * except for handlers set to '' (empty string).
Denis Vlasenkod5762932009-03-31 11:22:57 +00001768 *
1769 * If job control is off, backgrounded commands ("cmd &")
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001770 * have SIGINT, SIGQUIT set to SIG_IGN.
Denis Vlasenkod5762932009-03-31 11:22:57 +00001771 *
Denys Vlasenko28a105d2009-06-01 11:26:30 +02001772 * Commands which are run in command substitution ("`cmd`")
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001773 * have SIGTTIN, SIGTTOU, SIGTSTP set to SIG_IGN.
Denis Vlasenkod5762932009-03-31 11:22:57 +00001774 *
Denys Vlasenko4b7db4f2009-05-29 10:39:06 +02001775 * Ordinary commands have signals set to SIG_IGN/DFL as inherited
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001776 * by the shell from its parent.
Denis Vlasenkod5762932009-03-31 11:22:57 +00001777 *
Denys Vlasenko28a105d2009-06-01 11:26:30 +02001778 * Signals which differ from SIG_DFL action
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001779 * (note: child (i.e., [v]forked) shell is not an interactive shell):
Denis Vlasenkod5762932009-03-31 11:22:57 +00001780 *
1781 * SIGQUIT: ignore
1782 * SIGTERM (interactive): ignore
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001783 * SIGHUP (interactive):
1784 * send SIGCONT to stopped jobs, send SIGHUP to all jobs and exit
Denis Vlasenkod5762932009-03-31 11:22:57 +00001785 * SIGTTIN, SIGTTOU, SIGTSTP (if job control is on): ignore
Denis Vlasenkoc4ada792009-04-15 23:29:00 +00001786 * Note that ^Z is handled not by trapping SIGTSTP, but by seeing
1787 * that all pipe members are stopped. Try this in bash:
1788 * while :; do :; done - ^Z does not background it
1789 * (while :; do :; done) - ^Z backgrounds it
Denis Vlasenkod5762932009-03-31 11:22:57 +00001790 * SIGINT (interactive): wait for last pipe, ignore the rest
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001791 * of the command line, show prompt. NB: ^C does not send SIGINT
1792 * to interactive shell while shell is waiting for a pipe,
1793 * since shell is bg'ed (is not in foreground process group).
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001794 * Example 1: this waits 5 sec, but does not execute ls:
1795 * "echo $$; sleep 5; ls -l" + "kill -INT <pid>"
1796 * Example 2: this does not wait and does not execute ls:
1797 * "echo $$; sleep 5 & wait; ls -l" + "kill -INT <pid>"
1798 * Example 3: this does not wait 5 sec, but executes ls:
1799 * "sleep 5; ls -l" + press ^C
Denys Vlasenkob8709032011-05-08 21:20:01 +02001800 * Example 4: this does not wait and does not execute ls:
1801 * "sleep 5 & wait; ls -l" + press ^C
Denis Vlasenkod5762932009-03-31 11:22:57 +00001802 *
1803 * (What happens to signals which are IGN on shell start?)
1804 * (What happens with signal mask on shell start?)
1805 *
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001806 * Old implementation
1807 * ==================
Denis Vlasenkod5762932009-03-31 11:22:57 +00001808 * We use in-kernel pending signal mask to determine which signals were sent.
1809 * We block all signals which we don't want to take action immediately,
1810 * i.e. we block all signals which need to have special handling as described
1811 * above, and all signals which have traps set.
1812 * After each pipe execution, we extract any pending signals via sigtimedwait()
1813 * and act on them.
1814 *
Denys Vlasenko10c01312011-05-11 11:49:21 +02001815 * unsigned special_sig_mask: a mask of such "special" signals
Denis Vlasenkod5762932009-03-31 11:22:57 +00001816 * sigset_t blocked_set: current blocked signal set
1817 *
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001818 * "trap - SIGxxx":
Denys Vlasenko10c01312011-05-11 11:49:21 +02001819 * clear bit in blocked_set unless it is also in special_sig_mask
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001820 * "trap 'cmd' SIGxxx":
1821 * set bit in blocked_set (even if 'cmd' is '')
Denis Vlasenkod5762932009-03-31 11:22:57 +00001822 * after [v]fork, if we plan to be a shell:
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00001823 * unblock signals with special interactive handling
1824 * (child shell is not interactive),
Denys Vlasenkoe89a2412010-01-12 15:19:31 +01001825 * unset all traps except '' (note: regardless of child shell's type - {}, (), etc)
Denis Vlasenkod5762932009-03-31 11:22:57 +00001826 * after [v]fork, if we plan to exec:
Denys Vlasenko69b1cef2009-09-21 10:21:44 +02001827 * POSIX says fork clears pending signal mask in child - no need to clear it.
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001828 * Restore blocked signal set to one inherited by shell just prior to exec.
Denis Vlasenkod5762932009-03-31 11:22:57 +00001829 *
Denis Vlasenko7566bae2009-03-31 17:24:49 +00001830 * Note: as a result, we do not use signal handlers much. The only uses
Denys Vlasenko8d7be232009-05-25 16:38:32 +02001831 * are to count SIGCHLDs
Denis Vlasenko7566bae2009-03-31 17:24:49 +00001832 * and to restore tty pgrp on signal-induced exit.
Denys Vlasenko4ea0ca82009-09-25 12:58:37 +02001833 *
Denys Vlasenko67f71862009-09-25 14:21:06 +02001834 * Note 2 (compat):
Denys Vlasenko4ea0ca82009-09-25 12:58:37 +02001835 * Standard says "When a subshell is entered, traps that are not being ignored
1836 * are set to the default actions". bash interprets it so that traps which
Denys Vlasenkoe89a2412010-01-12 15:19:31 +01001837 * are set to '' (ignore) are NOT reset to defaults. We do the same.
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001838 *
1839 * Problem: the above approach makes it unwieldy to catch signals while
Denys Vlasenkoe95738f2013-07-08 03:13:08 +02001840 * we are in read builtin, or while we read commands from stdin:
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001841 * masked signals are not visible!
1842 *
1843 * New implementation
1844 * ==================
1845 * We record each signal we are interested in by installing signal handler
1846 * for them - a bit like emulating kernel pending signal mask in userspace.
1847 * We are interested in: signals which need to have special handling
1848 * as described above, and all signals which have traps set.
Denys Vlasenko8bd810b2013-11-28 01:50:01 +01001849 * Signals are recorded in pending_set.
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001850 * After each pipe execution, we extract any pending signals
1851 * and act on them.
1852 *
1853 * unsigned special_sig_mask: a mask of shell-special signals.
1854 * unsigned fatal_sig_mask: a mask of signals on which we restore tty pgrp.
1855 * char *traps[sig] if trap for sig is set (even if it's '').
1856 * sigset_t pending_set: set of sigs we received.
1857 *
1858 * "trap - SIGxxx":
1859 * if sig is in special_sig_mask, set handler back to:
1860 * record_pending_signo, or to IGN if it's a tty stop signal
1861 * if sig is in fatal_sig_mask, set handler back to sigexit.
1862 * else: set handler back to SIG_DFL
1863 * "trap 'cmd' SIGxxx":
1864 * set handler to record_pending_signo.
1865 * "trap '' SIGxxx":
1866 * set handler to SIG_IGN.
1867 * after [v]fork, if we plan to be a shell:
1868 * set signals with special interactive handling to SIG_DFL
1869 * (because child shell is not interactive),
1870 * unset all traps except '' (note: regardless of child shell's type - {}, (), etc)
1871 * after [v]fork, if we plan to exec:
1872 * POSIX says fork clears pending signal mask in child - no need to clear it.
1873 *
1874 * To make wait builtin interruptible, we handle SIGCHLD as special signal,
1875 * otherwise (if we leave it SIG_DFL) sigsuspend in wait builtin will not wake up on it.
1876 *
1877 * Note (compat):
1878 * Standard says "When a subshell is entered, traps that are not being ignored
1879 * are set to the default actions". bash interprets it so that traps which
1880 * are set to '' (ignore) are NOT reset to defaults. We do the same.
Denis Vlasenkod5762932009-03-31 11:22:57 +00001881 */
Denis Vlasenkoe4bd4f22009-04-17 13:52:51 +00001882enum {
1883 SPECIAL_INTERACTIVE_SIGS = 0
Denis Vlasenkoe4bd4f22009-04-17 13:52:51 +00001884 | (1 << SIGTERM)
Denis Vlasenkoe4bd4f22009-04-17 13:52:51 +00001885 | (1 << SIGINT)
Denis Vlasenkoc8653f62009-04-27 23:29:14 +00001886 | (1 << SIGHUP)
1887 ,
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001888 SPECIAL_JOBSTOP_SIGS = 0
Mike Frysinger38478a62009-05-20 04:48:06 -04001889#if ENABLE_HUSH_JOB
Denis Vlasenkoc8653f62009-04-27 23:29:14 +00001890 | (1 << SIGTTIN)
1891 | (1 << SIGTTOU)
1892 | (1 << SIGTSTP)
1893#endif
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001894 ,
Denis Vlasenkoe4bd4f22009-04-17 13:52:51 +00001895};
Denis Vlasenkod5762932009-03-31 11:22:57 +00001896
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001897static void record_pending_signo(int sig)
Denys Vlasenko54e9e122011-05-09 00:52:15 +02001898{
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001899 sigaddset(&G.pending_set, sig);
Denys Vlasenko8d7be232009-05-25 16:38:32 +02001900#if ENABLE_HUSH_FAST
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001901 if (sig == SIGCHLD) {
1902 G.count_SIGCHLD++;
Denys Vlasenko8d7be232009-05-25 16:38:32 +02001903//bb_error_msg("[%d] SIGCHLD_handler: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001904 }
Denys Vlasenko8d7be232009-05-25 16:38:32 +02001905#endif
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001906}
Denis Vlasenko7566bae2009-03-31 17:24:49 +00001907
Denys Vlasenko0806e402011-05-12 23:06:20 +02001908static sighandler_t install_sighandler(int sig, sighandler_t handler)
1909{
1910 struct sigaction old_sa;
1911
1912 /* We could use signal() to install handlers... almost:
1913 * except that we need to mask ALL signals while handlers run.
1914 * I saw signal nesting in strace, race window isn't small.
1915 * SA_RESTART is also needed, but in Linux, signal()
1916 * sets SA_RESTART too.
1917 */
1918 /* memset(&G.sa, 0, sizeof(G.sa)); - already done */
1919 /* sigfillset(&G.sa.sa_mask); - already done */
1920 /* G.sa.sa_flags = SA_RESTART; - already done */
1921 G.sa.sa_handler = handler;
1922 sigaction(sig, &G.sa, &old_sa);
1923 return old_sa.sa_handler;
1924}
1925
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02001926static void hush_exit(int exitcode) NORETURN;
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02001927
Denys Vlasenkob6afcc72016-12-12 16:30:20 +01001928static void restore_ttypgrp_and__exit(void) NORETURN;
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02001929static void restore_ttypgrp_and__exit(void)
1930{
1931 /* xfunc has failed! die die die */
1932 /* no EXIT traps, this is an escape hatch! */
1933 G.exiting = 1;
1934 hush_exit(xfunc_error_retval);
1935}
1936
Denys Vlasenkob6afcc72016-12-12 16:30:20 +01001937#if ENABLE_HUSH_JOB
1938
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02001939/* Needed only on some libc:
1940 * It was observed that on exit(), fgetc'ed buffered data
1941 * gets "unwound" via lseek(fd, -NUM, SEEK_CUR).
1942 * With the net effect that even after fork(), not vfork(),
1943 * exit() in NOEXECed applet in "sh SCRIPT":
1944 * noexec_applet_here
1945 * echo END_OF_SCRIPT
1946 * lseeks fd in input FILE object from EOF to "e" in "echo END_OF_SCRIPT".
1947 * This makes "echo END_OF_SCRIPT" executed twice.
Denys Vlasenko39701202017-08-02 19:44:05 +02001948 * Similar problems can be seen with msg_and_die_if_script() -> xfunc_die()
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02001949 * and in `cmd` handling.
1950 * If set as die_func(), this makes xfunc_die() exit via _exit(), not exit():
1951 */
Denys Vlasenkob6afcc72016-12-12 16:30:20 +01001952static void fflush_and__exit(void) NORETURN;
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02001953static void fflush_and__exit(void)
1954{
1955 fflush_all();
1956 _exit(xfunc_error_retval);
1957}
1958
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00001959/* After [v]fork, in child: do not restore tty pgrp on xfunc death */
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02001960# define disable_restore_tty_pgrp_on_exit() (die_func = fflush_and__exit)
Denis Vlasenko25af86f2009-04-07 13:29:27 +00001961/* After [v]fork, in parent: restore tty pgrp on xfunc death */
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02001962# define enable_restore_tty_pgrp_on_exit() (die_func = restore_ttypgrp_and__exit)
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00001963
Denis Vlasenko54e7ffb2007-04-21 00:03:36 +00001964/* Restores tty foreground process group, and exits.
1965 * May be called as signal handler for fatal signal
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00001966 * (will resend signal to itself, producing correct exit state)
Denis Vlasenko54e7ffb2007-04-21 00:03:36 +00001967 * or called directly with -EXITCODE.
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02001968 * We also call it if xfunc is exiting.
1969 */
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00001970static void sigexit(int sig) NORETURN;
Denis Vlasenko54e7ffb2007-04-21 00:03:36 +00001971static void sigexit(int sig)
1972{
Denis Vlasenkoabedaac2009-03-31 12:03:40 +00001973 /* Careful: we can end up here after [v]fork. Do not restore
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001974 * tty pgrp then, only top-level shell process does that */
Denys Vlasenkoebc1ee22011-05-12 10:59:18 +02001975 if (G_saved_tty_pgrp && getpid() == G.root_pid) {
1976 /* Disable all signals: job control, SIGPIPE, etc.
1977 * Mostly paranoid measure, to prevent infinite SIGTTOU.
1978 */
1979 sigprocmask_allsigs(SIG_BLOCK);
Mike Frysinger38478a62009-05-20 04:48:06 -04001980 tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp);
Denys Vlasenkoebc1ee22011-05-12 10:59:18 +02001981 }
Denis Vlasenko54e7ffb2007-04-21 00:03:36 +00001982
1983 /* Not a signal, just exit */
1984 if (sig <= 0)
1985 _exit(- sig);
1986
Denis Vlasenko400d8bb2008-02-24 13:36:01 +00001987 kill_myself_with_sig(sig); /* does not return */
Denis Vlasenko54e7ffb2007-04-21 00:03:36 +00001988}
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00001989#else
1990
Denys Vlasenko8391c482010-05-22 17:50:43 +02001991# define disable_restore_tty_pgrp_on_exit() ((void)0)
1992# define enable_restore_tty_pgrp_on_exit() ((void)0)
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00001993
Denis Vlasenkoe0755e52009-04-03 21:16:45 +00001994#endif
Denis Vlasenkob81b3df2007-04-28 16:48:04 +00001995
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001996static sighandler_t pick_sighandler(unsigned sig)
1997{
1998 sighandler_t handler = SIG_DFL;
1999 if (sig < sizeof(unsigned)*8) {
2000 unsigned sigmask = (1 << sig);
2001
2002#if ENABLE_HUSH_JOB
Denys Vlasenko75e77de2011-05-12 13:12:47 +02002003 /* is sig fatal? */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002004 if (G_fatal_sig_mask & sigmask)
2005 handler = sigexit;
Denys Vlasenko75e77de2011-05-12 13:12:47 +02002006 else
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002007#endif
2008 /* sig has special handling? */
Denys Vlasenko75e77de2011-05-12 13:12:47 +02002009 if (G.special_sig_mask & sigmask) {
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002010 handler = record_pending_signo;
Denys Vlasenko0c40a732011-05-12 09:50:12 +02002011 /* TTIN/TTOU/TSTP can't be set to record_pending_signo
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002012 * in order to ignore them: they will be raised
Denys Vlasenkof58f7052011-05-12 02:10:33 +02002013 * in an endless loop when we try to do some
2014 * terminal ioctls! We do have to _ignore_ these.
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002015 */
2016 if (SPECIAL_JOBSTOP_SIGS & sigmask)
2017 handler = SIG_IGN;
Denys Vlasenko0c40a732011-05-12 09:50:12 +02002018 }
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002019 }
2020 return handler;
2021}
2022
Mike Frysinger9f8128f2009-03-29 23:49:37 +00002023/* Restores tty foreground process group, and exits. */
Mike Frysinger9f8128f2009-03-29 23:49:37 +00002024static void hush_exit(int exitcode)
2025{
Denys Vlasenkobede2152011-09-04 16:12:33 +02002026#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
2027 save_history(G.line_input_state);
2028#endif
2029
Denys Vlasenko8ee2ada2011-02-07 02:03:51 +01002030 fflush_all();
Denys Vlasenko7a85c602017-01-08 17:40:18 +01002031 if (G.exiting <= 0 && G_traps && G_traps[0] && G_traps[0][0]) {
Denys Vlasenko27c56f12010-09-07 09:56:34 +02002032 char *argv[3];
2033 /* argv[0] is unused */
Denys Vlasenko46f839c2018-01-19 16:58:44 +01002034 argv[1] = xstrdup(G_traps[0]); /* copy, since EXIT trap handler may modify G_traps[0] */
Denys Vlasenko27c56f12010-09-07 09:56:34 +02002035 argv[2] = NULL;
Denys Vlasenkoa110c902010-09-12 15:38:04 +02002036 G.exiting = 1; /* prevent EXIT trap recursion */
Denys Vlasenko7a85c602017-01-08 17:40:18 +01002037 /* Note: G_traps[0] is not cleared!
Denys Vlasenkode8c3f62010-09-12 16:13:44 +02002038 * "trap" will still show it, if executed
2039 * in the handler */
2040 builtin_eval(argv);
Denis Vlasenkod5762932009-03-31 11:22:57 +00002041 }
Mike Frysinger9f8128f2009-03-29 23:49:37 +00002042
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01002043#if ENABLE_FEATURE_CLEAN_UP
2044 {
2045 struct variable *cur_var;
2046 if (G.cwd != bb_msg_unknown)
2047 free((char*)G.cwd);
2048 cur_var = G.top_var;
2049 while (cur_var) {
2050 struct variable *tmp = cur_var;
2051 if (!cur_var->max_len)
2052 free(cur_var->varstr);
2053 cur_var = cur_var->next;
2054 free(tmp);
2055 }
2056 }
2057#endif
2058
Denys Vlasenko8131eea2009-11-02 14:19:51 +01002059 fflush_all();
Denys Vlasenko215b0ca2016-08-19 18:23:56 +02002060#if ENABLE_HUSH_JOB
Denis Vlasenkoabedaac2009-03-31 12:03:40 +00002061 sigexit(- (exitcode & 0xff));
2062#else
Denys Vlasenko215b0ca2016-08-19 18:23:56 +02002063 _exit(exitcode);
Denis Vlasenkoabedaac2009-03-31 12:03:40 +00002064#endif
Mike Frysinger9f8128f2009-03-29 23:49:37 +00002065}
2066
Denys Vlasenkoacd5bc82010-09-12 15:05:39 +02002067
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002068//TODO: return a mask of ALL handled sigs?
2069static int check_and_run_traps(void)
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002070{
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002071 int last_sig = 0;
2072
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002073 while (1) {
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002074 int sig;
Denys Vlasenko80542ba2011-05-08 21:23:43 +02002075
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002076 if (sigisemptyset(&G.pending_set))
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002077 break;
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002078 sig = 0;
2079 do {
2080 sig++;
2081 if (sigismember(&G.pending_set, sig)) {
2082 sigdelset(&G.pending_set, sig);
2083 goto got_sig;
2084 }
2085 } while (sig < NSIG);
2086 break;
Denys Vlasenkob8709032011-05-08 21:20:01 +02002087 got_sig:
Denys Vlasenko7a85c602017-01-08 17:40:18 +01002088 if (G_traps && G_traps[sig]) {
Denys Vlasenko04b46bc2016-10-01 22:28:03 +02002089 debug_printf_exec("%s: sig:%d handler:'%s'\n", __func__, sig, G.traps[sig]);
Denys Vlasenko7a85c602017-01-08 17:40:18 +01002090 if (G_traps[sig][0]) {
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002091 /* We have user-defined handler */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002092 smalluint save_rcode;
Denys Vlasenko27c56f12010-09-07 09:56:34 +02002093 char *argv[3];
2094 /* argv[0] is unused */
Denys Vlasenko749575d2018-01-30 04:29:03 +01002095 argv[1] = xstrdup(G_traps[sig]);
2096 /* why strdup? trap can modify itself: trap 'trap "echo oops" INT' INT */
Denys Vlasenko27c56f12010-09-07 09:56:34 +02002097 argv[2] = NULL;
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002098 save_rcode = G.last_exitcode;
2099 builtin_eval(argv);
Denys Vlasenko749575d2018-01-30 04:29:03 +01002100 free(argv[1]);
Denys Vlasenko8660aeb2016-11-24 17:44:02 +01002101//FIXME: shouldn't it be set to 128 + sig instead?
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002102 G.last_exitcode = save_rcode;
Denys Vlasenkob8709032011-05-08 21:20:01 +02002103 last_sig = sig;
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002104 } /* else: "" trap, ignoring signal */
2105 continue;
2106 }
2107 /* not a trap: special action */
2108 switch (sig) {
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002109 case SIGINT:
Denys Vlasenko04b46bc2016-10-01 22:28:03 +02002110 debug_printf_exec("%s: sig:%d default SIGINT handler\n", __func__, sig);
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002111 G.flag_SIGINT = 1;
Denys Vlasenkob8709032011-05-08 21:20:01 +02002112 last_sig = sig;
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002113 break;
2114#if ENABLE_HUSH_JOB
2115 case SIGHUP: {
Denys Vlasenko49e6bf22017-08-04 14:28:16 +02002116//TODO: why are we doing this? ash and dash don't do this,
2117//they have no handler for SIGHUP at all,
2118//they rely on kernel to send SIGHUP+SIGCONT to orphaned process groups
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002119 struct pipe *job;
Denys Vlasenko04b46bc2016-10-01 22:28:03 +02002120 debug_printf_exec("%s: sig:%d default SIGHUP handler\n", __func__, sig);
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002121 /* bash is observed to signal whole process groups,
2122 * not individual processes */
2123 for (job = G.job_list; job; job = job->next) {
2124 if (job->pgrp <= 0)
2125 continue;
2126 debug_printf_exec("HUPing pgrp %d\n", job->pgrp);
2127 if (kill(- job->pgrp, SIGHUP) == 0)
2128 kill(- job->pgrp, SIGCONT);
2129 }
2130 sigexit(SIGHUP);
2131 }
2132#endif
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002133#if ENABLE_HUSH_FAST
2134 case SIGCHLD:
Denys Vlasenko04b46bc2016-10-01 22:28:03 +02002135 debug_printf_exec("%s: sig:%d default SIGCHLD handler\n", __func__, sig);
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002136 G.count_SIGCHLD++;
2137//bb_error_msg("[%d] check_and_run_traps: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
2138 /* Note:
Denys Vlasenko10ad6222017-04-17 16:13:32 +02002139 * We don't do 'last_sig = sig' here -> NOT returning this sig.
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002140 * This simplifies wait builtin a bit.
2141 */
2142 break;
2143#endif
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002144 default: /* ignored: */
Denys Vlasenko04b46bc2016-10-01 22:28:03 +02002145 debug_printf_exec("%s: sig:%d default handling is to ignore\n", __func__, sig);
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002146 /* SIGTERM, SIGQUIT, SIGTTIN, SIGTTOU, SIGTSTP */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002147 /* Note:
Denys Vlasenko10ad6222017-04-17 16:13:32 +02002148 * We don't do 'last_sig = sig' here -> NOT returning this sig.
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002149 * Example: wait is not interrupted by TERM
Denys Vlasenkob8709032011-05-08 21:20:01 +02002150 * in interactive shell, because TERM is ignored.
2151 */
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002152 break;
2153 }
2154 }
2155 return last_sig;
2156}
2157
Denis Vlasenkob81b3df2007-04-28 16:48:04 +00002158
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02002159static const char *get_cwd(int force)
Eric Andersen9ffb7dd2001-05-19 03:00:46 +00002160{
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02002161 if (force || G.cwd == NULL) {
2162 /* xrealloc_getcwd_or_warn(arg) calls free(arg),
2163 * we must not try to free(bb_msg_unknown) */
2164 if (G.cwd == bb_msg_unknown)
2165 G.cwd = NULL;
2166 G.cwd = xrealloc_getcwd_or_warn((char *)G.cwd);
2167 if (!G.cwd)
2168 G.cwd = bb_msg_unknown;
2169 }
Denis Vlasenko87a86552008-07-29 19:43:10 +00002170 return G.cwd;
Eric Andersen9ffb7dd2001-05-19 03:00:46 +00002171}
2172
Denis Vlasenko83506862007-11-23 13:11:42 +00002173
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002174/*
2175 * Shell and environment variable support
2176 */
Denys Vlasenko27c56f12010-09-07 09:56:34 +02002177static struct variable **get_ptr_to_local_var(const char *name, unsigned len)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002178{
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002179 struct variable **pp;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002180 struct variable *cur;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002181
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002182 pp = &G.top_var;
2183 while ((cur = *pp) != NULL) {
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002184 if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=')
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002185 return pp;
2186 pp = &cur->next;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002187 }
2188 return NULL;
2189}
2190
Denys Vlasenko03dad222010-01-12 23:29:57 +01002191static const char* FAST_FUNC get_local_var_value(const char *name)
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002192{
Denys Vlasenko29082232010-07-16 13:52:32 +02002193 struct variable **vpp;
Denys Vlasenko27c56f12010-09-07 09:56:34 +02002194 unsigned len = strlen(name);
Denys Vlasenko29082232010-07-16 13:52:32 +02002195
2196 if (G.expanded_assignments) {
2197 char **cpp = G.expanded_assignments;
Denys Vlasenko29082232010-07-16 13:52:32 +02002198 while (*cpp) {
2199 char *cp = *cpp;
2200 if (strncmp(cp, name, len) == 0 && cp[len] == '=')
2201 return cp + len + 1;
2202 cpp++;
2203 }
2204 }
2205
Denys Vlasenko27c56f12010-09-07 09:56:34 +02002206 vpp = get_ptr_to_local_var(name, len);
Denys Vlasenko29082232010-07-16 13:52:32 +02002207 if (vpp)
Denys Vlasenko27c56f12010-09-07 09:56:34 +02002208 return (*vpp)->varstr + len + 1;
Denys Vlasenko29082232010-07-16 13:52:32 +02002209
Denys Vlasenkodea47882009-10-09 15:40:49 +02002210 if (strcmp(name, "PPID") == 0)
2211 return utoa(G.root_ppid);
2212 // bash compat: UID? EUID?
Denys Vlasenko20b3d142009-10-09 20:59:39 +02002213#if ENABLE_HUSH_RANDOM_SUPPORT
Denys Vlasenko27c56f12010-09-07 09:56:34 +02002214 if (strcmp(name, "RANDOM") == 0)
Denys Vlasenko20b3d142009-10-09 20:59:39 +02002215 return utoa(next_random(&G.random_gen));
2216#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002217 return NULL;
2218}
2219
Denys Vlasenkocf079ff2018-04-06 14:50:12 +02002220static void handle_changed_special_names(const char *name, unsigned name_len)
2221{
Denys Vlasenkof5018da2018-04-06 17:58:21 +02002222 if (ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2223 && name_len == 3 && name[0] == 'P' && name[1] == 'S'
2224 ) {
Denys Vlasenkocf079ff2018-04-06 14:50:12 +02002225 cmdedit_update_prompt();
2226 return;
2227 }
2228
2229 if ((ENABLE_HUSH_LINENO_VAR || ENABLE_HUSH_GETOPTS)
2230 && name_len == 6
2231 ) {
2232#if ENABLE_HUSH_LINENO_VAR
Denys Vlasenko00bd7672018-04-06 14:57:53 +02002233 if (strncmp(name, "LINENO", 6) == 0) {
Denys Vlasenkocf079ff2018-04-06 14:50:12 +02002234 G.lineno_var = NULL;
Denys Vlasenko00bd7672018-04-06 14:57:53 +02002235 return;
2236 }
Denys Vlasenkocf079ff2018-04-06 14:50:12 +02002237#endif
2238#if ENABLE_HUSH_GETOPTS
Denys Vlasenko00bd7672018-04-06 14:57:53 +02002239 if (strncmp(name, "OPTIND", 6) == 0) {
Denys Vlasenkocf079ff2018-04-06 14:50:12 +02002240 G.getopt_count = 0;
Denys Vlasenko00bd7672018-04-06 14:57:53 +02002241 return;
2242 }
Denys Vlasenkocf079ff2018-04-06 14:50:12 +02002243#endif
2244 }
2245}
2246
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002247/* str holds "NAME=VAL" and is expected to be malloced.
Mike Frysinger6379bb42009-03-28 18:55:03 +00002248 * We take ownership of it.
Mike Frysinger6379bb42009-03-28 18:55:03 +00002249 */
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002250#define SETFLAG_EXPORT (1 << 0)
2251#define SETFLAG_UNEXPORT (1 << 1)
2252#define SETFLAG_MAKE_RO (1 << 2)
Denys Vlasenko332e4112018-04-04 22:32:59 +02002253#define SETFLAG_VARLVL_SHIFT 3
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002254static int set_local_var(char *str, unsigned flags)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002255{
Denys Vlasenko61407802018-04-04 21:14:28 +02002256 struct variable **cur_pp;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002257 struct variable *cur;
Denys Vlasenkoa7693902016-10-03 15:01:06 +02002258 char *free_me = NULL;
Denis Vlasenko950bd722009-04-21 11:23:56 +00002259 char *eq_sign;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002260 int name_len;
Denys Vlasenko332e4112018-04-04 22:32:59 +02002261 unsigned local_lvl = (flags >> SETFLAG_VARLVL_SHIFT);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002262
Denis Vlasenko950bd722009-04-21 11:23:56 +00002263 eq_sign = strchr(str, '=');
Denys Vlasenko929a41d2018-04-05 14:09:14 +02002264 if (HUSH_DEBUG && !eq_sign)
2265 bb_error_msg_and_die("BUG in setvar");
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002266
Denis Vlasenko950bd722009-04-21 11:23:56 +00002267 name_len = eq_sign - str + 1; /* including '=' */
Denys Vlasenko61407802018-04-04 21:14:28 +02002268 cur_pp = &G.top_var;
2269 while ((cur = *cur_pp) != NULL) {
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002270 if (strncmp(cur->varstr, str, name_len) != 0) {
Denys Vlasenko61407802018-04-04 21:14:28 +02002271 cur_pp = &cur->next;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002272 continue;
2273 }
Denys Vlasenkoa7693902016-10-03 15:01:06 +02002274
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002275 /* We found an existing var with this name */
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002276 if (cur->flg_read_only) {
Denys Vlasenko6b48e1f2017-07-17 21:31:17 +02002277 bb_error_msg("%s: readonly variable", str);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002278 free(str);
Denys Vlasenko5b2cc0a2017-07-18 02:44:06 +02002279//NOTE: in bash, assignment in "export READONLY_VAR=Z" fails, and sets $?=1,
2280//but export per se succeeds (does put the var in env). We don't mimic that.
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002281 return -1;
2282 }
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002283 if (flags & SETFLAG_UNEXPORT) { // && cur->flg_export ?
Denis Vlasenko950bd722009-04-21 11:23:56 +00002284 debug_printf_env("%s: unsetenv '%s'\n", __func__, str);
2285 *eq_sign = '\0';
2286 unsetenv(str);
2287 *eq_sign = '=';
2288 }
Denys Vlasenko332e4112018-04-04 22:32:59 +02002289 if (cur->var_nest_level < local_lvl) {
Denys Vlasenko295fef82009-06-03 12:47:26 +02002290 /* bash 3.2.33(1) and exported vars:
2291 * # export z=z
2292 * # f() { local z=a; env | grep ^z; }
2293 * # f
2294 * z=a
2295 * # env | grep ^z
2296 * z=z
2297 */
2298 if (cur->flg_export)
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002299 flags |= SETFLAG_EXPORT;
Denys Vlasenko929a41d2018-04-05 14:09:14 +02002300 /* New variable is local ("local VAR=VAL" or
2301 * "VAR=VAL cmd")
2302 * and existing one is global, or local
2303 * on a lower level that new one.
2304 * Remove it from global variable list:
2305 */
2306 *cur_pp = cur->next;
2307 if (G.shadowed_vars_pp) {
2308 /* Save in "shadowed" list */
2309 debug_printf_env("shadowing %s'%s'/%u by '%s'/%u\n",
2310 cur->flg_export ? "exported " : "",
2311 cur->varstr, cur->var_nest_level, str, local_lvl
2312 );
2313 cur->next = *G.shadowed_vars_pp;
2314 *G.shadowed_vars_pp = cur;
2315 } else {
2316 /* Came from pseudo_exec_argv(), no need to save: delete it */
2317 debug_printf_env("shadow-deleting %s'%s'/%u by '%s'/%u\n",
2318 cur->flg_export ? "exported " : "",
2319 cur->varstr, cur->var_nest_level, str, local_lvl
2320 );
2321 if (cur->max_len == 0) /* allocated "VAR=VAL"? */
2322 free_me = cur->varstr; /* then free it later */
2323 free(cur);
2324 }
Denys Vlasenko295fef82009-06-03 12:47:26 +02002325 break;
2326 }
Denys Vlasenko332e4112018-04-04 22:32:59 +02002327
Denis Vlasenko950bd722009-04-21 11:23:56 +00002328 if (strcmp(cur->varstr + name_len, eq_sign + 1) == 0) {
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02002329 debug_printf_env("assignement '%s' does not change anything\n", str);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002330 free_and_exp:
2331 free(str);
2332 goto exp;
2333 }
Denys Vlasenko929a41d2018-04-05 14:09:14 +02002334
2335 /* Replace the value in the found "struct variable" */
Denys Vlasenko295fef82009-06-03 12:47:26 +02002336 if (cur->max_len != 0) {
Denys Vlasenko929a41d2018-04-05 14:09:14 +02002337 if (cur->max_len >= strnlen(str, cur->max_len + 1)) {
Denys Vlasenko295fef82009-06-03 12:47:26 +02002338 /* This one is from startup env, reuse space */
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02002339 debug_printf_env("reusing startup env for '%s'\n", str);
Denys Vlasenko295fef82009-06-03 12:47:26 +02002340 strcpy(cur->varstr, str);
2341 goto free_and_exp;
2342 }
Denys Vlasenkoa7693902016-10-03 15:01:06 +02002343 /* Can't reuse */
2344 cur->max_len = 0;
2345 goto set_str_and_exp;
Denys Vlasenko295fef82009-06-03 12:47:26 +02002346 }
Denys Vlasenkoa7693902016-10-03 15:01:06 +02002347 /* max_len == 0 signifies "malloced" var, which we can
2348 * (and have to) free. But we can't free(cur->varstr) here:
2349 * if cur->flg_export is 1, it is in the environment.
2350 * We should either unsetenv+free, or wait until putenv,
2351 * then putenv(new)+free(old).
2352 */
2353 free_me = cur->varstr;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002354 goto set_str_and_exp;
2355 }
2356
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02002357 /* Not found or shadowed - create new variable struct */
Denys Vlasenko9db344a2018-04-09 19:05:11 +02002358 debug_printf_env("%s: alloc new var '%s'/%u\n", __func__, str, local_lvl);
Denys Vlasenko295fef82009-06-03 12:47:26 +02002359 cur = xzalloc(sizeof(*cur));
Denys Vlasenko332e4112018-04-04 22:32:59 +02002360 cur->var_nest_level = local_lvl;
Denys Vlasenko61407802018-04-04 21:14:28 +02002361 cur->next = *cur_pp;
2362 *cur_pp = cur;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002363
2364 set_str_and_exp:
2365 cur->varstr = str;
2366 exp:
Denys Vlasenko1e660422017-07-17 21:10:50 +02002367#if !BB_MMU || ENABLE_HUSH_READONLY
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002368 if (flags & SETFLAG_MAKE_RO) {
2369 cur->flg_read_only = 1;
Denys Vlasenko1e660422017-07-17 21:10:50 +02002370 }
2371#endif
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002372 if (flags & SETFLAG_EXPORT)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002373 cur->flg_export = 1;
2374 if (cur->flg_export) {
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002375 if (flags & SETFLAG_UNEXPORT) {
Denis Vlasenkoad4bd052009-04-20 22:04:21 +00002376 cur->flg_export = 0;
2377 /* unsetenv was already done */
2378 } else {
Denys Vlasenkoa7693902016-10-03 15:01:06 +02002379 int i;
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02002380 debug_printf_env("%s: putenv '%s'/%u\n", __func__, cur->varstr, cur->var_nest_level);
Denys Vlasenkoa7693902016-10-03 15:01:06 +02002381 i = putenv(cur->varstr);
2382 /* only now we can free old exported malloced string */
2383 free(free_me);
2384 return i;
Denis Vlasenkoad4bd052009-04-20 22:04:21 +00002385 }
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002386 }
Denys Vlasenkoa7693902016-10-03 15:01:06 +02002387 free(free_me);
Denys Vlasenko929a41d2018-04-05 14:09:14 +02002388
Denys Vlasenkocf079ff2018-04-06 14:50:12 +02002389 handle_changed_special_names(cur->varstr, name_len - 1);
Denys Vlasenko929a41d2018-04-05 14:09:14 +02002390
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002391 return 0;
2392}
2393
Denys Vlasenko6db47842009-09-05 20:15:17 +02002394/* Used at startup and after each cd */
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002395static void set_pwd_var(unsigned flag)
Denys Vlasenko6db47842009-09-05 20:15:17 +02002396{
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002397 set_local_var(xasprintf("PWD=%s", get_cwd(/*force:*/ 1)), flag);
Denys Vlasenko6db47842009-09-05 20:15:17 +02002398}
2399
Denys Vlasenko35a017c2018-06-26 18:27:54 +02002400#if ENABLE_HUSH_UNSET || ENABLE_HUSH_GETOPTS
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02002401static int unset_local_var_len(const char *name, int name_len)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002402{
2403 struct variable *cur;
Denys Vlasenko61407802018-04-04 21:14:28 +02002404 struct variable **cur_pp;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002405
Denys Vlasenko61407802018-04-04 21:14:28 +02002406 cur_pp = &G.top_var;
2407 while ((cur = *cur_pp) != NULL) {
Denys Vlasenkocf079ff2018-04-06 14:50:12 +02002408 if (strncmp(cur->varstr, name, name_len) == 0
2409 && cur->varstr[name_len] == '='
2410 ) {
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002411 if (cur->flg_read_only) {
2412 bb_error_msg("%s: readonly variable", name);
Mike Frysingerd690f682009-03-30 06:50:54 +00002413 return EXIT_FAILURE;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002414 }
Denys Vlasenkocf079ff2018-04-06 14:50:12 +02002415
Denys Vlasenko61407802018-04-04 21:14:28 +02002416 *cur_pp = cur->next;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002417 debug_printf_env("%s: unsetenv '%s'\n", __func__, cur->varstr);
2418 bb_unsetenv(cur->varstr);
2419 if (!cur->max_len)
2420 free(cur->varstr);
2421 free(cur);
Denys Vlasenkocf079ff2018-04-06 14:50:12 +02002422
Denys Vlasenkof5018da2018-04-06 17:58:21 +02002423 break;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002424 }
Denys Vlasenko61407802018-04-04 21:14:28 +02002425 cur_pp = &cur->next;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002426 }
Denys Vlasenkof5018da2018-04-06 17:58:21 +02002427
2428 /* Handle "unset PS1" et al even if did not find the variable to unset */
2429 handle_changed_special_names(name, name_len);
2430
Mike Frysingerd690f682009-03-30 06:50:54 +00002431 return EXIT_SUCCESS;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002432}
2433
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02002434static int unset_local_var(const char *name)
2435{
2436 return unset_local_var_len(name, strlen(name));
2437}
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01002438#endif
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02002439
Denys Vlasenkob2b14cb2018-06-26 18:09:22 +02002440#if BASH_HOSTNAME_VAR || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_READ || ENABLE_HUSH_GETOPTS \
2441 || (ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT)
Denys Vlasenko03dad222010-01-12 23:29:57 +01002442static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val)
Mike Frysinger98c52642009-04-02 10:02:37 +00002443{
Denis Vlasenkob29eb6e2009-04-02 13:46:27 +00002444 char *var = xasprintf("%s=%s", name, val);
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002445 set_local_var(var, /*flag:*/ 0);
Mike Frysinger98c52642009-04-02 10:02:37 +00002446}
Denys Vlasenkocc2fd5a2017-01-09 06:19:55 +01002447#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002448
Denis Vlasenkob29eb6e2009-04-02 13:46:27 +00002449
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002450/*
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002451 * Helpers for "var1=val1 var2=val2 cmd" feature
2452 */
2453static void add_vars(struct variable *var)
2454{
2455 struct variable *next;
2456
2457 while (var) {
2458 next = var->next;
2459 var->next = G.top_var;
2460 G.top_var = var;
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02002461 if (var->flg_export) {
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02002462 debug_printf_env("%s: restoring exported '%s'/%u\n", __func__, var->varstr, var->var_nest_level);
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002463 putenv(var->varstr);
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02002464 } else {
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02002465 debug_printf_env("%s: restoring variable '%s'/%u\n", __func__, var->varstr, var->var_nest_level);
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02002466 }
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002467 var = next;
2468 }
2469}
2470
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02002471/* We put strings[i] into variable table and possibly putenv them.
2472 * If variable is read only, we can free the strings[i]
2473 * which attempts to overwrite it.
2474 * The strings[] vector itself is freed.
2475 */
Denys Vlasenko929a41d2018-04-05 14:09:14 +02002476static void set_vars_and_save_old(char **strings)
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002477{
2478 char **s;
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002479
2480 if (!strings)
Denys Vlasenko929a41d2018-04-05 14:09:14 +02002481 return;
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02002482
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002483 s = strings;
2484 while (*s) {
2485 struct variable *var_p;
2486 struct variable **var_pp;
2487 char *eq;
2488
2489 eq = strchr(*s, '=');
Denys Vlasenkoe36a5892018-07-18 16:12:23 +02002490 if (HUSH_DEBUG && !eq)
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02002491 bb_error_msg_and_die("BUG in varexp4");
Denys Vlasenkoe36a5892018-07-18 16:12:23 +02002492 var_pp = get_ptr_to_local_var(*s, eq - *s);
2493 if (var_pp) {
2494 var_p = *var_pp;
2495 if (var_p->flg_read_only) {
2496 char **p;
2497 bb_error_msg("%s: readonly variable", *s);
2498 /*
2499 * "VAR=V BLTIN" unsets VARs after BLTIN completes.
2500 * If VAR is readonly, leaving it in the list
2501 * after asssignment error (msg above)
2502 * causes doubled error message later, on unset.
2503 */
2504 debug_printf_env("removing/freeing '%s' element\n", *s);
2505 free(*s);
2506 p = s;
2507 do { *p = p[1]; p++; } while (*p);
2508 goto next;
2509 }
2510 /* below, set_local_var() with nest level will
2511 * "shadow" (remove) this variable from
2512 * global linked list.
2513 */
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002514 }
Denys Vlasenkoe36a5892018-07-18 16:12:23 +02002515 debug_printf_env("%s: env override '%s'/%u\n", __func__, *s, G.var_nest_level);
2516 set_local_var(*s, (G.var_nest_level << SETFLAG_VARLVL_SHIFT) | SETFLAG_EXPORT);
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002517 s++;
Denys Vlasenko61407802018-04-04 21:14:28 +02002518 next: ;
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002519 }
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02002520 free(strings);
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002521}
2522
2523
2524/*
Denys Vlasenkoc538d5b2014-08-13 09:57:44 +02002525 * Unicode helper
2526 */
2527static void reinit_unicode_for_hush(void)
2528{
2529 /* Unicode support should be activated even if LANG is set
2530 * _during_ shell execution, not only if it was set when
2531 * shell was started. Therefore, re-check LANG every time:
2532 */
Denys Vlasenko841f8332014-08-13 10:09:49 +02002533 if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2534 || ENABLE_UNICODE_USING_LOCALE
Denys Vlasenko4c201c02018-07-17 15:04:17 +02002535 ) {
Denys Vlasenko841f8332014-08-13 10:09:49 +02002536 const char *s = get_local_var_value("LC_ALL");
2537 if (!s) s = get_local_var_value("LC_CTYPE");
2538 if (!s) s = get_local_var_value("LANG");
2539 reinit_unicode(s);
2540 }
Denys Vlasenkoc538d5b2014-08-13 09:57:44 +02002541}
2542
Denys Vlasenkoc538d5b2014-08-13 09:57:44 +02002543/*
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002544 * in_str support (strings, and "strings" read from files).
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002545 */
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002546
2547#if ENABLE_HUSH_INTERACTIVE
Denys Vlasenko4074d492016-09-30 01:49:53 +02002548/* To test correct lineedit/interactive behavior, type from command line:
2549 * echo $P\
2550 * \
2551 * AT\
2552 * H\
2553 * \
Denys Vlasenko10ad6222017-04-17 16:13:32 +02002554 * It exercises a lot of corner cases.
Denys Vlasenko4074d492016-09-30 01:49:53 +02002555 */
Denys Vlasenkof5018da2018-04-06 17:58:21 +02002556# if ENABLE_FEATURE_EDITING_FANCY_PROMPT
Mike Frysinger67c1c7b2009-04-24 06:26:18 +00002557static void cmdedit_update_prompt(void)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002558{
Denys Vlasenkof5018da2018-04-06 17:58:21 +02002559 G.PS1 = get_local_var_value("PS1");
2560 if (G.PS1 == NULL)
2561 G.PS1 = "";
2562 G.PS2 = get_local_var_value("PS2");
Mike Frysinger67c1c7b2009-04-24 06:26:18 +00002563 if (G.PS2 == NULL)
Denys Vlasenkof5018da2018-04-06 17:58:21 +02002564 G.PS2 = "";
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002565}
Denys Vlasenkof5018da2018-04-06 17:58:21 +02002566# endif
Denys Vlasenko8d6eab32018-04-07 17:01:31 +02002567static const char *setup_prompt_string(void)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002568{
2569 const char *prompt_str;
Denys Vlasenkof5018da2018-04-06 17:58:21 +02002570
Denys Vlasenko8d6eab32018-04-07 17:01:31 +02002571 debug_printf_prompt("%s promptmode:%d\n", __func__, G.promptmode);
Denys Vlasenkof5018da2018-04-06 17:58:21 +02002572
2573 IF_FEATURE_EDITING_FANCY_PROMPT( prompt_str = G.PS2;)
2574 IF_NOT_FEATURE_EDITING_FANCY_PROMPT(prompt_str = "> ";)
Denys Vlasenko8d6eab32018-04-07 17:01:31 +02002575 if (G.promptmode == 0) { /* PS1 */
Denys Vlasenkof5018da2018-04-06 17:58:21 +02002576 if (!ENABLE_FEATURE_EDITING_FANCY_PROMPT) {
2577 /* No fancy prompts supported, (re)generate "CURDIR $ " by hand */
Mike Frysingerec2c6552009-03-28 12:24:44 +00002578 free((char*)G.PS1);
Denys Vlasenko6db47842009-09-05 20:15:17 +02002579 /* bash uses $PWD value, even if it is set by user.
2580 * It uses current dir only if PWD is unset.
2581 * We always use current dir. */
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02002582 G.PS1 = xasprintf("%s %c ", get_cwd(0), (geteuid() != 0) ? '$' : '#');
Denys Vlasenkof5018da2018-04-06 17:58:21 +02002583 }
2584 prompt_str = G.PS1;
2585 }
Denys Vlasenko4074d492016-09-30 01:49:53 +02002586 debug_printf("prompt_str '%s'\n", prompt_str);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002587 return prompt_str;
2588}
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002589static int get_user_input(struct in_str *i)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002590{
2591 int r;
2592 const char *prompt_str;
2593
Denys Vlasenko8d6eab32018-04-07 17:01:31 +02002594 prompt_str = setup_prompt_string();
Denys Vlasenko8391c482010-05-22 17:50:43 +02002595# if ENABLE_FEATURE_EDITING
Denys Vlasenko8660aeb2016-11-24 17:44:02 +01002596 for (;;) {
Denys Vlasenkoc538d5b2014-08-13 09:57:44 +02002597 reinit_unicode_for_hush();
Denys Vlasenko4b89d512016-11-25 03:41:03 +01002598 if (G.flag_SIGINT) {
2599 /* There was ^C'ed, make it look prettier: */
2600 bb_putchar('\n');
2601 G.flag_SIGINT = 0;
2602 }
Denis Vlasenko422cd7c2009-03-31 12:41:52 +00002603 /* buglet: SIGINT will not make new prompt to appear _at once_,
Denys Vlasenko4b89d512016-11-25 03:41:03 +01002604 * only after <Enter>. (^C works immediately) */
Denys Vlasenko0448c552016-09-29 20:25:44 +02002605 r = read_line_input(G.line_input_state, prompt_str,
Denys Vlasenko84ea60e2017-08-02 17:27:28 +02002606 G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1
Denys Vlasenko0448c552016-09-29 20:25:44 +02002607 );
Denys Vlasenko4b89d512016-11-25 03:41:03 +01002608 /* read_line_input intercepts ^C, "convert" it to SIGINT */
Denys Vlasenkodd4b4462017-08-02 16:52:12 +02002609 if (r == 0)
Denys Vlasenko8660aeb2016-11-24 17:44:02 +01002610 raise(SIGINT);
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002611 check_and_run_traps();
Denys Vlasenko8660aeb2016-11-24 17:44:02 +01002612 if (r != 0 && !G.flag_SIGINT)
2613 break;
2614 /* ^C or SIGINT: repeat */
Denys Vlasenkodd4b4462017-08-02 16:52:12 +02002615 /* bash prints ^C even on real SIGINT (non-kbd generated) */
2616 write(STDOUT_FILENO, "^C", 2);
Denys Vlasenko8660aeb2016-11-24 17:44:02 +01002617 G.last_exitcode = 128 + SIGINT;
2618 }
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002619 if (r < 0) {
2620 /* EOF/error detected */
Denys Vlasenko4074d492016-09-30 01:49:53 +02002621 i->p = NULL;
2622 i->peek_buf[0] = r = EOF;
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002623 return r;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002624 }
Denys Vlasenko4074d492016-09-30 01:49:53 +02002625 i->p = G.user_input_buf;
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002626 return (unsigned char)*i->p++;
Denys Vlasenko8391c482010-05-22 17:50:43 +02002627# else
Denys Vlasenko8660aeb2016-11-24 17:44:02 +01002628 for (;;) {
Denis Vlasenko422cd7c2009-03-31 12:41:52 +00002629 G.flag_SIGINT = 0;
Denys Vlasenkob8709032011-05-08 21:20:01 +02002630 if (i->last_char == '\0' || i->last_char == '\n') {
2631 /* Why check_and_run_traps here? Try this interactively:
2632 * $ trap 'echo INT' INT; (sleep 2; kill -INT $$) &
2633 * $ <[enter], repeatedly...>
2634 * Without check_and_run_traps, handler never runs.
2635 */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002636 check_and_run_traps();
Denys Vlasenkob8709032011-05-08 21:20:01 +02002637 fputs(prompt_str, stdout);
2638 }
Denys Vlasenko8131eea2009-11-02 14:19:51 +01002639 fflush_all();
Denys Vlasenko4b89d512016-11-25 03:41:03 +01002640//FIXME: here ^C or SIGINT will have effect only after <Enter>
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02002641 r = hfgetc(i->file);
Denys Vlasenko8660aeb2016-11-24 17:44:02 +01002642 /* In !ENABLE_FEATURE_EDITING we don't use read_line_input,
2643 * no ^C masking happens during fgetc, no special code for ^C:
2644 * it generates SIGINT as usual.
2645 */
2646 check_and_run_traps();
2647 if (G.flag_SIGINT)
2648 G.last_exitcode = 128 + SIGINT;
2649 if (r != '\0')
2650 break;
2651 }
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002652 return r;
Denys Vlasenko8391c482010-05-22 17:50:43 +02002653# endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002654}
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002655/* This is the magic location that prints prompts
2656 * and gets data back from the user */
Denys Vlasenko4074d492016-09-30 01:49:53 +02002657static int fgetc_interactive(struct in_str *i)
2658{
2659 int ch;
2660 /* If it's interactive stdin, get new line. */
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02002661 if (G_interactive_fd && i->file->is_stdin) {
Denys Vlasenko4074d492016-09-30 01:49:53 +02002662 /* Returns first char (or EOF), the rest is in i->p[] */
2663 ch = get_user_input(i);
Denys Vlasenko8d6eab32018-04-07 17:01:31 +02002664 G.promptmode = 1; /* PS2 */
2665 debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode);
Denys Vlasenko4074d492016-09-30 01:49:53 +02002666 } else {
2667 /* Not stdin: script file, sourced file, etc */
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02002668 do ch = hfgetc(i->file); while (ch == '\0');
Denys Vlasenko4074d492016-09-30 01:49:53 +02002669 }
2670 return ch;
2671}
2672#else
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02002673static ALWAYS_INLINE int fgetc_interactive(struct in_str *i)
Denys Vlasenko4074d492016-09-30 01:49:53 +02002674{
2675 int ch;
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02002676 do ch = hfgetc(i->file); while (ch == '\0');
Denys Vlasenko4074d492016-09-30 01:49:53 +02002677 return ch;
2678}
2679#endif /* INTERACTIVE */
2680
Denys Vlasenko87e039d2016-11-08 22:35:05 +01002681static int i_getch(struct in_str *i)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002682{
2683 int ch;
2684
Denys Vlasenko87e039d2016-11-08 22:35:05 +01002685 if (!i->file) {
2686 /* string-based in_str */
2687 ch = (unsigned char)*i->p;
2688 if (ch != '\0') {
2689 i->p++;
2690 i->last_char = ch;
2691 return ch;
2692 }
2693 return EOF;
2694 }
2695
2696 /* FILE-based in_str */
2697
Denys Vlasenko4074d492016-09-30 01:49:53 +02002698#if ENABLE_FEATURE_EDITING
2699 /* This can be stdin, check line editing char[] buffer */
2700 if (i->p && *i->p != '\0') {
2701 ch = (unsigned char)*i->p++;
2702 goto out;
2703 }
2704#endif
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002705 /* peek_buf[] is an int array, not char. Can contain EOF. */
2706 ch = i->peek_buf[0];
Denys Vlasenko4074d492016-09-30 01:49:53 +02002707 if (ch != 0) {
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002708 int ch2 = i->peek_buf[1];
2709 i->peek_buf[0] = ch2;
2710 if (ch2 == 0) /* very likely, avoid redundant write */
2711 goto out;
2712 i->peek_buf[1] = 0;
2713 goto out;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002714 }
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002715
Denys Vlasenko4074d492016-09-30 01:49:53 +02002716 ch = fgetc_interactive(i);
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002717 out:
Denis Vlasenko913a2012009-04-05 22:17:04 +00002718 debug_printf("file_get: got '%c' %d\n", ch, ch);
Denys Vlasenkocecbc982011-03-30 18:54:52 +02002719 i->last_char = ch;
Denys Vlasenko5807e182018-02-08 19:19:04 +01002720#if ENABLE_HUSH_LINENO_VAR
2721 if (ch == '\n') {
Denys Vlasenko6aad1dd2018-01-19 15:37:04 +01002722 G.lineno++;
Denys Vlasenko5807e182018-02-08 19:19:04 +01002723 debug_printf_parse("G.lineno++ = %u\n", G.lineno);
2724 }
Denys Vlasenko6aad1dd2018-01-19 15:37:04 +01002725#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002726 return ch;
2727}
2728
Denys Vlasenko87e039d2016-11-08 22:35:05 +01002729static int i_peek(struct in_str *i)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002730{
2731 int ch;
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002732
Denys Vlasenko87e039d2016-11-08 22:35:05 +01002733 if (!i->file) {
2734 /* string-based in_str */
2735 /* Doesn't report EOF on NUL. None of the callers care. */
2736 return (unsigned char)*i->p;
2737 }
2738
2739 /* FILE-based in_str */
2740
Denys Vlasenko4074d492016-09-30 01:49:53 +02002741#if ENABLE_FEATURE_EDITING && ENABLE_HUSH_INTERACTIVE
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002742 /* This can be stdin, check line editing char[] buffer */
2743 if (i->p && *i->p != '\0')
2744 return (unsigned char)*i->p;
2745#endif
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002746 /* peek_buf[] is an int array, not char. Can contain EOF. */
2747 ch = i->peek_buf[0];
Denys Vlasenko4074d492016-09-30 01:49:53 +02002748 if (ch != 0)
2749 return ch;
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002750
Denys Vlasenko4074d492016-09-30 01:49:53 +02002751 /* Need to get a new char */
2752 ch = fgetc_interactive(i);
2753 debug_printf("file_peek: got '%c' %d\n", ch, ch);
2754
2755 /* Save it by either rolling back line editing buffer, or in i->peek_buf[0] */
2756#if ENABLE_FEATURE_EDITING && ENABLE_HUSH_INTERACTIVE
2757 if (i->p) {
2758 i->p -= 1;
2759 return ch;
2760 }
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002761#endif
Denys Vlasenko4074d492016-09-30 01:49:53 +02002762 i->peek_buf[0] = ch;
2763 /*i->peek_buf[1] = 0; - already is */
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002764 return ch;
2765}
2766
Denys Vlasenko4074d492016-09-30 01:49:53 +02002767/* Only ever called if i_peek() was called, and did not return EOF.
2768 * IOW: we know the previous peek saw an ordinary char, not EOF, not NUL,
2769 * not end-of-line. Therefore we never need to read a new editing line here.
2770 */
2771static int i_peek2(struct in_str *i)
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002772{
Denys Vlasenko4074d492016-09-30 01:49:53 +02002773 int ch;
2774
2775 /* There are two cases when i->p[] buffer exists.
2776 * (1) it's a string in_str.
Denys Vlasenko08755f92016-09-30 02:02:25 +02002777 * (2) It's a file, and we have a saved line editing buffer.
Denys Vlasenko4074d492016-09-30 01:49:53 +02002778 * In both cases, we know that i->p[0] exists and not NUL, and
2779 * the peek2 result is in i->p[1].
2780 */
2781 if (i->p)
2782 return (unsigned char)i->p[1];
2783
2784 /* Now we know it is a file-based in_str. */
2785
2786 /* peek_buf[] is an int array, not char. Can contain EOF. */
2787 /* Is there 2nd char? */
2788 ch = i->peek_buf[1];
2789 if (ch == 0) {
2790 /* We did not read it yet, get it now */
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02002791 do ch = hfgetc(i->file); while (ch == '\0');
Denys Vlasenko4074d492016-09-30 01:49:53 +02002792 i->peek_buf[1] = ch;
2793 }
2794
2795 debug_printf("file_peek2: got '%c' %d\n", ch, ch);
2796 return ch;
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002797}
2798
Denys Vlasenkoa94eeb02018-03-31 20:16:31 +02002799static int i_getch_and_eat_bkslash_nl(struct in_str *input)
2800{
2801 for (;;) {
2802 int ch, ch2;
2803
2804 ch = i_getch(input);
2805 if (ch != '\\')
2806 return ch;
2807 ch2 = i_peek(input);
2808 if (ch2 != '\n')
2809 return ch;
2810 /* backslash+newline, skip it */
2811 i_getch(input);
2812 }
2813}
2814
2815/* Note: this function _eats_ \<newline> pairs, safe to use plain
2816 * i_getch() after it instead of i_getch_and_eat_bkslash_nl().
2817 */
2818static int i_peek_and_eat_bkslash_nl(struct in_str *input)
2819{
2820 for (;;) {
2821 int ch, ch2;
2822
2823 ch = i_peek(input);
2824 if (ch != '\\')
2825 return ch;
2826 ch2 = i_peek2(input);
2827 if (ch2 != '\n')
2828 return ch;
2829 /* backslash+newline, skip it */
2830 i_getch(input);
2831 i_getch(input);
2832 }
2833}
2834
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02002835static void setup_file_in_str(struct in_str *i, HFILE *fp)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002836{
Denys Vlasenkoa1463192011-01-18 17:55:04 +01002837 memset(i, 0, sizeof(*i));
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02002838 i->file = fp;
Denys Vlasenkoa1463192011-01-18 17:55:04 +01002839 /* i->p = NULL; */
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002840}
2841
2842static void setup_string_in_str(struct in_str *i, const char *s)
2843{
Denys Vlasenkoa1463192011-01-18 17:55:04 +01002844 memset(i, 0, sizeof(*i));
Denys Vlasenko87e039d2016-11-08 22:35:05 +01002845 /*i->file = NULL */;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002846 i->p = s;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002847}
2848
2849
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002850/*
2851 * o_string support
2852 */
2853#define B_CHUNK (32 * sizeof(char*))
Eric Andersen25f27032001-04-26 23:22:31 +00002854
Denis Vlasenko0b677d82009-04-10 13:49:10 +00002855static void o_reset_to_empty_unquoted(o_string *o)
Eric Andersen25f27032001-04-26 23:22:31 +00002856{
2857 o->length = 0;
Denys Vlasenko38292b62010-09-05 14:49:40 +02002858 o->has_quoted_part = 0;
Denis Vlasenkod65ea392007-10-01 10:02:25 +00002859 if (o->data)
2860 o->data[0] = '\0';
Eric Andersen25f27032001-04-26 23:22:31 +00002861}
2862
Denys Vlasenko18567402018-07-20 17:51:31 +02002863static void o_free_and_set_NULL(o_string *o)
Eric Andersen25f27032001-04-26 23:22:31 +00002864{
Aaron Lehmanna170e1c2002-11-28 11:27:31 +00002865 free(o->data);
Denis Vlasenkod65ea392007-10-01 10:02:25 +00002866 memset(o, 0, sizeof(*o));
Eric Andersen25f27032001-04-26 23:22:31 +00002867}
2868
Denys Vlasenko18567402018-07-20 17:51:31 +02002869static ALWAYS_INLINE void o_free(o_string *o)
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00002870{
2871 free(o->data);
2872}
2873
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00002874static void o_grow_by(o_string *o, int len)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002875{
2876 if (o->length + len > o->maxlen) {
Denys Vlasenko46e64982016-09-29 19:50:55 +02002877 o->maxlen += (2 * len) | (B_CHUNK-1);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002878 o->data = xrealloc(o->data, 1 + o->maxlen);
2879 }
2880}
2881
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00002882static void o_addchr(o_string *o, int ch)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002883{
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00002884 debug_printf("o_addchr: '%c' o->length=%d o=%p\n", ch, o->length, o);
Denys Vlasenko46e64982016-09-29 19:50:55 +02002885 if (o->length < o->maxlen) {
2886 /* likely. avoid o_grow_by() call */
2887 add:
2888 o->data[o->length] = ch;
2889 o->length++;
2890 o->data[o->length] = '\0';
2891 return;
2892 }
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00002893 o_grow_by(o, 1);
Denys Vlasenko46e64982016-09-29 19:50:55 +02002894 goto add;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002895}
2896
Denys Vlasenko657086a2016-09-29 18:07:42 +02002897#if 0
2898/* Valid only if we know o_string is not empty */
2899static void o_delchr(o_string *o)
2900{
2901 o->length--;
2902 o->data[o->length] = '\0';
2903}
2904#endif
2905
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00002906static void o_addblock(o_string *o, const char *str, int len)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002907{
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00002908 o_grow_by(o, len);
Denys Vlasenko0675b032017-07-24 02:17:05 +02002909 ((char*)mempcpy(&o->data[o->length], str, len))[0] = '\0';
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002910 o->length += len;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002911}
2912
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00002913static void o_addstr(o_string *o, const char *str)
Mike Frysinger98c52642009-04-02 10:02:37 +00002914{
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00002915 o_addblock(o, str, strlen(str));
2916}
Denys Vlasenko2e48d532010-05-22 17:30:39 +02002917
Denys Vlasenkoaa449c92018-07-28 12:13:58 +02002918static void o_addstr_with_NUL(o_string *o, const char *str)
2919{
2920 o_addblock(o, str, strlen(str) + 1);
2921}
2922
Denys Vlasenko1e811b12010-05-22 03:12:29 +02002923#if !BB_MMU
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00002924static void nommu_addchr(o_string *o, int ch)
2925{
2926 if (o)
2927 o_addchr(o, ch);
2928}
2929#else
Denys Vlasenko28a105d2009-06-01 11:26:30 +02002930# define nommu_addchr(o, str) ((void)0)
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00002931#endif
2932
Denys Vlasenkoaa449c92018-07-28 12:13:58 +02002933#if ENABLE_HUSH_MODE_X
2934static void x_mode_addchr(int ch)
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00002935{
Denys Vlasenkoaa449c92018-07-28 12:13:58 +02002936 o_addchr(&G.x_mode_buf, ch);
Mike Frysinger98c52642009-04-02 10:02:37 +00002937}
Denys Vlasenkoaa449c92018-07-28 12:13:58 +02002938static void x_mode_addstr(const char *str)
2939{
2940 o_addstr(&G.x_mode_buf, str);
2941}
2942static void x_mode_addblock(const char *str, int len)
2943{
2944 o_addblock(&G.x_mode_buf, str, len);
2945}
2946static void x_mode_prefix(void)
2947{
2948 int n = G.x_mode_depth;
2949 do x_mode_addchr('+'); while (--n >= 0);
2950}
2951static void x_mode_flush(void)
2952{
2953 int len = G.x_mode_buf.length;
2954 if (len <= 0)
2955 return;
2956 if (G.x_mode_fd > 0) {
2957 G.x_mode_buf.data[len] = '\n';
2958 full_write(G.x_mode_fd, G.x_mode_buf.data, len + 1);
2959 }
2960 G.x_mode_buf.length = 0;
2961}
2962#endif
Mike Frysinger98c52642009-04-02 10:02:37 +00002963
Denys Vlasenkof3e28182009-11-17 03:35:31 +01002964/*
Denys Vlasenko238081f2010-10-03 14:26:26 +02002965 * HUSH_BRACE_EXPANSION code needs corresponding quoting on variable expansion side.
Denys Vlasenkof3e28182009-11-17 03:35:31 +01002966 * Currently, "v='{q,w}'; echo $v" erroneously expands braces in $v.
2967 * Apparently, on unquoted $v bash still does globbing
2968 * ("v='*.txt'; echo $v" prints all .txt files),
2969 * but NOT brace expansion! Thus, there should be TWO independent
2970 * quoting mechanisms on $v expansion side: one protects
2971 * $v from brace expansion, and other additionally protects "$v" against globbing.
2972 * We have only second one.
2973 */
2974
Denys Vlasenko9e800222010-10-03 14:28:04 +02002975#if ENABLE_HUSH_BRACE_EXPANSION
Denys Vlasenkof3e28182009-11-17 03:35:31 +01002976# define MAYBE_BRACES "{}"
2977#else
2978# define MAYBE_BRACES ""
2979#endif
2980
Eric Andersen25f27032001-04-26 23:22:31 +00002981/* My analysis of quoting semantics tells me that state information
2982 * is associated with a destination, not a source.
2983 */
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002984static void o_addqchr(o_string *o, int ch)
Eric Andersen25f27032001-04-26 23:22:31 +00002985{
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002986 int sz = 1;
Denys Vlasenkof3e28182009-11-17 03:35:31 +01002987 char *found = strchr("*?[\\" MAYBE_BRACES, ch);
Denis Vlasenko371de4a2008-10-14 12:43:13 +00002988 if (found)
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002989 sz++;
Denis Vlasenko371de4a2008-10-14 12:43:13 +00002990 o_grow_by(o, sz);
2991 if (found) {
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002992 o->data[o->length] = '\\';
2993 o->length++;
Eric Andersen25f27032001-04-26 23:22:31 +00002994 }
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002995 o->data[o->length] = ch;
2996 o->length++;
2997 o->data[o->length] = '\0';
Eric Andersen25f27032001-04-26 23:22:31 +00002998}
2999
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00003000static void o_addQchr(o_string *o, int ch)
Denis Vlasenko87f40ba2008-06-10 22:39:37 +00003001{
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00003002 int sz = 1;
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02003003 if ((o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)
3004 && strchr("*?[\\" MAYBE_BRACES, ch)
3005 ) {
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00003006 sz++;
3007 o->data[o->length] = '\\';
3008 o->length++;
3009 }
3010 o_grow_by(o, sz);
3011 o->data[o->length] = ch;
3012 o->length++;
3013 o->data[o->length] = '\0';
3014}
3015
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02003016static void o_addqblock(o_string *o, const char *str, int len)
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00003017{
Denis Vlasenko87f40ba2008-06-10 22:39:37 +00003018 while (len) {
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00003019 char ch;
3020 int sz;
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003021 int ordinary_cnt = strcspn(str, "*?[\\" MAYBE_BRACES);
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00003022 if (ordinary_cnt > len) /* paranoia */
3023 ordinary_cnt = len;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00003024 o_addblock(o, str, ordinary_cnt);
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00003025 if (ordinary_cnt == len)
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02003026 return; /* NUL is already added by o_addblock */
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00003027 str += ordinary_cnt;
Denis Vlasenko30c9cc52008-06-17 07:24:29 +00003028 len -= ordinary_cnt + 1; /* we are processing + 1 char below */
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00003029
Denis Vlasenko87f40ba2008-06-10 22:39:37 +00003030 ch = *str++;
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00003031 sz = 1;
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003032 if (ch) { /* it is necessarily one of "*?[\\" MAYBE_BRACES */
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00003033 sz++;
3034 o->data[o->length] = '\\';
3035 o->length++;
Denis Vlasenko87f40ba2008-06-10 22:39:37 +00003036 }
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00003037 o_grow_by(o, sz);
3038 o->data[o->length] = ch;
3039 o->length++;
Denis Vlasenko87f40ba2008-06-10 22:39:37 +00003040 }
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02003041 o->data[o->length] = '\0';
Denis Vlasenko87f40ba2008-06-10 22:39:37 +00003042}
3043
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02003044static void o_addQblock(o_string *o, const char *str, int len)
3045{
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02003046 if (!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)) {
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02003047 o_addblock(o, str, len);
3048 return;
3049 }
3050 o_addqblock(o, str, len);
3051}
3052
Denys Vlasenko38292b62010-09-05 14:49:40 +02003053static void o_addQstr(o_string *o, const char *str)
3054{
3055 o_addQblock(o, str, strlen(str));
3056}
3057
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003058/* A special kind of o_string for $VAR and `cmd` expansion.
3059 * It contains char* list[] at the beginning, which is grown in 16 element
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00003060 * increments. Actual string data starts at the next multiple of 16 * (char*).
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003061 * list[i] contains an INDEX (int!) into this string data.
3062 * It means that if list[] needs to grow, data needs to be moved higher up
3063 * but list[i]'s need not be modified.
3064 * NB: remembering how many list[i]'s you have there is crucial.
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00003065 * o_finalize_list() operation post-processes this structure - calculates
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003066 * and stores actual char* ptrs in list[]. Oh, it NULL terminates it as well.
3067 */
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003068#if DEBUG_EXPAND || DEBUG_GLOB
3069static void debug_print_list(const char *prefix, o_string *o, int n)
3070{
3071 char **list = (char**)o->data;
3072 int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3073 int i = 0;
Denis Vlasenko0701dca2009-04-11 10:38:47 +00003074
3075 indent();
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01003076 fdprintf(2, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d glob:%d quoted:%d escape:%d\n",
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02003077 prefix, list, n, string_start, o->length, o->maxlen,
3078 !!(o->o_expflags & EXP_FLAG_GLOB),
3079 o->has_quoted_part,
3080 !!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003081 while (i < n) {
Denis Vlasenko0701dca2009-04-11 10:38:47 +00003082 indent();
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01003083 fdprintf(2, " list[%d]=%d '%s' %p\n", i, (int)(uintptr_t)list[i],
3084 o->data + (int)(uintptr_t)list[i] + string_start,
3085 o->data + (int)(uintptr_t)list[i] + string_start);
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003086 i++;
3087 }
3088 if (n) {
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01003089 const char *p = o->data + (int)(uintptr_t)list[n - 1] + string_start;
Denis Vlasenko0701dca2009-04-11 10:38:47 +00003090 indent();
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01003091 fdprintf(2, " total_sz:%ld\n", (long)((p + strlen(p) + 1) - o->data));
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003092 }
3093}
3094#else
Denys Vlasenko28a105d2009-06-01 11:26:30 +02003095# define debug_print_list(prefix, o, n) ((void)0)
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003096#endif
3097
3098/* n = o_save_ptr_helper(str, n) "starts new string" by storing an index value
3099 * in list[n] so that it points past last stored byte so far.
3100 * It returns n+1. */
3101static int o_save_ptr_helper(o_string *o, int n)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003102{
3103 char **list = (char**)o->data;
Denis Vlasenko895bea22008-06-10 18:06:24 +00003104 int string_start;
3105 int string_len;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003106
3107 if (!o->has_empty_slot) {
Denis Vlasenko895bea22008-06-10 18:06:24 +00003108 string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3109 string_len = o->length - string_start;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003110 if (!(n & 0xf)) { /* 0, 0x10, 0x20...? */
Denis Vlasenko30c9cc52008-06-17 07:24:29 +00003111 debug_printf_list("list[%d]=%d string_start=%d (growing)\n", n, string_len, string_start);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003112 /* list[n] points to string_start, make space for 16 more pointers */
3113 o->maxlen += 0x10 * sizeof(list[0]);
3114 o->data = xrealloc(o->data, o->maxlen + 1);
Denis Vlasenko7049ff82008-06-25 09:53:17 +00003115 list = (char**)o->data;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003116 memmove(list + n + 0x10, list + n, string_len);
Denys Vlasenko186cf492018-07-27 12:14:39 +02003117 /*
3118 * expand_on_ifs() has a "previous argv[] ends in IFS?"
3119 * check. (grep for -prev-ifs-check-).
3120 * Ensure that argv[-1][last] is not garbage
3121 * but zero bytes, to save index check there.
3122 */
3123 list[n + 0x10 - 1] = 0;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003124 o->length += 0x10 * sizeof(list[0]);
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00003125 } else {
3126 debug_printf_list("list[%d]=%d string_start=%d\n",
3127 n, string_len, string_start);
3128 }
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003129 } else {
3130 /* We have empty slot at list[n], reuse without growth */
Denis Vlasenko895bea22008-06-10 18:06:24 +00003131 string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); /* NB: n+1! */
3132 string_len = o->length - string_start;
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00003133 debug_printf_list("list[%d]=%d string_start=%d (empty slot)\n",
3134 n, string_len, string_start);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003135 o->has_empty_slot = 0;
3136 }
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02003137 o->has_quoted_part = 0;
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02003138 list[n] = (char*)(uintptr_t)string_len;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003139 return n + 1;
3140}
3141
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003142/* "What was our last o_save_ptr'ed position (byte offset relative o->data)?" */
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00003143static int o_get_last_ptr(o_string *o, int n)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003144{
3145 char **list = (char**)o->data;
3146 int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3147
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02003148 return ((int)(uintptr_t)list[n-1]) + string_start;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003149}
3150
Denys Vlasenko9e800222010-10-03 14:28:04 +02003151#if ENABLE_HUSH_BRACE_EXPANSION
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003152/* There in a GNU extension, GLOB_BRACE, but it is not usable:
3153 * first, it processes even {a} (no commas), second,
3154 * I didn't manage to make it return strings when they don't match
Denys Vlasenko160746b2009-11-16 05:51:18 +01003155 * existing files. Need to re-implement it.
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003156 */
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003157
3158/* Helper */
3159static int glob_needed(const char *s)
3160{
3161 while (*s) {
3162 if (*s == '\\') {
3163 if (!s[1])
3164 return 0;
3165 s += 2;
3166 continue;
3167 }
3168 if (*s == '*' || *s == '[' || *s == '?' || *s == '{')
3169 return 1;
3170 s++;
3171 }
3172 return 0;
3173}
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003174/* Return pointer to next closing brace or to comma */
3175static const char *next_brace_sub(const char *cp)
3176{
3177 unsigned depth = 0;
3178 cp++;
3179 while (*cp != '\0') {
3180 if (*cp == '\\') {
3181 if (*++cp == '\0')
3182 break;
3183 cp++;
3184 continue;
Denys Vlasenko3581c622010-01-25 13:39:24 +01003185 }
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02003186 if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003187 break;
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02003188 if (*cp++ == '{')
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003189 depth++;
3190 }
3191
3192 return *cp != '\0' ? cp : NULL;
3193}
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003194/* Recursive brace globber. Note: may garble pattern[]. */
3195static int glob_brace(char *pattern, o_string *o, int n)
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003196{
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003197 char *new_pattern_buf;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003198 const char *begin;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003199 const char *next;
3200 const char *rest;
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003201 const char *p;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003202 size_t rest_len;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003203
3204 debug_printf_glob("glob_brace('%s')\n", pattern);
3205
3206 begin = pattern;
3207 while (1) {
3208 if (*begin == '\0')
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003209 goto simple_glob;
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02003210 if (*begin == '{') {
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003211 /* Find the first sub-pattern and at the same time
3212 * find the rest after the closing brace */
3213 next = next_brace_sub(begin);
3214 if (next == NULL) {
3215 /* An illegal expression */
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003216 goto simple_glob;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003217 }
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02003218 if (*next == '}') {
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003219 /* "{abc}" with no commas - illegal
3220 * brace expr, disregard and skip it */
3221 begin = next + 1;
3222 continue;
3223 }
3224 break;
3225 }
3226 if (*begin == '\\' && begin[1] != '\0')
3227 begin++;
3228 begin++;
3229 }
3230 debug_printf_glob("begin:%s\n", begin);
3231 debug_printf_glob("next:%s\n", next);
3232
3233 /* Now find the end of the whole brace expression */
3234 rest = next;
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02003235 while (*rest != '}') {
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003236 rest = next_brace_sub(rest);
3237 if (rest == NULL) {
3238 /* An illegal expression */
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003239 goto simple_glob;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003240 }
3241 debug_printf_glob("rest:%s\n", rest);
3242 }
3243 rest_len = strlen(++rest) + 1;
3244
3245 /* We are sure the brace expression is well-formed */
3246
3247 /* Allocate working buffer large enough for our work */
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003248 new_pattern_buf = xmalloc(strlen(pattern));
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003249
3250 /* We have a brace expression. BEGIN points to the opening {,
3251 * NEXT points past the terminator of the first element, and REST
3252 * points past the final }. We will accumulate result names from
3253 * recursive runs for each brace alternative in the buffer using
3254 * GLOB_APPEND. */
3255
3256 p = begin + 1;
3257 while (1) {
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003258 /* Construct the new glob expression */
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003259 memcpy(
3260 mempcpy(
3261 mempcpy(new_pattern_buf,
3262 /* We know the prefix for all sub-patterns */
3263 pattern, begin - pattern),
3264 p, next - p),
3265 rest, rest_len);
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003266
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003267 /* Note: glob_brace() may garble new_pattern_buf[].
3268 * That's why we re-copy prefix every time (1st memcpy above).
3269 */
3270 n = glob_brace(new_pattern_buf, o, n);
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02003271 if (*next == '}') {
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003272 /* We saw the last entry */
3273 break;
3274 }
3275 p = next + 1;
3276 next = next_brace_sub(next);
3277 }
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003278 free(new_pattern_buf);
3279 return n;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003280
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003281 simple_glob:
3282 {
3283 int gr;
3284 glob_t globdata;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003285
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003286 memset(&globdata, 0, sizeof(globdata));
3287 gr = glob(pattern, 0, NULL, &globdata);
3288 debug_printf_glob("glob('%s'):%d\n", pattern, gr);
3289 if (gr != 0) {
3290 if (gr == GLOB_NOMATCH) {
3291 globfree(&globdata);
3292 /* NB: garbles parameter */
3293 unbackslash(pattern);
3294 o_addstr_with_NUL(o, pattern);
3295 debug_printf_glob("glob pattern '%s' is literal\n", pattern);
3296 return o_save_ptr_helper(o, n);
3297 }
3298 if (gr == GLOB_NOSPACE)
Denys Vlasenko899ae532018-04-01 19:59:37 +02003299 bb_die_memory_exhausted();
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003300 /* GLOB_ABORTED? Only happens with GLOB_ERR flag,
3301 * but we didn't specify it. Paranoia again. */
3302 bb_error_msg_and_die("glob error %d on '%s'", gr, pattern);
3303 }
3304 if (globdata.gl_pathv && globdata.gl_pathv[0]) {
3305 char **argv = globdata.gl_pathv;
3306 while (1) {
3307 o_addstr_with_NUL(o, *argv);
3308 n = o_save_ptr_helper(o, n);
3309 argv++;
3310 if (!*argv)
3311 break;
3312 }
3313 }
3314 globfree(&globdata);
3315 }
3316 return n;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003317}
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003318/* Performs globbing on last list[],
3319 * saving each result as a new list[].
3320 */
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02003321static int perform_glob(o_string *o, int n)
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003322{
3323 char *pattern, *copy;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003324
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02003325 debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data);
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003326 if (!o->data)
3327 return o_save_ptr_helper(o, n);
3328 pattern = o->data + o_get_last_ptr(o, n);
3329 debug_printf_glob("glob pattern '%s'\n", pattern);
3330 if (!glob_needed(pattern)) {
3331 /* unbackslash last string in o in place, fix length */
3332 o->length = unbackslash(pattern) - o->data;
3333 debug_printf_glob("glob pattern '%s' is literal\n", pattern);
3334 return o_save_ptr_helper(o, n);
3335 }
3336
3337 copy = xstrdup(pattern);
3338 /* "forget" pattern in o */
3339 o->length = pattern - o->data;
3340 n = glob_brace(copy, o, n);
3341 free(copy);
3342 if (DEBUG_GLOB)
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02003343 debug_print_list("perform_glob returning", o, n);
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003344 return n;
3345}
3346
Denys Vlasenko238081f2010-10-03 14:26:26 +02003347#else /* !HUSH_BRACE_EXPANSION */
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003348
3349/* Helper */
3350static int glob_needed(const char *s)
3351{
3352 while (*s) {
3353 if (*s == '\\') {
3354 if (!s[1])
3355 return 0;
3356 s += 2;
3357 continue;
3358 }
3359 if (*s == '*' || *s == '[' || *s == '?')
3360 return 1;
3361 s++;
3362 }
3363 return 0;
3364}
3365/* Performs globbing on last list[],
3366 * saving each result as a new list[].
3367 */
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02003368static int perform_glob(o_string *o, int n)
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003369{
3370 glob_t globdata;
3371 int gr;
3372 char *pattern;
3373
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02003374 debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data);
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003375 if (!o->data)
3376 return o_save_ptr_helper(o, n);
3377 pattern = o->data + o_get_last_ptr(o, n);
Denis Vlasenko30c9cc52008-06-17 07:24:29 +00003378 debug_printf_glob("glob pattern '%s'\n", pattern);
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003379 if (!glob_needed(pattern)) {
3380 literal:
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003381 /* unbackslash last string in o in place, fix length */
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003382 o->length = unbackslash(pattern) - o->data;
Denis Vlasenko30c9cc52008-06-17 07:24:29 +00003383 debug_printf_glob("glob pattern '%s' is literal\n", pattern);
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003384 return o_save_ptr_helper(o, n);
3385 }
3386
3387 memset(&globdata, 0, sizeof(globdata));
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003388 /* Can't use GLOB_NOCHECK: it does not unescape the string.
3389 * If we glob "*.\*" and don't find anything, we need
3390 * to fall back to using literal "*.*", but GLOB_NOCHECK
3391 * will return "*.\*"!
3392 */
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003393 gr = glob(pattern, 0, NULL, &globdata);
3394 debug_printf_glob("glob('%s'):%d\n", pattern, gr);
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003395 if (gr != 0) {
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003396 if (gr == GLOB_NOMATCH) {
3397 globfree(&globdata);
3398 goto literal;
3399 }
3400 if (gr == GLOB_NOSPACE)
Denys Vlasenko899ae532018-04-01 19:59:37 +02003401 bb_die_memory_exhausted();
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003402 /* GLOB_ABORTED? Only happens with GLOB_ERR flag,
3403 * but we didn't specify it. Paranoia again. */
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003404 bb_error_msg_and_die("glob error %d on '%s'", gr, pattern);
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003405 }
3406 if (globdata.gl_pathv && globdata.gl_pathv[0]) {
3407 char **argv = globdata.gl_pathv;
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003408 /* "forget" pattern in o */
3409 o->length = pattern - o->data;
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003410 while (1) {
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00003411 o_addstr_with_NUL(o, *argv);
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003412 n = o_save_ptr_helper(o, n);
3413 argv++;
3414 if (!*argv)
3415 break;
3416 }
3417 }
3418 globfree(&globdata);
3419 if (DEBUG_GLOB)
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02003420 debug_print_list("perform_glob returning", o, n);
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003421 return n;
3422}
3423
Denys Vlasenko238081f2010-10-03 14:26:26 +02003424#endif /* !HUSH_BRACE_EXPANSION */
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003425
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02003426/* If o->o_expflags & EXP_FLAG_GLOB, glob the string so far remembered.
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00003427 * Otherwise, just finish current list[] and start new */
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003428static int o_save_ptr(o_string *o, int n)
3429{
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02003430 if (o->o_expflags & EXP_FLAG_GLOB) {
Denis Vlasenkoa8b6dff2009-03-20 12:05:14 +00003431 /* If o->has_empty_slot, list[n] was already globbed
3432 * (if it was requested back then when it was filled)
3433 * so don't do that again! */
3434 if (!o->has_empty_slot)
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02003435 return perform_glob(o, n); /* o_save_ptr_helper is inside */
Denis Vlasenkoa8b6dff2009-03-20 12:05:14 +00003436 }
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003437 return o_save_ptr_helper(o, n);
3438}
3439
3440/* "Please convert list[n] to real char* ptrs, and NULL terminate it." */
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00003441static char **o_finalize_list(o_string *o, int n)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003442{
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003443 char **list;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003444 int string_start;
3445
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003446 if (DEBUG_EXPAND)
3447 debug_print_list("finalized", o, n);
Denis Vlasenko30c9cc52008-06-17 07:24:29 +00003448 debug_printf_expand("finalized n:%d\n", n);
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003449 list = (char**)o->data;
3450 string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3451 list[--n] = NULL;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003452 while (n) {
3453 n--;
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003454 list[n] = o->data + (int)(uintptr_t)list[n] + string_start;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003455 }
3456 return list;
3457}
3458
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003459static void free_pipe_list(struct pipe *pi);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003460
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003461/* Returns pi->next - next pipe in the list */
3462static struct pipe *free_pipe(struct pipe *pi)
Denis Vlasenkof886fd22008-10-13 12:36:05 +00003463{
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003464 struct pipe *next;
3465 int i;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003466
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003467 debug_printf_clean("free_pipe (pid %d)\n", getpid());
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003468 for (i = 0; i < pi->num_cmds; i++) {
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003469 struct command *command;
3470 struct redir_struct *r, *rnext;
3471
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003472 command = &pi->cmds[i];
Denis Vlasenko0701dca2009-04-11 10:38:47 +00003473 debug_printf_clean(" command %d:\n", i);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003474 if (command->argv) {
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003475 if (DEBUG_CLEAN) {
3476 int a;
3477 char **p;
3478 for (a = 0, p = command->argv; *p; a++, p++) {
3479 debug_printf_clean(" argv[%d] = %s\n", a, *p);
3480 }
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003481 }
3482 free_strings(command->argv);
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003483 //command->argv = NULL;
Denis Vlasenkob6e65562009-04-03 16:49:04 +00003484 }
3485 /* not "else if": on syntax error, we may have both! */
3486 if (command->group) {
Denys Vlasenko9d617c42009-06-09 18:40:52 +02003487 debug_printf_clean(" begin group (cmd_type:%d)\n",
3488 command->cmd_type);
Denis Vlasenko0701dca2009-04-11 10:38:47 +00003489 free_pipe_list(command->group);
3490 debug_printf_clean(" end group\n");
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003491 //command->group = NULL;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003492 }
Denis Vlasenkoed055212009-04-11 10:37:10 +00003493 /* else is crucial here.
3494 * If group != NULL, child_func is meaningless */
3495#if ENABLE_HUSH_FUNCTIONS
3496 else if (command->child_func) {
3497 debug_printf_exec("cmd %p releases child func at %p\n", command, command->child_func);
3498 command->child_func->parent_cmd = NULL;
3499 }
3500#endif
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00003501#if !BB_MMU
3502 free(command->group_as_string);
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003503 //command->group_as_string = NULL;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00003504#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003505 for (r = command->redirects; r; r = rnext) {
Denis Vlasenko0701dca2009-04-11 10:38:47 +00003506 debug_printf_clean(" redirect %d%s",
3507 r->rd_fd, redir_table[r->rd_type].descrip);
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +00003508 /* guard against the case >$FOO, where foo is unset or blank */
3509 if (r->rd_filename) {
3510 debug_printf_clean(" fname:'%s'\n", r->rd_filename);
3511 free(r->rd_filename);
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003512 //r->rd_filename = NULL;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003513 }
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +00003514 debug_printf_clean(" rd_dup:%d\n", r->rd_dup);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003515 rnext = r->next;
3516 free(r);
3517 }
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003518 //command->redirects = NULL;
Denis Vlasenkof886fd22008-10-13 12:36:05 +00003519 }
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003520 free(pi->cmds); /* children are an array, they get freed all at once */
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003521 //pi->cmds = NULL;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003522#if ENABLE_HUSH_JOB
3523 free(pi->cmdtext);
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003524 //pi->cmdtext = NULL;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003525#endif
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003526
3527 next = pi->next;
3528 free(pi);
3529 return next;
Denis Vlasenkof886fd22008-10-13 12:36:05 +00003530}
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00003531
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003532static void free_pipe_list(struct pipe *pi)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003533{
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003534 while (pi) {
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003535#if HAS_KEYWORDS
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003536 debug_printf_clean("pipe reserved word %d\n", pi->res_word);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003537#endif
Denis Vlasenko0701dca2009-04-11 10:38:47 +00003538 debug_printf_clean("pipe followup code %d\n", pi->followup);
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003539 pi = free_pipe(pi);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003540 }
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003541}
3542
3543
Denys Vlasenkob36abf22010-09-05 14:50:59 +02003544/*** Parsing routines ***/
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00003545
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01003546#ifndef debug_print_tree
3547static void debug_print_tree(struct pipe *pi, int lvl)
3548{
3549 static const char *const PIPE[] = {
3550 [PIPE_SEQ] = "SEQ",
3551 [PIPE_AND] = "AND",
3552 [PIPE_OR ] = "OR" ,
3553 [PIPE_BG ] = "BG" ,
3554 };
3555 static const char *RES[] = {
3556 [RES_NONE ] = "NONE" ,
3557# if ENABLE_HUSH_IF
3558 [RES_IF ] = "IF" ,
3559 [RES_THEN ] = "THEN" ,
3560 [RES_ELIF ] = "ELIF" ,
3561 [RES_ELSE ] = "ELSE" ,
3562 [RES_FI ] = "FI" ,
3563# endif
3564# if ENABLE_HUSH_LOOPS
3565 [RES_FOR ] = "FOR" ,
3566 [RES_WHILE] = "WHILE",
3567 [RES_UNTIL] = "UNTIL",
3568 [RES_DO ] = "DO" ,
3569 [RES_DONE ] = "DONE" ,
3570# endif
3571# if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
3572 [RES_IN ] = "IN" ,
3573# endif
3574# if ENABLE_HUSH_CASE
3575 [RES_CASE ] = "CASE" ,
3576 [RES_CASE_IN ] = "CASE_IN" ,
3577 [RES_MATCH] = "MATCH",
3578 [RES_CASE_BODY] = "CASE_BODY",
3579 [RES_ESAC ] = "ESAC" ,
3580# endif
3581 [RES_XXXX ] = "XXXX" ,
3582 [RES_SNTX ] = "SNTX" ,
3583 };
3584 static const char *const CMDTYPE[] = {
3585 "{}",
3586 "()",
3587 "[noglob]",
3588# if ENABLE_HUSH_FUNCTIONS
3589 "func()",
3590# endif
3591 };
3592
3593 int pin, prn;
3594
3595 pin = 0;
3596 while (pi) {
Denys Vlasenko5807e182018-02-08 19:19:04 +01003597 fdprintf(2, "%*spipe %d %sres_word=%s followup=%d %s\n",
3598 lvl*2, "",
3599 pin,
3600 (IF_HAS_KEYWORDS(pi->pi_inverted ? "! " :) ""),
3601 RES[pi->res_word],
3602 pi->followup, PIPE[pi->followup]
3603 );
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01003604 prn = 0;
3605 while (prn < pi->num_cmds) {
3606 struct command *command = &pi->cmds[prn];
3607 char **argv = command->argv;
3608
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01003609 fdprintf(2, "%*s cmd %d assignment_cnt:%d",
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01003610 lvl*2, "", prn,
3611 command->assignment_cnt);
Denys Vlasenko5807e182018-02-08 19:19:04 +01003612#if ENABLE_HUSH_LINENO_VAR
3613 fdprintf(2, " LINENO:%u", command->lineno);
3614#endif
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01003615 if (command->group) {
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01003616 fdprintf(2, " group %s: (argv=%p)%s%s\n",
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01003617 CMDTYPE[command->cmd_type],
3618 argv
3619# if !BB_MMU
3620 , " group_as_string:", command->group_as_string
3621# else
3622 , "", ""
3623# endif
3624 );
3625 debug_print_tree(command->group, lvl+1);
3626 prn++;
3627 continue;
3628 }
3629 if (argv) while (*argv) {
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01003630 fdprintf(2, " '%s'", *argv);
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01003631 argv++;
3632 }
Denys Vlasenko474cb202018-07-24 13:03:03 +02003633 if (command->redirects)
3634 fdprintf(2, " {redir}");
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01003635 fdprintf(2, "\n");
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01003636 prn++;
3637 }
3638 pi = pi->next;
3639 pin++;
3640 }
3641}
3642#endif /* debug_print_tree */
3643
Denis Vlasenkoac678ec2007-04-16 22:32:04 +00003644static struct pipe *new_pipe(void)
3645{
Eric Andersen25f27032001-04-26 23:22:31 +00003646 struct pipe *pi;
Denis Vlasenko3ac0e002007-04-28 16:45:22 +00003647 pi = xzalloc(sizeof(struct pipe));
Denis Vlasenko5ec61322008-06-24 00:50:07 +00003648 /*pi->res_word = RES_NONE; - RES_NONE is 0 anyway */
Eric Andersen25f27032001-04-26 23:22:31 +00003649 return pi;
3650}
3651
Denis Vlasenkof8c1f022009-04-17 11:55:42 +00003652/* Command (member of a pipe) is complete, or we start a new pipe
3653 * if ctx->command is NULL.
3654 * No errors possible here.
3655 */
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003656static int done_command(struct parse_context *ctx)
3657{
3658 /* The command is really already in the pipe structure, so
3659 * advance the pipe counter and make a new, null command. */
3660 struct pipe *pi = ctx->pipe;
3661 struct command *command = ctx->command;
3662
Denys Vlasenkod6a37d82016-09-20 16:22:24 +02003663#if 0 /* Instead we emit error message at run time */
3664 if (ctx->pending_redirect) {
3665 /* For example, "cmd >" (no filename to redirect to) */
Denys Vlasenko39701202017-08-02 19:44:05 +02003666 syntax_error("invalid redirect");
Denys Vlasenkod6a37d82016-09-20 16:22:24 +02003667 ctx->pending_redirect = NULL;
3668 }
3669#endif
3670
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003671 if (command) {
Denis Vlasenkof8c1f022009-04-17 11:55:42 +00003672 if (IS_NULL_CMD(command)) {
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003673 debug_printf_parse("done_command: skipping null cmd, num_cmds=%d\n", pi->num_cmds);
Denis Vlasenkof8c1f022009-04-17 11:55:42 +00003674 goto clear_and_ret;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003675 }
3676 pi->num_cmds++;
3677 debug_printf_parse("done_command: ++num_cmds=%d\n", pi->num_cmds);
Denis Vlasenkocd418a22009-04-06 18:08:35 +00003678 //debug_print_tree(ctx->list_head, 20);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003679 } else {
3680 debug_printf_parse("done_command: initializing, num_cmds=%d\n", pi->num_cmds);
3681 }
3682
3683 /* Only real trickiness here is that the uncommitted
3684 * command structure is not counted in pi->num_cmds. */
3685 pi->cmds = xrealloc(pi->cmds, sizeof(*pi->cmds) * (pi->num_cmds+1));
Denis Vlasenkof8c1f022009-04-17 11:55:42 +00003686 ctx->command = command = &pi->cmds[pi->num_cmds];
3687 clear_and_ret:
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003688 memset(command, 0, sizeof(*command));
Denys Vlasenko5807e182018-02-08 19:19:04 +01003689#if ENABLE_HUSH_LINENO_VAR
Denys Vlasenko6aad1dd2018-01-19 15:37:04 +01003690 command->lineno = G.lineno;
Denys Vlasenko5807e182018-02-08 19:19:04 +01003691 debug_printf_parse("command->lineno = G.lineno (%u)\n", G.lineno);
Denys Vlasenko6aad1dd2018-01-19 15:37:04 +01003692#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003693 return pi->num_cmds; /* used only for 0/nonzero check */
3694}
3695
3696static void done_pipe(struct parse_context *ctx, pipe_style type)
3697{
3698 int not_null;
3699
3700 debug_printf_parse("done_pipe entered, followup %d\n", type);
3701 /* Close previous command */
3702 not_null = done_command(ctx);
Denis Vlasenkocd418a22009-04-06 18:08:35 +00003703#if HAS_KEYWORDS
3704 ctx->pipe->pi_inverted = ctx->ctx_inverted;
3705 ctx->ctx_inverted = 0;
3706 ctx->pipe->res_word = ctx->ctx_res_w;
3707#endif
Denys Vlasenkob24e55d2017-07-16 20:29:35 +02003708 if (type == PIPE_BG && ctx->list_head != ctx->pipe) {
3709 /* Necessary since && and || have precedence over &:
Denys Vlasenkoee553b92017-07-15 22:51:55 +02003710 * "cmd1 && cmd2 &" must spawn both cmds, not only cmd2,
3711 * in a backgrounded subshell.
3712 */
3713 struct pipe *pi;
3714 struct command *command;
3715
Denys Vlasenkob24e55d2017-07-16 20:29:35 +02003716 /* Is this actually this construct, all pipes end with && or ||? */
Denys Vlasenkoee553b92017-07-15 22:51:55 +02003717 pi = ctx->list_head;
3718 while (pi != ctx->pipe) {
3719 if (pi->followup != PIPE_AND && pi->followup != PIPE_OR)
3720 goto no_conv;
3721 pi = pi->next;
3722 }
3723
3724 debug_printf_parse("BG with more than one pipe, converting to { p1 &&...pN; } &\n");
3725 pi->followup = PIPE_SEQ; /* close pN _not_ with "&"! */
3726 pi = xzalloc(sizeof(*pi));
3727 pi->followup = PIPE_BG;
3728 pi->num_cmds = 1;
3729 pi->cmds = xzalloc(sizeof(pi->cmds[0]));
3730 command = &pi->cmds[0];
3731 if (CMD_NORMAL != 0) /* "if xzalloc didn't do that already" */
3732 command->cmd_type = CMD_NORMAL;
3733 command->group = ctx->list_head;
3734#if !BB_MMU
Denys Vlasenkob24e55d2017-07-16 20:29:35 +02003735 command->group_as_string = xstrndup(
3736 ctx->as_string.data,
3737 ctx->as_string.length - 1 /* do not copy last char, "&" */
3738 );
Denys Vlasenkoee553b92017-07-15 22:51:55 +02003739#endif
3740 /* Replace all pipes in ctx with one newly created */
3741 ctx->list_head = ctx->pipe = pi;
Denys Vlasenkob24e55d2017-07-16 20:29:35 +02003742 } else {
3743 no_conv:
3744 ctx->pipe->followup = type;
Denys Vlasenkoee553b92017-07-15 22:51:55 +02003745 }
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003746
3747 /* Without this check, even just <enter> on command line generates
3748 * tree of three NOPs (!). Which is harmless but annoying.
Denis Vlasenkof8c1f022009-04-17 11:55:42 +00003749 * IOW: it is safe to do it unconditionally. */
Denis Vlasenkocd418a22009-04-06 18:08:35 +00003750 if (not_null
Denis Vlasenko7f959372009-04-14 08:06:59 +00003751#if ENABLE_HUSH_IF
Denis Vlasenkocd418a22009-04-06 18:08:35 +00003752 || ctx->ctx_res_w == RES_FI
Denis Vlasenko7f959372009-04-14 08:06:59 +00003753#endif
3754#if ENABLE_HUSH_LOOPS
Denis Vlasenkocd418a22009-04-06 18:08:35 +00003755 || ctx->ctx_res_w == RES_DONE
3756 || ctx->ctx_res_w == RES_FOR
3757 || ctx->ctx_res_w == RES_IN
Denis Vlasenko7f959372009-04-14 08:06:59 +00003758#endif
3759#if ENABLE_HUSH_CASE
Denis Vlasenkocd418a22009-04-06 18:08:35 +00003760 || ctx->ctx_res_w == RES_ESAC
3761#endif
3762 ) {
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003763 struct pipe *new_p;
3764 debug_printf_parse("done_pipe: adding new pipe: "
3765 "not_null:%d ctx->ctx_res_w:%d\n",
3766 not_null, ctx->ctx_res_w);
3767 new_p = new_pipe();
3768 ctx->pipe->next = new_p;
3769 ctx->pipe = new_p;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003770 /* RES_THEN, RES_DO etc are "sticky" -
Denis Vlasenkof8c1f022009-04-17 11:55:42 +00003771 * they remain set for pipes inside if/while.
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003772 * This is used to control execution.
3773 * RES_FOR and RES_IN are NOT sticky (needed to support
3774 * cases where variable or value happens to match a keyword):
3775 */
3776#if ENABLE_HUSH_LOOPS
3777 if (ctx->ctx_res_w == RES_FOR
3778 || ctx->ctx_res_w == RES_IN)
3779 ctx->ctx_res_w = RES_NONE;
3780#endif
3781#if ENABLE_HUSH_CASE
3782 if (ctx->ctx_res_w == RES_MATCH)
Denys Vlasenkoe9bda902009-05-23 16:50:07 +02003783 ctx->ctx_res_w = RES_CASE_BODY;
3784 if (ctx->ctx_res_w == RES_CASE)
3785 ctx->ctx_res_w = RES_CASE_IN;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003786#endif
Denis Vlasenkob6e65562009-04-03 16:49:04 +00003787 ctx->command = NULL; /* trick done_command below */
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003788 /* Create the memory for command, roughly:
3789 * ctx->pipe->cmds = new struct command;
3790 * ctx->command = &ctx->pipe->cmds[0];
3791 */
3792 done_command(ctx);
Denis Vlasenkocd418a22009-04-06 18:08:35 +00003793 //debug_print_tree(ctx->list_head, 10);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003794 }
3795 debug_printf_parse("done_pipe return\n");
3796}
3797
Denis Vlasenko9af22c72008-10-09 12:54:58 +00003798static void initialize_context(struct parse_context *ctx)
Eric Andersen25f27032001-04-26 23:22:31 +00003799{
Denis Vlasenkoa8442002008-06-14 11:00:17 +00003800 memset(ctx, 0, sizeof(*ctx));
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02003801 if (MAYBE_ASSIGNMENT != 0)
3802 ctx->is_assignment = MAYBE_ASSIGNMENT;
Denis Vlasenko1a735862007-05-23 00:32:25 +00003803 ctx->pipe = ctx->list_head = new_pipe();
Denis Vlasenko9af22c72008-10-09 12:54:58 +00003804 /* Create the memory for command, roughly:
3805 * ctx->pipe->cmds = new struct command;
3806 * ctx->command = &ctx->pipe->cmds[0];
Denis Vlasenkoa8442002008-06-14 11:00:17 +00003807 */
3808 done_command(ctx);
Eric Andersen25f27032001-04-26 23:22:31 +00003809}
3810
Denis Vlasenkoa8442002008-06-14 11:00:17 +00003811/* If a reserved word is found and processed, parse context is modified
3812 * and 1 is returned.
Eric Andersen25f27032001-04-26 23:22:31 +00003813 */
Denis Vlasenko5ec61322008-06-24 00:50:07 +00003814#if HAS_KEYWORDS
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003815struct reserved_combo {
3816 char literal[6];
3817 unsigned char res;
3818 unsigned char assignment_flag;
3819 int flag;
3820};
3821enum {
3822 FLAG_END = (1 << RES_NONE ),
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003823# if ENABLE_HUSH_IF
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003824 FLAG_IF = (1 << RES_IF ),
3825 FLAG_THEN = (1 << RES_THEN ),
3826 FLAG_ELIF = (1 << RES_ELIF ),
3827 FLAG_ELSE = (1 << RES_ELSE ),
3828 FLAG_FI = (1 << RES_FI ),
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003829# endif
3830# if ENABLE_HUSH_LOOPS
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003831 FLAG_FOR = (1 << RES_FOR ),
3832 FLAG_WHILE = (1 << RES_WHILE),
3833 FLAG_UNTIL = (1 << RES_UNTIL),
3834 FLAG_DO = (1 << RES_DO ),
3835 FLAG_DONE = (1 << RES_DONE ),
3836 FLAG_IN = (1 << RES_IN ),
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003837# endif
3838# if ENABLE_HUSH_CASE
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003839 FLAG_MATCH = (1 << RES_MATCH),
3840 FLAG_ESAC = (1 << RES_ESAC ),
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003841# endif
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003842 FLAG_START = (1 << RES_XXXX ),
3843};
3844
3845static const struct reserved_combo* match_reserved_word(o_string *word)
3846{
Eric Andersen25f27032001-04-26 23:22:31 +00003847 /* Mostly a list of accepted follow-up reserved words.
3848 * FLAG_END means we are done with the sequence, and are ready
3849 * to turn the compound list into a command.
3850 * FLAG_START means the word must start a new compound list.
3851 */
Denis Vlasenkoc72c1ed2007-01-30 22:31:26 +00003852 static const struct reserved_combo reserved_list[] = {
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003853# if ENABLE_HUSH_IF
Denys Vlasenko29f9b722011-05-14 11:27:36 +02003854 { "!", RES_NONE, NOT_ASSIGNMENT , 0 },
3855 { "if", RES_IF, MAYBE_ASSIGNMENT, FLAG_THEN | FLAG_START },
3856 { "then", RES_THEN, MAYBE_ASSIGNMENT, FLAG_ELIF | FLAG_ELSE | FLAG_FI },
3857 { "elif", RES_ELIF, MAYBE_ASSIGNMENT, FLAG_THEN },
3858 { "else", RES_ELSE, MAYBE_ASSIGNMENT, FLAG_FI },
3859 { "fi", RES_FI, NOT_ASSIGNMENT , FLAG_END },
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003860# endif
3861# if ENABLE_HUSH_LOOPS
Denys Vlasenko29f9b722011-05-14 11:27:36 +02003862 { "for", RES_FOR, NOT_ASSIGNMENT , FLAG_IN | FLAG_DO | FLAG_START },
3863 { "while", RES_WHILE, MAYBE_ASSIGNMENT, FLAG_DO | FLAG_START },
3864 { "until", RES_UNTIL, MAYBE_ASSIGNMENT, FLAG_DO | FLAG_START },
3865 { "in", RES_IN, NOT_ASSIGNMENT , FLAG_DO },
3866 { "do", RES_DO, MAYBE_ASSIGNMENT, FLAG_DONE },
3867 { "done", RES_DONE, NOT_ASSIGNMENT , FLAG_END },
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003868# endif
3869# if ENABLE_HUSH_CASE
Denys Vlasenko29f9b722011-05-14 11:27:36 +02003870 { "case", RES_CASE, NOT_ASSIGNMENT , FLAG_MATCH | FLAG_START },
3871 { "esac", RES_ESAC, NOT_ASSIGNMENT , FLAG_END },
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003872# endif
Eric Andersen25f27032001-04-26 23:22:31 +00003873 };
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003874 const struct reserved_combo *r;
3875
Denys Vlasenkoe4dcba12010-10-28 18:57:19 +02003876 for (r = reserved_list; r < reserved_list + ARRAY_SIZE(reserved_list); r++) {
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003877 if (strcmp(word->data, r->literal) == 0)
3878 return r;
3879 }
3880 return NULL;
3881}
Denys Vlasenko5807e182018-02-08 19:19:04 +01003882/* Return NULL: not a keyword, else: keyword
Denis Vlasenkobb929512009-04-16 10:59:40 +00003883 */
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02003884static const struct reserved_combo* reserved_word(struct parse_context *ctx)
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003885{
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003886# if ENABLE_HUSH_CASE
Denis Vlasenko17f02e72008-07-14 04:32:29 +00003887 static const struct reserved_combo reserved_match = {
Denis Vlasenko2b576b82008-08-04 00:46:07 +00003888 "", RES_MATCH, NOT_ASSIGNMENT , FLAG_MATCH | FLAG_ESAC
Denis Vlasenko17f02e72008-07-14 04:32:29 +00003889 };
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003890# endif
Denis Vlasenkoc72c1ed2007-01-30 22:31:26 +00003891 const struct reserved_combo *r;
Denis Vlasenkoc72c1ed2007-01-30 22:31:26 +00003892
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02003893 if (ctx->word.has_quoted_part)
Denis Vlasenkobb929512009-04-16 10:59:40 +00003894 return 0;
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02003895 r = match_reserved_word(&ctx->word);
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003896 if (!r)
Denys Vlasenko5807e182018-02-08 19:19:04 +01003897 return r; /* NULL */
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003898
3899 debug_printf("found reserved word %s, res %d\n", r->literal, r->res);
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003900# if ENABLE_HUSH_CASE
Denys Vlasenkoe9bda902009-05-23 16:50:07 +02003901 if (r->res == RES_IN && ctx->ctx_res_w == RES_CASE_IN) {
3902 /* "case word IN ..." - IN part starts first MATCH part */
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003903 r = &reserved_match;
Denys Vlasenkoe9bda902009-05-23 16:50:07 +02003904 } else
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003905# endif
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003906 if (r->flag == 0) { /* '!' */
3907 if (ctx->ctx_inverted) { /* bash doesn't accept '! ! true' */
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00003908 syntax_error("! ! command");
Denis Vlasenkobb929512009-04-16 10:59:40 +00003909 ctx->ctx_res_w = RES_SNTX;
Eric Andersen25f27032001-04-26 23:22:31 +00003910 }
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003911 ctx->ctx_inverted = 1;
Denys Vlasenko5807e182018-02-08 19:19:04 +01003912 return r;
Eric Andersen25f27032001-04-26 23:22:31 +00003913 }
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003914 if (r->flag & FLAG_START) {
Denis Vlasenkob6e65562009-04-03 16:49:04 +00003915 struct parse_context *old;
Denis Vlasenkobb929512009-04-16 10:59:40 +00003916
Denys Vlasenko9e55a152017-07-10 10:01:12 +02003917 old = xmemdup(ctx, sizeof(*ctx));
Denis Vlasenkob6e65562009-04-03 16:49:04 +00003918 debug_printf_parse("push stack %p\n", old);
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003919 initialize_context(ctx);
Denis Vlasenkob6e65562009-04-03 16:49:04 +00003920 ctx->stack = old;
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003921 } else if (/*ctx->ctx_res_w == RES_NONE ||*/ !(ctx->old_flag & (1 << r->res))) {
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02003922 syntax_error_at(ctx->word.data);
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003923 ctx->ctx_res_w = RES_SNTX;
Denys Vlasenko5807e182018-02-08 19:19:04 +01003924 return r;
Denis Vlasenkobb929512009-04-16 10:59:40 +00003925 } else {
3926 /* "{...} fi" is ok. "{...} if" is not
3927 * Example:
3928 * if { echo foo; } then { echo bar; } fi */
3929 if (ctx->command->group)
3930 done_pipe(ctx, PIPE_SEQ);
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003931 }
Denis Vlasenkobb929512009-04-16 10:59:40 +00003932
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003933 ctx->ctx_res_w = r->res;
3934 ctx->old_flag = r->flag;
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02003935 ctx->is_assignment = r->assignment_flag;
3936 debug_printf_parse("ctx->is_assignment='%s'\n", assignment_flag[ctx->is_assignment]);
Denis Vlasenkobb929512009-04-16 10:59:40 +00003937
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003938 if (ctx->old_flag & FLAG_END) {
3939 struct parse_context *old;
Denis Vlasenkobb929512009-04-16 10:59:40 +00003940
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003941 done_pipe(ctx, PIPE_SEQ);
Denis Vlasenkob6e65562009-04-03 16:49:04 +00003942 debug_printf_parse("pop stack %p\n", ctx->stack);
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003943 old = ctx->stack;
3944 old->command->group = ctx->list_head;
Denys Vlasenko9d617c42009-06-09 18:40:52 +02003945 old->command->cmd_type = CMD_NORMAL;
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003946# if !BB_MMU
Denys Vlasenkob5be13c2015-09-04 06:22:10 +02003947 /* At this point, the compound command's string is in
3948 * ctx->as_string... except for the leading keyword!
3949 * Consider this example: "echo a | if true; then echo a; fi"
3950 * ctx->as_string will contain "true; then echo a; fi",
3951 * with "if " remaining in old->as_string!
3952 */
3953 {
3954 char *str;
3955 int len = old->as_string.length;
3956 /* Concatenate halves */
3957 o_addstr(&old->as_string, ctx->as_string.data);
Denys Vlasenko18567402018-07-20 17:51:31 +02003958 o_free(&ctx->as_string);
Denys Vlasenkob5be13c2015-09-04 06:22:10 +02003959 /* Find where leading keyword starts in first half */
3960 str = old->as_string.data + len;
3961 if (str > old->as_string.data)
3962 str--; /* skip whitespace after keyword */
3963 while (str > old->as_string.data && isalpha(str[-1]))
3964 str--;
3965 /* Ugh, we're done with this horrid hack */
3966 old->command->group_as_string = xstrdup(str);
3967 debug_printf_parse("pop, remembering as:'%s'\n",
3968 old->command->group_as_string);
3969 }
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003970# endif
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003971 *ctx = *old; /* physical copy */
3972 free(old);
3973 }
Denys Vlasenko5807e182018-02-08 19:19:04 +01003974 return r;
Eric Andersen25f27032001-04-26 23:22:31 +00003975}
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003976#endif /* HAS_KEYWORDS */
Eric Andersen25f27032001-04-26 23:22:31 +00003977
Denis Vlasenkoa8442002008-06-14 11:00:17 +00003978/* Word is complete, look at it and update parsing context.
Denis Vlasenkob6e65562009-04-03 16:49:04 +00003979 * Normal return is 0. Syntax errors return 1.
3980 * Note: on return, word is reset, but not o_free'd!
3981 */
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02003982static int done_word(struct parse_context *ctx)
Eric Andersen25f27032001-04-26 23:22:31 +00003983{
Denis Vlasenko9af22c72008-10-09 12:54:58 +00003984 struct command *command = ctx->command;
Eric Andersen25f27032001-04-26 23:22:31 +00003985
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02003986 debug_printf_parse("done_word entered: '%s' %p\n", ctx->word.data, command);
3987 if (ctx->word.length == 0 && !ctx->word.has_quoted_part) {
Denis Vlasenkoab876cd2008-06-18 16:29:32 +00003988 debug_printf_parse("done_word return 0: true null, ignored\n");
3989 return 0;
Eric Andersen25f27032001-04-26 23:22:31 +00003990 }
Denis Vlasenko2b576b82008-08-04 00:46:07 +00003991
Eric Andersen25f27032001-04-26 23:22:31 +00003992 if (ctx->pending_redirect) {
Denis Vlasenkoab876cd2008-06-18 16:29:32 +00003993 /* We do not glob in e.g. >*.tmp case. bash seems to glob here
3994 * only if run as "bash", not "sh" */
Denys Vlasenkoe84212f2018-04-01 20:11:23 +02003995 /* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003996 * "2.7 Redirection
Denys Vlasenkoe84212f2018-04-01 20:11:23 +02003997 * If the redirection operator is "<<" or "<<-", the word
3998 * that follows the redirection operator shall be
3999 * subjected to quote removal; it is unspecified whether
4000 * any of the other expansions occur. For the other
4001 * redirection operators, the word that follows the
4002 * redirection operator shall be subjected to tilde
4003 * expansion, parameter expansion, command substitution,
4004 * arithmetic expansion, and quote removal.
4005 * Pathname expansion shall not be performed
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004006 * on the word by a non-interactive shell; an interactive
4007 * shell may perform it, but shall do so only when
4008 * the expansion would result in one word."
4009 */
Denys Vlasenkobb6f5732018-04-01 18:55:00 +02004010//bash does not do parameter/command substitution or arithmetic expansion
4011//for _heredoc_ redirection word: these constructs look for exact eof marker
4012// as written:
4013// <<EOF$t
4014// <<EOF$((1))
Denys Vlasenkoe84212f2018-04-01 20:11:23 +02004015// <<EOF`true` [this case also makes heredoc "quoted", a-la <<"EOF". Probably bash-4.3.43 bug]
4016
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004017 ctx->pending_redirect->rd_filename = xstrdup(ctx->word.data);
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00004018 /* Cater for >\file case:
4019 * >\a creates file a; >\\a, >"\a", >"\\a" create file \a
4020 * Same with heredocs:
4021 * for <<\H delim is H; <<\\H, <<"\H", <<"\\H" - \H
4022 */
Denys Vlasenkoe640cb42009-05-28 16:49:11 +02004023 if (ctx->pending_redirect->rd_type == REDIRECT_HEREDOC) {
4024 unbackslash(ctx->pending_redirect->rd_filename);
4025 /* Is it <<"HEREDOC"? */
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004026 if (ctx->word.has_quoted_part) {
Denys Vlasenkoe640cb42009-05-28 16:49:11 +02004027 ctx->pending_redirect->rd_dup |= HEREDOC_QUOTED;
4028 }
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +00004029 }
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004030 debug_printf_parse("word stored in rd_filename: '%s'\n", ctx->word.data);
Denis Vlasenko1fd1ea42009-04-10 12:03:20 +00004031 ctx->pending_redirect = NULL;
Eric Andersen25f27032001-04-26 23:22:31 +00004032 } else {
Denis Vlasenko5ec61322008-06-24 00:50:07 +00004033#if HAS_KEYWORDS
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00004034# if ENABLE_HUSH_CASE
Denis Vlasenko757361f2008-07-14 08:26:47 +00004035 if (ctx->ctx_dsemicolon
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004036 && strcmp(ctx->word.data, "esac") != 0 /* not "... pattern) cmd;; esac" */
Denis Vlasenko757361f2008-07-14 08:26:47 +00004037 ) {
Denis Vlasenko395ae452008-07-14 06:29:38 +00004038 /* already done when ctx_dsemicolon was set to 1: */
Denis Vlasenko17f02e72008-07-14 04:32:29 +00004039 /* ctx->ctx_res_w = RES_MATCH; */
4040 ctx->ctx_dsemicolon = 0;
4041 } else
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00004042# endif
Denis Vlasenko9af22c72008-10-09 12:54:58 +00004043 if (!command->argv /* if it's the first word... */
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00004044# if ENABLE_HUSH_LOOPS
Denis Vlasenko733e3fb2008-07-06 10:01:13 +00004045 && ctx->ctx_res_w != RES_FOR /* ...not after FOR or IN */
4046 && ctx->ctx_res_w != RES_IN
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00004047# endif
Denys Vlasenkoe9bda902009-05-23 16:50:07 +02004048# if ENABLE_HUSH_CASE
4049 && ctx->ctx_res_w != RES_CASE
4050# endif
Denis Vlasenko733e3fb2008-07-06 10:01:13 +00004051 ) {
Denys Vlasenko5807e182018-02-08 19:19:04 +01004052 const struct reserved_combo *reserved;
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004053 reserved = reserved_word(ctx);
Denys Vlasenko5807e182018-02-08 19:19:04 +01004054 debug_printf_parse("checking for reserved-ness: %d\n", !!reserved);
Denys Vlasenko29f9b722011-05-14 11:27:36 +02004055 if (reserved) {
Denys Vlasenko5807e182018-02-08 19:19:04 +01004056# if ENABLE_HUSH_LINENO_VAR
4057/* Case:
4058 * "while ...; do
4059 * cmd ..."
4060 * If we don't close the pipe _now_, immediately after "do", lineno logic
4061 * sees "cmd" as starting at "do" - i.e., at the previous line.
4062 */
4063 if (0
4064 IF_HUSH_IF(|| reserved->res == RES_THEN)
4065 IF_HUSH_IF(|| reserved->res == RES_ELIF)
4066 IF_HUSH_IF(|| reserved->res == RES_ELSE)
4067 IF_HUSH_LOOPS(|| reserved->res == RES_DO)
4068 ) {
4069 done_pipe(ctx, PIPE_SEQ);
4070 }
4071# endif
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004072 o_reset_to_empty_unquoted(&ctx->word);
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004073 debug_printf_parse("done_word return %d\n",
4074 (ctx->ctx_res_w == RES_SNTX));
Denis Vlasenko5ec61322008-06-24 00:50:07 +00004075 return (ctx->ctx_res_w == RES_SNTX);
Denis Vlasenkoe725bfe2007-05-03 22:45:39 +00004076 }
Denys Vlasenko11752d42018-04-03 08:20:58 +02004077# if defined(CMD_SINGLEWORD_NOGLOB)
4078 if (0
4079# if BASH_TEST2
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004080 || strcmp(ctx->word.data, "[[") == 0
Denys Vlasenko11752d42018-04-03 08:20:58 +02004081# endif
4082 /* In bash, local/export/readonly are special, args
4083 * are assignments and therefore expansion of them
4084 * should be "one-word" expansion:
4085 * $ export i=`echo 'a b'` # one arg: "i=a b"
4086 * compare with:
4087 * $ ls i=`echo 'a b'` # two args: "i=a" and "b"
4088 * ls: cannot access i=a: No such file or directory
4089 * ls: cannot access b: No such file or directory
4090 * Note: bash 3.2.33(1) does this only if export word
4091 * itself is not quoted:
4092 * $ export i=`echo 'aaa bbb'`; echo "$i"
4093 * aaa bbb
4094 * $ "export" i=`echo 'aaa bbb'`; echo "$i"
4095 * aaa
4096 */
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004097 IF_HUSH_LOCAL( || strcmp(ctx->word.data, "local") == 0)
4098 IF_HUSH_EXPORT( || strcmp(ctx->word.data, "export") == 0)
4099 IF_HUSH_READONLY(|| strcmp(ctx->word.data, "readonly") == 0)
Denys Vlasenko11752d42018-04-03 08:20:58 +02004100 ) {
Denys Vlasenko9d617c42009-06-09 18:40:52 +02004101 command->cmd_type = CMD_SINGLEWORD_NOGLOB;
4102 }
4103 /* fall through */
Denys Vlasenko9ca656b2009-06-10 13:39:35 +02004104# endif
Eric Andersen25f27032001-04-26 23:22:31 +00004105 }
Denys Vlasenko11752d42018-04-03 08:20:58 +02004106#endif /* HAS_KEYWORDS */
4107
Denis Vlasenkobb929512009-04-16 10:59:40 +00004108 if (command->group) {
4109 /* "{ echo foo; } echo bar" - bad */
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004110 syntax_error_at(ctx->word.data);
Denis Vlasenkobb929512009-04-16 10:59:40 +00004111 debug_printf_parse("done_word return 1: syntax error, "
4112 "groups and arglists don't mix\n");
4113 return 1;
4114 }
Denys Vlasenko29f9b722011-05-14 11:27:36 +02004115
4116 /* If this word wasn't an assignment, next ones definitely
4117 * can't be assignments. Even if they look like ones. */
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004118 if (ctx->is_assignment != DEFINITELY_ASSIGNMENT
4119 && ctx->is_assignment != WORD_IS_KEYWORD
Denys Vlasenko29f9b722011-05-14 11:27:36 +02004120 ) {
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004121 ctx->is_assignment = NOT_ASSIGNMENT;
Denys Vlasenko29f9b722011-05-14 11:27:36 +02004122 } else {
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004123 if (ctx->is_assignment == DEFINITELY_ASSIGNMENT) {
Denys Vlasenko29f9b722011-05-14 11:27:36 +02004124 command->assignment_cnt++;
4125 debug_printf_parse("++assignment_cnt=%d\n", command->assignment_cnt);
4126 }
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004127 debug_printf_parse("ctx->is_assignment was:'%s'\n", assignment_flag[ctx->is_assignment]);
4128 ctx->is_assignment = MAYBE_ASSIGNMENT;
Denys Vlasenko29f9b722011-05-14 11:27:36 +02004129 }
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004130 debug_printf_parse("ctx->is_assignment='%s'\n", assignment_flag[ctx->is_assignment]);
4131 command->argv = add_string_to_strings(command->argv, xstrdup(ctx->word.data));
Denis Vlasenko9af22c72008-10-09 12:54:58 +00004132 debug_print_strings("word appended to argv", command->argv);
Denis Vlasenkoe725bfe2007-05-03 22:45:39 +00004133 }
Eric Andersen25f27032001-04-26 23:22:31 +00004134
Denis Vlasenko06810332007-05-21 23:30:54 +00004135#if ENABLE_HUSH_LOOPS
Denis Vlasenko733e3fb2008-07-06 10:01:13 +00004136 if (ctx->ctx_res_w == RES_FOR) {
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004137 if (ctx->word.has_quoted_part
Denis Vlasenko1fd1ea42009-04-10 12:03:20 +00004138 || !is_well_formed_var_name(command->argv[0], '\0')
4139 ) {
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +00004140 /* bash says just "not a valid identifier" */
Denis Vlasenko1fd1ea42009-04-10 12:03:20 +00004141 syntax_error("not a valid identifier in for");
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00004142 return 1;
4143 }
Denis Vlasenko1fd1ea42009-04-10 12:03:20 +00004144 /* Force FOR to have just one word (variable name) */
4145 /* NB: basically, this makes hush see "for v in ..."
4146 * syntax as if it is "for v; in ...". FOR and IN become
4147 * two pipe structs in parse tree. */
Denis Vlasenkofbf6dea2007-04-13 19:56:56 +00004148 done_pipe(ctx, PIPE_SEQ);
Denis Vlasenko733e3fb2008-07-06 10:01:13 +00004149 }
Denis Vlasenko06810332007-05-21 23:30:54 +00004150#endif
Denis Vlasenko17f02e72008-07-14 04:32:29 +00004151#if ENABLE_HUSH_CASE
4152 /* Force CASE to have just one word */
4153 if (ctx->ctx_res_w == RES_CASE) {
4154 done_pipe(ctx, PIPE_SEQ);
4155 }
4156#endif
Denis Vlasenko1fd1ea42009-04-10 12:03:20 +00004157
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004158 o_reset_to_empty_unquoted(&ctx->word);
Denis Vlasenko1fd1ea42009-04-10 12:03:20 +00004159
Denis Vlasenkoe725bfe2007-05-03 22:45:39 +00004160 debug_printf_parse("done_word return 0\n");
Eric Andersen25f27032001-04-26 23:22:31 +00004161 return 0;
4162}
4163
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004164
4165/* Peek ahead in the input to find out if we have a "&n" construct,
4166 * as in "2>&1", that represents duplicating a file descriptor.
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00004167 * Return:
4168 * REDIRFD_CLOSE if >&- "close fd" construct is seen,
4169 * REDIRFD_SYNTAX_ERR if syntax error,
4170 * REDIRFD_TO_FILE if no & was seen,
4171 * or the number found.
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004172 */
4173#if BB_MMU
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00004174#define parse_redir_right_fd(as_string, input) \
4175 parse_redir_right_fd(input)
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004176#endif
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00004177static int parse_redir_right_fd(o_string *as_string, struct in_str *input)
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004178{
4179 int ch, d, ok;
4180
4181 ch = i_peek(input);
4182 if (ch != '&')
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00004183 return REDIRFD_TO_FILE;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004184
4185 ch = i_getch(input); /* get the & */
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004186 nommu_addchr(as_string, ch);
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004187 ch = i_peek(input);
4188 if (ch == '-') {
4189 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004190 nommu_addchr(as_string, ch);
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +00004191 return REDIRFD_CLOSE;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004192 }
4193 d = 0;
4194 ok = 0;
4195 while (ch != EOF && isdigit(ch)) {
4196 d = d*10 + (ch-'0');
4197 ok = 1;
4198 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004199 nommu_addchr(as_string, ch);
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004200 ch = i_peek(input);
4201 }
4202 if (ok) return d;
4203
4204//TODO: this is the place to catch ">&file" bashism (redirect both fd 1 and 2)
4205
4206 bb_error_msg("ambiguous redirect");
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00004207 return REDIRFD_SYNTAX_ERR;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004208}
4209
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00004210/* Return code is 0 normal, 1 if a syntax error is detected
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004211 */
4212static int parse_redirect(struct parse_context *ctx,
4213 int fd,
4214 redir_type style,
4215 struct in_str *input)
4216{
4217 struct command *command = ctx->command;
4218 struct redir_struct *redir;
4219 struct redir_struct **redirp;
4220 int dup_num;
4221
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00004222 dup_num = REDIRFD_TO_FILE;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004223 if (style != REDIRECT_HEREDOC) {
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00004224 /* Check for a '>&1' type redirect */
4225 dup_num = parse_redir_right_fd(&ctx->as_string, input);
4226 if (dup_num == REDIRFD_SYNTAX_ERR)
4227 return 1;
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004228 } else {
Denys Vlasenkoa94eeb02018-03-31 20:16:31 +02004229 int ch = i_peek_and_eat_bkslash_nl(input);
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +00004230 dup_num = (ch == '-'); /* HEREDOC_SKIPTABS bit is 1 */
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004231 if (dup_num) { /* <<-... */
4232 ch = i_getch(input);
4233 nommu_addchr(&ctx->as_string, ch);
4234 ch = i_peek(input);
4235 }
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004236 }
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004237
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00004238 if (style == REDIRECT_OVERWRITE && dup_num == REDIRFD_TO_FILE) {
Denys Vlasenkoa94eeb02018-03-31 20:16:31 +02004239 int ch = i_peek_and_eat_bkslash_nl(input);
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004240 if (ch == '|') {
4241 /* >|FILE redirect ("clobbering" >).
4242 * Since we do not support "set -o noclobber" yet,
4243 * >| and > are the same for now. Just eat |.
4244 */
4245 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004246 nommu_addchr(&ctx->as_string, ch);
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004247 }
4248 }
4249
4250 /* Create a new redir_struct and append it to the linked list */
4251 redirp = &command->redirects;
4252 while ((redir = *redirp) != NULL) {
4253 redirp = &(redir->next);
4254 }
4255 *redirp = redir = xzalloc(sizeof(*redir));
4256 /* redir->next = NULL; */
4257 /* redir->rd_filename = NULL; */
4258 redir->rd_type = style;
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004259 redir->rd_fd = (fd == -1) ? redir_table[style].default_fd : fd;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004260
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +00004261 debug_printf_parse("redirect type %d %s\n", redir->rd_fd,
4262 redir_table[style].descrip);
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004263
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004264 redir->rd_dup = dup_num;
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00004265 if (style != REDIRECT_HEREDOC && dup_num != REDIRFD_TO_FILE) {
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004266 /* Erik had a check here that the file descriptor in question
4267 * is legit; I postpone that to "run time"
4268 * A "-" representation of "close me" shows up as a -3 here */
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +00004269 debug_printf_parse("duplicating redirect '%d>&%d'\n",
4270 redir->rd_fd, redir->rd_dup);
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004271 } else {
Denys Vlasenkod6a37d82016-09-20 16:22:24 +02004272#if 0 /* Instead we emit error message at run time */
4273 if (ctx->pending_redirect) {
4274 /* For example, "cmd > <file" */
Denys Vlasenko39701202017-08-02 19:44:05 +02004275 syntax_error("invalid redirect");
Denys Vlasenkod6a37d82016-09-20 16:22:24 +02004276 }
4277#endif
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004278 /* Set ctx->pending_redirect, so we know what to do at the
4279 * end of the next parsed word. */
4280 ctx->pending_redirect = redir;
4281 }
4282 return 0;
4283}
4284
Eric Andersen25f27032001-04-26 23:22:31 +00004285/* If a redirect is immediately preceded by a number, that number is
4286 * supposed to tell which file descriptor to redirect. This routine
4287 * looks for such preceding numbers. In an ideal world this routine
4288 * needs to handle all the following classes of redirects...
4289 * echo 2>foo # redirects fd 2 to file "foo", nothing passed to echo
4290 * echo 49>foo # redirects fd 49 to file "foo", nothing passed to echo
4291 * echo -2>foo # redirects fd 1 to file "foo", "-2" passed to echo
4292 * echo 49x>foo # redirects fd 1 to file "foo", "49x" passed to echo
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004293 *
4294 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
4295 * "2.7 Redirection
4296 * ... If n is quoted, the number shall not be recognized as part of
4297 * the redirection expression. For example:
4298 * echo \2>a
4299 * writes the character 2 into file a"
Denys Vlasenko38292b62010-09-05 14:49:40 +02004300 * We are getting it right by setting ->has_quoted_part on any \<char>
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004301 *
4302 * A -1 return means no valid number was found,
4303 * the caller should use the appropriate default for this redirection.
Eric Andersen25f27032001-04-26 23:22:31 +00004304 */
4305static int redirect_opt_num(o_string *o)
4306{
4307 int num;
4308
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004309 if (o->data == NULL)
Denis Vlasenkobb81c582007-01-30 22:32:09 +00004310 return -1;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004311 num = bb_strtou(o->data, NULL, 10);
4312 if (errno || num < 0)
4313 return -1;
Denis Vlasenko0b677d82009-04-10 13:49:10 +00004314 o_reset_to_empty_unquoted(o);
Eric Andersen25f27032001-04-26 23:22:31 +00004315 return num;
4316}
4317
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004318#if BB_MMU
4319#define fetch_till_str(as_string, input, word, skip_tabs) \
4320 fetch_till_str(input, word, skip_tabs)
4321#endif
4322static char *fetch_till_str(o_string *as_string,
4323 struct in_str *input,
4324 const char *word,
Denys Vlasenko77b32cc2010-09-06 11:27:32 +02004325 int heredoc_flags)
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004326{
4327 o_string heredoc = NULL_O_STRING;
Denys Vlasenko5b6210c2010-09-09 13:32:21 +02004328 unsigned past_EOL;
Denys Vlasenko77b32cc2010-09-06 11:27:32 +02004329 int prev = 0; /* not \ */
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004330 int ch;
4331
Denys Vlasenkod73cdbf2018-07-23 15:43:57 +02004332 /* Starting with "" is necessary for this case:
4333 * cat <<EOF
4334 *
4335 * xxx
4336 * EOF
4337 */
4338 heredoc.data = xzalloc(1); /* start as "", not as NULL */
4339
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004340 goto jump_in;
Denys Vlasenkob8709032011-05-08 21:20:01 +02004341
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004342 while (1) {
4343 ch = i_getch(input);
Denys Vlasenko5b6210c2010-09-09 13:32:21 +02004344 if (ch != EOF)
4345 nommu_addchr(as_string, ch);
Denys Vlasenko0f018b32017-07-29 20:43:26 +02004346 if (ch == '\n' || ch == EOF) {
4347 check_heredoc_end:
4348 if ((heredoc_flags & HEREDOC_QUOTED) || prev != '\\') {
Denys Vlasenkodfc73942018-07-24 14:03:18 +02004349 /* End-of-line, and not a line continuation */
Denys Vlasenko0f018b32017-07-29 20:43:26 +02004350 if (strcmp(heredoc.data + past_EOL, word) == 0) {
4351 heredoc.data[past_EOL] = '\0';
Denys Vlasenko3675c372018-07-23 16:31:21 +02004352 debug_printf_heredoc("parsed '%s' heredoc '%s'\n", word, heredoc.data);
Denys Vlasenko0f018b32017-07-29 20:43:26 +02004353 return heredoc.data;
4354 }
4355 if (ch == '\n') {
4356 /* This is a new line.
4357 * Remember position and backslash-escaping status.
4358 */
4359 o_addchr(&heredoc, ch);
4360 prev = ch;
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004361 jump_in:
Denys Vlasenko0f018b32017-07-29 20:43:26 +02004362 past_EOL = heredoc.length;
4363 /* Get 1st char of next line, possibly skipping leading tabs */
4364 do {
4365 ch = i_getch(input);
4366 if (ch != EOF)
4367 nommu_addchr(as_string, ch);
4368 } while ((heredoc_flags & HEREDOC_SKIPTABS) && ch == '\t');
4369 /* If this immediately ended the line,
4370 * go back to end-of-line checks.
4371 */
4372 if (ch == '\n')
4373 goto check_heredoc_end;
4374 }
Denys Vlasenkodfc73942018-07-24 14:03:18 +02004375 } else {
4376 /* Backslash-line continuation in an unquoted
4377 * heredoc. This does not need special handling
4378 * for heredoc body (unquoted heredocs are
4379 * expanded on "execution" and that would take
4380 * care of this case too), but not the case
4381 * of line continuation *in terminator*:
4382 * cat <<EOF
4383 * Ok1
4384 * EO\
4385 * F
4386 */
4387 heredoc.data[--heredoc.length] = '\0';
4388 prev = 0; /* not '\' */
4389 continue;
Denys Vlasenko5b6210c2010-09-09 13:32:21 +02004390 }
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004391 }
4392 if (ch == EOF) {
Denys Vlasenko18567402018-07-20 17:51:31 +02004393 o_free(&heredoc);
Denys Vlasenkodfc73942018-07-24 14:03:18 +02004394 return NULL; /* error */
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004395 }
4396 o_addchr(&heredoc, ch);
Denys Vlasenko5b6210c2010-09-09 13:32:21 +02004397 nommu_addchr(as_string, ch);
Denys Vlasenkoc3adfac2010-09-06 11:46:03 +02004398 if (prev == '\\' && ch == '\\')
4399 /* Correctly handle foo\\<eol> (not a line cont.) */
Denys Vlasenkodfc73942018-07-24 14:03:18 +02004400 prev = 0; /* not '\' */
Denys Vlasenkoc3adfac2010-09-06 11:46:03 +02004401 else
4402 prev = ch;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004403 }
4404}
4405
Denis Vlasenko3dfb0352009-04-08 09:29:14 +00004406/* Look at entire parse tree for not-yet-loaded REDIRECT_HEREDOCs
4407 * and load them all. There should be exactly heredoc_cnt of them.
4408 */
Denys Vlasenko474cb202018-07-24 13:03:03 +02004409#if BB_MMU
4410#define fetch_heredocs(as_string, pi, heredoc_cnt, input) \
4411 fetch_heredocs(pi, heredoc_cnt, input)
4412#endif
4413static int fetch_heredocs(o_string *as_string, struct pipe *pi, int heredoc_cnt, struct in_str *input)
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004414{
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00004415 while (pi && heredoc_cnt) {
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004416 int i;
4417 struct command *cmd = pi->cmds;
4418
Denys Vlasenko3675c372018-07-23 16:31:21 +02004419 debug_printf_heredoc("fetch_heredocs: num_cmds:%d cmd argv0:'%s'\n",
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004420 pi->num_cmds,
Denys Vlasenko3675c372018-07-23 16:31:21 +02004421 cmd->argv ? cmd->argv[0] : "NONE"
4422 );
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004423 for (i = 0; i < pi->num_cmds; i++) {
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004424 struct redir_struct *redir = cmd->redirects;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004425
Denys Vlasenko3675c372018-07-23 16:31:21 +02004426 debug_printf_heredoc("fetch_heredocs: %d cmd argv0:'%s'\n",
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004427 i, cmd->argv ? cmd->argv[0] : "NONE");
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004428 while (redir) {
4429 if (redir->rd_type == REDIRECT_HEREDOC) {
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004430 char *p;
4431
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004432 redir->rd_type = REDIRECT_HEREDOC2;
Denys Vlasenko764b2f02009-06-07 16:05:04 +02004433 /* redir->rd_dup is (ab)used to indicate <<- */
Denys Vlasenko474cb202018-07-24 13:03:03 +02004434 p = fetch_till_str(as_string, input,
Denys Vlasenko77b32cc2010-09-06 11:27:32 +02004435 redir->rd_filename, redir->rd_dup);
Denis Vlasenko3dfb0352009-04-08 09:29:14 +00004436 if (!p) {
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00004437 syntax_error("unexpected EOF in here document");
Denys Vlasenko474cb202018-07-24 13:03:03 +02004438 return -1;
Denis Vlasenko3dfb0352009-04-08 09:29:14 +00004439 }
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004440 free(redir->rd_filename);
4441 redir->rd_filename = p;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004442 heredoc_cnt--;
4443 }
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004444 redir = redir->next;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004445 }
Denys Vlasenko474cb202018-07-24 13:03:03 +02004446 if (cmd->group) {
4447 //bb_error_msg("%s:%u heredoc_cnt:%d", __func__, __LINE__, heredoc_cnt);
4448 heredoc_cnt = fetch_heredocs(as_string, cmd->group, heredoc_cnt, input);
4449 //bb_error_msg("%s:%u heredoc_cnt:%d", __func__, __LINE__, heredoc_cnt);
4450 if (heredoc_cnt < 0)
4451 return heredoc_cnt; /* error */
4452 }
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004453 cmd++;
4454 }
4455 pi = pi->next;
4456 }
Denys Vlasenko474cb202018-07-24 13:03:03 +02004457 return heredoc_cnt;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004458}
4459
4460
Denys Vlasenkob36abf22010-09-05 14:50:59 +02004461static int run_list(struct pipe *pi);
4462#if BB_MMU
Denys Vlasenko474cb202018-07-24 13:03:03 +02004463#define parse_stream(pstring, heredoc_cnt_ptr, input, end_trigger) \
4464 parse_stream(heredoc_cnt_ptr, input, end_trigger)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02004465#endif
4466static struct pipe *parse_stream(char **pstring,
Denys Vlasenko474cb202018-07-24 13:03:03 +02004467 int *heredoc_cnt_ptr,
Denys Vlasenkob36abf22010-09-05 14:50:59 +02004468 struct in_str *input,
4469 int end_trigger);
Denis Vlasenkoba7cf262007-05-25 14:34:30 +00004470
Denys Vlasenko474cb202018-07-24 13:03:03 +02004471/* Returns number of heredocs not yet consumed,
4472 * or -1 on error.
4473 */
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004474static int parse_group(struct parse_context *ctx,
Denys Vlasenko474cb202018-07-24 13:03:03 +02004475 struct in_str *input, int ch)
Eric Andersen25f27032001-04-26 23:22:31 +00004476{
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004477 /* ctx->word contains characters seen prior to ( or {.
Denis Vlasenko027e3fd2009-04-02 22:50:40 +00004478 * Typically it's empty, but for function defs,
Denis Vlasenko371de4a2008-10-14 12:43:13 +00004479 * it contains function name (without '()'). */
Denys Vlasenkofbf44852018-04-03 14:56:52 +02004480#if BB_MMU
4481# define as_string NULL
4482#else
4483 char *as_string = NULL;
4484#endif
Denis Vlasenkob6e65562009-04-03 16:49:04 +00004485 struct pipe *pipe_list;
Denys Vlasenko474cb202018-07-24 13:03:03 +02004486 int heredoc_cnt = 0;
Denis Vlasenko240c2552009-04-03 03:45:05 +00004487 int endch;
Denis Vlasenko9af22c72008-10-09 12:54:58 +00004488 struct command *command = ctx->command;
Denis Vlasenkoe725bfe2007-05-03 22:45:39 +00004489
4490 debug_printf_parse("parse_group entered\n");
Denis Vlasenko371de4a2008-10-14 12:43:13 +00004491#if ENABLE_HUSH_FUNCTIONS
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004492 if (ch == '(' && !ctx->word.has_quoted_part) {
4493 if (ctx->word.length)
4494 if (done_word(ctx))
Denys Vlasenko474cb202018-07-24 13:03:03 +02004495 return -1;
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00004496 if (!command->argv)
4497 goto skip; /* (... */
4498 if (command->argv[1]) { /* word word ... (... */
4499 syntax_error_unexpected_ch('(');
Denys Vlasenko474cb202018-07-24 13:03:03 +02004500 return -1;
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +00004501 }
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00004502 /* it is "word(..." or "word (..." */
4503 do
4504 ch = i_getch(input);
4505 while (ch == ' ' || ch == '\t');
4506 if (ch != ')') {
4507 syntax_error_unexpected_ch(ch);
Denys Vlasenko474cb202018-07-24 13:03:03 +02004508 return -1;
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00004509 }
4510 nommu_addchr(&ctx->as_string, ch);
4511 do
4512 ch = i_getch(input);
4513 while (ch == ' ' || ch == '\t' || ch == '\n');
Denys Vlasenkofbf44852018-04-03 14:56:52 +02004514 if (ch != '{' && ch != '(') {
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00004515 syntax_error_unexpected_ch(ch);
Denys Vlasenko474cb202018-07-24 13:03:03 +02004516 return -1;
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00004517 }
4518 nommu_addchr(&ctx->as_string, ch);
Denys Vlasenko9d617c42009-06-09 18:40:52 +02004519 command->cmd_type = CMD_FUNCDEF;
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00004520 goto skip;
Denis Vlasenko371de4a2008-10-14 12:43:13 +00004521 }
4522#endif
Denys Vlasenkod8389ad2009-11-16 03:18:46 +01004523
4524#if 0 /* Prevented by caller */
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +00004525 if (command->argv /* word [word]{... */
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02004526 || ctx->word.length /* word{... */
4527 || ctx->word.has_quoted_part /* ""{... */
Denis Vlasenko9af22c72008-10-09 12:54:58 +00004528 ) {
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00004529 syntax_error(NULL);
Denys Vlasenko474cb202018-07-24 13:03:03 +02004530 debug_printf_parse("parse_group return -1: "
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004531 "syntax error, groups and arglists don't mix\n");
Denys Vlasenko474cb202018-07-24 13:03:03 +02004532 return -1;
Eric Andersen25f27032001-04-26 23:22:31 +00004533 }
Denys Vlasenkod8389ad2009-11-16 03:18:46 +01004534#endif
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +00004535
Denys Vlasenkofbf44852018-04-03 14:56:52 +02004536 IF_HUSH_FUNCTIONS(skip:)
4537
Denis Vlasenko240c2552009-04-03 03:45:05 +00004538 endch = '}';
Denis Vlasenko90e485c2007-05-23 15:22:50 +00004539 if (ch == '(') {
Denis Vlasenko240c2552009-04-03 03:45:05 +00004540 endch = ')';
Denys Vlasenkofbf44852018-04-03 14:56:52 +02004541 IF_HUSH_FUNCTIONS(if (command->cmd_type != CMD_FUNCDEF))
4542 command->cmd_type = CMD_SUBSHELL;
Denis Vlasenkof8c1f022009-04-17 11:55:42 +00004543 } else {
4544 /* bash does not allow "{echo...", requires whitespace */
Denys Vlasenko672a55e2016-11-04 18:46:14 +01004545 ch = i_peek(input);
4546 if (ch != ' ' && ch != '\t' && ch != '\n'
4547 && ch != '(' /* but "{(..." is allowed (without whitespace) */
4548 ) {
Denis Vlasenkof8c1f022009-04-17 11:55:42 +00004549 syntax_error_unexpected_ch(ch);
Denys Vlasenko474cb202018-07-24 13:03:03 +02004550 return -1;
Denis Vlasenkof8c1f022009-04-17 11:55:42 +00004551 }
Denys Vlasenko672a55e2016-11-04 18:46:14 +01004552 if (ch != '(') {
4553 ch = i_getch(input);
4554 nommu_addchr(&ctx->as_string, ch);
4555 }
Eric Andersen25f27032001-04-26 23:22:31 +00004556 }
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +00004557
Denys Vlasenko474cb202018-07-24 13:03:03 +02004558 debug_printf_heredoc("calling parse_stream, heredoc_cnt:%d\n", heredoc_cnt);
4559 pipe_list = parse_stream(&as_string, &heredoc_cnt, input, endch);
4560 debug_printf_heredoc("parse_stream returned: heredoc_cnt:%d\n", heredoc_cnt);
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00004561#if !BB_MMU
Denys Vlasenkofbf44852018-04-03 14:56:52 +02004562 if (as_string)
4563 o_addstr(&ctx->as_string, as_string);
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00004564#endif
Denys Vlasenkofbf44852018-04-03 14:56:52 +02004565
4566 /* empty ()/{} or parse error? */
4567 if (!pipe_list || pipe_list == ERR_PTR) {
4568 /* parse_stream already emitted error msg */
4569 if (!BB_MMU)
4570 free(as_string);
Denys Vlasenko474cb202018-07-24 13:03:03 +02004571 debug_printf_parse("parse_group return -1: "
Denys Vlasenkofbf44852018-04-03 14:56:52 +02004572 "parse_stream returned %p\n", pipe_list);
Denys Vlasenko474cb202018-07-24 13:03:03 +02004573 return -1;
Denis Vlasenkof8d01d32008-06-14 17:13:20 +00004574 }
Denys Vlasenkofbf44852018-04-03 14:56:52 +02004575#if !BB_MMU
4576 as_string[strlen(as_string) - 1] = '\0'; /* plink ')' or '}' */
4577 command->group_as_string = as_string;
4578 debug_printf_parse("end of group, remembering as:'%s'\n",
4579 command->group_as_string);
4580#endif
4581
4582#if ENABLE_HUSH_FUNCTIONS
4583 /* Convert "f() (cmds)" to "f() {(cmds)}" */
4584 if (command->cmd_type == CMD_FUNCDEF && endch == ')') {
4585 struct command *cmd2;
4586
4587 cmd2 = xzalloc(sizeof(*cmd2));
4588 cmd2->cmd_type = CMD_SUBSHELL;
4589 cmd2->group = pipe_list;
4590# if !BB_MMU
4591//UNTESTED!
4592 cmd2->group_as_string = command->group_as_string;
4593 command->group_as_string = xasprintf("(%s)", command->group_as_string);
4594# endif
4595
4596 pipe_list = new_pipe();
4597 pipe_list->cmds = cmd2;
4598 pipe_list->num_cmds = 1;
4599 }
4600#endif
4601
4602 command->group = pipe_list;
4603
Denys Vlasenko474cb202018-07-24 13:03:03 +02004604 debug_printf_parse("parse_group return %d\n", heredoc_cnt);
4605 return heredoc_cnt;
Denis Vlasenko9af22c72008-10-09 12:54:58 +00004606 /* command remains "open", available for possible redirects */
Denys Vlasenkofbf44852018-04-03 14:56:52 +02004607#undef as_string
Eric Andersen25f27032001-04-26 23:22:31 +00004608}
4609
Denys Vlasenko0b883582016-12-23 16:49:07 +01004610#if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004611/* Subroutines for copying $(...) and `...` things */
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004612/* '...' */
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004613static int add_till_single_quote(o_string *dest, struct in_str *input)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004614{
4615 while (1) {
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004616 int ch = i_getch(input);
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004617 if (ch == EOF) {
Denis Vlasenkod68ae082009-04-09 20:41:34 +00004618 syntax_error_unterm_ch('\'');
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004619 return 0;
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004620 }
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004621 if (ch == '\'')
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004622 return 1;
Denis Vlasenko82dfec32008-06-16 12:47:11 +00004623 o_addchr(dest, ch);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004624 }
4625}
Denys Vlasenko4c3c8a12018-07-20 19:11:09 +02004626static int add_till_single_quote_dquoted(o_string *dest, struct in_str *input)
4627{
4628 while (1) {
4629 int ch = i_getch(input);
4630 if (ch == EOF) {
4631 syntax_error_unterm_ch('\'');
4632 return 0;
4633 }
4634 if (ch == '\'')
4635 return 1;
4636 o_addqchr(dest, ch);
4637 }
4638}
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004639/* "...\"...`..`...." - do we need to handle "...$(..)..." too? */
Denys Vlasenko4c3c8a12018-07-20 19:11:09 +02004640static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote);
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004641static int add_till_double_quote(o_string *dest, struct in_str *input)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004642{
4643 while (1) {
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004644 int ch = i_getch(input);
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004645 if (ch == EOF) {
Denis Vlasenkod68ae082009-04-09 20:41:34 +00004646 syntax_error_unterm_ch('"');
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004647 return 0;
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004648 }
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004649 if (ch == '"')
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004650 return 1;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004651 if (ch == '\\') { /* \x. Copy both chars. */
Denis Vlasenko82dfec32008-06-16 12:47:11 +00004652 o_addchr(dest, ch);
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004653 ch = i_getch(input);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004654 }
Denis Vlasenko82dfec32008-06-16 12:47:11 +00004655 o_addchr(dest, ch);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004656 if (ch == '`') {
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004657 if (!add_till_backquote(dest, input, /*in_dquote:*/ 1))
4658 return 0;
Denis Vlasenko82dfec32008-06-16 12:47:11 +00004659 o_addchr(dest, ch);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004660 continue;
4661 }
Denis Vlasenko5703c222008-06-15 11:49:42 +00004662 //if (ch == '$') ...
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004663 }
4664}
4665/* Process `cmd` - copy contents until "`" is seen. Complicated by
4666 * \` quoting.
4667 * "Within the backquoted style of command substitution, backslash
4668 * shall retain its literal meaning, except when followed by: '$', '`', or '\'.
4669 * The search for the matching backquote shall be satisfied by the first
4670 * backquote found without a preceding backslash; during this search,
4671 * if a non-escaped backquote is encountered within a shell comment,
4672 * a here-document, an embedded command substitution of the $(command)
4673 * form, or a quoted string, undefined results occur. A single-quoted
4674 * or double-quoted string that begins, but does not end, within the
4675 * "`...`" sequence produces undefined results."
4676 * Example Output
4677 * echo `echo '\'TEST\`echo ZZ\`BEST` \TESTZZBEST
4678 */
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004679static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004680{
4681 while (1) {
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004682 int ch = i_getch(input);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004683 if (ch == '`')
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004684 return 1;
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004685 if (ch == '\\') {
Denys Vlasenkoacd5bc82010-09-12 15:05:39 +02004686 /* \x. Copy both unless it is \`, \$, \\ and maybe \" */
4687 ch = i_getch(input);
4688 if (ch != '`'
4689 && ch != '$'
4690 && ch != '\\'
4691 && (!in_dquote || ch != '"')
4692 ) {
4693 o_addchr(dest, '\\');
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004694 }
Denys Vlasenkoacd5bc82010-09-12 15:05:39 +02004695 }
4696 if (ch == EOF) {
4697 syntax_error_unterm_ch('`');
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004698 return 0;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004699 }
Denis Vlasenko82dfec32008-06-16 12:47:11 +00004700 o_addchr(dest, ch);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004701 }
4702}
4703/* Process $(cmd) - copy contents until ")" is seen. Complicated by
4704 * quoting and nested ()s.
4705 * "With the $(command) style of command substitution, all characters
4706 * following the open parenthesis to the matching closing parenthesis
4707 * constitute the command. Any valid shell script can be used for command,
4708 * except a script consisting solely of redirections which produces
4709 * unspecified results."
4710 * Example Output
4711 * echo $(echo '(TEST)' BEST) (TEST) BEST
4712 * echo $(echo 'TEST)' BEST) TEST) BEST
4713 * echo $(echo \(\(TEST\) BEST) ((TEST) BEST
Denys Vlasenko74369502010-05-21 19:52:01 +02004714 *
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004715 * Also adapted to eat ${var%...} and $((...)) constructs, since ... part
Denys Vlasenkoa6ad3972010-05-22 00:26:06 +02004716 * can contain arbitrary constructs, just like $(cmd).
Denys Vlasenko36f774a2010-09-05 14:45:38 +02004717 * In bash compat mode, it needs to also be able to stop on ':' or '/'
4718 * for ${var:N[:M]} and ${var/P[/R]} parsing.
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004719 */
Denys Vlasenko74369502010-05-21 19:52:01 +02004720#define DOUBLE_CLOSE_CHAR_FLAG 0x80
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004721static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsigned end_ch)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004722{
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004723 int ch;
Denys Vlasenko74369502010-05-21 19:52:01 +02004724 char dbl = end_ch & DOUBLE_CLOSE_CHAR_FLAG;
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01004725# if BASH_SUBSTR || BASH_PATTERN_SUBST
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004726 char end_char2 = end_ch >> 8;
Denys Vlasenko9297dbc2010-07-05 21:37:12 +02004727# endif
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004728 end_ch &= (DOUBLE_CLOSE_CHAR_FLAG - 1);
4729
Denys Vlasenko817a2022018-06-26 15:35:17 +02004730#if ENABLE_HUSH_INTERACTIVE
Denys Vlasenko8d6eab32018-04-07 17:01:31 +02004731 G.promptmode = 1; /* PS2 */
Denys Vlasenko817a2022018-06-26 15:35:17 +02004732#endif
Denys Vlasenko8d6eab32018-04-07 17:01:31 +02004733 debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode);
4734
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004735 while (1) {
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004736 ch = i_getch(input);
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004737 if (ch == EOF) {
Denys Vlasenkoa6ad3972010-05-22 00:26:06 +02004738 syntax_error_unterm_ch(end_ch);
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004739 return 0;
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004740 }
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01004741 if (ch == end_ch
4742# if BASH_SUBSTR || BASH_PATTERN_SUBST
Denys Vlasenko55f81332018-03-02 18:12:12 +01004743 || ch == end_char2
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01004744# endif
4745 ) {
Denys Vlasenkoa6ad3972010-05-22 00:26:06 +02004746 if (!dbl)
4747 break;
4748 /* we look for closing )) of $((EXPR)) */
Denys Vlasenko657086a2016-09-29 18:07:42 +02004749 if (i_peek_and_eat_bkslash_nl(input) == end_ch) {
Denys Vlasenkoa6ad3972010-05-22 00:26:06 +02004750 i_getch(input); /* eat second ')' */
4751 break;
Mike Frysinger98c52642009-04-02 10:02:37 +00004752 }
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004753 }
Denis Vlasenko82dfec32008-06-16 12:47:11 +00004754 o_addchr(dest, ch);
Denys Vlasenkod4802c62018-03-02 20:48:36 +01004755 //bb_error_msg("%s:o_addchr('%c')", __func__, ch);
Denys Vlasenkoa6ad3972010-05-22 00:26:06 +02004756 if (ch == '(' || ch == '{') {
4757 ch = (ch == '(' ? ')' : '}');
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004758 if (!add_till_closing_bracket(dest, input, ch))
4759 return 0;
Denys Vlasenkoa6ad3972010-05-22 00:26:06 +02004760 o_addchr(dest, ch);
4761 continue;
4762 }
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004763 if (ch == '\'') {
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004764 if (!add_till_single_quote(dest, input))
4765 return 0;
Denis Vlasenko82dfec32008-06-16 12:47:11 +00004766 o_addchr(dest, ch);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004767 continue;
4768 }
4769 if (ch == '"') {
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004770 if (!add_till_double_quote(dest, input))
4771 return 0;
Denis Vlasenko82dfec32008-06-16 12:47:11 +00004772 o_addchr(dest, ch);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004773 continue;
4774 }
Denys Vlasenkoa6ad3972010-05-22 00:26:06 +02004775 if (ch == '`') {
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004776 if (!add_till_backquote(dest, input, /*in_dquote:*/ 0))
4777 return 0;
Denys Vlasenkoa6ad3972010-05-22 00:26:06 +02004778 o_addchr(dest, ch);
4779 continue;
4780 }
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004781 if (ch == '\\') {
4782 /* \x. Copy verbatim. Important for \(, \) */
Denis Vlasenko76db5ad2008-06-12 12:58:20 +00004783 ch = i_getch(input);
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004784 if (ch == EOF) {
Denys Vlasenkod4802c62018-03-02 20:48:36 +01004785 syntax_error_unterm_ch(end_ch);
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004786 return 0;
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004787 }
Denys Vlasenko657086a2016-09-29 18:07:42 +02004788#if 0
4789 if (ch == '\n') {
4790 /* "backslash+newline", ignore both */
4791 o_delchr(dest); /* undo insertion of '\' */
4792 continue;
4793 }
4794#endif
Denis Vlasenko82dfec32008-06-16 12:47:11 +00004795 o_addchr(dest, ch);
Denys Vlasenkod4802c62018-03-02 20:48:36 +01004796 //bb_error_msg("%s:o_addchr('%c') after '\\'", __func__, ch);
Denis Vlasenko76db5ad2008-06-12 12:58:20 +00004797 continue;
4798 }
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004799 }
Denys Vlasenko8d6eab32018-04-07 17:01:31 +02004800 debug_printf_parse("%s return '%s' ch:'%c'\n", __func__, dest->data, ch);
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004801 return ch;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004802}
Denys Vlasenko0b883582016-12-23 16:49:07 +01004803#endif /* ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS */
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004804
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00004805/* Return code: 0 for OK, 1 for syntax error */
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00004806#if BB_MMU
Denys Vlasenko101a4e32010-09-09 14:04:57 +02004807#define parse_dollar(as_string, dest, input, quote_mask) \
4808 parse_dollar(dest, input, quote_mask)
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004809#define as_string NULL
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00004810#endif
Denys Vlasenko2e48d532010-05-22 17:30:39 +02004811static int parse_dollar(o_string *as_string,
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00004812 o_string *dest,
Denys Vlasenko101a4e32010-09-09 14:04:57 +02004813 struct in_str *input, unsigned char quote_mask)
Eric Andersen25f27032001-04-26 23:22:31 +00004814{
Denys Vlasenko657086a2016-09-29 18:07:42 +02004815 int ch = i_peek_and_eat_bkslash_nl(input); /* first character after the $ */
Denis Vlasenkoe0a33672007-05-10 23:06:55 +00004816
Denys Vlasenko2e48d532010-05-22 17:30:39 +02004817 debug_printf_parse("parse_dollar entered: ch='%c'\n", ch);
Denis Vlasenko1f4cf512007-05-16 10:39:24 +00004818 if (isalpha(ch)) {
Denys Vlasenko0ca31982018-01-25 13:20:50 +01004819 make_var:
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00004820 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004821 nommu_addchr(as_string, ch);
Denys Vlasenko0ca31982018-01-25 13:20:50 +01004822 /*make_var1:*/
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004823 o_addchr(dest, SPECIAL_VAR_SYMBOL);
Denis Vlasenkoe0a33672007-05-10 23:06:55 +00004824 while (1) {
Denis Vlasenkoe0a33672007-05-10 23:06:55 +00004825 debug_printf_parse(": '%c'\n", ch);
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004826 o_addchr(dest, ch | quote_mask);
Denis Vlasenko1f4cf512007-05-16 10:39:24 +00004827 quote_mask = 0;
Denys Vlasenko657086a2016-09-29 18:07:42 +02004828 ch = i_peek_and_eat_bkslash_nl(input);
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02004829 if (!isalnum(ch) && ch != '_') {
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02004830 /* End of variable name reached */
Denis Vlasenko602d13c2007-05-13 18:34:53 +00004831 break;
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02004832 }
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00004833 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004834 nommu_addchr(as_string, ch);
Eric Andersen25f27032001-04-26 23:22:31 +00004835 }
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004836 o_addchr(dest, SPECIAL_VAR_SYMBOL);
Eric Andersen25f27032001-04-26 23:22:31 +00004837 } else if (isdigit(ch)) {
Denis Vlasenko602d13c2007-05-13 18:34:53 +00004838 make_one_char_var:
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00004839 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004840 nommu_addchr(as_string, ch);
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004841 o_addchr(dest, SPECIAL_VAR_SYMBOL);
Denis Vlasenko602d13c2007-05-13 18:34:53 +00004842 debug_printf_parse(": '%c'\n", ch);
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004843 o_addchr(dest, ch | quote_mask);
4844 o_addchr(dest, SPECIAL_VAR_SYMBOL);
Eric Andersen25f27032001-04-26 23:22:31 +00004845 } else switch (ch) {
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004846 case '$': /* pid */
4847 case '!': /* last bg pid */
4848 case '?': /* last exit code */
4849 case '#': /* number of args */
4850 case '*': /* args */
4851 case '@': /* args */
4852 goto make_one_char_var;
4853 case '{': {
Denys Vlasenko2093ad22017-07-26 00:07:27 +02004854 char len_single_ch;
4855
Mike Frysingeref3e7fd2009-06-01 14:13:39 -04004856 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4857
Denys Vlasenko74369502010-05-21 19:52:01 +02004858 ch = i_getch(input); /* eat '{' */
4859 nommu_addchr(as_string, ch);
4860
Denys Vlasenko46e64982016-09-29 19:50:55 +02004861 ch = i_getch_and_eat_bkslash_nl(input); /* first char after '{' */
Denys Vlasenko74369502010-05-21 19:52:01 +02004862 /* It should be ${?}, or ${#var},
4863 * or even ${?+subst} - operator acting on a special variable,
4864 * or the beginning of variable name.
4865 */
Denys Vlasenko101a4e32010-09-09 14:04:57 +02004866 if (ch == EOF
4867 || (!strchr(_SPECIAL_VARS_STR, ch) && !isalnum(ch)) /* not one of those */
4868 ) {
Denys Vlasenko74369502010-05-21 19:52:01 +02004869 bad_dollar_syntax:
4870 syntax_error_unterm_str("${name}");
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004871 debug_printf_parse("parse_dollar return 0: unterminated ${name}\n");
4872 return 0;
Denys Vlasenko74369502010-05-21 19:52:01 +02004873 }
Denys Vlasenko101a4e32010-09-09 14:04:57 +02004874 nommu_addchr(as_string, ch);
Denys Vlasenko2093ad22017-07-26 00:07:27 +02004875 len_single_ch = ch;
Denys Vlasenko74369502010-05-21 19:52:01 +02004876 ch |= quote_mask;
4877
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004878 /* It's possible to just call add_till_closing_bracket() at this point.
Denys Vlasenko74369502010-05-21 19:52:01 +02004879 * However, this regresses some of our testsuite cases
4880 * which check invalid constructs like ${%}.
4881 * Oh well... let's check that the var name part is fine... */
4882
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004883 while (1) {
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004884 unsigned pos;
4885
Denys Vlasenko74369502010-05-21 19:52:01 +02004886 o_addchr(dest, ch);
4887 debug_printf_parse(": '%c'\n", ch);
4888
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004889 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004890 nommu_addchr(as_string, ch);
Denys Vlasenko74369502010-05-21 19:52:01 +02004891 if (ch == '}')
Mike Frysinger98c52642009-04-02 10:02:37 +00004892 break;
Mike Frysinger98c52642009-04-02 10:02:37 +00004893
Denys Vlasenko74369502010-05-21 19:52:01 +02004894 if (!isalnum(ch) && ch != '_') {
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004895 unsigned end_ch;
4896 unsigned char last_ch;
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004897 /* handle parameter expansions
4898 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02
4899 */
Denys Vlasenko2093ad22017-07-26 00:07:27 +02004900 if (!strchr(VAR_SUBST_OPS, ch)) { /* ${var<bad_char>... */
4901 if (len_single_ch != '#'
4902 /*|| !strchr(SPECIAL_VARS_STR, ch) - disallow errors like ${#+} ? */
4903 || i_peek(input) != '}'
4904 ) {
4905 goto bad_dollar_syntax;
4906 }
4907 /* else: it's "length of C" ${#C} op,
4908 * where C is a single char
4909 * special var name, e.g. ${#!}.
4910 */
4911 }
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004912 /* Eat everything until closing '}' (or ':') */
4913 end_ch = '}';
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01004914 if (BASH_SUBSTR
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004915 && ch == ':'
Denys Vlasenko36f774a2010-09-05 14:45:38 +02004916 && !strchr(MINUS_PLUS_EQUAL_QUESTION, i_peek(input))
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004917 ) {
4918 /* It's ${var:N[:M]} thing */
4919 end_ch = '}' * 0x100 + ':';
4920 }
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01004921 if (BASH_PATTERN_SUBST
Denys Vlasenko36f774a2010-09-05 14:45:38 +02004922 && ch == '/'
4923 ) {
4924 /* It's ${var/[/]pattern[/repl]} thing */
4925 if (i_peek(input) == '/') { /* ${var//pattern[/repl]}? */
4926 i_getch(input);
4927 nommu_addchr(as_string, '/');
4928 ch = '\\';
4929 }
4930 end_ch = '}' * 0x100 + '/';
4931 }
4932 o_addchr(dest, ch);
Denys Vlasenkoc2aa2182018-08-04 22:25:28 +02004933 /* The pattern can't be empty.
4934 * IOW: if the first char after "${v//" is a slash,
4935 * it does not terminate the pattern - it's the first char of the pattern:
4936 * v=/dev/ram; echo ${v////-} prints -dev-ram (pattern is "/")
4937 * v=/dev/ram; echo ${v///r/-} prints /dev-am (pattern is "/r")
4938 */
4939 if (i_peek(input) == '/') {
4940 o_addchr(dest, i_getch(input));
4941 }
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004942 again:
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004943 if (!BB_MMU)
4944 pos = dest->length;
Denys Vlasenko9297dbc2010-07-05 21:37:12 +02004945#if ENABLE_HUSH_DOLLAR_OPS
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004946 last_ch = add_till_closing_bracket(dest, input, end_ch);
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004947 if (last_ch == 0) /* error? */
4948 return 0;
Denys Vlasenko9297dbc2010-07-05 21:37:12 +02004949#else
4950#error Simple code to only allow ${var} is not implemented
4951#endif
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004952 if (as_string) {
4953 o_addstr(as_string, dest->data + pos);
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004954 o_addchr(as_string, last_ch);
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004955 }
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004956
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01004957 if ((BASH_SUBSTR || BASH_PATTERN_SUBST)
4958 && (end_ch & 0xff00)
4959 ) {
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004960 /* close the first block: */
4961 o_addchr(dest, SPECIAL_VAR_SYMBOL);
Denys Vlasenko36f774a2010-09-05 14:45:38 +02004962 /* while parsing N from ${var:N[:M]}
4963 * or pattern from ${var/[/]pattern[/repl]} */
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004964 if ((end_ch & 0xff) == last_ch) {
Denys Vlasenko36f774a2010-09-05 14:45:38 +02004965 /* got ':' or '/'- parse the rest */
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004966 end_ch = '}';
4967 goto again;
4968 }
Denys Vlasenko36f774a2010-09-05 14:45:38 +02004969 /* got '}' */
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01004970 if (BASH_SUBSTR && end_ch == '}' * 0x100 + ':') {
Denys Vlasenko36f774a2010-09-05 14:45:38 +02004971 /* it's ${var:N} - emulate :999999999 */
4972 o_addstr(dest, "999999999");
4973 } /* else: it's ${var/[/]pattern} */
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004974 }
Denys Vlasenko74369502010-05-21 19:52:01 +02004975 break;
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004976 }
Denys Vlasenko2093ad22017-07-26 00:07:27 +02004977 len_single_ch = 0; /* it can't be ${#C} op */
Denys Vlasenko74369502010-05-21 19:52:01 +02004978 }
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004979 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4980 break;
4981 }
Denys Vlasenko0b883582016-12-23 16:49:07 +01004982#if ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_TICK
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004983 case '(': {
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004984 unsigned pos;
4985
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00004986 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004987 nommu_addchr(as_string, ch);
Denys Vlasenko0b883582016-12-23 16:49:07 +01004988# if ENABLE_FEATURE_SH_MATH
Denys Vlasenko657086a2016-09-29 18:07:42 +02004989 if (i_peek_and_eat_bkslash_nl(input) == '(') {
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00004990 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004991 nommu_addchr(as_string, ch);
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004992 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4993 o_addchr(dest, /*quote_mask |*/ '+');
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004994 if (!BB_MMU)
4995 pos = dest->length;
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004996 if (!add_till_closing_bracket(dest, input, ')' | DOUBLE_CLOSE_CHAR_FLAG))
4997 return 0; /* error */
Denis Vlasenkoc4a7af52009-04-05 20:33:27 +00004998 if (as_string) {
4999 o_addstr(as_string, dest->data + pos);
5000 o_addchr(as_string, ')');
5001 o_addchr(as_string, ')');
Denis Vlasenko0bb4a232009-04-05 01:42:59 +00005002 }
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00005003 o_addchr(dest, SPECIAL_VAR_SYMBOL);
Eric Andersen25f27032001-04-26 23:22:31 +00005004 break;
Denis Vlasenko76db5ad2008-06-12 12:58:20 +00005005 }
Denis Vlasenkod85a5df2009-04-05 08:43:57 +00005006# endif
5007# if ENABLE_HUSH_TICK
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00005008 o_addchr(dest, SPECIAL_VAR_SYMBOL);
5009 o_addchr(dest, quote_mask | '`');
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02005010 if (!BB_MMU)
5011 pos = dest->length;
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01005012 if (!add_till_closing_bracket(dest, input, ')'))
5013 return 0; /* error */
Denis Vlasenkoc4a7af52009-04-05 20:33:27 +00005014 if (as_string) {
5015 o_addstr(as_string, dest->data + pos);
Denys Vlasenkob70cef72010-01-12 13:45:45 +01005016 o_addchr(as_string, ')');
Denis Vlasenko0bb4a232009-04-05 01:42:59 +00005017 }
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00005018 o_addchr(dest, SPECIAL_VAR_SYMBOL);
Denis Vlasenkod85a5df2009-04-05 08:43:57 +00005019# endif
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00005020 break;
5021 }
Denis Vlasenkod85a5df2009-04-05 08:43:57 +00005022#endif
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00005023 case '_':
Denys Vlasenko0ca31982018-01-25 13:20:50 +01005024 goto make_var;
5025#if 0
Denys Vlasenko69b1cef2009-09-21 10:21:44 +02005026 /* TODO: $_ and $-: */
5027 /* $_ Shell or shell script name; or last argument of last command
5028 * (if last command wasn't a pipe; if it was, bash sets $_ to "");
5029 * but in command's env, set to full pathname used to invoke it */
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00005030 /* $- Option flags set by set builtin or shell options (-i etc) */
Denys Vlasenko0ca31982018-01-25 13:20:50 +01005031 ch = i_getch(input);
5032 nommu_addchr(as_string, ch);
5033 ch = i_peek_and_eat_bkslash_nl(input);
5034 if (isalnum(ch)) { /* it's $_name or $_123 */
5035 ch = '_';
5036 goto make_var1;
5037 }
5038 /* else: it's $_ */
5039#endif
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00005040 default:
5041 o_addQchr(dest, '$');
Eric Andersen25f27032001-04-26 23:22:31 +00005042 }
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01005043 debug_printf_parse("parse_dollar return 1 (ok)\n");
5044 return 1;
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02005045#undef as_string
Eric Andersen25f27032001-04-26 23:22:31 +00005046}
5047
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005048#if BB_MMU
Denys Vlasenkob762c782018-07-17 14:21:38 +02005049#define encode_string(as_string, dest, input, dquote_end) \
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02005050 encode_string(dest, input, dquote_end)
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02005051#define as_string NULL
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005052#endif
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02005053static int encode_string(o_string *as_string,
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005054 o_string *dest,
5055 struct in_str *input,
Denys Vlasenkob762c782018-07-17 14:21:38 +02005056 int dquote_end)
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00005057{
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00005058 int ch;
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00005059 int next;
5060
5061 again:
5062 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00005063 if (ch != EOF)
5064 nommu_addchr(as_string, ch);
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00005065 if (ch == dquote_end) { /* may be only '"' or EOF */
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01005066 debug_printf_parse("encode_string return 1 (ok)\n");
5067 return 1;
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00005068 }
Denis Vlasenko3dfb0352009-04-08 09:29:14 +00005069 /* note: can't move it above ch == dquote_end check! */
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00005070 if (ch == EOF) {
Denis Vlasenkod68ae082009-04-09 20:41:34 +00005071 syntax_error_unterm_ch('"');
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01005072 return 0; /* error */
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00005073 }
5074 next = '\0';
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00005075 if (ch != '\n') {
5076 next = i_peek(input);
5077 }
Denys Vlasenkof37eb392009-10-18 11:46:35 +02005078 debug_printf_parse("\" ch=%c (%d) escape=%d\n",
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02005079 ch, ch, !!(dest->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
Denys Vlasenkob762c782018-07-17 14:21:38 +02005080 if (ch == '\\') {
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00005081 if (next == EOF) {
Denys Vlasenko4709df02018-04-10 14:49:01 +02005082 /* Testcase: in interactive shell a file with
5083 * echo "unterminated string\<eof>
5084 * is sourced.
5085 */
5086 syntax_error_unterm_ch('"');
5087 return 0; /* error */
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00005088 }
5089 /* bash:
5090 * "The backslash retains its special meaning [in "..."]
5091 * only when followed by one of the following characters:
5092 * $, `, ", \, or <newline>. A double quote may be quoted
Denys Vlasenkoe640cb42009-05-28 16:49:11 +02005093 * within double quotes by preceding it with a backslash."
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02005094 * NB: in (unquoted) heredoc, above does not apply to ",
5095 * therefore we check for it by "next == dquote_end" cond.
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00005096 */
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02005097 if (next == dquote_end || strchr("$`\\\n", next)) {
Denys Vlasenko850b15b2010-09-09 12:58:19 +02005098 ch = i_getch(input); /* eat next */
5099 if (ch == '\n')
5100 goto again; /* skip \<newline> */
Denys Vlasenko4f870492010-09-10 11:06:01 +02005101 } /* else: ch remains == '\\', and we double it below: */
5102 o_addqchr(dest, ch); /* \c if c is a glob char, else just c */
Denys Vlasenko850b15b2010-09-09 12:58:19 +02005103 nommu_addchr(as_string, ch);
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00005104 goto again;
5105 }
5106 if (ch == '$') {
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01005107 if (!parse_dollar(as_string, dest, input, /*quote_mask:*/ 0x80)) {
5108 debug_printf_parse("encode_string return 0: "
5109 "parse_dollar returned 0 (error)\n");
5110 return 0;
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00005111 }
5112 goto again;
5113 }
5114#if ENABLE_HUSH_TICK
5115 if (ch == '`') {
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02005116 //unsigned pos = dest->length;
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00005117 o_addchr(dest, SPECIAL_VAR_SYMBOL);
5118 o_addchr(dest, 0x80 | '`');
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01005119 if (!add_till_backquote(dest, input, /*in_dquote:*/ dquote_end == '"'))
5120 return 0; /* error */
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00005121 o_addchr(dest, SPECIAL_VAR_SYMBOL);
5122 //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
Denis Vlasenkof328e002009-04-02 16:55:38 +00005123 goto again;
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00005124 }
5125#endif
Denis Vlasenkof328e002009-04-02 16:55:38 +00005126 o_addQchr(dest, ch);
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00005127 goto again;
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02005128#undef as_string
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00005129}
5130
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005131/*
5132 * Scan input until EOF or end_trigger char.
5133 * Return a list of pipes to execute, or NULL on EOF
5134 * or if end_trigger character is met.
Denys Vlasenkocecbc982011-03-30 18:54:52 +02005135 * On syntax error, exit if shell is not interactive,
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005136 * reset parsing machinery and start parsing anew,
5137 * or return ERR_PTR.
Denis Vlasenko027e3fd2009-04-02 22:50:40 +00005138 */
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005139static struct pipe *parse_stream(char **pstring,
Denys Vlasenko474cb202018-07-24 13:03:03 +02005140 int *heredoc_cnt_ptr,
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005141 struct in_str *input,
5142 int end_trigger)
Eric Andersen25f27032001-04-26 23:22:31 +00005143{
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005144 struct parse_context ctx;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00005145 int heredoc_cnt;
Eric Andersen25f27032001-04-26 23:22:31 +00005146
Denys Vlasenko77a7b552010-09-09 12:40:03 +02005147 /* Single-quote triggers a bypass of the main loop until its mate is
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005148 * found. When recursing, quote state is passed in via ctx.word.o_expflags.
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00005149 */
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005150 debug_printf_parse("parse_stream entered, end_trigger='%c'\n",
Denys Vlasenko90a99042009-09-06 02:36:23 +02005151 end_trigger ? end_trigger : 'X');
Denis Vlasenko0701dca2009-04-11 10:38:47 +00005152 debug_enter();
Denis Vlasenkoe725bfe2007-05-03 22:45:39 +00005153
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005154 initialize_context(&ctx);
5155
5156 /* If very first arg is "" or '', ctx.word.data may end up NULL.
5157 * Preventing this:
5158 */
Denys Vlasenko8b08d5a2018-07-18 15:48:53 +02005159 ctx.word.data = xzalloc(1); /* start as "", not as NULL */
Denys Vlasenkof37eb392009-10-18 11:46:35 +02005160
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005161 /* We used to separate words on $IFS here. This was wrong.
5162 * $IFS is used only for word splitting when $var is expanded,
Denys Vlasenko77a7b552010-09-09 12:40:03 +02005163 * here we should use blank chars as separators, not $IFS
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005164 */
Denys Vlasenko77a7b552010-09-09 12:40:03 +02005165
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00005166 heredoc_cnt = 0;
Denis Vlasenko1a735862007-05-23 00:32:25 +00005167 while (1) {
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005168 const char *is_blank;
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00005169 const char *is_special;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005170 int ch;
5171 int next;
5172 int redir_fd;
5173 redir_type redir_style;
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00005174
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00005175 ch = i_getch(input);
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00005176 debug_printf_parse(": ch=%c (%d) escape=%d\n",
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005177 ch, ch, !!(ctx.word.o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00005178 if (ch == EOF) {
5179 struct pipe *pi;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00005180
5181 if (heredoc_cnt) {
Denis Vlasenkod68ae082009-04-09 20:41:34 +00005182 syntax_error_unterm_str("here document");
Denys Vlasenkob1cfc452009-05-02 17:18:34 +02005183 goto parse_error;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00005184 }
Denys Vlasenkob1cfc452009-05-02 17:18:34 +02005185 if (end_trigger == ')') {
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01005186 syntax_error_unterm_ch('(');
5187 goto parse_error;
Denys Vlasenkob1cfc452009-05-02 17:18:34 +02005188 }
Denys Vlasenko42246472016-11-07 16:22:35 +01005189 if (end_trigger == '}') {
5190 syntax_error_unterm_ch('{');
5191 goto parse_error;
5192 }
Denys Vlasenkob1cfc452009-05-02 17:18:34 +02005193
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005194 if (done_word(&ctx)) {
Denys Vlasenkob1cfc452009-05-02 17:18:34 +02005195 goto parse_error;
Denis Vlasenko55789c62008-06-18 16:30:42 +00005196 }
Denys Vlasenko18567402018-07-20 17:51:31 +02005197 o_free_and_set_NULL(&ctx.word);
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00005198 done_pipe(&ctx, PIPE_SEQ);
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00005199 pi = ctx.list_head;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005200 /* If we got nothing... */
Denis Vlasenko0b677d82009-04-10 13:49:10 +00005201 /* (this makes bare "&" cmd a no-op.
5202 * bash says: "syntax error near unexpected token '&'") */
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00005203 if (pi->num_cmds == 0
Denys Vlasenko60cb48c2013-01-14 15:57:44 +01005204 IF_HAS_KEYWORDS(&& pi->res_word == RES_NONE)
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00005205 ) {
Denis Vlasenko0701dca2009-04-11 10:38:47 +00005206 free_pipe_list(pi);
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00005207 pi = NULL;
5208 }
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005209#if !BB_MMU
Denys Vlasenkob5be13c2015-09-04 06:22:10 +02005210 debug_printf_parse("as_string1 '%s'\n", ctx.as_string.data);
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005211 if (pstring)
5212 *pstring = ctx.as_string.data;
5213 else
Denys Vlasenko18567402018-07-20 17:51:31 +02005214 o_free(&ctx.as_string);
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005215#endif
Denys Vlasenko474cb202018-07-24 13:03:03 +02005216 // heredoc_cnt must be 0 here anyway
5217 //if (heredoc_cnt_ptr)
5218 // *heredoc_cnt_ptr = heredoc_cnt;
Denis Vlasenko0701dca2009-04-11 10:38:47 +00005219 debug_leave();
Denys Vlasenko474cb202018-07-24 13:03:03 +02005220 debug_printf_heredoc("parse_stream return heredoc_cnt:%d\n", heredoc_cnt);
Denis Vlasenko0701dca2009-04-11 10:38:47 +00005221 debug_printf_parse("parse_stream return %p\n", pi);
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00005222 return pi;
Denis Vlasenko1a735862007-05-23 00:32:25 +00005223 }
Denys Vlasenkod8389ad2009-11-16 03:18:46 +01005224
Denys Vlasenko0403bed2018-04-11 01:33:54 +02005225 /* Handle "'" and "\" first, as they won't play nice with
5226 * i_peek_and_eat_bkslash_nl() anyway:
5227 * echo z\\
5228 * and
5229 * echo '\
5230 * '
5231 * would break.
5232 */
Denys Vlasenkof693b602018-04-11 20:00:43 +02005233 if (ch == '\\') {
5234 ch = i_getch(input);
5235 if (ch == '\n')
5236 continue; /* drop \<newline>, get next char */
5237 nommu_addchr(&ctx.as_string, '\\');
5238 o_addchr(&ctx.word, '\\');
5239 if (ch == EOF) {
5240 /* Testcase: eval 'echo Ok\' */
5241 /* bash-4.3.43 was removing backslash,
5242 * but 4.4.19 retains it, most other shells too
5243 */
5244 continue; /* get next char */
5245 }
5246 /* Example: echo Hello \2>file
5247 * we need to know that word 2 is quoted
5248 */
5249 ctx.word.has_quoted_part = 1;
5250 nommu_addchr(&ctx.as_string, ch);
5251 o_addchr(&ctx.word, ch);
5252 continue; /* get next char */
5253 }
5254 nommu_addchr(&ctx.as_string, ch);
Denys Vlasenko92a930b2018-04-10 14:20:48 +02005255 if (ch == '\'') {
5256 ctx.word.has_quoted_part = 1;
5257 next = i_getch(input);
5258 if (next == '\'' && !ctx.pending_redirect)
5259 goto insert_empty_quoted_str_marker;
5260
5261 ch = next;
5262 while (1) {
5263 if (ch == EOF) {
5264 syntax_error_unterm_ch('\'');
5265 goto parse_error;
5266 }
5267 nommu_addchr(&ctx.as_string, ch);
5268 if (ch == '\'')
5269 break;
5270 if (ch == SPECIAL_VAR_SYMBOL) {
5271 /* Convert raw ^C to corresponding special variable reference */
5272 o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5273 o_addchr(&ctx.word, SPECIAL_VAR_QUOTED_SVS);
5274 }
5275 o_addqchr(&ctx.word, ch);
5276 ch = i_getch(input);
5277 }
5278 continue; /* get next char */
Denys Vlasenko1e5111b2018-04-01 03:04:55 +02005279 }
Denys Vlasenko92a930b2018-04-10 14:20:48 +02005280
Denys Vlasenko0403bed2018-04-11 01:33:54 +02005281 next = '\0';
5282 if (ch != '\n')
5283 next = i_peek_and_eat_bkslash_nl(input);
5284
Denys Vlasenko92a930b2018-04-10 14:20:48 +02005285 is_special = "{}<>;&|()#" /* special outside of "str" */
Denys Vlasenko0403bed2018-04-11 01:33:54 +02005286 "$\"" IF_HUSH_TICK("`") /* always special */
Denys Vlasenko932b9972018-01-11 12:39:48 +01005287 SPECIAL_VAR_SYMBOL_STR;
Denys Vlasenkod8389ad2009-11-16 03:18:46 +01005288 /* Are { and } special here? */
Denys Vlasenko3227d3f2010-05-17 09:49:47 +02005289 if (ctx.command->argv /* word [word]{... - non-special */
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005290 || ctx.word.length /* word{... - non-special */
5291 || ctx.word.has_quoted_part /* ""{... - non-special */
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005292 || (next != ';' /* }; - special */
5293 && next != ')' /* }) - special */
Denys Vlasenko672a55e2016-11-04 18:46:14 +01005294 && next != '(' /* {( - special */
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005295 && next != '&' /* }& and }&& ... - special */
5296 && next != '|' /* }|| ... - special */
5297 && !strchr(defifs, next) /* {word - non-special */
Denys Vlasenko3227d3f2010-05-17 09:49:47 +02005298 )
Denys Vlasenkod8389ad2009-11-16 03:18:46 +01005299 ) {
5300 /* They are not special, skip "{}" */
5301 is_special += 2;
5302 }
5303 is_special = strchr(is_special, ch);
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005304 is_blank = strchr(defifs, ch);
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00005305
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005306 if (!is_special && !is_blank) { /* ordinary char */
Denis Vlasenkobf25fbc2009-04-19 13:57:51 +00005307 ordinary_char:
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005308 o_addQchr(&ctx.word, ch);
5309 if ((ctx.is_assignment == MAYBE_ASSIGNMENT
5310 || ctx.is_assignment == WORD_IS_KEYWORD)
Denis Vlasenko55789c62008-06-18 16:30:42 +00005311 && ch == '='
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005312 && is_well_formed_var_name(ctx.word.data, '=')
Denis Vlasenko55789c62008-06-18 16:30:42 +00005313 ) {
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005314 ctx.is_assignment = DEFINITELY_ASSIGNMENT;
5315 debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
Denis Vlasenko55789c62008-06-18 16:30:42 +00005316 }
Denis Vlasenkobb81c582007-01-30 22:32:09 +00005317 continue;
5318 }
Denis Vlasenko240c2552009-04-03 03:45:05 +00005319
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005320 if (is_blank) {
Denys Vlasenko5807e182018-02-08 19:19:04 +01005321#if ENABLE_HUSH_LINENO_VAR
5322/* Case:
5323 * "while ...; do<whitespace><newline>
5324 * cmd ..."
5325 * would think that "cmd" starts in <whitespace> -
5326 * i.e., at the previous line.
5327 * We need to skip all whitespace before newlines.
5328 */
Denys Vlasenkof7869012018-02-08 19:39:42 +01005329 while (ch != '\n') {
5330 next = i_peek(input);
5331 if (next != ' ' && next != '\t' && next != '\n')
5332 break; /* next char is not ws */
5333 ch = i_getch(input);
Denys Vlasenko5807e182018-02-08 19:19:04 +01005334 }
Denys Vlasenkof7869012018-02-08 19:39:42 +01005335 /* ch == last eaten whitespace char */
Denys Vlasenko5807e182018-02-08 19:19:04 +01005336#endif
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005337 if (done_word(&ctx)) {
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005338 goto parse_error;
Eric Andersenaac75e52001-04-30 18:18:45 +00005339 }
Denis Vlasenko37181682009-04-03 03:19:15 +00005340 if (ch == '\n') {
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01005341 /* Is this a case when newline is simply ignored?
5342 * Some examples:
5343 * "cmd | <newline> cmd ..."
5344 * "case ... in <newline> word) ..."
5345 */
5346 if (IS_NULL_CMD(ctx.command)
Denys Vlasenko3675c372018-07-23 16:31:21 +02005347 && ctx.word.length == 0
5348 && !ctx.word.has_quoted_part
5349 && heredoc_cnt == 0
Denis Vlasenkof1736072008-07-31 10:09:26 +00005350 ) {
Denys Vlasenko642e71a2011-01-07 15:16:05 +01005351 /* This newline can be ignored. But...
Denys Vlasenko98c46d12011-01-18 17:30:07 +01005352 * Without check #1, interactive shell
5353 * ignores even bare <newline>,
5354 * and shows the continuation prompt:
Denys Vlasenko642e71a2011-01-07 15:16:05 +01005355 * ps1_prompt$ <enter>
Denys Vlasenko98c46d12011-01-18 17:30:07 +01005356 * ps2> _ <=== wrong, should be ps1
5357 * Without check #2, "cmd & <newline>"
5358 * is similarly mistreated.
5359 * (BTW, this makes "cmd & cmd"
5360 * and "cmd && cmd" non-orthogonal.
5361 * Really, ask yourself, why
5362 * "cmd && <newline>" doesn't start
5363 * cmd but waits for more input?
Denys Vlasenkob24e55d2017-07-16 20:29:35 +02005364 * The only reason is that it might be
5365 * a "cmd1 && <nl> cmd2 &" construct,
5366 * cmd1 may need to run in BG).
Denys Vlasenko642e71a2011-01-07 15:16:05 +01005367 */
5368 struct pipe *pi = ctx.list_head;
Denys Vlasenko98c46d12011-01-18 17:30:07 +01005369 if (pi->num_cmds != 0 /* check #1 */
5370 && pi->followup != PIPE_BG /* check #2 */
5371 ) {
Denys Vlasenko642e71a2011-01-07 15:16:05 +01005372 continue;
Denys Vlasenko98c46d12011-01-18 17:30:07 +01005373 }
Denis Vlasenkof1736072008-07-31 10:09:26 +00005374 }
Denis Vlasenko240c2552009-04-03 03:45:05 +00005375 /* Treat newline as a command separator. */
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005376 done_pipe(&ctx, PIPE_SEQ);
Denys Vlasenko3675c372018-07-23 16:31:21 +02005377 debug_printf_heredoc("heredoc_cnt:%d\n", heredoc_cnt);
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00005378 if (heredoc_cnt) {
Denys Vlasenko474cb202018-07-24 13:03:03 +02005379 heredoc_cnt = fetch_heredocs(&ctx.as_string, ctx.list_head, heredoc_cnt, input);
5380 if (heredoc_cnt != 0)
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00005381 goto parse_error;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00005382 }
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005383 ctx.is_assignment = MAYBE_ASSIGNMENT;
5384 debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
Denis Vlasenko240c2552009-04-03 03:45:05 +00005385 ch = ';';
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005386 /* note: if (is_blank) continue;
Denis Vlasenko240c2552009-04-03 03:45:05 +00005387 * will still trigger for us */
Denis Vlasenkoe725bfe2007-05-03 22:45:39 +00005388 }
Denis Vlasenkobb81c582007-01-30 22:32:09 +00005389 }
Denis Vlasenko9f8d9382009-04-19 14:03:11 +00005390
5391 /* "cmd}" or "cmd }..." without semicolon or &:
5392 * } is an ordinary char in this case, even inside { cmd; }
5393 * Pathological example: { ""}; } should exec "}" cmd
5394 */
Denis Vlasenkodcd78c42009-04-19 23:07:51 +00005395 if (ch == '}') {
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005396 if (ctx.word.length != 0 /* word} */
5397 || ctx.word.has_quoted_part /* ""} */
Denis Vlasenkodcd78c42009-04-19 23:07:51 +00005398 ) {
5399 goto ordinary_char;
5400 }
Denys Vlasenko672a55e2016-11-04 18:46:14 +01005401 if (!IS_NULL_CMD(ctx.command)) { /* cmd } */
5402 /* Generally, there should be semicolon: "cmd; }"
5403 * However, bash allows to omit it if "cmd" is
5404 * a group. Examples:
5405 * { { echo 1; } }
5406 * {(echo 1)}
5407 * { echo 0 >&2 | { echo 1; } }
5408 * { while false; do :; done }
5409 * { case a in b) ;; esac }
5410 */
5411 if (ctx.command->group)
5412 goto term_group;
5413 goto ordinary_char;
5414 }
Denis Vlasenkodcd78c42009-04-19 23:07:51 +00005415 if (!IS_NULL_PIPE(ctx.pipe)) /* cmd | } */
Denys Vlasenko672a55e2016-11-04 18:46:14 +01005416 /* Can't be an end of {cmd}, skip the check */
Denis Vlasenkodcd78c42009-04-19 23:07:51 +00005417 goto skip_end_trigger;
5418 /* else: } does terminate a group */
Denis Vlasenko9f8d9382009-04-19 14:03:11 +00005419 }
Denys Vlasenko672a55e2016-11-04 18:46:14 +01005420 term_group:
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00005421 if (end_trigger && end_trigger == ch
Denys Vlasenkoe9bda902009-05-23 16:50:07 +02005422 && (ch != ';' || heredoc_cnt == 0)
5423#if ENABLE_HUSH_CASE
5424 && (ch != ')'
5425 || ctx.ctx_res_w != RES_MATCH
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005426 || (!ctx.word.has_quoted_part && strcmp(ctx.word.data, "esac") == 0)
Denys Vlasenkoe9bda902009-05-23 16:50:07 +02005427 )
5428#endif
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00005429 ) {
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005430 if (done_word(&ctx)) {
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005431 goto parse_error;
5432 }
5433 done_pipe(&ctx, PIPE_SEQ);
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005434 ctx.is_assignment = MAYBE_ASSIGNMENT;
5435 debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
Denis Vlasenko240c2552009-04-03 03:45:05 +00005436 /* Do we sit outside of any if's, loops or case's? */
Denis Vlasenko37181682009-04-03 03:19:15 +00005437 if (!HAS_KEYWORDS
Denys Vlasenko60cb48c2013-01-14 15:57:44 +01005438 IF_HAS_KEYWORDS(|| (ctx.ctx_res_w == RES_NONE && ctx.old_flag == 0))
Denis Vlasenko37181682009-04-03 03:19:15 +00005439 ) {
Denys Vlasenko18567402018-07-20 17:51:31 +02005440 o_free_and_set_NULL(&ctx.word);
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005441#if !BB_MMU
Denys Vlasenkob5be13c2015-09-04 06:22:10 +02005442 debug_printf_parse("as_string2 '%s'\n", ctx.as_string.data);
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005443 if (pstring)
5444 *pstring = ctx.as_string.data;
5445 else
Denys Vlasenko18567402018-07-20 17:51:31 +02005446 o_free(&ctx.as_string);
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005447#endif
Denys Vlasenko39701202017-08-02 19:44:05 +02005448 if (ch != ';' && IS_NULL_PIPE(ctx.list_head)) {
5449 /* Example: bare "{ }", "()" */
5450 G.last_exitcode = 2; /* bash compat */
5451 syntax_error_unexpected_ch(ch);
5452 goto parse_error2;
5453 }
Denys Vlasenko474cb202018-07-24 13:03:03 +02005454 if (heredoc_cnt_ptr)
5455 *heredoc_cnt_ptr = heredoc_cnt;
5456 debug_printf_heredoc("parse_stream return heredoc_cnt:%d\n", heredoc_cnt);
Denis Vlasenko0701dca2009-04-11 10:38:47 +00005457 debug_printf_parse("parse_stream return %p: "
5458 "end_trigger char found\n",
5459 ctx.list_head);
Denys Vlasenko39701202017-08-02 19:44:05 +02005460 debug_leave();
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005461 return ctx.list_head;
Denis Vlasenkof8d01d32008-06-14 17:13:20 +00005462 }
Denis Vlasenkobb81c582007-01-30 22:32:09 +00005463 }
Denys Vlasenko92a930b2018-04-10 14:20:48 +02005464
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005465 if (is_blank)
Denis Vlasenkobb81c582007-01-30 22:32:09 +00005466 continue;
Denis Vlasenko55789c62008-06-18 16:30:42 +00005467
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00005468 /* Catch <, > before deciding whether this word is
5469 * an assignment. a=1 2>z b=2: b=2 is still assignment */
5470 switch (ch) {
5471 case '>':
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005472 redir_fd = redirect_opt_num(&ctx.word);
5473 if (done_word(&ctx)) {
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00005474 goto parse_error;
5475 }
5476 redir_style = REDIRECT_OVERWRITE;
5477 if (next == '>') {
5478 redir_style = REDIRECT_APPEND;
5479 ch = i_getch(input);
5480 nommu_addchr(&ctx.as_string, ch);
5481 }
5482#if 0
5483 else if (next == '(') {
5484 syntax_error(">(process) not supported");
5485 goto parse_error;
5486 }
5487#endif
5488 if (parse_redirect(&ctx, redir_fd, redir_style, input))
5489 goto parse_error;
Denys Vlasenko92a930b2018-04-10 14:20:48 +02005490 continue; /* get next char */
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00005491 case '<':
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005492 redir_fd = redirect_opt_num(&ctx.word);
5493 if (done_word(&ctx)) {
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00005494 goto parse_error;
5495 }
5496 redir_style = REDIRECT_INPUT;
5497 if (next == '<') {
5498 redir_style = REDIRECT_HEREDOC;
5499 heredoc_cnt++;
Denys Vlasenko3675c372018-07-23 16:31:21 +02005500 debug_printf_heredoc("++heredoc_cnt=%d\n", heredoc_cnt);
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00005501 ch = i_getch(input);
5502 nommu_addchr(&ctx.as_string, ch);
5503 } else if (next == '>') {
5504 redir_style = REDIRECT_IO;
5505 ch = i_getch(input);
5506 nommu_addchr(&ctx.as_string, ch);
5507 }
5508#if 0
5509 else if (next == '(') {
5510 syntax_error("<(process) not supported");
5511 goto parse_error;
5512 }
5513#endif
5514 if (parse_redirect(&ctx, redir_fd, redir_style, input))
5515 goto parse_error;
Denys Vlasenko92a930b2018-04-10 14:20:48 +02005516 continue; /* get next char */
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01005517 case '#':
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005518 if (ctx.word.length == 0 && !ctx.word.has_quoted_part) {
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01005519 /* skip "#comment" */
Denys Vlasenko25f3b732017-10-22 15:55:48 +02005520 /* note: we do not add it to &ctx.as_string */
5521/* TODO: in bash:
5522 * comment inside $() goes to the next \n, even inside quoted string (!):
5523 * cmd "$(cmd2 #comment)" - syntax error
5524 * cmd "`cmd2 #comment`" - ok
5525 * We accept both (comment ends where command subst ends, in both cases).
5526 */
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01005527 while (1) {
5528 ch = i_peek(input);
Denys Vlasenko25f3b732017-10-22 15:55:48 +02005529 if (ch == '\n') {
5530 nommu_addchr(&ctx.as_string, '\n');
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01005531 break;
Denys Vlasenko25f3b732017-10-22 15:55:48 +02005532 }
5533 ch = i_getch(input);
5534 if (ch == EOF)
5535 break;
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01005536 }
Denys Vlasenko92a930b2018-04-10 14:20:48 +02005537 continue; /* get next char */
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01005538 }
5539 break;
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00005540 }
Denys Vlasenko92a930b2018-04-10 14:20:48 +02005541 skip_end_trigger:
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00005542
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005543 if (ctx.is_assignment == MAYBE_ASSIGNMENT
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00005544 /* check that we are not in word in "a=1 2>word b=1": */
5545 && !ctx.pending_redirect
5546 ) {
5547 /* ch is a special char and thus this word
5548 * cannot be an assignment */
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005549 ctx.is_assignment = NOT_ASSIGNMENT;
5550 debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00005551 }
5552
Denys Vlasenkocbfe6ad2009-08-12 19:47:44 +02005553 /* Note: nommu_addchr(&ctx.as_string, ch) is already done */
5554
Denis Vlasenkobb81c582007-01-30 22:32:09 +00005555 switch (ch) {
Denys Vlasenko932b9972018-01-11 12:39:48 +01005556 case SPECIAL_VAR_SYMBOL:
5557 /* Convert raw ^C to corresponding special variable reference */
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005558 o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5559 o_addchr(&ctx.word, SPECIAL_VAR_QUOTED_SVS);
Denys Vlasenko932b9972018-01-11 12:39:48 +01005560 /* fall through */
5561 case '#':
5562 /* non-comment #: "echo a#b" etc */
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005563 o_addchr(&ctx.word, ch);
Denys Vlasenkoe8b1bc02018-04-10 13:13:10 +02005564 continue; /* get next char */
Eric Andersen25f27032001-04-26 23:22:31 +00005565 case '$':
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005566 if (!parse_dollar(&ctx.as_string, &ctx.word, input, /*quote_mask:*/ 0)) {
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00005567 debug_printf_parse("parse_stream parse error: "
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01005568 "parse_dollar returned 0 (error)\n");
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005569 goto parse_error;
Denis Vlasenkoe725bfe2007-05-03 22:45:39 +00005570 }
Denys Vlasenkoe8b1bc02018-04-10 13:13:10 +02005571 continue; /* get next char */
Denys Vlasenkoe8b1bc02018-04-10 13:13:10 +02005572 case '"':
5573 ctx.word.has_quoted_part = 1;
5574 if (next == '"' && !ctx.pending_redirect) {
Denys Vlasenko92a930b2018-04-10 14:20:48 +02005575 i_getch(input); /* eat second " */
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005576 insert_empty_quoted_str_marker:
5577 nommu_addchr(&ctx.as_string, next);
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005578 o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5579 o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
Denys Vlasenkoe8b1bc02018-04-10 13:13:10 +02005580 continue; /* get next char */
Eric Andersen25f27032001-04-26 23:22:31 +00005581 }
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005582 if (ctx.is_assignment == NOT_ASSIGNMENT)
5583 ctx.word.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS;
Denys Vlasenkob762c782018-07-17 14:21:38 +02005584 if (!encode_string(&ctx.as_string, &ctx.word, input, '"'))
Denys Vlasenko77a7b552010-09-09 12:40:03 +02005585 goto parse_error;
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005586 ctx.word.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS;
Denys Vlasenkoe8b1bc02018-04-10 13:13:10 +02005587 continue; /* get next char */
Denis Vlasenko14b5dd92007-05-20 21:51:38 +00005588#if ENABLE_HUSH_TICK
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00005589 case '`': {
Denys Vlasenko60a94142011-05-13 20:57:01 +02005590 USE_FOR_NOMMU(unsigned pos;)
Denys Vlasenko2e48d532010-05-22 17:30:39 +02005591
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005592 o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5593 o_addchr(&ctx.word, '`');
5594 USE_FOR_NOMMU(pos = ctx.word.length;)
5595 if (!add_till_backquote(&ctx.word, input, /*in_dquote:*/ 0))
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01005596 goto parse_error;
Denys Vlasenko2e48d532010-05-22 17:30:39 +02005597# if !BB_MMU
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005598 o_addstr(&ctx.as_string, ctx.word.data + pos);
Denis Vlasenko5c090a92009-04-08 21:51:33 +00005599 o_addchr(&ctx.as_string, '`');
Denys Vlasenko2e48d532010-05-22 17:30:39 +02005600# endif
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005601 o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5602 //debug_printf_subst("SUBST RES3 '%s'\n", ctx.word.data + pos);
Denys Vlasenkoe8b1bc02018-04-10 13:13:10 +02005603 continue; /* get next char */
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00005604 }
Denis Vlasenko14b5dd92007-05-20 21:51:38 +00005605#endif
Eric Andersen25f27032001-04-26 23:22:31 +00005606 case ';':
Denis Vlasenko17f02e72008-07-14 04:32:29 +00005607#if ENABLE_HUSH_CASE
5608 case_semi:
5609#endif
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005610 if (done_word(&ctx)) {
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005611 goto parse_error;
5612 }
5613 done_pipe(&ctx, PIPE_SEQ);
Denis Vlasenko17f02e72008-07-14 04:32:29 +00005614#if ENABLE_HUSH_CASE
5615 /* Eat multiple semicolons, detect
5616 * whether it means something special */
5617 while (1) {
Denys Vlasenko1e5111b2018-04-01 03:04:55 +02005618 ch = i_peek_and_eat_bkslash_nl(input);
Denis Vlasenko17f02e72008-07-14 04:32:29 +00005619 if (ch != ';')
5620 break;
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00005621 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00005622 nommu_addchr(&ctx.as_string, ch);
Denys Vlasenkoe9bda902009-05-23 16:50:07 +02005623 if (ctx.ctx_res_w == RES_CASE_BODY) {
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005624 ctx.ctx_dsemicolon = 1;
5625 ctx.ctx_res_w = RES_MATCH;
Denis Vlasenko17f02e72008-07-14 04:32:29 +00005626 break;
5627 }
5628 }
5629#endif
Denis Vlasenko2b576b82008-08-04 00:46:07 +00005630 new_cmd:
5631 /* We just finished a cmd. New one may start
5632 * with an assignment */
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005633 ctx.is_assignment = MAYBE_ASSIGNMENT;
5634 debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
Denys Vlasenkoe8b1bc02018-04-10 13:13:10 +02005635 continue; /* get next char */
Eric Andersen25f27032001-04-26 23:22:31 +00005636 case '&':
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005637 if (done_word(&ctx)) {
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005638 goto parse_error;
5639 }
Denis Vlasenkobb81c582007-01-30 22:32:09 +00005640 if (next == '&') {
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00005641 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00005642 nommu_addchr(&ctx.as_string, ch);
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005643 done_pipe(&ctx, PIPE_AND);
Eric Andersen25f27032001-04-26 23:22:31 +00005644 } else {
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005645 done_pipe(&ctx, PIPE_BG);
Eric Andersen25f27032001-04-26 23:22:31 +00005646 }
Denis Vlasenko2b576b82008-08-04 00:46:07 +00005647 goto new_cmd;
Eric Andersen25f27032001-04-26 23:22:31 +00005648 case '|':
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005649 if (done_word(&ctx)) {
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005650 goto parse_error;
5651 }
Denis Vlasenkofbeeb322008-07-31 00:17:01 +00005652#if ENABLE_HUSH_CASE
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005653 if (ctx.ctx_res_w == RES_MATCH)
Denis Vlasenkof1736072008-07-31 10:09:26 +00005654 break; /* we are in case's "word | word)" */
Denis Vlasenkofbeeb322008-07-31 00:17:01 +00005655#endif
Denis Vlasenko2b576b82008-08-04 00:46:07 +00005656 if (next == '|') { /* || */
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00005657 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00005658 nommu_addchr(&ctx.as_string, ch);
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005659 done_pipe(&ctx, PIPE_OR);
Eric Andersen25f27032001-04-26 23:22:31 +00005660 } else {
5661 /* we could pick up a file descriptor choice here
5662 * with redirect_opt_num(), but bash doesn't do it.
5663 * "echo foo 2| cat" yields "foo 2". */
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005664 done_command(&ctx);
Eric Andersen25f27032001-04-26 23:22:31 +00005665 }
Denis Vlasenko2b576b82008-08-04 00:46:07 +00005666 goto new_cmd;
Eric Andersen25f27032001-04-26 23:22:31 +00005667 case '(':
Denis Vlasenko17f02e72008-07-14 04:32:29 +00005668#if ENABLE_HUSH_CASE
Denis Vlasenkof1736072008-07-31 10:09:26 +00005669 /* "case... in [(]word)..." - skip '(' */
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005670 if (ctx.ctx_res_w == RES_MATCH
5671 && ctx.command->argv == NULL /* not (word|(... */
Denys Vlasenko09b7a7e2018-04-10 03:22:10 +02005672 && ctx.word.length == 0 /* not word(... */
5673 && ctx.word.has_quoted_part == 0 /* not ""(... */
Denis Vlasenko17f02e72008-07-14 04:32:29 +00005674 ) {
Denys Vlasenkoe8b1bc02018-04-10 13:13:10 +02005675 continue; /* get next char */
Denis Vlasenko17f02e72008-07-14 04:32:29 +00005676 }
5677#endif
Denys Vlasenko474cb202018-07-24 13:03:03 +02005678 /* fall through */
5679 case '{': {
5680 int n = parse_group(&ctx, input, ch);
5681 if (n < 0) {
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005682 goto parse_error;
Denis Vlasenkoe725bfe2007-05-03 22:45:39 +00005683 }
Denys Vlasenko474cb202018-07-24 13:03:03 +02005684 debug_printf_heredoc("parse_group done, needs heredocs:%d\n", n);
5685 heredoc_cnt += n;
Denis Vlasenko2b576b82008-08-04 00:46:07 +00005686 goto new_cmd;
Denys Vlasenko474cb202018-07-24 13:03:03 +02005687 }
Eric Andersen25f27032001-04-26 23:22:31 +00005688 case ')':
Denis Vlasenko17f02e72008-07-14 04:32:29 +00005689#if ENABLE_HUSH_CASE
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005690 if (ctx.ctx_res_w == RES_MATCH)
Denis Vlasenko17f02e72008-07-14 04:32:29 +00005691 goto case_semi;
5692#endif
Denys Vlasenko474cb202018-07-24 13:03:03 +02005693
Eric Andersen25f27032001-04-26 23:22:31 +00005694 case '}':
Denis Vlasenkoc3735272008-10-09 12:58:26 +00005695 /* proper use of this character is caught by end_trigger:
5696 * if we see {, we call parse_group(..., end_trigger='}')
5697 * and it will match } earlier (not here). */
Denys Vlasenkob05bcaf2017-01-03 11:47:50 +01005698 G.last_exitcode = 2;
Denys Vlasenko39701202017-08-02 19:44:05 +02005699 syntax_error_unexpected_ch(ch);
Denys Vlasenko9fda6092017-07-14 13:36:48 +02005700 goto parse_error2;
Eric Andersen25f27032001-04-26 23:22:31 +00005701 default:
Denis Vlasenko5ec61322008-06-24 00:50:07 +00005702 if (HUSH_DEBUG)
Denys Vlasenko332e4112018-04-04 22:32:59 +02005703 bb_error_msg_and_die("BUG: unexpected %c", ch);
Eric Andersen25f27032001-04-26 23:22:31 +00005704 }
Denis Vlasenkof8d01d32008-06-14 17:13:20 +00005705 } /* while (1) */
Denis Vlasenko027e3fd2009-04-02 22:50:40 +00005706
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005707 parse_error:
Denys Vlasenkob05bcaf2017-01-03 11:47:50 +01005708 G.last_exitcode = 1;
Denys Vlasenko9fda6092017-07-14 13:36:48 +02005709 parse_error2:
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005710 {
Denis Vlasenko60b392f2009-04-03 19:14:32 +00005711 struct parse_context *pctx;
5712 IF_HAS_KEYWORDS(struct parse_context *p2;)
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005713
5714 /* Clean up allocated tree.
Denys Vlasenko764b2f02009-06-07 16:05:04 +02005715 * Sample for finding leaks on syntax error recovery path.
5716 * Run it from interactive shell, watch pmap `pidof hush`.
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005717 * while if false; then false; fi; do break; fi
Denis Vlasenkocc4c6932009-04-05 07:38:48 +00005718 * Samples to catch leaks at execution:
Denys Vlasenko5d5a6112016-11-07 19:36:50 +01005719 * while if (true | { true;}); then echo ok; fi; do break; done
5720 * while if (true | { true;}); then echo ok; fi; do (if echo ok; break; then :; fi) | cat; break; done
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005721 */
5722 pctx = &ctx;
5723 do {
5724 /* Update pipe/command counts,
5725 * otherwise freeing may miss some */
5726 done_pipe(pctx, PIPE_SEQ);
5727 debug_printf_clean("freeing list %p from ctx %p\n",
5728 pctx->list_head, pctx);
5729 debug_print_tree(pctx->list_head, 0);
Denis Vlasenko0701dca2009-04-11 10:38:47 +00005730 free_pipe_list(pctx->list_head);
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005731 debug_printf_clean("freed list %p\n", pctx->list_head);
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005732#if !BB_MMU
Denys Vlasenko18567402018-07-20 17:51:31 +02005733 o_free(&pctx->as_string);
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005734#endif
Denis Vlasenko60b392f2009-04-03 19:14:32 +00005735 IF_HAS_KEYWORDS(p2 = pctx->stack;)
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005736 if (pctx != &ctx) {
5737 free(pctx);
5738 }
Denis Vlasenko60b392f2009-04-03 19:14:32 +00005739 IF_HAS_KEYWORDS(pctx = p2;)
5740 } while (HAS_KEYWORDS && pctx);
Denys Vlasenkocecbc982011-03-30 18:54:52 +02005741
Denys Vlasenko474cb202018-07-24 13:03:03 +02005742 o_free(&ctx.word);
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005743#if !BB_MMU
Denys Vlasenkocecbc982011-03-30 18:54:52 +02005744 if (pstring)
5745 *pstring = NULL;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005746#endif
Denys Vlasenkocecbc982011-03-30 18:54:52 +02005747 debug_leave();
5748 return ERR_PTR;
Denis Vlasenko027e3fd2009-04-02 22:50:40 +00005749 }
Eric Andersen25f27032001-04-26 23:22:31 +00005750}
5751
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005752
5753/*** Execution routines ***/
5754
5755/* Expansion can recurse, need forward decls: */
Denys Vlasenko637982f2017-07-06 01:52:23 +02005756#if !BASH_PATTERN_SUBST && !ENABLE_HUSH_CASE
Denys Vlasenko34179952018-04-11 13:47:59 +02005757#define expand_string_to_string(str, EXP_flags, do_unbackslash) \
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02005758 expand_string_to_string(str)
5759#endif
Denys Vlasenko34179952018-04-11 13:47:59 +02005760static char *expand_string_to_string(const char *str, int EXP_flags, int do_unbackslash);
Denys Vlasenko26777aa2010-11-22 23:49:10 +01005761#if ENABLE_HUSH_TICK
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005762static int process_command_subs(o_string *dest, const char *s);
Denys Vlasenko26777aa2010-11-22 23:49:10 +01005763#endif
Denys Vlasenko4c3c8a12018-07-20 19:11:09 +02005764static int expand_vars_to_list(o_string *output, int n, char *arg);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005765
5766/* expand_strvec_to_strvec() takes a list of strings, expands
5767 * all variable references within and returns a pointer to
5768 * a list of expanded strings, possibly with larger number
5769 * of strings. (Think VAR="a b"; echo $VAR).
5770 * This new list is allocated as a single malloc block.
5771 * NULL-terminated list of char* pointers is at the beginning of it,
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005772 * followed by strings themselves.
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005773 * Caller can deallocate entire list by single free(list). */
5774
Denys Vlasenko238081f2010-10-03 14:26:26 +02005775/* A horde of its helpers come first: */
5776
5777static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len)
5778{
5779 while (--len >= 0) {
Denys Vlasenko9e800222010-10-03 14:28:04 +02005780 char c = *str++;
Denys Vlasenko957f79f2010-10-03 17:15:50 +02005781
Denys Vlasenko9e800222010-10-03 14:28:04 +02005782#if ENABLE_HUSH_BRACE_EXPANSION
5783 if (c == '{' || c == '}') {
5784 /* { -> \{, } -> \} */
5785 o_addchr(o, '\\');
Denys Vlasenko957f79f2010-10-03 17:15:50 +02005786 /* And now we want to add { or } and continue:
5787 * o_addchr(o, c);
5788 * continue;
Denys Vlasenko10ad6222017-04-17 16:13:32 +02005789 * luckily, just falling through achieves this.
Denys Vlasenko957f79f2010-10-03 17:15:50 +02005790 */
Denys Vlasenko9e800222010-10-03 14:28:04 +02005791 }
5792#endif
5793 o_addchr(o, c);
5794 if (c == '\\') {
Denys Vlasenko238081f2010-10-03 14:26:26 +02005795 /* \z -> \\\z; \<eol> -> \\<eol> */
5796 o_addchr(o, '\\');
5797 if (len) {
5798 len--;
5799 o_addchr(o, '\\');
5800 o_addchr(o, *str++);
5801 }
5802 }
5803 }
5804}
5805
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005806/* Store given string, finalizing the word and starting new one whenever
5807 * we encounter IFS char(s). This is used for expanding variable values.
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005808 * End-of-string does NOT finalize word: think about 'echo -$VAR-'.
Denys Vlasenko168579a2018-07-19 13:45:54 +02005809 * Return in output->ended_in_ifs:
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005810 * 1 - ended with IFS char, else 0 (this includes case of empty str).
5811 */
Denys Vlasenko168579a2018-07-19 13:45:54 +02005812static int expand_on_ifs(o_string *output, int n, const char *str)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005813{
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005814 int last_is_ifs = 0;
5815
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005816 while (1) {
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02005817 int word_len;
5818
5819 if (!*str) /* EOL - do not finalize word */
5820 break;
5821 word_len = strcspn(str, G.ifs);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005822 if (word_len) {
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02005823 /* We have WORD_LEN leading non-IFS chars */
Denys Vlasenko238081f2010-10-03 14:26:26 +02005824 if (!(output->o_expflags & EXP_FLAG_GLOB)) {
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02005825 o_addblock(output, str, word_len);
Denys Vlasenko238081f2010-10-03 14:26:26 +02005826 } else {
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02005827 /* Protect backslashes against globbing up :)
Denys Vlasenkoa769e022010-09-10 10:12:34 +02005828 * Example: "v='\*'; echo b$v" prints "b\*"
5829 * (and does not try to glob on "*")
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02005830 */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005831 o_addblock_duplicate_backslash(output, str, word_len);
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02005832 /*/ Why can't we do it easier? */
5833 /*o_addblock(output, str, word_len); - WRONG: "v='\*'; echo Z$v" prints "Z*" instead of "Z\*" */
5834 /*o_addqblock(output, str, word_len); - WRONG: "v='*'; echo Z$v" prints "Z*" instead of Z* files */
5835 }
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005836 last_is_ifs = 0;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005837 str += word_len;
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02005838 if (!*str) /* EOL - do not finalize word */
5839 break;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005840 }
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005841
5842 /* We know str here points to at least one IFS char */
5843 last_is_ifs = 1;
Denys Vlasenko96786362018-04-11 16:02:58 +02005844 str += strspn(str, G.ifs_whitespace); /* skip IFS whitespace chars */
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005845 if (!*str) /* EOL - do not finalize word */
5846 break;
5847
Denys Vlasenko96786362018-04-11 16:02:58 +02005848 if (G.ifs_whitespace != G.ifs /* usually false ($IFS is usually all whitespace), */
5849 && strchr(G.ifs, *str) /* the second check would fail */
5850 ) {
5851 /* This is a non-whitespace $IFS char */
5852 /* Skip it and IFS whitespace chars, start new word */
5853 str++;
5854 str += strspn(str, G.ifs_whitespace);
5855 goto new_word;
5856 }
5857
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005858 /* Start new word... but not always! */
5859 /* Case "v=' a'; echo ''$v": we do need to finalize empty word: */
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02005860 if (output->has_quoted_part
Denys Vlasenko186cf492018-07-27 12:14:39 +02005861 /*
5862 * Case "v=' a'; echo $v":
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02005863 * here nothing precedes the space in $v expansion,
5864 * therefore we should not finish the word
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005865 * (IOW: if there *is* word to finalize, only then do it):
Denys Vlasenko186cf492018-07-27 12:14:39 +02005866 * It's okay if this accesses the byte before first argv[]:
5867 * past call to o_save_ptr() cleared it to zero byte
5868 * (grep for -prev-ifs-check-).
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02005869 */
Denys Vlasenko186cf492018-07-27 12:14:39 +02005870 || output->data[output->length - 1]
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02005871 ) {
Denys Vlasenko96786362018-04-11 16:02:58 +02005872 new_word:
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02005873 o_addchr(output, '\0');
5874 debug_print_list("expand_on_ifs", output, n);
5875 n = o_save_ptr(output, n);
5876 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005877 }
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005878
Denys Vlasenko168579a2018-07-19 13:45:54 +02005879 output->ended_in_ifs = last_is_ifs;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005880 debug_print_list("expand_on_ifs[1]", output, n);
5881 return n;
5882}
5883
5884/* Helper to expand $((...)) and heredoc body. These act as if
5885 * they are in double quotes, with the exception that they are not :).
5886 * Just the rules are similar: "expand only $var and `cmd`"
5887 *
5888 * Returns malloced string.
5889 * As an optimization, we return NULL if expansion is not needed.
5890 */
Denys Vlasenkob762c782018-07-17 14:21:38 +02005891static char *encode_then_expand_string(const char *str)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005892{
5893 char *exp_str;
5894 struct in_str input;
5895 o_string dest = NULL_O_STRING;
Denys Vlasenko0d2e0de2018-07-17 14:33:19 +02005896 const char *cp;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005897
Denys Vlasenko0d2e0de2018-07-17 14:33:19 +02005898 cp = str;
5899 for (;;) {
5900 if (!*cp) return NULL; /* string has no special chars */
5901 if (*cp == '$') break;
5902 if (*cp == '\\') break;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005903#if ENABLE_HUSH_TICK
Denys Vlasenko0d2e0de2018-07-17 14:33:19 +02005904 if (*cp == '`') break;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005905#endif
Denys Vlasenko0d2e0de2018-07-17 14:33:19 +02005906 cp++;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005907 }
5908
5909 /* We need to expand. Example:
5910 * echo $(($a + `echo 1`)) $((1 + $((2)) ))
5911 */
5912 setup_string_in_str(&input, str);
Denys Vlasenkob762c782018-07-17 14:21:38 +02005913 encode_string(NULL, &dest, &input, EOF);
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01005914//TODO: error check (encode_string returns 0 on error)?
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005915 //bb_error_msg("'%s' -> '%s'", str, dest.data);
Denys Vlasenko34179952018-04-11 13:47:59 +02005916 exp_str = expand_string_to_string(dest.data,
Denys Vlasenkob762c782018-07-17 14:21:38 +02005917 EXP_FLAG_ESC_GLOB_CHARS,
5918 /*unbackslash:*/ 1
5919 );
5920 //bb_error_msg("'%s' -> '%s'", dest.data, exp_str);
Denys Vlasenko18567402018-07-20 17:51:31 +02005921 o_free(&dest);
Denys Vlasenkob762c782018-07-17 14:21:38 +02005922 return exp_str;
5923}
5924
Denys Vlasenko54fdabd2018-07-31 10:36:29 +02005925static const char *first_special_char_in_vararg(const char *cp)
5926{
5927 for (;;) {
5928 if (!*cp) return NULL; /* string has no special chars */
5929 if (*cp == '$') return cp;
5930 if (*cp == '\\') return cp;
5931 if (*cp == '\'') return cp;
5932 if (*cp == '"') return cp;
5933#if ENABLE_HUSH_TICK
5934 if (*cp == '`') return cp;
5935#endif
5936 /* dquoted "${x:+ARG}" should not glob, therefore
5937 * '*' et al require some non-literal processing: */
5938 if (*cp == '*') return cp;
5939 if (*cp == '?') return cp;
5940 if (*cp == '[') return cp;
5941 cp++;
5942 }
5943}
5944
Denys Vlasenko4c3c8a12018-07-20 19:11:09 +02005945/* Expanding ARG in ${var#ARG}, ${var%ARG}, or ${var/ARG/ARG}.
5946 * These can contain single- and double-quoted strings,
5947 * and treated as if the ARG string is initially unquoted. IOW:
5948 * ${var#ARG} and "${var#ARG}" treat ARG the same (ARG can even be
5949 * a dquoted string: "${var#"zz"}"), the difference only comes later
5950 * (word splitting and globbing of the ${var...} result).
5951 */
Denys Vlasenkob762c782018-07-17 14:21:38 +02005952#if !BASH_PATTERN_SUBST
5953#define encode_then_expand_vararg(str, handle_squotes, do_unbackslash) \
5954 encode_then_expand_vararg(str, handle_squotes)
5955#endif
5956static char *encode_then_expand_vararg(const char *str, int handle_squotes, int do_unbackslash)
5957{
5958#if !BASH_PATTERN_SUBST
5959 const int do_unbackslash = 0;
5960#endif
5961 char *exp_str;
5962 struct in_str input;
5963 o_string dest = NULL_O_STRING;
5964
Denys Vlasenko54fdabd2018-07-31 10:36:29 +02005965 if (!first_special_char_in_vararg(str)) {
5966 /* string has no special chars */
5967 return NULL;
Denys Vlasenkob762c782018-07-17 14:21:38 +02005968 }
5969
Denys Vlasenkob762c782018-07-17 14:21:38 +02005970 setup_string_in_str(&input, str);
Denys Vlasenko8b08d5a2018-07-18 15:48:53 +02005971 dest.data = xzalloc(1); /* start as "", not as NULL */
Denys Vlasenkob762c782018-07-17 14:21:38 +02005972 exp_str = NULL;
5973
5974 for (;;) {
5975 int ch;
Denys Vlasenkob762c782018-07-17 14:21:38 +02005976
5977 ch = i_getch(&input);
Denys Vlasenkob762c782018-07-17 14:21:38 +02005978 debug_printf_parse("%s: ch=%c (%d) escape=%d\n",
5979 __func__, ch, ch, !!dest.o_expflags);
Denys Vlasenko4c3c8a12018-07-20 19:11:09 +02005980
5981 if (!dest.o_expflags) {
5982 if (ch == EOF)
5983 break;
5984 if (handle_squotes && ch == '\'') {
5985 if (!add_till_single_quote_dquoted(&dest, &input))
Denys Vlasenkob762c782018-07-17 14:21:38 +02005986 goto ret; /* error */
Denys Vlasenko4c3c8a12018-07-20 19:11:09 +02005987 continue;
Denys Vlasenkob762c782018-07-17 14:21:38 +02005988 }
Denys Vlasenko4c3c8a12018-07-20 19:11:09 +02005989 }
5990 if (ch == EOF) {
5991 syntax_error_unterm_ch('"');
5992 goto ret; /* error */
Denys Vlasenkob762c782018-07-17 14:21:38 +02005993 }
5994 if (ch == '"') {
5995 dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS;
5996 continue;
5997 }
5998 if (ch == '\\') {
5999 ch = i_getch(&input);
6000 if (ch == EOF) {
6001//example? error message? syntax_error_unterm_ch('"');
6002 debug_printf_parse("%s: error: \\<eof>\n", __func__);
6003 goto ret;
6004 }
6005 o_addqchr(&dest, ch);
6006 continue;
6007 }
Denys Vlasenkob762c782018-07-17 14:21:38 +02006008 if (ch == '$') {
6009 if (!parse_dollar(NULL, &dest, &input, /*quote_mask:*/ 0x80)) {
6010 debug_printf_parse("%s: error: parse_dollar returned 0 (error)\n", __func__);
6011 goto ret;
6012 }
6013 continue;
6014 }
6015#if ENABLE_HUSH_TICK
6016 if (ch == '`') {
6017 //unsigned pos = dest->length;
6018 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6019 o_addchr(&dest, 0x80 | '`');
6020 if (!add_till_backquote(&dest, &input,
6021 /*in_dquote:*/ dest.o_expflags /* nonzero if EXP_FLAG_ESC_GLOB_CHARS set */
6022 )
6023 ) {
6024 goto ret; /* error */
6025 }
6026 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6027 //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
6028 continue;
6029 }
6030#endif
6031 o_addQchr(&dest, ch);
6032 } /* for (;;) */
6033
6034 debug_printf_parse("encode: '%s' -> '%s'\n", str, dest.data);
6035 exp_str = expand_string_to_string(dest.data,
Denys Vlasenko34179952018-04-11 13:47:59 +02006036 do_unbackslash ? EXP_FLAG_ESC_GLOB_CHARS : 0,
6037 do_unbackslash
6038 );
Denys Vlasenkob762c782018-07-17 14:21:38 +02006039 ret:
6040 debug_printf_parse("expand: '%s' -> '%s'\n", dest.data, exp_str);
Denys Vlasenko18567402018-07-20 17:51:31 +02006041 o_free(&dest);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006042 return exp_str;
6043}
6044
Denys Vlasenko4c3c8a12018-07-20 19:11:09 +02006045/* Expanding ARG in ${var+ARG}, ${var-ARG}
6046 */
Denys Vlasenko294eb462018-07-20 16:18:59 +02006047static int encode_then_append_var_plusminus(o_string *output, int n,
Denys Vlasenko54fdabd2018-07-31 10:36:29 +02006048 char *str, int dquoted)
Denys Vlasenko294eb462018-07-20 16:18:59 +02006049{
6050 struct in_str input;
6051 o_string dest = NULL_O_STRING;
6052
Denys Vlasenko54fdabd2018-07-31 10:36:29 +02006053 if (!first_special_char_in_vararg(str)
6054 && '\0' == str[strcspn(str, G.ifs)]
6055 ) {
6056 /* string has no special chars
6057 * && string has no $IFS chars
6058 */
6059 return expand_vars_to_list(output, n, str);
Denys Vlasenko294eb462018-07-20 16:18:59 +02006060 }
Denys Vlasenko294eb462018-07-20 16:18:59 +02006061
Denys Vlasenko294eb462018-07-20 16:18:59 +02006062 setup_string_in_str(&input, str);
6063
6064 for (;;) {
6065 int ch;
6066
6067 ch = i_getch(&input);
6068 debug_printf_parse("%s: ch=%c (%d) escape=%x\n",
6069 __func__, ch, ch, dest.o_expflags);
6070
6071 if (!dest.o_expflags) {
6072 if (ch == EOF)
6073 break;
6074 if (!dquoted && strchr(G.ifs, ch)) {
6075 /* PREFIX${x:d${e}f ...} and we met space: expand "d${e}f" and start new word.
6076 * do not assume we are at the start of the word (PREFIX above).
6077 */
6078 if (dest.data) {
6079 n = expand_vars_to_list(output, n, dest.data);
Denys Vlasenko18567402018-07-20 17:51:31 +02006080 o_free_and_set_NULL(&dest);
Denys Vlasenko294eb462018-07-20 16:18:59 +02006081 o_addchr(output, '\0');
6082 n = o_save_ptr(output, n); /* create next word */
6083 } else
6084 if (output->length != o_get_last_ptr(output, n)
6085 || output->has_quoted_part
6086 ) {
6087 /* For these cases:
6088 * f() { for i; do echo "|$i|"; done; }; x=x
6089 * f a${x:+ }b # 1st condition
6090 * |a|
6091 * |b|
6092 * f ""${x:+ }b # 2nd condition
6093 * ||
6094 * |b|
6095 */
6096 o_addchr(output, '\0');
6097 n = o_save_ptr(output, n); /* create next word */
6098 }
6099 continue;
6100 }
6101 if (!dquoted && ch == '\'') {
Denys Vlasenko4c3c8a12018-07-20 19:11:09 +02006102 if (!add_till_single_quote_dquoted(&dest, &input))
6103 goto ret; /* error */
Denys Vlasenko83e434d2018-07-20 17:36:06 +02006104 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6105 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
Denys Vlasenko294eb462018-07-20 16:18:59 +02006106 continue;
6107 }
6108 }
6109 if (ch == EOF) {
6110 syntax_error_unterm_ch('"');
6111 goto ret; /* error */
6112 }
6113 if (ch == '"') {
6114 dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS;
Denys Vlasenko83e434d2018-07-20 17:36:06 +02006115 if (dest.o_expflags) {
6116 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6117 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6118 }
Denys Vlasenko294eb462018-07-20 16:18:59 +02006119 continue;
6120 }
6121 if (ch == '\\') {
6122 ch = i_getch(&input);
6123 if (ch == EOF) {
6124//example? error message? syntax_error_unterm_ch('"');
6125 debug_printf_parse("%s: error: \\<eof>\n", __func__);
6126 goto ret;
6127 }
6128 o_addqchr(&dest, ch);
6129 continue;
6130 }
6131 if (ch == '$') {
6132 if (!parse_dollar(NULL, &dest, &input, /*quote_mask:*/ (dest.o_expflags || dquoted) ? 0x80 : 0)) {
6133 debug_printf_parse("%s: error: parse_dollar returned 0 (error)\n", __func__);
6134 goto ret;
6135 }
6136 continue;
6137 }
6138#if ENABLE_HUSH_TICK
6139 if (ch == '`') {
6140 //unsigned pos = dest->length;
6141 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6142 o_addchr(&dest, (dest.o_expflags || dquoted) ? 0x80 | '`' : '`');
6143 if (!add_till_backquote(&dest, &input,
6144 /*in_dquote:*/ dest.o_expflags /* nonzero if EXP_FLAG_ESC_GLOB_CHARS set */
6145 )
6146 ) {
6147 goto ret; /* error */
6148 }
6149 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6150 //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
6151 continue;
6152 }
6153#endif
Denys Vlasenkof36caa42018-07-20 19:29:41 +02006154 if (dquoted) {
6155 /* Always glob-protect if in dquotes:
6156 * x=x; echo "${x:+/bin/c*}" - prints: /bin/c*
6157 * x=x; echo "${x:+"/bin/c*"}" - prints: /bin/c*
6158 */
6159 o_addqchr(&dest, ch);
6160 } else {
6161 /* Glob-protect only if char is quoted:
6162 * x=x; echo ${x:+/bin/c*} - prints many filenames
6163 * x=x; echo ${x:+"/bin/c*"} - prints: /bin/c*
6164 */
6165 o_addQchr(&dest, ch);
6166 }
Denys Vlasenko294eb462018-07-20 16:18:59 +02006167 } /* for (;;) */
6168
6169 if (dest.data) {
6170 n = expand_vars_to_list(output, n, dest.data);
6171 }
6172 ret:
Denys Vlasenko18567402018-07-20 17:51:31 +02006173 o_free(&dest);
Denys Vlasenko294eb462018-07-20 16:18:59 +02006174 return n;
6175}
6176
Denys Vlasenko0b883582016-12-23 16:49:07 +01006177#if ENABLE_FEATURE_SH_MATH
Denys Vlasenko063847d2010-09-15 13:33:02 +02006178static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006179{
Denys Vlasenko06d44d72010-09-13 12:49:03 +02006180 arith_state_t math_state;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006181 arith_t res;
6182 char *exp_str;
6183
Denys Vlasenko06d44d72010-09-13 12:49:03 +02006184 math_state.lookupvar = get_local_var_value;
6185 math_state.setvar = set_local_var_from_halves;
6186 //math_state.endofname = endofname;
Denys Vlasenkob762c782018-07-17 14:21:38 +02006187 exp_str = encode_then_expand_string(arg);
Denys Vlasenko06d44d72010-09-13 12:49:03 +02006188 res = arith(&math_state, exp_str ? exp_str : arg);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006189 free(exp_str);
Denys Vlasenko063847d2010-09-15 13:33:02 +02006190 if (errmsg_p)
6191 *errmsg_p = math_state.errmsg;
6192 if (math_state.errmsg)
Denys Vlasenko39701202017-08-02 19:44:05 +02006193 msg_and_die_if_script(math_state.errmsg);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006194 return res;
6195}
6196#endif
6197
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01006198#if BASH_PATTERN_SUBST
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006199/* ${var/[/]pattern[/repl]} helpers */
6200static char *strstr_pattern(char *val, const char *pattern, int *size)
6201{
6202 while (1) {
6203 char *end = scan_and_match(val, pattern, SCAN_MOVE_FROM_RIGHT + SCAN_MATCH_LEFT_HALF);
6204 debug_printf_varexp("val:'%s' pattern:'%s' end:'%s'\n", val, pattern, end);
6205 if (end) {
6206 *size = end - val;
6207 return val;
6208 }
6209 if (*val == '\0')
6210 return NULL;
6211 /* Optimization: if "*pat" did not match the start of "string",
6212 * we know that "tring", "ring" etc will not match too:
6213 */
6214 if (pattern[0] == '*')
6215 return NULL;
6216 val++;
6217 }
6218}
6219static char *replace_pattern(char *val, const char *pattern, const char *repl, char exp_op)
6220{
6221 char *result = NULL;
6222 unsigned res_len = 0;
6223 unsigned repl_len = strlen(repl);
6224
Denys Vlasenkocba79a82018-01-25 14:07:40 +01006225 /* Null pattern never matches, including if "var" is empty */
6226 if (!pattern[0])
6227 return result; /* NULL, no replaces happened */
6228
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006229 while (1) {
6230 int size;
6231 char *s = strstr_pattern(val, pattern, &size);
6232 if (!s)
6233 break;
6234
6235 result = xrealloc(result, res_len + (s - val) + repl_len + 1);
Denys Vlasenko0675b032017-07-24 02:17:05 +02006236 strcpy(mempcpy(result + res_len, val, s - val), repl);
6237 res_len += (s - val) + repl_len;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006238 debug_printf_varexp("val:'%s' s:'%s' result:'%s'\n", val, s, result);
6239
6240 val = s + size;
6241 if (exp_op == '/')
6242 break;
6243 }
Denys Vlasenko0675b032017-07-24 02:17:05 +02006244 if (*val && result) {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006245 result = xrealloc(result, res_len + strlen(val) + 1);
6246 strcpy(result + res_len, val);
6247 debug_printf_varexp("val:'%s' result:'%s'\n", val, result);
6248 }
6249 debug_printf_varexp("result:'%s'\n", result);
6250 return result;
6251}
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01006252#endif /* BASH_PATTERN_SUBST */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006253
Denys Vlasenko168579a2018-07-19 13:45:54 +02006254static int append_str_maybe_ifs_split(o_string *output, int n,
Denys Vlasenko18e8b612018-07-20 14:24:56 +02006255 int first_ch, const char *val)
Denys Vlasenko116b50a2018-07-19 11:16:53 +02006256{
6257 if (!(first_ch & 0x80)) { /* unquoted $VAR */
6258 debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val,
6259 !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
6260 if (val && val[0])
Denys Vlasenko168579a2018-07-19 13:45:54 +02006261 n = expand_on_ifs(output, n, val);
Denys Vlasenko116b50a2018-07-19 11:16:53 +02006262 } else { /* quoted "$VAR" */
6263 output->has_quoted_part = 1;
6264 debug_printf_expand("quoted '%s', output->o_escape:%d\n", val,
6265 !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
6266 if (val && val[0])
6267 o_addQstr(output, val);
6268 }
6269 return n;
6270}
6271
Denys Vlasenko4c3c8a12018-07-20 19:11:09 +02006272/* Handle <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct.
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006273 */
Denys Vlasenko4c3c8a12018-07-20 19:11:09 +02006274static NOINLINE int expand_one_var(o_string *output, int n,
6275 int first_ch, char *arg, char **pp)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006276{
Denys Vlasenko0ca31982018-01-25 13:20:50 +01006277 const char *val;
6278 char *to_be_freed;
6279 char *p;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006280 char *var;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006281 char exp_op;
6282 char exp_save = exp_save; /* for compiler */
6283 char *exp_saveptr; /* points to expansion operator */
6284 char *exp_word = exp_word; /* for compiler */
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006285 char arg0;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006286
Denys Vlasenko0ca31982018-01-25 13:20:50 +01006287 val = NULL;
6288 to_be_freed = NULL;
6289 p = *pp;
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02006290 *p = '\0'; /* replace trailing SPECIAL_VAR_SYMBOL */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006291 var = arg;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006292 exp_saveptr = arg[1] ? strchr(VAR_ENCODED_SUBST_OPS, arg[1]) : NULL;
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006293 arg0 = arg[0];
Denys Vlasenkob762c782018-07-17 14:21:38 +02006294 arg[0] = (arg0 & 0x7f);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006295 exp_op = 0;
6296
Denys Vlasenkob762c782018-07-17 14:21:38 +02006297 if (arg[0] == '#' && arg[1] /* ${#...} but not ${#} */
Denys Vlasenko2093ad22017-07-26 00:07:27 +02006298 && (!exp_saveptr /* and ( not(${#<op_char>...}) */
6299 || (arg[2] == '\0' && strchr(SPECIAL_VARS_STR, arg[1])) /* or ${#C} "len of $C" ) */
6300 ) /* NB: skipping ^^^specvar check mishandles ${#::2} */
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02006301 ) {
6302 /* It must be length operator: ${#var} */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006303 var++;
6304 exp_op = 'L';
6305 } else {
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02006306 /* Maybe handle parameter expansion */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006307 if (exp_saveptr /* if 2nd char is one of expansion operators */
Denys Vlasenkob762c782018-07-17 14:21:38 +02006308 && strchr(NUMERIC_SPECVARS_STR, arg[0]) /* 1st char is special variable */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006309 ) {
6310 /* ${?:0}, ${#[:]%0} etc */
6311 exp_saveptr = var + 1;
6312 } else {
6313 /* ${?}, ${var}, ${var:0}, ${var[:]%0} etc */
6314 exp_saveptr = var+1 + strcspn(var+1, VAR_ENCODED_SUBST_OPS);
6315 }
6316 exp_op = exp_save = *exp_saveptr;
6317 if (exp_op) {
6318 exp_word = exp_saveptr + 1;
6319 if (exp_op == ':') {
6320 exp_op = *exp_word++;
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02006321//TODO: try ${var:} and ${var:bogus} in non-bash config
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01006322 if (BASH_SUBSTR
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02006323 && (!exp_op || !strchr(MINUS_PLUS_EQUAL_QUESTION, exp_op))
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006324 ) {
6325 /* oops... it's ${var:N[:M]}, not ${var:?xxx} or some such */
6326 exp_op = ':';
6327 exp_word--;
6328 }
6329 }
6330 *exp_saveptr = '\0';
6331 } /* else: it's not an expansion op, but bare ${var} */
6332 }
6333
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02006334 /* Look up the variable in question */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006335 if (isdigit(var[0])) {
Denys Vlasenko77a7b552010-09-09 12:40:03 +02006336 /* parse_dollar should have vetted var for us */
Denys Vlasenko8a6a4612018-07-19 12:14:47 +02006337 int nn = xatoi_positive(var);
6338 if (nn < G.global_argc)
6339 val = G.global_argv[nn];
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006340 /* else val remains NULL: $N with too big N */
6341 } else {
6342 switch (var[0]) {
6343 case '$': /* pid */
6344 val = utoa(G.root_pid);
6345 break;
6346 case '!': /* bg pid */
6347 val = G.last_bg_pid ? utoa(G.last_bg_pid) : "";
6348 break;
6349 case '?': /* exitcode */
6350 val = utoa(G.last_exitcode);
6351 break;
6352 case '#': /* argc */
6353 val = utoa(G.global_argc ? G.global_argc-1 : 0);
6354 break;
6355 default:
6356 val = get_local_var_value(var);
6357 }
6358 }
6359
6360 /* Handle any expansions */
6361 if (exp_op == 'L') {
Denys Vlasenkoc538d5b2014-08-13 09:57:44 +02006362 reinit_unicode_for_hush();
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006363 debug_printf_expand("expand: length(%s)=", val);
Denys Vlasenkoc538d5b2014-08-13 09:57:44 +02006364 val = utoa(val ? unicode_strlen(val) : 0);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006365 debug_printf_expand("%s\n", val);
6366 } else if (exp_op) {
6367 if (exp_op == '%' || exp_op == '#') {
6368 /* Standard-mandated substring removal ops:
6369 * ${parameter%word} - remove smallest suffix pattern
6370 * ${parameter%%word} - remove largest suffix pattern
6371 * ${parameter#word} - remove smallest prefix pattern
6372 * ${parameter##word} - remove largest prefix pattern
6373 *
6374 * Word is expanded to produce a glob pattern.
6375 * Then var's value is matched to it and matching part removed.
6376 */
Denys Vlasenkob762c782018-07-17 14:21:38 +02006377//FIXME: ${x#...${...}...}
6378//should evaluate inner ${...} even if x is "" and no shrinking of it is possible -
6379//inner ${...} may have side effects!
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006380 if (val && val[0]) {
Denys Vlasenko4f870492010-09-10 11:06:01 +02006381 char *t;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006382 char *exp_exp_word;
6383 char *loc;
6384 unsigned scan_flags = pick_scan(exp_op, *exp_word);
Denys Vlasenkoe4dcba12010-10-28 18:57:19 +02006385 if (exp_op == *exp_word) /* ## or %% */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006386 exp_word++;
Denys Vlasenko55f81332018-03-02 18:12:12 +01006387 debug_printf_expand("expand: exp_word:'%s'\n", exp_word);
Denys Vlasenkob762c782018-07-17 14:21:38 +02006388 exp_exp_word = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ 1, /*unbackslash:*/ 0);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006389 if (exp_exp_word)
6390 exp_word = exp_exp_word;
Denys Vlasenkob762c782018-07-17 14:21:38 +02006391 debug_printf_expand("expand: exp_word:'%s'\n", exp_word);
6392 /*
6393 * HACK ALERT. We depend here on the fact that
Denys Vlasenko4f870492010-09-10 11:06:01 +02006394 * G.global_argv and results of utoa and get_local_var_value
6395 * are actually in writable memory:
Denys Vlasenkob762c782018-07-17 14:21:38 +02006396 * scan_and_match momentarily stores NULs there.
6397 */
Denys Vlasenko4f870492010-09-10 11:06:01 +02006398 t = (char*)val;
6399 loc = scan_and_match(t, exp_word, scan_flags);
Denys Vlasenko55f81332018-03-02 18:12:12 +01006400 debug_printf_expand("op:%c str:'%s' pat:'%s' res:'%s'\n", exp_op, t, exp_word, loc);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006401 free(exp_exp_word);
6402 if (loc) { /* match was found */
6403 if (scan_flags & SCAN_MATCH_LEFT_HALF) /* #[#] */
Denys Vlasenko4f870492010-09-10 11:06:01 +02006404 val = loc; /* take right part */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006405 else /* %[%] */
Denys Vlasenko4f870492010-09-10 11:06:01 +02006406 val = to_be_freed = xstrndup(val, loc - val); /* left */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006407 }
6408 }
6409 }
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01006410#if BASH_PATTERN_SUBST
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006411 else if (exp_op == '/' || exp_op == '\\') {
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02006412 /* It's ${var/[/]pattern[/repl]} thing.
6413 * Note that in encoded form it has TWO parts:
6414 * var/pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL>
Denys Vlasenko4f870492010-09-10 11:06:01 +02006415 * and if // is used, it is encoded as \:
6416 * var\pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL>
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02006417 */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006418 if (val && val[0]) {
Denys Vlasenko4f870492010-09-10 11:06:01 +02006419 /* pattern uses non-standard expansion.
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02006420 * repl should be unbackslashed and globbed
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02006421 * by the usual expansion rules:
Denys Vlasenkode026252018-04-05 17:04:53 +02006422 * >az >bz
6423 * v='a bz'; echo "${v/a*z/a*z}" #prints "a*z"
6424 * v='a bz'; echo "${v/a*z/\z}" #prints "z"
6425 * v='a bz'; echo ${v/a*z/a*z} #prints "az"
6426 * v='a bz'; echo ${v/a*z/\z} #prints "z"
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02006427 * (note that a*z _pattern_ is never globbed!)
6428 */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006429 char *pattern, *repl, *t;
Denys Vlasenkob762c782018-07-17 14:21:38 +02006430 pattern = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ 1, /*unbackslash:*/ 0);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006431 if (!pattern)
6432 pattern = xstrdup(exp_word);
6433 debug_printf_varexp("pattern:'%s'->'%s'\n", exp_word, pattern);
6434 *p++ = SPECIAL_VAR_SYMBOL;
6435 exp_word = p;
6436 p = strchr(p, SPECIAL_VAR_SYMBOL);
6437 *p = '\0';
Denys Vlasenkob762c782018-07-17 14:21:38 +02006438 repl = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ 1, /*unbackslash:*/ 1);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006439 debug_printf_varexp("repl:'%s'->'%s'\n", exp_word, repl);
6440 /* HACK ALERT. We depend here on the fact that
6441 * G.global_argv and results of utoa and get_local_var_value
6442 * are actually in writable memory:
6443 * replace_pattern momentarily stores NULs there. */
6444 t = (char*)val;
6445 to_be_freed = replace_pattern(t,
6446 pattern,
6447 (repl ? repl : exp_word),
6448 exp_op);
6449 if (to_be_freed) /* at least one replace happened */
6450 val = to_be_freed;
6451 free(pattern);
6452 free(repl);
Denys Vlasenkocba79a82018-01-25 14:07:40 +01006453 } else {
6454 /* Empty variable always gives nothing */
6455 // "v=''; echo ${v/*/w}" prints "", not "w"
6456 /* Just skip "replace" part */
6457 *p++ = SPECIAL_VAR_SYMBOL;
6458 p = strchr(p, SPECIAL_VAR_SYMBOL);
6459 *p = '\0';
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006460 }
6461 }
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01006462#endif /* BASH_PATTERN_SUBST */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006463 else if (exp_op == ':') {
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01006464#if BASH_SUBSTR && ENABLE_FEATURE_SH_MATH
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006465 /* It's ${var:N[:M]} bashism.
6466 * Note that in encoded form it has TWO parts:
6467 * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL>
6468 */
6469 arith_t beg, len;
Denys Vlasenko063847d2010-09-15 13:33:02 +02006470 const char *errmsg;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006471
Denys Vlasenko063847d2010-09-15 13:33:02 +02006472 beg = expand_and_evaluate_arith(exp_word, &errmsg);
6473 if (errmsg)
6474 goto arith_err;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006475 debug_printf_varexp("beg:'%s'=%lld\n", exp_word, (long long)beg);
6476 *p++ = SPECIAL_VAR_SYMBOL;
6477 exp_word = p;
6478 p = strchr(p, SPECIAL_VAR_SYMBOL);
6479 *p = '\0';
Denys Vlasenko063847d2010-09-15 13:33:02 +02006480 len = expand_and_evaluate_arith(exp_word, &errmsg);
6481 if (errmsg)
6482 goto arith_err;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006483 debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len);
Denys Vlasenkoe32b6502017-07-17 16:46:57 +02006484 if (beg < 0) {
6485 /* negative beg counts from the end */
6486 beg = (arith_t)strlen(val) + beg;
6487 if (beg < 0) /* ${v: -999999} is "" */
6488 beg = len = 0;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006489 }
Denys Vlasenkoe32b6502017-07-17 16:46:57 +02006490 debug_printf_varexp("from val:'%s'\n", val);
6491 if (len < 0) {
6492 /* in bash, len=-n means strlen()-n */
6493 len = (arith_t)strlen(val) - beg + len;
6494 if (len < 0) /* bash compat */
Denys Vlasenko39701202017-08-02 19:44:05 +02006495 msg_and_die_if_script("%s: substring expression < 0", var);
Denys Vlasenkoe32b6502017-07-17 16:46:57 +02006496 }
Denys Vlasenko0ba80e42017-07-17 16:50:20 +02006497 if (len <= 0 || !val || beg >= strlen(val)) {
Denys Vlasenkoe32b6502017-07-17 16:46:57 +02006498 arith_err:
6499 val = NULL;
6500 } else {
6501 /* Paranoia. What if user entered 9999999999999
6502 * which fits in arith_t but not int? */
6503 if (len >= INT_MAX)
6504 len = INT_MAX;
6505 val = to_be_freed = xstrndup(val + beg, len);
6506 }
6507 debug_printf_varexp("val:'%s'\n", val);
6508#else /* not (HUSH_SUBSTR_EXPANSION && FEATURE_SH_MATH) */
Denys Vlasenko39701202017-08-02 19:44:05 +02006509 msg_and_die_if_script("malformed ${%s:...}", var);
Denys Vlasenkoe32b6502017-07-17 16:46:57 +02006510 val = NULL;
6511#endif
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006512 } else { /* one of "-=+?" */
6513 /* Standard-mandated substitution ops:
6514 * ${var?word} - indicate error if unset
6515 * If var is unset, word (or a message indicating it is unset
6516 * if word is null) is written to standard error
6517 * and the shell exits with a non-zero exit status.
6518 * Otherwise, the value of var is substituted.
6519 * ${var-word} - use default value
6520 * If var is unset, word is substituted.
6521 * ${var=word} - assign and use default value
6522 * If var is unset, word is assigned to var.
6523 * In all cases, final value of var is substituted.
6524 * ${var+word} - use alternative value
6525 * If var is unset, null is substituted.
6526 * Otherwise, word is substituted.
6527 *
6528 * Word is subjected to tilde expansion, parameter expansion,
6529 * command substitution, and arithmetic expansion.
6530 * If word is not needed, it is not expanded.
6531 *
6532 * Colon forms (${var:-word}, ${var:=word} etc) do the same,
6533 * but also treat null var as if it is unset.
Denys Vlasenko294eb462018-07-20 16:18:59 +02006534 *
6535 * Word-splitting and single quote behavior:
6536 *
6537 * $ f() { for i; do echo "|$i|"; done; };
6538 *
6539 * $ x=; f ${x:?'x y' z}
6540 * bash: x: x y z #BUG: does not abort, ${} results in empty expansion
6541 * $ x=; f "${x:?'x y' z}"
6542 * bash: x: x y z # dash prints: dash: x: 'x y' z #BUG: does not abort, ${} results in ""
6543 *
6544 * $ x=; f ${x:='x y' z}
6545 * |x|
6546 * |y|
6547 * |z|
6548 * $ x=; f "${x:='x y' z}"
6549 * |'x y' z|
6550 *
Denys Vlasenko4c3c8a12018-07-20 19:11:09 +02006551 * $ x=x; f ${x:+'x y' z}
Denys Vlasenko294eb462018-07-20 16:18:59 +02006552 * |x y|
6553 * |z|
6554 * $ x=x; f "${x:+'x y' z}"
6555 * |'x y' z|
6556 *
6557 * $ x=; f ${x:-'x y' z}
6558 * |x y|
6559 * |z|
6560 * $ x=; f "${x:-'x y' z}"
6561 * |'x y' z|
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006562 */
6563 int use_word = (!val || ((exp_save == ':') && !val[0]));
6564 if (exp_op == '+')
6565 use_word = !use_word;
6566 debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op,
6567 (exp_save == ':') ? "true" : "false", use_word);
6568 if (use_word) {
Denys Vlasenko294eb462018-07-20 16:18:59 +02006569 if (exp_op == '+' || exp_op == '-') {
6570 /* ${var+word} - use alternative value */
6571 /* ${var-word} - use default value */
6572 n = encode_then_append_var_plusminus(output, n, exp_word,
6573 /*dquoted:*/ (arg0 & 0x80)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006574 );
Denys Vlasenko294eb462018-07-20 16:18:59 +02006575 val = NULL;
6576 } else {
6577 /* ${var?word} - indicate error if unset */
6578 /* ${var=word} - assign and use default value */
6579 to_be_freed = encode_then_expand_vararg(exp_word,
6580 /*handle_squotes:*/ !(arg0 & 0x80),
6581 /*unbackslash:*/ 0
6582 );
6583 if (to_be_freed)
6584 exp_word = to_be_freed;
6585 if (exp_op == '?') {
6586 /* mimic bash message */
6587 msg_and_die_if_script("%s: %s",
6588 var,
6589 exp_word[0]
6590 ? exp_word
6591 : "parameter null or not set"
6592 /* ash has more specific messages, a-la: */
6593 /*: (exp_save == ':' ? "parameter null or not set" : "parameter not set")*/
6594 );
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006595//TODO: how interactive bash aborts expansion mid-command?
Denys Vlasenko168579a2018-07-19 13:45:54 +02006596//It aborts the entire line, returns to prompt:
Denys Vlasenko8a6a4612018-07-19 12:14:47 +02006597// $ f() { for i; do echo "|$i|"; done; }; x=; f "${x:?'x y' z}"; echo YO
6598// bash: x: x y z
6599// $
6600// ("echo YO" is not executed, neither the f function call)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006601 } else {
Denys Vlasenko294eb462018-07-20 16:18:59 +02006602 val = exp_word;
6603 }
6604 if (exp_op == '=') {
6605 /* ${var=[word]} or ${var:=[word]} */
6606 if (isdigit(var[0]) || var[0] == '#') {
6607 /* mimic bash message */
6608 msg_and_die_if_script("$%s: cannot assign in this way", var);
6609 val = NULL;
6610 } else {
6611 char *new_var = xasprintf("%s=%s", var, val);
6612 set_local_var(new_var, /*flag:*/ 0);
6613 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006614 }
6615 }
6616 }
6617 } /* one of "-=+?" */
6618
6619 *exp_saveptr = exp_save;
6620 } /* if (exp_op) */
6621
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006622 arg[0] = arg0;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006623 *pp = p;
Denys Vlasenko8a6a4612018-07-19 12:14:47 +02006624
Denys Vlasenko168579a2018-07-19 13:45:54 +02006625 n = append_str_maybe_ifs_split(output, n, first_ch, val);
Denys Vlasenko8a6a4612018-07-19 12:14:47 +02006626
6627 free(to_be_freed);
6628 return n;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006629}
6630
6631/* Expand all variable references in given string, adding words to list[]
6632 * at n, n+1,... positions. Return updated n (so that list[n] is next one
6633 * to be filled). This routine is extremely tricky: has to deal with
6634 * variables/parameters with whitespace, $* and $@, and constructs like
6635 * 'echo -$*-'. If you play here, you must run testsuite afterwards! */
Denys Vlasenko95d48f22010-09-08 13:58:55 +02006636static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006637{
Denys Vlasenko95d48f22010-09-08 13:58:55 +02006638 /* output->o_expflags & EXP_FLAG_SINGLEWORD (0x80) if we are in
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006639 * expansion of right-hand side of assignment == 1-element expand.
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006640 */
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006641 char cant_be_null = 0; /* only bit 0x80 matters */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006642 char *p;
6643
Denys Vlasenko95d48f22010-09-08 13:58:55 +02006644 debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg,
6645 !!(output->o_expflags & EXP_FLAG_SINGLEWORD));
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006646 debug_print_list("expand_vars_to_list[0]", output, n);
6647
6648 while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) {
6649 char first_ch;
Denys Vlasenko0b883582016-12-23 16:49:07 +01006650#if ENABLE_FEATURE_SH_MATH
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006651 char arith_buf[sizeof(arith_t)*3 + 2];
6652#endif
Denys Vlasenko6e42b892011-08-01 18:16:43 +02006653
Denys Vlasenko168579a2018-07-19 13:45:54 +02006654 if (output->ended_in_ifs) {
Denys Vlasenko6e42b892011-08-01 18:16:43 +02006655 o_addchr(output, '\0');
6656 n = o_save_ptr(output, n);
Denys Vlasenko168579a2018-07-19 13:45:54 +02006657 output->ended_in_ifs = 0;
Denys Vlasenko6e42b892011-08-01 18:16:43 +02006658 }
6659
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006660 o_addblock(output, arg, p - arg);
6661 debug_print_list("expand_vars_to_list[1]", output, n);
6662 arg = ++p;
6663 p = strchr(p, SPECIAL_VAR_SYMBOL);
6664
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006665 /* Fetch special var name (if it is indeed one of them)
6666 * and quote bit, force the bit on if singleword expansion -
6667 * important for not getting v=$@ expand to many words. */
Denys Vlasenko95d48f22010-09-08 13:58:55 +02006668 first_ch = arg[0] | (output->o_expflags & EXP_FLAG_SINGLEWORD);
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006669
6670 /* Is this variable quoted and thus expansion can't be null?
6671 * "$@" is special. Even if quoted, it can still
6672 * expand to nothing (not even an empty string),
6673 * thus it is excluded. */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006674 if ((first_ch & 0x7f) != '@')
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006675 cant_be_null |= first_ch;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006676
6677 switch (first_ch & 0x7f) {
6678 /* Highest bit in first_ch indicates that var is double-quoted */
6679 case '*':
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02006680 case '@': {
6681 int i;
6682 if (!G.global_argv[1])
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006683 break;
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02006684 i = 1;
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006685 cant_be_null |= first_ch; /* do it for "$@" _now_, when we know it's not empty */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006686 if (!(first_ch & 0x80)) { /* unquoted $* or $@ */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006687 while (G.global_argv[i]) {
Denys Vlasenko168579a2018-07-19 13:45:54 +02006688 n = expand_on_ifs(output, n, G.global_argv[i]);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006689 debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1);
6690 if (G.global_argv[i++][0] && G.global_argv[i]) {
6691 /* this argv[] is not empty and not last:
6692 * put terminating NUL, start new word */
6693 o_addchr(output, '\0');
6694 debug_print_list("expand_vars_to_list[2]", output, n);
6695 n = o_save_ptr(output, n);
6696 debug_print_list("expand_vars_to_list[3]", output, n);
6697 }
6698 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006699 } else
Denys Vlasenko95d48f22010-09-08 13:58:55 +02006700 /* If EXP_FLAG_SINGLEWORD, we handle assignment 'a=....$@.....'
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006701 * and in this case should treat it like '$*' - see 'else...' below */
Denys Vlasenko6ffaa002018-03-31 00:46:07 +02006702 if (first_ch == (char)('@'|0x80) /* quoted $@ */
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006703 && !(output->o_expflags & EXP_FLAG_SINGLEWORD) /* not v="$@" case */
Denys Vlasenko95d48f22010-09-08 13:58:55 +02006704 ) {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006705 while (1) {
6706 o_addQstr(output, G.global_argv[i]);
6707 if (++i >= G.global_argc)
6708 break;
6709 o_addchr(output, '\0');
6710 debug_print_list("expand_vars_to_list[4]", output, n);
6711 n = o_save_ptr(output, n);
6712 }
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006713 } else { /* quoted $* (or v="$@" case): add as one word */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006714 while (1) {
6715 o_addQstr(output, G.global_argv[i]);
6716 if (!G.global_argv[++i])
6717 break;
6718 if (G.ifs[0])
6719 o_addchr(output, G.ifs[0]);
6720 }
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02006721 output->has_quoted_part = 1;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006722 }
6723 break;
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02006724 }
Denys Vlasenko18e8b612018-07-20 14:24:56 +02006725 case SPECIAL_VAR_SYMBOL: {
6726 /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_SYMBOL> */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006727 /* "Empty variable", used to make "" etc to not disappear */
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02006728 output->has_quoted_part = 1;
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006729 cant_be_null = 0x80;
Denys Vlasenko18e8b612018-07-20 14:24:56 +02006730 arg++;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006731 break;
Denys Vlasenko18e8b612018-07-20 14:24:56 +02006732 }
Denys Vlasenko932b9972018-01-11 12:39:48 +01006733 case SPECIAL_VAR_QUOTED_SVS:
6734 /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_QUOTED_SVS><SPECIAL_VAR_SYMBOL> */
Denys Vlasenko18e8b612018-07-20 14:24:56 +02006735 /* "^C variable", represents literal ^C char (possible in scripts) */
Denys Vlasenko83e434d2018-07-20 17:36:06 +02006736 o_addchr(output, SPECIAL_VAR_SYMBOL);
Denys Vlasenko932b9972018-01-11 12:39:48 +01006737 arg++;
Denys Vlasenko932b9972018-01-11 12:39:48 +01006738 break;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006739#if ENABLE_HUSH_TICK
Denys Vlasenko18e8b612018-07-20 14:24:56 +02006740 case '`': {
6741 /* <SPECIAL_VAR_SYMBOL>`cmd<SPECIAL_VAR_SYMBOL> */
Denys Vlasenko116b50a2018-07-19 11:16:53 +02006742 o_string subst_result = NULL_O_STRING;
6743
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006744 *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006745 arg++;
6746 /* Can't just stuff it into output o_string,
6747 * expanded result may need to be globbed
Denys Vlasenko10ad6222017-04-17 16:13:32 +02006748 * and $IFS-split */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006749 debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch);
6750 G.last_exitcode = process_command_subs(&subst_result, arg);
Denys Vlasenko5fa05052018-04-03 11:21:13 +02006751 G.expand_exitcode = G.last_exitcode;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006752 debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data);
Denys Vlasenko168579a2018-07-19 13:45:54 +02006753 n = append_str_maybe_ifs_split(output, n, first_ch, subst_result.data);
Denys Vlasenko18567402018-07-20 17:51:31 +02006754 o_free(&subst_result);
Denys Vlasenko18e8b612018-07-20 14:24:56 +02006755 break;
Denys Vlasenko116b50a2018-07-19 11:16:53 +02006756 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006757#endif
Denys Vlasenko0b883582016-12-23 16:49:07 +01006758#if ENABLE_FEATURE_SH_MATH
Denys Vlasenko18e8b612018-07-20 14:24:56 +02006759 case '+': {
6760 /* <SPECIAL_VAR_SYMBOL>+arith<SPECIAL_VAR_SYMBOL> */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006761 arith_t res;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006762
6763 arg++; /* skip '+' */
6764 *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */
6765 debug_printf_subst("ARITH '%s' first_ch %x\n", arg, first_ch);
Denys Vlasenko063847d2010-09-15 13:33:02 +02006766 res = expand_and_evaluate_arith(arg, NULL);
Denys Vlasenkobed7c812010-09-16 11:50:46 +02006767 debug_printf_subst("ARITH RES '"ARITH_FMT"'\n", res);
6768 sprintf(arith_buf, ARITH_FMT, res);
Denys Vlasenko18e8b612018-07-20 14:24:56 +02006769 o_addstr(output, arith_buf);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006770 break;
6771 }
6772#endif
Denys Vlasenko8a6a4612018-07-19 12:14:47 +02006773 default:
Denys Vlasenko18e8b612018-07-20 14:24:56 +02006774 /* <SPECIAL_VAR_SYMBOL>varname[ops]<SPECIAL_VAR_SYMBOL> */
Denys Vlasenko168579a2018-07-19 13:45:54 +02006775 n = expand_one_var(output, n, first_ch, arg, &p);
Denys Vlasenko18e8b612018-07-20 14:24:56 +02006776 break;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006777 } /* switch (char after <SPECIAL_VAR_SYMBOL>) */
6778
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006779 /* Restore NULL'ed SPECIAL_VAR_SYMBOL.
6780 * Do the check to avoid writing to a const string. */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006781 if (*p != SPECIAL_VAR_SYMBOL)
6782 *p = SPECIAL_VAR_SYMBOL;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006783 arg = ++p;
6784 } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */
6785
Denys Vlasenko4c3c8a12018-07-20 19:11:09 +02006786 if (*arg) {
6787 /* handle trailing string */
Denys Vlasenko168579a2018-07-19 13:45:54 +02006788 if (output->ended_in_ifs) {
Denys Vlasenko6e42b892011-08-01 18:16:43 +02006789 o_addchr(output, '\0');
6790 n = o_save_ptr(output, n);
6791 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006792 debug_print_list("expand_vars_to_list[a]", output, n);
6793 /* this part is literal, and it was already pre-quoted
Denys Vlasenko294eb462018-07-20 16:18:59 +02006794 * if needed (much earlier), do not use o_addQstr here!
6795 */
6796 o_addstr(output, arg);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006797 debug_print_list("expand_vars_to_list[b]", output, n);
Denys Vlasenko18567402018-07-20 17:51:31 +02006798 } else
6799 if (output->length == o_get_last_ptr(output, n) /* expansion is empty */
Denys Vlasenko83e434d2018-07-20 17:36:06 +02006800 && !(cant_be_null & 0x80) /* and all vars were not quoted */
6801 && !output->has_quoted_part
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006802 ) {
6803 n--;
6804 /* allow to reuse list[n] later without re-growth */
6805 output->has_empty_slot = 1;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006806 }
6807
6808 return n;
6809}
6810
Denys Vlasenko95d48f22010-09-08 13:58:55 +02006811static char **expand_variables(char **argv, unsigned expflags)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006812{
6813 int n;
6814 char **list;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006815 o_string output = NULL_O_STRING;
6816
Denys Vlasenko95d48f22010-09-08 13:58:55 +02006817 output.o_expflags = expflags;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006818
6819 n = 0;
Denys Vlasenko57235be2018-07-20 14:45:12 +02006820 for (;;) {
6821 /* go to next list[n] */
6822 output.ended_in_ifs = 0;
6823 n = o_save_ptr(&output, n);
6824
6825 if (!*argv)
6826 break;
6827
6828 /* expand argv[i] */
6829 n = expand_vars_to_list(&output, n, *argv++);
Denys Vlasenko294eb462018-07-20 16:18:59 +02006830 /* if (!output->has_empty_slot) -- need this?? */
6831 o_addchr(&output, '\0');
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006832 }
6833 debug_print_list("expand_variables", &output, n);
6834
6835 /* output.data (malloced in one block) gets returned in "list" */
6836 list = o_finalize_list(&output, n);
6837 debug_print_strings("expand_variables[1]", list);
6838 return list;
6839}
6840
6841static char **expand_strvec_to_strvec(char **argv)
6842{
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02006843 return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006844}
6845
Denys Vlasenko11752d42018-04-03 08:20:58 +02006846#if defined(CMD_SINGLEWORD_NOGLOB)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006847static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
6848{
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02006849 return expand_variables(argv, EXP_FLAG_SINGLEWORD);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006850}
6851#endif
6852
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02006853/* Used for expansion of right hand of assignments,
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02006854 * $((...)), heredocs, variable expansion parts.
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02006855 *
6856 * NB: should NOT do globbing!
6857 * "export v=/bin/c*; env | grep ^v=" outputs "v=/bin/c*"
6858 */
Denys Vlasenko34179952018-04-11 13:47:59 +02006859static char *expand_string_to_string(const char *str, int EXP_flags, int do_unbackslash)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006860{
Denys Vlasenko637982f2017-07-06 01:52:23 +02006861#if !BASH_PATTERN_SUBST && !ENABLE_HUSH_CASE
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02006862 const int do_unbackslash = 1;
Denys Vlasenko34179952018-04-11 13:47:59 +02006863 const int EXP_flags = EXP_FLAG_ESC_GLOB_CHARS;
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02006864#endif
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006865 char *argv[2], **list;
6866
Denys Vlasenkoebee4102010-09-10 10:17:53 +02006867 debug_printf_expand("string_to_string<='%s'\n", str);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006868 /* This is generally an optimization, but it also
6869 * handles "", which otherwise trips over !list[0] check below.
6870 * (is this ever happens that we actually get str="" here?)
6871 */
6872 if (!strchr(str, SPECIAL_VAR_SYMBOL) && !strchr(str, '\\')) {
6873 //TODO: Can use on strings with \ too, just unbackslash() them?
Denys Vlasenkoebee4102010-09-10 10:17:53 +02006874 debug_printf_expand("string_to_string(fast)=>'%s'\n", str);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006875 return xstrdup(str);
6876 }
6877
6878 argv[0] = (char*)str;
6879 argv[1] = NULL;
Denys Vlasenko34179952018-04-11 13:47:59 +02006880 list = expand_variables(argv, EXP_flags | EXP_FLAG_SINGLEWORD);
Denys Vlasenko2e711012018-07-18 16:02:25 +02006881 if (!list[0]) {
6882 /* Example where it happens:
6883 * x=; echo ${x:-"$@"}
6884 */
6885 ((char*)list)[0] = '\0';
6886 } else {
6887 if (HUSH_DEBUG)
6888 if (list[1])
6889 bb_error_msg_and_die("BUG in varexp2");
6890 /* actually, just move string 2*sizeof(char*) bytes back */
6891 overlapping_strcpy((char*)list, list[0]);
6892 if (do_unbackslash)
6893 unbackslash((char*)list);
6894 }
Denys Vlasenkoebee4102010-09-10 10:17:53 +02006895 debug_printf_expand("string_to_string=>'%s'\n", (char*)list);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006896 return (char*)list;
6897}
6898
Denys Vlasenkoabf75562018-04-02 17:25:18 +02006899#if 0
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006900static char* expand_strvec_to_string(char **argv)
6901{
6902 char **list;
6903
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02006904 list = expand_variables(argv, EXP_FLAG_SINGLEWORD);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006905 /* Convert all NULs to spaces */
6906 if (list[0]) {
6907 int n = 1;
6908 while (list[n]) {
6909 if (HUSH_DEBUG)
6910 if (list[n-1] + strlen(list[n-1]) + 1 != list[n])
6911 bb_error_msg_and_die("BUG in varexp3");
6912 /* bash uses ' ' regardless of $IFS contents */
6913 list[n][-1] = ' ';
6914 n++;
6915 }
6916 }
Denys Vlasenko78c9c732016-09-29 01:44:17 +02006917 overlapping_strcpy((char*)list, list[0] ? list[0] : "");
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006918 debug_printf_expand("strvec_to_string='%s'\n", (char*)list);
6919 return (char*)list;
6920}
Denys Vlasenko1f191122018-01-11 13:17:30 +01006921#endif
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006922
6923static char **expand_assignments(char **argv, int count)
6924{
6925 int i;
6926 char **p;
6927
6928 G.expanded_assignments = p = NULL;
6929 /* Expand assignments into one string each */
6930 for (i = 0; i < count; i++) {
Denys Vlasenko34179952018-04-11 13:47:59 +02006931 p = add_string_to_strings(p,
6932 expand_string_to_string(argv[i],
6933 EXP_FLAG_ESC_GLOB_CHARS,
6934 /*unbackslash:*/ 1
6935 )
6936 );
6937 G.expanded_assignments = p;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006938 }
6939 G.expanded_assignments = NULL;
6940 return p;
6941}
6942
6943
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006944static void switch_off_special_sigs(unsigned mask)
6945{
6946 unsigned sig = 0;
6947 while ((mask >>= 1) != 0) {
6948 sig++;
6949 if (!(mask & 1))
6950 continue;
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006951#if ENABLE_HUSH_TRAP
6952 if (G_traps) {
6953 if (G_traps[sig] && !G_traps[sig][0])
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006954 /* trap is '', has to remain SIG_IGN */
6955 continue;
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006956 free(G_traps[sig]);
6957 G_traps[sig] = NULL;
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006958 }
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006959#endif
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006960 /* We are here only if no trap or trap was not '' */
Denys Vlasenko0806e402011-05-12 23:06:20 +02006961 install_sighandler(sig, SIG_DFL);
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006962 }
6963}
6964
Denys Vlasenkob347df92011-08-09 22:49:15 +02006965#if BB_MMU
6966/* never called */
6967void re_execute_shell(char ***to_free, const char *s,
6968 char *g_argv0, char **g_argv,
6969 char **builtin_argv) NORETURN;
6970
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006971static void reset_traps_to_defaults(void)
6972{
6973 /* This function is always called in a child shell
6974 * after fork (not vfork, NOMMU doesn't use this function).
6975 */
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006976 IF_HUSH_TRAP(unsigned sig;)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006977 unsigned mask;
6978
6979 /* Child shells are not interactive.
6980 * SIGTTIN/SIGTTOU/SIGTSTP should not have special handling.
6981 * Testcase: (while :; do :; done) + ^Z should background.
6982 * Same goes for SIGTERM, SIGHUP, SIGINT.
6983 */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006984 mask = (G.special_sig_mask & SPECIAL_INTERACTIVE_SIGS) | G_fatal_sig_mask;
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006985 if (!G_traps && !mask)
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006986 return; /* already no traps and no special sigs */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006987
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006988 /* Switch off special sigs */
6989 switch_off_special_sigs(mask);
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006990# if ENABLE_HUSH_JOB
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006991 G_fatal_sig_mask = 0;
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006992# endif
Denys Vlasenko10c01312011-05-11 11:49:21 +02006993 G.special_sig_mask &= ~SPECIAL_INTERACTIVE_SIGS;
Denys Vlasenkof58f7052011-05-12 02:10:33 +02006994 /* SIGQUIT,SIGCHLD and maybe SPECIAL_JOBSTOP_SIGS
6995 * remain set in G.special_sig_mask */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006996
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006997# if ENABLE_HUSH_TRAP
6998 if (!G_traps)
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006999 return;
7000
7001 /* Reset all sigs to default except ones with empty traps */
7002 for (sig = 0; sig < NSIG; sig++) {
Denys Vlasenko7a85c602017-01-08 17:40:18 +01007003 if (!G_traps[sig])
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02007004 continue; /* no trap: nothing to do */
Denys Vlasenko7a85c602017-01-08 17:40:18 +01007005 if (!G_traps[sig][0])
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02007006 continue; /* empty trap: has to remain SIG_IGN */
7007 /* sig has non-empty trap, reset it: */
Denys Vlasenko7a85c602017-01-08 17:40:18 +01007008 free(G_traps[sig]);
7009 G_traps[sig] = NULL;
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02007010 /* There is no signal for trap 0 (EXIT) */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007011 if (sig == 0)
7012 continue;
Denys Vlasenko0806e402011-05-12 23:06:20 +02007013 install_sighandler(sig, pick_sighandler(sig));
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007014 }
Denys Vlasenko7a85c602017-01-08 17:40:18 +01007015# endif
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007016}
7017
7018#else /* !BB_MMU */
7019
7020static void re_execute_shell(char ***to_free, const char *s,
7021 char *g_argv0, char **g_argv,
7022 char **builtin_argv) NORETURN;
7023static void re_execute_shell(char ***to_free, const char *s,
7024 char *g_argv0, char **g_argv,
7025 char **builtin_argv)
7026{
7027# define NOMMU_HACK_FMT ("-$%x:%x:%x:%x:%x:%llx" IF_HUSH_LOOPS(":%x"))
7028 /* delims + 2 * (number of bytes in printed hex numbers) */
7029 char param_buf[sizeof(NOMMU_HACK_FMT) + 2 * (sizeof(int)*6 + sizeof(long long)*1)];
7030 char *heredoc_argv[4];
7031 struct variable *cur;
7032# if ENABLE_HUSH_FUNCTIONS
7033 struct function *funcp;
7034# endif
7035 char **argv, **pp;
7036 unsigned cnt;
7037 unsigned long long empty_trap_mask;
7038
7039 if (!g_argv0) { /* heredoc */
7040 argv = heredoc_argv;
7041 argv[0] = (char *) G.argv0_for_re_execing;
7042 argv[1] = (char *) "-<";
7043 argv[2] = (char *) s;
7044 argv[3] = NULL;
7045 pp = &argv[3]; /* used as pointer to empty environment */
7046 goto do_exec;
7047 }
7048
7049 cnt = 0;
7050 pp = builtin_argv;
7051 if (pp) while (*pp++)
7052 cnt++;
7053
7054 empty_trap_mask = 0;
Denys Vlasenko7a85c602017-01-08 17:40:18 +01007055 if (G_traps) {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007056 int sig;
7057 for (sig = 1; sig < NSIG; sig++) {
Denys Vlasenko7a85c602017-01-08 17:40:18 +01007058 if (G_traps[sig] && !G_traps[sig][0])
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007059 empty_trap_mask |= 1LL << sig;
7060 }
7061 }
7062
7063 sprintf(param_buf, NOMMU_HACK_FMT
7064 , (unsigned) G.root_pid
7065 , (unsigned) G.root_ppid
7066 , (unsigned) G.last_bg_pid
7067 , (unsigned) G.last_exitcode
7068 , cnt
7069 , empty_trap_mask
7070 IF_HUSH_LOOPS(, G.depth_of_loop)
7071 );
7072# undef NOMMU_HACK_FMT
7073 /* 1:hush 2:-$<pid>:<pid>:<exitcode>:<etc...> <vars...> <funcs...>
7074 * 3:-c 4:<cmd> 5:<arg0> <argN...> 6:NULL
7075 */
7076 cnt += 6;
7077 for (cur = G.top_var; cur; cur = cur->next) {
7078 if (!cur->flg_export || cur->flg_read_only)
7079 cnt += 2;
7080 }
7081# if ENABLE_HUSH_FUNCTIONS
7082 for (funcp = G.top_func; funcp; funcp = funcp->next)
7083 cnt += 3;
7084# endif
7085 pp = g_argv;
7086 while (*pp++)
7087 cnt++;
7088 *to_free = argv = pp = xzalloc(sizeof(argv[0]) * cnt);
7089 *pp++ = (char *) G.argv0_for_re_execing;
7090 *pp++ = param_buf;
7091 for (cur = G.top_var; cur; cur = cur->next) {
7092 if (strcmp(cur->varstr, hush_version_str) == 0)
7093 continue;
7094 if (cur->flg_read_only) {
7095 *pp++ = (char *) "-R";
7096 *pp++ = cur->varstr;
7097 } else if (!cur->flg_export) {
7098 *pp++ = (char *) "-V";
7099 *pp++ = cur->varstr;
7100 }
7101 }
7102# if ENABLE_HUSH_FUNCTIONS
7103 for (funcp = G.top_func; funcp; funcp = funcp->next) {
7104 *pp++ = (char *) "-F";
7105 *pp++ = funcp->name;
7106 *pp++ = funcp->body_as_string;
7107 }
7108# endif
7109 /* We can pass activated traps here. Say, -Tnn:trap_string
7110 *
7111 * However, POSIX says that subshells reset signals with traps
7112 * to SIG_DFL.
7113 * I tested bash-3.2 and it not only does that with true subshells
7114 * of the form ( list ), but with any forked children shells.
7115 * I set trap "echo W" WINCH; and then tried:
7116 *
7117 * { echo 1; sleep 20; echo 2; } &
7118 * while true; do echo 1; sleep 20; echo 2; break; done &
7119 * true | { echo 1; sleep 20; echo 2; } | cat
7120 *
7121 * In all these cases sending SIGWINCH to the child shell
7122 * did not run the trap. If I add trap "echo V" WINCH;
7123 * _inside_ group (just before echo 1), it works.
7124 *
7125 * I conclude it means we don't need to pass active traps here.
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007126 */
7127 *pp++ = (char *) "-c";
7128 *pp++ = (char *) s;
7129 if (builtin_argv) {
7130 while (*++builtin_argv)
7131 *pp++ = *builtin_argv;
7132 *pp++ = (char *) "";
7133 }
7134 *pp++ = g_argv0;
7135 while (*g_argv)
7136 *pp++ = *g_argv++;
7137 /* *pp = NULL; - is already there */
7138 pp = environ;
7139
7140 do_exec:
7141 debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
Denys Vlasenko75e77de2011-05-12 13:12:47 +02007142 /* Don't propagate SIG_IGN to the child */
7143 if (SPECIAL_JOBSTOP_SIGS != 0)
7144 switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007145 execve(bb_busybox_exec_path, argv, pp);
7146 /* Fallback. Useful for init=/bin/hush usage etc */
7147 if (argv[0][0] == '/')
7148 execve(argv[0], argv, pp);
7149 xfunc_error_retval = 127;
7150 bb_error_msg_and_die("can't re-execute the shell");
7151}
7152#endif /* !BB_MMU */
7153
7154
7155static int run_and_free_list(struct pipe *pi);
7156
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00007157/* Executing from string: eval, sh -c '...'
Denis Vlasenkob6e65562009-04-03 16:49:04 +00007158 * or from file: /etc/profile, . file, sh <script>, sh (intereactive)
7159 * end_trigger controls how often we stop parsing
7160 * NUL: parse all, execute, return
7161 * ';': parse till ';' or newline, execute, repeat till EOF
7162 */
7163static void parse_and_run_stream(struct in_str *inp, int end_trigger)
Eric Andersen25f27032001-04-26 23:22:31 +00007164{
Denys Vlasenko00243b02009-11-16 02:00:03 +01007165 /* Why we need empty flag?
7166 * An obscure corner case "false; ``; echo $?":
7167 * empty command in `` should still set $? to 0.
7168 * But we can't just set $? to 0 at the start,
7169 * this breaks "false; echo `echo $?`" case.
7170 */
7171 bool empty = 1;
Denis Vlasenkob6e65562009-04-03 16:49:04 +00007172 while (1) {
7173 struct pipe *pipe_list;
Denis Vlasenkof8d01d32008-06-14 17:13:20 +00007174
Denys Vlasenkoa1463192011-01-18 17:55:04 +01007175#if ENABLE_HUSH_INTERACTIVE
Denys Vlasenko8d6eab32018-04-07 17:01:31 +02007176 if (end_trigger == ';') {
7177 G.promptmode = 0; /* PS1 */
7178 debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode);
7179 }
Denys Vlasenkoa1463192011-01-18 17:55:04 +01007180#endif
Denys Vlasenko474cb202018-07-24 13:03:03 +02007181 pipe_list = parse_stream(NULL, NULL, inp, end_trigger);
Denys Vlasenkocecbc982011-03-30 18:54:52 +02007182 if (!pipe_list || pipe_list == ERR_PTR) { /* EOF/error */
7183 /* If we are in "big" script
7184 * (not in `cmd` or something similar)...
7185 */
7186 if (pipe_list == ERR_PTR && end_trigger == ';') {
7187 /* Discard cached input (rest of line) */
7188 int ch = inp->last_char;
7189 while (ch != EOF && ch != '\n') {
7190 //bb_error_msg("Discarded:'%c'", ch);
7191 ch = i_getch(inp);
7192 }
7193 /* Force prompt */
7194 inp->p = NULL;
7195 /* This stream isn't empty */
7196 empty = 0;
7197 continue;
7198 }
7199 if (!pipe_list && empty)
Denys Vlasenko00243b02009-11-16 02:00:03 +01007200 G.last_exitcode = 0;
Denis Vlasenkob6e65562009-04-03 16:49:04 +00007201 break;
Denys Vlasenko00243b02009-11-16 02:00:03 +01007202 }
Denis Vlasenkob6e65562009-04-03 16:49:04 +00007203 debug_print_tree(pipe_list, 0);
7204 debug_printf_exec("parse_and_run_stream: run_and_free_list\n");
7205 run_and_free_list(pipe_list);
Denys Vlasenko00243b02009-11-16 02:00:03 +01007206 empty = 0;
Denys Vlasenko04b46bc2016-10-01 22:28:03 +02007207 if (G_flag_return_in_progress == 1)
Denys Vlasenko68d5cb52011-03-24 02:50:03 +01007208 break;
Denis Vlasenkob6e65562009-04-03 16:49:04 +00007209 }
Eric Andersen25f27032001-04-26 23:22:31 +00007210}
7211
Denis Vlasenkob6e65562009-04-03 16:49:04 +00007212static void parse_and_run_string(const char *s)
Eric Andersen25f27032001-04-26 23:22:31 +00007213{
7214 struct in_str input;
Denys Vlasenkoaa617ac2018-02-13 15:30:13 +01007215 //IF_HUSH_LINENO_VAR(unsigned sv = G.lineno;)
7216
Eric Andersen25f27032001-04-26 23:22:31 +00007217 setup_string_in_str(&input, s);
Denis Vlasenkob6e65562009-04-03 16:49:04 +00007218 parse_and_run_stream(&input, '\0');
Denys Vlasenkoaa617ac2018-02-13 15:30:13 +01007219 //IF_HUSH_LINENO_VAR(G.lineno = sv;)
Eric Andersen25f27032001-04-26 23:22:31 +00007220}
7221
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02007222static void parse_and_run_file(HFILE *fp)
Eric Andersen25f27032001-04-26 23:22:31 +00007223{
Eric Andersen25f27032001-04-26 23:22:31 +00007224 struct in_str input;
Denys Vlasenkoaa617ac2018-02-13 15:30:13 +01007225 IF_HUSH_LINENO_VAR(unsigned sv = G.lineno;)
Denys Vlasenko6aad1dd2018-01-19 15:37:04 +01007226
Denys Vlasenkoaa617ac2018-02-13 15:30:13 +01007227 IF_HUSH_LINENO_VAR(G.lineno = 1;)
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02007228 setup_file_in_str(&input, fp);
Denis Vlasenkob6e65562009-04-03 16:49:04 +00007229 parse_and_run_stream(&input, ';');
Denys Vlasenkoaa617ac2018-02-13 15:30:13 +01007230 IF_HUSH_LINENO_VAR(G.lineno = sv;)
Eric Andersen25f27032001-04-26 23:22:31 +00007231}
7232
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007233#if ENABLE_HUSH_TICK
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02007234static int generate_stream_from_string(const char *s, pid_t *pid_p)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007235{
7236 pid_t pid;
7237 int channel[2];
7238# if !BB_MMU
7239 char **to_free = NULL;
7240# endif
7241
7242 xpipe(channel);
7243 pid = BB_MMU ? xfork() : xvfork();
7244 if (pid == 0) { /* child */
7245 disable_restore_tty_pgrp_on_exit();
7246 /* Process substitution is not considered to be usual
7247 * 'command execution'.
7248 * SUSv3 says ctrl-Z should be ignored, ctrl-C should not.
7249 */
7250 bb_signals(0
7251 + (1 << SIGTSTP)
7252 + (1 << SIGTTIN)
7253 + (1 << SIGTTOU)
7254 , SIG_IGN);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007255 close(channel[0]); /* NB: close _first_, then move fd! */
7256 xmove_fd(channel[1], 1);
Denys Vlasenko7a85c602017-01-08 17:40:18 +01007257# if ENABLE_HUSH_TRAP
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007258 /* Awful hack for `trap` or $(trap).
7259 *
7260 * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
7261 * contains an example where "trap" is executed in a subshell:
7262 *
7263 * save_traps=$(trap)
7264 * ...
7265 * eval "$save_traps"
7266 *
7267 * Standard does not say that "trap" in subshell shall print
7268 * parent shell's traps. It only says that its output
7269 * must have suitable form, but then, in the above example
7270 * (which is not supposed to be normative), it implies that.
7271 *
7272 * bash (and probably other shell) does implement it
7273 * (traps are reset to defaults, but "trap" still shows them),
7274 * but as a result, "trap" logic is hopelessly messed up:
7275 *
7276 * # trap
7277 * trap -- 'echo Ho' SIGWINCH <--- we have a handler
7278 * # (trap) <--- trap is in subshell - no output (correct, traps are reset)
7279 * # true | trap <--- trap is in subshell - no output (ditto)
7280 * # echo `true | trap` <--- in subshell - output (but traps are reset!)
7281 * trap -- 'echo Ho' SIGWINCH
7282 * # echo `(trap)` <--- in subshell in subshell - output
7283 * trap -- 'echo Ho' SIGWINCH
7284 * # echo `true | (trap)` <--- in subshell in subshell in subshell - output!
7285 * trap -- 'echo Ho' SIGWINCH
7286 *
7287 * The rules when to forget and when to not forget traps
7288 * get really complex and nonsensical.
7289 *
7290 * Our solution: ONLY bare $(trap) or `trap` is special.
7291 */
7292 s = skip_whitespace(s);
Denys Vlasenko8dff01d2015-03-12 17:48:34 +01007293 if (is_prefixed_with(s, "trap")
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007294 && skip_whitespace(s + 4)[0] == '\0'
7295 ) {
7296 static const char *const argv[] = { NULL, NULL };
7297 builtin_trap((char**)argv);
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02007298 fflush_all(); /* important */
7299 _exit(0);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007300 }
Denys Vlasenko7a85c602017-01-08 17:40:18 +01007301# endif
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007302# if BB_MMU
Denys Vlasenko7c5f18a2018-07-26 15:21:50 +02007303 /* Prevent it from trying to handle ctrl-z etc */
7304 IF_HUSH_JOB(G.run_list_level = 1;)
7305 CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007306 reset_traps_to_defaults();
Denys Vlasenko7c5f18a2018-07-26 15:21:50 +02007307 IF_HUSH_MODE_X(G.x_mode_depth++;)
Denys Vlasenko9dda9272018-07-27 14:12:05 +02007308 //bb_error_msg("%s: ++x_mode_depth=%d", __func__, G.x_mode_depth);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007309 parse_and_run_string(s);
7310 _exit(G.last_exitcode);
7311# else
7312 /* We re-execute after vfork on NOMMU. This makes this script safe:
7313 * yes "0123456789012345678901234567890" | dd bs=32 count=64k >BIG
7314 * huge=`cat BIG` # was blocking here forever
7315 * echo OK
7316 */
7317 re_execute_shell(&to_free,
7318 s,
7319 G.global_argv[0],
7320 G.global_argv + 1,
7321 NULL);
7322# endif
7323 }
7324
7325 /* parent */
7326 *pid_p = pid;
7327# if ENABLE_HUSH_FAST
7328 G.count_SIGCHLD++;
7329//bb_error_msg("[%d] fork in generate_stream_from_string:"
7330// " G.count_SIGCHLD:%d G.handled_SIGCHLD:%d",
7331// getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
7332# endif
7333 enable_restore_tty_pgrp_on_exit();
7334# if !BB_MMU
7335 free(to_free);
7336# endif
7337 close(channel[1]);
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02007338 return channel[0];
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007339}
7340
7341/* Return code is exit status of the process that is run. */
7342static int process_command_subs(o_string *dest, const char *s)
7343{
7344 FILE *fp;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007345 pid_t pid;
7346 int status, ch, eol_cnt;
7347
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02007348 fp = xfdopen_for_read(generate_stream_from_string(s, &pid));
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007349
7350 /* Now send results of command back into original context */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007351 eol_cnt = 0;
Denys Vlasenkoaa617ac2018-02-13 15:30:13 +01007352 while ((ch = getc(fp)) != EOF) {
7353 if (ch == '\0')
7354 continue;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007355 if (ch == '\n') {
7356 eol_cnt++;
7357 continue;
7358 }
7359 while (eol_cnt) {
7360 o_addchr(dest, '\n');
7361 eol_cnt--;
7362 }
7363 o_addQchr(dest, ch);
7364 }
7365
7366 debug_printf("done reading from `cmd` pipe, closing it\n");
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02007367 fclose(fp);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007368 /* We need to extract exitcode. Test case
7369 * "true; echo `sleep 1; false` $?"
7370 * should print 1 */
7371 safe_waitpid(pid, &status, 0);
7372 debug_printf("child exited. returning its exitcode:%d\n", WEXITSTATUS(status));
7373 return WEXITSTATUS(status);
7374}
7375#endif /* ENABLE_HUSH_TICK */
7376
7377
7378static void setup_heredoc(struct redir_struct *redir)
7379{
7380 struct fd_pair pair;
7381 pid_t pid;
7382 int len, written;
7383 /* the _body_ of heredoc (misleading field name) */
7384 const char *heredoc = redir->rd_filename;
7385 char *expanded;
7386#if !BB_MMU
7387 char **to_free;
7388#endif
7389
7390 expanded = NULL;
7391 if (!(redir->rd_dup & HEREDOC_QUOTED)) {
Denys Vlasenkob762c782018-07-17 14:21:38 +02007392 expanded = encode_then_expand_string(heredoc);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007393 if (expanded)
7394 heredoc = expanded;
7395 }
7396 len = strlen(heredoc);
7397
7398 close(redir->rd_fd); /* often saves dup2+close in xmove_fd */
7399 xpiped_pair(pair);
7400 xmove_fd(pair.rd, redir->rd_fd);
7401
7402 /* Try writing without forking. Newer kernels have
7403 * dynamically growing pipes. Must use non-blocking write! */
7404 ndelay_on(pair.wr);
7405 while (1) {
7406 written = write(pair.wr, heredoc, len);
7407 if (written <= 0)
7408 break;
7409 len -= written;
7410 if (len == 0) {
7411 close(pair.wr);
7412 free(expanded);
7413 return;
7414 }
7415 heredoc += written;
7416 }
7417 ndelay_off(pair.wr);
7418
7419 /* Okay, pipe buffer was not big enough */
7420 /* Note: we must not create a stray child (bastard? :)
7421 * for the unsuspecting parent process. Child creates a grandchild
7422 * and exits before parent execs the process which consumes heredoc
7423 * (that exec happens after we return from this function) */
7424#if !BB_MMU
7425 to_free = NULL;
7426#endif
7427 pid = xvfork();
7428 if (pid == 0) {
7429 /* child */
7430 disable_restore_tty_pgrp_on_exit();
7431 pid = BB_MMU ? xfork() : xvfork();
7432 if (pid != 0)
7433 _exit(0);
7434 /* grandchild */
7435 close(redir->rd_fd); /* read side of the pipe */
7436#if BB_MMU
7437 full_write(pair.wr, heredoc, len); /* may loop or block */
7438 _exit(0);
7439#else
7440 /* Delegate blocking writes to another process */
7441 xmove_fd(pair.wr, STDOUT_FILENO);
7442 re_execute_shell(&to_free, heredoc, NULL, NULL, NULL);
7443#endif
7444 }
7445 /* parent */
7446#if ENABLE_HUSH_FAST
7447 G.count_SIGCHLD++;
7448//bb_error_msg("[%d] fork in setup_heredoc: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
7449#endif
7450 enable_restore_tty_pgrp_on_exit();
7451#if !BB_MMU
7452 free(to_free);
7453#endif
7454 close(pair.wr);
7455 free(expanded);
7456 wait(NULL); /* wait till child has died */
7457}
7458
Denys Vlasenko2db74612017-07-07 22:07:28 +02007459struct squirrel {
7460 int orig_fd;
7461 int moved_to;
7462 /* moved_to = n: fd was moved to n; restore back to orig_fd after redir */
7463 /* moved_to = -1: fd was opened by redirect; close orig_fd after redir */
7464};
7465
Denys Vlasenko621fc502017-07-24 12:42:17 +02007466static struct squirrel *append_squirrel(struct squirrel *sq, int i, int orig, int moved)
7467{
7468 sq = xrealloc(sq, (i + 2) * sizeof(sq[0]));
7469 sq[i].orig_fd = orig;
7470 sq[i].moved_to = moved;
7471 sq[i+1].orig_fd = -1; /* end marker */
7472 return sq;
7473}
7474
Denys Vlasenko2db74612017-07-07 22:07:28 +02007475static struct squirrel *add_squirrel(struct squirrel *sq, int fd, int avoid_fd)
7476{
Denys Vlasenko621fc502017-07-24 12:42:17 +02007477 int moved_to;
Denys Vlasenko32fdf2f2017-07-31 04:32:06 +02007478 int i;
Denys Vlasenko2db74612017-07-07 22:07:28 +02007479
Denys Vlasenkod16e6122017-08-11 15:41:39 +02007480 i = 0;
7481 if (sq) for (; sq[i].orig_fd >= 0; i++) {
Denys Vlasenko2db74612017-07-07 22:07:28 +02007482 /* If we collide with an already moved fd... */
7483 if (fd == sq[i].moved_to) {
Denys Vlasenko9acd63c2018-03-28 18:35:07 +02007484 sq[i].moved_to = dup_CLOEXEC(sq[i].moved_to, avoid_fd);
Denys Vlasenko2db74612017-07-07 22:07:28 +02007485 debug_printf_redir("redirect_fd %d: already busy, moving to %d\n", fd, sq[i].moved_to);
7486 if (sq[i].moved_to < 0) /* what? */
7487 xfunc_die();
7488 return sq;
7489 }
7490 if (fd == sq[i].orig_fd) {
7491 /* Example: echo Hello >/dev/null 1>&2 */
7492 debug_printf_redir("redirect_fd %d: already moved\n", fd);
7493 return sq;
7494 }
Denys Vlasenko2db74612017-07-07 22:07:28 +02007495 }
7496
Denys Vlasenko2db74612017-07-07 22:07:28 +02007497 /* If this fd is open, we move and remember it; if it's closed, moved_to = -1 */
Denys Vlasenko9acd63c2018-03-28 18:35:07 +02007498 moved_to = dup_CLOEXEC(fd, avoid_fd);
Denys Vlasenko621fc502017-07-24 12:42:17 +02007499 debug_printf_redir("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, moved_to);
7500 if (moved_to < 0 && errno != EBADF)
Denys Vlasenko2db74612017-07-07 22:07:28 +02007501 xfunc_die();
Denys Vlasenko621fc502017-07-24 12:42:17 +02007502 return append_squirrel(sq, i, fd, moved_to);
Denys Vlasenko2db74612017-07-07 22:07:28 +02007503}
7504
Denys Vlasenko657e9002017-07-30 23:34:04 +02007505static struct squirrel *add_squirrel_closed(struct squirrel *sq, int fd)
7506{
7507 int i;
7508
Denys Vlasenkod16e6122017-08-11 15:41:39 +02007509 i = 0;
7510 if (sq) for (; sq[i].orig_fd >= 0; i++) {
Denys Vlasenko657e9002017-07-30 23:34:04 +02007511 /* If we collide with an already moved fd... */
7512 if (fd == sq[i].orig_fd) {
7513 /* Examples:
7514 * "echo 3>FILE 3>&- 3>FILE"
7515 * "echo 3>&- 3>FILE"
7516 * No need for last redirect to insert
7517 * another "need to close 3" indicator.
7518 */
7519 debug_printf_redir("redirect_fd %d: already moved or closed\n", fd);
7520 return sq;
7521 }
Denys Vlasenko657e9002017-07-30 23:34:04 +02007522 }
7523
7524 debug_printf_redir("redirect_fd %d: previous fd was closed\n", fd);
7525 return append_squirrel(sq, i, fd, -1);
7526}
7527
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02007528/* fd: redirect wants this fd to be used (e.g. 3>file).
7529 * Move all conflicting internally used fds,
7530 * and remember them so that we can restore them later.
7531 */
Denys Vlasenko657e9002017-07-30 23:34:04 +02007532static int save_fd_on_redirect(int fd, int avoid_fd, struct squirrel **sqp)
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02007533{
Denys Vlasenko2db74612017-07-07 22:07:28 +02007534 if (avoid_fd < 9) /* the important case here is that it can be -1 */
7535 avoid_fd = 9;
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02007536
7537#if ENABLE_HUSH_INTERACTIVE
Denys Vlasenko32fdf2f2017-07-31 04:32:06 +02007538 if (fd == G.interactive_fd) {
7539 /* Testcase: "ls -l /proc/$$/fd 255>&-" should work */
Denys Vlasenko657e9002017-07-30 23:34:04 +02007540 G.interactive_fd = xdup_CLOEXEC_and_close(G.interactive_fd, avoid_fd);
Denys Vlasenko2db74612017-07-07 22:07:28 +02007541 debug_printf_redir("redirect_fd %d: matches interactive_fd, moving it to %d\n", fd, G.interactive_fd);
7542 return 1; /* "we closed fd" */
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02007543 }
7544#endif
Denys Vlasenko945e9b02018-07-24 18:01:22 +02007545 /* Are we called from setup_redirects(squirrel==NULL)
7546 * in redirect in a [v]forked child?
7547 */
7548 if (sqp == NULL) {
7549 /* No need to move script fds.
7550 * For NOMMU case, it's actively wrong: we'd change ->fd
7551 * fields in memory for the parent, but parent's fds
7552 * aren't be moved, it would use wrong fd!
7553 * Reproducer: "cmd 3>FILE" in script.
7554 * If we would call move_HFILEs_on_redirect(), child would:
7555 * fcntl64(3, F_DUPFD_CLOEXEC, 10) = 10
7556 * close(3) = 0
7557 * and change ->fd to 10 if fd#3 is a script fd. WRONG.
7558 */
7559 //bb_error_msg("sqp == NULL: [v]forked child");
7560 return 0;
7561 }
7562
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02007563 /* If this one of script's fds? */
7564 if (move_HFILEs_on_redirect(fd, avoid_fd))
7565 return 1; /* yes. "we closed fd" (actually moved it) */
7566
Denys Vlasenko945e9b02018-07-24 18:01:22 +02007567 /* Are we called for "exec 3>FILE"? Came through
7568 * redirect_and_varexp_helper(squirrel=ERR_PTR) -> setup_redirects(ERR_PTR)
7569 * This case used to fail for this script:
7570 * exec 3>FILE
7571 * echo Ok
7572 * ...100000 more lines...
7573 * echo Ok
7574 * as follows:
7575 * read(3, "exec 3>FILE\necho Ok\necho Ok"..., 1024) = 1024
7576 * open("FILE", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 4
7577 * dup2(4, 3) = 3
7578 * ^^^^^^^^ oops, we lost fd#3 opened to our script!
7579 * close(4) = 0
7580 * write(1, "Ok\n", 3) = 3
7581 * ... = 3
7582 * write(1, "Ok\n", 3) = 3
7583 * read(3, 0x94fbc08, 1024) = -1 EBADF (Bad file descriptor)
7584 * ^^^^^^^^ oops, wrong fd!!!
7585 * With this case separate from sqp == NULL and *after* move_HFILEs,
7586 * it now works:
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02007587 */
Denys Vlasenko945e9b02018-07-24 18:01:22 +02007588 if (sqp == ERR_PTR) {
7589 /* Don't preserve redirected fds: exec is _meant_ to change these */
7590 //bb_error_msg("sqp == ERR_PTR: exec >FILE");
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02007591 return 0;
Denys Vlasenko945e9b02018-07-24 18:01:22 +02007592 }
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02007593
Denys Vlasenko2db74612017-07-07 22:07:28 +02007594 /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
7595 *sqp = add_squirrel(*sqp, fd, avoid_fd);
7596 return 0; /* "we did not close fd" */
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02007597}
7598
Denys Vlasenko2db74612017-07-07 22:07:28 +02007599static void restore_redirects(struct squirrel *sq)
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02007600{
Denys Vlasenko2db74612017-07-07 22:07:28 +02007601 if (sq) {
Denys Vlasenko32fdf2f2017-07-31 04:32:06 +02007602 int i;
7603 for (i = 0; sq[i].orig_fd >= 0; i++) {
Denys Vlasenko2db74612017-07-07 22:07:28 +02007604 if (sq[i].moved_to >= 0) {
7605 /* We simply die on error */
7606 debug_printf_redir("restoring redirected fd from %d to %d\n", sq[i].moved_to, sq[i].orig_fd);
7607 xmove_fd(sq[i].moved_to, sq[i].orig_fd);
7608 } else {
7609 /* cmd1 9>FILE; cmd2_should_see_fd9_closed */
7610 debug_printf_redir("restoring redirected fd %d: closing it\n", sq[i].orig_fd);
7611 close(sq[i].orig_fd);
7612 }
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02007613 }
Denys Vlasenko2db74612017-07-07 22:07:28 +02007614 free(sq);
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02007615 }
7616
Denys Vlasenko2db74612017-07-07 22:07:28 +02007617 /* If moved, G.interactive_fd stays on new fd, not restoring it */
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02007618}
7619
Denys Vlasenkobf1c3442017-07-31 04:54:53 +02007620#if ENABLE_FEATURE_SH_STANDALONE && BB_MMU
Denys Vlasenko5b3d2eb2017-07-31 18:02:28 +02007621static void close_saved_fds_and_FILE_fds(void)
Denys Vlasenkobf1c3442017-07-31 04:54:53 +02007622{
7623 if (G_interactive_fd)
7624 close(G_interactive_fd);
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02007625 close_all_HFILE_list();
Denys Vlasenkobf1c3442017-07-31 04:54:53 +02007626}
7627#endif
7628
Denys Vlasenko32fdf2f2017-07-31 04:32:06 +02007629static int internally_opened_fd(int fd, struct squirrel *sq)
7630{
7631 int i;
7632
7633#if ENABLE_HUSH_INTERACTIVE
7634 if (fd == G.interactive_fd)
7635 return 1;
7636#endif
7637 /* If this one of script's fds? */
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02007638 if (fd_in_HFILEs(fd))
Denys Vlasenko32fdf2f2017-07-31 04:32:06 +02007639 return 1;
7640
7641 if (sq) for (i = 0; sq[i].orig_fd >= 0; i++) {
7642 if (fd == sq[i].moved_to)
7643 return 1;
7644 }
7645 return 0;
7646}
7647
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007648/* squirrel != NULL means we squirrel away copies of stdin, stdout,
7649 * and stderr if they are redirected. */
Denys Vlasenko2db74612017-07-07 22:07:28 +02007650static int setup_redirects(struct command *prog, struct squirrel **sqp)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007651{
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007652 struct redir_struct *redir;
7653
7654 for (redir = prog->redirects; redir; redir = redir->next) {
Denys Vlasenko657e9002017-07-30 23:34:04 +02007655 int newfd;
7656 int closed;
7657
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007658 if (redir->rd_type == REDIRECT_HEREDOC2) {
Denys Vlasenko869994c2016-08-20 15:16:00 +02007659 /* "rd_fd<<HERE" case */
Denys Vlasenko657e9002017-07-30 23:34:04 +02007660 save_fd_on_redirect(redir->rd_fd, /*avoid:*/ 0, sqp);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007661 /* for REDIRECT_HEREDOC2, rd_filename holds _contents_
7662 * of the heredoc */
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02007663 debug_printf_redir("set heredoc '%s'\n",
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007664 redir->rd_filename);
7665 setup_heredoc(redir);
7666 continue;
7667 }
7668
7669 if (redir->rd_dup == REDIRFD_TO_FILE) {
Denys Vlasenko869994c2016-08-20 15:16:00 +02007670 /* "rd_fd<*>file" case (<*> is <,>,>>,<>) */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007671 char *p;
Denys Vlasenko657e9002017-07-30 23:34:04 +02007672 int mode;
7673
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007674 if (redir->rd_filename == NULL) {
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02007675 /* Examples:
Denys Vlasenkod6a37d82016-09-20 16:22:24 +02007676 * "cmd >" (no filename)
7677 * "cmd > <file" (2nd redirect starts too early)
7678 */
Denys Vlasenko39701202017-08-02 19:44:05 +02007679 syntax_error("invalid redirect");
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007680 continue;
7681 }
7682 mode = redir_table[redir->rd_type].mode;
Denys Vlasenko34179952018-04-11 13:47:59 +02007683 p = expand_string_to_string(redir->rd_filename,
7684 EXP_FLAG_ESC_GLOB_CHARS, /*unbackslash:*/ 1);
Denys Vlasenko657e9002017-07-30 23:34:04 +02007685 newfd = open_or_warn(p, mode);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007686 free(p);
Denys Vlasenko657e9002017-07-30 23:34:04 +02007687 if (newfd < 0) {
Denys Vlasenko869994c2016-08-20 15:16:00 +02007688 /* Error message from open_or_warn can be lost
7689 * if stderr has been redirected, but bash
7690 * and ash both lose it as well
7691 * (though zsh doesn't!)
7692 */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007693 return 1;
7694 }
Denys Vlasenko657e9002017-07-30 23:34:04 +02007695 if (newfd == redir->rd_fd && sqp) {
Denys Vlasenko621fc502017-07-24 12:42:17 +02007696 /* open() gave us precisely the fd we wanted.
7697 * This means that this fd was not busy
7698 * (not opened to anywhere).
7699 * Remember to close it on restore:
7700 */
Denys Vlasenko657e9002017-07-30 23:34:04 +02007701 *sqp = add_squirrel_closed(*sqp, newfd);
7702 debug_printf_redir("redir to previously closed fd %d\n", newfd);
Denys Vlasenko621fc502017-07-24 12:42:17 +02007703 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007704 } else {
Denys Vlasenko657e9002017-07-30 23:34:04 +02007705 /* "rd_fd>&rd_dup" or "rd_fd>&-" case */
7706 newfd = redir->rd_dup;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007707 }
7708
Denys Vlasenko657e9002017-07-30 23:34:04 +02007709 if (newfd == redir->rd_fd)
7710 continue;
7711
7712 /* if "N>FILE": move newfd to redir->rd_fd */
7713 /* if "N>&M": dup newfd to redir->rd_fd */
7714 /* if "N>&-": close redir->rd_fd (newfd is REDIRFD_CLOSE) */
7715
7716 closed = save_fd_on_redirect(redir->rd_fd, /*avoid:*/ newfd, sqp);
7717 if (newfd == REDIRFD_CLOSE) {
7718 /* "N>&-" means "close me" */
7719 if (!closed) {
7720 /* ^^^ optimization: saving may already
7721 * have closed it. If not... */
7722 close(redir->rd_fd);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007723 }
Denys Vlasenko657e9002017-07-30 23:34:04 +02007724 /* Sometimes we do another close on restore, getting EBADF.
7725 * Consider "echo 3>FILE 3>&-"
7726 * first redirect remembers "need to close 3",
7727 * and second redirect closes 3! Restore code then closes 3 again.
7728 */
7729 } else {
Denys Vlasenko32fdf2f2017-07-31 04:32:06 +02007730 /* if newfd is a script fd or saved fd, simulate EBADF */
Denys Vlasenko945e9b02018-07-24 18:01:22 +02007731 if (internally_opened_fd(newfd, sqp && sqp != ERR_PTR ? *sqp : NULL)) {
Denys Vlasenko32fdf2f2017-07-31 04:32:06 +02007732 //errno = EBADF;
7733 //bb_perror_msg_and_die("can't duplicate file descriptor");
7734 newfd = -1; /* same effect as code above */
7735 }
Denys Vlasenko657e9002017-07-30 23:34:04 +02007736 xdup2(newfd, redir->rd_fd);
7737 if (redir->rd_dup == REDIRFD_TO_FILE)
7738 /* "rd_fd > FILE" */
7739 close(newfd);
7740 /* else: "rd_fd > rd_dup" */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007741 }
7742 }
7743 return 0;
7744}
7745
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007746static char *find_in_path(const char *arg)
7747{
7748 char *ret = NULL;
7749 const char *PATH = get_local_var_value("PATH");
7750
7751 if (!PATH)
7752 return NULL;
7753
7754 while (1) {
7755 const char *end = strchrnul(PATH, ':');
7756 int sz = end - PATH; /* must be int! */
7757
7758 free(ret);
7759 if (sz != 0) {
7760 ret = xasprintf("%.*s/%s", sz, PATH, arg);
7761 } else {
7762 /* We have xxx::yyyy in $PATH,
7763 * it means "use current dir" */
7764 ret = xstrdup(arg);
7765 }
7766 if (access(ret, F_OK) == 0)
7767 break;
7768
7769 if (*end == '\0') {
7770 free(ret);
7771 return NULL;
7772 }
7773 PATH = end + 1;
7774 }
7775
7776 return ret;
7777}
7778
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02007779static const struct built_in_command *find_builtin_helper(const char *name,
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007780 const struct built_in_command *x,
7781 const struct built_in_command *end)
7782{
7783 while (x != end) {
7784 if (strcmp(name, x->b_cmd) != 0) {
7785 x++;
7786 continue;
7787 }
7788 debug_printf_exec("found builtin '%s'\n", name);
7789 return x;
7790 }
7791 return NULL;
7792}
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02007793static const struct built_in_command *find_builtin1(const char *name)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007794{
7795 return find_builtin_helper(name, bltins1, &bltins1[ARRAY_SIZE(bltins1)]);
7796}
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02007797static const struct built_in_command *find_builtin(const char *name)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007798{
7799 const struct built_in_command *x = find_builtin1(name);
7800 if (x)
7801 return x;
7802 return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]);
7803}
7804
Denys Vlasenko99496dc2018-06-26 15:36:58 +02007805static void remove_nested_vars(void)
7806{
7807 struct variable *cur;
7808 struct variable **cur_pp;
7809
7810 cur_pp = &G.top_var;
7811 while ((cur = *cur_pp) != NULL) {
7812 if (cur->var_nest_level <= G.var_nest_level) {
7813 cur_pp = &cur->next;
7814 continue;
7815 }
7816 /* Unexport */
7817 if (cur->flg_export) {
7818 debug_printf_env("unexporting nested '%s'/%u\n", cur->varstr, cur->var_nest_level);
7819 bb_unsetenv(cur->varstr);
7820 }
7821 /* Remove from global list */
7822 *cur_pp = cur->next;
7823 /* Free */
7824 if (!cur->max_len) {
7825 debug_printf_env("freeing nested '%s'/%u\n", cur->varstr, cur->var_nest_level);
7826 free(cur->varstr);
7827 }
7828 free(cur);
7829 }
7830}
7831
7832static void enter_var_nest_level(void)
7833{
7834 G.var_nest_level++;
7835 debug_printf_env("var_nest_level++ %u\n", G.var_nest_level);
7836
7837 /* Try: f() { echo -n .; f; }; f
7838 * struct variable::var_nest_level is uint16_t,
7839 * thus limiting recursion to < 2^16.
7840 * In any case, with 8 Mbyte stack SEGV happens
7841 * not too long after 2^16 recursions anyway.
7842 */
7843 if (G.var_nest_level > 0xff00)
7844 bb_error_msg_and_die("fatal recursion (depth %u)", G.var_nest_level);
7845}
7846
7847static void leave_var_nest_level(void)
7848{
7849 G.var_nest_level--;
7850 debug_printf_env("var_nest_level-- %u\n", G.var_nest_level);
7851 if (HUSH_DEBUG && (int)G.var_nest_level < 0)
7852 bb_error_msg_and_die("BUG: nesting underflow");
7853
7854 remove_nested_vars();
7855}
7856
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007857#if ENABLE_HUSH_FUNCTIONS
7858static struct function **find_function_slot(const char *name)
7859{
Denys Vlasenko33f7c8f2018-03-06 17:21:57 +01007860 struct function *funcp;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007861 struct function **funcpp = &G.top_func;
Denys Vlasenko33f7c8f2018-03-06 17:21:57 +01007862
7863 while ((funcp = *funcpp) != NULL) {
7864 if (strcmp(name, funcp->name) == 0) {
7865 debug_printf_exec("found function '%s'\n", name);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007866 break;
7867 }
Denys Vlasenko33f7c8f2018-03-06 17:21:57 +01007868 funcpp = &funcp->next;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007869 }
7870 return funcpp;
7871}
7872
Denys Vlasenko33f7c8f2018-03-06 17:21:57 +01007873static ALWAYS_INLINE const struct function *find_function(const char *name)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007874{
7875 const struct function *funcp = *find_function_slot(name);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007876 return funcp;
7877}
7878
7879/* Note: takes ownership on name ptr */
7880static struct function *new_function(char *name)
7881{
7882 struct function **funcpp = find_function_slot(name);
7883 struct function *funcp = *funcpp;
7884
7885 if (funcp != NULL) {
7886 struct command *cmd = funcp->parent_cmd;
7887 debug_printf_exec("func %p parent_cmd %p\n", funcp, cmd);
7888 if (!cmd) {
7889 debug_printf_exec("freeing & replacing function '%s'\n", funcp->name);
7890 free(funcp->name);
7891 /* Note: if !funcp->body, do not free body_as_string!
7892 * This is a special case of "-F name body" function:
7893 * body_as_string was not malloced! */
7894 if (funcp->body) {
7895 free_pipe_list(funcp->body);
7896# if !BB_MMU
7897 free(funcp->body_as_string);
7898# endif
7899 }
7900 } else {
7901 debug_printf_exec("reinserting in tree & replacing function '%s'\n", funcp->name);
7902 cmd->argv[0] = funcp->name;
7903 cmd->group = funcp->body;
7904# if !BB_MMU
7905 cmd->group_as_string = funcp->body_as_string;
7906# endif
7907 }
7908 } else {
7909 debug_printf_exec("remembering new function '%s'\n", name);
7910 funcp = *funcpp = xzalloc(sizeof(*funcp));
7911 /*funcp->next = NULL;*/
7912 }
7913
7914 funcp->name = name;
7915 return funcp;
7916}
7917
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01007918# if ENABLE_HUSH_UNSET
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007919static void unset_func(const char *name)
7920{
7921 struct function **funcpp = find_function_slot(name);
7922 struct function *funcp = *funcpp;
7923
7924 if (funcp != NULL) {
7925 debug_printf_exec("freeing function '%s'\n", funcp->name);
7926 *funcpp = funcp->next;
7927 /* funcp is unlinked now, deleting it.
7928 * Note: if !funcp->body, the function was created by
7929 * "-F name body", do not free ->body_as_string
7930 * and ->name as they were not malloced. */
7931 if (funcp->body) {
7932 free_pipe_list(funcp->body);
7933 free(funcp->name);
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01007934# if !BB_MMU
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007935 free(funcp->body_as_string);
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01007936# endif
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007937 }
7938 free(funcp);
7939 }
7940}
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01007941# endif
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007942
7943# if BB_MMU
7944#define exec_function(to_free, funcp, argv) \
7945 exec_function(funcp, argv)
7946# endif
7947static void exec_function(char ***to_free,
7948 const struct function *funcp,
7949 char **argv) NORETURN;
7950static void exec_function(char ***to_free,
7951 const struct function *funcp,
7952 char **argv)
7953{
7954# if BB_MMU
Denys Vlasenkod4e4fdb2017-07-03 21:31:16 +02007955 int n;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007956
7957 argv[0] = G.global_argv[0];
7958 G.global_argv = argv;
Denys Vlasenkod4e4fdb2017-07-03 21:31:16 +02007959 G.global_argc = n = 1 + string_array_len(argv + 1);
Denys Vlasenko5b3d2eb2017-07-31 18:02:28 +02007960
7961// Example when we are here: "cmd | func"
7962// func will run with saved-redirect fds open.
7963// $ f() { echo /proc/self/fd/*; }
7964// $ true | f
7965// /proc/self/fd/0 /proc/self/fd/1 /proc/self/fd/2 /proc/self/fd/255 /proc/self/fd/3
7966// stdio^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ G_interactive_fd^ DIR fd for glob
7967// Same in script:
7968// $ . ./SCRIPT
7969// /proc/self/fd/0 /proc/self/fd/1 /proc/self/fd/2 /proc/self/fd/255 /proc/self/fd/3 /proc/self/fd/4
7970// stdio^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ G_interactive_fd^ opened ./SCRIPT DIR fd for glob
7971// They are CLOEXEC so external programs won't see them, but
7972// for "more correctness" we might want to close those extra fds here:
7973//? close_saved_fds_and_FILE_fds();
7974
Denys Vlasenko332e4112018-04-04 22:32:59 +02007975 /* "we are in a function, ok to use return" */
Denys Vlasenko5b3d2eb2017-07-31 18:02:28 +02007976 G_flag_return_in_progress = -1;
Denys Vlasenko9db344a2018-04-09 19:05:11 +02007977 enter_var_nest_level();
Denys Vlasenko5b3d2eb2017-07-31 18:02:28 +02007978 IF_HUSH_LOCAL(G.func_nest_level++;)
7979
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007980 /* On MMU, funcp->body is always non-NULL */
7981 n = run_list(funcp->body);
7982 fflush_all();
7983 _exit(n);
7984# else
Denys Vlasenko5b3d2eb2017-07-31 18:02:28 +02007985//? close_saved_fds_and_FILE_fds();
7986
7987//TODO: check whether "true | func_with_return" works
7988
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007989 re_execute_shell(to_free,
7990 funcp->body_as_string,
7991 G.global_argv[0],
7992 argv + 1,
7993 NULL);
7994# endif
7995}
7996
7997static int run_function(const struct function *funcp, char **argv)
7998{
7999 int rc;
8000 save_arg_t sv;
8001 smallint sv_flg;
8002
8003 save_and_replace_G_args(&sv, argv);
8004
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02008005 /* "We are in function, ok to use return" */
Denys Vlasenko04b46bc2016-10-01 22:28:03 +02008006 sv_flg = G_flag_return_in_progress;
8007 G_flag_return_in_progress = -1;
Denys Vlasenko332e4112018-04-04 22:32:59 +02008008
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02008009 /* Make "local" variables properly shadow previous ones */
8010 IF_HUSH_LOCAL(enter_var_nest_level();)
Denys Vlasenko5b3d2eb2017-07-31 18:02:28 +02008011 IF_HUSH_LOCAL(G.func_nest_level++;)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008012
8013 /* On MMU, funcp->body is always non-NULL */
8014# if !BB_MMU
8015 if (!funcp->body) {
8016 /* Function defined by -F */
8017 parse_and_run_string(funcp->body_as_string);
8018 rc = G.last_exitcode;
8019 } else
8020# endif
8021 {
8022 rc = run_list(funcp->body);
8023 }
8024
Denys Vlasenko332e4112018-04-04 22:32:59 +02008025 IF_HUSH_LOCAL(G.func_nest_level--;)
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02008026 IF_HUSH_LOCAL(leave_var_nest_level();)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008027
Denys Vlasenko04b46bc2016-10-01 22:28:03 +02008028 G_flag_return_in_progress = sv_flg;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008029
8030 restore_G_args(&sv, argv);
8031
8032 return rc;
8033}
8034#endif /* ENABLE_HUSH_FUNCTIONS */
8035
8036
8037#if BB_MMU
8038#define exec_builtin(to_free, x, argv) \
8039 exec_builtin(x, argv)
8040#else
8041#define exec_builtin(to_free, x, argv) \
8042 exec_builtin(to_free, argv)
8043#endif
8044static void exec_builtin(char ***to_free,
8045 const struct built_in_command *x,
8046 char **argv) NORETURN;
8047static void exec_builtin(char ***to_free,
8048 const struct built_in_command *x,
8049 char **argv)
8050{
8051#if BB_MMU
Denys Vlasenko8ee2ada2011-02-07 02:03:51 +01008052 int rcode;
8053 fflush_all();
Denys Vlasenko5b3d2eb2017-07-31 18:02:28 +02008054//? close_saved_fds_and_FILE_fds();
Denys Vlasenko8ee2ada2011-02-07 02:03:51 +01008055 rcode = x->b_function(argv);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008056 fflush_all();
8057 _exit(rcode);
8058#else
Denys Vlasenko8ee2ada2011-02-07 02:03:51 +01008059 fflush_all();
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008060 /* On NOMMU, we must never block!
8061 * Example: { sleep 99 | read line; } & echo Ok
8062 */
8063 re_execute_shell(to_free,
8064 argv[0],
8065 G.global_argv[0],
8066 G.global_argv + 1,
8067 argv);
8068#endif
8069}
8070
8071
8072static void execvp_or_die(char **argv) NORETURN;
8073static void execvp_or_die(char **argv)
8074{
Denys Vlasenko04465da2016-10-03 01:01:15 +02008075 int e;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008076 debug_printf_exec("execing '%s'\n", argv[0]);
Denys Vlasenko75e77de2011-05-12 13:12:47 +02008077 /* Don't propagate SIG_IGN to the child */
8078 if (SPECIAL_JOBSTOP_SIGS != 0)
8079 switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008080 execvp(argv[0], argv);
Denys Vlasenko04465da2016-10-03 01:01:15 +02008081 e = 2;
8082 if (errno == EACCES) e = 126;
8083 if (errno == ENOENT) e = 127;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008084 bb_perror_msg("can't execute '%s'", argv[0]);
Denys Vlasenko04465da2016-10-03 01:01:15 +02008085 _exit(e);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008086}
8087
8088#if ENABLE_HUSH_MODE_X
Denys Vlasenkoaa449c92018-07-28 12:13:58 +02008089static void x_mode_print_optionally_squoted(const char *str)
Denys Vlasenko4b70c922018-07-27 17:42:38 +02008090{
8091 unsigned len;
8092 const char *cp;
8093
8094 cp = str;
Denys Vlasenkoaa449c92018-07-28 12:13:58 +02008095
8096 /* the set of chars which-cause-string-to-be-squoted mimics bash */
8097 /* test a char with: bash -c 'set -x; echo "CH"' */
8098 if (str[strcspn(str, "\\\"'`$(){}[]<>;#&|~*?!^"
8099 " " "\001\002\003\004\005\006\007"
8100 "\010\011\012\013\014\015\016\017"
8101 "\020\021\022\023\024\025\026\027"
8102 "\030\031\032\033\034\035\036\037"
8103 )
8104 ] == '\0'
8105 ) {
8106 /* string has no special chars */
8107 x_mode_addstr(str);
8108 return;
Denys Vlasenko4b70c922018-07-27 17:42:38 +02008109 }
8110
8111 cp = str;
8112 for (;;) {
8113 /* print '....' up to EOL or first squote */
8114 len = (int)(strchrnul(cp, '\'') - cp);
8115 if (len != 0) {
Denys Vlasenkoaa449c92018-07-28 12:13:58 +02008116 x_mode_addchr('\'');
8117 x_mode_addblock(cp, len);
8118 x_mode_addchr('\'');
Denys Vlasenko4b70c922018-07-27 17:42:38 +02008119 cp += len;
8120 }
8121 if (*cp == '\0')
8122 break;
8123 /* string contains squote(s), print them as \' */
Denys Vlasenkoaa449c92018-07-28 12:13:58 +02008124 x_mode_addchr('\\');
8125 x_mode_addchr('\'');
Denys Vlasenko4b70c922018-07-27 17:42:38 +02008126 cp++;
8127 }
8128}
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008129static void dump_cmd_in_x_mode(char **argv)
8130{
8131 if (G_x_mode && argv) {
Denys Vlasenko9dda9272018-07-27 14:12:05 +02008132 unsigned n;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008133
Denys Vlasenko4b70c922018-07-27 17:42:38 +02008134 /* "+[+++...][ cmd...]\n\0" */
Denys Vlasenkoaa449c92018-07-28 12:13:58 +02008135 x_mode_prefix();
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008136 n = 0;
Denys Vlasenko4b70c922018-07-27 17:42:38 +02008137 while (argv[n]) {
Denys Vlasenkoaa449c92018-07-28 12:13:58 +02008138 x_mode_addchr(' ');
8139 if (argv[n][0] == '\0') {
8140 x_mode_addchr('\'');
8141 x_mode_addchr('\'');
8142 } else {
8143 x_mode_print_optionally_squoted(argv[n]);
Denys Vlasenko4b70c922018-07-27 17:42:38 +02008144 }
8145 n++;
8146 }
Denys Vlasenkoaa449c92018-07-28 12:13:58 +02008147 x_mode_flush();
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008148 }
8149}
8150#else
8151# define dump_cmd_in_x_mode(argv) ((void)0)
8152#endif
8153
Denys Vlasenko57000292018-01-12 14:41:45 +01008154#if ENABLE_HUSH_COMMAND
8155static void if_command_vV_print_and_exit(char opt_vV, char *cmd, const char *explanation)
8156{
8157 char *to_free;
Denys Vlasenkoafb73a22018-01-12 16:17:59 +01008158
Denys Vlasenko57000292018-01-12 14:41:45 +01008159 if (!opt_vV)
8160 return;
8161
8162 to_free = NULL;
8163 if (!explanation) {
8164 char *path = getenv("PATH");
8165 explanation = to_free = find_executable(cmd, &path); /* path == NULL is ok */
Denys Vlasenkoafb73a22018-01-12 16:17:59 +01008166 if (!explanation)
8167 _exit(1); /* PROG was not found */
Denys Vlasenko57000292018-01-12 14:41:45 +01008168 if (opt_vV != 'V')
8169 cmd = to_free; /* -v PROG prints "/path/to/PROG" */
8170 }
Denys Vlasenkoafb73a22018-01-12 16:17:59 +01008171 printf((opt_vV == 'V') ? "%s is %s\n" : "%s\n", cmd, explanation);
Denys Vlasenko57000292018-01-12 14:41:45 +01008172 free(to_free);
8173 fflush_all();
Denys Vlasenkoafb73a22018-01-12 16:17:59 +01008174 _exit(0);
Denys Vlasenko57000292018-01-12 14:41:45 +01008175}
8176#else
8177# define if_command_vV_print_and_exit(a,b,c) ((void)0)
8178#endif
8179
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008180#if BB_MMU
8181#define pseudo_exec_argv(nommu_save, argv, assignment_cnt, argv_expanded) \
8182 pseudo_exec_argv(argv, assignment_cnt, argv_expanded)
8183#define pseudo_exec(nommu_save, command, argv_expanded) \
8184 pseudo_exec(command, argv_expanded)
8185#endif
8186
8187/* Called after [v]fork() in run_pipe, or from builtin_exec.
8188 * Never returns.
8189 * Don't exit() here. If you don't exec, use _exit instead.
8190 * The at_exit handlers apparently confuse the calling process,
Denys Vlasenko215b0ca2016-08-19 18:23:56 +02008191 * in particular stdin handling. Not sure why? -- because of vfork! (vda)
Denys Vlasenko215b0ca2016-08-19 18:23:56 +02008192 */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008193static void pseudo_exec_argv(nommu_save_t *nommu_save,
8194 char **argv, int assignment_cnt,
8195 char **argv_expanded) NORETURN;
8196static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save,
8197 char **argv, int assignment_cnt,
8198 char **argv_expanded)
8199{
Denys Vlasenko57000292018-01-12 14:41:45 +01008200 const struct built_in_command *x;
Denys Vlasenko929a41d2018-04-05 14:09:14 +02008201 struct variable **sv_shadowed;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008202 char **new_env;
Denys Vlasenko34f6b122018-04-05 11:30:17 +02008203 IF_HUSH_COMMAND(char opt_vV = 0;)
8204 IF_HUSH_FUNCTIONS(const struct function *funcp;)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008205
8206 new_env = expand_assignments(argv, assignment_cnt);
8207 dump_cmd_in_x_mode(new_env);
8208
8209 if (!argv[assignment_cnt]) {
8210 /* Case when we are here: ... | var=val | ...
8211 * (note that we do not exit early, i.e., do not optimize out
8212 * expand_assignments(): think about ... | var=`sleep 1` | ...
8213 */
8214 free_strings(new_env);
8215 _exit(EXIT_SUCCESS);
8216 }
8217
Denys Vlasenko929a41d2018-04-05 14:09:14 +02008218 sv_shadowed = G.shadowed_vars_pp;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008219#if BB_MMU
Denys Vlasenko929a41d2018-04-05 14:09:14 +02008220 G.shadowed_vars_pp = NULL; /* "don't save, free them instead" */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008221#else
Denys Vlasenko929a41d2018-04-05 14:09:14 +02008222 G.shadowed_vars_pp = &nommu_save->old_vars;
Denys Vlasenko9db344a2018-04-09 19:05:11 +02008223 G.var_nest_level++;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008224#endif
Denys Vlasenko929a41d2018-04-05 14:09:14 +02008225 set_vars_and_save_old(new_env);
8226 G.shadowed_vars_pp = sv_shadowed;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008227
8228 if (argv_expanded) {
8229 argv = argv_expanded;
8230 } else {
8231 argv = expand_strvec_to_strvec(argv + assignment_cnt);
8232#if !BB_MMU
8233 nommu_save->argv = argv;
8234#endif
8235 }
8236 dump_cmd_in_x_mode(argv);
8237
8238#if ENABLE_FEATURE_SH_STANDALONE || BB_MMU
8239 if (strchr(argv[0], '/') != NULL)
8240 goto skip;
8241#endif
8242
Denys Vlasenko75481d32017-07-31 05:27:09 +02008243#if ENABLE_HUSH_FUNCTIONS
8244 /* Check if the command matches any functions (this goes before bltins) */
Denys Vlasenko34f6b122018-04-05 11:30:17 +02008245 funcp = find_function(argv[0]);
8246 if (funcp)
8247 exec_function(&nommu_save->argv_from_re_execing, funcp, argv);
Denys Vlasenko75481d32017-07-31 05:27:09 +02008248#endif
8249
Denys Vlasenko57000292018-01-12 14:41:45 +01008250#if ENABLE_HUSH_COMMAND
8251 /* "command BAR": run BAR without looking it up among functions
8252 * "command -v BAR": print "BAR" or "/path/to/BAR"; or exit 1
8253 * "command -V BAR": print "BAR is {a function,a shell builtin,/path/to/BAR}"
8254 */
8255 while (strcmp(argv[0], "command") == 0 && argv[1]) {
8256 char *p;
8257
8258 argv++;
8259 p = *argv;
8260 if (p[0] != '-' || !p[1])
8261 continue; /* bash allows "command command command [-OPT] BAR" */
8262
8263 for (;;) {
8264 p++;
8265 switch (*p) {
8266 case '\0':
8267 argv++;
8268 p = *argv;
8269 if (p[0] != '-' || !p[1])
8270 goto after_opts;
8271 continue; /* next arg is also -opts, process it too */
8272 case 'v':
8273 case 'V':
8274 opt_vV = *p;
8275 continue;
8276 default:
8277 bb_error_msg_and_die("%s: %s: invalid option", "command", argv[0]);
8278 }
8279 }
8280 }
8281 after_opts:
8282# if ENABLE_HUSH_FUNCTIONS
8283 if (opt_vV && find_function(argv[0]))
8284 if_command_vV_print_and_exit(opt_vV, argv[0], "a function");
8285# endif
8286#endif
8287
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008288 /* Check if the command matches any of the builtins.
8289 * Depending on context, this might be redundant. But it's
8290 * easier to waste a few CPU cycles than it is to figure out
8291 * if this is one of those cases.
8292 */
Denys Vlasenko57000292018-01-12 14:41:45 +01008293 /* Why "BB_MMU ? :" difference in logic? -
8294 * On NOMMU, it is more expensive to re-execute shell
8295 * just in order to run echo or test builtin.
8296 * It's better to skip it here and run corresponding
8297 * non-builtin later. */
8298 x = BB_MMU ? find_builtin(argv[0]) : find_builtin1(argv[0]);
8299 if (x) {
8300 if_command_vV_print_and_exit(opt_vV, argv[0], "a shell builtin");
8301 exec_builtin(&nommu_save->argv_from_re_execing, x, argv);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008302 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008303
8304#if ENABLE_FEATURE_SH_STANDALONE
8305 /* Check if the command matches any busybox applets */
8306 {
8307 int a = find_applet_by_name(argv[0]);
8308 if (a >= 0) {
Denys Vlasenko57000292018-01-12 14:41:45 +01008309 if_command_vV_print_and_exit(opt_vV, argv[0], "an applet");
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008310# if BB_MMU /* see above why on NOMMU it is not allowed */
8311 if (APPLET_IS_NOEXEC(a)) {
Denys Vlasenkobf1c3442017-07-31 04:54:53 +02008312 /* Do not leak open fds from opened script files etc.
8313 * Testcase: interactive "ls -l /proc/self/fd"
8314 * should not show tty fd open.
8315 */
Denys Vlasenko5b3d2eb2017-07-31 18:02:28 +02008316 close_saved_fds_and_FILE_fds();
Denys Vlasenko75481d32017-07-31 05:27:09 +02008317//FIXME: should also close saved redir fds
Denys Vlasenko9acd63c2018-03-28 18:35:07 +02008318//This casuses test failures in
8319//redir_children_should_not_see_saved_fd_2.tests
8320//redir_children_should_not_see_saved_fd_3.tests
8321//if you replace "busybox find" with just "find" in them
Denys Vlasenko7c40ddd2017-08-02 16:37:39 +02008322 /* Without this, "rm -i FILE" can't be ^C'ed: */
8323 switch_off_special_sigs(G.special_sig_mask);
Denys Vlasenkoc9c1ccc2017-08-07 18:59:35 +02008324 debug_printf_exec("running applet '%s'\n", argv[0]);
Denys Vlasenko80e8e3c2017-08-07 19:24:57 +02008325 run_noexec_applet_and_exit(a, argv[0], argv);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008326 }
8327# endif
8328 /* Re-exec ourselves */
8329 debug_printf_exec("re-execing applet '%s'\n", argv[0]);
Denys Vlasenko75e77de2011-05-12 13:12:47 +02008330 /* Don't propagate SIG_IGN to the child */
8331 if (SPECIAL_JOBSTOP_SIGS != 0)
8332 switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008333 execv(bb_busybox_exec_path, argv);
8334 /* If they called chroot or otherwise made the binary no longer
8335 * executable, fall through */
8336 }
8337 }
8338#endif
8339
8340#if ENABLE_FEATURE_SH_STANDALONE || BB_MMU
8341 skip:
8342#endif
Denys Vlasenko57000292018-01-12 14:41:45 +01008343 if_command_vV_print_and_exit(opt_vV, argv[0], NULL);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008344 execvp_or_die(argv);
8345}
8346
8347/* Called after [v]fork() in run_pipe
8348 */
8349static void pseudo_exec(nommu_save_t *nommu_save,
8350 struct command *command,
8351 char **argv_expanded) NORETURN;
8352static void pseudo_exec(nommu_save_t *nommu_save,
8353 struct command *command,
8354 char **argv_expanded)
8355{
Denys Vlasenko49015a62018-04-03 13:02:43 +02008356#if ENABLE_HUSH_FUNCTIONS
8357 if (command->cmd_type == CMD_FUNCDEF) {
8358 /* Ignore funcdefs in pipes:
8359 * true | f() { cmd }
8360 */
8361 _exit(0);
8362 }
8363#endif
8364
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008365 if (command->argv) {
8366 pseudo_exec_argv(nommu_save, command->argv,
8367 command->assignment_cnt, argv_expanded);
8368 }
8369
8370 if (command->group) {
8371 /* Cases when we are here:
8372 * ( list )
8373 * { list } &
8374 * ... | ( list ) | ...
8375 * ... | { list } | ...
8376 */
8377#if BB_MMU
8378 int rcode;
8379 debug_printf_exec("pseudo_exec: run_list\n");
8380 reset_traps_to_defaults();
8381 rcode = run_list(command->group);
8382 /* OK to leak memory by not calling free_pipe_list,
8383 * since this process is about to exit */
8384 _exit(rcode);
8385#else
8386 re_execute_shell(&nommu_save->argv_from_re_execing,
8387 command->group_as_string,
8388 G.global_argv[0],
8389 G.global_argv + 1,
8390 NULL);
8391#endif
8392 }
8393
8394 /* Case when we are here: ... | >file */
8395 debug_printf_exec("pseudo_exec'ed null command\n");
8396 _exit(EXIT_SUCCESS);
8397}
8398
8399#if ENABLE_HUSH_JOB
8400static const char *get_cmdtext(struct pipe *pi)
8401{
8402 char **argv;
8403 char *p;
8404 int len;
8405
8406 /* This is subtle. ->cmdtext is created only on first backgrounding.
8407 * (Think "cat, <ctrl-z>, fg, <ctrl-z>, fg, <ctrl-z>...." here...)
8408 * On subsequent bg argv is trashed, but we won't use it */
8409 if (pi->cmdtext)
8410 return pi->cmdtext;
Denys Vlasenko1eada9a2016-11-08 17:28:45 +01008411
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008412 argv = pi->cmds[0].argv;
Denys Vlasenko1eada9a2016-11-08 17:28:45 +01008413 if (!argv) {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008414 pi->cmdtext = xzalloc(1);
8415 return pi->cmdtext;
8416 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008417 len = 0;
8418 do {
8419 len += strlen(*argv) + 1;
8420 } while (*++argv);
8421 p = xmalloc(len);
8422 pi->cmdtext = p;
8423 argv = pi->cmds[0].argv;
8424 do {
Denys Vlasenko1eada9a2016-11-08 17:28:45 +01008425 p = stpcpy(p, *argv);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008426 *p++ = ' ';
8427 } while (*++argv);
8428 p[-1] = '\0';
8429 return pi->cmdtext;
8430}
8431
Denys Vlasenko2ed74e22017-07-14 19:58:46 +02008432static void remove_job_from_table(struct pipe *pi)
8433{
8434 struct pipe *prev_pipe;
8435
8436 if (pi == G.job_list) {
8437 G.job_list = pi->next;
8438 } else {
8439 prev_pipe = G.job_list;
8440 while (prev_pipe->next != pi)
8441 prev_pipe = prev_pipe->next;
8442 prev_pipe->next = pi->next;
8443 }
8444 G.last_jobid = 0;
8445 if (G.job_list)
8446 G.last_jobid = G.job_list->jobid;
8447}
8448
8449static void delete_finished_job(struct pipe *pi)
8450{
8451 remove_job_from_table(pi);
8452 free_pipe(pi);
8453}
8454
8455static void clean_up_last_dead_job(void)
8456{
8457 if (G.job_list && !G.job_list->alive_cmds)
8458 delete_finished_job(G.job_list);
8459}
8460
Denys Vlasenko16096292017-07-10 10:00:28 +02008461static void insert_job_into_table(struct pipe *pi)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008462{
8463 struct pipe *job, **jobp;
8464 int i;
8465
Denys Vlasenko2ed74e22017-07-14 19:58:46 +02008466 clean_up_last_dead_job();
8467
Denys Vlasenko9e55a152017-07-10 10:01:12 +02008468 /* Find the end of the list, and find next job ID to use */
8469 i = 0;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008470 jobp = &G.job_list;
Denys Vlasenko9e55a152017-07-10 10:01:12 +02008471 while ((job = *jobp) != NULL) {
8472 if (job->jobid > i)
8473 i = job->jobid;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008474 jobp = &job->next;
Denys Vlasenko9e55a152017-07-10 10:01:12 +02008475 }
8476 pi->jobid = i + 1;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008477
Denys Vlasenko9e55a152017-07-10 10:01:12 +02008478 /* Create a new job struct at the end */
8479 job = *jobp = xmemdup(pi, sizeof(*pi));
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008480 job->next = NULL;
8481 job->cmds = xzalloc(sizeof(pi->cmds[0]) * pi->num_cmds);
8482 /* Cannot copy entire pi->cmds[] vector! This causes double frees */
8483 for (i = 0; i < pi->num_cmds; i++) {
8484 job->cmds[i].pid = pi->cmds[i].pid;
8485 /* all other fields are not used and stay zero */
8486 }
8487 job->cmdtext = xstrdup(get_cmdtext(pi));
8488
8489 if (G_interactive_fd)
Denys Vlasenkod5b5c2f2017-01-08 15:46:04 +01008490 printf("[%u] %u %s\n", job->jobid, (unsigned)job->cmds[0].pid, job->cmdtext);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008491 G.last_jobid = job->jobid;
8492}
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008493#endif /* JOB */
8494
Denys Vlasenko62b717b2016-11-07 22:12:18 +01008495static int job_exited_or_stopped(struct pipe *pi)
8496{
8497 int rcode, i;
8498
8499 if (pi->alive_cmds != pi->stopped_cmds)
8500 return -1;
8501
8502 /* All processes in fg pipe have exited or stopped */
8503 rcode = 0;
8504 i = pi->num_cmds;
8505 while (--i >= 0) {
8506 rcode = pi->cmds[i].cmd_exitcode;
8507 /* usually last process gives overall exitstatus,
8508 * but with "set -o pipefail", last *failed* process does */
8509 if (G.o_opt[OPT_O_PIPEFAIL] == 0 || rcode != 0)
8510 break;
8511 }
8512 IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
8513 return rcode;
8514}
8515
Denys Vlasenko7e675362016-10-28 21:57:31 +02008516static int process_wait_result(struct pipe *fg_pipe, pid_t childpid, int status)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008517{
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008518#if ENABLE_HUSH_JOB
8519 struct pipe *pi;
8520#endif
Denys Vlasenko7e675362016-10-28 21:57:31 +02008521 int i, dead;
8522
8523 dead = WIFEXITED(status) || WIFSIGNALED(status);
8524
8525#if DEBUG_JOBS
8526 if (WIFSTOPPED(status))
8527 debug_printf_jobs("pid %d stopped by sig %d (exitcode %d)\n",
8528 childpid, WSTOPSIG(status), WEXITSTATUS(status));
8529 if (WIFSIGNALED(status))
8530 debug_printf_jobs("pid %d killed by sig %d (exitcode %d)\n",
8531 childpid, WTERMSIG(status), WEXITSTATUS(status));
8532 if (WIFEXITED(status))
8533 debug_printf_jobs("pid %d exited, exitcode %d\n",
8534 childpid, WEXITSTATUS(status));
8535#endif
8536 /* Were we asked to wait for a fg pipe? */
8537 if (fg_pipe) {
8538 i = fg_pipe->num_cmds;
Denys Vlasenko62b717b2016-11-07 22:12:18 +01008539
Denys Vlasenko7e675362016-10-28 21:57:31 +02008540 while (--i >= 0) {
Denys Vlasenko62b717b2016-11-07 22:12:18 +01008541 int rcode;
8542
Denys Vlasenko7e675362016-10-28 21:57:31 +02008543 debug_printf_jobs("check pid %d\n", fg_pipe->cmds[i].pid);
8544 if (fg_pipe->cmds[i].pid != childpid)
8545 continue;
8546 if (dead) {
8547 int ex;
8548 fg_pipe->cmds[i].pid = 0;
8549 fg_pipe->alive_cmds--;
8550 ex = WEXITSTATUS(status);
8551 /* bash prints killer signal's name for *last*
8552 * process in pipe (prints just newline for SIGINT/SIGPIPE).
8553 * Mimic this. Example: "sleep 5" + (^\ or kill -QUIT)
8554 */
8555 if (WIFSIGNALED(status)) {
8556 int sig = WTERMSIG(status);
8557 if (i == fg_pipe->num_cmds-1)
8558 /* TODO: use strsignal() instead for bash compat? but that's bloat... */
8559 puts(sig == SIGINT || sig == SIGPIPE ? "" : get_signame(sig));
8560 /* TODO: if (WCOREDUMP(status)) + " (core dumped)"; */
8561 /* TODO: MIPS has 128 sigs (1..128), what if sig==128 here?
8562 * Maybe we need to use sig | 128? */
8563 ex = sig + 128;
8564 }
8565 fg_pipe->cmds[i].cmd_exitcode = ex;
8566 } else {
8567 fg_pipe->stopped_cmds++;
8568 }
8569 debug_printf_jobs("fg_pipe: alive_cmds %d stopped_cmds %d\n",
8570 fg_pipe->alive_cmds, fg_pipe->stopped_cmds);
Denys Vlasenko62b717b2016-11-07 22:12:18 +01008571 rcode = job_exited_or_stopped(fg_pipe);
8572 if (rcode >= 0) {
Denys Vlasenko7e675362016-10-28 21:57:31 +02008573/* Note: *non-interactive* bash does not continue if all processes in fg pipe
8574 * are stopped. Testcase: "cat | cat" in a script (not on command line!)
8575 * and "killall -STOP cat" */
8576 if (G_interactive_fd) {
8577#if ENABLE_HUSH_JOB
8578 if (fg_pipe->alive_cmds != 0)
Denys Vlasenko16096292017-07-10 10:00:28 +02008579 insert_job_into_table(fg_pipe);
Denys Vlasenko7e675362016-10-28 21:57:31 +02008580#endif
8581 return rcode;
8582 }
8583 if (fg_pipe->alive_cmds == 0)
8584 return rcode;
8585 }
8586 /* There are still running processes in the fg_pipe */
8587 return -1;
8588 }
Denys Vlasenko10ad6222017-04-17 16:13:32 +02008589 /* It wasn't in fg_pipe, look for process in bg pipes */
Denys Vlasenko7e675362016-10-28 21:57:31 +02008590 }
8591
8592#if ENABLE_HUSH_JOB
8593 /* We were asked to wait for bg or orphaned children */
8594 /* No need to remember exitcode in this case */
8595 for (pi = G.job_list; pi; pi = pi->next) {
8596 for (i = 0; i < pi->num_cmds; i++) {
8597 if (pi->cmds[i].pid == childpid)
8598 goto found_pi_and_prognum;
8599 }
8600 }
8601 /* Happens when shell is used as init process (init=/bin/sh) */
8602 debug_printf("checkjobs: pid %d was not in our list!\n", childpid);
8603 return -1; /* this wasn't a process from fg_pipe */
8604
8605 found_pi_and_prognum:
8606 if (dead) {
8607 /* child exited */
Denys Vlasenko840a4352017-07-07 22:56:02 +02008608 int rcode = WEXITSTATUS(status);
Denys Vlasenko7e675362016-10-28 21:57:31 +02008609 if (WIFSIGNALED(status))
Denys Vlasenko840a4352017-07-07 22:56:02 +02008610 rcode = 128 + WTERMSIG(status);
8611 pi->cmds[i].cmd_exitcode = rcode;
8612 if (G.last_bg_pid == pi->cmds[i].pid)
8613 G.last_bg_pid_exitcode = rcode;
8614 pi->cmds[i].pid = 0;
Denys Vlasenko7e675362016-10-28 21:57:31 +02008615 pi->alive_cmds--;
8616 if (!pi->alive_cmds) {
Denys Vlasenko2ed74e22017-07-14 19:58:46 +02008617 if (G_interactive_fd) {
Denys Vlasenko7e675362016-10-28 21:57:31 +02008618 printf(JOB_STATUS_FORMAT, pi->jobid,
8619 "Done", pi->cmdtext);
Denys Vlasenko2ed74e22017-07-14 19:58:46 +02008620 delete_finished_job(pi);
8621 } else {
8622/*
8623 * bash deletes finished jobs from job table only in interactive mode,
8624 * after "jobs" cmd, or if pid of a new process matches one of the old ones
8625 * (see cleanup_dead_jobs(), delete_old_job(), J_NOTIFIED in bash source).
8626 * Testcase script: "(exit 3) & sleep 1; wait %1; echo $?" prints 3 in bash.
8627 * We only retain one "dead" job, if it's the single job on the list.
8628 * This covers most of real-world scenarios where this is useful.
8629 */
8630 if (pi != G.job_list)
8631 delete_finished_job(pi);
8632 }
Denys Vlasenko7e675362016-10-28 21:57:31 +02008633 }
8634 } else {
8635 /* child stopped */
8636 pi->stopped_cmds++;
8637 }
8638#endif
8639 return -1; /* this wasn't a process from fg_pipe */
8640}
8641
8642/* Check to see if any processes have exited -- if they have,
8643 * figure out why and see if a job has completed.
Denys Vlasenko62b717b2016-11-07 22:12:18 +01008644 *
8645 * If non-NULL fg_pipe: wait for its completion or stop.
8646 * Return its exitcode or zero if stopped.
8647 *
8648 * Alternatively (fg_pipe == NULL, waitfor_pid != 0):
8649 * waitpid(WNOHANG), if waitfor_pid exits or stops, return exitcode+1,
8650 * else return <0 if waitpid errors out (e.g. ECHILD: nothing to wait for)
8651 * or 0 if no children changed status.
8652 *
8653 * Alternatively (fg_pipe == NULL, waitfor_pid == 0),
8654 * return <0 if waitpid errors out (e.g. ECHILD: nothing to wait for)
8655 * or 0 if no children changed status.
Denys Vlasenko7e675362016-10-28 21:57:31 +02008656 */
8657static int checkjobs(struct pipe *fg_pipe, pid_t waitfor_pid)
8658{
8659 int attributes;
8660 int status;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008661 int rcode = 0;
8662
8663 debug_printf_jobs("checkjobs %p\n", fg_pipe);
8664
8665 attributes = WUNTRACED;
8666 if (fg_pipe == NULL)
8667 attributes |= WNOHANG;
8668
8669 errno = 0;
8670#if ENABLE_HUSH_FAST
8671 if (G.handled_SIGCHLD == G.count_SIGCHLD) {
8672//bb_error_msg("[%d] checkjobs: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d children?:%d fg_pipe:%p",
8673//getpid(), G.count_SIGCHLD, G.handled_SIGCHLD, G.we_have_children, fg_pipe);
8674 /* There was neither fork nor SIGCHLD since last waitpid */
8675 /* Avoid doing waitpid syscall if possible */
8676 if (!G.we_have_children) {
8677 errno = ECHILD;
8678 return -1;
8679 }
8680 if (fg_pipe == NULL) { /* is WNOHANG set? */
8681 /* We have children, but they did not exit
8682 * or stop yet (we saw no SIGCHLD) */
8683 return 0;
8684 }
8685 /* else: !WNOHANG, waitpid will block, can't short-circuit */
8686 }
8687#endif
8688
8689/* Do we do this right?
8690 * bash-3.00# sleep 20 | false
8691 * <ctrl-Z pressed>
8692 * [3]+ Stopped sleep 20 | false
8693 * bash-3.00# echo $?
8694 * 1 <========== bg pipe is not fully done, but exitcode is already known!
8695 * [hush 1.14.0: yes we do it right]
8696 */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008697 while (1) {
Denys Vlasenko7e675362016-10-28 21:57:31 +02008698 pid_t childpid;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008699#if ENABLE_HUSH_FAST
Denys Vlasenko7e675362016-10-28 21:57:31 +02008700 int i;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008701 i = G.count_SIGCHLD;
8702#endif
8703 childpid = waitpid(-1, &status, attributes);
8704 if (childpid <= 0) {
8705 if (childpid && errno != ECHILD)
8706 bb_perror_msg("waitpid");
8707#if ENABLE_HUSH_FAST
8708 else { /* Until next SIGCHLD, waitpid's are useless */
8709 G.we_have_children = (childpid == 0);
8710 G.handled_SIGCHLD = i;
8711//bb_error_msg("[%d] checkjobs: waitpid returned <= 0, G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
8712 }
8713#endif
Denys Vlasenko7e675362016-10-28 21:57:31 +02008714 /* ECHILD (no children), or 0 (no change in children status) */
8715 rcode = childpid;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008716 break;
8717 }
Denys Vlasenko7e675362016-10-28 21:57:31 +02008718 rcode = process_wait_result(fg_pipe, childpid, status);
8719 if (rcode >= 0) {
8720 /* fg_pipe exited or stopped */
8721 break;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008722 }
Denys Vlasenko7e675362016-10-28 21:57:31 +02008723 if (childpid == waitfor_pid) {
Denys Vlasenko62b717b2016-11-07 22:12:18 +01008724 debug_printf_exec("childpid==waitfor_pid:%d status:0x%08x\n", childpid, status);
Denys Vlasenko7e675362016-10-28 21:57:31 +02008725 rcode = WEXITSTATUS(status);
8726 if (WIFSIGNALED(status))
8727 rcode = 128 + WTERMSIG(status);
Denys Vlasenko62b717b2016-11-07 22:12:18 +01008728 if (WIFSTOPPED(status))
8729 /* bash: "cmd & wait $!" and cmd stops: $? = 128 + stopsig */
8730 rcode = 128 + WSTOPSIG(status);
Denys Vlasenko7e675362016-10-28 21:57:31 +02008731 rcode++;
8732 break; /* "wait PID" called us, give it exitcode+1 */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008733 }
Denys Vlasenko7e675362016-10-28 21:57:31 +02008734 /* This wasn't one of our processes, or */
8735 /* fg_pipe still has running processes, do waitpid again */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008736 } /* while (waitpid succeeds)... */
8737
8738 return rcode;
8739}
8740
8741#if ENABLE_HUSH_JOB
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02008742static int checkjobs_and_fg_shell(struct pipe *fg_pipe)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008743{
8744 pid_t p;
Denys Vlasenko7e675362016-10-28 21:57:31 +02008745 int rcode = checkjobs(fg_pipe, 0 /*(no pid to wait for)*/);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008746 if (G_saved_tty_pgrp) {
8747 /* Job finished, move the shell to the foreground */
8748 p = getpgrp(); /* our process group id */
8749 debug_printf_jobs("fg'ing ourself: getpgrp()=%d\n", (int)p);
8750 tcsetpgrp(G_interactive_fd, p);
8751 }
8752 return rcode;
8753}
8754#endif
8755
8756/* Start all the jobs, but don't wait for anything to finish.
8757 * See checkjobs().
8758 *
8759 * Return code is normally -1, when the caller has to wait for children
8760 * to finish to determine the exit status of the pipe. If the pipe
8761 * is a simple builtin command, however, the action is done by the
8762 * time run_pipe returns, and the exit code is provided as the
8763 * return value.
8764 *
8765 * Returns -1 only if started some children. IOW: we have to
8766 * mask out retvals of builtins etc with 0xff!
8767 *
8768 * The only case when we do not need to [v]fork is when the pipe
8769 * is single, non-backgrounded, non-subshell command. Examples:
8770 * cmd ; ... { list } ; ...
8771 * cmd && ... { list } && ...
8772 * cmd || ... { list } || ...
Denys Vlasenkob72baeb2011-02-02 18:38:57 +01008773 * If it is, then we can run cmd as a builtin, NOFORK,
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008774 * or (if SH_STANDALONE) an applet, and we can run the { list }
8775 * with run_list. If it isn't one of these, we fork and exec cmd.
8776 *
8777 * Cases when we must fork:
8778 * non-single: cmd | cmd
8779 * backgrounded: cmd & { list } &
8780 * subshell: ( list ) [&]
8781 */
8782#if !ENABLE_HUSH_MODE_X
Denys Vlasenko945e9b02018-07-24 18:01:22 +02008783#define redirect_and_varexp_helper(command, sqp, argv_expanded) \
8784 redirect_and_varexp_helper(command, sqp)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008785#endif
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02008786static int redirect_and_varexp_helper(
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008787 struct command *command,
Denys Vlasenko2db74612017-07-07 22:07:28 +02008788 struct squirrel **sqp,
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008789 char **argv_expanded)
8790{
Denys Vlasenko41d8f102018-04-05 14:41:21 +02008791 /* Assignments occur before redirects. Try:
8792 * a=`sleep 1` sleep 2 3>/qwe/rty
8793 */
8794
8795 char **new_env = expand_assignments(command->argv, command->assignment_cnt);
8796 dump_cmd_in_x_mode(new_env);
8797 dump_cmd_in_x_mode(argv_expanded);
8798 /* this takes ownership of new_env[i] elements, and frees new_env: */
8799 set_vars_and_save_old(new_env);
8800
Denys Vlasenko41d8f102018-04-05 14:41:21 +02008801 return setup_redirects(command, sqp);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008802}
8803static NOINLINE int run_pipe(struct pipe *pi)
8804{
8805 static const char *const null_ptr = NULL;
8806
8807 int cmd_no;
8808 int next_infd;
8809 struct command *command;
8810 char **argv_expanded;
8811 char **argv;
Denys Vlasenko2db74612017-07-07 22:07:28 +02008812 struct squirrel *squirrel = NULL;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008813 int rcode;
8814
8815 debug_printf_exec("run_pipe start: members:%d\n", pi->num_cmds);
8816 debug_enter();
8817
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02008818 /* Testcase: set -- q w e; (IFS='' echo "$*"; IFS=''; echo "$*"); echo "$*"
8819 * Result should be 3 lines: q w e, qwe, q w e
8820 */
Denys Vlasenko96786362018-04-11 16:02:58 +02008821 if (G.ifs_whitespace != G.ifs)
8822 free(G.ifs_whitespace);
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02008823 G.ifs = get_local_var_value("IFS");
Denys Vlasenko96786362018-04-11 16:02:58 +02008824 if (G.ifs) {
8825 char *p;
8826 G.ifs_whitespace = (char*)G.ifs;
8827 p = skip_whitespace(G.ifs);
8828 if (*p) {
8829 /* Not all $IFS is whitespace */
8830 char *d;
8831 int len = p - G.ifs;
8832 p = skip_non_whitespace(p);
8833 G.ifs_whitespace = xmalloc(len + strlen(p) + 1); /* can overestimate */
8834 d = mempcpy(G.ifs_whitespace, G.ifs, len);
8835 while (*p) {
8836 if (isspace(*p))
8837 *d++ = *p;
8838 p++;
8839 }
8840 *d = '\0';
8841 }
8842 } else {
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02008843 G.ifs = defifs;
Denys Vlasenko96786362018-04-11 16:02:58 +02008844 G.ifs_whitespace = (char*)G.ifs;
8845 }
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02008846
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008847 IF_HUSH_JOB(pi->pgrp = -1;)
8848 pi->stopped_cmds = 0;
8849 command = &pi->cmds[0];
8850 argv_expanded = NULL;
8851
8852 if (pi->num_cmds != 1
8853 || pi->followup == PIPE_BG
8854 || command->cmd_type == CMD_SUBSHELL
8855 ) {
8856 goto must_fork;
8857 }
8858
8859 pi->alive_cmds = 1;
8860
8861 debug_printf_exec(": group:%p argv:'%s'\n",
8862 command->group, command->argv ? command->argv[0] : "NONE");
8863
8864 if (command->group) {
8865#if ENABLE_HUSH_FUNCTIONS
8866 if (command->cmd_type == CMD_FUNCDEF) {
8867 /* "executing" func () { list } */
8868 struct function *funcp;
8869
8870 funcp = new_function(command->argv[0]);
8871 /* funcp->name is already set to argv[0] */
8872 funcp->body = command->group;
8873# if !BB_MMU
8874 funcp->body_as_string = command->group_as_string;
8875 command->group_as_string = NULL;
8876# endif
8877 command->group = NULL;
8878 command->argv[0] = NULL;
8879 debug_printf_exec("cmd %p has child func at %p\n", command, funcp);
8880 funcp->parent_cmd = command;
8881 command->child_func = funcp;
8882
8883 debug_printf_exec("run_pipe: return EXIT_SUCCESS\n");
8884 debug_leave();
8885 return EXIT_SUCCESS;
8886 }
8887#endif
8888 /* { list } */
Denys Vlasenko41ef41b2018-07-24 16:54:41 +02008889 debug_printf_exec("non-subshell group\n");
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008890 rcode = 1; /* exitcode if redir failed */
Denys Vlasenko2db74612017-07-07 22:07:28 +02008891 if (setup_redirects(command, &squirrel) == 0) {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008892 debug_printf_exec(": run_list\n");
Denys Vlasenkod1b84572018-03-28 18:42:54 +02008893//FIXME: we need to pass squirrel down into run_list()
8894//for SH_STANDALONE case, or else this construct:
8895// { find /proc/self/fd; true; } >FILE; cmd2
8896//has no way of closing saved fd#1 for "find",
8897//and in SH_STANDALONE mode, "find" is not execed,
8898//therefore CLOEXEC on saved fd does not help.
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008899 rcode = run_list(command->group) & 0xff;
8900 }
8901 restore_redirects(squirrel);
8902 IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
8903 debug_leave();
8904 debug_printf_exec("run_pipe: return %d\n", rcode);
8905 return rcode;
8906 }
8907
8908 argv = command->argv ? command->argv : (char **) &null_ptr;
8909 {
8910 const struct built_in_command *x;
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02008911 IF_HUSH_FUNCTIONS(const struct function *funcp;)
8912 IF_NOT_HUSH_FUNCTIONS(enum { funcp = 0 };)
Denys Vlasenko929a41d2018-04-05 14:09:14 +02008913 struct variable **sv_shadowed;
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02008914 struct variable *old_vars;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008915
Denys Vlasenko5807e182018-02-08 19:19:04 +01008916#if ENABLE_HUSH_LINENO_VAR
Denys Vlasenkob8d076b2018-01-19 16:00:57 +01008917 if (G.lineno_var)
8918 strcpy(G.lineno_var + sizeof("LINENO=")-1, utoa(command->lineno));
8919#endif
Denys Vlasenko6aad1dd2018-01-19 15:37:04 +01008920
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008921 if (argv[command->assignment_cnt] == NULL) {
Denys Vlasenko5fa05052018-04-03 11:21:13 +02008922 /* Assignments, but no command.
8923 * Ensure redirects take effect (that is, create files).
8924 * Try "a=t >file"
8925 */
Denys Vlasenko21b7f1b2018-04-05 15:15:53 +02008926 unsigned i;
Denys Vlasenko5fa05052018-04-03 11:21:13 +02008927 G.expand_exitcode = 0;
Denys Vlasenko21b7f1b2018-04-05 15:15:53 +02008928 only_assignments:
Denys Vlasenko2db74612017-07-07 22:07:28 +02008929 rcode = setup_redirects(command, &squirrel);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008930 restore_redirects(squirrel);
Denys Vlasenko21b7f1b2018-04-05 15:15:53 +02008931
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008932 /* Set shell variables */
Denys Vlasenko21b7f1b2018-04-05 15:15:53 +02008933 i = 0;
8934 while (i < command->assignment_cnt) {
Denys Vlasenko34179952018-04-11 13:47:59 +02008935 char *p = expand_string_to_string(argv[i],
8936 EXP_FLAG_ESC_GLOB_CHARS,
8937 /*unbackslash:*/ 1
8938 );
Denys Vlasenko9dda9272018-07-27 14:12:05 +02008939#if ENABLE_HUSH_MODE_X
8940 if (G_x_mode) {
Denys Vlasenko4b70c922018-07-27 17:42:38 +02008941 char *eq;
Denys Vlasenkoaa449c92018-07-28 12:13:58 +02008942 if (i == 0)
8943 x_mode_prefix();
8944 x_mode_addchr(' ');
Denys Vlasenko4b70c922018-07-27 17:42:38 +02008945 eq = strchrnul(p, '=');
Denys Vlasenkoaa449c92018-07-28 12:13:58 +02008946 if (*eq) eq++;
8947 x_mode_addblock(p, (eq - p));
8948 x_mode_print_optionally_squoted(eq);
8949 x_mode_flush();
Denys Vlasenko9dda9272018-07-27 14:12:05 +02008950 }
8951#endif
Denys Vlasenko21b7f1b2018-04-05 15:15:53 +02008952 debug_printf_env("set shell var:'%s'->'%s'\n", *argv, p);
Denys Vlasenko38ef39a2017-07-18 01:40:01 +02008953 if (set_local_var(p, /*flag:*/ 0)) {
8954 /* assignment to readonly var / putenv error? */
8955 rcode = 1;
8956 }
Denys Vlasenko21b7f1b2018-04-05 15:15:53 +02008957 i++;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008958 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008959 /* Redirect error sets $? to 1. Otherwise,
8960 * if evaluating assignment value set $?, retain it.
Denys Vlasenko5fa05052018-04-03 11:21:13 +02008961 * Else, clear $?:
8962 * false; q=`exit 2`; echo $? - should print 2
8963 * false; x=1; echo $? - should print 0
8964 * Because of the 2nd case, we can't just use G.last_exitcode.
8965 */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008966 if (rcode == 0)
Denys Vlasenko5fa05052018-04-03 11:21:13 +02008967 rcode = G.expand_exitcode;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008968 IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
8969 debug_leave();
8970 debug_printf_exec("run_pipe: return %d\n", rcode);
8971 return rcode;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008972 }
8973
8974 /* Expand the rest into (possibly) many strings each */
Denys Vlasenko11752d42018-04-03 08:20:58 +02008975#if defined(CMD_SINGLEWORD_NOGLOB)
Denys Vlasenko929a41d2018-04-05 14:09:14 +02008976 if (command->cmd_type == CMD_SINGLEWORD_NOGLOB)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008977 argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt);
Denys Vlasenko929a41d2018-04-05 14:09:14 +02008978 else
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008979#endif
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008980 argv_expanded = expand_strvec_to_strvec(argv + command->assignment_cnt);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008981
Denys Vlasenko41d8f102018-04-05 14:41:21 +02008982 /* If someone gives us an empty string: `cmd with empty output` */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008983 if (!argv_expanded[0]) {
8984 free(argv_expanded);
Denys Vlasenko21b7f1b2018-04-05 15:15:53 +02008985 /* `false` still has to set exitcode 1 */
8986 G.expand_exitcode = G.last_exitcode;
Denys Vlasenko41d8f102018-04-05 14:41:21 +02008987 goto only_assignments;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008988 }
8989
Denys Vlasenko929a41d2018-04-05 14:09:14 +02008990 old_vars = NULL;
8991 sv_shadowed = G.shadowed_vars_pp;
8992
Denys Vlasenko75481d32017-07-31 05:27:09 +02008993 /* Check if argv[0] matches any functions (this goes before bltins) */
Denys Vlasenko929a41d2018-04-05 14:09:14 +02008994 IF_HUSH_FUNCTIONS(funcp = find_function(argv_expanded[0]);)
8995 IF_HUSH_FUNCTIONS(x = NULL;)
8996 IF_HUSH_FUNCTIONS(if (!funcp))
Denys Vlasenko75481d32017-07-31 05:27:09 +02008997 x = find_builtin(argv_expanded[0]);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008998 if (x || funcp) {
Denys Vlasenko34f6b122018-04-05 11:30:17 +02008999 if (x && x->b_function == builtin_exec && argv_expanded[1] == NULL) {
9000 debug_printf("exec with redirects only\n");
Denys Vlasenko41d8f102018-04-05 14:41:21 +02009001 /*
9002 * Variable assignments are executed, but then "forgotten":
9003 * a=`sleep 1;echo A` exec 3>&-; echo $a
9004 * sleeps, but prints nothing.
9005 */
9006 enter_var_nest_level();
9007 G.shadowed_vars_pp = &old_vars;
Denys Vlasenko945e9b02018-07-24 18:01:22 +02009008 rcode = redirect_and_varexp_helper(command,
9009 /*squirrel:*/ ERR_PTR,
9010 argv_expanded
9011 );
Denys Vlasenko41d8f102018-04-05 14:41:21 +02009012 G.shadowed_vars_pp = sv_shadowed;
Denys Vlasenko34f6b122018-04-05 11:30:17 +02009013 /* rcode=1 can be if redir file can't be opened */
Denys Vlasenko41d8f102018-04-05 14:41:21 +02009014
Denys Vlasenko34f6b122018-04-05 11:30:17 +02009015 goto clean_up_and_ret1;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009016 }
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02009017
Denys Vlasenko34f6b122018-04-05 11:30:17 +02009018 /* Bump var nesting, or this will leak exported $a:
Denys Vlasenkod358b0b2018-04-05 00:51:55 +02009019 * a=b true; env | grep ^a=
9020 */
9021 enter_var_nest_level();
Denys Vlasenko929a41d2018-04-05 14:09:14 +02009022 /* Collect all variables "shadowed" by helper
9023 * (IOW: old vars overridden by "var1=val1 var2=val2 cmd..." syntax)
9024 * into old_vars list:
9025 */
9026 G.shadowed_vars_pp = &old_vars;
9027 rcode = redirect_and_varexp_helper(command, &squirrel, argv_expanded);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009028 if (rcode == 0) {
9029 if (!funcp) {
Denys Vlasenko929a41d2018-04-05 14:09:14 +02009030 /* Do not collect *to old_vars list* vars shadowed
9031 * by e.g. "local VAR" builtin (collect them
9032 * in the previously nested list instead):
9033 * don't want them to be restored immediately
9034 * after "local" completes.
9035 */
9036 G.shadowed_vars_pp = sv_shadowed;
9037
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009038 debug_printf_exec(": builtin '%s' '%s'...\n",
9039 x->b_cmd, argv_expanded[1]);
Denys Vlasenko8ee2ada2011-02-07 02:03:51 +01009040 fflush_all();
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009041 rcode = x->b_function(argv_expanded) & 0xff;
9042 fflush_all();
9043 }
9044#if ENABLE_HUSH_FUNCTIONS
9045 else {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009046 debug_printf_exec(": function '%s' '%s'...\n",
9047 funcp->name, argv_expanded[1]);
9048 rcode = run_function(funcp, argv_expanded) & 0xff;
Denys Vlasenko929a41d2018-04-05 14:09:14 +02009049 /*
9050 * But do collect *to old_vars list* vars shadowed
9051 * within function execution. To that end, restore
9052 * this pointer _after_ function run:
9053 */
9054 G.shadowed_vars_pp = sv_shadowed;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009055 }
9056#endif
9057 }
Denys Vlasenko34f6b122018-04-05 11:30:17 +02009058 } else
Denys Vlasenko82d1c1f2017-12-31 17:30:02 +01009059 if (ENABLE_FEATURE_SH_NOFORK && NUM_APPLETS > 1) {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009060 int n = find_applet_by_name(argv_expanded[0]);
Denys Vlasenko34f6b122018-04-05 11:30:17 +02009061 if (n < 0 || !APPLET_IS_NOFORK(n))
9062 goto must_fork;
9063
9064 enter_var_nest_level();
Denys Vlasenko929a41d2018-04-05 14:09:14 +02009065 /* Collect all variables "shadowed" by helper into old_vars list */
9066 G.shadowed_vars_pp = &old_vars;
9067 rcode = redirect_and_varexp_helper(command, &squirrel, argv_expanded);
9068 G.shadowed_vars_pp = sv_shadowed;
9069
Denys Vlasenko34f6b122018-04-05 11:30:17 +02009070 if (rcode == 0) {
9071 debug_printf_exec(": run_nofork_applet '%s' '%s'...\n",
9072 argv_expanded[0], argv_expanded[1]);
9073 /*
9074 * Note: signals (^C) can't interrupt here.
9075 * We remember them and they will be acted upon
9076 * after applet returns.
9077 * This makes applets which can run for a long time
9078 * and/or wait for user input ineligible for NOFORK:
9079 * for example, "yes" or "rm" (rm -i waits for input).
9080 */
9081 rcode = run_nofork_applet(n, argv_expanded);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009082 }
Denys Vlasenko4e1dc532018-04-05 13:10:34 +02009083 } else
9084 goto must_fork;
Denys Vlasenko34f6b122018-04-05 11:30:17 +02009085
Denys Vlasenko41d8f102018-04-05 14:41:21 +02009086 restore_redirects(squirrel);
9087 clean_up_and_ret1:
Denys Vlasenko34f6b122018-04-05 11:30:17 +02009088 leave_var_nest_level();
9089 add_vars(old_vars);
Denys Vlasenko34f6b122018-04-05 11:30:17 +02009090
9091 /*
9092 * Try "usleep 99999999" + ^C + "echo $?"
9093 * with FEATURE_SH_NOFORK=y.
9094 */
9095 if (!funcp) {
9096 /* It was builtin or nofork.
9097 * if this would be a real fork/execed program,
9098 * it should have died if a fatal sig was received.
9099 * But OTOH, there was no separate process,
9100 * the sig was sent to _shell_, not to non-existing
9101 * child.
9102 * Let's just handle ^C only, this one is obvious:
9103 * we aren't ok with exitcode 0 when ^C was pressed
9104 * during builtin/nofork.
9105 */
9106 if (sigismember(&G.pending_set, SIGINT))
9107 rcode = 128 + SIGINT;
9108 }
Denys Vlasenko34f6b122018-04-05 11:30:17 +02009109 free(argv_expanded);
9110 IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
9111 debug_leave();
9112 debug_printf_exec("run_pipe return %d\n", rcode);
9113 return rcode;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009114 }
9115
9116 must_fork:
9117 /* NB: argv_expanded may already be created, and that
9118 * might include `cmd` runs! Do not rerun it! We *must*
9119 * use argv_expanded if it's non-NULL */
9120
9121 /* Going to fork a child per each pipe member */
9122 pi->alive_cmds = 0;
9123 next_infd = 0;
9124
9125 cmd_no = 0;
9126 while (cmd_no < pi->num_cmds) {
9127 struct fd_pair pipefds;
9128#if !BB_MMU
Denys Vlasenko9db344a2018-04-09 19:05:11 +02009129 int sv_var_nest_level = G.var_nest_level;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009130 volatile nommu_save_t nommu_save;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009131 nommu_save.old_vars = NULL;
9132 nommu_save.argv = NULL;
9133 nommu_save.argv_from_re_execing = NULL;
9134#endif
9135 command = &pi->cmds[cmd_no];
9136 cmd_no++;
9137 if (command->argv) {
9138 debug_printf_exec(": pipe member '%s' '%s'...\n",
9139 command->argv[0], command->argv[1]);
9140 } else {
9141 debug_printf_exec(": pipe member with no argv\n");
9142 }
9143
9144 /* pipes are inserted between pairs of commands */
9145 pipefds.rd = 0;
9146 pipefds.wr = 1;
9147 if (cmd_no < pi->num_cmds)
9148 xpiped_pair(pipefds);
9149
Denys Vlasenko5807e182018-02-08 19:19:04 +01009150#if ENABLE_HUSH_LINENO_VAR
Denys Vlasenkob8d076b2018-01-19 16:00:57 +01009151 if (G.lineno_var)
9152 strcpy(G.lineno_var + sizeof("LINENO=")-1, utoa(command->lineno));
9153#endif
Denys Vlasenko6aad1dd2018-01-19 15:37:04 +01009154
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009155 command->pid = BB_MMU ? fork() : vfork();
9156 if (!command->pid) { /* child */
9157#if ENABLE_HUSH_JOB
9158 disable_restore_tty_pgrp_on_exit();
9159 CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */
9160
9161 /* Every child adds itself to new process group
9162 * with pgid == pid_of_first_child_in_pipe */
9163 if (G.run_list_level == 1 && G_interactive_fd) {
9164 pid_t pgrp;
9165 pgrp = pi->pgrp;
9166 if (pgrp < 0) /* true for 1st process only */
9167 pgrp = getpid();
9168 if (setpgid(0, pgrp) == 0
9169 && pi->followup != PIPE_BG
9170 && G_saved_tty_pgrp /* we have ctty */
9171 ) {
9172 /* We do it in *every* child, not just first,
9173 * to avoid races */
9174 tcsetpgrp(G_interactive_fd, pgrp);
9175 }
9176 }
9177#endif
9178 if (pi->alive_cmds == 0 && pi->followup == PIPE_BG) {
9179 /* 1st cmd in backgrounded pipe
9180 * should have its stdin /dev/null'ed */
9181 close(0);
9182 if (open(bb_dev_null, O_RDONLY))
9183 xopen("/", O_RDONLY);
9184 } else {
9185 xmove_fd(next_infd, 0);
9186 }
9187 xmove_fd(pipefds.wr, 1);
9188 if (pipefds.rd > 1)
9189 close(pipefds.rd);
9190 /* Like bash, explicit redirects override pipes,
Denys Vlasenko869994c2016-08-20 15:16:00 +02009191 * and the pipe fd (fd#1) is available for dup'ing:
9192 * "cmd1 2>&1 | cmd2": fd#1 is duped to fd#2, thus stderr
9193 * of cmd1 goes into pipe.
9194 */
9195 if (setup_redirects(command, NULL)) {
9196 /* Happens when redir file can't be opened:
9197 * $ hush -c 'echo FOO >&2 | echo BAR 3>/qwe/rty; echo BAZ'
9198 * FOO
9199 * hush: can't open '/qwe/rty': No such file or directory
9200 * BAZ
9201 * (echo BAR is not executed, it hits _exit(1) below)
9202 */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009203 _exit(1);
Denys Vlasenko869994c2016-08-20 15:16:00 +02009204 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009205
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009206 /* Stores to nommu_save list of env vars putenv'ed
9207 * (NOMMU, on MMU we don't need that) */
9208 /* cast away volatility... */
9209 pseudo_exec((nommu_save_t*) &nommu_save, command, argv_expanded);
9210 /* pseudo_exec() does not return */
9211 }
9212
9213 /* parent or error */
9214#if ENABLE_HUSH_FAST
9215 G.count_SIGCHLD++;
9216//bb_error_msg("[%d] fork in run_pipe: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
9217#endif
9218 enable_restore_tty_pgrp_on_exit();
9219#if !BB_MMU
9220 /* Clean up after vforked child */
9221 free(nommu_save.argv);
9222 free(nommu_save.argv_from_re_execing);
Denys Vlasenko9db344a2018-04-09 19:05:11 +02009223 G.var_nest_level = sv_var_nest_level;
9224 remove_nested_vars();
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009225 add_vars(nommu_save.old_vars);
9226#endif
9227 free(argv_expanded);
9228 argv_expanded = NULL;
9229 if (command->pid < 0) { /* [v]fork failed */
9230 /* Clearly indicate, was it fork or vfork */
9231 bb_perror_msg(BB_MMU ? "vfork"+1 : "vfork");
9232 } else {
9233 pi->alive_cmds++;
9234#if ENABLE_HUSH_JOB
9235 /* Second and next children need to know pid of first one */
9236 if (pi->pgrp < 0)
9237 pi->pgrp = command->pid;
9238#endif
9239 }
9240
9241 if (cmd_no > 1)
9242 close(next_infd);
9243 if (cmd_no < pi->num_cmds)
9244 close(pipefds.wr);
9245 /* Pass read (output) pipe end to next iteration */
9246 next_infd = pipefds.rd;
9247 }
9248
9249 if (!pi->alive_cmds) {
9250 debug_leave();
9251 debug_printf_exec("run_pipe return 1 (all forks failed, no children)\n");
9252 return 1;
9253 }
9254
9255 debug_leave();
9256 debug_printf_exec("run_pipe return -1 (%u children started)\n", pi->alive_cmds);
9257 return -1;
9258}
9259
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009260/* NB: called by pseudo_exec, and therefore must not modify any
9261 * global data until exec/_exit (we can be a child after vfork!) */
9262static int run_list(struct pipe *pi)
9263{
9264#if ENABLE_HUSH_CASE
9265 char *case_word = NULL;
9266#endif
9267#if ENABLE_HUSH_LOOPS
9268 struct pipe *loop_top = NULL;
9269 char **for_lcur = NULL;
9270 char **for_list = NULL;
9271#endif
9272 smallint last_followup;
9273 smalluint rcode;
9274#if ENABLE_HUSH_IF || ENABLE_HUSH_CASE
9275 smalluint cond_code = 0;
9276#else
9277 enum { cond_code = 0 };
9278#endif
9279#if HAS_KEYWORDS
Denys Vlasenko9b782552010-09-08 13:33:26 +02009280 smallint rword; /* RES_foo */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009281 smallint last_rword; /* ditto */
9282#endif
9283
9284 debug_printf_exec("run_list start lvl %d\n", G.run_list_level);
9285 debug_enter();
9286
9287#if ENABLE_HUSH_LOOPS
9288 /* Check syntax for "for" */
Denys Vlasenko0d6a4ec2010-12-18 01:34:49 +01009289 {
9290 struct pipe *cpipe;
9291 for (cpipe = pi; cpipe; cpipe = cpipe->next) {
9292 if (cpipe->res_word != RES_FOR && cpipe->res_word != RES_IN)
9293 continue;
9294 /* current word is FOR or IN (BOLD in comments below) */
9295 if (cpipe->next == NULL) {
9296 syntax_error("malformed for");
9297 debug_leave();
9298 debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level);
9299 return 1;
9300 }
9301 /* "FOR v; do ..." and "for v IN a b; do..." are ok */
9302 if (cpipe->next->res_word == RES_DO)
9303 continue;
9304 /* next word is not "do". It must be "in" then ("FOR v in ...") */
9305 if (cpipe->res_word == RES_IN /* "for v IN a b; not_do..."? */
9306 || cpipe->next->res_word != RES_IN /* FOR v not_do_and_not_in..."? */
9307 ) {
9308 syntax_error("malformed for");
9309 debug_leave();
9310 debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level);
9311 return 1;
9312 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009313 }
9314 }
9315#endif
9316
9317 /* Past this point, all code paths should jump to ret: label
9318 * in order to return, no direct "return" statements please.
9319 * This helps to ensure that no memory is leaked. */
9320
9321#if ENABLE_HUSH_JOB
9322 G.run_list_level++;
9323#endif
9324
9325#if HAS_KEYWORDS
9326 rword = RES_NONE;
9327 last_rword = RES_XXXX;
9328#endif
9329 last_followup = PIPE_SEQ;
9330 rcode = G.last_exitcode;
9331
9332 /* Go through list of pipes, (maybe) executing them. */
9333 for (; pi; pi = IF_HUSH_LOOPS(rword == RES_DONE ? loop_top : ) pi->next) {
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01009334 int r;
Denys Vlasenko9fda6092017-07-14 13:36:48 +02009335 int sv_errexit_depth;
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01009336
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009337 if (G.flag_SIGINT)
9338 break;
Denys Vlasenko04b46bc2016-10-01 22:28:03 +02009339 if (G_flag_return_in_progress == 1)
9340 break;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009341
9342 IF_HAS_KEYWORDS(rword = pi->res_word;)
9343 debug_printf_exec(": rword=%d cond_code=%d last_rword=%d\n",
9344 rword, cond_code, last_rword);
Denys Vlasenko9fda6092017-07-14 13:36:48 +02009345
9346 sv_errexit_depth = G.errexit_depth;
Denys Vlasenko82d1c1f2017-12-31 17:30:02 +01009347 if (
9348#if ENABLE_HUSH_IF
9349 rword == RES_IF || rword == RES_ELIF ||
9350#endif
Denys Vlasenko9fda6092017-07-14 13:36:48 +02009351 pi->followup != PIPE_SEQ
9352 ) {
9353 G.errexit_depth++;
9354 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009355#if ENABLE_HUSH_LOOPS
9356 if ((rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR)
9357 && loop_top == NULL /* avoid bumping G.depth_of_loop twice */
9358 ) {
9359 /* start of a loop: remember where loop starts */
9360 loop_top = pi;
9361 G.depth_of_loop++;
9362 }
9363#endif
9364 /* Still in the same "if...", "then..." or "do..." branch? */
9365 if (IF_HAS_KEYWORDS(rword == last_rword &&) 1) {
9366 if ((rcode == 0 && last_followup == PIPE_OR)
9367 || (rcode != 0 && last_followup == PIPE_AND)
9368 ) {
9369 /* It is "<true> || CMD" or "<false> && CMD"
9370 * and we should not execute CMD */
9371 debug_printf_exec("skipped cmd because of || or &&\n");
9372 last_followup = pi->followup;
Denys Vlasenko3beab832013-04-07 18:16:58 +02009373 goto dont_check_jobs_but_continue;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009374 }
9375 }
9376 last_followup = pi->followup;
9377 IF_HAS_KEYWORDS(last_rword = rword;)
9378#if ENABLE_HUSH_IF
9379 if (cond_code) {
9380 if (rword == RES_THEN) {
9381 /* if false; then ... fi has exitcode 0! */
9382 G.last_exitcode = rcode = EXIT_SUCCESS;
9383 /* "if <false> THEN cmd": skip cmd */
9384 continue;
9385 }
9386 } else {
9387 if (rword == RES_ELSE || rword == RES_ELIF) {
9388 /* "if <true> then ... ELSE/ELIF cmd":
9389 * skip cmd and all following ones */
9390 break;
9391 }
9392 }
9393#endif
9394#if ENABLE_HUSH_LOOPS
9395 if (rword == RES_FOR) { /* && pi->num_cmds - always == 1 */
9396 if (!for_lcur) {
9397 /* first loop through for */
9398
9399 static const char encoded_dollar_at[] ALIGN1 = {
9400 SPECIAL_VAR_SYMBOL, '@' | 0x80, SPECIAL_VAR_SYMBOL, '\0'
9401 }; /* encoded representation of "$@" */
9402 static const char *const encoded_dollar_at_argv[] = {
9403 encoded_dollar_at, NULL
9404 }; /* argv list with one element: "$@" */
9405 char **vals;
9406
Denys Vlasenkoa5db1d72018-07-28 12:42:08 +02009407 G.last_exitcode = rcode = EXIT_SUCCESS;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009408 vals = (char**)encoded_dollar_at_argv;
9409 if (pi->next->res_word == RES_IN) {
9410 /* if no variable values after "in" we skip "for" */
9411 if (!pi->next->cmds[0].argv) {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009412 debug_printf_exec(": null FOR: exitcode EXIT_SUCCESS\n");
9413 break;
9414 }
9415 vals = pi->next->cmds[0].argv;
9416 } /* else: "for var; do..." -> assume "$@" list */
9417 /* create list of variable values */
9418 debug_print_strings("for_list made from", vals);
9419 for_list = expand_strvec_to_strvec(vals);
9420 for_lcur = for_list;
9421 debug_print_strings("for_list", for_list);
9422 }
9423 if (!*for_lcur) {
9424 /* "for" loop is over, clean up */
9425 free(for_list);
9426 for_list = NULL;
9427 for_lcur = NULL;
9428 break;
9429 }
9430 /* Insert next value from for_lcur */
9431 /* note: *for_lcur already has quotes removed, $var expanded, etc */
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02009432 set_local_var(xasprintf("%s=%s", pi->cmds[0].argv[0], *for_lcur++), /*flag:*/ 0);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009433 continue;
9434 }
9435 if (rword == RES_IN) {
9436 continue; /* "for v IN list;..." - "in" has no cmds anyway */
9437 }
9438 if (rword == RES_DONE) {
9439 continue; /* "done" has no cmds too */
9440 }
9441#endif
9442#if ENABLE_HUSH_CASE
9443 if (rword == RES_CASE) {
Denys Vlasenkoaeaee432016-11-04 20:14:04 +01009444 debug_printf_exec("CASE cond_code:%d\n", cond_code);
Denys Vlasenko34179952018-04-11 13:47:59 +02009445 case_word = expand_string_to_string(pi->cmds->argv[0],
9446 EXP_FLAG_ESC_GLOB_CHARS, /*unbackslash:*/ 1);
Denys Vlasenkoabf75562018-04-02 17:25:18 +02009447 debug_printf_exec("CASE word1:'%s'\n", case_word);
9448 //unbackslash(case_word);
9449 //debug_printf_exec("CASE word2:'%s'\n", case_word);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009450 continue;
9451 }
9452 if (rword == RES_MATCH) {
9453 char **argv;
9454
Denys Vlasenkoaeaee432016-11-04 20:14:04 +01009455 debug_printf_exec("MATCH cond_code:%d\n", cond_code);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009456 if (!case_word) /* "case ... matched_word) ... WORD)": we executed selected branch, stop */
9457 break;
9458 /* all prev words didn't match, does this one match? */
9459 argv = pi->cmds->argv;
9460 while (*argv) {
Denys Vlasenko34179952018-04-11 13:47:59 +02009461 char *pattern;
9462 debug_printf_exec("expand_string_to_string('%s')\n", *argv);
9463 pattern = expand_string_to_string(*argv,
9464 EXP_FLAG_ESC_GLOB_CHARS,
9465 /*unbackslash:*/ 0
9466 );
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009467 /* TODO: which FNM_xxx flags to use? */
9468 cond_code = (fnmatch(pattern, case_word, /*flags:*/ 0) != 0);
Denys Vlasenko34179952018-04-11 13:47:59 +02009469 debug_printf_exec("fnmatch(pattern:'%s',str:'%s'):%d\n",
9470 pattern, case_word, cond_code);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009471 free(pattern);
Denys Vlasenko34179952018-04-11 13:47:59 +02009472 if (cond_code == 0) {
9473 /* match! we will execute this branch */
Denys Vlasenkoaeaee432016-11-04 20:14:04 +01009474 free(case_word);
9475 case_word = NULL; /* make future "word)" stop */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009476 break;
9477 }
9478 argv++;
9479 }
9480 continue;
9481 }
9482 if (rword == RES_CASE_BODY) { /* inside of a case branch */
Denys Vlasenkoaeaee432016-11-04 20:14:04 +01009483 debug_printf_exec("CASE_BODY cond_code:%d\n", cond_code);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009484 if (cond_code != 0)
9485 continue; /* not matched yet, skip this pipe */
9486 }
Denys Vlasenkoaeaee432016-11-04 20:14:04 +01009487 if (rword == RES_ESAC) {
9488 debug_printf_exec("ESAC cond_code:%d\n", cond_code);
9489 if (case_word) {
9490 /* "case" did not match anything: still set $? (to 0) */
9491 G.last_exitcode = rcode = EXIT_SUCCESS;
9492 }
9493 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009494#endif
9495 /* Just pressing <enter> in shell should check for jobs.
9496 * OTOH, in non-interactive shell this is useless
9497 * and only leads to extra job checks */
9498 if (pi->num_cmds == 0) {
9499 if (G_interactive_fd)
9500 goto check_jobs_and_continue;
9501 continue;
9502 }
9503
9504 /* After analyzing all keywords and conditions, we decided
9505 * to execute this pipe. NB: have to do checkjobs(NULL)
9506 * after run_pipe to collect any background children,
9507 * even if list execution is to be stopped. */
9508 debug_printf_exec(": run_pipe with %d members\n", pi->num_cmds);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009509#if ENABLE_HUSH_LOOPS
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01009510 G.flag_break_continue = 0;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009511#endif
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01009512 rcode = r = run_pipe(pi); /* NB: rcode is a smalluint, r is int */
9513 if (r != -1) {
9514 /* We ran a builtin, function, or group.
9515 * rcode is already known
9516 * and we don't need to wait for anything. */
9517 debug_printf_exec(": builtin/func exitcode %d\n", rcode);
9518 G.last_exitcode = rcode;
9519 check_and_run_traps();
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009520#if ENABLE_HUSH_LOOPS
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01009521 /* Was it "break" or "continue"? */
9522 if (G.flag_break_continue) {
9523 smallint fbc = G.flag_break_continue;
9524 /* We might fall into outer *loop*,
9525 * don't want to break it too */
9526 if (loop_top) {
9527 G.depth_break_continue--;
9528 if (G.depth_break_continue == 0)
9529 G.flag_break_continue = 0;
9530 /* else: e.g. "continue 2" should *break* once, *then* continue */
9531 } /* else: "while... do... { we are here (innermost list is not a loop!) };...done" */
9532 if (G.depth_break_continue != 0 || fbc == BC_BREAK) {
Denys Vlasenko7e675362016-10-28 21:57:31 +02009533 checkjobs(NULL, 0 /*(no pid to wait for)*/);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009534 break;
9535 }
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01009536 /* "continue": simulate end of loop */
9537 rword = RES_DONE;
9538 continue;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009539 }
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01009540#endif
9541 if (G_flag_return_in_progress == 1) {
9542 checkjobs(NULL, 0 /*(no pid to wait for)*/);
9543 break;
9544 }
9545 } else if (pi->followup == PIPE_BG) {
9546 /* What does bash do with attempts to background builtins? */
9547 /* even bash 3.2 doesn't do that well with nested bg:
9548 * try "{ { sleep 10; echo DEEP; } & echo HERE; } &".
9549 * I'm NOT treating inner &'s as jobs */
9550#if ENABLE_HUSH_JOB
9551 if (G.run_list_level == 1)
Denys Vlasenko16096292017-07-10 10:00:28 +02009552 insert_job_into_table(pi);
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01009553#endif
9554 /* Last command's pid goes to $! */
9555 G.last_bg_pid = pi->cmds[pi->num_cmds - 1].pid;
Denys Vlasenko840a4352017-07-07 22:56:02 +02009556 G.last_bg_pid_exitcode = 0;
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01009557 debug_printf_exec(": cmd&: exitcode EXIT_SUCCESS\n");
Denys Vlasenko7c40ddd2017-08-02 16:37:39 +02009558/* Check pi->pi_inverted? "! sleep 1 & echo $?": bash says 1. dash and ash say 0 */
Denys Vlasenko6c635d62016-11-08 20:26:11 +01009559 rcode = EXIT_SUCCESS;
9560 goto check_traps;
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01009561 } else {
9562#if ENABLE_HUSH_JOB
9563 if (G.run_list_level == 1 && G_interactive_fd) {
9564 /* Waits for completion, then fg's main shell */
9565 rcode = checkjobs_and_fg_shell(pi);
9566 debug_printf_exec(": checkjobs_and_fg_shell exitcode %d\n", rcode);
Denys Vlasenko6c635d62016-11-08 20:26:11 +01009567 goto check_traps;
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01009568 }
Denys Vlasenko6c635d62016-11-08 20:26:11 +01009569#endif
9570 /* This one just waits for completion */
9571 rcode = checkjobs(pi, 0 /*(no pid to wait for)*/);
9572 debug_printf_exec(": checkjobs exitcode %d\n", rcode);
9573 check_traps:
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01009574 G.last_exitcode = rcode;
9575 check_and_run_traps();
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009576 }
9577
Denys Vlasenko9fda6092017-07-14 13:36:48 +02009578 /* Handle "set -e" */
9579 if (rcode != 0 && G.o_opt[OPT_O_ERREXIT]) {
9580 debug_printf_exec("ERREXIT:1 errexit_depth:%d\n", G.errexit_depth);
9581 if (G.errexit_depth == 0)
9582 hush_exit(rcode);
9583 }
9584 G.errexit_depth = sv_errexit_depth;
9585
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009586 /* Analyze how result affects subsequent commands */
9587#if ENABLE_HUSH_IF
9588 if (rword == RES_IF || rword == RES_ELIF)
9589 cond_code = rcode;
9590#endif
Denys Vlasenko3beab832013-04-07 18:16:58 +02009591 check_jobs_and_continue:
Denys Vlasenko7e675362016-10-28 21:57:31 +02009592 checkjobs(NULL, 0 /*(no pid to wait for)*/);
Denys Vlasenko3beab832013-04-07 18:16:58 +02009593 dont_check_jobs_but_continue: ;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009594#if ENABLE_HUSH_LOOPS
9595 /* Beware of "while false; true; do ..."! */
Denys Vlasenko00ae9892011-05-31 17:35:45 +02009596 if (pi->next
9597 && (pi->next->res_word == RES_DO || pi->next->res_word == RES_DONE)
Denys Vlasenko56a3b822011-06-01 12:47:07 +02009598 /* check for RES_DONE is needed for "while ...; do \n done" case */
Denys Vlasenko00ae9892011-05-31 17:35:45 +02009599 ) {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009600 if (rword == RES_WHILE) {
9601 if (rcode) {
9602 /* "while false; do...done" - exitcode 0 */
9603 G.last_exitcode = rcode = EXIT_SUCCESS;
9604 debug_printf_exec(": while expr is false: breaking (exitcode:EXIT_SUCCESS)\n");
Denys Vlasenko3beab832013-04-07 18:16:58 +02009605 break;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009606 }
9607 }
9608 if (rword == RES_UNTIL) {
9609 if (!rcode) {
9610 debug_printf_exec(": until expr is true: breaking\n");
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009611 break;
9612 }
9613 }
9614 }
9615#endif
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009616 } /* for (pi) */
9617
9618#if ENABLE_HUSH_JOB
9619 G.run_list_level--;
9620#endif
9621#if ENABLE_HUSH_LOOPS
9622 if (loop_top)
9623 G.depth_of_loop--;
9624 free(for_list);
9625#endif
9626#if ENABLE_HUSH_CASE
9627 free(case_word);
9628#endif
9629 debug_leave();
9630 debug_printf_exec("run_list lvl %d return %d\n", G.run_list_level + 1, rcode);
9631 return rcode;
9632}
9633
9634/* Select which version we will use */
9635static int run_and_free_list(struct pipe *pi)
9636{
9637 int rcode = 0;
9638 debug_printf_exec("run_and_free_list entered\n");
Dan Fandrich85c62472010-11-20 13:05:17 -08009639 if (!G.o_opt[OPT_O_NOEXEC]) {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02009640 debug_printf_exec(": run_list: 1st pipe with %d cmds\n", pi->num_cmds);
9641 rcode = run_list(pi);
9642 }
9643 /* free_pipe_list has the side effect of clearing memory.
9644 * In the long run that function can be merged with run_list,
9645 * but doing that now would hobble the debugging effort. */
9646 free_pipe_list(pi);
9647 debug_printf_exec("run_and_free_list return %d\n", rcode);
9648 return rcode;
9649}
9650
9651
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009652static void install_sighandlers(unsigned mask)
Eric Andersen52a97ca2001-06-22 06:49:26 +00009653{
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009654 sighandler_t old_handler;
9655 unsigned sig = 0;
9656 while ((mask >>= 1) != 0) {
9657 sig++;
9658 if (!(mask & 1))
9659 continue;
Denys Vlasenko0806e402011-05-12 23:06:20 +02009660 old_handler = install_sighandler(sig, pick_sighandler(sig));
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009661 /* POSIX allows shell to re-enable SIGCHLD
9662 * even if it was SIG_IGN on entry.
9663 * Therefore we skip IGN check for it:
9664 */
9665 if (sig == SIGCHLD)
9666 continue;
Denys Vlasenko49e6bf22017-08-04 14:28:16 +02009667 /* bash re-enables SIGHUP which is SIG_IGNed on entry.
9668 * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
9669 */
9670 //if (sig == SIGHUP) continue; - TODO?
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009671 if (old_handler == SIG_IGN) {
9672 /* oops... restore back to IGN, and record this fact */
Denys Vlasenko0806e402011-05-12 23:06:20 +02009673 install_sighandler(sig, old_handler);
Denys Vlasenko7a85c602017-01-08 17:40:18 +01009674#if ENABLE_HUSH_TRAP
9675 if (!G_traps)
9676 G_traps = xzalloc(sizeof(G_traps[0]) * NSIG);
9677 free(G_traps[sig]);
9678 G_traps[sig] = xzalloc(1); /* == xstrdup(""); */
9679#endif
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009680 }
9681 }
9682}
9683
9684/* Called a few times only (or even once if "sh -c") */
9685static void install_special_sighandlers(void)
9686{
Denis Vlasenkof9375282009-04-05 19:13:39 +00009687 unsigned mask;
Denys Vlasenkoe89a2412010-01-12 15:19:31 +01009688
Denys Vlasenko54e9e122011-05-09 00:52:15 +02009689 /* Which signals are shell-special? */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009690 mask = (1 << SIGQUIT) | (1 << SIGCHLD);
Denys Vlasenko54e9e122011-05-09 00:52:15 +02009691 if (G_interactive_fd) {
9692 mask |= SPECIAL_INTERACTIVE_SIGS;
9693 if (G_saved_tty_pgrp) /* we have ctty, job control sigs work */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009694 mask |= SPECIAL_JOBSTOP_SIGS;
Denys Vlasenko54e9e122011-05-09 00:52:15 +02009695 }
Denys Vlasenkof58f7052011-05-12 02:10:33 +02009696 /* Careful, do not re-install handlers we already installed */
9697 if (G.special_sig_mask != mask) {
9698 unsigned diff = mask & ~G.special_sig_mask;
9699 G.special_sig_mask = mask;
9700 install_sighandlers(diff);
9701 }
Denis Vlasenkof9375282009-04-05 19:13:39 +00009702}
9703
9704#if ENABLE_HUSH_JOB
9705/* helper */
Denys Vlasenko54e9e122011-05-09 00:52:15 +02009706/* Set handlers to restore tty pgrp and exit */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009707static void install_fatal_sighandlers(void)
Denis Vlasenkof9375282009-04-05 19:13:39 +00009708{
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009709 unsigned mask;
Denys Vlasenko54e9e122011-05-09 00:52:15 +02009710
9711 /* We will restore tty pgrp on these signals */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009712 mask = 0
Denys Vlasenko830ea352016-11-08 04:59:11 +01009713 /*+ (1 << SIGILL ) * HUSH_DEBUG*/
9714 /*+ (1 << SIGFPE ) * HUSH_DEBUG*/
Denys Vlasenko54e9e122011-05-09 00:52:15 +02009715 + (1 << SIGBUS ) * HUSH_DEBUG
9716 + (1 << SIGSEGV) * HUSH_DEBUG
Denys Vlasenko830ea352016-11-08 04:59:11 +01009717 /*+ (1 << SIGTRAP) * HUSH_DEBUG*/
Denys Vlasenko54e9e122011-05-09 00:52:15 +02009718 + (1 << SIGABRT)
9719 /* bash 3.2 seems to handle these just like 'fatal' ones */
9720 + (1 << SIGPIPE)
9721 + (1 << SIGALRM)
Denys Vlasenkof58f7052011-05-12 02:10:33 +02009722 /* if we are interactive, SIGHUP, SIGTERM and SIGINT are special sigs.
Denys Vlasenko54e9e122011-05-09 00:52:15 +02009723 * if we aren't interactive... but in this case
Denys Vlasenkof58f7052011-05-12 02:10:33 +02009724 * we never want to restore pgrp on exit, and this fn is not called
9725 */
Denys Vlasenko54e9e122011-05-09 00:52:15 +02009726 /*+ (1 << SIGHUP )*/
9727 /*+ (1 << SIGTERM)*/
9728 /*+ (1 << SIGINT )*/
9729 ;
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009730 G_fatal_sig_mask = mask;
Denys Vlasenko54e9e122011-05-09 00:52:15 +02009731
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009732 install_sighandlers(mask);
Denis Vlasenkof9375282009-04-05 19:13:39 +00009733}
Denis Vlasenkob81b3df2007-04-28 16:48:04 +00009734#endif
Eric Andersenada18ff2001-05-21 16:18:22 +00009735
Denys Vlasenko6696eac2010-11-14 02:01:50 +01009736static int set_mode(int state, char mode, const char *o_opt)
Denis Vlasenkod5762932009-03-31 11:22:57 +00009737{
Denys Vlasenko6696eac2010-11-14 02:01:50 +01009738 int idx;
Denis Vlasenkod5762932009-03-31 11:22:57 +00009739 switch (mode) {
Denys Vlasenko6696eac2010-11-14 02:01:50 +01009740 case 'n':
Dan Fandrich85c62472010-11-20 13:05:17 -08009741 G.o_opt[OPT_O_NOEXEC] = state;
Denys Vlasenko6696eac2010-11-14 02:01:50 +01009742 break;
9743 case 'x':
9744 IF_HUSH_MODE_X(G_x_mode = state;)
Denys Vlasenkoaa449c92018-07-28 12:13:58 +02009745 IF_HUSH_MODE_X(if (G.x_mode_fd <= 0) G.x_mode_fd = dup_CLOEXEC(2, 10);)
Denys Vlasenko6696eac2010-11-14 02:01:50 +01009746 break;
9747 case 'o':
9748 if (!o_opt) {
9749 /* "set -+o" without parameter.
9750 * in bash, set -o produces this output:
9751 * pipefail off
9752 * and set +o:
9753 * set +o pipefail
9754 * We always use the second form.
9755 */
9756 const char *p = o_opt_strings;
9757 idx = 0;
9758 while (*p) {
9759 printf("set %co %s\n", (G.o_opt[idx] ? '-' : '+'), p);
9760 idx++;
9761 p += strlen(p) + 1;
9762 }
9763 break;
9764 }
9765 idx = index_in_strings(o_opt_strings, o_opt);
9766 if (idx >= 0) {
9767 G.o_opt[idx] = state;
9768 break;
9769 }
Denys Vlasenko9fda6092017-07-14 13:36:48 +02009770 case 'e':
9771 G.o_opt[OPT_O_ERREXIT] = state;
9772 break;
Denys Vlasenko6696eac2010-11-14 02:01:50 +01009773 default:
9774 return EXIT_FAILURE;
Denis Vlasenkod5762932009-03-31 11:22:57 +00009775 }
9776 return EXIT_SUCCESS;
9777}
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009778
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00009779int hush_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Matt Kraai2d91deb2001-08-01 17:21:35 +00009780int hush_main(int argc, char **argv)
Eric Andersen25f27032001-04-26 23:22:31 +00009781{
Denys Vlasenkof58f7052011-05-12 02:10:33 +02009782 enum {
9783 OPT_login = (1 << 0),
Denys Vlasenkof2ed39b2018-04-05 16:46:49 +02009784 OPT_s = (1 << 1),
Denys Vlasenkof58f7052011-05-12 02:10:33 +02009785 };
9786 unsigned flags;
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02009787 unsigned builtin_argc;
Denis Vlasenkofbf6dea2007-04-13 19:56:56 +00009788 char **e;
Denis Vlasenkod76c0492007-05-25 02:16:25 +00009789 struct variable *cur_var;
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01009790 struct variable *shell_ver;
Eric Andersenbc604a22001-05-16 05:24:03 +00009791
Denis Vlasenko574f2f42008-02-27 18:41:59 +00009792 INIT_G();
Denys Vlasenko10c01312011-05-11 11:49:21 +02009793 if (EXIT_SUCCESS != 0) /* if EXIT_SUCCESS == 0, it is already done */
Denis Vlasenkoab2b0642009-04-06 18:42:11 +00009794 G.last_exitcode = EXIT_SUCCESS;
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02009795
Denys Vlasenko10c01312011-05-11 11:49:21 +02009796#if ENABLE_HUSH_FAST
9797 G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
9798#endif
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +00009799#if !BB_MMU
9800 G.argv0_for_re_execing = argv[0];
9801#endif
Denys Vlasenko6aad1dd2018-01-19 15:37:04 +01009802
Denis Vlasenko0a83fc32007-05-25 11:12:32 +00009803 /* Deal with HUSH_VERSION */
Denys Vlasenko6aad1dd2018-01-19 15:37:04 +01009804 debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION");
9805 unsetenv("HUSH_VERSION"); /* in case it exists in initial env */
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01009806 shell_ver = xzalloc(sizeof(*shell_ver));
9807 shell_ver->flg_export = 1;
9808 shell_ver->flg_read_only = 1;
Denys Vlasenko4f870492010-09-10 11:06:01 +02009809 /* Code which handles ${var<op>...} needs writable values for all variables,
Denys Vlasenko36f774a2010-09-05 14:45:38 +02009810 * therefore we xstrdup: */
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01009811 shell_ver->varstr = xstrdup(hush_version_str);
Denys Vlasenko6aad1dd2018-01-19 15:37:04 +01009812
Denys Vlasenko605067b2010-09-06 12:10:51 +02009813 /* Create shell local variables from the values
9814 * currently living in the environment */
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01009815 G.top_var = shell_ver;
Denis Vlasenko87a86552008-07-29 19:43:10 +00009816 cur_var = G.top_var;
Denis Vlasenko0a83fc32007-05-25 11:12:32 +00009817 e = environ;
Denis Vlasenkod76c0492007-05-25 02:16:25 +00009818 if (e) while (*e) {
9819 char *value = strchr(*e, '=');
9820 if (value) { /* paranoia */
9821 cur_var->next = xzalloc(sizeof(*cur_var));
9822 cur_var = cur_var->next;
Denis Vlasenko28c0f0f2007-05-25 02:46:01 +00009823 cur_var->varstr = *e;
Denis Vlasenkod76c0492007-05-25 02:16:25 +00009824 cur_var->max_len = strlen(*e);
9825 cur_var->flg_export = 1;
9826 }
9827 e++;
9828 }
Denys Vlasenko605067b2010-09-06 12:10:51 +02009829 /* (Re)insert HUSH_VERSION into env (AFTER we scanned the env!) */
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01009830 debug_printf_env("putenv '%s'\n", shell_ver->varstr);
9831 putenv(shell_ver->varstr);
Denys Vlasenko6db47842009-09-05 20:15:17 +02009832
9833 /* Export PWD */
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02009834 set_pwd_var(SETFLAG_EXPORT);
Denys Vlasenko3fa97af2014-04-15 11:43:29 +02009835
Denys Vlasenkof5018da2018-04-06 17:58:21 +02009836#if ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT
9837 /* Set (but not export) PS1/2 unless already set */
9838 if (!get_local_var_value("PS1"))
9839 set_local_var_from_halves("PS1", "\\w \\$ ");
9840 if (!get_local_var_value("PS2"))
9841 set_local_var_from_halves("PS2", "> ");
9842#endif
9843
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01009844#if BASH_HOSTNAME_VAR
Denys Vlasenko3fa97af2014-04-15 11:43:29 +02009845 /* Set (but not export) HOSTNAME unless already set */
9846 if (!get_local_var_value("HOSTNAME")) {
9847 struct utsname uts;
9848 uname(&uts);
9849 set_local_var_from_halves("HOSTNAME", uts.nodename);
9850 }
Denys Vlasenko6db47842009-09-05 20:15:17 +02009851 /* bash also exports SHLVL and _,
9852 * and sets (but doesn't export) the following variables:
9853 * BASH=/bin/bash
9854 * BASH_VERSINFO=([0]="3" [1]="2" [2]="0" [3]="1" [4]="release" [5]="i386-pc-linux-gnu")
9855 * BASH_VERSION='3.2.0(1)-release'
9856 * HOSTTYPE=i386
9857 * MACHTYPE=i386-pc-linux-gnu
9858 * OSTYPE=linux-gnu
Denys Vlasenkodea47882009-10-09 15:40:49 +02009859 * PPID=<NNNNN> - we also do it elsewhere
Denys Vlasenko6db47842009-09-05 20:15:17 +02009860 * EUID=<NNNNN>
9861 * UID=<NNNNN>
9862 * GROUPS=()
9863 * LINES=<NNN>
9864 * COLUMNS=<NNN>
9865 * BASH_ARGC=()
9866 * BASH_ARGV=()
9867 * BASH_LINENO=()
9868 * BASH_SOURCE=()
9869 * DIRSTACK=()
9870 * PIPESTATUS=([0]="0")
9871 * HISTFILE=/<xxx>/.bash_history
9872 * HISTFILESIZE=500
9873 * HISTSIZE=500
9874 * MAILCHECK=60
9875 * PATH=/usr/gnu/bin:/usr/local/bin:/bin:/usr/bin:.
9876 * SHELL=/bin/bash
9877 * SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
9878 * TERM=dumb
9879 * OPTERR=1
9880 * OPTIND=1
9881 * IFS=$' \t\n'
Denys Vlasenko6db47842009-09-05 20:15:17 +02009882 * PS4='+ '
9883 */
Denys Vlasenko3fa97af2014-04-15 11:43:29 +02009884#endif
Denys Vlasenko6db47842009-09-05 20:15:17 +02009885
Denys Vlasenko5807e182018-02-08 19:19:04 +01009886#if ENABLE_HUSH_LINENO_VAR
9887 if (ENABLE_HUSH_LINENO_VAR) {
Denys Vlasenko6aad1dd2018-01-19 15:37:04 +01009888 char *p = xasprintf("LINENO=%*s", (int)(sizeof(int)*3), "");
9889 set_local_var(p, /*flags*/ 0);
9890 G.lineno_var = p; /* can't assign before set_local_var("LINENO=...") */
9891 }
9892#endif
9893
Denis Vlasenko38f63192007-01-22 09:03:07 +00009894#if ENABLE_FEATURE_EDITING
Denys Vlasenkoe45af7a2011-09-04 16:15:24 +02009895 G.line_input_state = new_line_input_t(FOR_SHELL);
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00009896#endif
Denys Vlasenko99862cb2010-09-12 17:34:13 +02009897
Eric Andersen94ac2442001-05-22 19:05:18 +00009898 /* Initialize some more globals to non-zero values */
Mike Frysinger67c1c7b2009-04-24 06:26:18 +00009899 cmdedit_update_prompt();
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +00009900
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02009901 die_func = restore_ttypgrp_and__exit;
Denis Vlasenkoed782372009-04-10 00:45:02 +00009902
Denis Vlasenkoc4a7af52009-04-05 20:33:27 +00009903 /* Shell is non-interactive at first. We need to call
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009904 * install_special_sighandlers() if we are going to execute "sh <script>",
Denis Vlasenkod3f973e2009-04-06 10:21:42 +00009905 * "sh -c <cmds>" or login shell's /etc/profile and friends.
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009906 * If we later decide that we are interactive, we run install_special_sighandlers()
Denis Vlasenkoc4a7af52009-04-05 20:33:27 +00009907 * in order to intercept (more) signals.
9908 */
9909
9910 /* Parse options */
Mike Frysinger19a7ea12009-03-28 13:02:11 +00009911 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */
Denys Vlasenkof58f7052011-05-12 02:10:33 +02009912 flags = (argv[0] && argv[0][0] == '-') ? OPT_login : 0;
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02009913 builtin_argc = 0;
Denis Vlasenko0bb4a232009-04-05 01:42:59 +00009914 while (1) {
Denys Vlasenkof2ed39b2018-04-05 16:46:49 +02009915 int opt = getopt(argc, argv, "+c:exinsl"
Denis Vlasenko0bb4a232009-04-05 01:42:59 +00009916#if !BB_MMU
Denis Vlasenkobc569742009-04-12 20:35:19 +00009917 "<:$:R:V:"
9918# if ENABLE_HUSH_FUNCTIONS
9919 "F:"
9920# endif
Denis Vlasenko0bb4a232009-04-05 01:42:59 +00009921#endif
9922 );
9923 if (opt <= 0)
9924 break;
Eric Andersen25f27032001-04-26 23:22:31 +00009925 switch (opt) {
Denis Vlasenkofbf6dea2007-04-13 19:56:56 +00009926 case 'c':
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02009927 /* Possibilities:
9928 * sh ... -c 'script'
9929 * sh ... -c 'script' ARG0 [ARG1...]
9930 * On NOMMU, if builtin_argc != 0,
Denys Vlasenko17323a62010-01-28 01:57:05 +01009931 * sh ... -c 'builtin' BARGV... "" ARG0 [ARG1...]
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02009932 * "" needs to be replaced with NULL
9933 * and BARGV vector fed to builtin function.
Denys Vlasenko17323a62010-01-28 01:57:05 +01009934 * Note: the form without ARG0 never happens:
9935 * sh ... -c 'builtin' BARGV... ""
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02009936 */
Denys Vlasenkodea47882009-10-09 15:40:49 +02009937 if (!G.root_pid) {
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +00009938 G.root_pid = getpid();
Denys Vlasenkodea47882009-10-09 15:40:49 +02009939 G.root_ppid = getppid();
9940 }
Denis Vlasenko87a86552008-07-29 19:43:10 +00009941 G.global_argv = argv + optind;
9942 G.global_argc = argc - optind;
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02009943 if (builtin_argc) {
9944 /* -c 'builtin' [BARGV...] "" ARG0 [ARG1...] */
9945 const struct built_in_command *x;
9946
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009947 install_special_sighandlers();
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02009948 x = find_builtin(optarg);
9949 if (x) { /* paranoia */
9950 G.global_argc -= builtin_argc; /* skip [BARGV...] "" */
9951 G.global_argv += builtin_argc;
9952 G.global_argv[-1] = NULL; /* replace "" */
Denys Vlasenko8ee2ada2011-02-07 02:03:51 +01009953 fflush_all();
Denys Vlasenko17323a62010-01-28 01:57:05 +01009954 G.last_exitcode = x->b_function(argv + optind - 1);
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02009955 }
9956 goto final_return;
9957 }
9958 if (!G.global_argv[0]) {
9959 /* -c 'script' (no params): prevent empty $0 */
9960 G.global_argv--; /* points to argv[i] of 'script' */
9961 G.global_argv[0] = argv[0];
Denys Vlasenko5ae8f1c2010-05-22 06:32:11 +02009962 G.global_argc++;
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02009963 } /* else -c 'script' ARG0 [ARG1...]: $0 is ARG0 */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009964 install_special_sighandlers();
Denis Vlasenkob6e65562009-04-03 16:49:04 +00009965 parse_and_run_string(optarg);
Denis Vlasenkofbf6dea2007-04-13 19:56:56 +00009966 goto final_return;
9967 case 'i':
Denis Vlasenkoc666f712007-05-16 22:18:54 +00009968 /* Well, we cannot just declare interactiveness,
9969 * we have to have some stuff (ctty, etc) */
Denis Vlasenko60b392f2009-04-03 19:14:32 +00009970 /* G_interactive_fd++; */
Denis Vlasenkofbf6dea2007-04-13 19:56:56 +00009971 break;
Mike Frysinger19a7ea12009-03-28 13:02:11 +00009972 case 's':
Denys Vlasenkof2ed39b2018-04-05 16:46:49 +02009973 flags |= OPT_s;
Mike Frysinger19a7ea12009-03-28 13:02:11 +00009974 break;
Denys Vlasenkof58f7052011-05-12 02:10:33 +02009975 case 'l':
9976 flags |= OPT_login;
9977 break;
Denis Vlasenko0bb4a232009-04-05 01:42:59 +00009978#if !BB_MMU
Denis Vlasenko50f3aa42009-04-07 10:52:40 +00009979 case '<': /* "big heredoc" support */
Denys Vlasenko729ecb82010-06-07 14:14:26 +02009980 full_write1_str(optarg);
Denis Vlasenko50f3aa42009-04-07 10:52:40 +00009981 _exit(0);
Denys Vlasenkoe89a2412010-01-12 15:19:31 +01009982 case '$': {
9983 unsigned long long empty_trap_mask;
9984
Denis Vlasenko34e573d2009-04-06 12:56:28 +00009985 G.root_pid = bb_strtou(optarg, &optarg, 16);
9986 optarg++;
Denys Vlasenkodea47882009-10-09 15:40:49 +02009987 G.root_ppid = bb_strtou(optarg, &optarg, 16);
9988 optarg++;
Denis Vlasenko34e573d2009-04-06 12:56:28 +00009989 G.last_bg_pid = bb_strtou(optarg, &optarg, 16);
9990 optarg++;
Denis Vlasenkoab2b0642009-04-06 18:42:11 +00009991 G.last_exitcode = bb_strtou(optarg, &optarg, 16);
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02009992 optarg++;
9993 builtin_argc = bb_strtou(optarg, &optarg, 16);
Denys Vlasenkoe89a2412010-01-12 15:19:31 +01009994 optarg++;
9995 empty_trap_mask = bb_strtoull(optarg, &optarg, 16);
9996 if (empty_trap_mask != 0) {
Denys Vlasenko4ee824f2017-07-03 01:22:13 +02009997 IF_HUSH_TRAP(int sig;)
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009998 install_special_sighandlers();
Denys Vlasenko4ee824f2017-07-03 01:22:13 +02009999# if ENABLE_HUSH_TRAP
Denys Vlasenko7a85c602017-01-08 17:40:18 +010010000 G_traps = xzalloc(sizeof(G_traps[0]) * NSIG);
Denys Vlasenkoe89a2412010-01-12 15:19:31 +010010001 for (sig = 1; sig < NSIG; sig++) {
10002 if (empty_trap_mask & (1LL << sig)) {
Denys Vlasenko7a85c602017-01-08 17:40:18 +010010003 G_traps[sig] = xzalloc(1); /* == xstrdup(""); */
Denys Vlasenko0806e402011-05-12 23:06:20 +020010004 install_sighandler(sig, SIG_IGN);
Denys Vlasenkoe89a2412010-01-12 15:19:31 +010010005 }
10006 }
Denys Vlasenko4ee824f2017-07-03 01:22:13 +020010007# endif
Denys Vlasenkoe89a2412010-01-12 15:19:31 +010010008 }
Denis Vlasenkod3f973e2009-04-06 10:21:42 +000010009# if ENABLE_HUSH_LOOPS
Denis Vlasenko34e573d2009-04-06 12:56:28 +000010010 optarg++;
10011 G.depth_of_loop = bb_strtou(optarg, &optarg, 16);
Denis Vlasenkod3f973e2009-04-06 10:21:42 +000010012# endif
Denys Vlasenkoeb0de052018-04-09 17:54:07 +020010013# if ENABLE_HUSH_FUNCTIONS
10014 /* nommu uses re-exec trick for "... | func | ...",
10015 * should allow "return".
10016 * This accidentally allows returns in subshells.
10017 */
10018 G_flag_return_in_progress = -1;
10019# endif
Denis Vlasenko34e573d2009-04-06 12:56:28 +000010020 break;
Denys Vlasenkoe89a2412010-01-12 15:19:31 +010010021 }
Denis Vlasenko0bb4a232009-04-05 01:42:59 +000010022 case 'R':
10023 case 'V':
Denys Vlasenko3bab36b2017-07-18 01:05:24 +020010024 set_local_var(xstrdup(optarg), opt == 'R' ? SETFLAG_MAKE_RO : 0);
Denis Vlasenko0bb4a232009-04-05 01:42:59 +000010025 break;
Denis Vlasenkobc569742009-04-12 20:35:19 +000010026# if ENABLE_HUSH_FUNCTIONS
10027 case 'F': {
10028 struct function *funcp = new_function(optarg);
10029 /* funcp->name is already set to optarg */
10030 /* funcp->body is set to NULL. It's a special case. */
10031 funcp->body_as_string = argv[optind];
10032 optind++;
10033 break;
10034 }
10035# endif
Denis Vlasenko0bb4a232009-04-05 01:42:59 +000010036#endif
Mike Frysingerad88d5a2009-03-28 13:44:51 +000010037 case 'n':
10038 case 'x':
Denys Vlasenko9fda6092017-07-14 13:36:48 +020010039 case 'e':
Denys Vlasenko6696eac2010-11-14 02:01:50 +010010040 if (set_mode(1, opt, NULL) == 0) /* no error */
Mike Frysingerad88d5a2009-03-28 13:44:51 +000010041 break;
Denis Vlasenkofbf6dea2007-04-13 19:56:56 +000010042 default:
Eric Andersen9ffb7dd2001-05-19 03:00:46 +000010043#ifndef BB_VER
Denis Vlasenkofbf6dea2007-04-13 19:56:56 +000010044 fprintf(stderr, "Usage: sh [FILE]...\n"
10045 " or: sh -c command [args]...\n\n");
10046 exit(EXIT_FAILURE);
Eric Andersen9ffb7dd2001-05-19 03:00:46 +000010047#else
Denis Vlasenkofbf6dea2007-04-13 19:56:56 +000010048 bb_show_usage();
Eric Andersen9ffb7dd2001-05-19 03:00:46 +000010049#endif
Eric Andersen25f27032001-04-26 23:22:31 +000010050 }
Denis Vlasenkof9375282009-04-05 19:13:39 +000010051 } /* option parsing loop */
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +000010052
Denys Vlasenkof58f7052011-05-12 02:10:33 +020010053 /* Skip options. Try "hush -l": $1 should not be "-l"! */
10054 G.global_argc = argc - (optind - 1);
10055 G.global_argv = argv + (optind - 1);
10056 G.global_argv[0] = argv[0];
10057
Denys Vlasenkodea47882009-10-09 15:40:49 +020010058 if (!G.root_pid) {
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +000010059 G.root_pid = getpid();
Denys Vlasenkodea47882009-10-09 15:40:49 +020010060 G.root_ppid = getppid();
10061 }
Denis Vlasenkof9375282009-04-05 19:13:39 +000010062
10063 /* If we are login shell... */
Denys Vlasenkof58f7052011-05-12 02:10:33 +020010064 if (flags & OPT_login) {
Denys Vlasenko41ef41b2018-07-24 16:54:41 +020010065 HFILE *input;
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +000010066 debug_printf("sourcing /etc/profile\n");
Denys Vlasenko41ef41b2018-07-24 16:54:41 +020010067 input = hfopen("/etc/profile");
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +000010068 if (input != NULL) {
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +020010069 install_special_sighandlers();
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +000010070 parse_and_run_file(input);
Denys Vlasenko41ef41b2018-07-24 16:54:41 +020010071 hfclose(input);
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +000010072 }
Denis Vlasenkof9375282009-04-05 19:13:39 +000010073 /* bash: after sourcing /etc/profile,
10074 * tries to source (in the given order):
10075 * ~/.bash_profile, ~/.bash_login, ~/.profile,
Denys Vlasenko28a105d2009-06-01 11:26:30 +020010076 * stopping on first found. --noprofile turns this off.
Denis Vlasenkof9375282009-04-05 19:13:39 +000010077 * bash also sources ~/.bash_logout on exit.
10078 * If called as sh, skips .bash_XXX files.
10079 */
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +000010080 }
10081
Denys Vlasenkof2ed39b2018-04-05 16:46:49 +020010082 /* -s is: hush -s ARGV1 ARGV2 (no SCRIPT) */
10083 if (!(flags & OPT_s) && G.global_argv[1]) {
Denys Vlasenko41ef41b2018-07-24 16:54:41 +020010084 HFILE *input;
Denis Vlasenkof9375282009-04-05 19:13:39 +000010085 /*
Denis Vlasenkod3f973e2009-04-06 10:21:42 +000010086 * "bash <script>" (which is never interactive (unless -i?))
10087 * sources $BASH_ENV here (without scanning $PATH).
Denis Vlasenkof9375282009-04-05 19:13:39 +000010088 * If called as sh, does the same but with $ENV.
Denys Vlasenko2eb0a7e2016-10-27 11:28:59 +020010089 * Also NB, per POSIX, $ENV should undergo parameter expansion.
Denis Vlasenkof9375282009-04-05 19:13:39 +000010090 */
Denys Vlasenkof58f7052011-05-12 02:10:33 +020010091 G.global_argc--;
10092 G.global_argv++;
10093 debug_printf("running script '%s'\n", G.global_argv[0]);
Denys Vlasenkob7adf7a2016-10-25 17:00:13 +020010094 xfunc_error_retval = 127; /* for "hush /does/not/exist" case */
Denys Vlasenko41ef41b2018-07-24 16:54:41 +020010095 input = hfopen(G.global_argv[0]);
10096 if (!input) {
10097 bb_simple_perror_msg_and_die(G.global_argv[0]);
10098 }
Denys Vlasenkob7adf7a2016-10-25 17:00:13 +020010099 xfunc_error_retval = 1;
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +020010100 install_special_sighandlers();
Denis Vlasenkof9375282009-04-05 19:13:39 +000010101 parse_and_run_file(input);
10102#if ENABLE_FEATURE_CLEAN_UP
Denys Vlasenko41ef41b2018-07-24 16:54:41 +020010103 hfclose(input);
Denis Vlasenkof9375282009-04-05 19:13:39 +000010104#endif
10105 goto final_return;
10106 }
10107
Denis Vlasenkoc4a7af52009-04-05 20:33:27 +000010108 /* Up to here, shell was non-interactive. Now it may become one.
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +020010109 * NB: don't forget to (re)run install_special_sighandlers() as needed.
Denis Vlasenkoc4a7af52009-04-05 20:33:27 +000010110 */
Denis Vlasenkof9375282009-04-05 19:13:39 +000010111
Denys Vlasenko28a105d2009-06-01 11:26:30 +020010112 /* A shell is interactive if the '-i' flag was given,
10113 * or if all of the following conditions are met:
Denis Vlasenko55b2de72007-04-18 17:21:28 +000010114 * no -c command
Eric Andersen25f27032001-04-26 23:22:31 +000010115 * no arguments remaining or the -s flag given
10116 * standard input is a terminal
10117 * standard output is a terminal
Denis Vlasenkof9375282009-04-05 19:13:39 +000010118 * Refer to Posix.2, the description of the 'sh' utility.
10119 */
10120#if ENABLE_HUSH_JOB
10121 if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
Mike Frysinger38478a62009-05-20 04:48:06 -040010122 G_saved_tty_pgrp = tcgetpgrp(STDIN_FILENO);
10123 debug_printf("saved_tty_pgrp:%d\n", G_saved_tty_pgrp);
10124 if (G_saved_tty_pgrp < 0)
10125 G_saved_tty_pgrp = 0;
Denis Vlasenkoc8653f62009-04-27 23:29:14 +000010126
10127 /* try to dup stdin to high fd#, >= 255 */
Denys Vlasenko9acd63c2018-03-28 18:35:07 +020010128 G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254);
Denis Vlasenkoc8653f62009-04-27 23:29:14 +000010129 if (G_interactive_fd < 0) {
10130 /* try to dup to any fd */
10131 G_interactive_fd = dup(STDIN_FILENO);
Denis Vlasenko60b392f2009-04-03 19:14:32 +000010132 if (G_interactive_fd < 0) {
Denis Vlasenkoc8653f62009-04-27 23:29:14 +000010133 /* give up */
10134 G_interactive_fd = 0;
Mike Frysinger38478a62009-05-20 04:48:06 -040010135 G_saved_tty_pgrp = 0;
Denis Vlasenko54e7ffb2007-04-21 00:03:36 +000010136 }
10137 }
Denis Vlasenkoc8653f62009-04-27 23:29:14 +000010138// TODO: track & disallow any attempts of user
10139// to (inadvertently) close/redirect G_interactive_fd
Eric Andersen25f27032001-04-26 23:22:31 +000010140 }
Denis Vlasenkof9375282009-04-05 19:13:39 +000010141 debug_printf("interactive_fd:%d\n", G_interactive_fd);
Denis Vlasenko60b392f2009-04-03 19:14:32 +000010142 if (G_interactive_fd) {
Denis Vlasenkof9375282009-04-05 19:13:39 +000010143 close_on_exec_on(G_interactive_fd);
Denis Vlasenkoc8653f62009-04-27 23:29:14 +000010144
Mike Frysinger38478a62009-05-20 04:48:06 -040010145 if (G_saved_tty_pgrp) {
Denis Vlasenkoc8653f62009-04-27 23:29:14 +000010146 /* If we were run as 'hush &', sleep until we are
10147 * in the foreground (tty pgrp == our pgrp).
10148 * If we get started under a job aware app (like bash),
10149 * make sure we are now in charge so we don't fight over
10150 * who gets the foreground */
10151 while (1) {
10152 pid_t shell_pgrp = getpgrp();
Mike Frysinger38478a62009-05-20 04:48:06 -040010153 G_saved_tty_pgrp = tcgetpgrp(G_interactive_fd);
10154 if (G_saved_tty_pgrp == shell_pgrp)
Denis Vlasenkoc8653f62009-04-27 23:29:14 +000010155 break;
10156 /* send TTIN to ourself (should stop us) */
10157 kill(- shell_pgrp, SIGTTIN);
10158 }
Denis Vlasenkof9375282009-04-05 19:13:39 +000010159 }
Denis Vlasenkoc8653f62009-04-27 23:29:14 +000010160
Denys Vlasenkof58f7052011-05-12 02:10:33 +020010161 /* Install more signal handlers */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +020010162 install_special_sighandlers();
Denis Vlasenkoc8653f62009-04-27 23:29:14 +000010163
Mike Frysinger38478a62009-05-20 04:48:06 -040010164 if (G_saved_tty_pgrp) {
Denis Vlasenkoc8653f62009-04-27 23:29:14 +000010165 /* Set other signals to restore saved_tty_pgrp */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +020010166 install_fatal_sighandlers();
Denis Vlasenkoc8653f62009-04-27 23:29:14 +000010167 /* Put ourselves in our own process group
10168 * (bash, too, does this only if ctty is available) */
10169 bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */
10170 /* Grab control of the terminal */
10171 tcsetpgrp(G_interactive_fd, getpid());
10172 }
Denys Vlasenko550bf5b2015-10-09 16:42:57 +020010173 enable_restore_tty_pgrp_on_exit();
Denys Vlasenko4840ae82011-09-04 15:28:03 +020010174
10175# if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0
10176 {
10177 const char *hp = get_local_var_value("HISTFILE");
10178 if (!hp) {
10179 hp = get_local_var_value("HOME");
10180 if (hp)
10181 hp = concat_path_file(hp, ".hush_history");
10182 } else {
10183 hp = xstrdup(hp);
10184 }
10185 if (hp) {
10186 G.line_input_state->hist_file = hp;
Denys Vlasenko4840ae82011-09-04 15:28:03 +020010187 //set_local_var(xasprintf("HISTFILE=%s", ...));
10188 }
10189# if ENABLE_FEATURE_SH_HISTFILESIZE
10190 hp = get_local_var_value("HISTFILESIZE");
10191 G.line_input_state->max_history = size_from_HISTFILESIZE(hp);
10192# endif
10193 }
10194# endif
Denys Vlasenkoe89a2412010-01-12 15:19:31 +010010195 } else {
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +020010196 install_special_sighandlers();
Denys Vlasenkoe89a2412010-01-12 15:19:31 +010010197 }
Denis Vlasenkoe3f2f892007-04-28 16:48:27 +000010198#elif ENABLE_HUSH_INTERACTIVE
Denis Vlasenkof9375282009-04-05 19:13:39 +000010199 /* No job control compiled in, only prompt/line editing */
10200 if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
Denys Vlasenko9acd63c2018-03-28 18:35:07 +020010201 G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254);
Denis Vlasenko60b392f2009-04-03 19:14:32 +000010202 if (G_interactive_fd < 0) {
Denis Vlasenkoe3f2f892007-04-28 16:48:27 +000010203 /* try to dup to any fd */
Denys Vlasenkod1a83232018-06-26 15:50:33 +020010204 G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, -1);
Denis Vlasenko60b392f2009-04-03 19:14:32 +000010205 if (G_interactive_fd < 0)
Denis Vlasenkoe3f2f892007-04-28 16:48:27 +000010206 /* give up */
Denis Vlasenko60b392f2009-04-03 19:14:32 +000010207 G_interactive_fd = 0;
Denis Vlasenkoe3f2f892007-04-28 16:48:27 +000010208 }
10209 }
Denis Vlasenko60b392f2009-04-03 19:14:32 +000010210 if (G_interactive_fd) {
Denis Vlasenkof9375282009-04-05 19:13:39 +000010211 close_on_exec_on(G_interactive_fd);
Denis Vlasenkof9375282009-04-05 19:13:39 +000010212 }
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +020010213 install_special_sighandlers();
Denis Vlasenkof9375282009-04-05 19:13:39 +000010214#else
10215 /* We have interactiveness code disabled */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +020010216 install_special_sighandlers();
Denis Vlasenkof9375282009-04-05 19:13:39 +000010217#endif
10218 /* bash:
10219 * if interactive but not a login shell, sources ~/.bashrc
10220 * (--norc turns this off, --rcfile <file> overrides)
10221 */
10222
10223 if (!ENABLE_FEATURE_SH_EXTRA_QUIET && G_interactive_fd) {
Denys Vlasenkoc34c0332009-09-29 12:25:30 +020010224 /* note: ash and hush share this string */
10225 printf("\n\n%s %s\n"
10226 IF_HUSH_HELP("Enter 'help' for a list of built-in commands.\n")
10227 "\n",
10228 bb_banner,
10229 "hush - the humble shell"
10230 );
Mike Frysingerb2705e12009-03-23 08:44:02 +000010231 }
10232
Denys Vlasenko41ef41b2018-07-24 16:54:41 +020010233 parse_and_run_file(hfopen(NULL)); /* stdin */
Eric Andersen25f27032001-04-26 23:22:31 +000010234
Denis Vlasenkod76c0492007-05-25 02:16:25 +000010235 final_return:
Denis Vlasenkoab2b0642009-04-06 18:42:11 +000010236 hush_exit(G.last_exitcode);
Eric Andersen25f27032001-04-26 23:22:31 +000010237}
Denis Vlasenko96702ca2007-11-23 23:28:55 +000010238
10239
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010240/*
10241 * Built-ins
10242 */
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +020010243static int FAST_FUNC builtin_true(char **argv UNUSED_PARAM)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010244{
10245 return 0;
10246}
10247
Denys Vlasenko265062d2017-01-10 15:13:30 +010010248#if ENABLE_HUSH_TEST || ENABLE_HUSH_ECHO || ENABLE_HUSH_PRINTF || ENABLE_HUSH_KILL
Denys Vlasenko8bc7f2c2009-10-19 13:20:52 +020010249static int run_applet_main(char **argv, int (*applet_main_func)(int argc, char **argv))
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010250{
Denys Vlasenkod4e4fdb2017-07-03 21:31:16 +020010251 int argc = string_array_len(argv);
10252 return applet_main_func(argc, argv);
Mike Frysingerccb19592009-10-15 03:31:15 -040010253}
Denys Vlasenko265062d2017-01-10 15:13:30 +010010254#endif
Kang-Che Sung027d3ab2017-01-11 14:18:15 +010010255#if ENABLE_HUSH_TEST || BASH_TEST2
Mike Frysingerccb19592009-10-15 03:31:15 -040010256static int FAST_FUNC builtin_test(char **argv)
10257{
Denys Vlasenkoc0836532009-10-19 13:13:06 +020010258 return run_applet_main(argv, test_main);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010259}
Denys Vlasenko265062d2017-01-10 15:13:30 +010010260#endif
Denys Vlasenko1cc68042017-01-09 17:10:04 +010010261#if ENABLE_HUSH_ECHO
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +020010262static int FAST_FUNC builtin_echo(char **argv)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010263{
Denys Vlasenkoc0836532009-10-19 13:13:06 +020010264 return run_applet_main(argv, echo_main);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010265}
Denys Vlasenko1cc68042017-01-09 17:10:04 +010010266#endif
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010010267#if ENABLE_HUSH_PRINTF
Mike Frysinger4ebc76c2009-10-15 03:32:39 -040010268static int FAST_FUNC builtin_printf(char **argv)
10269{
Denys Vlasenkoc0836532009-10-19 13:13:06 +020010270 return run_applet_main(argv, printf_main);
Mike Frysinger4ebc76c2009-10-15 03:32:39 -040010271}
10272#endif
10273
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010010274#if ENABLE_HUSH_HELP
10275static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM)
10276{
10277 const struct built_in_command *x;
10278
10279 printf(
10280 "Built-in commands:\n"
10281 "------------------\n");
10282 for (x = bltins1; x != &bltins1[ARRAY_SIZE(bltins1)]; x++) {
10283 if (x->b_descr)
10284 printf("%-10s%s\n", x->b_cmd, x->b_descr);
10285 }
10286 return EXIT_SUCCESS;
10287}
10288#endif
10289
10290#if MAX_HISTORY && ENABLE_FEATURE_EDITING
10291static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM)
10292{
10293 show_history(G.line_input_state);
10294 return EXIT_SUCCESS;
10295}
10296#endif
10297
Denys Vlasenkob131cce2010-05-20 03:39:43 +020010298static char **skip_dash_dash(char **argv)
10299{
10300 argv++;
10301 if (argv[0] && argv[0][0] == '-' && argv[0][1] == '-' && argv[0][2] == '\0')
10302 argv++;
10303 return argv;
10304}
10305
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +020010306static int FAST_FUNC builtin_cd(char **argv)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010307{
Denys Vlasenkob131cce2010-05-20 03:39:43 +020010308 const char *newdir;
10309
10310 argv = skip_dash_dash(argv);
10311 newdir = argv[0];
Denis Vlasenkobfbc9712009-04-06 12:04:42 +000010312 if (newdir == NULL) {
Denis Vlasenkob6e65562009-04-03 16:49:04 +000010313 /* bash does nothing (exitcode 0) if HOME is ""; if it's unset,
Denis Vlasenko0b677d82009-04-10 13:49:10 +000010314 * bash says "bash: cd: HOME not set" and does nothing
10315 * (exitcode 1)
Denis Vlasenkob6e65562009-04-03 16:49:04 +000010316 */
Denys Vlasenko90a99042009-09-06 02:36:23 +020010317 const char *home = get_local_var_value("HOME");
10318 newdir = home ? home : "/";
Denis Vlasenkob0a64782009-04-06 11:33:07 +000010319 }
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010320 if (chdir(newdir)) {
Denis Vlasenkobfbc9712009-04-06 12:04:42 +000010321 /* Mimic bash message exactly */
10322 bb_perror_msg("cd: %s", newdir);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010323 return EXIT_FAILURE;
10324 }
Denys Vlasenko6db47842009-09-05 20:15:17 +020010325 /* Read current dir (get_cwd(1) is inside) and set PWD.
10326 * Note: do not enforce exporting. If PWD was unset or unexported,
10327 * set it again, but do not export. bash does the same.
10328 */
Denys Vlasenko3bab36b2017-07-18 01:05:24 +020010329 set_pwd_var(/*flag:*/ 0);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010330 return EXIT_SUCCESS;
10331}
10332
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010010333static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM)
10334{
10335 puts(get_cwd(0));
10336 return EXIT_SUCCESS;
10337}
10338
10339static int FAST_FUNC builtin_eval(char **argv)
10340{
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010010341 argv = skip_dash_dash(argv);
Denys Vlasenko1f191122018-01-11 13:17:30 +010010342
Denys Vlasenkob0441a72018-07-15 18:03:56 +020010343 if (!argv[0])
10344 return EXIT_SUCCESS;
Denys Vlasenko1f191122018-01-11 13:17:30 +010010345
Denys Vlasenko7c5f18a2018-07-26 15:21:50 +020010346 IF_HUSH_MODE_X(G.x_mode_depth++;)
Denys Vlasenko9dda9272018-07-27 14:12:05 +020010347 //bb_error_msg("%s: ++x_mode_depth=%d", __func__, G.x_mode_depth);
Denys Vlasenkob0441a72018-07-15 18:03:56 +020010348 if (!argv[1]) {
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010010349 /* bash:
10350 * eval "echo Hi; done" ("done" is syntax error):
10351 * "echo Hi" will not execute too.
10352 */
Denys Vlasenkob0441a72018-07-15 18:03:56 +020010353 parse_and_run_string(argv[0]);
10354 } else {
10355 /* "The eval utility shall construct a command by
10356 * concatenating arguments together, separating
10357 * each with a <space> character."
10358 */
10359 char *str, *p;
10360 unsigned len = 0;
10361 char **pp = argv;
10362 do
10363 len += strlen(*pp) + 1;
10364 while (*++pp);
10365 str = p = xmalloc(len);
10366 pp = argv;
10367 for (;;) {
10368 p = stpcpy(p, *pp);
10369 pp++;
10370 if (!*pp)
10371 break;
10372 *p++ = ' ';
10373 }
10374 parse_and_run_string(str);
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010010375 free(str);
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010010376 }
Denys Vlasenko7c5f18a2018-07-26 15:21:50 +020010377 IF_HUSH_MODE_X(G.x_mode_depth--;)
Denys Vlasenko9dda9272018-07-27 14:12:05 +020010378 //bb_error_msg("%s: --x_mode_depth=%d", __func__, G.x_mode_depth);
Denys Vlasenkob0441a72018-07-15 18:03:56 +020010379 return G.last_exitcode;
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010010380}
10381
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +020010382static int FAST_FUNC builtin_exec(char **argv)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010383{
Denys Vlasenkob131cce2010-05-20 03:39:43 +020010384 argv = skip_dash_dash(argv);
10385 if (argv[0] == NULL)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010386 return EXIT_SUCCESS; /* bash does this */
Denys Vlasenkof37eb392009-10-18 11:46:35 +020010387
Denys Vlasenkof37eb392009-10-18 11:46:35 +020010388 /* Careful: we can end up here after [v]fork. Do not restore
10389 * tty pgrp then, only top-level shell process does that */
10390 if (G_saved_tty_pgrp && getpid() == G.root_pid)
10391 tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp);
10392
Denys Vlasenko5b3d2eb2017-07-31 18:02:28 +020010393 /* Saved-redirect fds, script fds and G_interactive_fd are still
10394 * open here. However, they are all CLOEXEC, and execv below
10395 * closes them. Try interactive "exec ls -l /proc/self/fd",
10396 * it should show no extra open fds in the "ls" process.
10397 * If we'd try to run builtins/NOEXECs, this would need improving.
10398 */
10399 //close_saved_fds_and_FILE_fds();
10400
Denys Vlasenko3ef4f772009-10-19 23:09:06 +020010401 /* TODO: if exec fails, bash does NOT exit! We do.
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +020010402 * We'll need to undo trap cleanup (it's inside execvp_or_die)
Denys Vlasenko3ef4f772009-10-19 23:09:06 +020010403 * and tcsetpgrp, and this is inherently racy.
10404 */
10405 execvp_or_die(argv);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010406}
10407
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +020010408static int FAST_FUNC builtin_exit(char **argv)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010409{
Denis Vlasenkocd418a22009-04-06 18:08:35 +000010410 debug_printf_exec("%s()\n", __func__);
Denis Vlasenko40e84372009-04-18 11:23:38 +000010411
10412 /* interactive bash:
10413 * # trap "echo EEE" EXIT
10414 * # exit
10415 * exit
10416 * There are stopped jobs.
10417 * (if there are _stopped_ jobs, running ones don't count)
10418 * # exit
10419 * exit
Denys Vlasenko6830ade2013-01-15 13:58:01 +010010420 * EEE (then bash exits)
Denis Vlasenko40e84372009-04-18 11:23:38 +000010421 *
Denys Vlasenkoa110c902010-09-12 15:38:04 +020010422 * TODO: we can use G.exiting = -1 as indicator "last cmd was exit"
Denis Vlasenko40e84372009-04-18 11:23:38 +000010423 */
Denis Vlasenkoefea9d22009-04-09 13:43:11 +000010424
10425 /* note: EXIT trap is run by hush_exit */
Denys Vlasenkob131cce2010-05-20 03:39:43 +020010426 argv = skip_dash_dash(argv);
10427 if (argv[0] == NULL)
Denis Vlasenkoab2b0642009-04-06 18:42:11 +000010428 hush_exit(G.last_exitcode);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010429 /* mimic bash: exit 123abc == exit 255 + error msg */
10430 xfunc_error_retval = 255;
10431 /* bash: exit -2 == exit 254, no error msg */
Denys Vlasenkob131cce2010-05-20 03:39:43 +020010432 hush_exit(xatoi(argv[0]) & 0xff);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010433}
10434
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010010435#if ENABLE_HUSH_TYPE
10436/* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */
10437static int FAST_FUNC builtin_type(char **argv)
10438{
10439 int ret = EXIT_SUCCESS;
10440
10441 while (*++argv) {
10442 const char *type;
10443 char *path = NULL;
10444
10445 if (0) {} /* make conditional compile easier below */
10446 /*else if (find_alias(*argv))
10447 type = "an alias";*/
10448#if ENABLE_HUSH_FUNCTIONS
10449 else if (find_function(*argv))
10450 type = "a function";
10451#endif
10452 else if (find_builtin(*argv))
10453 type = "a shell builtin";
10454 else if ((path = find_in_path(*argv)) != NULL)
10455 type = path;
10456 else {
10457 bb_error_msg("type: %s: not found", *argv);
10458 ret = EXIT_FAILURE;
10459 continue;
10460 }
10461
10462 printf("%s is %s\n", *argv, type);
10463 free(path);
10464 }
10465
10466 return ret;
10467}
10468#endif
10469
10470#if ENABLE_HUSH_READ
10471/* Interruptibility of read builtin in bash
10472 * (tested on bash-4.2.8 by sending signals (not by ^C)):
10473 *
10474 * Empty trap makes read ignore corresponding signal, for any signal.
10475 *
10476 * SIGINT:
10477 * - terminates non-interactive shell;
10478 * - interrupts read in interactive shell;
10479 * if it has non-empty trap:
10480 * - executes trap and returns to command prompt in interactive shell;
10481 * - executes trap and returns to read in non-interactive shell;
10482 * SIGTERM:
10483 * - is ignored (does not interrupt) read in interactive shell;
10484 * - terminates non-interactive shell;
10485 * if it has non-empty trap:
10486 * - executes trap and returns to read;
10487 * SIGHUP:
10488 * - terminates shell (regardless of interactivity);
10489 * if it has non-empty trap:
10490 * - executes trap and returns to read;
Denys Vlasenkof5470412017-05-22 19:34:45 +020010491 * SIGCHLD from children:
10492 * - does not interrupt read regardless of interactivity:
10493 * try: sleep 1 & read x; echo $x
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010010494 */
10495static int FAST_FUNC builtin_read(char **argv)
10496{
10497 const char *r;
10498 char *opt_n = NULL;
10499 char *opt_p = NULL;
10500 char *opt_t = NULL;
10501 char *opt_u = NULL;
Denys Vlasenko1f41c882017-08-09 13:52:36 +020010502 char *opt_d = NULL; /* optimized out if !BASH */
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010010503 const char *ifs;
10504 int read_flags;
10505
10506 /* "!": do not abort on errors.
10507 * Option string must start with "sr" to match BUILTIN_READ_xxx
10508 */
Denys Vlasenko1f41c882017-08-09 13:52:36 +020010509 read_flags = getopt32(argv,
10510#if BASH_READ_D
10511 "!srn:p:t:u:d:", &opt_n, &opt_p, &opt_t, &opt_u, &opt_d
10512#else
10513 "!srn:p:t:u:", &opt_n, &opt_p, &opt_t, &opt_u
10514#endif
10515 );
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010010516 if (read_flags == (uint32_t)-1)
10517 return EXIT_FAILURE;
10518 argv += optind;
10519 ifs = get_local_var_value("IFS"); /* can be NULL */
10520
10521 again:
10522 r = shell_builtin_read(set_local_var_from_halves,
10523 argv,
10524 ifs,
10525 read_flags,
10526 opt_n,
10527 opt_p,
10528 opt_t,
Denys Vlasenko1f41c882017-08-09 13:52:36 +020010529 opt_u,
10530 opt_d
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010010531 );
10532
10533 if ((uintptr_t)r == 1 && errno == EINTR) {
10534 unsigned sig = check_and_run_traps();
Denys Vlasenkof5470412017-05-22 19:34:45 +020010535 if (sig != SIGINT)
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010010536 goto again;
10537 }
10538
10539 if ((uintptr_t)r > 1) {
10540 bb_error_msg("%s", r);
10541 r = (char*)(uintptr_t)1;
10542 }
10543
10544 return (uintptr_t)r;
10545}
10546#endif
10547
10548#if ENABLE_HUSH_UMASK
10549static int FAST_FUNC builtin_umask(char **argv)
10550{
10551 int rc;
10552 mode_t mask;
10553
10554 rc = 1;
10555 mask = umask(0);
10556 argv = skip_dash_dash(argv);
10557 if (argv[0]) {
10558 mode_t old_mask = mask;
10559
10560 /* numeric umasks are taken as-is */
10561 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
10562 if (!isdigit(argv[0][0]))
10563 mask ^= 0777;
10564 mask = bb_parse_mode(argv[0], mask);
10565 if (!isdigit(argv[0][0]))
10566 mask ^= 0777;
10567 if ((unsigned)mask > 0777) {
10568 mask = old_mask;
10569 /* bash messages:
10570 * bash: umask: 'q': invalid symbolic mode operator
10571 * bash: umask: 999: octal number out of range
10572 */
10573 bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]);
10574 rc = 0;
10575 }
10576 } else {
10577 /* Mimic bash */
10578 printf("%04o\n", (unsigned) mask);
10579 /* fall through and restore mask which we set to 0 */
10580 }
10581 umask(mask);
10582
10583 return !rc; /* rc != 0 - success */
10584}
10585#endif
10586
Denys Vlasenko41ade052017-01-08 18:56:24 +010010587#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_TRAP
Denis Vlasenko38e626d2009-04-18 12:58:19 +000010588static void print_escaped(const char *s)
10589{
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +020010590 if (*s == '\'')
10591 goto squote;
Denis Vlasenko38e626d2009-04-18 12:58:19 +000010592 do {
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +020010593 const char *p = strchrnul(s, '\'');
10594 /* print 'xxxx', possibly just '' */
10595 printf("'%.*s'", (int)(p - s), s);
10596 if (*p == '\0')
10597 break;
10598 s = p;
10599 squote:
Denis Vlasenko38e626d2009-04-18 12:58:19 +000010600 /* s points to '; print "'''...'''" */
10601 putchar('"');
10602 do putchar('\''); while (*++s == '\'');
10603 putchar('"');
10604 } while (*s);
10605}
Denys Vlasenko41ade052017-01-08 18:56:24 +010010606#endif
Denis Vlasenko38e626d2009-04-18 12:58:19 +000010607
Denys Vlasenko1e660422017-07-17 21:10:50 +020010608#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_LOCAL || ENABLE_HUSH_READONLY
Denys Vlasenko3bab36b2017-07-18 01:05:24 +020010609static int helper_export_local(char **argv, unsigned flags)
Denys Vlasenko295fef82009-06-03 12:47:26 +020010610{
10611 do {
10612 char *name = *argv;
Denys Vlasenko27c56f12010-09-07 09:56:34 +020010613 char *name_end = strchrnul(name, '=');
Denys Vlasenko295fef82009-06-03 12:47:26 +020010614
10615 /* So far we do not check that name is valid (TODO?) */
10616
Denys Vlasenko27c56f12010-09-07 09:56:34 +020010617 if (*name_end == '\0') {
10618 struct variable *var, **vpp;
Denys Vlasenko295fef82009-06-03 12:47:26 +020010619
Denys Vlasenko27c56f12010-09-07 09:56:34 +020010620 vpp = get_ptr_to_local_var(name, name_end - name);
10621 var = vpp ? *vpp : NULL;
10622
Denys Vlasenko3bab36b2017-07-18 01:05:24 +020010623 if (flags & SETFLAG_UNEXPORT) {
Denys Vlasenko295fef82009-06-03 12:47:26 +020010624 /* export -n NAME (without =VALUE) */
10625 if (var) {
10626 var->flg_export = 0;
10627 debug_printf_env("%s: unsetenv '%s'\n", __func__, name);
10628 unsetenv(name);
10629 } /* else: export -n NOT_EXISTING_VAR: no-op */
10630 continue;
10631 }
Denys Vlasenko3bab36b2017-07-18 01:05:24 +020010632 if (flags & SETFLAG_EXPORT) {
Denys Vlasenko295fef82009-06-03 12:47:26 +020010633 /* export NAME (without =VALUE) */
10634 if (var) {
10635 var->flg_export = 1;
10636 debug_printf_env("%s: putenv '%s'\n", __func__, var->varstr);
10637 putenv(var->varstr);
10638 continue;
10639 }
10640 }
Denys Vlasenko38ef39a2017-07-18 01:40:01 +020010641 if (flags & SETFLAG_MAKE_RO) {
10642 /* readonly NAME (without =VALUE) */
10643 if (var) {
10644 var->flg_read_only = 1;
10645 continue;
10646 }
10647 }
Denys Vlasenko6ec76d82017-01-08 18:40:41 +010010648# if ENABLE_HUSH_LOCAL
Denys Vlasenkob95ee962017-07-17 21:19:53 +020010649 /* Is this "local" bltin? */
Denys Vlasenko3bab36b2017-07-18 01:05:24 +020010650 if (!(flags & (SETFLAG_EXPORT|SETFLAG_UNEXPORT|SETFLAG_MAKE_RO))) {
Denys Vlasenko332e4112018-04-04 22:32:59 +020010651 unsigned lvl = flags >> SETFLAG_VARLVL_SHIFT;
10652 if (var && var->var_nest_level == lvl) {
Denys Vlasenkob95ee962017-07-17 21:19:53 +020010653 /* "local x=abc; ...; local x" - ignore second local decl */
10654 continue;
10655 }
Denys Vlasenko61508d92016-10-02 21:12:02 +020010656 }
Denys Vlasenko6ec76d82017-01-08 18:40:41 +010010657# endif
Denys Vlasenko295fef82009-06-03 12:47:26 +020010658 /* Exporting non-existing variable.
10659 * bash does not put it in environment,
10660 * but remembers that it is exported,
10661 * and does put it in env when it is set later.
Denys Vlasenko1e660422017-07-17 21:10:50 +020010662 * We just set it to "" and export.
10663 */
Denys Vlasenko295fef82009-06-03 12:47:26 +020010664 /* Or, it's "local NAME" (without =VALUE).
Denys Vlasenko1e660422017-07-17 21:10:50 +020010665 * bash sets the value to "".
10666 */
10667 /* Or, it's "readonly NAME" (without =VALUE).
10668 * bash remembers NAME and disallows its creation
10669 * in the future.
10670 */
Denys Vlasenko295fef82009-06-03 12:47:26 +020010671 name = xasprintf("%s=", name);
10672 } else {
10673 /* (Un)exporting/making local NAME=VALUE */
10674 name = xstrdup(name);
10675 }
Denys Vlasenko21b7f1b2018-04-05 15:15:53 +020010676 debug_printf_env("%s: set_local_var('%s')\n", __func__, name);
Denys Vlasenko38ef39a2017-07-18 01:40:01 +020010677 if (set_local_var(name, flags))
10678 return EXIT_FAILURE;
Denys Vlasenko295fef82009-06-03 12:47:26 +020010679 } while (*++argv);
Denys Vlasenko1e660422017-07-17 21:10:50 +020010680 return EXIT_SUCCESS;
Denys Vlasenko295fef82009-06-03 12:47:26 +020010681}
Denys Vlasenko6ec76d82017-01-08 18:40:41 +010010682#endif
Denys Vlasenko295fef82009-06-03 12:47:26 +020010683
Denys Vlasenko6ec76d82017-01-08 18:40:41 +010010684#if ENABLE_HUSH_EXPORT
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +020010685static int FAST_FUNC builtin_export(char **argv)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010686{
Denis Vlasenkoad4bd052009-04-20 22:04:21 +000010687 unsigned opt_unexport;
10688
Denys Vlasenkodf5131c2009-06-07 16:04:17 +020010689#if ENABLE_HUSH_EXPORT_N
10690 /* "!": do not abort on errors */
10691 opt_unexport = getopt32(argv, "!n");
10692 if (opt_unexport == (uint32_t)-1)
10693 return EXIT_FAILURE;
10694 argv += optind;
10695#else
10696 opt_unexport = 0;
10697 argv++;
10698#endif
10699
10700 if (argv[0] == NULL) {
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010701 char **e = environ;
Denis Vlasenko0b677d82009-04-10 13:49:10 +000010702 if (e) {
10703 while (*e) {
10704#if 0
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010705 puts(*e++);
Denis Vlasenko0b677d82009-04-10 13:49:10 +000010706#else
10707 /* ash emits: export VAR='VAL'
10708 * bash: declare -x VAR="VAL"
10709 * we follow ash example */
10710 const char *s = *e++;
10711 const char *p = strchr(s, '=');
10712
10713 if (!p) /* wtf? take next variable */
10714 continue;
10715 /* export var= */
10716 printf("export %.*s", (int)(p - s) + 1, s);
Denis Vlasenko38e626d2009-04-18 12:58:19 +000010717 print_escaped(p + 1);
Denis Vlasenko0b677d82009-04-10 13:49:10 +000010718 putchar('\n');
10719#endif
10720 }
Denys Vlasenko8131eea2009-11-02 14:19:51 +010010721 /*fflush_all(); - done after each builtin anyway */
Denis Vlasenko0b677d82009-04-10 13:49:10 +000010722 }
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010723 return EXIT_SUCCESS;
10724 }
10725
Denys Vlasenko3bab36b2017-07-18 01:05:24 +020010726 return helper_export_local(argv, opt_unexport ? SETFLAG_UNEXPORT : SETFLAG_EXPORT);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010727}
Denys Vlasenko6ec76d82017-01-08 18:40:41 +010010728#endif
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010729
Denys Vlasenko295fef82009-06-03 12:47:26 +020010730#if ENABLE_HUSH_LOCAL
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +020010731static int FAST_FUNC builtin_local(char **argv)
Denys Vlasenko295fef82009-06-03 12:47:26 +020010732{
10733 if (G.func_nest_level == 0) {
10734 bb_error_msg("%s: not in a function", argv[0]);
10735 return EXIT_FAILURE; /* bash compat */
10736 }
Denys Vlasenko1e660422017-07-17 21:10:50 +020010737 argv++;
Denys Vlasenkod358b0b2018-04-05 00:51:55 +020010738 /* Since all builtins run in a nested variable level,
10739 * need to use level - 1 here. Or else the variable will be removed at once
10740 * after builtin returns.
10741 */
10742 return helper_export_local(argv, (G.var_nest_level - 1) << SETFLAG_VARLVL_SHIFT);
Denys Vlasenko295fef82009-06-03 12:47:26 +020010743}
10744#endif
10745
Denys Vlasenko1e660422017-07-17 21:10:50 +020010746#if ENABLE_HUSH_READONLY
10747static int FAST_FUNC builtin_readonly(char **argv)
10748{
Denys Vlasenko3bab36b2017-07-18 01:05:24 +020010749 argv++;
10750 if (*argv == NULL) {
Denys Vlasenko1e660422017-07-17 21:10:50 +020010751 /* bash: readonly [-p]: list all readonly VARs
10752 * (-p has no effect in bash)
10753 */
10754 struct variable *e;
10755 for (e = G.top_var; e; e = e->next) {
10756 if (e->flg_read_only) {
10757//TODO: quote value: readonly VAR='VAL'
10758 printf("readonly %s\n", e->varstr);
10759 }
10760 }
10761 return EXIT_SUCCESS;
10762 }
Denys Vlasenko3bab36b2017-07-18 01:05:24 +020010763 return helper_export_local(argv, SETFLAG_MAKE_RO);
Denys Vlasenko1e660422017-07-17 21:10:50 +020010764}
10765#endif
10766
Denys Vlasenko10d5ece2017-01-08 18:28:43 +010010767#if ENABLE_HUSH_UNSET
Denys Vlasenko61508d92016-10-02 21:12:02 +020010768/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#unset */
10769static int FAST_FUNC builtin_unset(char **argv)
10770{
10771 int ret;
10772 unsigned opts;
10773
10774 /* "!": do not abort on errors */
10775 /* "+": stop at 1st non-option */
10776 opts = getopt32(argv, "!+vf");
10777 if (opts == (unsigned)-1)
10778 return EXIT_FAILURE;
10779 if (opts == 3) {
10780 bb_error_msg("unset: -v and -f are exclusive");
10781 return EXIT_FAILURE;
10782 }
10783 argv += optind;
10784
10785 ret = EXIT_SUCCESS;
10786 while (*argv) {
10787 if (!(opts & 2)) { /* not -f */
10788 if (unset_local_var(*argv)) {
10789 /* unset <nonexistent_var> doesn't fail.
10790 * Error is when one tries to unset RO var.
10791 * Message was printed by unset_local_var. */
10792 ret = EXIT_FAILURE;
10793 }
10794 }
Denys Vlasenko10d5ece2017-01-08 18:28:43 +010010795# if ENABLE_HUSH_FUNCTIONS
Denys Vlasenko61508d92016-10-02 21:12:02 +020010796 else {
10797 unset_func(*argv);
10798 }
Denys Vlasenko10d5ece2017-01-08 18:28:43 +010010799# endif
Denys Vlasenko61508d92016-10-02 21:12:02 +020010800 argv++;
10801 }
10802 return ret;
10803}
Denys Vlasenko10d5ece2017-01-08 18:28:43 +010010804#endif
Denys Vlasenko61508d92016-10-02 21:12:02 +020010805
Denys Vlasenko10d5ece2017-01-08 18:28:43 +010010806#if ENABLE_HUSH_SET
Denys Vlasenko61508d92016-10-02 21:12:02 +020010807/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set
10808 * built-in 'set' handler
10809 * SUSv3 says:
10810 * set [-abCefhmnuvx] [-o option] [argument...]
10811 * set [+abCefhmnuvx] [+o option] [argument...]
10812 * set -- [argument...]
10813 * set -o
10814 * set +o
10815 * Implementations shall support the options in both their hyphen and
10816 * plus-sign forms. These options can also be specified as options to sh.
10817 * Examples:
10818 * Write out all variables and their values: set
10819 * Set $1, $2, and $3 and set "$#" to 3: set c a b
10820 * Turn on the -x and -v options: set -xv
10821 * Unset all positional parameters: set --
10822 * Set $1 to the value of x, even if it begins with '-' or '+': set -- "$x"
10823 * Set the positional parameters to the expansion of x, even if x expands
10824 * with a leading '-' or '+': set -- $x
10825 *
10826 * So far, we only support "set -- [argument...]" and some of the short names.
10827 */
10828static int FAST_FUNC builtin_set(char **argv)
10829{
10830 int n;
10831 char **pp, **g_argv;
10832 char *arg = *++argv;
10833
10834 if (arg == NULL) {
10835 struct variable *e;
10836 for (e = G.top_var; e; e = e->next)
10837 puts(e->varstr);
10838 return EXIT_SUCCESS;
10839 }
10840
10841 do {
10842 if (strcmp(arg, "--") == 0) {
10843 ++argv;
10844 goto set_argv;
10845 }
10846 if (arg[0] != '+' && arg[0] != '-')
10847 break;
10848 for (n = 1; arg[n]; ++n) {
10849 if (set_mode((arg[0] == '-'), arg[n], argv[1]))
10850 goto error;
10851 if (arg[n] == 'o' && argv[1])
10852 argv++;
10853 }
10854 } while ((arg = *++argv) != NULL);
10855 /* Now argv[0] is 1st argument */
10856
10857 if (arg == NULL)
10858 return EXIT_SUCCESS;
10859 set_argv:
10860
10861 /* NB: G.global_argv[0] ($0) is never freed/changed */
10862 g_argv = G.global_argv;
10863 if (G.global_args_malloced) {
10864 pp = g_argv;
10865 while (*++pp)
10866 free(*pp);
10867 g_argv[1] = NULL;
10868 } else {
10869 G.global_args_malloced = 1;
10870 pp = xzalloc(sizeof(pp[0]) * 2);
10871 pp[0] = g_argv[0]; /* retain $0 */
10872 g_argv = pp;
10873 }
10874 /* This realloc's G.global_argv */
10875 G.global_argv = pp = add_strings_to_strings(g_argv, argv, /*dup:*/ 1);
10876
Denys Vlasenkod4e4fdb2017-07-03 21:31:16 +020010877 G.global_argc = 1 + string_array_len(pp + 1);
Denys Vlasenko61508d92016-10-02 21:12:02 +020010878
10879 return EXIT_SUCCESS;
10880
10881 /* Nothing known, so abort */
10882 error:
Denys Vlasenko57000292018-01-12 14:41:45 +010010883 bb_error_msg("%s: %s: invalid option", "set", arg);
Denys Vlasenko61508d92016-10-02 21:12:02 +020010884 return EXIT_FAILURE;
10885}
Denys Vlasenko10d5ece2017-01-08 18:28:43 +010010886#endif
Denys Vlasenko61508d92016-10-02 21:12:02 +020010887
10888static int FAST_FUNC builtin_shift(char **argv)
10889{
10890 int n = 1;
10891 argv = skip_dash_dash(argv);
10892 if (argv[0]) {
Denys Vlasenkoe59591a2017-07-06 20:12:44 +020010893 n = bb_strtou(argv[0], NULL, 10);
10894 if (errno || n < 0) {
10895 /* shared string with ash.c */
10896 bb_error_msg("Illegal number: %s", argv[0]);
10897 /*
10898 * ash aborts in this case.
10899 * bash prints error message and set $? to 1.
10900 * Interestingly, for "shift 99999" bash does not
10901 * print error message, but does set $? to 1
10902 * (and does no shifting at all).
10903 */
10904 }
Denys Vlasenko61508d92016-10-02 21:12:02 +020010905 }
10906 if (n >= 0 && n < G.global_argc) {
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +010010907 if (G_global_args_malloced) {
Denys Vlasenko61508d92016-10-02 21:12:02 +020010908 int m = 1;
10909 while (m <= n)
10910 free(G.global_argv[m++]);
10911 }
10912 G.global_argc -= n;
10913 memmove(&G.global_argv[1], &G.global_argv[n+1],
10914 G.global_argc * sizeof(G.global_argv[0]));
10915 return EXIT_SUCCESS;
10916 }
10917 return EXIT_FAILURE;
10918}
10919
Denys Vlasenko74d40582017-08-11 01:32:46 +020010920#if ENABLE_HUSH_GETOPTS
10921static int FAST_FUNC builtin_getopts(char **argv)
10922{
Denys Vlasenko9a7d0a02017-08-11 02:37:48 +020010923/* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getopts.html
10924
Denys Vlasenko74d40582017-08-11 01:32:46 +020010925TODO:
Denys Vlasenko74d40582017-08-11 01:32:46 +020010926If a required argument is not found, and getopts is not silent,
10927a question mark (?) is placed in VAR, OPTARG is unset, and a
10928diagnostic message is printed. If getopts is silent, then a
10929colon (:) is placed in VAR and OPTARG is set to the option
10930character found.
10931
10932Test that VAR is a valid variable name?
Denys Vlasenko9a7d0a02017-08-11 02:37:48 +020010933
10934"Whenever the shell is invoked, OPTIND shall be initialized to 1"
Denys Vlasenko74d40582017-08-11 01:32:46 +020010935*/
10936 char cbuf[2];
10937 const char *cp, *optstring, *var;
Denys Vlasenko238ff982017-08-29 13:38:30 +020010938 int c, n, exitcode, my_opterr;
10939 unsigned count;
Denys Vlasenko74d40582017-08-11 01:32:46 +020010940
10941 optstring = *++argv;
10942 if (!optstring || !(var = *++argv)) {
10943 bb_error_msg("usage: getopts OPTSTRING VAR [ARGS]");
10944 return EXIT_FAILURE;
10945 }
10946
Denys Vlasenko238ff982017-08-29 13:38:30 +020010947 if (argv[1])
10948 argv[0] = G.global_argv[0]; /* for error messages in getopt() */
10949 else
10950 argv = G.global_argv;
10951 cbuf[1] = '\0';
10952
10953 my_opterr = 0;
Denys Vlasenko048491f2017-08-17 12:36:39 +020010954 if (optstring[0] != ':') {
Denys Vlasenko419db032017-08-11 17:21:14 +020010955 cp = get_local_var_value("OPTERR");
Denys Vlasenko048491f2017-08-17 12:36:39 +020010956 /* 0 if "OPTERR=0", 1 otherwise */
Denys Vlasenko238ff982017-08-29 13:38:30 +020010957 my_opterr = (!cp || NOT_LONE_CHAR(cp, '0'));
Denys Vlasenko419db032017-08-11 17:21:14 +020010958 }
Denys Vlasenko74d40582017-08-11 01:32:46 +020010959
10960 /* getopts stops on first non-option. Add "+" to force that */
10961 /*if (optstring[0] != '+')*/ {
10962 char *s = alloca(strlen(optstring) + 2);
10963 sprintf(s, "+%s", optstring);
10964 optstring = s;
10965 }
10966
Denys Vlasenko238ff982017-08-29 13:38:30 +020010967 /* Naively, now we should just
10968 * cp = get_local_var_value("OPTIND");
10969 * optind = cp ? atoi(cp) : 0;
10970 * optarg = NULL;
10971 * opterr = my_opterr;
10972 * c = getopt(string_array_len(argv), argv, optstring);
10973 * and be done? Not so fast...
10974 * Unlike normal getopt() usage in C programs, here
10975 * each successive call will (usually) have the same argv[] CONTENTS,
10976 * but not the ADDRESSES. Worse yet, it's possible that between
10977 * invocations of "getopts", there will be calls to shell builtins
10978 * which use getopt() internally. Example:
10979 * while getopts "abc" RES -a -bc -abc de; do
10980 * unset -ff func
10981 * done
10982 * This would not work correctly: getopt() call inside "unset"
10983 * modifies internal libc state which is tracking position in
10984 * multi-option strings ("-abc"). At best, it can skip options
10985 * or return the same option infinitely. With glibc implementation
10986 * of getopt(), it would use outright invalid pointers and return
10987 * garbage even _without_ "unset" mangling internal state.
10988 *
10989 * We resort to resetting getopt() state and calling it N times,
10990 * until we get Nth result (or failure).
10991 * (N == G.getopt_count is reset to 0 whenever OPTIND is [un]set).
10992 */
Denys Vlasenko60161812017-08-29 14:32:17 +020010993 GETOPT_RESET();
Denys Vlasenko238ff982017-08-29 13:38:30 +020010994 count = 0;
10995 n = string_array_len(argv);
10996 do {
10997 optarg = NULL;
10998 opterr = (count < G.getopt_count) ? 0 : my_opterr;
10999 c = getopt(n, argv, optstring);
11000 if (c < 0)
11001 break;
11002 count++;
11003 } while (count <= G.getopt_count);
11004
11005 /* Set OPTIND. Prevent resetting of the magic counter! */
11006 set_local_var_from_halves("OPTIND", utoa(optind));
11007 G.getopt_count = count; /* "next time, give me N+1'th result" */
Denys Vlasenko60161812017-08-29 14:32:17 +020011008 GETOPT_RESET(); /* just in case */
Denys Vlasenko419db032017-08-11 17:21:14 +020011009
11010 /* Set OPTARG */
11011 /* Always set or unset, never left as-is, even on exit/error:
11012 * "If no option was found, or if the option that was found
11013 * does not have an option-argument, OPTARG shall be unset."
11014 */
11015 cp = optarg;
11016 if (c == '?') {
11017 /* If ":optstring" and unknown option is seen,
11018 * it is stored to OPTARG.
11019 */
11020 if (optstring[1] == ':') {
11021 cbuf[0] = optopt;
11022 cp = cbuf;
11023 }
11024 }
11025 if (cp)
11026 set_local_var_from_halves("OPTARG", cp);
11027 else
11028 unset_local_var("OPTARG");
11029
11030 /* Convert -1 to "?" */
Denys Vlasenko74d40582017-08-11 01:32:46 +020011031 exitcode = EXIT_SUCCESS;
11032 if (c < 0) { /* -1: end of options */
11033 exitcode = EXIT_FAILURE;
11034 c = '?';
11035 }
Denys Vlasenko419db032017-08-11 17:21:14 +020011036
Denys Vlasenko238ff982017-08-29 13:38:30 +020011037 /* Set VAR */
Denys Vlasenko74d40582017-08-11 01:32:46 +020011038 cbuf[0] = c;
Denys Vlasenko74d40582017-08-11 01:32:46 +020011039 set_local_var_from_halves(var, cbuf);
Denys Vlasenko9a7d0a02017-08-11 02:37:48 +020011040
Denys Vlasenko74d40582017-08-11 01:32:46 +020011041 return exitcode;
11042}
11043#endif
11044
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010011045static int FAST_FUNC builtin_source(char **argv)
Denys Vlasenko61508d92016-10-02 21:12:02 +020011046{
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010011047 char *arg_path, *filename;
Denys Vlasenko41ef41b2018-07-24 16:54:41 +020011048 HFILE *input;
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010011049 save_arg_t sv;
11050 char *args_need_save;
11051#if ENABLE_HUSH_FUNCTIONS
11052 smallint sv_flg;
Denys Vlasenko7a85c602017-01-08 17:40:18 +010011053#endif
Denys Vlasenko61508d92016-10-02 21:12:02 +020011054
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010011055 argv = skip_dash_dash(argv);
11056 filename = argv[0];
11057 if (!filename) {
11058 /* bash says: "bash: .: filename argument required" */
11059 return 2; /* bash compat */
11060 }
11061 arg_path = NULL;
11062 if (!strchr(filename, '/')) {
11063 arg_path = find_in_path(filename);
11064 if (arg_path)
11065 filename = arg_path;
Denys Vlasenko54c21112018-01-27 20:46:45 +010011066 else if (!ENABLE_HUSH_BASH_SOURCE_CURDIR) {
Denys Vlasenkof7e0fea2018-01-27 19:05:59 +010011067 errno = ENOENT;
11068 bb_simple_perror_msg(filename);
11069 return EXIT_FAILURE;
11070 }
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010011071 }
Denys Vlasenko41ef41b2018-07-24 16:54:41 +020011072 input = hfopen(filename);
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010011073 free(arg_path);
11074 if (!input) {
Denys Vlasenko41ef41b2018-07-24 16:54:41 +020011075 bb_perror_msg("%s", filename);
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010011076 /* POSIX: non-interactive shell should abort here,
11077 * not merely fail. So far no one complained :)
11078 */
11079 return EXIT_FAILURE;
11080 }
11081
11082#if ENABLE_HUSH_FUNCTIONS
11083 sv_flg = G_flag_return_in_progress;
11084 /* "we are inside sourced file, ok to use return" */
11085 G_flag_return_in_progress = -1;
11086#endif
11087 args_need_save = argv[1]; /* used as a boolean variable */
11088 if (args_need_save)
11089 save_and_replace_G_args(&sv, argv);
11090
11091 /* "false; . ./empty_line; echo Zero:$?" should print 0 */
11092 G.last_exitcode = 0;
11093 parse_and_run_file(input);
Denys Vlasenko41ef41b2018-07-24 16:54:41 +020011094 hfclose(input);
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010011095
11096 if (args_need_save) /* can't use argv[1] instead: "shift" can mangle it */
11097 restore_G_args(&sv, argv);
11098#if ENABLE_HUSH_FUNCTIONS
11099 G_flag_return_in_progress = sv_flg;
11100#endif
11101
11102 return G.last_exitcode;
11103}
11104
Denys Vlasenko7a85c602017-01-08 17:40:18 +010011105#if ENABLE_HUSH_TRAP
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +020011106static int FAST_FUNC builtin_trap(char **argv)
Denis Vlasenko38e626d2009-04-18 12:58:19 +000011107{
Denis Vlasenko38e626d2009-04-18 12:58:19 +000011108 int sig;
11109 char *new_cmd;
11110
Denys Vlasenko7a85c602017-01-08 17:40:18 +010011111 if (!G_traps)
11112 G_traps = xzalloc(sizeof(G_traps[0]) * NSIG);
Denis Vlasenko38e626d2009-04-18 12:58:19 +000011113
11114 argv++;
11115 if (!*argv) {
Denis Vlasenko6008d8a2009-04-18 13:05:10 +000011116 int i;
Denis Vlasenko38e626d2009-04-18 12:58:19 +000011117 /* No args: print all trapped */
11118 for (i = 0; i < NSIG; ++i) {
Denys Vlasenko7a85c602017-01-08 17:40:18 +010011119 if (G_traps[i]) {
Denis Vlasenko38e626d2009-04-18 12:58:19 +000011120 printf("trap -- ");
Denys Vlasenko7a85c602017-01-08 17:40:18 +010011121 print_escaped(G_traps[i]);
Denys Vlasenkoe74aaf92009-09-27 02:05:45 +020011122 /* note: bash adds "SIG", but only if invoked
11123 * as "bash". If called as "sh", or if set -o posix,
11124 * then it prints short signal names.
11125 * We are printing short names: */
11126 printf(" %s\n", get_signame(i));
Denis Vlasenko38e626d2009-04-18 12:58:19 +000011127 }
11128 }
Denys Vlasenko8131eea2009-11-02 14:19:51 +010011129 /*fflush_all(); - done after each builtin anyway */
Denis Vlasenko38e626d2009-04-18 12:58:19 +000011130 return EXIT_SUCCESS;
11131 }
11132
11133 new_cmd = NULL;
Denis Vlasenko38e626d2009-04-18 12:58:19 +000011134 /* If first arg is a number: reset all specified signals */
11135 sig = bb_strtou(*argv, NULL, 10);
11136 if (errno == 0) {
11137 int ret;
11138 process_sig_list:
11139 ret = EXIT_SUCCESS;
11140 while (*argv) {
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +020011141 sighandler_t handler;
11142
Denis Vlasenko38e626d2009-04-18 12:58:19 +000011143 sig = get_signum(*argv++);
Denys Vlasenko86981e32017-07-25 20:06:17 +020011144 if (sig < 0) {
Denis Vlasenko38e626d2009-04-18 12:58:19 +000011145 ret = EXIT_FAILURE;
11146 /* Mimic bash message exactly */
Denys Vlasenko74562982017-07-06 18:40:45 +020011147 bb_error_msg("trap: %s: invalid signal specification", argv[-1]);
Denis Vlasenko38e626d2009-04-18 12:58:19 +000011148 continue;
11149 }
11150
Denys Vlasenko7a85c602017-01-08 17:40:18 +010011151 free(G_traps[sig]);
11152 G_traps[sig] = xstrdup(new_cmd);
Denis Vlasenko38e626d2009-04-18 12:58:19 +000011153
Denys Vlasenkoe89a2412010-01-12 15:19:31 +010011154 debug_printf("trap: setting SIG%s (%i) to '%s'\n",
Denys Vlasenko7a85c602017-01-08 17:40:18 +010011155 get_signame(sig), sig, G_traps[sig]);
Denis Vlasenko38e626d2009-04-18 12:58:19 +000011156
11157 /* There is no signal for 0 (EXIT) */
11158 if (sig == 0)
11159 continue;
11160
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +020011161 if (new_cmd)
11162 handler = (new_cmd[0] ? record_pending_signo : SIG_IGN);
11163 else
11164 /* We are removing trap handler */
11165 handler = pick_sighandler(sig);
Denys Vlasenko0806e402011-05-12 23:06:20 +020011166 install_sighandler(sig, handler);
Denis Vlasenko38e626d2009-04-18 12:58:19 +000011167 }
11168 return ret;
11169 }
11170
11171 if (!argv[1]) { /* no second arg */
11172 bb_error_msg("trap: invalid arguments");
11173 return EXIT_FAILURE;
11174 }
11175
11176 /* First arg is "-": reset all specified to default */
11177 /* First arg is "--": skip it, the rest is "handler SIGs..." */
11178 /* Everything else: set arg as signal handler
11179 * (includes "" case, which ignores signal) */
11180 if (argv[0][0] == '-') {
11181 if (argv[0][1] == '\0') { /* "-" */
11182 /* new_cmd remains NULL: "reset these sigs" */
11183 goto reset_traps;
11184 }
11185 if (argv[0][1] == '-' && argv[0][2] == '\0') { /* "--" */
11186 argv++;
11187 }
11188 /* else: "-something", no special meaning */
11189 }
11190 new_cmd = *argv;
11191 reset_traps:
11192 argv++;
11193 goto process_sig_list;
11194}
Denys Vlasenko7a85c602017-01-08 17:40:18 +010011195#endif
Denis Vlasenko38e626d2009-04-18 12:58:19 +000011196
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000011197#if ENABLE_HUSH_JOB
Denys Vlasenko4e1c8b42016-11-07 20:06:40 +010011198static struct pipe *parse_jobspec(const char *str)
11199{
11200 struct pipe *pi;
Denys Vlasenkod5b5c2f2017-01-08 15:46:04 +010011201 unsigned jobnum;
Denys Vlasenko4e1c8b42016-11-07 20:06:40 +010011202
Denys Vlasenkod5b5c2f2017-01-08 15:46:04 +010011203 if (sscanf(str, "%%%u", &jobnum) != 1) {
11204 if (str[0] != '%'
11205 || (str[1] != '%' && str[1] != '+' && str[1] != '\0')
11206 ) {
11207 bb_error_msg("bad argument '%s'", str);
11208 return NULL;
11209 }
11210 /* It is "%%", "%+" or "%" - current job */
11211 jobnum = G.last_jobid;
11212 if (jobnum == 0) {
11213 bb_error_msg("no current job");
11214 return NULL;
11215 }
Denys Vlasenko4e1c8b42016-11-07 20:06:40 +010011216 }
11217 for (pi = G.job_list; pi; pi = pi->next) {
11218 if (pi->jobid == jobnum) {
11219 return pi;
11220 }
11221 }
Denys Vlasenkofd68f1e2017-01-09 05:47:57 +010011222 bb_error_msg("%u: no such job", jobnum);
Denys Vlasenko4e1c8b42016-11-07 20:06:40 +010011223 return NULL;
11224}
11225
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010011226static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM)
11227{
11228 struct pipe *job;
11229 const char *status_string;
11230
11231 checkjobs(NULL, 0 /*(no pid to wait for)*/);
11232 for (job = G.job_list; job; job = job->next) {
11233 if (job->alive_cmds == job->stopped_cmds)
11234 status_string = "Stopped";
11235 else
11236 status_string = "Running";
11237
11238 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->cmdtext);
11239 }
Denys Vlasenko2ed74e22017-07-14 19:58:46 +020011240
11241 clean_up_last_dead_job();
11242
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010011243 return EXIT_SUCCESS;
11244}
11245
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000011246/* built-in 'fg' and 'bg' handler */
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +020011247static int FAST_FUNC builtin_fg_bg(char **argv)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000011248{
Denys Vlasenko4e1c8b42016-11-07 20:06:40 +010011249 int i;
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000011250 struct pipe *pi;
11251
Denis Vlasenko60b392f2009-04-03 19:14:32 +000011252 if (!G_interactive_fd)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000011253 return EXIT_FAILURE;
Denis Vlasenkoc8653f62009-04-27 23:29:14 +000011254
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000011255 /* If they gave us no args, assume they want the last backgrounded task */
11256 if (!argv[1]) {
Denis Vlasenko87a86552008-07-29 19:43:10 +000011257 for (pi = G.job_list; pi; pi = pi->next) {
11258 if (pi->jobid == G.last_jobid) {
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000011259 goto found;
11260 }
11261 }
11262 bb_error_msg("%s: no current job", argv[0]);
11263 return EXIT_FAILURE;
11264 }
Denys Vlasenko4e1c8b42016-11-07 20:06:40 +010011265
11266 pi = parse_jobspec(argv[1]);
11267 if (!pi)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000011268 return EXIT_FAILURE;
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000011269 found:
Denis Vlasenko6b9e0532009-04-18 01:23:21 +000011270 /* TODO: bash prints a string representation
11271 * of job being foregrounded (like "sleep 1 | cat") */
Mike Frysinger38478a62009-05-20 04:48:06 -040011272 if (argv[0][0] == 'f' && G_saved_tty_pgrp) {
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000011273 /* Put the job into the foreground. */
Denis Vlasenko60b392f2009-04-03 19:14:32 +000011274 tcsetpgrp(G_interactive_fd, pi->pgrp);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000011275 }
11276
11277 /* Restart the processes in the job */
Denis Vlasenko9af22c72008-10-09 12:54:58 +000011278 debug_printf_jobs("reviving %d procs, pgrp %d\n", pi->num_cmds, pi->pgrp);
11279 for (i = 0; i < pi->num_cmds; i++) {
11280 debug_printf_jobs("reviving pid %d\n", pi->cmds[i].pid);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000011281 }
Denis Vlasenko9af22c72008-10-09 12:54:58 +000011282 pi->stopped_cmds = 0;
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000011283
11284 i = kill(- pi->pgrp, SIGCONT);
11285 if (i < 0) {
11286 if (errno == ESRCH) {
Denys Vlasenko16096292017-07-10 10:00:28 +020011287 delete_finished_job(pi);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000011288 return EXIT_SUCCESS;
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000011289 }
Denis Vlasenko34d4d892009-04-04 20:24:37 +000011290 bb_perror_msg("kill (SIGCONT)");
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000011291 }
11292
Denis Vlasenko34d4d892009-04-04 20:24:37 +000011293 if (argv[0][0] == 'f') {
Denys Vlasenko16096292017-07-10 10:00:28 +020011294 remove_job_from_table(pi); /* FG job shouldn't be in job table */
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000011295 return checkjobs_and_fg_shell(pi);
11296 }
11297 return EXIT_SUCCESS;
11298}
11299#endif
11300
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010011301#if ENABLE_HUSH_KILL
11302static int FAST_FUNC builtin_kill(char **argv)
11303{
11304 int ret = 0;
11305
Denys Vlasenkofd68f1e2017-01-09 05:47:57 +010011306# if ENABLE_HUSH_JOB
11307 if (argv[1] && strcmp(argv[1], "-l") != 0) {
11308 int i = 1;
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010011309
11310 do {
11311 struct pipe *pi;
11312 char *dst;
11313 int j, n;
11314
11315 if (argv[i][0] != '%')
11316 continue;
11317 /*
11318 * "kill %N" - job kill
11319 * Converting to pgrp / pid kill
11320 */
11321 pi = parse_jobspec(argv[i]);
11322 if (!pi) {
11323 /* Eat bad jobspec */
11324 j = i;
11325 do {
11326 j++;
11327 argv[j - 1] = argv[j];
11328 } while (argv[j]);
11329 ret = 1;
11330 i--;
11331 continue;
11332 }
11333 /*
11334 * In jobs started under job control, we signal
11335 * entire process group by kill -PGRP_ID.
11336 * This happens, f.e., in interactive shell.
11337 *
11338 * Otherwise, we signal each child via
11339 * kill PID1 PID2 PID3.
11340 * Testcases:
11341 * sh -c 'sleep 1|sleep 1 & kill %1'
11342 * sh -c 'true|sleep 2 & sleep 1; kill %1'
11343 * sh -c 'true|sleep 1 & sleep 2; kill %1'
11344 */
Denys Vlasenko5362cc42017-01-09 05:57:13 +010011345 n = G_interactive_fd ? 1 : pi->num_cmds;
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010011346 dst = alloca(n * sizeof(int)*4);
11347 argv[i] = dst;
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010011348 if (G_interactive_fd)
11349 dst += sprintf(dst, " -%u", (int)pi->pgrp);
Denys Vlasenkofd68f1e2017-01-09 05:47:57 +010011350 else for (j = 0; j < n; j++) {
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010011351 struct command *cmd = &pi->cmds[j];
11352 /* Skip exited members of the job */
11353 if (cmd->pid == 0)
11354 continue;
11355 /*
11356 * kill_main has matching code to expect
11357 * leading space. Needed to not confuse
11358 * negative pids with "kill -SIGNAL_NO" syntax
11359 */
11360 dst += sprintf(dst, " %u", (int)cmd->pid);
11361 }
11362 *dst = '\0';
11363 } while (argv[++i]);
11364 }
Denys Vlasenkofd68f1e2017-01-09 05:47:57 +010011365# endif
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010011366
Denys Vlasenkofd68f1e2017-01-09 05:47:57 +010011367 if (argv[1] || ret == 0) {
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010011368 ret = run_applet_main(argv, kill_main);
11369 }
Denys Vlasenkofd68f1e2017-01-09 05:47:57 +010011370 /* else: ret = 1, "kill %bad_jobspec" case */
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010011371 return ret;
11372}
11373#endif
11374
11375#if ENABLE_HUSH_WAIT
Mike Frysinger56bdea12009-03-28 20:01:58 +000011376/* http://www.opengroup.org/onlinepubs/9699919799/utilities/wait.html */
Denys Vlasenko62b717b2016-11-07 22:12:18 +010011377#if !ENABLE_HUSH_JOB
11378# define wait_for_child_or_signal(pipe,pid) wait_for_child_or_signal(pid)
11379#endif
11380static int wait_for_child_or_signal(struct pipe *waitfor_pipe, pid_t waitfor_pid)
Denys Vlasenko7e675362016-10-28 21:57:31 +020011381{
11382 int ret = 0;
11383 for (;;) {
11384 int sig;
Denys Vlasenko62b717b2016-11-07 22:12:18 +010011385 sigset_t oldset;
Denys Vlasenko7e675362016-10-28 21:57:31 +020011386
Denys Vlasenko830ea352016-11-08 04:59:11 +010011387 if (!sigisemptyset(&G.pending_set))
11388 goto check_sig;
11389
Denys Vlasenko7e675362016-10-28 21:57:31 +020011390 /* waitpid is not interruptible by SA_RESTARTed
11391 * signals which we use. Thus, this ugly dance:
11392 */
11393
11394 /* Make sure possible SIGCHLD is stored in kernel's
11395 * pending signal mask before we call waitpid.
11396 * Or else we may race with SIGCHLD, lose it,
Denys Vlasenko62b717b2016-11-07 22:12:18 +010011397 * and get stuck in sigsuspend...
Denys Vlasenko7e675362016-10-28 21:57:31 +020011398 */
Denys Vlasenko62b717b2016-11-07 22:12:18 +010011399 sigfillset(&oldset); /* block all signals, remember old set */
11400 sigprocmask(SIG_SETMASK, &oldset, &oldset);
Denys Vlasenko7e675362016-10-28 21:57:31 +020011401
11402 if (!sigisemptyset(&G.pending_set)) {
11403 /* Crap! we raced with some signal! */
Denys Vlasenko7e675362016-10-28 21:57:31 +020011404 goto restore;
11405 }
11406
11407 /*errno = 0; - checkjobs does this */
Denys Vlasenko62b717b2016-11-07 22:12:18 +010011408/* Can't pass waitfor_pipe into checkjobs(): it won't be interruptible */
Denys Vlasenko7e675362016-10-28 21:57:31 +020011409 ret = checkjobs(NULL, waitfor_pid); /* waitpid(WNOHANG) inside */
Denys Vlasenko62b717b2016-11-07 22:12:18 +010011410 debug_printf_exec("checkjobs:%d\n", ret);
11411#if ENABLE_HUSH_JOB
11412 if (waitfor_pipe) {
11413 int rcode = job_exited_or_stopped(waitfor_pipe);
11414 debug_printf_exec("job_exited_or_stopped:%d\n", rcode);
11415 if (rcode >= 0) {
11416 ret = rcode;
11417 sigprocmask(SIG_SETMASK, &oldset, NULL);
11418 break;
11419 }
11420 }
11421#endif
Denys Vlasenko7e675362016-10-28 21:57:31 +020011422 /* if ECHILD, there are no children (ret is -1 or 0) */
11423 /* if ret == 0, no children changed state */
11424 /* if ret != 0, it's exitcode+1 of exited waitfor_pid child */
Denys Vlasenko62b717b2016-11-07 22:12:18 +010011425 if (errno == ECHILD || ret) {
11426 ret--;
11427 if (ret < 0) /* if ECHILD, may need to fix "ret" */
Denys Vlasenko7e675362016-10-28 21:57:31 +020011428 ret = 0;
11429 sigprocmask(SIG_SETMASK, &oldset, NULL);
11430 break;
11431 }
Denys Vlasenko7e675362016-10-28 21:57:31 +020011432 /* Wait for SIGCHLD or any other signal */
Denys Vlasenko7e675362016-10-28 21:57:31 +020011433 /* It is vitally important for sigsuspend that SIGCHLD has non-DFL handler! */
11434 /* Note: sigsuspend invokes signal handler */
11435 sigsuspend(&oldset);
11436 restore:
11437 sigprocmask(SIG_SETMASK, &oldset, NULL);
Denys Vlasenko830ea352016-11-08 04:59:11 +010011438 check_sig:
Denys Vlasenko7e675362016-10-28 21:57:31 +020011439 /* So, did we get a signal? */
Denys Vlasenko7e675362016-10-28 21:57:31 +020011440 sig = check_and_run_traps();
11441 if (sig /*&& sig != SIGCHLD - always true */) {
Denys Vlasenko7c40ddd2017-08-02 16:37:39 +020011442 /* Do this for any (non-ignored) signal, not only for ^C */
Denys Vlasenko7e675362016-10-28 21:57:31 +020011443 ret = 128 + sig;
11444 break;
11445 }
11446 /* SIGCHLD, or no signal, or ignored one, such as SIGQUIT. Repeat */
11447 }
11448 return ret;
11449}
11450
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +020011451static int FAST_FUNC builtin_wait(char **argv)
Mike Frysinger56bdea12009-03-28 20:01:58 +000011452{
Denys Vlasenko7e675362016-10-28 21:57:31 +020011453 int ret;
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +020011454 int status;
Mike Frysinger56bdea12009-03-28 20:01:58 +000011455
Denys Vlasenkob131cce2010-05-20 03:39:43 +020011456 argv = skip_dash_dash(argv);
11457 if (argv[0] == NULL) {
Denis Vlasenko7566bae2009-03-31 17:24:49 +000011458 /* Don't care about wait results */
11459 /* Note 1: must wait until there are no more children */
11460 /* Note 2: must be interruptible */
11461 /* Examples:
11462 * $ sleep 3 & sleep 6 & wait
11463 * [1] 30934 sleep 3
11464 * [2] 30935 sleep 6
11465 * [1] Done sleep 3
11466 * [2] Done sleep 6
11467 * $ sleep 3 & sleep 6 & wait
11468 * [1] 30936 sleep 3
11469 * [2] 30937 sleep 6
11470 * [1] Done sleep 3
11471 * ^C <-- after ~4 sec from keyboard
11472 * $
11473 */
Denys Vlasenko62b717b2016-11-07 22:12:18 +010011474 return wait_for_child_or_signal(NULL, 0 /*(no job and no pid to wait for)*/);
Denis Vlasenko7566bae2009-03-31 17:24:49 +000011475 }
Mike Frysinger56bdea12009-03-28 20:01:58 +000011476
Denys Vlasenko7e675362016-10-28 21:57:31 +020011477 do {
Denis Vlasenkod5762932009-03-31 11:22:57 +000011478 pid_t pid = bb_strtou(*argv, NULL, 10);
Denys Vlasenko7e675362016-10-28 21:57:31 +020011479 if (errno || pid <= 0) {
Denys Vlasenko62b717b2016-11-07 22:12:18 +010011480#if ENABLE_HUSH_JOB
11481 if (argv[0][0] == '%') {
Denys Vlasenko02affb42016-11-08 00:59:29 +010011482 struct pipe *wait_pipe;
Denys Vlasenkod5b5c2f2017-01-08 15:46:04 +010011483 ret = 127; /* bash compat for bad jobspecs */
Denys Vlasenko62b717b2016-11-07 22:12:18 +010011484 wait_pipe = parse_jobspec(*argv);
11485 if (wait_pipe) {
Denys Vlasenko02affb42016-11-08 00:59:29 +010011486 ret = job_exited_or_stopped(wait_pipe);
Denys Vlasenko2ed74e22017-07-14 19:58:46 +020011487 if (ret < 0) {
Denys Vlasenko02affb42016-11-08 00:59:29 +010011488 ret = wait_for_child_or_signal(wait_pipe, 0);
Denys Vlasenko2ed74e22017-07-14 19:58:46 +020011489 } else {
11490 /* waiting on "last dead job" removes it */
11491 clean_up_last_dead_job();
Denys Vlasenko13102632017-07-08 00:24:32 +020011492 }
Denys Vlasenko62b717b2016-11-07 22:12:18 +010011493 }
Denys Vlasenkod5b5c2f2017-01-08 15:46:04 +010011494 /* else: parse_jobspec() already emitted error msg */
11495 continue;
Denys Vlasenko62b717b2016-11-07 22:12:18 +010011496 }
11497#endif
Denis Vlasenkod5762932009-03-31 11:22:57 +000011498 /* mimic bash message */
11499 bb_error_msg("wait: '%s': not a pid or valid job spec", *argv);
Denys Vlasenko9db74e42016-10-28 22:39:12 +020011500 ret = EXIT_FAILURE;
11501 continue; /* bash checks all argv[] */
Denis Vlasenkod5762932009-03-31 11:22:57 +000011502 }
Denys Vlasenko02affb42016-11-08 00:59:29 +010011503
Denys Vlasenko7e675362016-10-28 21:57:31 +020011504 /* Do we have such child? */
11505 ret = waitpid(pid, &status, WNOHANG);
11506 if (ret < 0) {
11507 /* No */
Denys Vlasenko840a4352017-07-07 22:56:02 +020011508 ret = 127;
Denys Vlasenko7e675362016-10-28 21:57:31 +020011509 if (errno == ECHILD) {
Denys Vlasenko0c5657e2017-07-14 19:27:03 +020011510 if (pid == G.last_bg_pid) {
Denys Vlasenko9db74e42016-10-28 22:39:12 +020011511 /* "wait $!" but last bg task has already exited. Try:
11512 * (sleep 1; exit 3) & sleep 2; echo $?; wait $!; echo $?
11513 * In bash it prints exitcode 0, then 3.
Denys Vlasenko26ad94b2016-11-07 23:07:21 +010011514 * In dash, it is 127.
Denys Vlasenko9db74e42016-10-28 22:39:12 +020011515 */
Denys Vlasenko840a4352017-07-07 22:56:02 +020011516 ret = G.last_bg_pid_exitcode;
Denys Vlasenko26ad94b2016-11-07 23:07:21 +010011517 } else {
11518 /* Example: "wait 1". mimic bash message */
11519 bb_error_msg("wait: pid %d is not a child of this shell", (int)pid);
Denys Vlasenko9db74e42016-10-28 22:39:12 +020011520 }
Denys Vlasenko7e675362016-10-28 21:57:31 +020011521 } else {
11522 /* ??? */
11523 bb_perror_msg("wait %s", *argv);
11524 }
Denys Vlasenko9db74e42016-10-28 22:39:12 +020011525 continue; /* bash checks all argv[] */
11526 }
11527 if (ret == 0) {
Denys Vlasenko7e675362016-10-28 21:57:31 +020011528 /* Yes, and it still runs */
Denys Vlasenko02affb42016-11-08 00:59:29 +010011529 ret = wait_for_child_or_signal(NULL, pid);
Denys Vlasenko7e675362016-10-28 21:57:31 +020011530 } else {
11531 /* Yes, and it just exited */
Denys Vlasenko02affb42016-11-08 00:59:29 +010011532 process_wait_result(NULL, pid, status);
Denys Vlasenko85378cd2015-10-11 21:47:11 +020011533 ret = WEXITSTATUS(status);
Mike Frysinger56bdea12009-03-28 20:01:58 +000011534 if (WIFSIGNALED(status))
11535 ret = 128 + WTERMSIG(status);
Mike Frysinger56bdea12009-03-28 20:01:58 +000011536 }
Denys Vlasenko9db74e42016-10-28 22:39:12 +020011537 } while (*++argv);
Mike Frysinger56bdea12009-03-28 20:01:58 +000011538
11539 return ret;
11540}
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010011541#endif
Mike Frysinger56bdea12009-03-28 20:01:58 +000011542
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +000011543#if ENABLE_HUSH_LOOPS || ENABLE_HUSH_FUNCTIONS
11544static unsigned parse_numeric_argv1(char **argv, unsigned def, unsigned def_min)
11545{
11546 if (argv[1]) {
11547 def = bb_strtou(argv[1], NULL, 10);
11548 if (errno || def < def_min || argv[2]) {
11549 bb_error_msg("%s: bad arguments", argv[0]);
11550 def = UINT_MAX;
11551 }
11552 }
11553 return def;
11554}
11555#endif
11556
Denis Vlasenkodadfb492008-07-29 10:16:05 +000011557#if ENABLE_HUSH_LOOPS
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +020011558static int FAST_FUNC builtin_break(char **argv)
Denis Vlasenkobcb25532008-07-28 23:04:34 +000011559{
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +000011560 unsigned depth;
Denis Vlasenko87a86552008-07-29 19:43:10 +000011561 if (G.depth_of_loop == 0) {
Denis Vlasenko4f504a92008-07-29 19:48:30 +000011562 bb_error_msg("%s: only meaningful in a loop", argv[0]);
Denys Vlasenko49117b42016-07-21 14:40:08 +020011563 /* if we came from builtin_continue(), need to undo "= 1" */
11564 G.flag_break_continue = 0;
Denis Vlasenkofcf37c32008-07-29 11:37:15 +000011565 return EXIT_SUCCESS; /* bash compat */
11566 }
Denys Vlasenko49117b42016-07-21 14:40:08 +020011567 G.flag_break_continue++; /* BC_BREAK = 1, or BC_CONTINUE = 2 */
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +000011568
11569 G.depth_break_continue = depth = parse_numeric_argv1(argv, 1, 1);
11570 if (depth == UINT_MAX)
11571 G.flag_break_continue = BC_BREAK;
11572 if (G.depth_of_loop < depth)
Denis Vlasenko87a86552008-07-29 19:43:10 +000011573 G.depth_break_continue = G.depth_of_loop;
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +000011574
Denis Vlasenkobcb25532008-07-28 23:04:34 +000011575 return EXIT_SUCCESS;
11576}
11577
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +020011578static int FAST_FUNC builtin_continue(char **argv)
Denis Vlasenkobcb25532008-07-28 23:04:34 +000011579{
Denis Vlasenko4f504a92008-07-29 19:48:30 +000011580 G.flag_break_continue = 1; /* BC_CONTINUE = 2 = 1+1 */
11581 return builtin_break(argv);
Denis Vlasenkobcb25532008-07-28 23:04:34 +000011582}
Denis Vlasenkodadfb492008-07-29 10:16:05 +000011583#endif
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +000011584
11585#if ENABLE_HUSH_FUNCTIONS
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +020011586static int FAST_FUNC builtin_return(char **argv)
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +000011587{
11588 int rc;
11589
Denys Vlasenko04b46bc2016-10-01 22:28:03 +020011590 if (G_flag_return_in_progress != -1) {
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +000011591 bb_error_msg("%s: not in a function or sourced script", argv[0]);
11592 return EXIT_FAILURE; /* bash compat */
11593 }
11594
Denys Vlasenko04b46bc2016-10-01 22:28:03 +020011595 G_flag_return_in_progress = 1;
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +000011596
11597 /* bash:
11598 * out of range: wraps around at 256, does not error out
11599 * non-numeric param:
11600 * f() { false; return qwe; }; f; echo $?
11601 * bash: return: qwe: numeric argument required <== we do this
11602 * 255 <== we also do this
11603 */
11604 rc = parse_numeric_argv1(argv, G.last_exitcode, 0);
11605 return rc;
11606}
11607#endif
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010011608
Denys Vlasenko11f2e992017-08-10 16:34:03 +020011609#if ENABLE_HUSH_TIMES
11610static int FAST_FUNC builtin_times(char **argv UNUSED_PARAM)
11611{
11612 static const uint8_t times_tbl[] ALIGN1 = {
11613 ' ', offsetof(struct tms, tms_utime),
11614 '\n', offsetof(struct tms, tms_stime),
11615 ' ', offsetof(struct tms, tms_cutime),
11616 '\n', offsetof(struct tms, tms_cstime),
11617 0
11618 };
11619 const uint8_t *p;
11620 unsigned clk_tck;
11621 struct tms buf;
11622
11623 clk_tck = bb_clk_tck();
11624
11625 times(&buf);
11626 p = times_tbl;
11627 do {
11628 unsigned sec, frac;
11629 unsigned long t;
11630 t = *(clock_t *)(((char *) &buf) + p[1]);
11631 sec = t / clk_tck;
11632 frac = t % clk_tck;
11633 printf("%um%u.%03us%c",
11634 sec / 60, sec % 60,
11635 (frac * 1000) / clk_tck,
11636 p[0]);
11637 p += 2;
11638 } while (*p);
11639
11640 return EXIT_SUCCESS;
11641}
11642#endif
11643
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010011644#if ENABLE_HUSH_MEMLEAK
11645static int FAST_FUNC builtin_memleak(char **argv UNUSED_PARAM)
11646{
11647 void *p;
11648 unsigned long l;
11649
11650# ifdef M_TRIM_THRESHOLD
11651 /* Optional. Reduces probability of false positives */
11652 malloc_trim(0);
11653# endif
11654 /* Crude attempt to find where "free memory" starts,
11655 * sans fragmentation. */
11656 p = malloc(240);
11657 l = (unsigned long)p;
11658 free(p);
11659 p = malloc(3400);
11660 if (l < (unsigned long)p) l = (unsigned long)p;
11661 free(p);
11662
11663
11664# if 0 /* debug */
11665 {
11666 struct mallinfo mi = mallinfo();
11667 printf("top alloc:0x%lx malloced:%d+%d=%d\n", l,
11668 mi.arena, mi.hblkhd, mi.arena + mi.hblkhd);
11669 }
11670# endif
11671
11672 if (!G.memleak_value)
11673 G.memleak_value = l;
11674
11675 l -= G.memleak_value;
11676 if ((long)l < 0)
11677 l = 0;
11678 l /= 1024;
11679 if (l > 127)
11680 l = 127;
11681
11682 /* Exitcode is "how many kilobytes we leaked since 1st call" */
11683 return l;
11684}
11685#endif