blob: f9a8de423ba8daa6b23837ed0e6ee8432e5d880c [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
50 * builtins mandated by standards we don't support:
Denys Vlasenko74d40582017-08-11 01:32:46 +020051 * [un]alias, command, fc:
Denys Vlasenko203fd7b2017-07-17 16:13:35 +020052 * command -v CMD: print "/path/to/CMD"
53 * prints "CMD" for builtins
54 * prints "alias ALIAS='EXPANSION'" for aliases
55 * prints nothing and sets $? to 1 if not found
56 * command -V CMD: print "CMD is /path/CMD|a shell builtin|etc"
57 * command [-p] CMD: run CMD, even if a function CMD also exists
58 * (can use this to override standalone shell as well)
59 * -p: use default $PATH
Denys Vlasenko1e660422017-07-17 21:10:50 +020060 * command BLTIN: disables special-ness (e.g. errors do not abort)
Denys Vlasenko203fd7b2017-07-17 16:13:35 +020061 * fc -l[nr] [BEG] [END]: list range of commands in history
62 * fc [-e EDITOR] [BEG] [END]: edit/rerun range of commands
63 * fc -s [PAT=REP] [CMD]: rerun CMD, replacing PAT with REP
Mike Frysinger25a6ca02009-03-28 13:59:26 +000064 *
Denys Vlasenkoadc0e202010-05-17 18:56:58 +020065 * Bash compat TODO:
66 * redirection of stdout+stderr: &> and >&
Denys Vlasenkoadc0e202010-05-17 18:56:58 +020067 * reserved words: function select
68 * advanced test: [[ ]]
Denys Vlasenkoadc0e202010-05-17 18:56:58 +020069 * process substitution: <(list) and >(list)
70 * =~: regex operator
Denys Vlasenko9ca656b2009-06-10 13:39:35 +020071 * let EXPR [EXPR...]
Denys Vlasenko349ef962010-05-21 15:46:24 +020072 * Each EXPR is an arithmetic expression (ARITHMETIC EVALUATION)
73 * If the last arg evaluates to 0, let returns 1; 0 otherwise.
74 * NB: let `echo 'a=a + 1'` - error (IOW: multi-word expansion is used)
Denys Vlasenko9ca656b2009-06-10 13:39:35 +020075 * ((EXPR))
Denys Vlasenko349ef962010-05-21 15:46:24 +020076 * The EXPR is evaluated according to ARITHMETIC EVALUATION.
77 * This is exactly equivalent to let "EXPR".
Denys Vlasenkoadc0e202010-05-17 18:56:58 +020078 * $[EXPR]: synonym for $((EXPR))
Denys Vlasenko203fd7b2017-07-17 16:13:35 +020079 * indirect expansion: ${!VAR}
80 * substring op on @: ${@:n:m}
Denys Vlasenkobbecd742010-10-03 17:22:52 +020081 *
82 * Won't do:
Denys Vlasenko203fd7b2017-07-17 16:13:35 +020083 * Some builtins mandated by standards:
84 * newgrp [GRP]: not a builtin in bash but a suid binary
85 * which spawns a new shell with new group ID
Denys Vlasenkobbecd742010-10-03 17:22:52 +020086 * In bash, export builtin is special, its arguments are assignments
Denys Vlasenko08218012009-06-03 14:43:56 +020087 * and therefore expansion of them should be "one-word" expansion:
88 * $ export i=`echo 'a b'` # export has one arg: "i=a b"
89 * compare with:
90 * $ ls i=`echo 'a b'` # ls has two args: "i=a" and "b"
91 * ls: cannot access i=a: No such file or directory
92 * ls: cannot access b: No such file or directory
Denys Vlasenko9ca656b2009-06-10 13:39:35 +020093 * Note1: same applies to local builtin.
Denys Vlasenko08218012009-06-03 14:43:56 +020094 * Note2: bash 3.2.33(1) does this only if export word itself
95 * is not quoted:
96 * $ export i=`echo 'aaa bbb'`; echo "$i"
97 * aaa bbb
98 * $ "export" i=`echo 'aaa bbb'`; echo "$i"
99 * aaa
Eric Andersen25f27032001-04-26 23:22:31 +0000100 */
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200101//config:config HUSH
Denys Vlasenko4eed2c62017-07-18 22:01:24 +0200102//config: bool "hush (64 kb)"
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200103//config: default y
104//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200105//config: hush is a small shell. It handles the normal flow control
106//config: constructs such as if/then/elif/else/fi, for/in/do/done, while loops,
107//config: case/esac. Redirections, here documents, $((arithmetic))
108//config: and functions are supported.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200109//config:
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200110//config: It will compile and work on no-mmu systems.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200111//config:
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200112//config: It does not handle select, aliases, tilde expansion,
113//config: &>file and >&file redirection of stdout+stderr.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200114//config:
115//config:config HUSH_BASH_COMPAT
116//config: bool "bash-compatible extensions"
117//config: default y
Denys Vlasenko0b883582016-12-23 16:49:07 +0100118//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200119//config:
Denys Vlasenko9e800222010-10-03 14:28:04 +0200120//config:config HUSH_BRACE_EXPANSION
121//config: bool "Brace expansion"
122//config: default y
123//config: depends on HUSH_BASH_COMPAT
124//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200125//config: Enable {abc,def} extension.
Denys Vlasenko9e800222010-10-03 14:28:04 +0200126//config:
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200127//config:config HUSH_INTERACTIVE
128//config: bool "Interactive mode"
129//config: default y
Denys Vlasenko0b883582016-12-23 16:49:07 +0100130//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200131//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200132//config: Enable interactive mode (prompt and command editing).
133//config: Without this, hush simply reads and executes commands
134//config: from stdin just like a shell script from a file.
135//config: No prompt, no PS1/PS2 magic shell variables.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200136//config:
Denys Vlasenko99862cb2010-09-12 17:34:13 +0200137//config:config HUSH_SAVEHISTORY
138//config: bool "Save command history to .hush_history"
139//config: default y
140//config: depends on HUSH_INTERACTIVE && FEATURE_EDITING_SAVEHISTORY
Denys Vlasenko99862cb2010-09-12 17:34:13 +0200141//config:
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200142//config:config HUSH_JOB
143//config: bool "Job control"
144//config: default y
145//config: depends on HUSH_INTERACTIVE
146//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200147//config: Enable job control: Ctrl-Z backgrounds, Ctrl-C interrupts current
148//config: command (not entire shell), fg/bg builtins work. Without this option,
149//config: "cmd &" still works by simply spawning a process and immediately
150//config: prompting for next command (or executing next command in a script),
151//config: but no separate process group is formed.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200152//config:
153//config:config HUSH_TICK
Denys Vlasenkof5604222017-01-10 14:58:54 +0100154//config: bool "Support process substitution"
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200155//config: default y
Denys Vlasenko0b883582016-12-23 16:49:07 +0100156//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200157//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200158//config: Enable `command` and $(command).
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200159//config:
160//config:config HUSH_IF
161//config: bool "Support if/then/elif/else/fi"
162//config: default y
Denys Vlasenko0b883582016-12-23 16:49:07 +0100163//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200164//config:
165//config:config HUSH_LOOPS
166//config: bool "Support for, while and until loops"
167//config: default y
Denys Vlasenko0b883582016-12-23 16:49:07 +0100168//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200169//config:
170//config:config HUSH_CASE
171//config: bool "Support case ... esac statement"
172//config: default y
Denys Vlasenko0b883582016-12-23 16:49:07 +0100173//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200174//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200175//config: Enable case ... esac statement. +400 bytes.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200176//config:
177//config:config HUSH_FUNCTIONS
178//config: bool "Support funcname() { commands; } syntax"
179//config: default y
Denys Vlasenko0b883582016-12-23 16:49:07 +0100180//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200181//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200182//config: Enable support for shell functions. +800 bytes.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200183//config:
184//config:config HUSH_LOCAL
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100185//config: bool "local builtin"
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200186//config: default y
187//config: depends on HUSH_FUNCTIONS
188//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200189//config: Enable support for local variables in functions.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200190//config:
191//config:config HUSH_RANDOM_SUPPORT
192//config: bool "Pseudorandom generator and $RANDOM variable"
193//config: default y
Denys Vlasenko0b883582016-12-23 16:49:07 +0100194//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200195//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200196//config: Enable pseudorandom generator and dynamic variable "$RANDOM".
197//config: Each read of "$RANDOM" will generate a new pseudorandom value.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200198//config:
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200199//config:config HUSH_MODE_X
200//config: bool "Support 'hush -x' option and 'set -x' command"
201//config: default y
Denys Vlasenko0b883582016-12-23 16:49:07 +0100202//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200203//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200204//config: This instructs hush to print commands before execution.
205//config: Adds ~300 bytes.
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200206//config:
Denys Vlasenko1cc68042017-01-09 17:10:04 +0100207//config:config HUSH_ECHO
208//config: bool "echo builtin"
209//config: default y
210//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko1cc68042017-01-09 17:10:04 +0100211//config:
212//config:config HUSH_PRINTF
213//config: bool "printf builtin"
214//config: default y
215//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenkof5604222017-01-10 14:58:54 +0100216//config:
Denys Vlasenko265062d2017-01-10 15:13:30 +0100217//config:config HUSH_TEST
218//config: bool "test builtin"
219//config: default y
220//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
221//config:
Denys Vlasenkof5604222017-01-10 14:58:54 +0100222//config:config HUSH_HELP
223//config: bool "help builtin"
224//config: default y
225//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko1cc68042017-01-09 17:10:04 +0100226//config:
Denys Vlasenko6ec76d82017-01-08 18:40:41 +0100227//config:config HUSH_EXPORT
228//config: bool "export builtin"
229//config: default y
230//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko6ec76d82017-01-08 18:40:41 +0100231//config:
232//config:config HUSH_EXPORT_N
233//config: bool "Support 'export -n' option"
234//config: default y
235//config: depends on HUSH_EXPORT
236//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200237//config: export -n unexports variables. It is a bash extension.
Denys Vlasenko6ec76d82017-01-08 18:40:41 +0100238//config:
Denys Vlasenko1e660422017-07-17 21:10:50 +0200239//config:config HUSH_READONLY
240//config: bool "readonly builtin"
241//config: default y
Denys Vlasenko6b0695b2017-07-17 21:47:27 +0200242//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko1e660422017-07-17 21:10:50 +0200243//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200244//config: Enable support for read-only variables.
Denys Vlasenko1e660422017-07-17 21:10:50 +0200245//config:
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100246//config:config HUSH_KILL
Denys Vlasenkof5604222017-01-10 14:58:54 +0100247//config: bool "kill builtin (supports kill %jobspec)"
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100248//config: default y
249//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100250//config:
251//config:config HUSH_WAIT
252//config: bool "wait builtin"
253//config: default y
254//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100255//config:
256//config:config HUSH_TRAP
257//config: bool "trap builtin"
258//config: default y
259//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100260//config:
261//config:config HUSH_TYPE
262//config: bool "type builtin"
263//config: default y
264//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100265//config:
Denys Vlasenko11f2e992017-08-10 16:34:03 +0200266//config:config HUSH_TIMES
267//config: bool "times builtin"
268//config: default y
269//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
270//config:
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100271//config:config HUSH_READ
272//config: bool "read builtin"
273//config: default y
274//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100275//config:
Denys Vlasenko10d5ece2017-01-08 18:28:43 +0100276//config:config HUSH_SET
277//config: bool "set builtin"
278//config: default y
279//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko10d5ece2017-01-08 18:28:43 +0100280//config:
281//config:config HUSH_UNSET
282//config: bool "unset builtin"
283//config: default y
284//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenkof5604222017-01-10 14:58:54 +0100285//config:
286//config:config HUSH_ULIMIT
287//config: bool "ulimit builtin"
288//config: default y
289//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko10d5ece2017-01-08 18:28:43 +0100290//config:
Denys Vlasenkod5933b12017-01-08 18:31:39 +0100291//config:config HUSH_UMASK
292//config: bool "umask builtin"
293//config: default y
294//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenkod5933b12017-01-08 18:31:39 +0100295//config:
Denys Vlasenko74d40582017-08-11 01:32:46 +0200296//config:config HUSH_GETOPTS
297//config: bool "getopts builtin"
298//config: default y
299//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
300//config:
Denys Vlasenko44719692017-01-08 18:44:41 +0100301//config:config HUSH_MEMLEAK
302//config: bool "memleak builtin (debugging)"
303//config: default n
304//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
Denys Vlasenko202a2d12010-07-16 12:36:14 +0200305
Denys Vlasenko20704f02011-03-23 17:59:27 +0100306//applet:IF_HUSH(APPLET(hush, BB_DIR_BIN, BB_SUID_DROP))
Denys Vlasenko205d48e2017-01-29 14:57:33 +0100307// APPLET_ODDNAME:name main location suid_type help
Denys Vlasenko205d48e2017-01-29 14:57:33 +0100308//applet:IF_SH_IS_HUSH( APPLET_ODDNAME(sh, hush, BB_DIR_BIN, BB_SUID_DROP, hush))
Denys Vlasenko0b883582016-12-23 16:49:07 +0100309//applet:IF_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, hush))
Denys Vlasenko20704f02011-03-23 17:59:27 +0100310
311//kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o
Denys Vlasenko0b883582016-12-23 16:49:07 +0100312//kbuild:lib-$(CONFIG_SH_IS_HUSH) += hush.o match.o shell_common.o
313//kbuild:lib-$(CONFIG_BASH_IS_HUSH) += hush.o match.o shell_common.o
Denys Vlasenko20704f02011-03-23 17:59:27 +0100314//kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o
315
Dan Fandrich89ca2f92010-11-28 01:54:39 +0100316/* -i (interactive) and -s (read stdin) are also accepted,
317 * but currently do nothing, therefore aren't shown in help.
318 * NOMMU-specific options are not meant to be used by users,
319 * therefore we don't show them either.
320 */
321//usage:#define hush_trivial_usage
Denys Vlasenko9fda6092017-07-14 13:36:48 +0200322//usage: "[-enxl] [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
Denys Vlasenkob0b83432011-03-07 12:34:59 +0100323//usage:#define hush_full_usage "\n\n"
324//usage: "Unix shell interpreter"
325
Denys Vlasenko67047462016-12-22 15:21:58 +0100326#if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
327 || defined(__APPLE__) \
328 )
329# include <malloc.h> /* for malloc_trim */
330#endif
331#include <glob.h>
332/* #include <dmalloc.h> */
333#if ENABLE_HUSH_CASE
334# include <fnmatch.h>
335#endif
Denys Vlasenko11f2e992017-08-10 16:34:03 +0200336#include <sys/times.h>
Denys Vlasenko67047462016-12-22 15:21:58 +0100337#include <sys/utsname.h> /* for setting $HOSTNAME */
338
339#include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */
340#include "unicode.h"
341#include "shell_common.h"
342#include "math.h"
343#include "match.h"
344#if ENABLE_HUSH_RANDOM_SUPPORT
345# include "random.h"
346#else
347# define CLEAR_RANDOM_T(rnd) ((void)0)
348#endif
349#ifndef F_DUPFD_CLOEXEC
350# define F_DUPFD_CLOEXEC F_DUPFD
351#endif
352#ifndef PIPE_BUF
353# define PIPE_BUF 4096 /* amount of buffering in a pipe */
354#endif
355
Denis Vlasenko1943aec2009-04-09 14:15:57 +0000356
Kang-Che Sung027d3ab2017-01-11 14:18:15 +0100357/* So far, all bash compat is controlled by one config option */
358/* Separate defines document which part of code implements what */
359#define BASH_PATTERN_SUBST ENABLE_HUSH_BASH_COMPAT
360#define BASH_SUBSTR ENABLE_HUSH_BASH_COMPAT
Kang-Che Sung027d3ab2017-01-11 14:18:15 +0100361#define BASH_SOURCE ENABLE_HUSH_BASH_COMPAT
362#define BASH_HOSTNAME_VAR ENABLE_HUSH_BASH_COMPAT
Denys Vlasenko4ee824f2017-07-03 01:22:13 +0200363#define BASH_TEST2 (ENABLE_HUSH_BASH_COMPAT && ENABLE_HUSH_TEST)
Denys Vlasenko1f41c882017-08-09 13:52:36 +0200364#define BASH_READ_D ENABLE_HUSH_BASH_COMPAT
Kang-Che Sung027d3ab2017-01-11 14:18:15 +0100365
366
Denys Vlasenko8d7be232009-05-25 16:38:32 +0200367/* Build knobs */
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +0000368#define LEAK_HUNTING 0
369#define BUILD_AS_NOMMU 0
370/* Enable/disable sanity checks. Ok to enable in production,
371 * only adds a bit of bloat. Set to >1 to get non-production level verbosity.
372 * Keeping 1 for now even in released versions.
373 */
374#define HUSH_DEBUG 1
Denys Vlasenko8d7be232009-05-25 16:38:32 +0200375/* Slightly bigger (+200 bytes), but faster hush.
376 * So far it only enables a trick with counting SIGCHLDs and forks,
377 * which allows us to do fewer waitpid's.
378 * (we can detect a case where neither forks were done nor SIGCHLDs happened
379 * and therefore waitpid will return the same result as last time)
380 */
381#define ENABLE_HUSH_FAST 0
Denys Vlasenko9297dbc2010-07-05 21:37:12 +0200382/* TODO: implement simplified code for users which do not need ${var%...} ops
383 * So far ${var%...} ops are always enabled:
384 */
385#define ENABLE_HUSH_DOLLAR_OPS 1
Denis Vlasenko1943aec2009-04-09 14:15:57 +0000386
387
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +0000388#if BUILD_AS_NOMMU
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000389# undef BB_MMU
390# undef USE_FOR_NOMMU
391# undef USE_FOR_MMU
392# define BB_MMU 0
393# define USE_FOR_NOMMU(...) __VA_ARGS__
394# define USE_FOR_MMU(...)
395#endif
396
Denys Vlasenko1fcbff22010-06-26 02:40:08 +0200397#include "NUM_APPLETS.h"
Denys Vlasenko14974842010-03-23 01:08:26 +0100398#if NUM_APPLETS == 1
Denis Vlasenko61befda2008-11-25 01:36:03 +0000399/* STANDALONE does not make sense, and won't compile */
Denis Vlasenkoce4acbb2009-04-10 23:23:41 +0000400# undef CONFIG_FEATURE_SH_STANDALONE
401# undef ENABLE_FEATURE_SH_STANDALONE
Denis Vlasenko5e34ff22009-04-21 11:09:40 +0000402# undef IF_FEATURE_SH_STANDALONE
Denys Vlasenko14974842010-03-23 01:08:26 +0100403# undef IF_NOT_FEATURE_SH_STANDALONE
404# define ENABLE_FEATURE_SH_STANDALONE 0
Denis Vlasenko5e34ff22009-04-21 11:09:40 +0000405# define IF_FEATURE_SH_STANDALONE(...)
406# define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
Denis Vlasenko61befda2008-11-25 01:36:03 +0000407#endif
408
Denis Vlasenko05743d72008-02-10 12:10:08 +0000409#if !ENABLE_HUSH_INTERACTIVE
Denis Vlasenkoce4acbb2009-04-10 23:23:41 +0000410# undef ENABLE_FEATURE_EDITING
411# define ENABLE_FEATURE_EDITING 0
412# undef ENABLE_FEATURE_EDITING_FANCY_PROMPT
413# define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0
Denys Vlasenko8cab6672012-04-20 14:48:00 +0200414# undef ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
415# define ENABLE_FEATURE_EDITING_SAVE_ON_EXIT 0
Denis Vlasenko8412d792007-10-01 09:59:47 +0000416#endif
417
Denis Vlasenko424f79b2009-03-22 14:23:34 +0000418/* Do we support ANY keywords? */
419#if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
Denis Vlasenkoce4acbb2009-04-10 23:23:41 +0000420# define HAS_KEYWORDS 1
421# define IF_HAS_KEYWORDS(...) __VA_ARGS__
422# define IF_HAS_NO_KEYWORDS(...)
Denis Vlasenko424f79b2009-03-22 14:23:34 +0000423#else
Denis Vlasenkoce4acbb2009-04-10 23:23:41 +0000424# define HAS_KEYWORDS 0
425# define IF_HAS_KEYWORDS(...)
426# define IF_HAS_NO_KEYWORDS(...) __VA_ARGS__
Denis Vlasenko424f79b2009-03-22 14:23:34 +0000427#endif
Denis Vlasenko8412d792007-10-01 09:59:47 +0000428
Denis Vlasenkod01ff132007-05-02 21:40:23 +0000429/* If you comment out one of these below, it will be #defined later
430 * to perform debug printfs to stderr: */
Denis Vlasenko03eb8bf2007-05-14 16:19:34 +0000431#define debug_printf(...) do {} while (0)
Denis Vlasenko400c5b62007-05-04 13:07:27 +0000432/* Finer-grained debug switches */
Denis Vlasenko03eb8bf2007-05-14 16:19:34 +0000433#define debug_printf_parse(...) do {} while (0)
434#define debug_print_tree(a, b) do {} while (0)
435#define debug_printf_exec(...) do {} while (0)
Denis Vlasenkof886fd22008-10-13 12:36:05 +0000436#define debug_printf_env(...) do {} while (0)
Denis Vlasenko03eb8bf2007-05-14 16:19:34 +0000437#define debug_printf_jobs(...) do {} while (0)
438#define debug_printf_expand(...) do {} while (0)
Denys Vlasenko1e811b12010-05-22 03:12:29 +0200439#define debug_printf_varexp(...) do {} while (0)
Denis Vlasenkob61e13d2008-06-17 05:11:43 +0000440#define debug_printf_glob(...) do {} while (0)
Denys Vlasenko2db74612017-07-07 22:07:28 +0200441#define debug_printf_redir(...) do {} while (0)
Denis Vlasenkob61e13d2008-06-17 05:11:43 +0000442#define debug_printf_list(...) do {} while (0)
Denis Vlasenko30c9cc52008-06-17 07:24:29 +0000443#define debug_printf_subst(...) do {} while (0)
Denis Vlasenko03eb8bf2007-05-14 16:19:34 +0000444#define debug_printf_clean(...) do {} while (0)
Denis Vlasenkod01ff132007-05-02 21:40:23 +0000445
Denis Vlasenkob6e65562009-04-03 16:49:04 +0000446#define ERR_PTR ((void*)(long)1)
447
Denys Vlasenkod5b5c2f2017-01-08 15:46:04 +0100448#define JOB_STATUS_FORMAT "[%u] %-22s %.40s\n"
Denis Vlasenko5ec61322008-06-24 00:50:07 +0000449
Denys Vlasenkoe85248a2010-05-22 06:20:26 +0200450#define _SPECIAL_VARS_STR "_*@$!?#"
451#define SPECIAL_VARS_STR ("_*@$!?#" + 1)
452#define NUMERIC_SPECVARS_STR ("_*@$!?#" + 3)
Kang-Che Sung027d3ab2017-01-11 14:18:15 +0100453#if BASH_PATTERN_SUBST
Denys Vlasenko36f774a2010-09-05 14:45:38 +0200454/* Support / and // replace ops */
455/* Note that // is stored as \ in "encoded" string representation */
456# define VAR_ENCODED_SUBST_OPS "\\/%#:-=+?"
457# define VAR_SUBST_OPS ("\\/%#:-=+?" + 1)
458# define MINUS_PLUS_EQUAL_QUESTION ("\\/%#:-=+?" + 5)
459#else
460# define VAR_ENCODED_SUBST_OPS "%#:-=+?"
461# define VAR_SUBST_OPS "%#:-=+?"
462# define MINUS_PLUS_EQUAL_QUESTION ("%#:-=+?" + 3)
463#endif
Denys Vlasenkoe85248a2010-05-22 06:20:26 +0200464
465#define SPECIAL_VAR_SYMBOL 3
Eric Andersen25f27032001-04-26 23:22:31 +0000466
Denys Vlasenkocb6ff252009-05-04 00:14:30 +0200467struct variable;
468
Denis Vlasenkocc90f442009-04-08 16:40:34 +0000469static const char hush_version_str[] ALIGN1 = "HUSH_VERSION="BB_VER;
470
471/* This supports saving pointers malloced in vfork child,
Denis Vlasenkoc376db32009-04-15 21:49:48 +0000472 * to be freed in the parent.
Denis Vlasenkocc90f442009-04-08 16:40:34 +0000473 */
474#if !BB_MMU
475typedef struct nommu_save_t {
476 char **new_env;
Denys Vlasenkocb6ff252009-05-04 00:14:30 +0200477 struct variable *old_vars;
Denis Vlasenkocc90f442009-04-08 16:40:34 +0000478 char **argv;
Denis Vlasenko27014ed2009-04-15 21:48:23 +0000479 char **argv_from_re_execing;
Denis Vlasenkocc90f442009-04-08 16:40:34 +0000480} nommu_save_t;
481#endif
482
Denys Vlasenko9b782552010-09-08 13:33:26 +0200483enum {
Eric Andersen25f27032001-04-26 23:22:31 +0000484 RES_NONE = 0,
Denis Vlasenko06810332007-05-21 23:30:54 +0000485#if ENABLE_HUSH_IF
Denis Vlasenko17f02e72008-07-14 04:32:29 +0000486 RES_IF ,
487 RES_THEN ,
488 RES_ELIF ,
489 RES_ELSE ,
490 RES_FI ,
Denis Vlasenko06810332007-05-21 23:30:54 +0000491#endif
492#if ENABLE_HUSH_LOOPS
Denis Vlasenko17f02e72008-07-14 04:32:29 +0000493 RES_FOR ,
494 RES_WHILE ,
495 RES_UNTIL ,
496 RES_DO ,
497 RES_DONE ,
Denis Vlasenkod91afa32008-07-29 11:10:01 +0000498#endif
499#if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
Denis Vlasenko17f02e72008-07-14 04:32:29 +0000500 RES_IN ,
Denis Vlasenko06810332007-05-21 23:30:54 +0000501#endif
Denis Vlasenko17f02e72008-07-14 04:32:29 +0000502#if ENABLE_HUSH_CASE
503 RES_CASE ,
Denys Vlasenkoe9bda902009-05-23 16:50:07 +0200504 /* three pseudo-keywords support contrived "case" syntax: */
505 RES_CASE_IN, /* "case ... IN", turns into RES_MATCH when IN is observed */
506 RES_MATCH , /* "word)" */
507 RES_CASE_BODY, /* "this command is inside CASE" */
Denis Vlasenko17f02e72008-07-14 04:32:29 +0000508 RES_ESAC ,
509#endif
510 RES_XXXX ,
511 RES_SNTX
Denys Vlasenko9b782552010-09-08 13:33:26 +0200512};
Denis Vlasenkoc7985b72008-06-17 05:43:38 +0000513
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000514typedef struct o_string {
515 char *data;
516 int length; /* position where data is appended */
517 int maxlen;
Denys Vlasenko5b686cb2010-09-08 13:44:34 +0200518 int o_expflags;
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +0000519 /* At least some part of the string was inside '' or "",
520 * possibly empty one: word"", wo''rd etc. */
Denys Vlasenko38292b62010-09-05 14:49:40 +0200521 smallint has_quoted_part;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000522 smallint has_empty_slot;
523 smallint o_assignment; /* 0:maybe, 1:yes, 2:no */
524} o_string;
525enum {
Denys Vlasenko0e13b402010-09-21 12:35:39 +0200526 EXP_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */
527 EXP_FLAG_GLOB = 0x2,
528 /* Protect newly added chars against globbing
529 * by prepending \ to *, ?, [, \ */
530 EXP_FLAG_ESC_GLOB_CHARS = 0x1,
531};
532enum {
533 MAYBE_ASSIGNMENT = 0,
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000534 DEFINITELY_ASSIGNMENT = 1,
Denys Vlasenko0e13b402010-09-21 12:35:39 +0200535 NOT_ASSIGNMENT = 2,
Maninder Singh97c64912015-05-25 13:46:36 +0200536 /* Not an assignment, but next word may be: "if v=xyz cmd;" */
Denys Vlasenko0e13b402010-09-21 12:35:39 +0200537 WORD_IS_KEYWORD = 3,
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000538};
539/* Used for initialization: o_string foo = NULL_O_STRING; */
540#define NULL_O_STRING { NULL }
541
Denys Vlasenko29f9b722011-05-14 11:27:36 +0200542#ifndef debug_printf_parse
543static const char *const assignment_flag[] = {
544 "MAYBE_ASSIGNMENT",
545 "DEFINITELY_ASSIGNMENT",
546 "NOT_ASSIGNMENT",
547 "WORD_IS_KEYWORD",
548};
549#endif
550
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000551typedef struct in_str {
552 const char *p;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000553#if ENABLE_HUSH_INTERACTIVE
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000554 smallint promptmode; /* 0: PS1, 1: PS2 */
555#endif
Denys Vlasenkod17a91d2016-09-29 18:02:37 +0200556 int peek_buf[2];
Denys Vlasenkocecbc982011-03-30 18:54:52 +0200557 int last_char;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000558 FILE *file;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000559} in_str;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000560
Denys Vlasenko764b2f02009-06-07 16:05:04 +0200561/* The descrip member of this structure is only used to make
562 * debugging output pretty */
563static const struct {
564 int mode;
565 signed char default_fd;
566 char descrip[3];
567} redir_table[] = {
568 { O_RDONLY, 0, "<" },
569 { O_CREAT|O_TRUNC|O_WRONLY, 1, ">" },
570 { O_CREAT|O_APPEND|O_WRONLY, 1, ">>" },
571 { O_CREAT|O_RDWR, 1, "<>" },
572 { O_RDONLY, 0, "<<" },
573/* Should not be needed. Bogus default_fd helps in debugging */
574/* { O_RDONLY, 77, "<<" }, */
575};
576
Eric Andersen25f27032001-04-26 23:22:31 +0000577struct redir_struct {
Denis Vlasenko55789c62008-06-18 16:30:42 +0000578 struct redir_struct *next;
Denis Vlasenko5ec61322008-06-24 00:50:07 +0000579 char *rd_filename; /* filename */
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +0000580 int rd_fd; /* fd to redirect */
581 /* fd to redirect to, or -3 if rd_fd is to be closed (n>&-) */
582 int rd_dup;
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +0000583 smallint rd_type; /* (enum redir_type) */
584 /* note: for heredocs, rd_filename contains heredoc delimiter,
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +0000585 * and subsequently heredoc itself; and rd_dup is a bitmask:
Denys Vlasenko764b2f02009-06-07 16:05:04 +0200586 * bit 0: do we need to trim leading tabs?
587 * bit 1: is heredoc quoted (<<'delim' syntax) ?
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +0000588 */
Eric Andersen25f27032001-04-26 23:22:31 +0000589};
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +0000590typedef enum redir_type {
Denys Vlasenko764b2f02009-06-07 16:05:04 +0200591 REDIRECT_INPUT = 0,
592 REDIRECT_OVERWRITE = 1,
593 REDIRECT_APPEND = 2,
594 REDIRECT_IO = 3,
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +0000595 REDIRECT_HEREDOC = 4,
Denys Vlasenko764b2f02009-06-07 16:05:04 +0200596 REDIRECT_HEREDOC2 = 5, /* REDIRECT_HEREDOC after heredoc is loaded */
Denis Vlasenkoc96865f2009-04-10 00:20:58 +0000597
598 REDIRFD_CLOSE = -3,
599 REDIRFD_SYNTAX_ERR = -2,
Denis Vlasenko835fcfd2009-04-10 13:51:56 +0000600 REDIRFD_TO_FILE = -1,
601 /* otherwise, rd_fd is redirected to rd_dup */
Denis Vlasenkoc96865f2009-04-10 00:20:58 +0000602
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +0000603 HEREDOC_SKIPTABS = 1,
604 HEREDOC_QUOTED = 2,
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +0000605} redir_type;
606
Eric Andersen25f27032001-04-26 23:22:31 +0000607
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000608struct command {
Denis Vlasenko0c886c62007-01-30 22:30:09 +0000609 pid_t pid; /* 0 if exited */
Denis Vlasenko2b576b82008-08-04 00:46:07 +0000610 int assignment_cnt; /* how many argv[i] are assignments? */
Denys Vlasenko9d617c42009-06-09 18:40:52 +0200611 smallint cmd_type; /* CMD_xxx */
612#define CMD_NORMAL 0
613#define CMD_SUBSHELL 1
Kang-Che Sung027d3ab2017-01-11 14:18:15 +0100614#if BASH_TEST2
Denys Vlasenkod383b492010-09-06 10:22:13 +0200615/* used for "[[ EXPR ]]" */
Denys Vlasenko9ca656b2009-06-10 13:39:35 +0200616# define CMD_SINGLEWORD_NOGLOB 2
Denis Vlasenkoed055212009-04-11 10:37:10 +0000617#endif
Denys Vlasenko9ca656b2009-06-10 13:39:35 +0200618#if ENABLE_HUSH_FUNCTIONS
619# define CMD_FUNCDEF 3
620#endif
621
Denys Vlasenko6696eac2010-11-14 02:01:50 +0100622 smalluint cmd_exitcode;
Denys Vlasenkocb6ff252009-05-04 00:14:30 +0200623 /* if non-NULL, this "command" is { list }, ( list ), or a compound statement */
624 struct pipe *group;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000625#if !BB_MMU
626 char *group_as_string;
627#endif
Denis Vlasenkoed055212009-04-11 10:37:10 +0000628#if ENABLE_HUSH_FUNCTIONS
629 struct function *child_func;
630/* This field is used to prevent a bug here:
Denys Vlasenko9d617c42009-06-09 18:40:52 +0200631 * while...do f1() {a;}; f1; f1() {b;}; f1; done
Denis Vlasenkoed055212009-04-11 10:37:10 +0000632 * When we execute "f1() {a;}" cmd, we create new function and clear
633 * cmd->group, cmd->group_as_string, cmd->argv[0].
Denys Vlasenko9d617c42009-06-09 18:40:52 +0200634 * When we execute "f1() {b;}", we notice that f1 exists,
635 * and that its "parent cmd" struct is still "alive",
Denis Vlasenkoed055212009-04-11 10:37:10 +0000636 * we put those fields back into cmd->xxx
637 * (struct function has ->parent_cmd ptr to facilitate that).
638 * When we loop back, we can execute "f1() {a;}" again and set f1 correctly.
639 * Without this trick, loop would execute a;b;b;b;...
640 * instead of correct sequence a;b;a;b;...
641 * When command is freed, it severs the link
642 * (sets ->child_func->parent_cmd to NULL).
643 */
644#endif
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000645 char **argv; /* command name and arguments */
Denis Vlasenko03eb8bf2007-05-14 16:19:34 +0000646/* argv vector may contain variable references (^Cvar^C, ^C0^C etc)
647 * and on execution these are substituted with their values.
648 * Substitution can make _several_ words out of one argv[n]!
649 * Example: argv[0]=='.^C*^C.' here: echo .$*.
Denis Vlasenkoc7985b72008-06-17 05:43:38 +0000650 * References of the form ^C`cmd arg^C are `cmd arg` substitutions.
Denis Vlasenko03eb8bf2007-05-14 16:19:34 +0000651 */
Denis Vlasenkoed055212009-04-11 10:37:10 +0000652 struct redir_struct *redirects; /* I/O redirections */
653};
Denis Vlasenkof8c1f022009-04-17 11:55:42 +0000654/* Is there anything in this command at all? */
655#define IS_NULL_CMD(cmd) \
656 (!(cmd)->group && !(cmd)->argv && !(cmd)->redirects)
657
Eric Andersen25f27032001-04-26 23:22:31 +0000658struct pipe {
Denis Vlasenkob81b3df2007-04-28 16:48:04 +0000659 struct pipe *next;
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +0000660 int num_cmds; /* total number of commands in pipe */
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000661 int alive_cmds; /* number of commands running (not exited) */
662 int stopped_cmds; /* number of commands alive, but stopped */
Denis Vlasenkoe3f2f892007-04-28 16:48:27 +0000663#if ENABLE_HUSH_JOB
Denys Vlasenkod5b5c2f2017-01-08 15:46:04 +0100664 unsigned jobid; /* job number */
Denis Vlasenko0c886c62007-01-30 22:30:09 +0000665 pid_t pgrp; /* process group ID for the job */
Denis Vlasenko219e88d2007-05-21 10:18:23 +0000666 char *cmdtext; /* name of job */
Denis Vlasenkob81b3df2007-04-28 16:48:04 +0000667#endif
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000668 struct command *cmds; /* array of commands in pipe */
Denis Vlasenko219e88d2007-05-21 10:18:23 +0000669 smallint followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
Denis Vlasenko5ec61322008-06-24 00:50:07 +0000670 IF_HAS_KEYWORDS(smallint pi_inverted;) /* "! cmd | cmd" */
671 IF_HAS_KEYWORDS(smallint res_word;) /* needed for if, for, while, until... */
Eric Andersen25f27032001-04-26 23:22:31 +0000672};
Denis Vlasenkoa2b11e32009-04-06 14:11:13 +0000673typedef enum pipe_style {
Denys Vlasenko00a06b92016-11-08 20:35:53 +0100674 PIPE_SEQ = 0,
675 PIPE_AND = 1,
676 PIPE_OR = 2,
677 PIPE_BG = 3,
Denis Vlasenkoa2b11e32009-04-06 14:11:13 +0000678} pipe_style;
Denis Vlasenkof8c1f022009-04-17 11:55:42 +0000679/* Is there anything in this pipe at all? */
680#define IS_NULL_PIPE(pi) \
681 ((pi)->num_cmds == 0 IF_HAS_KEYWORDS( && (pi)->res_word == RES_NONE))
Eric Andersen25f27032001-04-26 23:22:31 +0000682
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000683/* This holds pointers to the various results of parsing */
684struct parse_context {
Denis Vlasenkof9f74292009-04-03 00:07:05 +0000685 /* linked list of pipes */
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000686 struct pipe *list_head;
Denis Vlasenkof9f74292009-04-03 00:07:05 +0000687 /* last pipe (being constructed right now) */
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000688 struct pipe *pipe;
Denis Vlasenkof9f74292009-04-03 00:07:05 +0000689 /* last command in pipe (being constructed right now) */
690 struct command *command;
691 /* last redirect in command->redirects list */
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000692 struct redir_struct *pending_redirect;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +0000693#if !BB_MMU
694 o_string as_string;
695#endif
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000696#if HAS_KEYWORDS
697 smallint ctx_res_w;
698 smallint ctx_inverted; /* "! cmd | cmd" */
699#if ENABLE_HUSH_CASE
700 smallint ctx_dsemicolon; /* ";;" seen */
701#endif
Denis Vlasenkof9f74292009-04-03 00:07:05 +0000702 /* bitmask of FLAG_xxx, for figuring out valid reserved words */
703 int old_flag;
704 /* group we are enclosed in:
Denis Vlasenko34d4d892009-04-04 20:24:37 +0000705 * example: "if pipe1; pipe2; then pipe3; fi"
706 * when we see "if" or "then", we malloc and copy current context,
707 * and make ->stack point to it. then we parse pipeN.
708 * when closing "then" / fi" / whatever is found,
709 * we move list_head into ->stack->command->group,
710 * copy ->stack into current context, and delete ->stack.
711 * (parsing of { list } and ( list ) doesn't use this method)
Denis Vlasenkof9f74292009-04-03 00:07:05 +0000712 */
Denis Vlasenko9af22c72008-10-09 12:54:58 +0000713 struct parse_context *stack;
714#endif
715};
716
Denis Vlasenkod76c0492007-05-25 02:16:25 +0000717/* On program start, environ points to initial environment.
718 * putenv adds new pointers into it, unsetenv removes them.
719 * Neither of these (de)allocates the strings.
720 * setenv allocates new strings in malloc space and does putenv,
721 * and thus setenv is unusable (leaky) for shell's purposes */
722#define setenv(...) setenv_is_leaky_dont_use()
723struct variable {
724 struct variable *next;
Denis Vlasenko28c0f0f2007-05-25 02:46:01 +0000725 char *varstr; /* points to "name=" portion */
Denys Vlasenko295fef82009-06-03 12:47:26 +0200726#if ENABLE_HUSH_LOCAL
727 unsigned func_nest_level;
728#endif
Denis Vlasenkod76c0492007-05-25 02:16:25 +0000729 int max_len; /* if > 0, name is part of initial env; else name is malloced */
730 smallint flg_export; /* putenv should be done on this var */
Denis Vlasenko219e88d2007-05-21 10:18:23 +0000731 smallint flg_read_only;
Eric Andersen9ffb7dd2001-05-19 03:00:46 +0000732};
733
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000734enum {
Denis Vlasenkobcb25532008-07-28 23:04:34 +0000735 BC_BREAK = 1,
736 BC_CONTINUE = 2,
737};
738
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +0000739#if ENABLE_HUSH_FUNCTIONS
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +0000740struct function {
741 struct function *next;
742 char *name;
Denis Vlasenkoed055212009-04-11 10:37:10 +0000743 struct command *parent_cmd;
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +0000744 struct pipe *body;
Denys Vlasenkoc1947f12009-10-23 01:30:26 +0200745# if !BB_MMU
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +0000746 char *body_as_string;
Denys Vlasenkoc1947f12009-10-23 01:30:26 +0200747# endif
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +0000748};
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +0000749#endif
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +0000750
Denis Vlasenkod76c0492007-05-25 02:16:25 +0000751
Denys Vlasenko6696eac2010-11-14 02:01:50 +0100752/* set -/+o OPT support. (TODO: make it optional)
753 * bash supports the following opts:
754 * allexport off
755 * braceexpand on
756 * emacs on
757 * errexit off
758 * errtrace off
759 * functrace off
760 * hashall on
761 * histexpand off
762 * history on
763 * ignoreeof off
764 * interactive-comments on
765 * keyword off
766 * monitor on
767 * noclobber off
768 * noexec off
769 * noglob off
770 * nolog off
771 * notify off
772 * nounset off
773 * onecmd off
774 * physical off
775 * pipefail off
776 * posix off
777 * privileged off
778 * verbose off
779 * vi off
780 * xtrace off
781 */
Dan Fandrich85c62472010-11-20 13:05:17 -0800782static const char o_opt_strings[] ALIGN1 =
783 "pipefail\0"
784 "noexec\0"
Denys Vlasenko9fda6092017-07-14 13:36:48 +0200785 "errexit\0"
Dan Fandrich85c62472010-11-20 13:05:17 -0800786#if ENABLE_HUSH_MODE_X
787 "xtrace\0"
788#endif
789 ;
Denys Vlasenko6696eac2010-11-14 02:01:50 +0100790enum {
791 OPT_O_PIPEFAIL,
Dan Fandrich85c62472010-11-20 13:05:17 -0800792 OPT_O_NOEXEC,
Denys Vlasenko9fda6092017-07-14 13:36:48 +0200793 OPT_O_ERREXIT,
Dan Fandrich85c62472010-11-20 13:05:17 -0800794#if ENABLE_HUSH_MODE_X
795 OPT_O_XTRACE,
796#endif
Denys Vlasenko6696eac2010-11-14 02:01:50 +0100797 NUM_OPT_O
798};
799
800
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +0200801struct FILE_list {
802 struct FILE_list *next;
803 FILE *fp;
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +0200804 int fd;
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +0200805};
806
807
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000808/* "Globals" within this file */
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000809/* Sorted roughly by size (smaller offsets == smaller code) */
810struct globals {
Denis Vlasenkoc8653f62009-04-27 23:29:14 +0000811 /* interactive_fd != 0 means we are an interactive shell.
812 * If we are, then saved_tty_pgrp can also be != 0, meaning
813 * that controlling tty is available. With saved_tty_pgrp == 0,
814 * job control still works, but terminal signals
815 * (^C, ^Z, ^Y, ^\) won't work at all, and background
816 * process groups can only be created with "cmd &".
817 * With saved_tty_pgrp != 0, hush will use tcsetpgrp()
818 * to give tty to the foreground process group,
819 * and will take it back when the group is stopped (^Z)
820 * or killed (^C).
821 */
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000822#if ENABLE_HUSH_INTERACTIVE
823 /* 'interactive_fd' is a fd# open to ctty, if we have one
824 * _AND_ if we decided to act interactively */
825 int interactive_fd;
826 const char *PS1;
827 const char *PS2;
Denis Vlasenkoc8653f62009-04-27 23:29:14 +0000828# define G_interactive_fd (G.interactive_fd)
Denis Vlasenko60b392f2009-04-03 19:14:32 +0000829#else
Denis Vlasenkoc8653f62009-04-27 23:29:14 +0000830# define G_interactive_fd 0
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000831#endif
832#if ENABLE_FEATURE_EDITING
833 line_input_t *line_input_state;
834#endif
Denis Vlasenkocc3f20b2008-06-23 22:31:52 +0000835 pid_t root_pid;
Denys Vlasenkodea47882009-10-09 15:40:49 +0200836 pid_t root_ppid;
Denis Vlasenko87a86552008-07-29 19:43:10 +0000837 pid_t last_bg_pid;
Denys Vlasenko20b3d142009-10-09 20:59:39 +0200838#if ENABLE_HUSH_RANDOM_SUPPORT
839 random_t random_gen;
840#endif
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000841#if ENABLE_HUSH_JOB
842 int run_list_level;
Denys Vlasenkod5b5c2f2017-01-08 15:46:04 +0100843 unsigned last_jobid;
Denis Vlasenkoc8653f62009-04-27 23:29:14 +0000844 pid_t saved_tty_pgrp;
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000845 struct pipe *job_list;
Mike Frysinger38478a62009-05-20 04:48:06 -0400846# define G_saved_tty_pgrp (G.saved_tty_pgrp)
847#else
848# define G_saved_tty_pgrp 0
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000849#endif
Denys Vlasenko9fda6092017-07-14 13:36:48 +0200850 /* How deeply are we in context where "set -e" is ignored */
851 int errexit_depth;
852 /* "set -e" rules (do we follow them correctly?):
853 * Exit if pipe, list, or compound command exits with a non-zero status.
854 * Shell does not exit if failed command is part of condition in
855 * if/while, part of && or || list except the last command, any command
856 * in a pipe but the last, or if the command's return value is being
857 * inverted with !. If a compound command other than a subshell returns a
858 * non-zero status because a command failed while -e was being ignored, the
859 * shell does not exit. A trap on ERR, if set, is executed before the shell
860 * exits [ERR is a bashism].
861 *
862 * If a compound command or function executes in a context where -e is
863 * ignored, none of the commands executed within are affected by the -e
864 * setting. If a compound command or function sets -e while executing in a
865 * context where -e is ignored, that setting does not have any effect until
866 * the compound command or the command containing the function call completes.
867 */
868
Denys Vlasenko26777aa2010-11-22 23:49:10 +0100869 char o_opt[NUM_OPT_O];
Denys Vlasenko57542eb2010-11-28 03:59:30 +0100870#if ENABLE_HUSH_MODE_X
871# define G_x_mode (G.o_opt[OPT_O_XTRACE])
872#else
873# define G_x_mode 0
874#endif
Denis Vlasenko422cd7c2009-03-31 12:41:52 +0000875 smallint flag_SIGINT;
Denis Vlasenkodadfb492008-07-29 10:16:05 +0000876#if ENABLE_HUSH_LOOPS
Denis Vlasenkobcb25532008-07-28 23:04:34 +0000877 smallint flag_break_continue;
Denis Vlasenkodadfb492008-07-29 10:16:05 +0000878#endif
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +0000879#if ENABLE_HUSH_FUNCTIONS
880 /* 0: outside of a function (or sourced file)
881 * -1: inside of a function, ok to use return builtin
Denis Vlasenkoc8653f62009-04-27 23:29:14 +0000882 * 1: return is invoked, skip all till end of func
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +0000883 */
884 smallint flag_return_in_progress;
Denys Vlasenko04b46bc2016-10-01 22:28:03 +0200885# define G_flag_return_in_progress (G.flag_return_in_progress)
886#else
887# define G_flag_return_in_progress 0
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +0000888#endif
Denis Vlasenkoefea9d22009-04-09 13:43:11 +0000889 smallint exiting; /* used to prevent EXIT trap recursion */
Denis Vlasenkod5762932009-03-31 11:22:57 +0000890 /* These four support $?, $#, and $1 */
Denis Vlasenkoab2b0642009-04-06 18:42:11 +0000891 smalluint last_exitcode;
Denys Vlasenko840a4352017-07-07 22:56:02 +0200892 smalluint last_bg_pid_exitcode;
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +0100893#if ENABLE_HUSH_SET
Denis Vlasenkocc4c6932009-04-05 07:38:48 +0000894 /* are global_argv and global_argv[1..n] malloced? (note: not [0]) */
Denis Vlasenko11fb7cf2009-03-20 10:13:08 +0000895 smalluint global_args_malloced;
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +0100896# define G_global_args_malloced (G.global_args_malloced)
897#else
898# define G_global_args_malloced 0
899#endif
Denis Vlasenkoe1300f62009-03-22 11:41:18 +0000900 /* how many non-NULL argv's we have. NB: $# + 1 */
901 int global_argc;
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000902 char **global_argv;
Denis Vlasenkocc4c6932009-04-05 07:38:48 +0000903#if !BB_MMU
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +0000904 char *argv0_for_re_execing;
Denis Vlasenkocc4c6932009-04-05 07:38:48 +0000905#endif
Denis Vlasenkodadfb492008-07-29 10:16:05 +0000906#if ENABLE_HUSH_LOOPS
Denis Vlasenko6a2d40f2008-07-28 23:07:06 +0000907 unsigned depth_break_continue;
Denis Vlasenkofcf37c32008-07-29 11:37:15 +0000908 unsigned depth_of_loop;
Denis Vlasenkodadfb492008-07-29 10:16:05 +0000909#endif
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000910 const char *ifs;
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000911 const char *cwd;
Denys Vlasenko52e460b2010-09-16 16:12:00 +0200912 struct variable *top_var;
Denys Vlasenko29082232010-07-16 13:52:32 +0200913 char **expanded_assignments;
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +0000914#if ENABLE_HUSH_FUNCTIONS
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +0000915 struct function *top_func;
Denys Vlasenko295fef82009-06-03 12:47:26 +0200916# if ENABLE_HUSH_LOCAL
917 struct variable **shadowed_vars_pp;
918 unsigned func_nest_level;
919# endif
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +0000920#endif
Denis Vlasenkod5762932009-03-31 11:22:57 +0000921 /* Signal and trap handling */
Denys Vlasenko8d7be232009-05-25 16:38:32 +0200922#if ENABLE_HUSH_FAST
923 unsigned count_SIGCHLD;
924 unsigned handled_SIGCHLD;
Denys Vlasenkoe2df5f42009-05-26 14:34:10 +0200925 smallint we_have_children;
Denys Vlasenko8d7be232009-05-25 16:38:32 +0200926#endif
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +0200927 struct FILE_list *FILE_list;
Denys Vlasenko10c01312011-05-11 11:49:21 +0200928 /* Which signals have non-DFL handler (even with no traps set)?
929 * Set at the start to:
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +0200930 * (SIGQUIT + maybe SPECIAL_INTERACTIVE_SIGS + maybe SPECIAL_JOBSTOP_SIGS)
Denys Vlasenko10c01312011-05-11 11:49:21 +0200931 * SPECIAL_INTERACTIVE_SIGS are cleared after fork.
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +0200932 * The rest is cleared right before execv syscalls.
Denys Vlasenko10c01312011-05-11 11:49:21 +0200933 * Other than these two times, never modified.
934 */
935 unsigned special_sig_mask;
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +0200936#if ENABLE_HUSH_JOB
937 unsigned fatal_sig_mask;
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +0100938# define G_fatal_sig_mask (G.fatal_sig_mask)
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +0200939#else
Denys Vlasenko75e77de2011-05-12 13:12:47 +0200940# define G_fatal_sig_mask 0
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +0200941#endif
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100942#if ENABLE_HUSH_TRAP
Denis Vlasenko7566bae2009-03-31 17:24:49 +0000943 char **traps; /* char *traps[NSIG] */
Denys Vlasenko7a85c602017-01-08 17:40:18 +0100944# define G_traps G.traps
945#else
946# define G_traps ((char**)NULL)
947#endif
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +0200948 sigset_t pending_set;
Denys Vlasenko44719692017-01-08 18:44:41 +0100949#if ENABLE_HUSH_MEMLEAK
Denis Vlasenkoc73b70c2009-04-08 11:48:57 +0000950 unsigned long memleak_value;
Denys Vlasenko44719692017-01-08 18:44:41 +0100951#endif
952#if HUSH_DEBUG
Denis Vlasenko0701dca2009-04-11 10:38:47 +0000953 int debug_indent;
Denis Vlasenkoc73b70c2009-04-08 11:48:57 +0000954#endif
Denys Vlasenko0806e402011-05-12 23:06:20 +0200955 struct sigaction sa;
Denys Vlasenko0448c552016-09-29 20:25:44 +0200956#if ENABLE_FEATURE_EDITING
957 char user_input_buf[CONFIG_FEATURE_EDITING_MAX_LEN];
958#endif
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000959};
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000960#define G (*ptr_to_globals)
Denis Vlasenko87a86552008-07-29 19:43:10 +0000961/* Not #defining name to G.name - this quickly gets unwieldy
962 * (too many defines). Also, I actually prefer to see when a variable
963 * is global, thus "G." prefix is a useful hint */
Denis Vlasenko574f2f42008-02-27 18:41:59 +0000964#define INIT_G() do { \
965 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
Denys Vlasenko0806e402011-05-12 23:06:20 +0200966 /* memset(&G.sa, 0, sizeof(G.sa)); */ \
967 sigfillset(&G.sa.sa_mask); \
968 G.sa.sa_flags = SA_RESTART; \
Denis Vlasenko574f2f42008-02-27 18:41:59 +0000969} while (0)
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +0000970
971
Denis Vlasenko424f79b2009-03-22 14:23:34 +0000972/* Function prototypes for builtins */
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +0200973static int builtin_cd(char **argv) FAST_FUNC;
Denys Vlasenko1cc68042017-01-09 17:10:04 +0100974#if ENABLE_HUSH_ECHO
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +0200975static int builtin_echo(char **argv) FAST_FUNC;
Denys Vlasenko1cc68042017-01-09 17:10:04 +0100976#endif
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +0200977static int builtin_eval(char **argv) FAST_FUNC;
978static int builtin_exec(char **argv) FAST_FUNC;
979static int builtin_exit(char **argv) FAST_FUNC;
Denys Vlasenko6ec76d82017-01-08 18:40:41 +0100980#if ENABLE_HUSH_EXPORT
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +0200981static int builtin_export(char **argv) FAST_FUNC;
Denys Vlasenko6ec76d82017-01-08 18:40:41 +0100982#endif
Denys Vlasenko1e660422017-07-17 21:10:50 +0200983#if ENABLE_HUSH_READONLY
984static int builtin_readonly(char **argv) FAST_FUNC;
985#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +0000986#if ENABLE_HUSH_JOB
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +0200987static int builtin_fg_bg(char **argv) FAST_FUNC;
988static int builtin_jobs(char **argv) FAST_FUNC;
Denis Vlasenko424f79b2009-03-22 14:23:34 +0000989#endif
Denys Vlasenko74d40582017-08-11 01:32:46 +0200990#if ENABLE_HUSH_GETOPTS
991static int builtin_getopts(char **argv) FAST_FUNC;
992#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +0000993#if ENABLE_HUSH_HELP
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +0200994static int builtin_help(char **argv) FAST_FUNC;
Denis Vlasenko424f79b2009-03-22 14:23:34 +0000995#endif
Denys Vlasenkoff463a82013-05-12 02:45:23 +0200996#if MAX_HISTORY && ENABLE_FEATURE_EDITING
Flemming Madsend96ffda2013-04-07 18:47:24 +0200997static int builtin_history(char **argv) FAST_FUNC;
998#endif
Denys Vlasenko295fef82009-06-03 12:47:26 +0200999#if ENABLE_HUSH_LOCAL
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001000static int builtin_local(char **argv) FAST_FUNC;
Denys Vlasenko295fef82009-06-03 12:47:26 +02001001#endif
Denys Vlasenko44719692017-01-08 18:44:41 +01001002#if ENABLE_HUSH_MEMLEAK
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001003static int builtin_memleak(char **argv) FAST_FUNC;
Denis Vlasenkoc73b70c2009-04-08 11:48:57 +00001004#endif
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001005#if ENABLE_HUSH_PRINTF
Mike Frysinger4ebc76c2009-10-15 03:32:39 -04001006static int builtin_printf(char **argv) FAST_FUNC;
1007#endif
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001008static int builtin_pwd(char **argv) FAST_FUNC;
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001009#if ENABLE_HUSH_READ
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001010static int builtin_read(char **argv) FAST_FUNC;
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001011#endif
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01001012#if ENABLE_HUSH_SET
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001013static int builtin_set(char **argv) FAST_FUNC;
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01001014#endif
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001015static int builtin_shift(char **argv) FAST_FUNC;
1016static int builtin_source(char **argv) FAST_FUNC;
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01001017#if ENABLE_HUSH_TEST || BASH_TEST2
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001018static int builtin_test(char **argv) FAST_FUNC;
Denys Vlasenko265062d2017-01-10 15:13:30 +01001019#endif
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001020#if ENABLE_HUSH_TRAP
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001021static int builtin_trap(char **argv) FAST_FUNC;
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001022#endif
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001023#if ENABLE_HUSH_TYPE
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001024static int builtin_type(char **argv) FAST_FUNC;
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001025#endif
Denys Vlasenko11f2e992017-08-10 16:34:03 +02001026#if ENABLE_HUSH_TIMES
1027static int builtin_times(char **argv) FAST_FUNC;
1028#endif
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001029static int builtin_true(char **argv) FAST_FUNC;
Denys Vlasenkod5933b12017-01-08 18:31:39 +01001030#if ENABLE_HUSH_UMASK
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001031static int builtin_umask(char **argv) FAST_FUNC;
Denys Vlasenkod5933b12017-01-08 18:31:39 +01001032#endif
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01001033#if ENABLE_HUSH_UNSET
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001034static int builtin_unset(char **argv) FAST_FUNC;
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01001035#endif
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001036#if ENABLE_HUSH_KILL
1037static int builtin_kill(char **argv) FAST_FUNC;
1038#endif
1039#if ENABLE_HUSH_WAIT
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001040static int builtin_wait(char **argv) FAST_FUNC;
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001041#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001042#if ENABLE_HUSH_LOOPS
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001043static int builtin_break(char **argv) FAST_FUNC;
1044static int builtin_continue(char **argv) FAST_FUNC;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001045#endif
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +00001046#if ENABLE_HUSH_FUNCTIONS
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02001047static int builtin_return(char **argv) FAST_FUNC;
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +00001048#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001049
1050/* Table of built-in functions. They can be forked or not, depending on
1051 * context: within pipes, they fork. As simple commands, they do not.
1052 * When used in non-forking context, they can change global variables
1053 * in the parent shell process. If forked, of course they cannot.
1054 * For example, 'unset foo | whatever' will parse and run, but foo will
1055 * still be set at the end. */
1056struct built_in_command {
Denys Vlasenko17323a62010-01-28 01:57:05 +01001057 const char *b_cmd;
1058 int (*b_function)(char **argv) FAST_FUNC;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001059#if ENABLE_HUSH_HELP
Denys Vlasenko17323a62010-01-28 01:57:05 +01001060 const char *b_descr;
Denys Vlasenko28a105d2009-06-01 11:26:30 +02001061# define BLTIN(cmd, func, help) { cmd, func, help }
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001062#else
Denys Vlasenko28a105d2009-06-01 11:26:30 +02001063# define BLTIN(cmd, func, help) { cmd, func }
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001064#endif
1065};
1066
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001067static const struct built_in_command bltins1[] = {
Denys Vlasenko80f806c2017-01-10 16:51:10 +01001068 BLTIN("." , builtin_source , "Run commands in file"),
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001069 BLTIN(":" , builtin_true , NULL),
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001070#if ENABLE_HUSH_JOB
Denys Vlasenko80f806c2017-01-10 16:51:10 +01001071 BLTIN("bg" , builtin_fg_bg , "Resume job in background"),
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001072#endif
1073#if ENABLE_HUSH_LOOPS
Denys Vlasenko80f806c2017-01-10 16:51:10 +01001074 BLTIN("break" , builtin_break , "Exit loop"),
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001075#endif
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001076 BLTIN("cd" , builtin_cd , "Change directory"),
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001077#if ENABLE_HUSH_LOOPS
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001078 BLTIN("continue" , builtin_continue, "Start new loop iteration"),
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001079#endif
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001080 BLTIN("eval" , builtin_eval , "Construct and run shell command"),
1081 BLTIN("exec" , builtin_exec , "Execute command, don't return to shell"),
Denys Vlasenko80f806c2017-01-10 16:51:10 +01001082 BLTIN("exit" , builtin_exit , NULL),
Denys Vlasenko6ec76d82017-01-08 18:40:41 +01001083#if ENABLE_HUSH_EXPORT
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001084 BLTIN("export" , builtin_export , "Set environment variables"),
Denys Vlasenko6ec76d82017-01-08 18:40:41 +01001085#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001086#if ENABLE_HUSH_JOB
Denys Vlasenkod2c15bc2017-07-18 18:14:42 +02001087 BLTIN("fg" , builtin_fg_bg , "Bring job to foreground"),
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001088#endif
Denys Vlasenko74d40582017-08-11 01:32:46 +02001089#if ENABLE_HUSH_GETOPTS
1090 BLTIN("getopts" , builtin_getopts , NULL),
1091#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001092#if ENABLE_HUSH_HELP
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001093 BLTIN("help" , builtin_help , NULL),
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001094#endif
Denys Vlasenkoff463a82013-05-12 02:45:23 +02001095#if MAX_HISTORY && ENABLE_FEATURE_EDITING
Denys Vlasenko80f806c2017-01-10 16:51:10 +01001096 BLTIN("history" , builtin_history , "Show history"),
Flemming Madsend96ffda2013-04-07 18:47:24 +02001097#endif
Denis Vlasenko34d4d892009-04-04 20:24:37 +00001098#if ENABLE_HUSH_JOB
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001099 BLTIN("jobs" , builtin_jobs , "List jobs"),
Denis Vlasenko34d4d892009-04-04 20:24:37 +00001100#endif
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001101#if ENABLE_HUSH_KILL
1102 BLTIN("kill" , builtin_kill , "Send signals to processes"),
1103#endif
Denys Vlasenko295fef82009-06-03 12:47:26 +02001104#if ENABLE_HUSH_LOCAL
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001105 BLTIN("local" , builtin_local , "Set local variables"),
Denys Vlasenko295fef82009-06-03 12:47:26 +02001106#endif
Denys Vlasenko44719692017-01-08 18:44:41 +01001107#if ENABLE_HUSH_MEMLEAK
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001108 BLTIN("memleak" , builtin_memleak , NULL),
Denis Vlasenkoc73b70c2009-04-08 11:48:57 +00001109#endif
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001110#if ENABLE_HUSH_READ
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001111 BLTIN("read" , builtin_read , "Input into variable"),
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001112#endif
Denys Vlasenko1e660422017-07-17 21:10:50 +02001113#if ENABLE_HUSH_READONLY
1114 BLTIN("readonly" , builtin_readonly, "Make variables read-only"),
1115#endif
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +00001116#if ENABLE_HUSH_FUNCTIONS
Denys Vlasenko80f806c2017-01-10 16:51:10 +01001117 BLTIN("return" , builtin_return , "Return from function"),
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +00001118#endif
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01001119#if ENABLE_HUSH_SET
Denys Vlasenko80f806c2017-01-10 16:51:10 +01001120 BLTIN("set" , builtin_set , "Set positional parameters"),
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01001121#endif
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001122 BLTIN("shift" , builtin_shift , "Shift positional parameters"),
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01001123#if BASH_SOURCE
Denys Vlasenko80f806c2017-01-10 16:51:10 +01001124 BLTIN("source" , builtin_source , NULL),
Denys Vlasenko82731b42010-05-17 17:49:52 +02001125#endif
Denys Vlasenko11f2e992017-08-10 16:34:03 +02001126#if ENABLE_HUSH_TIMES
1127 BLTIN("times" , builtin_times , NULL),
1128#endif
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001129#if ENABLE_HUSH_TRAP
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001130 BLTIN("trap" , builtin_trap , "Trap signals"),
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001131#endif
Denys Vlasenko2bba5912014-03-14 12:43:57 +01001132 BLTIN("true" , builtin_true , NULL),
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001133#if ENABLE_HUSH_TYPE
Denys Vlasenko651a2692010-03-23 16:25:17 +01001134 BLTIN("type" , builtin_type , "Show command type"),
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001135#endif
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001136#if ENABLE_HUSH_ULIMIT
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01001137 BLTIN("ulimit" , shell_builtin_ulimit, "Control resource limits"),
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001138#endif
Denys Vlasenkod5933b12017-01-08 18:31:39 +01001139#if ENABLE_HUSH_UMASK
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001140 BLTIN("umask" , builtin_umask , "Set file creation mask"),
Denys Vlasenkod5933b12017-01-08 18:31:39 +01001141#endif
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01001142#if ENABLE_HUSH_UNSET
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001143 BLTIN("unset" , builtin_unset , "Unset variables"),
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01001144#endif
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001145#if ENABLE_HUSH_WAIT
Denys Vlasenkod2c15bc2017-07-18 18:14:42 +02001146 BLTIN("wait" , builtin_wait , "Wait for process to finish"),
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001147#endif
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001148};
Denys Vlasenko80f806c2017-01-10 16:51:10 +01001149/* These builtins won't be used if we are on NOMMU and need to re-exec
1150 * (it's cheaper to run an external program in this case):
1151 */
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001152static const struct built_in_command bltins2[] = {
Denys Vlasenko265062d2017-01-10 15:13:30 +01001153#if ENABLE_HUSH_TEST
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001154 BLTIN("[" , builtin_test , NULL),
Denys Vlasenko265062d2017-01-10 15:13:30 +01001155#endif
Denys Vlasenko8944c672017-01-11 14:22:00 +01001156#if BASH_TEST2
1157 BLTIN("[[" , builtin_test , NULL),
1158#endif
Denys Vlasenko1cc68042017-01-09 17:10:04 +01001159#if ENABLE_HUSH_ECHO
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001160 BLTIN("echo" , builtin_echo , NULL),
Denys Vlasenko1cc68042017-01-09 17:10:04 +01001161#endif
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01001162#if ENABLE_HUSH_PRINTF
Mike Frysinger4ebc76c2009-10-15 03:32:39 -04001163 BLTIN("printf" , builtin_printf , NULL),
1164#endif
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001165 BLTIN("pwd" , builtin_pwd , NULL),
Denys Vlasenko265062d2017-01-10 15:13:30 +01001166#if ENABLE_HUSH_TEST
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02001167 BLTIN("test" , builtin_test , NULL),
Denys Vlasenko265062d2017-01-10 15:13:30 +01001168#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00001169};
1170
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +00001171
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001172/* Debug printouts.
1173 */
1174#if HUSH_DEBUG
1175/* prevent disasters with G.debug_indent < 0 */
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001176# define indent() fdprintf(2, "%*s", (G.debug_indent * 2) & 0xff, "")
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001177# define debug_enter() (G.debug_indent++)
1178# define debug_leave() (G.debug_indent--)
1179#else
Denys Vlasenko28a105d2009-06-01 11:26:30 +02001180# define indent() ((void)0)
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001181# define debug_enter() ((void)0)
1182# define debug_leave() ((void)0)
1183#endif
1184
1185#ifndef debug_printf
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001186# define debug_printf(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001187#endif
1188
1189#ifndef debug_printf_parse
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001190# define debug_printf_parse(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001191#endif
1192
1193#ifndef debug_printf_exec
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001194#define debug_printf_exec(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001195#endif
1196
1197#ifndef debug_printf_env
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001198# define debug_printf_env(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001199#endif
1200
1201#ifndef debug_printf_jobs
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001202# define debug_printf_jobs(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001203# define DEBUG_JOBS 1
1204#else
1205# define DEBUG_JOBS 0
1206#endif
1207
1208#ifndef debug_printf_expand
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001209# define debug_printf_expand(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001210# define DEBUG_EXPAND 1
1211#else
1212# define DEBUG_EXPAND 0
1213#endif
1214
Denys Vlasenko1e811b12010-05-22 03:12:29 +02001215#ifndef debug_printf_varexp
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001216# define debug_printf_varexp(...) (indent(), fdprintf(2, __VA_ARGS__))
Denys Vlasenko1e811b12010-05-22 03:12:29 +02001217#endif
1218
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001219#ifndef debug_printf_glob
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001220# define debug_printf_glob(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001221# define DEBUG_GLOB 1
1222#else
1223# define DEBUG_GLOB 0
1224#endif
1225
Denys Vlasenko2db74612017-07-07 22:07:28 +02001226#ifndef debug_printf_redir
1227# define debug_printf_redir(...) (indent(), fdprintf(2, __VA_ARGS__))
1228#endif
1229
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001230#ifndef debug_printf_list
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001231# define debug_printf_list(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001232#endif
1233
1234#ifndef debug_printf_subst
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001235# define debug_printf_subst(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001236#endif
1237
1238#ifndef debug_printf_clean
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001239# define debug_printf_clean(...) (indent(), fdprintf(2, __VA_ARGS__))
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001240# define DEBUG_CLEAN 1
1241#else
1242# define DEBUG_CLEAN 0
1243#endif
1244
1245#if DEBUG_EXPAND
1246static void debug_print_strings(const char *prefix, char **vv)
1247{
1248 indent();
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001249 fdprintf(2, "%s:\n", prefix);
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001250 while (*vv)
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001251 fdprintf(2, " '%s'\n", *vv++);
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001252}
1253#else
Denys Vlasenko28a105d2009-06-01 11:26:30 +02001254# define debug_print_strings(prefix, vv) ((void)0)
Denis Vlasenko0701dca2009-04-11 10:38:47 +00001255#endif
1256
1257
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001258/* Leak hunting. Use hush_leaktool.sh for post-processing.
1259 */
1260#if LEAK_HUNTING
1261static void *xxmalloc(int lineno, size_t size)
Denis Vlasenko90e485c2007-05-23 15:22:50 +00001262{
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001263 void *ptr = xmalloc((size + 0xff) & ~0xff);
1264 fdprintf(2, "line %d: malloc %p\n", lineno, ptr);
1265 return ptr;
1266}
1267static void *xxrealloc(int lineno, void *ptr, size_t size)
1268{
1269 ptr = xrealloc(ptr, (size + 0xff) & ~0xff);
1270 fdprintf(2, "line %d: realloc %p\n", lineno, ptr);
1271 return ptr;
1272}
1273static char *xxstrdup(int lineno, const char *str)
1274{
1275 char *ptr = xstrdup(str);
1276 fdprintf(2, "line %d: strdup %p\n", lineno, ptr);
1277 return ptr;
1278}
1279static void xxfree(void *ptr)
1280{
1281 fdprintf(2, "free %p\n", ptr);
1282 free(ptr);
1283}
Denys Vlasenko8391c482010-05-22 17:50:43 +02001284# define xmalloc(s) xxmalloc(__LINE__, s)
1285# define xrealloc(p, s) xxrealloc(__LINE__, p, s)
1286# define xstrdup(s) xxstrdup(__LINE__, s)
1287# define free(p) xxfree(p)
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001288#endif
1289
1290
1291/* Syntax and runtime errors. They always abort scripts.
1292 * In interactive use they usually discard unparsed and/or unexecuted commands
1293 * and return to the prompt.
1294 * HUSH_DEBUG >= 2 prints line number in this file where it was detected.
1295 */
1296#if HUSH_DEBUG < 2
Denys Vlasenko39701202017-08-02 19:44:05 +02001297# define msg_and_die_if_script(lineno, ...) msg_and_die_if_script(__VA_ARGS__)
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00001298# define syntax_error(lineno, msg) syntax_error(msg)
1299# define syntax_error_at(lineno, msg) syntax_error_at(msg)
1300# define syntax_error_unterm_ch(lineno, ch) syntax_error_unterm_ch(ch)
1301# define syntax_error_unterm_str(lineno, s) syntax_error_unterm_str(s)
1302# define syntax_error_unexpected_ch(lineno, ch) syntax_error_unexpected_ch(ch)
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001303#endif
1304
Denys Vlasenko39701202017-08-02 19:44:05 +02001305static void die_if_script(void)
1306{
1307 if (!G_interactive_fd) {
1308 if (G.last_exitcode) /* sometines it's 2, not 1 (bash compat) */
1309 xfunc_error_retval = G.last_exitcode;
1310 xfunc_die();
1311 }
1312}
1313
1314static void msg_and_die_if_script(unsigned lineno, const char *fmt, ...)
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001315{
Denis Vlasenkod68ae082009-04-09 20:41:34 +00001316 va_list p;
1317
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001318#if HUSH_DEBUG >= 2
1319 bb_error_msg("hush.c:%u", lineno);
1320#endif
Denis Vlasenkod68ae082009-04-09 20:41:34 +00001321 va_start(p, fmt);
1322 bb_verror_msg(fmt, p, NULL);
1323 va_end(p);
Denys Vlasenko39701202017-08-02 19:44:05 +02001324 die_if_script();
Mike Frysinger6379bb42009-03-28 18:55:03 +00001325}
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001326
Denys Vlasenkocecbc982011-03-30 18:54:52 +02001327static void syntax_error(unsigned lineno UNUSED_PARAM, const char *msg)
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001328{
1329 if (msg)
Denys Vlasenkocecbc982011-03-30 18:54:52 +02001330 bb_error_msg("syntax error: %s", msg);
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001331 else
Denys Vlasenkocecbc982011-03-30 18:54:52 +02001332 bb_error_msg("syntax error");
Denys Vlasenko39701202017-08-02 19:44:05 +02001333 die_if_script();
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001334}
1335
Denys Vlasenkocecbc982011-03-30 18:54:52 +02001336static void syntax_error_at(unsigned lineno UNUSED_PARAM, const char *msg)
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001337{
Denys Vlasenkocecbc982011-03-30 18:54:52 +02001338 bb_error_msg("syntax error at '%s'", msg);
Denys Vlasenko39701202017-08-02 19:44:05 +02001339 die_if_script();
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001340}
1341
Denys Vlasenkocecbc982011-03-30 18:54:52 +02001342static void syntax_error_unterm_str(unsigned lineno UNUSED_PARAM, const char *s)
Mike Frysinger6a46ab82009-06-01 14:14:36 -04001343{
Denys Vlasenkocecbc982011-03-30 18:54:52 +02001344 bb_error_msg("syntax error: unterminated %s", s);
Denys Vlasenko39701202017-08-02 19:44:05 +02001345//? source4.tests fails: in bash, echo ${^} in script does not terminate the script
1346// die_if_script();
Mike Frysinger6a46ab82009-06-01 14:14:36 -04001347}
1348
Denis Vlasenkod68ae082009-04-09 20:41:34 +00001349static void syntax_error_unterm_ch(unsigned lineno, char ch)
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001350{
Mike Frysinger6a46ab82009-06-01 14:14:36 -04001351 char msg[2] = { ch, '\0' };
1352 syntax_error_unterm_str(lineno, msg);
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001353}
1354
Denys Vlasenkocecbc982011-03-30 18:54:52 +02001355static void syntax_error_unexpected_ch(unsigned lineno UNUSED_PARAM, int ch)
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00001356{
1357 char msg[2];
1358 msg[0] = ch;
1359 msg[1] = '\0';
Denys Vlasenkob05bcaf2017-01-03 11:47:50 +01001360#if HUSH_DEBUG >= 2
1361 bb_error_msg("hush.c:%u", lineno);
1362#endif
Denys Vlasenkocecbc982011-03-30 18:54:52 +02001363 bb_error_msg("syntax error: unexpected %s", ch == EOF ? "EOF" : msg);
Denys Vlasenko39701202017-08-02 19:44:05 +02001364 die_if_script();
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00001365}
1366
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001367#if HUSH_DEBUG < 2
Denys Vlasenko39701202017-08-02 19:44:05 +02001368# undef msg_and_die_if_script
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001369# undef syntax_error
1370# undef syntax_error_at
Denis Vlasenkod68ae082009-04-09 20:41:34 +00001371# undef syntax_error_unterm_ch
1372# undef syntax_error_unterm_str
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00001373# undef syntax_error_unexpected_ch
Denis Vlasenko90e485c2007-05-23 15:22:50 +00001374#else
Denys Vlasenko39701202017-08-02 19:44:05 +02001375# define msg_and_die_if_script(...) msg_and_die_if_script(__LINE__, __VA_ARGS__)
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00001376# define syntax_error(msg) syntax_error(__LINE__, msg)
1377# define syntax_error_at(msg) syntax_error_at(__LINE__, msg)
1378# define syntax_error_unterm_ch(ch) syntax_error_unterm_ch(__LINE__, ch)
1379# define syntax_error_unterm_str(s) syntax_error_unterm_str(__LINE__, s)
1380# define syntax_error_unexpected_ch(ch) syntax_error_unexpected_ch(__LINE__, ch)
Denis Vlasenko90e485c2007-05-23 15:22:50 +00001381#endif
Eric Andersen25f27032001-04-26 23:22:31 +00001382
Denis Vlasenko552433b2009-04-04 19:29:21 +00001383
Mike Frysinger67c1c7b2009-04-24 06:26:18 +00001384#if ENABLE_HUSH_INTERACTIVE
1385static void cmdedit_update_prompt(void);
1386#else
Denys Vlasenko28a105d2009-06-01 11:26:30 +02001387# define cmdedit_update_prompt() ((void)0)
Mike Frysinger67c1c7b2009-04-24 06:26:18 +00001388#endif
1389
1390
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001391/* Utility functions
1392 */
Denis Vlasenko55789c62008-06-18 16:30:42 +00001393/* Replace each \x with x in place, return ptr past NUL. */
1394static char *unbackslash(char *src)
1395{
Denys Vlasenko71885402009-09-24 01:44:13 +02001396 char *dst = src = strchrnul(src, '\\');
Denis Vlasenko55789c62008-06-18 16:30:42 +00001397 while (1) {
1398 if (*src == '\\')
1399 src++;
1400 if ((*dst++ = *src++) == '\0')
1401 break;
1402 }
1403 return dst;
1404}
1405
Denis Vlasenko11fb7cf2009-03-20 10:13:08 +00001406static char **add_strings_to_strings(char **strings, char **add, int need_to_dup)
Denis Vlasenkod65ea392007-10-01 10:02:25 +00001407{
1408 int i;
1409 unsigned count1;
1410 unsigned count2;
1411 char **v;
1412
1413 v = strings;
1414 count1 = 0;
1415 if (v) {
1416 while (*v) {
1417 count1++;
1418 v++;
1419 }
1420 }
1421 count2 = 0;
1422 v = add;
1423 while (*v) {
1424 count2++;
1425 v++;
1426 }
1427 v = xrealloc(strings, (count1 + count2 + 1) * sizeof(char*));
1428 v[count1 + count2] = NULL;
1429 i = count2;
1430 while (--i >= 0)
Denis Vlasenko11fb7cf2009-03-20 10:13:08 +00001431 v[count1 + i] = (need_to_dup ? xstrdup(add[i]) : add[i]);
Denis Vlasenkod65ea392007-10-01 10:02:25 +00001432 return v;
1433}
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001434#if LEAK_HUNTING
Denis Vlasenkocc90f442009-04-08 16:40:34 +00001435static char **xx_add_strings_to_strings(int lineno, char **strings, char **add, int need_to_dup)
1436{
1437 char **ptr = add_strings_to_strings(strings, add, need_to_dup);
1438 fdprintf(2, "line %d: add_strings_to_strings %p\n", lineno, ptr);
1439 return ptr;
1440}
1441#define add_strings_to_strings(strings, add, need_to_dup) \
1442 xx_add_strings_to_strings(__LINE__, strings, add, need_to_dup)
1443#endif
Denis Vlasenkod65ea392007-10-01 10:02:25 +00001444
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02001445/* Note: takes ownership of "add" ptr (it is not strdup'ed) */
Denis Vlasenko22d10a02008-10-13 08:53:43 +00001446static char **add_string_to_strings(char **strings, char *add)
Denis Vlasenkod65ea392007-10-01 10:02:25 +00001447{
1448 char *v[2];
Denis Vlasenkod65ea392007-10-01 10:02:25 +00001449 v[0] = add;
1450 v[1] = NULL;
Denis Vlasenko11fb7cf2009-03-20 10:13:08 +00001451 return add_strings_to_strings(strings, v, /*dup:*/ 0);
Denis Vlasenko22d10a02008-10-13 08:53:43 +00001452}
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00001453#if LEAK_HUNTING
Denis Vlasenkocc90f442009-04-08 16:40:34 +00001454static char **xx_add_string_to_strings(int lineno, char **strings, char *add)
1455{
1456 char **ptr = add_string_to_strings(strings, add);
1457 fdprintf(2, "line %d: add_string_to_strings %p\n", lineno, ptr);
1458 return ptr;
1459}
1460#define add_string_to_strings(strings, add) \
1461 xx_add_string_to_strings(__LINE__, strings, add)
1462#endif
Denis Vlasenkod65ea392007-10-01 10:02:25 +00001463
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02001464static void free_strings(char **strings)
Denis Vlasenkod65ea392007-10-01 10:02:25 +00001465{
Denis Vlasenkoafd7a8d2008-10-09 16:29:44 +00001466 char **v;
1467
1468 if (!strings)
1469 return;
Denis Vlasenkoafd7a8d2008-10-09 16:29:44 +00001470 v = strings;
1471 while (*v) {
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02001472 free(*v);
1473 v++;
Denis Vlasenkod65ea392007-10-01 10:02:25 +00001474 }
Denis Vlasenkoafd7a8d2008-10-09 16:29:44 +00001475 free(strings);
Denis Vlasenkod65ea392007-10-01 10:02:25 +00001476}
1477
Denys Vlasenko2db74612017-07-07 22:07:28 +02001478static int fcntl_F_DUPFD(int fd, int avoid_fd)
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001479{
Denys Vlasenko2db74612017-07-07 22:07:28 +02001480 int newfd;
1481 repeat:
1482 newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001483 if (newfd < 0) {
Denys Vlasenko2db74612017-07-07 22:07:28 +02001484 if (errno == EBUSY)
1485 goto repeat;
1486 if (errno == EINTR)
1487 goto repeat;
1488 }
1489 return newfd;
1490}
1491
Denys Vlasenko657e9002017-07-30 23:34:04 +02001492static int xdup_CLOEXEC_and_close(int fd, int avoid_fd)
Denys Vlasenko2db74612017-07-07 22:07:28 +02001493{
1494 int newfd;
1495 repeat:
Denys Vlasenko657e9002017-07-30 23:34:04 +02001496 newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
Denys Vlasenko2db74612017-07-07 22:07:28 +02001497 if (newfd < 0) {
1498 if (errno == EBUSY)
1499 goto repeat;
1500 if (errno == EINTR)
1501 goto repeat;
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001502 /* fd was not open? */
1503 if (errno == EBADF)
1504 return fd;
1505 xfunc_die();
1506 }
Denys Vlasenko657e9002017-07-30 23:34:04 +02001507 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
1508 fcntl(newfd, F_SETFD, FD_CLOEXEC);
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001509 close(fd);
1510 return newfd;
1511}
1512
1513
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02001514/* Manipulating the list of open FILEs */
1515static FILE *remember_FILE(FILE *fp)
1516{
1517 if (fp) {
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02001518 struct FILE_list *n = xmalloc(sizeof(*n));
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02001519 n->next = G.FILE_list;
1520 G.FILE_list = n;
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001521 n->fp = fp;
1522 n->fd = fileno(fp);
1523 close_on_exec_on(n->fd);
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02001524 }
1525 return fp;
1526}
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02001527static void fclose_and_forget(FILE *fp)
1528{
1529 struct FILE_list **pp = &G.FILE_list;
1530 while (*pp) {
1531 struct FILE_list *cur = *pp;
1532 if (cur->fp == fp) {
1533 *pp = cur->next;
1534 free(cur);
1535 break;
1536 }
1537 pp = &cur->next;
1538 }
1539 fclose(fp);
1540}
Denys Vlasenko2db74612017-07-07 22:07:28 +02001541static int save_FILEs_on_redirect(int fd, int avoid_fd)
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001542{
1543 struct FILE_list *fl = G.FILE_list;
1544 while (fl) {
1545 if (fd == fl->fd) {
1546 /* We use it only on script files, they are all CLOEXEC */
Denys Vlasenko657e9002017-07-30 23:34:04 +02001547 fl->fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
Denys Vlasenko2db74612017-07-07 22:07:28 +02001548 debug_printf_redir("redirect_fd %d: matches a script fd, moving it to %d\n", fd, fl->fd);
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001549 return 1;
1550 }
1551 fl = fl->next;
1552 }
1553 return 0;
1554}
1555static void restore_redirected_FILEs(void)
1556{
1557 struct FILE_list *fl = G.FILE_list;
1558 while (fl) {
1559 int should_be = fileno(fl->fp);
1560 if (fl->fd != should_be) {
Denys Vlasenko2db74612017-07-07 22:07:28 +02001561 debug_printf_redir("restoring script fd from %d to %d\n", fl->fd, should_be);
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001562 xmove_fd(fl->fd, should_be);
1563 fl->fd = should_be;
1564 }
1565 fl = fl->next;
1566 }
1567}
Denys Vlasenko4ee824f2017-07-03 01:22:13 +02001568#if ENABLE_FEATURE_SH_STANDALONE && BB_MMU
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02001569static void close_all_FILE_list(void)
1570{
1571 struct FILE_list *fl = G.FILE_list;
1572 while (fl) {
1573 /* fclose would also free FILE object.
1574 * It is disastrous if we share memory with a vforked parent.
1575 * I'm not sure we never come here after vfork.
1576 * Therefore just close fd, nothing more.
1577 */
1578 /*fclose(fl->fp); - unsafe */
1579 close(fl->fd);
1580 fl = fl->next;
1581 }
1582}
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02001583#endif
Denys Vlasenko32fdf2f2017-07-31 04:32:06 +02001584static int fd_in_FILEs(int fd)
1585{
1586 struct FILE_list *fl = G.FILE_list;
1587 while (fl) {
1588 if (fl->fd == fd)
1589 return 1;
1590 fl = fl->next;
1591 }
1592 return 0;
1593}
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02001594
1595
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001596/* Helpers for setting new $n and restoring them back
1597 */
1598typedef struct save_arg_t {
1599 char *sv_argv0;
1600 char **sv_g_argv;
1601 int sv_g_argc;
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +01001602 IF_HUSH_SET(smallint sv_g_malloced;)
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001603} save_arg_t;
1604
1605static void save_and_replace_G_args(save_arg_t *sv, char **argv)
1606{
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001607 sv->sv_argv0 = argv[0];
1608 sv->sv_g_argv = G.global_argv;
1609 sv->sv_g_argc = G.global_argc;
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +01001610 IF_HUSH_SET(sv->sv_g_malloced = G.global_args_malloced;)
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001611
1612 argv[0] = G.global_argv[0]; /* retain $0 */
1613 G.global_argv = argv;
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +01001614 IF_HUSH_SET(G.global_args_malloced = 0;)
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001615
Denys Vlasenkod4e4fdb2017-07-03 21:31:16 +02001616 G.global_argc = 1 + string_array_len(argv + 1);
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001617}
1618
1619static void restore_G_args(save_arg_t *sv, char **argv)
1620{
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +01001621#if ENABLE_HUSH_SET
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001622 if (G.global_args_malloced) {
1623 /* someone ran "set -- arg1 arg2 ...", undo */
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +01001624 char **pp = G.global_argv;
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001625 while (*++pp) /* note: does not free $0 */
1626 free(*pp);
1627 free(G.global_argv);
1628 }
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +01001629#endif
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001630 argv[0] = sv->sv_argv0;
1631 G.global_argv = sv->sv_g_argv;
1632 G.global_argc = sv->sv_g_argc;
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +01001633 IF_HUSH_SET(G.global_args_malloced = sv->sv_g_malloced;)
Denis Vlasenko270b1c32009-04-17 18:54:50 +00001634}
1635
1636
Denis Vlasenkod5762932009-03-31 11:22:57 +00001637/* Basic theory of signal handling in shell
1638 * ========================================
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001639 * This does not describe what hush does, rather, it is current understanding
1640 * what it _should_ do. If it doesn't, it's a bug.
Denis Vlasenkod5762932009-03-31 11:22:57 +00001641 * http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#trap
1642 *
1643 * Signals are handled only after each pipe ("cmd | cmd | cmd" thing)
1644 * is finished or backgrounded. It is the same in interactive and
1645 * non-interactive shells, and is the same regardless of whether
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001646 * a user trap handler is installed or a shell special one is in effect.
Denys Vlasenko69b1cef2009-09-21 10:21:44 +02001647 * ^C or ^Z from keyboard seems to execute "at once" because it usually
Denis Vlasenkod5762932009-03-31 11:22:57 +00001648 * backgrounds (i.e. stops) or kills all members of currently running
1649 * pipe.
1650 *
Denys Vlasenko8bd810b2013-11-28 01:50:01 +01001651 * Wait builtin is interruptible by signals for which user trap is set
Denis Vlasenkod5762932009-03-31 11:22:57 +00001652 * or by SIGINT in interactive shell.
1653 *
1654 * Trap handlers will execute even within trap handlers. (right?)
1655 *
Denys Vlasenkoe89a2412010-01-12 15:19:31 +01001656 * User trap handlers are forgotten when subshell ("(cmd)") is entered,
1657 * except for handlers set to '' (empty string).
Denis Vlasenkod5762932009-03-31 11:22:57 +00001658 *
1659 * If job control is off, backgrounded commands ("cmd &")
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001660 * have SIGINT, SIGQUIT set to SIG_IGN.
Denis Vlasenkod5762932009-03-31 11:22:57 +00001661 *
Denys Vlasenko28a105d2009-06-01 11:26:30 +02001662 * Commands which are run in command substitution ("`cmd`")
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001663 * have SIGTTIN, SIGTTOU, SIGTSTP set to SIG_IGN.
Denis Vlasenkod5762932009-03-31 11:22:57 +00001664 *
Denys Vlasenko4b7db4f2009-05-29 10:39:06 +02001665 * Ordinary commands have signals set to SIG_IGN/DFL as inherited
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001666 * by the shell from its parent.
Denis Vlasenkod5762932009-03-31 11:22:57 +00001667 *
Denys Vlasenko28a105d2009-06-01 11:26:30 +02001668 * Signals which differ from SIG_DFL action
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001669 * (note: child (i.e., [v]forked) shell is not an interactive shell):
Denis Vlasenkod5762932009-03-31 11:22:57 +00001670 *
1671 * SIGQUIT: ignore
1672 * SIGTERM (interactive): ignore
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001673 * SIGHUP (interactive):
1674 * send SIGCONT to stopped jobs, send SIGHUP to all jobs and exit
Denis Vlasenkod5762932009-03-31 11:22:57 +00001675 * SIGTTIN, SIGTTOU, SIGTSTP (if job control is on): ignore
Denis Vlasenkoc4ada792009-04-15 23:29:00 +00001676 * Note that ^Z is handled not by trapping SIGTSTP, but by seeing
1677 * that all pipe members are stopped. Try this in bash:
1678 * while :; do :; done - ^Z does not background it
1679 * (while :; do :; done) - ^Z backgrounds it
Denis Vlasenkod5762932009-03-31 11:22:57 +00001680 * SIGINT (interactive): wait for last pipe, ignore the rest
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001681 * of the command line, show prompt. NB: ^C does not send SIGINT
1682 * to interactive shell while shell is waiting for a pipe,
1683 * since shell is bg'ed (is not in foreground process group).
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001684 * Example 1: this waits 5 sec, but does not execute ls:
1685 * "echo $$; sleep 5; ls -l" + "kill -INT <pid>"
1686 * Example 2: this does not wait and does not execute ls:
1687 * "echo $$; sleep 5 & wait; ls -l" + "kill -INT <pid>"
1688 * Example 3: this does not wait 5 sec, but executes ls:
1689 * "sleep 5; ls -l" + press ^C
Denys Vlasenkob8709032011-05-08 21:20:01 +02001690 * Example 4: this does not wait and does not execute ls:
1691 * "sleep 5 & wait; ls -l" + press ^C
Denis Vlasenkod5762932009-03-31 11:22:57 +00001692 *
1693 * (What happens to signals which are IGN on shell start?)
1694 * (What happens with signal mask on shell start?)
1695 *
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001696 * Old implementation
1697 * ==================
Denis Vlasenkod5762932009-03-31 11:22:57 +00001698 * We use in-kernel pending signal mask to determine which signals were sent.
1699 * We block all signals which we don't want to take action immediately,
1700 * i.e. we block all signals which need to have special handling as described
1701 * above, and all signals which have traps set.
1702 * After each pipe execution, we extract any pending signals via sigtimedwait()
1703 * and act on them.
1704 *
Denys Vlasenko10c01312011-05-11 11:49:21 +02001705 * unsigned special_sig_mask: a mask of such "special" signals
Denis Vlasenkod5762932009-03-31 11:22:57 +00001706 * sigset_t blocked_set: current blocked signal set
1707 *
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001708 * "trap - SIGxxx":
Denys Vlasenko10c01312011-05-11 11:49:21 +02001709 * clear bit in blocked_set unless it is also in special_sig_mask
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001710 * "trap 'cmd' SIGxxx":
1711 * set bit in blocked_set (even if 'cmd' is '')
Denis Vlasenkod5762932009-03-31 11:22:57 +00001712 * after [v]fork, if we plan to be a shell:
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00001713 * unblock signals with special interactive handling
1714 * (child shell is not interactive),
Denys Vlasenkoe89a2412010-01-12 15:19:31 +01001715 * unset all traps except '' (note: regardless of child shell's type - {}, (), etc)
Denis Vlasenkod5762932009-03-31 11:22:57 +00001716 * after [v]fork, if we plan to exec:
Denys Vlasenko69b1cef2009-09-21 10:21:44 +02001717 * POSIX says fork clears pending signal mask in child - no need to clear it.
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001718 * Restore blocked signal set to one inherited by shell just prior to exec.
Denis Vlasenkod5762932009-03-31 11:22:57 +00001719 *
Denis Vlasenko7566bae2009-03-31 17:24:49 +00001720 * Note: as a result, we do not use signal handlers much. The only uses
Denys Vlasenko8d7be232009-05-25 16:38:32 +02001721 * are to count SIGCHLDs
Denis Vlasenko7566bae2009-03-31 17:24:49 +00001722 * and to restore tty pgrp on signal-induced exit.
Denys Vlasenko4ea0ca82009-09-25 12:58:37 +02001723 *
Denys Vlasenko67f71862009-09-25 14:21:06 +02001724 * Note 2 (compat):
Denys Vlasenko4ea0ca82009-09-25 12:58:37 +02001725 * Standard says "When a subshell is entered, traps that are not being ignored
1726 * are set to the default actions". bash interprets it so that traps which
Denys Vlasenkoe89a2412010-01-12 15:19:31 +01001727 * are set to '' (ignore) are NOT reset to defaults. We do the same.
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001728 *
1729 * Problem: the above approach makes it unwieldy to catch signals while
Denys Vlasenkoe95738f2013-07-08 03:13:08 +02001730 * we are in read builtin, or while we read commands from stdin:
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001731 * masked signals are not visible!
1732 *
1733 * New implementation
1734 * ==================
1735 * We record each signal we are interested in by installing signal handler
1736 * for them - a bit like emulating kernel pending signal mask in userspace.
1737 * We are interested in: signals which need to have special handling
1738 * as described above, and all signals which have traps set.
Denys Vlasenko8bd810b2013-11-28 01:50:01 +01001739 * Signals are recorded in pending_set.
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001740 * After each pipe execution, we extract any pending signals
1741 * and act on them.
1742 *
1743 * unsigned special_sig_mask: a mask of shell-special signals.
1744 * unsigned fatal_sig_mask: a mask of signals on which we restore tty pgrp.
1745 * char *traps[sig] if trap for sig is set (even if it's '').
1746 * sigset_t pending_set: set of sigs we received.
1747 *
1748 * "trap - SIGxxx":
1749 * if sig is in special_sig_mask, set handler back to:
1750 * record_pending_signo, or to IGN if it's a tty stop signal
1751 * if sig is in fatal_sig_mask, set handler back to sigexit.
1752 * else: set handler back to SIG_DFL
1753 * "trap 'cmd' SIGxxx":
1754 * set handler to record_pending_signo.
1755 * "trap '' SIGxxx":
1756 * set handler to SIG_IGN.
1757 * after [v]fork, if we plan to be a shell:
1758 * set signals with special interactive handling to SIG_DFL
1759 * (because child shell is not interactive),
1760 * unset all traps except '' (note: regardless of child shell's type - {}, (), etc)
1761 * after [v]fork, if we plan to exec:
1762 * POSIX says fork clears pending signal mask in child - no need to clear it.
1763 *
1764 * To make wait builtin interruptible, we handle SIGCHLD as special signal,
1765 * otherwise (if we leave it SIG_DFL) sigsuspend in wait builtin will not wake up on it.
1766 *
1767 * Note (compat):
1768 * Standard says "When a subshell is entered, traps that are not being ignored
1769 * are set to the default actions". bash interprets it so that traps which
1770 * are set to '' (ignore) are NOT reset to defaults. We do the same.
Denis Vlasenkod5762932009-03-31 11:22:57 +00001771 */
Denis Vlasenkoe4bd4f22009-04-17 13:52:51 +00001772enum {
1773 SPECIAL_INTERACTIVE_SIGS = 0
Denis Vlasenkoe4bd4f22009-04-17 13:52:51 +00001774 | (1 << SIGTERM)
Denis Vlasenkoe4bd4f22009-04-17 13:52:51 +00001775 | (1 << SIGINT)
Denis Vlasenkoc8653f62009-04-27 23:29:14 +00001776 | (1 << SIGHUP)
1777 ,
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001778 SPECIAL_JOBSTOP_SIGS = 0
Mike Frysinger38478a62009-05-20 04:48:06 -04001779#if ENABLE_HUSH_JOB
Denis Vlasenkoc8653f62009-04-27 23:29:14 +00001780 | (1 << SIGTTIN)
1781 | (1 << SIGTTOU)
1782 | (1 << SIGTSTP)
1783#endif
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001784 ,
Denis Vlasenkoe4bd4f22009-04-17 13:52:51 +00001785};
Denis Vlasenkod5762932009-03-31 11:22:57 +00001786
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001787static void record_pending_signo(int sig)
Denys Vlasenko54e9e122011-05-09 00:52:15 +02001788{
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001789 sigaddset(&G.pending_set, sig);
Denys Vlasenko8d7be232009-05-25 16:38:32 +02001790#if ENABLE_HUSH_FAST
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001791 if (sig == SIGCHLD) {
1792 G.count_SIGCHLD++;
Denys Vlasenko8d7be232009-05-25 16:38:32 +02001793//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 +02001794 }
Denys Vlasenko8d7be232009-05-25 16:38:32 +02001795#endif
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001796}
Denis Vlasenko7566bae2009-03-31 17:24:49 +00001797
Denys Vlasenko0806e402011-05-12 23:06:20 +02001798static sighandler_t install_sighandler(int sig, sighandler_t handler)
1799{
1800 struct sigaction old_sa;
1801
1802 /* We could use signal() to install handlers... almost:
1803 * except that we need to mask ALL signals while handlers run.
1804 * I saw signal nesting in strace, race window isn't small.
1805 * SA_RESTART is also needed, but in Linux, signal()
1806 * sets SA_RESTART too.
1807 */
1808 /* memset(&G.sa, 0, sizeof(G.sa)); - already done */
1809 /* sigfillset(&G.sa.sa_mask); - already done */
1810 /* G.sa.sa_flags = SA_RESTART; - already done */
1811 G.sa.sa_handler = handler;
1812 sigaction(sig, &G.sa, &old_sa);
1813 return old_sa.sa_handler;
1814}
1815
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02001816static void hush_exit(int exitcode) NORETURN;
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02001817
Denys Vlasenkob6afcc72016-12-12 16:30:20 +01001818static void restore_ttypgrp_and__exit(void) NORETURN;
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02001819static void restore_ttypgrp_and__exit(void)
1820{
1821 /* xfunc has failed! die die die */
1822 /* no EXIT traps, this is an escape hatch! */
1823 G.exiting = 1;
1824 hush_exit(xfunc_error_retval);
1825}
1826
Denys Vlasenkob6afcc72016-12-12 16:30:20 +01001827#if ENABLE_HUSH_JOB
1828
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02001829/* Needed only on some libc:
1830 * It was observed that on exit(), fgetc'ed buffered data
1831 * gets "unwound" via lseek(fd, -NUM, SEEK_CUR).
1832 * With the net effect that even after fork(), not vfork(),
1833 * exit() in NOEXECed applet in "sh SCRIPT":
1834 * noexec_applet_here
1835 * echo END_OF_SCRIPT
1836 * lseeks fd in input FILE object from EOF to "e" in "echo END_OF_SCRIPT".
1837 * This makes "echo END_OF_SCRIPT" executed twice.
Denys Vlasenko39701202017-08-02 19:44:05 +02001838 * Similar problems can be seen with msg_and_die_if_script() -> xfunc_die()
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02001839 * and in `cmd` handling.
1840 * If set as die_func(), this makes xfunc_die() exit via _exit(), not exit():
1841 */
Denys Vlasenkob6afcc72016-12-12 16:30:20 +01001842static void fflush_and__exit(void) NORETURN;
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02001843static void fflush_and__exit(void)
1844{
1845 fflush_all();
1846 _exit(xfunc_error_retval);
1847}
1848
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00001849/* After [v]fork, in child: do not restore tty pgrp on xfunc death */
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02001850# define disable_restore_tty_pgrp_on_exit() (die_func = fflush_and__exit)
Denis Vlasenko25af86f2009-04-07 13:29:27 +00001851/* After [v]fork, in parent: restore tty pgrp on xfunc death */
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02001852# define enable_restore_tty_pgrp_on_exit() (die_func = restore_ttypgrp_and__exit)
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00001853
Denis Vlasenko54e7ffb2007-04-21 00:03:36 +00001854/* Restores tty foreground process group, and exits.
1855 * May be called as signal handler for fatal signal
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00001856 * (will resend signal to itself, producing correct exit state)
Denis Vlasenko54e7ffb2007-04-21 00:03:36 +00001857 * or called directly with -EXITCODE.
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02001858 * We also call it if xfunc is exiting.
1859 */
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00001860static void sigexit(int sig) NORETURN;
Denis Vlasenko54e7ffb2007-04-21 00:03:36 +00001861static void sigexit(int sig)
1862{
Denis Vlasenkoabedaac2009-03-31 12:03:40 +00001863 /* Careful: we can end up here after [v]fork. Do not restore
Denis Vlasenko7b830e72009-03-31 13:05:32 +00001864 * tty pgrp then, only top-level shell process does that */
Denys Vlasenkoebc1ee22011-05-12 10:59:18 +02001865 if (G_saved_tty_pgrp && getpid() == G.root_pid) {
1866 /* Disable all signals: job control, SIGPIPE, etc.
1867 * Mostly paranoid measure, to prevent infinite SIGTTOU.
1868 */
1869 sigprocmask_allsigs(SIG_BLOCK);
Mike Frysinger38478a62009-05-20 04:48:06 -04001870 tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp);
Denys Vlasenkoebc1ee22011-05-12 10:59:18 +02001871 }
Denis Vlasenko54e7ffb2007-04-21 00:03:36 +00001872
1873 /* Not a signal, just exit */
1874 if (sig <= 0)
1875 _exit(- sig);
1876
Denis Vlasenko400d8bb2008-02-24 13:36:01 +00001877 kill_myself_with_sig(sig); /* does not return */
Denis Vlasenko54e7ffb2007-04-21 00:03:36 +00001878}
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00001879#else
1880
Denys Vlasenko8391c482010-05-22 17:50:43 +02001881# define disable_restore_tty_pgrp_on_exit() ((void)0)
1882# define enable_restore_tty_pgrp_on_exit() ((void)0)
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00001883
Denis Vlasenkoe0755e52009-04-03 21:16:45 +00001884#endif
Denis Vlasenkob81b3df2007-04-28 16:48:04 +00001885
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001886static sighandler_t pick_sighandler(unsigned sig)
1887{
1888 sighandler_t handler = SIG_DFL;
1889 if (sig < sizeof(unsigned)*8) {
1890 unsigned sigmask = (1 << sig);
1891
1892#if ENABLE_HUSH_JOB
Denys Vlasenko75e77de2011-05-12 13:12:47 +02001893 /* is sig fatal? */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001894 if (G_fatal_sig_mask & sigmask)
1895 handler = sigexit;
Denys Vlasenko75e77de2011-05-12 13:12:47 +02001896 else
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001897#endif
1898 /* sig has special handling? */
Denys Vlasenko75e77de2011-05-12 13:12:47 +02001899 if (G.special_sig_mask & sigmask) {
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001900 handler = record_pending_signo;
Denys Vlasenko0c40a732011-05-12 09:50:12 +02001901 /* TTIN/TTOU/TSTP can't be set to record_pending_signo
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001902 * in order to ignore them: they will be raised
Denys Vlasenkof58f7052011-05-12 02:10:33 +02001903 * in an endless loop when we try to do some
1904 * terminal ioctls! We do have to _ignore_ these.
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001905 */
1906 if (SPECIAL_JOBSTOP_SIGS & sigmask)
1907 handler = SIG_IGN;
Denys Vlasenko0c40a732011-05-12 09:50:12 +02001908 }
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001909 }
1910 return handler;
1911}
1912
Mike Frysinger9f8128f2009-03-29 23:49:37 +00001913/* Restores tty foreground process group, and exits. */
Mike Frysinger9f8128f2009-03-29 23:49:37 +00001914static void hush_exit(int exitcode)
1915{
Denys Vlasenkobede2152011-09-04 16:12:33 +02001916#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
1917 save_history(G.line_input_state);
1918#endif
1919
Denys Vlasenko8ee2ada2011-02-07 02:03:51 +01001920 fflush_all();
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001921 if (G.exiting <= 0 && G_traps && G_traps[0] && G_traps[0][0]) {
Denys Vlasenko27c56f12010-09-07 09:56:34 +02001922 char *argv[3];
1923 /* argv[0] is unused */
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001924 argv[1] = G_traps[0];
Denys Vlasenko27c56f12010-09-07 09:56:34 +02001925 argv[2] = NULL;
Denys Vlasenkoa110c902010-09-12 15:38:04 +02001926 G.exiting = 1; /* prevent EXIT trap recursion */
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001927 /* Note: G_traps[0] is not cleared!
Denys Vlasenkode8c3f62010-09-12 16:13:44 +02001928 * "trap" will still show it, if executed
1929 * in the handler */
1930 builtin_eval(argv);
Denis Vlasenkod5762932009-03-31 11:22:57 +00001931 }
Mike Frysinger9f8128f2009-03-29 23:49:37 +00001932
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01001933#if ENABLE_FEATURE_CLEAN_UP
1934 {
1935 struct variable *cur_var;
1936 if (G.cwd != bb_msg_unknown)
1937 free((char*)G.cwd);
1938 cur_var = G.top_var;
1939 while (cur_var) {
1940 struct variable *tmp = cur_var;
1941 if (!cur_var->max_len)
1942 free(cur_var->varstr);
1943 cur_var = cur_var->next;
1944 free(tmp);
1945 }
1946 }
1947#endif
1948
Denys Vlasenko8131eea2009-11-02 14:19:51 +01001949 fflush_all();
Denys Vlasenko215b0ca2016-08-19 18:23:56 +02001950#if ENABLE_HUSH_JOB
Denis Vlasenkoabedaac2009-03-31 12:03:40 +00001951 sigexit(- (exitcode & 0xff));
1952#else
Denys Vlasenko215b0ca2016-08-19 18:23:56 +02001953 _exit(exitcode);
Denis Vlasenkoabedaac2009-03-31 12:03:40 +00001954#endif
Mike Frysinger9f8128f2009-03-29 23:49:37 +00001955}
1956
Denys Vlasenkoacd5bc82010-09-12 15:05:39 +02001957
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001958//TODO: return a mask of ALL handled sigs?
1959static int check_and_run_traps(void)
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00001960{
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00001961 int last_sig = 0;
1962
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00001963 while (1) {
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001964 int sig;
Denys Vlasenko80542ba2011-05-08 21:23:43 +02001965
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001966 if (sigisemptyset(&G.pending_set))
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00001967 break;
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001968 sig = 0;
1969 do {
1970 sig++;
1971 if (sigismember(&G.pending_set, sig)) {
1972 sigdelset(&G.pending_set, sig);
1973 goto got_sig;
1974 }
1975 } while (sig < NSIG);
1976 break;
Denys Vlasenkob8709032011-05-08 21:20:01 +02001977 got_sig:
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001978 if (G_traps && G_traps[sig]) {
Denys Vlasenko04b46bc2016-10-01 22:28:03 +02001979 debug_printf_exec("%s: sig:%d handler:'%s'\n", __func__, sig, G.traps[sig]);
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001980 if (G_traps[sig][0]) {
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00001981 /* We have user-defined handler */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02001982 smalluint save_rcode;
Denys Vlasenko27c56f12010-09-07 09:56:34 +02001983 char *argv[3];
1984 /* argv[0] is unused */
Denys Vlasenko7a85c602017-01-08 17:40:18 +01001985 argv[1] = G_traps[sig];
Denys Vlasenko27c56f12010-09-07 09:56:34 +02001986 argv[2] = NULL;
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00001987 save_rcode = G.last_exitcode;
1988 builtin_eval(argv);
Denys Vlasenko8660aeb2016-11-24 17:44:02 +01001989//FIXME: shouldn't it be set to 128 + sig instead?
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00001990 G.last_exitcode = save_rcode;
Denys Vlasenkob8709032011-05-08 21:20:01 +02001991 last_sig = sig;
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00001992 } /* else: "" trap, ignoring signal */
1993 continue;
1994 }
1995 /* not a trap: special action */
1996 switch (sig) {
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00001997 case SIGINT:
Denys Vlasenko04b46bc2016-10-01 22:28:03 +02001998 debug_printf_exec("%s: sig:%d default SIGINT handler\n", __func__, sig);
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00001999 G.flag_SIGINT = 1;
Denys Vlasenkob8709032011-05-08 21:20:01 +02002000 last_sig = sig;
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002001 break;
2002#if ENABLE_HUSH_JOB
2003 case SIGHUP: {
Denys Vlasenko49e6bf22017-08-04 14:28:16 +02002004//TODO: why are we doing this? ash and dash don't do this,
2005//they have no handler for SIGHUP at all,
2006//they rely on kernel to send SIGHUP+SIGCONT to orphaned process groups
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002007 struct pipe *job;
Denys Vlasenko04b46bc2016-10-01 22:28:03 +02002008 debug_printf_exec("%s: sig:%d default SIGHUP handler\n", __func__, sig);
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002009 /* bash is observed to signal whole process groups,
2010 * not individual processes */
2011 for (job = G.job_list; job; job = job->next) {
2012 if (job->pgrp <= 0)
2013 continue;
2014 debug_printf_exec("HUPing pgrp %d\n", job->pgrp);
2015 if (kill(- job->pgrp, SIGHUP) == 0)
2016 kill(- job->pgrp, SIGCONT);
2017 }
2018 sigexit(SIGHUP);
2019 }
2020#endif
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002021#if ENABLE_HUSH_FAST
2022 case SIGCHLD:
Denys Vlasenko04b46bc2016-10-01 22:28:03 +02002023 debug_printf_exec("%s: sig:%d default SIGCHLD handler\n", __func__, sig);
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002024 G.count_SIGCHLD++;
2025//bb_error_msg("[%d] check_and_run_traps: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
2026 /* Note:
Denys Vlasenko10ad6222017-04-17 16:13:32 +02002027 * We don't do 'last_sig = sig' here -> NOT returning this sig.
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002028 * This simplifies wait builtin a bit.
2029 */
2030 break;
2031#endif
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002032 default: /* ignored: */
Denys Vlasenko04b46bc2016-10-01 22:28:03 +02002033 debug_printf_exec("%s: sig:%d default handling is to ignore\n", __func__, sig);
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002034 /* SIGTERM, SIGQUIT, SIGTTIN, SIGTTOU, SIGTSTP */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002035 /* Note:
Denys Vlasenko10ad6222017-04-17 16:13:32 +02002036 * We don't do 'last_sig = sig' here -> NOT returning this sig.
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002037 * Example: wait is not interrupted by TERM
Denys Vlasenkob8709032011-05-08 21:20:01 +02002038 * in interactive shell, because TERM is ignored.
2039 */
Denis Vlasenko6b9e0532009-04-18 01:23:21 +00002040 break;
2041 }
2042 }
2043 return last_sig;
2044}
2045
Denis Vlasenkob81b3df2007-04-28 16:48:04 +00002046
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02002047static const char *get_cwd(int force)
Eric Andersen9ffb7dd2001-05-19 03:00:46 +00002048{
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02002049 if (force || G.cwd == NULL) {
2050 /* xrealloc_getcwd_or_warn(arg) calls free(arg),
2051 * we must not try to free(bb_msg_unknown) */
2052 if (G.cwd == bb_msg_unknown)
2053 G.cwd = NULL;
2054 G.cwd = xrealloc_getcwd_or_warn((char *)G.cwd);
2055 if (!G.cwd)
2056 G.cwd = bb_msg_unknown;
2057 }
Denis Vlasenko87a86552008-07-29 19:43:10 +00002058 return G.cwd;
Eric Andersen9ffb7dd2001-05-19 03:00:46 +00002059}
2060
Denis Vlasenko83506862007-11-23 13:11:42 +00002061
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002062/*
2063 * Shell and environment variable support
2064 */
Denys Vlasenko27c56f12010-09-07 09:56:34 +02002065static struct variable **get_ptr_to_local_var(const char *name, unsigned len)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002066{
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002067 struct variable **pp;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002068 struct variable *cur;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002069
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002070 pp = &G.top_var;
2071 while ((cur = *pp) != NULL) {
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002072 if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=')
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002073 return pp;
2074 pp = &cur->next;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002075 }
2076 return NULL;
2077}
2078
Denys Vlasenko03dad222010-01-12 23:29:57 +01002079static const char* FAST_FUNC get_local_var_value(const char *name)
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002080{
Denys Vlasenko29082232010-07-16 13:52:32 +02002081 struct variable **vpp;
Denys Vlasenko27c56f12010-09-07 09:56:34 +02002082 unsigned len = strlen(name);
Denys Vlasenko29082232010-07-16 13:52:32 +02002083
2084 if (G.expanded_assignments) {
2085 char **cpp = G.expanded_assignments;
Denys Vlasenko29082232010-07-16 13:52:32 +02002086 while (*cpp) {
2087 char *cp = *cpp;
2088 if (strncmp(cp, name, len) == 0 && cp[len] == '=')
2089 return cp + len + 1;
2090 cpp++;
2091 }
2092 }
2093
Denys Vlasenko27c56f12010-09-07 09:56:34 +02002094 vpp = get_ptr_to_local_var(name, len);
Denys Vlasenko29082232010-07-16 13:52:32 +02002095 if (vpp)
Denys Vlasenko27c56f12010-09-07 09:56:34 +02002096 return (*vpp)->varstr + len + 1;
Denys Vlasenko29082232010-07-16 13:52:32 +02002097
Denys Vlasenkodea47882009-10-09 15:40:49 +02002098 if (strcmp(name, "PPID") == 0)
2099 return utoa(G.root_ppid);
2100 // bash compat: UID? EUID?
Denys Vlasenko20b3d142009-10-09 20:59:39 +02002101#if ENABLE_HUSH_RANDOM_SUPPORT
Denys Vlasenko27c56f12010-09-07 09:56:34 +02002102 if (strcmp(name, "RANDOM") == 0)
Denys Vlasenko20b3d142009-10-09 20:59:39 +02002103 return utoa(next_random(&G.random_gen));
2104#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002105 return NULL;
2106}
2107
2108/* str holds "NAME=VAL" and is expected to be malloced.
Mike Frysinger6379bb42009-03-28 18:55:03 +00002109 * We take ownership of it.
Mike Frysinger6379bb42009-03-28 18:55:03 +00002110 */
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002111#define SETFLAG_EXPORT (1 << 0)
2112#define SETFLAG_UNEXPORT (1 << 1)
2113#define SETFLAG_MAKE_RO (1 << 2)
2114#define SETFLAG_LOCAL_SHIFT 3
2115static int set_local_var(char *str, unsigned flags)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002116{
Denys Vlasenko295fef82009-06-03 12:47:26 +02002117 struct variable **var_pp;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002118 struct variable *cur;
Denys Vlasenkoa7693902016-10-03 15:01:06 +02002119 char *free_me = NULL;
Denis Vlasenko950bd722009-04-21 11:23:56 +00002120 char *eq_sign;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002121 int name_len;
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002122 IF_HUSH_LOCAL(unsigned local_lvl = (flags >> SETFLAG_LOCAL_SHIFT);)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002123
Denis Vlasenko950bd722009-04-21 11:23:56 +00002124 eq_sign = strchr(str, '=');
2125 if (!eq_sign) { /* not expected to ever happen? */
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002126 free(str);
2127 return -1;
2128 }
2129
Denis Vlasenko950bd722009-04-21 11:23:56 +00002130 name_len = eq_sign - str + 1; /* including '=' */
Denys Vlasenko295fef82009-06-03 12:47:26 +02002131 var_pp = &G.top_var;
2132 while ((cur = *var_pp) != NULL) {
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002133 if (strncmp(cur->varstr, str, name_len) != 0) {
Denys Vlasenko295fef82009-06-03 12:47:26 +02002134 var_pp = &cur->next;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002135 continue;
2136 }
Denys Vlasenkoa7693902016-10-03 15:01:06 +02002137
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002138 /* We found an existing var with this name */
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002139 if (cur->flg_read_only) {
Denys Vlasenko6b48e1f2017-07-17 21:31:17 +02002140 bb_error_msg("%s: readonly variable", str);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002141 free(str);
Denys Vlasenko5b2cc0a2017-07-18 02:44:06 +02002142//NOTE: in bash, assignment in "export READONLY_VAR=Z" fails, and sets $?=1,
2143//but export per se succeeds (does put the var in env). We don't mimic that.
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002144 return -1;
2145 }
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002146 if (flags & SETFLAG_UNEXPORT) { // && cur->flg_export ?
Denis Vlasenko950bd722009-04-21 11:23:56 +00002147 debug_printf_env("%s: unsetenv '%s'\n", __func__, str);
2148 *eq_sign = '\0';
2149 unsetenv(str);
2150 *eq_sign = '=';
2151 }
Denys Vlasenko295fef82009-06-03 12:47:26 +02002152#if ENABLE_HUSH_LOCAL
2153 if (cur->func_nest_level < local_lvl) {
2154 /* New variable is declared as local,
2155 * and existing one is global, or local
2156 * from enclosing function.
2157 * Remove and save old one: */
2158 *var_pp = cur->next;
2159 cur->next = *G.shadowed_vars_pp;
2160 *G.shadowed_vars_pp = cur;
2161 /* bash 3.2.33(1) and exported vars:
2162 * # export z=z
2163 * # f() { local z=a; env | grep ^z; }
2164 * # f
2165 * z=a
2166 * # env | grep ^z
2167 * z=z
2168 */
2169 if (cur->flg_export)
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002170 flags |= SETFLAG_EXPORT;
Denys Vlasenko295fef82009-06-03 12:47:26 +02002171 break;
2172 }
2173#endif
Denis Vlasenko950bd722009-04-21 11:23:56 +00002174 if (strcmp(cur->varstr + name_len, eq_sign + 1) == 0) {
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002175 free_and_exp:
2176 free(str);
2177 goto exp;
2178 }
Denys Vlasenko295fef82009-06-03 12:47:26 +02002179 if (cur->max_len != 0) {
2180 if (cur->max_len >= strlen(str)) {
2181 /* This one is from startup env, reuse space */
2182 strcpy(cur->varstr, str);
2183 goto free_and_exp;
2184 }
Denys Vlasenkoa7693902016-10-03 15:01:06 +02002185 /* Can't reuse */
2186 cur->max_len = 0;
2187 goto set_str_and_exp;
Denys Vlasenko295fef82009-06-03 12:47:26 +02002188 }
Denys Vlasenkoa7693902016-10-03 15:01:06 +02002189 /* max_len == 0 signifies "malloced" var, which we can
2190 * (and have to) free. But we can't free(cur->varstr) here:
2191 * if cur->flg_export is 1, it is in the environment.
2192 * We should either unsetenv+free, or wait until putenv,
2193 * then putenv(new)+free(old).
2194 */
2195 free_me = cur->varstr;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002196 goto set_str_and_exp;
2197 }
2198
Denys Vlasenko295fef82009-06-03 12:47:26 +02002199 /* Not found - create new variable struct */
2200 cur = xzalloc(sizeof(*cur));
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002201 IF_HUSH_LOCAL(cur->func_nest_level = local_lvl;)
Denys Vlasenko295fef82009-06-03 12:47:26 +02002202 cur->next = *var_pp;
2203 *var_pp = cur;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002204
2205 set_str_and_exp:
2206 cur->varstr = str;
2207 exp:
Denys Vlasenko1e660422017-07-17 21:10:50 +02002208#if !BB_MMU || ENABLE_HUSH_READONLY
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002209 if (flags & SETFLAG_MAKE_RO) {
2210 cur->flg_read_only = 1;
Denys Vlasenko1e660422017-07-17 21:10:50 +02002211 }
2212#endif
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002213 if (flags & SETFLAG_EXPORT)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002214 cur->flg_export = 1;
Mike Frysinger67c1c7b2009-04-24 06:26:18 +00002215 if (name_len == 4 && cur->varstr[0] == 'P' && cur->varstr[1] == 'S')
2216 cmdedit_update_prompt();
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002217 if (cur->flg_export) {
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002218 if (flags & SETFLAG_UNEXPORT) {
Denis Vlasenkoad4bd052009-04-20 22:04:21 +00002219 cur->flg_export = 0;
2220 /* unsetenv was already done */
2221 } else {
Denys Vlasenkoa7693902016-10-03 15:01:06 +02002222 int i;
Denis Vlasenkoad4bd052009-04-20 22:04:21 +00002223 debug_printf_env("%s: putenv '%s'\n", __func__, cur->varstr);
Denys Vlasenkoa7693902016-10-03 15:01:06 +02002224 i = putenv(cur->varstr);
2225 /* only now we can free old exported malloced string */
2226 free(free_me);
2227 return i;
Denis Vlasenkoad4bd052009-04-20 22:04:21 +00002228 }
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002229 }
Denys Vlasenkoa7693902016-10-03 15:01:06 +02002230 free(free_me);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002231 return 0;
2232}
2233
Denys Vlasenko6db47842009-09-05 20:15:17 +02002234/* Used at startup and after each cd */
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002235static void set_pwd_var(unsigned flag)
Denys Vlasenko6db47842009-09-05 20:15:17 +02002236{
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002237 set_local_var(xasprintf("PWD=%s", get_cwd(/*force:*/ 1)), flag);
Denys Vlasenko6db47842009-09-05 20:15:17 +02002238}
2239
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02002240static int unset_local_var_len(const char *name, int name_len)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002241{
2242 struct variable *cur;
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02002243 struct variable **var_pp;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002244
2245 if (!name)
Mike Frysingerd690f682009-03-30 06:50:54 +00002246 return EXIT_SUCCESS;
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02002247 var_pp = &G.top_var;
2248 while ((cur = *var_pp) != NULL) {
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002249 if (strncmp(cur->varstr, name, name_len) == 0 && cur->varstr[name_len] == '=') {
2250 if (cur->flg_read_only) {
2251 bb_error_msg("%s: readonly variable", name);
Mike Frysingerd690f682009-03-30 06:50:54 +00002252 return EXIT_FAILURE;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002253 }
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02002254 *var_pp = cur->next;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002255 debug_printf_env("%s: unsetenv '%s'\n", __func__, cur->varstr);
2256 bb_unsetenv(cur->varstr);
Mike Frysinger67c1c7b2009-04-24 06:26:18 +00002257 if (name_len == 3 && cur->varstr[0] == 'P' && cur->varstr[1] == 'S')
2258 cmdedit_update_prompt();
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002259 if (!cur->max_len)
2260 free(cur->varstr);
2261 free(cur);
Mike Frysingerd690f682009-03-30 06:50:54 +00002262 return EXIT_SUCCESS;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002263 }
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02002264 var_pp = &cur->next;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002265 }
Mike Frysingerd690f682009-03-30 06:50:54 +00002266 return EXIT_SUCCESS;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002267}
2268
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01002269#if ENABLE_HUSH_UNSET
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02002270static int unset_local_var(const char *name)
2271{
2272 return unset_local_var_len(name, strlen(name));
2273}
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01002274#endif
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02002275
2276static void unset_vars(char **strings)
2277{
2278 char **v;
2279
2280 if (!strings)
2281 return;
2282 v = strings;
2283 while (*v) {
2284 const char *eq = strchrnul(*v, '=');
2285 unset_local_var_len(*v, (int)(eq - *v));
2286 v++;
2287 }
2288 free(strings);
2289}
2290
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01002291#if BASH_HOSTNAME_VAR || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_READ
Denys Vlasenko03dad222010-01-12 23:29:57 +01002292static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val)
Mike Frysinger98c52642009-04-02 10:02:37 +00002293{
Denis Vlasenkob29eb6e2009-04-02 13:46:27 +00002294 char *var = xasprintf("%s=%s", name, val);
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002295 set_local_var(var, /*flag:*/ 0);
Mike Frysinger98c52642009-04-02 10:02:37 +00002296}
Denys Vlasenkocc2fd5a2017-01-09 06:19:55 +01002297#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002298
Denis Vlasenkob29eb6e2009-04-02 13:46:27 +00002299
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002300/*
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002301 * Helpers for "var1=val1 var2=val2 cmd" feature
2302 */
2303static void add_vars(struct variable *var)
2304{
2305 struct variable *next;
2306
2307 while (var) {
2308 next = var->next;
2309 var->next = G.top_var;
2310 G.top_var = var;
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02002311 if (var->flg_export) {
2312 debug_printf_env("%s: restoring exported '%s'\n", __func__, var->varstr);
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002313 putenv(var->varstr);
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02002314 } else {
Denys Vlasenko295fef82009-06-03 12:47:26 +02002315 debug_printf_env("%s: restoring variable '%s'\n", __func__, var->varstr);
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02002316 }
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002317 var = next;
2318 }
2319}
2320
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02002321static struct variable *set_vars_and_save_old(char **strings)
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002322{
2323 char **s;
2324 struct variable *old = NULL;
2325
2326 if (!strings)
2327 return old;
2328 s = strings;
2329 while (*s) {
2330 struct variable *var_p;
2331 struct variable **var_pp;
2332 char *eq;
2333
2334 eq = strchr(*s, '=');
2335 if (eq) {
Denys Vlasenko27c56f12010-09-07 09:56:34 +02002336 var_pp = get_ptr_to_local_var(*s, eq - *s);
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002337 if (var_pp) {
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002338 var_p = *var_pp;
Denys Vlasenko5b2cc0a2017-07-18 02:44:06 +02002339 if (var_p->flg_read_only) {
Denys Vlasenkocf511092017-07-18 15:58:02 +02002340 char **p;
Denys Vlasenko5b2cc0a2017-07-18 02:44:06 +02002341 bb_error_msg("%s: readonly variable", *s);
Denys Vlasenkocf511092017-07-18 15:58:02 +02002342 /*
2343 * "VAR=V BLTIN" unsets VARs after BLTIN completes.
2344 * If VAR is readonly, leaving it in the list
2345 * after asssignment error (msg above)
2346 * causes doubled error message later, on unset.
2347 */
2348 debug_printf_env("removing/freeing '%s' element\n", *s);
2349 free(*s);
2350 p = s;
2351 do { *p = p[1]; p++; } while (*p);
Denys Vlasenko5b2cc0a2017-07-18 02:44:06 +02002352 goto next;
2353 }
2354 /* Remove variable from global linked list */
Denys Vlasenkoacdc49c2009-05-04 01:58:10 +02002355 debug_printf_env("%s: removing '%s'\n", __func__, var_p->varstr);
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002356 *var_pp = var_p->next;
2357 /* Add it to returned list */
2358 var_p->next = old;
2359 old = var_p;
2360 }
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02002361 set_local_var(*s, SETFLAG_EXPORT);
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002362 }
Denys Vlasenko5b2cc0a2017-07-18 02:44:06 +02002363 next:
Denys Vlasenkocb6ff252009-05-04 00:14:30 +02002364 s++;
2365 }
2366 return old;
2367}
2368
2369
2370/*
Denys Vlasenkoc538d5b2014-08-13 09:57:44 +02002371 * Unicode helper
2372 */
2373static void reinit_unicode_for_hush(void)
2374{
2375 /* Unicode support should be activated even if LANG is set
2376 * _during_ shell execution, not only if it was set when
2377 * shell was started. Therefore, re-check LANG every time:
2378 */
Denys Vlasenko841f8332014-08-13 10:09:49 +02002379 if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2380 || ENABLE_UNICODE_USING_LOCALE
2381 ) {
2382 const char *s = get_local_var_value("LC_ALL");
2383 if (!s) s = get_local_var_value("LC_CTYPE");
2384 if (!s) s = get_local_var_value("LANG");
2385 reinit_unicode(s);
2386 }
Denys Vlasenkoc538d5b2014-08-13 09:57:44 +02002387}
2388
Denys Vlasenkoc538d5b2014-08-13 09:57:44 +02002389/*
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002390 * in_str support (strings, and "strings" read from files).
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002391 */
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002392
2393#if ENABLE_HUSH_INTERACTIVE
Denys Vlasenko4074d492016-09-30 01:49:53 +02002394/* To test correct lineedit/interactive behavior, type from command line:
2395 * echo $P\
2396 * \
2397 * AT\
2398 * H\
2399 * \
Denys Vlasenko10ad6222017-04-17 16:13:32 +02002400 * It exercises a lot of corner cases.
Denys Vlasenko4074d492016-09-30 01:49:53 +02002401 */
Mike Frysinger67c1c7b2009-04-24 06:26:18 +00002402static void cmdedit_update_prompt(void)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002403{
Mike Frysingerec2c6552009-03-28 12:24:44 +00002404 if (ENABLE_FEATURE_EDITING_FANCY_PROMPT) {
Mike Frysinger67c1c7b2009-04-24 06:26:18 +00002405 G.PS1 = get_local_var_value("PS1");
Mike Frysingerec2c6552009-03-28 12:24:44 +00002406 if (G.PS1 == NULL)
2407 G.PS1 = "\\w \\$ ";
Mike Frysinger67c1c7b2009-04-24 06:26:18 +00002408 G.PS2 = get_local_var_value("PS2");
Denys Vlasenko690ad242009-04-30 21:24:24 +02002409 } else {
Mike Frysingerec2c6552009-03-28 12:24:44 +00002410 G.PS1 = NULL;
Denys Vlasenko690ad242009-04-30 21:24:24 +02002411 }
Mike Frysinger67c1c7b2009-04-24 06:26:18 +00002412 if (G.PS2 == NULL)
2413 G.PS2 = "> ";
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002414}
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02002415static const char *setup_prompt_string(int promptmode)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002416{
2417 const char *prompt_str;
2418 debug_printf("setup_prompt_string %d ", promptmode);
Mike Frysingerec2c6552009-03-28 12:24:44 +00002419 if (!ENABLE_FEATURE_EDITING_FANCY_PROMPT) {
2420 /* Set up the prompt */
2421 if (promptmode == 0) { /* PS1 */
2422 free((char*)G.PS1);
Denys Vlasenko6db47842009-09-05 20:15:17 +02002423 /* bash uses $PWD value, even if it is set by user.
2424 * It uses current dir only if PWD is unset.
2425 * We always use current dir. */
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02002426 G.PS1 = xasprintf("%s %c ", get_cwd(0), (geteuid() != 0) ? '$' : '#');
Mike Frysingerec2c6552009-03-28 12:24:44 +00002427 prompt_str = G.PS1;
2428 } else
2429 prompt_str = G.PS2;
2430 } else
2431 prompt_str = (promptmode == 0) ? G.PS1 : G.PS2;
Denys Vlasenko4074d492016-09-30 01:49:53 +02002432 debug_printf("prompt_str '%s'\n", prompt_str);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002433 return prompt_str;
2434}
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002435static int get_user_input(struct in_str *i)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002436{
2437 int r;
2438 const char *prompt_str;
2439
2440 prompt_str = setup_prompt_string(i->promptmode);
Denys Vlasenko8391c482010-05-22 17:50:43 +02002441# if ENABLE_FEATURE_EDITING
Denys Vlasenko8660aeb2016-11-24 17:44:02 +01002442 for (;;) {
Denys Vlasenkoc538d5b2014-08-13 09:57:44 +02002443 reinit_unicode_for_hush();
Denys Vlasenko4b89d512016-11-25 03:41:03 +01002444 if (G.flag_SIGINT) {
2445 /* There was ^C'ed, make it look prettier: */
2446 bb_putchar('\n');
2447 G.flag_SIGINT = 0;
2448 }
Denis Vlasenko422cd7c2009-03-31 12:41:52 +00002449 /* buglet: SIGINT will not make new prompt to appear _at once_,
Denys Vlasenko4b89d512016-11-25 03:41:03 +01002450 * only after <Enter>. (^C works immediately) */
Denys Vlasenko0448c552016-09-29 20:25:44 +02002451 r = read_line_input(G.line_input_state, prompt_str,
Denys Vlasenko84ea60e2017-08-02 17:27:28 +02002452 G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1
Denys Vlasenko0448c552016-09-29 20:25:44 +02002453 );
Denys Vlasenko4b89d512016-11-25 03:41:03 +01002454 /* read_line_input intercepts ^C, "convert" it to SIGINT */
Denys Vlasenkodd4b4462017-08-02 16:52:12 +02002455 if (r == 0)
Denys Vlasenko8660aeb2016-11-24 17:44:02 +01002456 raise(SIGINT);
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002457 check_and_run_traps();
Denys Vlasenko8660aeb2016-11-24 17:44:02 +01002458 if (r != 0 && !G.flag_SIGINT)
2459 break;
2460 /* ^C or SIGINT: repeat */
Denys Vlasenkodd4b4462017-08-02 16:52:12 +02002461 /* bash prints ^C even on real SIGINT (non-kbd generated) */
2462 write(STDOUT_FILENO, "^C", 2);
Denys Vlasenko8660aeb2016-11-24 17:44:02 +01002463 G.last_exitcode = 128 + SIGINT;
2464 }
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002465 if (r < 0) {
2466 /* EOF/error detected */
Denys Vlasenko4074d492016-09-30 01:49:53 +02002467 i->p = NULL;
2468 i->peek_buf[0] = r = EOF;
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002469 return r;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002470 }
Denys Vlasenko4074d492016-09-30 01:49:53 +02002471 i->p = G.user_input_buf;
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002472 return (unsigned char)*i->p++;
Denys Vlasenko8391c482010-05-22 17:50:43 +02002473# else
Denys Vlasenko8660aeb2016-11-24 17:44:02 +01002474 for (;;) {
Denis Vlasenko422cd7c2009-03-31 12:41:52 +00002475 G.flag_SIGINT = 0;
Denys Vlasenkob8709032011-05-08 21:20:01 +02002476 if (i->last_char == '\0' || i->last_char == '\n') {
2477 /* Why check_and_run_traps here? Try this interactively:
2478 * $ trap 'echo INT' INT; (sleep 2; kill -INT $$) &
2479 * $ <[enter], repeatedly...>
2480 * Without check_and_run_traps, handler never runs.
2481 */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02002482 check_and_run_traps();
Denys Vlasenkob8709032011-05-08 21:20:01 +02002483 fputs(prompt_str, stdout);
2484 }
Denys Vlasenko8131eea2009-11-02 14:19:51 +01002485 fflush_all();
Denys Vlasenko4b89d512016-11-25 03:41:03 +01002486//FIXME: here ^C or SIGINT will have effect only after <Enter>
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002487 r = fgetc(i->file);
Denys Vlasenko8660aeb2016-11-24 17:44:02 +01002488 /* In !ENABLE_FEATURE_EDITING we don't use read_line_input,
2489 * no ^C masking happens during fgetc, no special code for ^C:
2490 * it generates SIGINT as usual.
2491 */
2492 check_and_run_traps();
2493 if (G.flag_SIGINT)
2494 G.last_exitcode = 128 + SIGINT;
2495 if (r != '\0')
2496 break;
2497 }
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002498 return r;
Denys Vlasenko8391c482010-05-22 17:50:43 +02002499# endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002500}
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002501/* This is the magic location that prints prompts
2502 * and gets data back from the user */
Denys Vlasenko4074d492016-09-30 01:49:53 +02002503static int fgetc_interactive(struct in_str *i)
2504{
2505 int ch;
2506 /* If it's interactive stdin, get new line. */
2507 if (G_interactive_fd && i->file == stdin) {
2508 /* Returns first char (or EOF), the rest is in i->p[] */
2509 ch = get_user_input(i);
2510 i->promptmode = 1; /* PS2 */
2511 } else {
2512 /* Not stdin: script file, sourced file, etc */
2513 do ch = fgetc(i->file); while (ch == '\0');
2514 }
2515 return ch;
2516}
2517#else
2518static inline int fgetc_interactive(struct in_str *i)
2519{
2520 int ch;
2521 do ch = fgetc(i->file); while (ch == '\0');
2522 return ch;
2523}
2524#endif /* INTERACTIVE */
2525
Denys Vlasenko87e039d2016-11-08 22:35:05 +01002526static int i_getch(struct in_str *i)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002527{
2528 int ch;
2529
Denys Vlasenko87e039d2016-11-08 22:35:05 +01002530 if (!i->file) {
2531 /* string-based in_str */
2532 ch = (unsigned char)*i->p;
2533 if (ch != '\0') {
2534 i->p++;
2535 i->last_char = ch;
2536 return ch;
2537 }
2538 return EOF;
2539 }
2540
2541 /* FILE-based in_str */
2542
Denys Vlasenko4074d492016-09-30 01:49:53 +02002543#if ENABLE_FEATURE_EDITING
2544 /* This can be stdin, check line editing char[] buffer */
2545 if (i->p && *i->p != '\0') {
2546 ch = (unsigned char)*i->p++;
2547 goto out;
2548 }
2549#endif
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002550 /* peek_buf[] is an int array, not char. Can contain EOF. */
2551 ch = i->peek_buf[0];
Denys Vlasenko4074d492016-09-30 01:49:53 +02002552 if (ch != 0) {
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002553 int ch2 = i->peek_buf[1];
2554 i->peek_buf[0] = ch2;
2555 if (ch2 == 0) /* very likely, avoid redundant write */
2556 goto out;
2557 i->peek_buf[1] = 0;
2558 goto out;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002559 }
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002560
Denys Vlasenko4074d492016-09-30 01:49:53 +02002561 ch = fgetc_interactive(i);
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002562 out:
Denis Vlasenko913a2012009-04-05 22:17:04 +00002563 debug_printf("file_get: got '%c' %d\n", ch, ch);
Denys Vlasenkocecbc982011-03-30 18:54:52 +02002564 i->last_char = ch;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002565 return ch;
2566}
2567
Denys Vlasenko87e039d2016-11-08 22:35:05 +01002568static int i_peek(struct in_str *i)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002569{
2570 int ch;
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002571
Denys Vlasenko87e039d2016-11-08 22:35:05 +01002572 if (!i->file) {
2573 /* string-based in_str */
2574 /* Doesn't report EOF on NUL. None of the callers care. */
2575 return (unsigned char)*i->p;
2576 }
2577
2578 /* FILE-based in_str */
2579
Denys Vlasenko4074d492016-09-30 01:49:53 +02002580#if ENABLE_FEATURE_EDITING && ENABLE_HUSH_INTERACTIVE
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002581 /* This can be stdin, check line editing char[] buffer */
2582 if (i->p && *i->p != '\0')
2583 return (unsigned char)*i->p;
2584#endif
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002585 /* peek_buf[] is an int array, not char. Can contain EOF. */
2586 ch = i->peek_buf[0];
Denys Vlasenko4074d492016-09-30 01:49:53 +02002587 if (ch != 0)
2588 return ch;
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002589
Denys Vlasenko4074d492016-09-30 01:49:53 +02002590 /* Need to get a new char */
2591 ch = fgetc_interactive(i);
2592 debug_printf("file_peek: got '%c' %d\n", ch, ch);
2593
2594 /* Save it by either rolling back line editing buffer, or in i->peek_buf[0] */
2595#if ENABLE_FEATURE_EDITING && ENABLE_HUSH_INTERACTIVE
2596 if (i->p) {
2597 i->p -= 1;
2598 return ch;
2599 }
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002600#endif
Denys Vlasenko4074d492016-09-30 01:49:53 +02002601 i->peek_buf[0] = ch;
2602 /*i->peek_buf[1] = 0; - already is */
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002603 return ch;
2604}
2605
Denys Vlasenko4074d492016-09-30 01:49:53 +02002606/* Only ever called if i_peek() was called, and did not return EOF.
2607 * IOW: we know the previous peek saw an ordinary char, not EOF, not NUL,
2608 * not end-of-line. Therefore we never need to read a new editing line here.
2609 */
2610static int i_peek2(struct in_str *i)
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002611{
Denys Vlasenko4074d492016-09-30 01:49:53 +02002612 int ch;
2613
2614 /* There are two cases when i->p[] buffer exists.
2615 * (1) it's a string in_str.
Denys Vlasenko08755f92016-09-30 02:02:25 +02002616 * (2) It's a file, and we have a saved line editing buffer.
Denys Vlasenko4074d492016-09-30 01:49:53 +02002617 * In both cases, we know that i->p[0] exists and not NUL, and
2618 * the peek2 result is in i->p[1].
2619 */
2620 if (i->p)
2621 return (unsigned char)i->p[1];
2622
2623 /* Now we know it is a file-based in_str. */
2624
2625 /* peek_buf[] is an int array, not char. Can contain EOF. */
2626 /* Is there 2nd char? */
2627 ch = i->peek_buf[1];
2628 if (ch == 0) {
2629 /* We did not read it yet, get it now */
2630 do ch = fgetc(i->file); while (ch == '\0');
2631 i->peek_buf[1] = ch;
2632 }
2633
2634 debug_printf("file_peek2: got '%c' %d\n", ch, ch);
2635 return ch;
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02002636}
2637
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002638static void setup_file_in_str(struct in_str *i, FILE *f)
2639{
Denys Vlasenkoa1463192011-01-18 17:55:04 +01002640 memset(i, 0, sizeof(*i));
Denys Vlasenkoa1463192011-01-18 17:55:04 +01002641 /* i->promptmode = 0; - PS1 (memset did it) */
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002642 i->file = f;
Denys Vlasenkoa1463192011-01-18 17:55:04 +01002643 /* i->p = NULL; */
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002644}
2645
2646static void setup_string_in_str(struct in_str *i, const char *s)
2647{
Denys Vlasenkoa1463192011-01-18 17:55:04 +01002648 memset(i, 0, sizeof(*i));
Denys Vlasenkoa1463192011-01-18 17:55:04 +01002649 /* i->promptmode = 0; - PS1 (memset did it) */
Denys Vlasenko87e039d2016-11-08 22:35:05 +01002650 /*i->file = NULL */;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002651 i->p = s;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00002652}
2653
2654
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002655/*
2656 * o_string support
2657 */
2658#define B_CHUNK (32 * sizeof(char*))
Eric Andersen25f27032001-04-26 23:22:31 +00002659
Denis Vlasenko0b677d82009-04-10 13:49:10 +00002660static void o_reset_to_empty_unquoted(o_string *o)
Eric Andersen25f27032001-04-26 23:22:31 +00002661{
2662 o->length = 0;
Denys Vlasenko38292b62010-09-05 14:49:40 +02002663 o->has_quoted_part = 0;
Denis Vlasenkod65ea392007-10-01 10:02:25 +00002664 if (o->data)
2665 o->data[0] = '\0';
Eric Andersen25f27032001-04-26 23:22:31 +00002666}
2667
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00002668static void o_free(o_string *o)
Eric Andersen25f27032001-04-26 23:22:31 +00002669{
Aaron Lehmanna170e1c2002-11-28 11:27:31 +00002670 free(o->data);
Denis Vlasenkod65ea392007-10-01 10:02:25 +00002671 memset(o, 0, sizeof(*o));
Eric Andersen25f27032001-04-26 23:22:31 +00002672}
2673
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00002674static ALWAYS_INLINE void o_free_unsafe(o_string *o)
2675{
2676 free(o->data);
2677}
2678
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00002679static void o_grow_by(o_string *o, int len)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002680{
2681 if (o->length + len > o->maxlen) {
Denys Vlasenko46e64982016-09-29 19:50:55 +02002682 o->maxlen += (2 * len) | (B_CHUNK-1);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002683 o->data = xrealloc(o->data, 1 + o->maxlen);
2684 }
2685}
2686
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00002687static void o_addchr(o_string *o, int ch)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002688{
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00002689 debug_printf("o_addchr: '%c' o->length=%d o=%p\n", ch, o->length, o);
Denys Vlasenko46e64982016-09-29 19:50:55 +02002690 if (o->length < o->maxlen) {
2691 /* likely. avoid o_grow_by() call */
2692 add:
2693 o->data[o->length] = ch;
2694 o->length++;
2695 o->data[o->length] = '\0';
2696 return;
2697 }
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00002698 o_grow_by(o, 1);
Denys Vlasenko46e64982016-09-29 19:50:55 +02002699 goto add;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002700}
2701
Denys Vlasenko657086a2016-09-29 18:07:42 +02002702#if 0
2703/* Valid only if we know o_string is not empty */
2704static void o_delchr(o_string *o)
2705{
2706 o->length--;
2707 o->data[o->length] = '\0';
2708}
2709#endif
2710
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00002711static void o_addblock(o_string *o, const char *str, int len)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002712{
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00002713 o_grow_by(o, len);
Denys Vlasenko0675b032017-07-24 02:17:05 +02002714 ((char*)mempcpy(&o->data[o->length], str, len))[0] = '\0';
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002715 o->length += len;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002716}
2717
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00002718static void o_addstr(o_string *o, const char *str)
Mike Frysinger98c52642009-04-02 10:02:37 +00002719{
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00002720 o_addblock(o, str, strlen(str));
2721}
Denys Vlasenko2e48d532010-05-22 17:30:39 +02002722
Denys Vlasenko1e811b12010-05-22 03:12:29 +02002723#if !BB_MMU
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00002724static void nommu_addchr(o_string *o, int ch)
2725{
2726 if (o)
2727 o_addchr(o, ch);
2728}
2729#else
Denys Vlasenko28a105d2009-06-01 11:26:30 +02002730# define nommu_addchr(o, str) ((void)0)
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00002731#endif
2732
2733static void o_addstr_with_NUL(o_string *o, const char *str)
2734{
2735 o_addblock(o, str, strlen(str) + 1);
Mike Frysinger98c52642009-04-02 10:02:37 +00002736}
2737
Denys Vlasenkof3e28182009-11-17 03:35:31 +01002738/*
Denys Vlasenko238081f2010-10-03 14:26:26 +02002739 * HUSH_BRACE_EXPANSION code needs corresponding quoting on variable expansion side.
Denys Vlasenkof3e28182009-11-17 03:35:31 +01002740 * Currently, "v='{q,w}'; echo $v" erroneously expands braces in $v.
2741 * Apparently, on unquoted $v bash still does globbing
2742 * ("v='*.txt'; echo $v" prints all .txt files),
2743 * but NOT brace expansion! Thus, there should be TWO independent
2744 * quoting mechanisms on $v expansion side: one protects
2745 * $v from brace expansion, and other additionally protects "$v" against globbing.
2746 * We have only second one.
2747 */
2748
Denys Vlasenko9e800222010-10-03 14:28:04 +02002749#if ENABLE_HUSH_BRACE_EXPANSION
Denys Vlasenkof3e28182009-11-17 03:35:31 +01002750# define MAYBE_BRACES "{}"
2751#else
2752# define MAYBE_BRACES ""
2753#endif
2754
Eric Andersen25f27032001-04-26 23:22:31 +00002755/* My analysis of quoting semantics tells me that state information
2756 * is associated with a destination, not a source.
2757 */
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002758static void o_addqchr(o_string *o, int ch)
Eric Andersen25f27032001-04-26 23:22:31 +00002759{
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002760 int sz = 1;
Denys Vlasenkof3e28182009-11-17 03:35:31 +01002761 char *found = strchr("*?[\\" MAYBE_BRACES, ch);
Denis Vlasenko371de4a2008-10-14 12:43:13 +00002762 if (found)
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002763 sz++;
Denis Vlasenko371de4a2008-10-14 12:43:13 +00002764 o_grow_by(o, sz);
2765 if (found) {
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002766 o->data[o->length] = '\\';
2767 o->length++;
Eric Andersen25f27032001-04-26 23:22:31 +00002768 }
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002769 o->data[o->length] = ch;
2770 o->length++;
2771 o->data[o->length] = '\0';
Eric Andersen25f27032001-04-26 23:22:31 +00002772}
2773
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002774static void o_addQchr(o_string *o, int ch)
Denis Vlasenko87f40ba2008-06-10 22:39:37 +00002775{
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002776 int sz = 1;
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02002777 if ((o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)
2778 && strchr("*?[\\" MAYBE_BRACES, ch)
2779 ) {
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002780 sz++;
2781 o->data[o->length] = '\\';
2782 o->length++;
2783 }
2784 o_grow_by(o, sz);
2785 o->data[o->length] = ch;
2786 o->length++;
2787 o->data[o->length] = '\0';
2788}
2789
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02002790static void o_addqblock(o_string *o, const char *str, int len)
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002791{
Denis Vlasenko87f40ba2008-06-10 22:39:37 +00002792 while (len) {
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002793 char ch;
2794 int sz;
Denys Vlasenkof3e28182009-11-17 03:35:31 +01002795 int ordinary_cnt = strcspn(str, "*?[\\" MAYBE_BRACES);
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002796 if (ordinary_cnt > len) /* paranoia */
2797 ordinary_cnt = len;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00002798 o_addblock(o, str, ordinary_cnt);
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002799 if (ordinary_cnt == len)
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02002800 return; /* NUL is already added by o_addblock */
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002801 str += ordinary_cnt;
Denis Vlasenko30c9cc52008-06-17 07:24:29 +00002802 len -= ordinary_cnt + 1; /* we are processing + 1 char below */
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002803
Denis Vlasenko87f40ba2008-06-10 22:39:37 +00002804 ch = *str++;
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002805 sz = 1;
Denys Vlasenkof3e28182009-11-17 03:35:31 +01002806 if (ch) { /* it is necessarily one of "*?[\\" MAYBE_BRACES */
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002807 sz++;
2808 o->data[o->length] = '\\';
2809 o->length++;
Denis Vlasenko87f40ba2008-06-10 22:39:37 +00002810 }
Denis Vlasenko7e3d33b2008-06-12 13:31:04 +00002811 o_grow_by(o, sz);
2812 o->data[o->length] = ch;
2813 o->length++;
Denis Vlasenko87f40ba2008-06-10 22:39:37 +00002814 }
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02002815 o->data[o->length] = '\0';
Denis Vlasenko87f40ba2008-06-10 22:39:37 +00002816}
2817
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02002818static void o_addQblock(o_string *o, const char *str, int len)
2819{
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02002820 if (!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)) {
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02002821 o_addblock(o, str, len);
2822 return;
2823 }
2824 o_addqblock(o, str, len);
2825}
2826
Denys Vlasenko38292b62010-09-05 14:49:40 +02002827static void o_addQstr(o_string *o, const char *str)
2828{
2829 o_addQblock(o, str, strlen(str));
2830}
2831
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002832/* A special kind of o_string for $VAR and `cmd` expansion.
2833 * It contains char* list[] at the beginning, which is grown in 16 element
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00002834 * increments. Actual string data starts at the next multiple of 16 * (char*).
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002835 * list[i] contains an INDEX (int!) into this string data.
2836 * It means that if list[] needs to grow, data needs to be moved higher up
2837 * but list[i]'s need not be modified.
2838 * NB: remembering how many list[i]'s you have there is crucial.
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00002839 * o_finalize_list() operation post-processes this structure - calculates
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002840 * and stores actual char* ptrs in list[]. Oh, it NULL terminates it as well.
2841 */
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00002842#if DEBUG_EXPAND || DEBUG_GLOB
2843static void debug_print_list(const char *prefix, o_string *o, int n)
2844{
2845 char **list = (char**)o->data;
2846 int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
2847 int i = 0;
Denis Vlasenko0701dca2009-04-11 10:38:47 +00002848
2849 indent();
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01002850 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 +02002851 prefix, list, n, string_start, o->length, o->maxlen,
2852 !!(o->o_expflags & EXP_FLAG_GLOB),
2853 o->has_quoted_part,
2854 !!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00002855 while (i < n) {
Denis Vlasenko0701dca2009-04-11 10:38:47 +00002856 indent();
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01002857 fdprintf(2, " list[%d]=%d '%s' %p\n", i, (int)(uintptr_t)list[i],
2858 o->data + (int)(uintptr_t)list[i] + string_start,
2859 o->data + (int)(uintptr_t)list[i] + string_start);
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00002860 i++;
2861 }
2862 if (n) {
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01002863 const char *p = o->data + (int)(uintptr_t)list[n - 1] + string_start;
Denis Vlasenko0701dca2009-04-11 10:38:47 +00002864 indent();
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01002865 fdprintf(2, " total_sz:%ld\n", (long)((p + strlen(p) + 1) - o->data));
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00002866 }
2867}
2868#else
Denys Vlasenko28a105d2009-06-01 11:26:30 +02002869# define debug_print_list(prefix, o, n) ((void)0)
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00002870#endif
2871
2872/* n = o_save_ptr_helper(str, n) "starts new string" by storing an index value
2873 * in list[n] so that it points past last stored byte so far.
2874 * It returns n+1. */
2875static int o_save_ptr_helper(o_string *o, int n)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002876{
2877 char **list = (char**)o->data;
Denis Vlasenko895bea22008-06-10 18:06:24 +00002878 int string_start;
2879 int string_len;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002880
2881 if (!o->has_empty_slot) {
Denis Vlasenko895bea22008-06-10 18:06:24 +00002882 string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
2883 string_len = o->length - string_start;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002884 if (!(n & 0xf)) { /* 0, 0x10, 0x20...? */
Denis Vlasenko30c9cc52008-06-17 07:24:29 +00002885 debug_printf_list("list[%d]=%d string_start=%d (growing)\n", n, string_len, string_start);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002886 /* list[n] points to string_start, make space for 16 more pointers */
2887 o->maxlen += 0x10 * sizeof(list[0]);
2888 o->data = xrealloc(o->data, o->maxlen + 1);
Denis Vlasenko7049ff82008-06-25 09:53:17 +00002889 list = (char**)o->data;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002890 memmove(list + n + 0x10, list + n, string_len);
2891 o->length += 0x10 * sizeof(list[0]);
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00002892 } else {
2893 debug_printf_list("list[%d]=%d string_start=%d\n",
2894 n, string_len, string_start);
2895 }
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002896 } else {
2897 /* We have empty slot at list[n], reuse without growth */
Denis Vlasenko895bea22008-06-10 18:06:24 +00002898 string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); /* NB: n+1! */
2899 string_len = o->length - string_start;
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00002900 debug_printf_list("list[%d]=%d string_start=%d (empty slot)\n",
2901 n, string_len, string_start);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002902 o->has_empty_slot = 0;
2903 }
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02002904 o->has_quoted_part = 0;
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02002905 list[n] = (char*)(uintptr_t)string_len;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002906 return n + 1;
2907}
2908
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00002909/* "What was our last o_save_ptr'ed position (byte offset relative o->data)?" */
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00002910static int o_get_last_ptr(o_string *o, int n)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002911{
2912 char **list = (char**)o->data;
2913 int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
2914
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02002915 return ((int)(uintptr_t)list[n-1]) + string_start;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00002916}
2917
Denys Vlasenko9e800222010-10-03 14:28:04 +02002918#if ENABLE_HUSH_BRACE_EXPANSION
Denys Vlasenko5b2db972009-11-16 05:49:36 +01002919/* There in a GNU extension, GLOB_BRACE, but it is not usable:
2920 * first, it processes even {a} (no commas), second,
2921 * I didn't manage to make it return strings when they don't match
Denys Vlasenko160746b2009-11-16 05:51:18 +01002922 * existing files. Need to re-implement it.
Denys Vlasenko5b2db972009-11-16 05:49:36 +01002923 */
Denys Vlasenkof3e28182009-11-17 03:35:31 +01002924
2925/* Helper */
2926static int glob_needed(const char *s)
2927{
2928 while (*s) {
2929 if (*s == '\\') {
2930 if (!s[1])
2931 return 0;
2932 s += 2;
2933 continue;
2934 }
2935 if (*s == '*' || *s == '[' || *s == '?' || *s == '{')
2936 return 1;
2937 s++;
2938 }
2939 return 0;
2940}
Denys Vlasenko5b2db972009-11-16 05:49:36 +01002941/* Return pointer to next closing brace or to comma */
2942static const char *next_brace_sub(const char *cp)
2943{
2944 unsigned depth = 0;
2945 cp++;
2946 while (*cp != '\0') {
2947 if (*cp == '\\') {
2948 if (*++cp == '\0')
2949 break;
2950 cp++;
2951 continue;
Denys Vlasenko3581c622010-01-25 13:39:24 +01002952 }
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02002953 if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
Denys Vlasenko5b2db972009-11-16 05:49:36 +01002954 break;
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02002955 if (*cp++ == '{')
Denys Vlasenko5b2db972009-11-16 05:49:36 +01002956 depth++;
2957 }
2958
2959 return *cp != '\0' ? cp : NULL;
2960}
Denys Vlasenkof3e28182009-11-17 03:35:31 +01002961/* Recursive brace globber. Note: may garble pattern[]. */
2962static int glob_brace(char *pattern, o_string *o, int n)
Denys Vlasenko5b2db972009-11-16 05:49:36 +01002963{
Denys Vlasenkof3e28182009-11-17 03:35:31 +01002964 char *new_pattern_buf;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01002965 const char *begin;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01002966 const char *next;
2967 const char *rest;
Denys Vlasenkof3e28182009-11-17 03:35:31 +01002968 const char *p;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01002969 size_t rest_len;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01002970
2971 debug_printf_glob("glob_brace('%s')\n", pattern);
2972
2973 begin = pattern;
2974 while (1) {
2975 if (*begin == '\0')
Denys Vlasenkof3e28182009-11-17 03:35:31 +01002976 goto simple_glob;
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02002977 if (*begin == '{') {
Denys Vlasenko5b2db972009-11-16 05:49:36 +01002978 /* Find the first sub-pattern and at the same time
2979 * find the rest after the closing brace */
2980 next = next_brace_sub(begin);
2981 if (next == NULL) {
2982 /* An illegal expression */
Denys Vlasenkof3e28182009-11-17 03:35:31 +01002983 goto simple_glob;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01002984 }
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02002985 if (*next == '}') {
Denys Vlasenko5b2db972009-11-16 05:49:36 +01002986 /* "{abc}" with no commas - illegal
2987 * brace expr, disregard and skip it */
2988 begin = next + 1;
2989 continue;
2990 }
2991 break;
2992 }
2993 if (*begin == '\\' && begin[1] != '\0')
2994 begin++;
2995 begin++;
2996 }
2997 debug_printf_glob("begin:%s\n", begin);
2998 debug_printf_glob("next:%s\n", next);
2999
3000 /* Now find the end of the whole brace expression */
3001 rest = next;
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02003002 while (*rest != '}') {
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003003 rest = next_brace_sub(rest);
3004 if (rest == NULL) {
3005 /* An illegal expression */
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003006 goto simple_glob;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003007 }
3008 debug_printf_glob("rest:%s\n", rest);
3009 }
3010 rest_len = strlen(++rest) + 1;
3011
3012 /* We are sure the brace expression is well-formed */
3013
3014 /* Allocate working buffer large enough for our work */
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003015 new_pattern_buf = xmalloc(strlen(pattern));
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003016
3017 /* We have a brace expression. BEGIN points to the opening {,
3018 * NEXT points past the terminator of the first element, and REST
3019 * points past the final }. We will accumulate result names from
3020 * recursive runs for each brace alternative in the buffer using
3021 * GLOB_APPEND. */
3022
3023 p = begin + 1;
3024 while (1) {
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003025 /* Construct the new glob expression */
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003026 memcpy(
3027 mempcpy(
3028 mempcpy(new_pattern_buf,
3029 /* We know the prefix for all sub-patterns */
3030 pattern, begin - pattern),
3031 p, next - p),
3032 rest, rest_len);
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003033
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003034 /* Note: glob_brace() may garble new_pattern_buf[].
3035 * That's why we re-copy prefix every time (1st memcpy above).
3036 */
3037 n = glob_brace(new_pattern_buf, o, n);
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02003038 if (*next == '}') {
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003039 /* We saw the last entry */
3040 break;
3041 }
3042 p = next + 1;
3043 next = next_brace_sub(next);
3044 }
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003045 free(new_pattern_buf);
3046 return n;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003047
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003048 simple_glob:
3049 {
3050 int gr;
3051 glob_t globdata;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003052
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003053 memset(&globdata, 0, sizeof(globdata));
3054 gr = glob(pattern, 0, NULL, &globdata);
3055 debug_printf_glob("glob('%s'):%d\n", pattern, gr);
3056 if (gr != 0) {
3057 if (gr == GLOB_NOMATCH) {
3058 globfree(&globdata);
3059 /* NB: garbles parameter */
3060 unbackslash(pattern);
3061 o_addstr_with_NUL(o, pattern);
3062 debug_printf_glob("glob pattern '%s' is literal\n", pattern);
3063 return o_save_ptr_helper(o, n);
3064 }
3065 if (gr == GLOB_NOSPACE)
3066 bb_error_msg_and_die(bb_msg_memory_exhausted);
3067 /* GLOB_ABORTED? Only happens with GLOB_ERR flag,
3068 * but we didn't specify it. Paranoia again. */
3069 bb_error_msg_and_die("glob error %d on '%s'", gr, pattern);
3070 }
3071 if (globdata.gl_pathv && globdata.gl_pathv[0]) {
3072 char **argv = globdata.gl_pathv;
3073 while (1) {
3074 o_addstr_with_NUL(o, *argv);
3075 n = o_save_ptr_helper(o, n);
3076 argv++;
3077 if (!*argv)
3078 break;
3079 }
3080 }
3081 globfree(&globdata);
3082 }
3083 return n;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003084}
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003085/* Performs globbing on last list[],
3086 * saving each result as a new list[].
3087 */
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02003088static int perform_glob(o_string *o, int n)
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003089{
3090 char *pattern, *copy;
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003091
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02003092 debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data);
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003093 if (!o->data)
3094 return o_save_ptr_helper(o, n);
3095 pattern = o->data + o_get_last_ptr(o, n);
3096 debug_printf_glob("glob pattern '%s'\n", pattern);
3097 if (!glob_needed(pattern)) {
3098 /* unbackslash last string in o in place, fix length */
3099 o->length = unbackslash(pattern) - o->data;
3100 debug_printf_glob("glob pattern '%s' is literal\n", pattern);
3101 return o_save_ptr_helper(o, n);
3102 }
3103
3104 copy = xstrdup(pattern);
3105 /* "forget" pattern in o */
3106 o->length = pattern - o->data;
3107 n = glob_brace(copy, o, n);
3108 free(copy);
3109 if (DEBUG_GLOB)
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02003110 debug_print_list("perform_glob returning", o, n);
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003111 return n;
3112}
3113
Denys Vlasenko238081f2010-10-03 14:26:26 +02003114#else /* !HUSH_BRACE_EXPANSION */
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003115
3116/* Helper */
3117static int glob_needed(const char *s)
3118{
3119 while (*s) {
3120 if (*s == '\\') {
3121 if (!s[1])
3122 return 0;
3123 s += 2;
3124 continue;
3125 }
3126 if (*s == '*' || *s == '[' || *s == '?')
3127 return 1;
3128 s++;
3129 }
3130 return 0;
3131}
3132/* Performs globbing on last list[],
3133 * saving each result as a new list[].
3134 */
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02003135static int perform_glob(o_string *o, int n)
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003136{
3137 glob_t globdata;
3138 int gr;
3139 char *pattern;
3140
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02003141 debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data);
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003142 if (!o->data)
3143 return o_save_ptr_helper(o, n);
3144 pattern = o->data + o_get_last_ptr(o, n);
Denis Vlasenko30c9cc52008-06-17 07:24:29 +00003145 debug_printf_glob("glob pattern '%s'\n", pattern);
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003146 if (!glob_needed(pattern)) {
3147 literal:
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003148 /* unbackslash last string in o in place, fix length */
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003149 o->length = unbackslash(pattern) - o->data;
Denis Vlasenko30c9cc52008-06-17 07:24:29 +00003150 debug_printf_glob("glob pattern '%s' is literal\n", pattern);
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003151 return o_save_ptr_helper(o, n);
3152 }
3153
3154 memset(&globdata, 0, sizeof(globdata));
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003155 /* Can't use GLOB_NOCHECK: it does not unescape the string.
3156 * If we glob "*.\*" and don't find anything, we need
3157 * to fall back to using literal "*.*", but GLOB_NOCHECK
3158 * will return "*.\*"!
3159 */
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003160 gr = glob(pattern, 0, NULL, &globdata);
3161 debug_printf_glob("glob('%s'):%d\n", pattern, gr);
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003162 if (gr != 0) {
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003163 if (gr == GLOB_NOMATCH) {
3164 globfree(&globdata);
3165 goto literal;
3166 }
3167 if (gr == GLOB_NOSPACE)
3168 bb_error_msg_and_die(bb_msg_memory_exhausted);
Denys Vlasenko5b2db972009-11-16 05:49:36 +01003169 /* GLOB_ABORTED? Only happens with GLOB_ERR flag,
3170 * but we didn't specify it. Paranoia again. */
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003171 bb_error_msg_and_die("glob error %d on '%s'", gr, pattern);
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003172 }
3173 if (globdata.gl_pathv && globdata.gl_pathv[0]) {
3174 char **argv = globdata.gl_pathv;
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003175 /* "forget" pattern in o */
3176 o->length = pattern - o->data;
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003177 while (1) {
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00003178 o_addstr_with_NUL(o, *argv);
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003179 n = o_save_ptr_helper(o, n);
3180 argv++;
3181 if (!*argv)
3182 break;
3183 }
3184 }
3185 globfree(&globdata);
3186 if (DEBUG_GLOB)
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02003187 debug_print_list("perform_glob returning", o, n);
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003188 return n;
3189}
3190
Denys Vlasenko238081f2010-10-03 14:26:26 +02003191#endif /* !HUSH_BRACE_EXPANSION */
Denys Vlasenkof3e28182009-11-17 03:35:31 +01003192
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02003193/* If o->o_expflags & EXP_FLAG_GLOB, glob the string so far remembered.
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00003194 * Otherwise, just finish current list[] and start new */
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003195static int o_save_ptr(o_string *o, int n)
3196{
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02003197 if (o->o_expflags & EXP_FLAG_GLOB) {
Denis Vlasenkoa8b6dff2009-03-20 12:05:14 +00003198 /* If o->has_empty_slot, list[n] was already globbed
3199 * (if it was requested back then when it was filled)
3200 * so don't do that again! */
3201 if (!o->has_empty_slot)
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02003202 return perform_glob(o, n); /* o_save_ptr_helper is inside */
Denis Vlasenkoa8b6dff2009-03-20 12:05:14 +00003203 }
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003204 return o_save_ptr_helper(o, n);
3205}
3206
3207/* "Please convert list[n] to real char* ptrs, and NULL terminate it." */
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00003208static char **o_finalize_list(o_string *o, int n)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003209{
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003210 char **list;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003211 int string_start;
3212
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003213 n = o_save_ptr(o, n); /* force growth for list[n] if necessary */
3214 if (DEBUG_EXPAND)
3215 debug_print_list("finalized", o, n);
Denis Vlasenko30c9cc52008-06-17 07:24:29 +00003216 debug_printf_expand("finalized n:%d\n", n);
Denis Vlasenkob61e13d2008-06-17 05:11:43 +00003217 list = (char**)o->data;
3218 string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3219 list[--n] = NULL;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003220 while (n) {
3221 n--;
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003222 list[n] = o->data + (int)(uintptr_t)list[n] + string_start;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00003223 }
3224 return list;
3225}
3226
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003227static void free_pipe_list(struct pipe *pi);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003228
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003229/* Returns pi->next - next pipe in the list */
3230static struct pipe *free_pipe(struct pipe *pi)
Denis Vlasenkof886fd22008-10-13 12:36:05 +00003231{
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003232 struct pipe *next;
3233 int i;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003234
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003235 debug_printf_clean("free_pipe (pid %d)\n", getpid());
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003236 for (i = 0; i < pi->num_cmds; i++) {
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003237 struct command *command;
3238 struct redir_struct *r, *rnext;
3239
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003240 command = &pi->cmds[i];
Denis Vlasenko0701dca2009-04-11 10:38:47 +00003241 debug_printf_clean(" command %d:\n", i);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003242 if (command->argv) {
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003243 if (DEBUG_CLEAN) {
3244 int a;
3245 char **p;
3246 for (a = 0, p = command->argv; *p; a++, p++) {
3247 debug_printf_clean(" argv[%d] = %s\n", a, *p);
3248 }
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003249 }
3250 free_strings(command->argv);
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003251 //command->argv = NULL;
Denis Vlasenkob6e65562009-04-03 16:49:04 +00003252 }
3253 /* not "else if": on syntax error, we may have both! */
3254 if (command->group) {
Denys Vlasenko9d617c42009-06-09 18:40:52 +02003255 debug_printf_clean(" begin group (cmd_type:%d)\n",
3256 command->cmd_type);
Denis Vlasenko0701dca2009-04-11 10:38:47 +00003257 free_pipe_list(command->group);
3258 debug_printf_clean(" end group\n");
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003259 //command->group = NULL;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003260 }
Denis Vlasenkoed055212009-04-11 10:37:10 +00003261 /* else is crucial here.
3262 * If group != NULL, child_func is meaningless */
3263#if ENABLE_HUSH_FUNCTIONS
3264 else if (command->child_func) {
3265 debug_printf_exec("cmd %p releases child func at %p\n", command, command->child_func);
3266 command->child_func->parent_cmd = NULL;
3267 }
3268#endif
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00003269#if !BB_MMU
3270 free(command->group_as_string);
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003271 //command->group_as_string = NULL;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00003272#endif
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003273 for (r = command->redirects; r; r = rnext) {
Denis Vlasenko0701dca2009-04-11 10:38:47 +00003274 debug_printf_clean(" redirect %d%s",
3275 r->rd_fd, redir_table[r->rd_type].descrip);
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +00003276 /* guard against the case >$FOO, where foo is unset or blank */
3277 if (r->rd_filename) {
3278 debug_printf_clean(" fname:'%s'\n", r->rd_filename);
3279 free(r->rd_filename);
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003280 //r->rd_filename = NULL;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003281 }
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +00003282 debug_printf_clean(" rd_dup:%d\n", r->rd_dup);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003283 rnext = r->next;
3284 free(r);
3285 }
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003286 //command->redirects = NULL;
Denis Vlasenkof886fd22008-10-13 12:36:05 +00003287 }
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003288 free(pi->cmds); /* children are an array, they get freed all at once */
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003289 //pi->cmds = NULL;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003290#if ENABLE_HUSH_JOB
3291 free(pi->cmdtext);
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003292 //pi->cmdtext = NULL;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003293#endif
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003294
3295 next = pi->next;
3296 free(pi);
3297 return next;
Denis Vlasenkof886fd22008-10-13 12:36:05 +00003298}
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00003299
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003300static void free_pipe_list(struct pipe *pi)
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003301{
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003302 while (pi) {
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003303#if HAS_KEYWORDS
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003304 debug_printf_clean("pipe reserved word %d\n", pi->res_word);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003305#endif
Denis Vlasenko0701dca2009-04-11 10:38:47 +00003306 debug_printf_clean("pipe followup code %d\n", pi->followup);
Denys Vlasenko27c56f12010-09-07 09:56:34 +02003307 pi = free_pipe(pi);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003308 }
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003309}
3310
3311
Denys Vlasenkob36abf22010-09-05 14:50:59 +02003312/*** Parsing routines ***/
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00003313
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01003314#ifndef debug_print_tree
3315static void debug_print_tree(struct pipe *pi, int lvl)
3316{
3317 static const char *const PIPE[] = {
3318 [PIPE_SEQ] = "SEQ",
3319 [PIPE_AND] = "AND",
3320 [PIPE_OR ] = "OR" ,
3321 [PIPE_BG ] = "BG" ,
3322 };
3323 static const char *RES[] = {
3324 [RES_NONE ] = "NONE" ,
3325# if ENABLE_HUSH_IF
3326 [RES_IF ] = "IF" ,
3327 [RES_THEN ] = "THEN" ,
3328 [RES_ELIF ] = "ELIF" ,
3329 [RES_ELSE ] = "ELSE" ,
3330 [RES_FI ] = "FI" ,
3331# endif
3332# if ENABLE_HUSH_LOOPS
3333 [RES_FOR ] = "FOR" ,
3334 [RES_WHILE] = "WHILE",
3335 [RES_UNTIL] = "UNTIL",
3336 [RES_DO ] = "DO" ,
3337 [RES_DONE ] = "DONE" ,
3338# endif
3339# if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
3340 [RES_IN ] = "IN" ,
3341# endif
3342# if ENABLE_HUSH_CASE
3343 [RES_CASE ] = "CASE" ,
3344 [RES_CASE_IN ] = "CASE_IN" ,
3345 [RES_MATCH] = "MATCH",
3346 [RES_CASE_BODY] = "CASE_BODY",
3347 [RES_ESAC ] = "ESAC" ,
3348# endif
3349 [RES_XXXX ] = "XXXX" ,
3350 [RES_SNTX ] = "SNTX" ,
3351 };
3352 static const char *const CMDTYPE[] = {
3353 "{}",
3354 "()",
3355 "[noglob]",
3356# if ENABLE_HUSH_FUNCTIONS
3357 "func()",
3358# endif
3359 };
3360
3361 int pin, prn;
3362
3363 pin = 0;
3364 while (pi) {
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01003365 fdprintf(2, "%*spipe %d res_word=%s followup=%d %s\n", lvl*2, "",
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01003366 pin, RES[pi->res_word], pi->followup, PIPE[pi->followup]);
3367 prn = 0;
3368 while (prn < pi->num_cmds) {
3369 struct command *command = &pi->cmds[prn];
3370 char **argv = command->argv;
3371
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01003372 fdprintf(2, "%*s cmd %d assignment_cnt:%d",
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01003373 lvl*2, "", prn,
3374 command->assignment_cnt);
3375 if (command->group) {
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01003376 fdprintf(2, " group %s: (argv=%p)%s%s\n",
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01003377 CMDTYPE[command->cmd_type],
3378 argv
3379# if !BB_MMU
3380 , " group_as_string:", command->group_as_string
3381# else
3382 , "", ""
3383# endif
3384 );
3385 debug_print_tree(command->group, lvl+1);
3386 prn++;
3387 continue;
3388 }
3389 if (argv) while (*argv) {
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01003390 fdprintf(2, " '%s'", *argv);
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01003391 argv++;
3392 }
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01003393 fdprintf(2, "\n");
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01003394 prn++;
3395 }
3396 pi = pi->next;
3397 pin++;
3398 }
3399}
3400#endif /* debug_print_tree */
3401
Denis Vlasenkoac678ec2007-04-16 22:32:04 +00003402static struct pipe *new_pipe(void)
3403{
Eric Andersen25f27032001-04-26 23:22:31 +00003404 struct pipe *pi;
Denis Vlasenko3ac0e002007-04-28 16:45:22 +00003405 pi = xzalloc(sizeof(struct pipe));
Denis Vlasenko5ec61322008-06-24 00:50:07 +00003406 /*pi->res_word = RES_NONE; - RES_NONE is 0 anyway */
Eric Andersen25f27032001-04-26 23:22:31 +00003407 return pi;
3408}
3409
Denis Vlasenkof8c1f022009-04-17 11:55:42 +00003410/* Command (member of a pipe) is complete, or we start a new pipe
3411 * if ctx->command is NULL.
3412 * No errors possible here.
3413 */
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003414static int done_command(struct parse_context *ctx)
3415{
3416 /* The command is really already in the pipe structure, so
3417 * advance the pipe counter and make a new, null command. */
3418 struct pipe *pi = ctx->pipe;
3419 struct command *command = ctx->command;
3420
Denys Vlasenkod6a37d82016-09-20 16:22:24 +02003421#if 0 /* Instead we emit error message at run time */
3422 if (ctx->pending_redirect) {
3423 /* For example, "cmd >" (no filename to redirect to) */
Denys Vlasenko39701202017-08-02 19:44:05 +02003424 syntax_error("invalid redirect");
Denys Vlasenkod6a37d82016-09-20 16:22:24 +02003425 ctx->pending_redirect = NULL;
3426 }
3427#endif
3428
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003429 if (command) {
Denis Vlasenkof8c1f022009-04-17 11:55:42 +00003430 if (IS_NULL_CMD(command)) {
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003431 debug_printf_parse("done_command: skipping null cmd, num_cmds=%d\n", pi->num_cmds);
Denis Vlasenkof8c1f022009-04-17 11:55:42 +00003432 goto clear_and_ret;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003433 }
3434 pi->num_cmds++;
3435 debug_printf_parse("done_command: ++num_cmds=%d\n", pi->num_cmds);
Denis Vlasenkocd418a22009-04-06 18:08:35 +00003436 //debug_print_tree(ctx->list_head, 20);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003437 } else {
3438 debug_printf_parse("done_command: initializing, num_cmds=%d\n", pi->num_cmds);
3439 }
3440
3441 /* Only real trickiness here is that the uncommitted
3442 * command structure is not counted in pi->num_cmds. */
3443 pi->cmds = xrealloc(pi->cmds, sizeof(*pi->cmds) * (pi->num_cmds+1));
Denis Vlasenkof8c1f022009-04-17 11:55:42 +00003444 ctx->command = command = &pi->cmds[pi->num_cmds];
3445 clear_and_ret:
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003446 memset(command, 0, sizeof(*command));
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003447 return pi->num_cmds; /* used only for 0/nonzero check */
3448}
3449
3450static void done_pipe(struct parse_context *ctx, pipe_style type)
3451{
3452 int not_null;
3453
3454 debug_printf_parse("done_pipe entered, followup %d\n", type);
3455 /* Close previous command */
3456 not_null = done_command(ctx);
Denis Vlasenkocd418a22009-04-06 18:08:35 +00003457#if HAS_KEYWORDS
3458 ctx->pipe->pi_inverted = ctx->ctx_inverted;
3459 ctx->ctx_inverted = 0;
3460 ctx->pipe->res_word = ctx->ctx_res_w;
3461#endif
Denys Vlasenkob24e55d2017-07-16 20:29:35 +02003462 if (type == PIPE_BG && ctx->list_head != ctx->pipe) {
3463 /* Necessary since && and || have precedence over &:
Denys Vlasenkoee553b92017-07-15 22:51:55 +02003464 * "cmd1 && cmd2 &" must spawn both cmds, not only cmd2,
3465 * in a backgrounded subshell.
3466 */
3467 struct pipe *pi;
3468 struct command *command;
3469
Denys Vlasenkob24e55d2017-07-16 20:29:35 +02003470 /* Is this actually this construct, all pipes end with && or ||? */
Denys Vlasenkoee553b92017-07-15 22:51:55 +02003471 pi = ctx->list_head;
3472 while (pi != ctx->pipe) {
3473 if (pi->followup != PIPE_AND && pi->followup != PIPE_OR)
3474 goto no_conv;
3475 pi = pi->next;
3476 }
3477
3478 debug_printf_parse("BG with more than one pipe, converting to { p1 &&...pN; } &\n");
3479 pi->followup = PIPE_SEQ; /* close pN _not_ with "&"! */
3480 pi = xzalloc(sizeof(*pi));
3481 pi->followup = PIPE_BG;
3482 pi->num_cmds = 1;
3483 pi->cmds = xzalloc(sizeof(pi->cmds[0]));
3484 command = &pi->cmds[0];
3485 if (CMD_NORMAL != 0) /* "if xzalloc didn't do that already" */
3486 command->cmd_type = CMD_NORMAL;
3487 command->group = ctx->list_head;
3488#if !BB_MMU
Denys Vlasenkob24e55d2017-07-16 20:29:35 +02003489 command->group_as_string = xstrndup(
3490 ctx->as_string.data,
3491 ctx->as_string.length - 1 /* do not copy last char, "&" */
3492 );
Denys Vlasenkoee553b92017-07-15 22:51:55 +02003493#endif
3494 /* Replace all pipes in ctx with one newly created */
3495 ctx->list_head = ctx->pipe = pi;
Denys Vlasenkob24e55d2017-07-16 20:29:35 +02003496 } else {
3497 no_conv:
3498 ctx->pipe->followup = type;
Denys Vlasenkoee553b92017-07-15 22:51:55 +02003499 }
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003500
3501 /* Without this check, even just <enter> on command line generates
3502 * tree of three NOPs (!). Which is harmless but annoying.
Denis Vlasenkof8c1f022009-04-17 11:55:42 +00003503 * IOW: it is safe to do it unconditionally. */
Denis Vlasenkocd418a22009-04-06 18:08:35 +00003504 if (not_null
Denis Vlasenko7f959372009-04-14 08:06:59 +00003505#if ENABLE_HUSH_IF
Denis Vlasenkocd418a22009-04-06 18:08:35 +00003506 || ctx->ctx_res_w == RES_FI
Denis Vlasenko7f959372009-04-14 08:06:59 +00003507#endif
3508#if ENABLE_HUSH_LOOPS
Denis Vlasenkocd418a22009-04-06 18:08:35 +00003509 || ctx->ctx_res_w == RES_DONE
3510 || ctx->ctx_res_w == RES_FOR
3511 || ctx->ctx_res_w == RES_IN
Denis Vlasenko7f959372009-04-14 08:06:59 +00003512#endif
3513#if ENABLE_HUSH_CASE
Denis Vlasenkocd418a22009-04-06 18:08:35 +00003514 || ctx->ctx_res_w == RES_ESAC
3515#endif
3516 ) {
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003517 struct pipe *new_p;
3518 debug_printf_parse("done_pipe: adding new pipe: "
3519 "not_null:%d ctx->ctx_res_w:%d\n",
3520 not_null, ctx->ctx_res_w);
3521 new_p = new_pipe();
3522 ctx->pipe->next = new_p;
3523 ctx->pipe = new_p;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003524 /* RES_THEN, RES_DO etc are "sticky" -
Denis Vlasenkof8c1f022009-04-17 11:55:42 +00003525 * they remain set for pipes inside if/while.
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003526 * This is used to control execution.
3527 * RES_FOR and RES_IN are NOT sticky (needed to support
3528 * cases where variable or value happens to match a keyword):
3529 */
3530#if ENABLE_HUSH_LOOPS
3531 if (ctx->ctx_res_w == RES_FOR
3532 || ctx->ctx_res_w == RES_IN)
3533 ctx->ctx_res_w = RES_NONE;
3534#endif
3535#if ENABLE_HUSH_CASE
3536 if (ctx->ctx_res_w == RES_MATCH)
Denys Vlasenkoe9bda902009-05-23 16:50:07 +02003537 ctx->ctx_res_w = RES_CASE_BODY;
3538 if (ctx->ctx_res_w == RES_CASE)
3539 ctx->ctx_res_w = RES_CASE_IN;
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003540#endif
Denis Vlasenkob6e65562009-04-03 16:49:04 +00003541 ctx->command = NULL; /* trick done_command below */
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003542 /* Create the memory for command, roughly:
3543 * ctx->pipe->cmds = new struct command;
3544 * ctx->command = &ctx->pipe->cmds[0];
3545 */
3546 done_command(ctx);
Denis Vlasenkocd418a22009-04-06 18:08:35 +00003547 //debug_print_tree(ctx->list_head, 10);
Denis Vlasenko424f79b2009-03-22 14:23:34 +00003548 }
3549 debug_printf_parse("done_pipe return\n");
3550}
3551
Denis Vlasenko9af22c72008-10-09 12:54:58 +00003552static void initialize_context(struct parse_context *ctx)
Eric Andersen25f27032001-04-26 23:22:31 +00003553{
Denis Vlasenkoa8442002008-06-14 11:00:17 +00003554 memset(ctx, 0, sizeof(*ctx));
Denis Vlasenko1a735862007-05-23 00:32:25 +00003555 ctx->pipe = ctx->list_head = new_pipe();
Denis Vlasenko9af22c72008-10-09 12:54:58 +00003556 /* Create the memory for command, roughly:
3557 * ctx->pipe->cmds = new struct command;
3558 * ctx->command = &ctx->pipe->cmds[0];
Denis Vlasenkoa8442002008-06-14 11:00:17 +00003559 */
3560 done_command(ctx);
Eric Andersen25f27032001-04-26 23:22:31 +00003561}
3562
Denis Vlasenkoa8442002008-06-14 11:00:17 +00003563/* If a reserved word is found and processed, parse context is modified
3564 * and 1 is returned.
Eric Andersen25f27032001-04-26 23:22:31 +00003565 */
Denis Vlasenko5ec61322008-06-24 00:50:07 +00003566#if HAS_KEYWORDS
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003567struct reserved_combo {
3568 char literal[6];
3569 unsigned char res;
3570 unsigned char assignment_flag;
3571 int flag;
3572};
3573enum {
3574 FLAG_END = (1 << RES_NONE ),
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003575# if ENABLE_HUSH_IF
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003576 FLAG_IF = (1 << RES_IF ),
3577 FLAG_THEN = (1 << RES_THEN ),
3578 FLAG_ELIF = (1 << RES_ELIF ),
3579 FLAG_ELSE = (1 << RES_ELSE ),
3580 FLAG_FI = (1 << RES_FI ),
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003581# endif
3582# if ENABLE_HUSH_LOOPS
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003583 FLAG_FOR = (1 << RES_FOR ),
3584 FLAG_WHILE = (1 << RES_WHILE),
3585 FLAG_UNTIL = (1 << RES_UNTIL),
3586 FLAG_DO = (1 << RES_DO ),
3587 FLAG_DONE = (1 << RES_DONE ),
3588 FLAG_IN = (1 << RES_IN ),
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003589# endif
3590# if ENABLE_HUSH_CASE
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003591 FLAG_MATCH = (1 << RES_MATCH),
3592 FLAG_ESAC = (1 << RES_ESAC ),
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003593# endif
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003594 FLAG_START = (1 << RES_XXXX ),
3595};
3596
3597static const struct reserved_combo* match_reserved_word(o_string *word)
3598{
Eric Andersen25f27032001-04-26 23:22:31 +00003599 /* Mostly a list of accepted follow-up reserved words.
3600 * FLAG_END means we are done with the sequence, and are ready
3601 * to turn the compound list into a command.
3602 * FLAG_START means the word must start a new compound list.
3603 */
Denis Vlasenkoc72c1ed2007-01-30 22:31:26 +00003604 static const struct reserved_combo reserved_list[] = {
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003605# if ENABLE_HUSH_IF
Denys Vlasenko29f9b722011-05-14 11:27:36 +02003606 { "!", RES_NONE, NOT_ASSIGNMENT , 0 },
3607 { "if", RES_IF, MAYBE_ASSIGNMENT, FLAG_THEN | FLAG_START },
3608 { "then", RES_THEN, MAYBE_ASSIGNMENT, FLAG_ELIF | FLAG_ELSE | FLAG_FI },
3609 { "elif", RES_ELIF, MAYBE_ASSIGNMENT, FLAG_THEN },
3610 { "else", RES_ELSE, MAYBE_ASSIGNMENT, FLAG_FI },
3611 { "fi", RES_FI, NOT_ASSIGNMENT , FLAG_END },
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003612# endif
3613# if ENABLE_HUSH_LOOPS
Denys Vlasenko29f9b722011-05-14 11:27:36 +02003614 { "for", RES_FOR, NOT_ASSIGNMENT , FLAG_IN | FLAG_DO | FLAG_START },
3615 { "while", RES_WHILE, MAYBE_ASSIGNMENT, FLAG_DO | FLAG_START },
3616 { "until", RES_UNTIL, MAYBE_ASSIGNMENT, FLAG_DO | FLAG_START },
3617 { "in", RES_IN, NOT_ASSIGNMENT , FLAG_DO },
3618 { "do", RES_DO, MAYBE_ASSIGNMENT, FLAG_DONE },
3619 { "done", RES_DONE, NOT_ASSIGNMENT , FLAG_END },
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003620# endif
3621# if ENABLE_HUSH_CASE
Denys Vlasenko29f9b722011-05-14 11:27:36 +02003622 { "case", RES_CASE, NOT_ASSIGNMENT , FLAG_MATCH | FLAG_START },
3623 { "esac", RES_ESAC, NOT_ASSIGNMENT , FLAG_END },
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003624# endif
Eric Andersen25f27032001-04-26 23:22:31 +00003625 };
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003626 const struct reserved_combo *r;
3627
Denys Vlasenkoe4dcba12010-10-28 18:57:19 +02003628 for (r = reserved_list; r < reserved_list + ARRAY_SIZE(reserved_list); r++) {
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003629 if (strcmp(word->data, r->literal) == 0)
3630 return r;
3631 }
3632 return NULL;
3633}
Denis Vlasenkobb929512009-04-16 10:59:40 +00003634/* Return 0: not a keyword, 1: keyword
3635 */
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003636static int reserved_word(o_string *word, struct parse_context *ctx)
3637{
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003638# if ENABLE_HUSH_CASE
Denis Vlasenko17f02e72008-07-14 04:32:29 +00003639 static const struct reserved_combo reserved_match = {
Denis Vlasenko2b576b82008-08-04 00:46:07 +00003640 "", RES_MATCH, NOT_ASSIGNMENT , FLAG_MATCH | FLAG_ESAC
Denis Vlasenko17f02e72008-07-14 04:32:29 +00003641 };
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003642# endif
Denis Vlasenkoc72c1ed2007-01-30 22:31:26 +00003643 const struct reserved_combo *r;
Denis Vlasenkoc72c1ed2007-01-30 22:31:26 +00003644
Denys Vlasenko38292b62010-09-05 14:49:40 +02003645 if (word->has_quoted_part)
Denis Vlasenkobb929512009-04-16 10:59:40 +00003646 return 0;
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003647 r = match_reserved_word(word);
3648 if (!r)
3649 return 0;
3650
3651 debug_printf("found reserved word %s, res %d\n", r->literal, r->res);
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003652# if ENABLE_HUSH_CASE
Denys Vlasenkoe9bda902009-05-23 16:50:07 +02003653 if (r->res == RES_IN && ctx->ctx_res_w == RES_CASE_IN) {
3654 /* "case word IN ..." - IN part starts first MATCH part */
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003655 r = &reserved_match;
Denys Vlasenkoe9bda902009-05-23 16:50:07 +02003656 } else
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003657# endif
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003658 if (r->flag == 0) { /* '!' */
3659 if (ctx->ctx_inverted) { /* bash doesn't accept '! ! true' */
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00003660 syntax_error("! ! command");
Denis Vlasenkobb929512009-04-16 10:59:40 +00003661 ctx->ctx_res_w = RES_SNTX;
Eric Andersen25f27032001-04-26 23:22:31 +00003662 }
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003663 ctx->ctx_inverted = 1;
Denis Vlasenko1a735862007-05-23 00:32:25 +00003664 return 1;
Eric Andersen25f27032001-04-26 23:22:31 +00003665 }
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003666 if (r->flag & FLAG_START) {
Denis Vlasenkob6e65562009-04-03 16:49:04 +00003667 struct parse_context *old;
Denis Vlasenkobb929512009-04-16 10:59:40 +00003668
Denys Vlasenko9e55a152017-07-10 10:01:12 +02003669 old = xmemdup(ctx, sizeof(*ctx));
Denis Vlasenkob6e65562009-04-03 16:49:04 +00003670 debug_printf_parse("push stack %p\n", old);
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003671 initialize_context(ctx);
Denis Vlasenkob6e65562009-04-03 16:49:04 +00003672 ctx->stack = old;
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003673 } else if (/*ctx->ctx_res_w == RES_NONE ||*/ !(ctx->old_flag & (1 << r->res))) {
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00003674 syntax_error_at(word->data);
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003675 ctx->ctx_res_w = RES_SNTX;
3676 return 1;
Denis Vlasenkobb929512009-04-16 10:59:40 +00003677 } else {
3678 /* "{...} fi" is ok. "{...} if" is not
3679 * Example:
3680 * if { echo foo; } then { echo bar; } fi */
3681 if (ctx->command->group)
3682 done_pipe(ctx, PIPE_SEQ);
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003683 }
Denis Vlasenkobb929512009-04-16 10:59:40 +00003684
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003685 ctx->ctx_res_w = r->res;
3686 ctx->old_flag = r->flag;
Denis Vlasenkobb929512009-04-16 10:59:40 +00003687 word->o_assignment = r->assignment_flag;
Denys Vlasenko29f9b722011-05-14 11:27:36 +02003688 debug_printf_parse("word->o_assignment='%s'\n", assignment_flag[word->o_assignment]);
Denis Vlasenkobb929512009-04-16 10:59:40 +00003689
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003690 if (ctx->old_flag & FLAG_END) {
3691 struct parse_context *old;
Denis Vlasenkobb929512009-04-16 10:59:40 +00003692
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003693 done_pipe(ctx, PIPE_SEQ);
Denis Vlasenkob6e65562009-04-03 16:49:04 +00003694 debug_printf_parse("pop stack %p\n", ctx->stack);
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003695 old = ctx->stack;
3696 old->command->group = ctx->list_head;
Denys Vlasenko9d617c42009-06-09 18:40:52 +02003697 old->command->cmd_type = CMD_NORMAL;
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003698# if !BB_MMU
Denys Vlasenkob5be13c2015-09-04 06:22:10 +02003699 /* At this point, the compound command's string is in
3700 * ctx->as_string... except for the leading keyword!
3701 * Consider this example: "echo a | if true; then echo a; fi"
3702 * ctx->as_string will contain "true; then echo a; fi",
3703 * with "if " remaining in old->as_string!
3704 */
3705 {
3706 char *str;
3707 int len = old->as_string.length;
3708 /* Concatenate halves */
3709 o_addstr(&old->as_string, ctx->as_string.data);
3710 o_free_unsafe(&ctx->as_string);
3711 /* Find where leading keyword starts in first half */
3712 str = old->as_string.data + len;
3713 if (str > old->as_string.data)
3714 str--; /* skip whitespace after keyword */
3715 while (str > old->as_string.data && isalpha(str[-1]))
3716 str--;
3717 /* Ugh, we're done with this horrid hack */
3718 old->command->group_as_string = xstrdup(str);
3719 debug_printf_parse("pop, remembering as:'%s'\n",
3720 old->command->group_as_string);
3721 }
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003722# endif
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003723 *ctx = *old; /* physical copy */
3724 free(old);
3725 }
Denis Vlasenkoc3735272008-10-09 12:58:26 +00003726 return 1;
Eric Andersen25f27032001-04-26 23:22:31 +00003727}
Denys Vlasenkoc0836532009-10-19 13:13:06 +02003728#endif /* HAS_KEYWORDS */
Eric Andersen25f27032001-04-26 23:22:31 +00003729
Denis Vlasenkoa8442002008-06-14 11:00:17 +00003730/* Word is complete, look at it and update parsing context.
Denis Vlasenkob6e65562009-04-03 16:49:04 +00003731 * Normal return is 0. Syntax errors return 1.
3732 * Note: on return, word is reset, but not o_free'd!
3733 */
Denis Vlasenko9af22c72008-10-09 12:54:58 +00003734static int done_word(o_string *word, struct parse_context *ctx)
Eric Andersen25f27032001-04-26 23:22:31 +00003735{
Denis Vlasenko9af22c72008-10-09 12:54:58 +00003736 struct command *command = ctx->command;
Eric Andersen25f27032001-04-26 23:22:31 +00003737
Denis Vlasenko9af22c72008-10-09 12:54:58 +00003738 debug_printf_parse("done_word entered: '%s' %p\n", word->data, command);
Denys Vlasenko38292b62010-09-05 14:49:40 +02003739 if (word->length == 0 && !word->has_quoted_part) {
Denis Vlasenkoab876cd2008-06-18 16:29:32 +00003740 debug_printf_parse("done_word return 0: true null, ignored\n");
3741 return 0;
Eric Andersen25f27032001-04-26 23:22:31 +00003742 }
Denis Vlasenko2b576b82008-08-04 00:46:07 +00003743
Eric Andersen25f27032001-04-26 23:22:31 +00003744 if (ctx->pending_redirect) {
Denis Vlasenkoab876cd2008-06-18 16:29:32 +00003745 /* We do not glob in e.g. >*.tmp case. bash seems to glob here
3746 * only if run as "bash", not "sh" */
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003747 /* http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
3748 * "2.7 Redirection
3749 * ...the word that follows the redirection operator
3750 * shall be subjected to tilde expansion, parameter expansion,
3751 * command substitution, arithmetic expansion, and quote
3752 * removal. Pathname expansion shall not be performed
3753 * on the word by a non-interactive shell; an interactive
3754 * shell may perform it, but shall do so only when
3755 * the expansion would result in one word."
3756 */
Denis Vlasenkoab876cd2008-06-18 16:29:32 +00003757 ctx->pending_redirect->rd_filename = xstrdup(word->data);
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00003758 /* Cater for >\file case:
3759 * >\a creates file a; >\\a, >"\a", >"\\a" create file \a
3760 * Same with heredocs:
3761 * for <<\H delim is H; <<\\H, <<"\H", <<"\\H" - \H
3762 */
Denys Vlasenkoe640cb42009-05-28 16:49:11 +02003763 if (ctx->pending_redirect->rd_type == REDIRECT_HEREDOC) {
3764 unbackslash(ctx->pending_redirect->rd_filename);
3765 /* Is it <<"HEREDOC"? */
Denys Vlasenko38292b62010-09-05 14:49:40 +02003766 if (word->has_quoted_part) {
Denys Vlasenkoe640cb42009-05-28 16:49:11 +02003767 ctx->pending_redirect->rd_dup |= HEREDOC_QUOTED;
3768 }
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +00003769 }
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003770 debug_printf_parse("word stored in rd_filename: '%s'\n", word->data);
Denis Vlasenko1fd1ea42009-04-10 12:03:20 +00003771 ctx->pending_redirect = NULL;
Eric Andersen25f27032001-04-26 23:22:31 +00003772 } else {
Denis Vlasenko5ec61322008-06-24 00:50:07 +00003773#if HAS_KEYWORDS
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00003774# if ENABLE_HUSH_CASE
Denis Vlasenko757361f2008-07-14 08:26:47 +00003775 if (ctx->ctx_dsemicolon
3776 && strcmp(word->data, "esac") != 0 /* not "... pattern) cmd;; esac" */
3777 ) {
Denis Vlasenko395ae452008-07-14 06:29:38 +00003778 /* already done when ctx_dsemicolon was set to 1: */
Denis Vlasenko17f02e72008-07-14 04:32:29 +00003779 /* ctx->ctx_res_w = RES_MATCH; */
3780 ctx->ctx_dsemicolon = 0;
3781 } else
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00003782# endif
Denis Vlasenko9af22c72008-10-09 12:54:58 +00003783 if (!command->argv /* if it's the first word... */
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00003784# if ENABLE_HUSH_LOOPS
Denis Vlasenko733e3fb2008-07-06 10:01:13 +00003785 && ctx->ctx_res_w != RES_FOR /* ...not after FOR or IN */
3786 && ctx->ctx_res_w != RES_IN
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00003787# endif
Denys Vlasenkoe9bda902009-05-23 16:50:07 +02003788# if ENABLE_HUSH_CASE
3789 && ctx->ctx_res_w != RES_CASE
3790# endif
Denis Vlasenko733e3fb2008-07-06 10:01:13 +00003791 ) {
Denys Vlasenko29f9b722011-05-14 11:27:36 +02003792 int reserved = reserved_word(word, ctx);
3793 debug_printf_parse("checking for reserved-ness: %d\n", reserved);
3794 if (reserved) {
Denis Vlasenko0b677d82009-04-10 13:49:10 +00003795 o_reset_to_empty_unquoted(word);
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00003796 debug_printf_parse("done_word return %d\n",
3797 (ctx->ctx_res_w == RES_SNTX));
Denis Vlasenko5ec61322008-06-24 00:50:07 +00003798 return (ctx->ctx_res_w == RES_SNTX);
Denis Vlasenkoe725bfe2007-05-03 22:45:39 +00003799 }
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01003800# if BASH_TEST2
Denys Vlasenko9d617c42009-06-09 18:40:52 +02003801 if (strcmp(word->data, "[[") == 0) {
3802 command->cmd_type = CMD_SINGLEWORD_NOGLOB;
3803 }
3804 /* fall through */
Denys Vlasenko9ca656b2009-06-10 13:39:35 +02003805# endif
Eric Andersen25f27032001-04-26 23:22:31 +00003806 }
Denis Vlasenko5ec61322008-06-24 00:50:07 +00003807#endif
Denis Vlasenkobb929512009-04-16 10:59:40 +00003808 if (command->group) {
3809 /* "{ echo foo; } echo bar" - bad */
3810 syntax_error_at(word->data);
3811 debug_printf_parse("done_word return 1: syntax error, "
3812 "groups and arglists don't mix\n");
3813 return 1;
3814 }
Denys Vlasenko29f9b722011-05-14 11:27:36 +02003815
3816 /* If this word wasn't an assignment, next ones definitely
3817 * can't be assignments. Even if they look like ones. */
3818 if (word->o_assignment != DEFINITELY_ASSIGNMENT
3819 && word->o_assignment != WORD_IS_KEYWORD
3820 ) {
3821 word->o_assignment = NOT_ASSIGNMENT;
3822 } else {
3823 if (word->o_assignment == DEFINITELY_ASSIGNMENT) {
3824 command->assignment_cnt++;
3825 debug_printf_parse("++assignment_cnt=%d\n", command->assignment_cnt);
3826 }
3827 debug_printf_parse("word->o_assignment was:'%s'\n", assignment_flag[word->o_assignment]);
3828 word->o_assignment = MAYBE_ASSIGNMENT;
3829 }
3830 debug_printf_parse("word->o_assignment='%s'\n", assignment_flag[word->o_assignment]);
3831
Denys Vlasenko38292b62010-09-05 14:49:40 +02003832 if (word->has_quoted_part
Denis Vlasenko55789c62008-06-18 16:30:42 +00003833 /* optimization: and if it's ("" or '') or ($v... or `cmd`...): */
3834 && (word->data[0] == '\0' || word->data[0] == SPECIAL_VAR_SYMBOL)
Denis Vlasenko733e3fb2008-07-06 10:01:13 +00003835 /* (otherwise it's known to be not empty and is already safe) */
Denis Vlasenkoab876cd2008-06-18 16:29:32 +00003836 ) {
Denis Vlasenko733e3fb2008-07-06 10:01:13 +00003837 /* exclude "$@" - it can expand to no word despite "" */
Denis Vlasenkoafdcd122008-07-05 17:40:04 +00003838 char *p = word->data;
3839 while (p[0] == SPECIAL_VAR_SYMBOL
3840 && (p[1] & 0x7f) == '@'
3841 && p[2] == SPECIAL_VAR_SYMBOL
3842 ) {
3843 p += 3;
3844 }
Denis Vlasenkoc1c63b62008-06-18 09:20:35 +00003845 }
Denis Vlasenko22d10a02008-10-13 08:53:43 +00003846 command->argv = add_string_to_strings(command->argv, xstrdup(word->data));
Denis Vlasenko9af22c72008-10-09 12:54:58 +00003847 debug_print_strings("word appended to argv", command->argv);
Denis Vlasenkoe725bfe2007-05-03 22:45:39 +00003848 }
Eric Andersen25f27032001-04-26 23:22:31 +00003849
Denis Vlasenko06810332007-05-21 23:30:54 +00003850#if ENABLE_HUSH_LOOPS
Denis Vlasenko733e3fb2008-07-06 10:01:13 +00003851 if (ctx->ctx_res_w == RES_FOR) {
Denys Vlasenko38292b62010-09-05 14:49:40 +02003852 if (word->has_quoted_part
Denis Vlasenko1fd1ea42009-04-10 12:03:20 +00003853 || !is_well_formed_var_name(command->argv[0], '\0')
3854 ) {
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +00003855 /* bash says just "not a valid identifier" */
Denis Vlasenko1fd1ea42009-04-10 12:03:20 +00003856 syntax_error("not a valid identifier in for");
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00003857 return 1;
3858 }
Denis Vlasenko1fd1ea42009-04-10 12:03:20 +00003859 /* Force FOR to have just one word (variable name) */
3860 /* NB: basically, this makes hush see "for v in ..."
3861 * syntax as if it is "for v; in ...". FOR and IN become
3862 * two pipe structs in parse tree. */
Denis Vlasenkofbf6dea2007-04-13 19:56:56 +00003863 done_pipe(ctx, PIPE_SEQ);
Denis Vlasenko733e3fb2008-07-06 10:01:13 +00003864 }
Denis Vlasenko06810332007-05-21 23:30:54 +00003865#endif
Denis Vlasenko17f02e72008-07-14 04:32:29 +00003866#if ENABLE_HUSH_CASE
3867 /* Force CASE to have just one word */
3868 if (ctx->ctx_res_w == RES_CASE) {
3869 done_pipe(ctx, PIPE_SEQ);
3870 }
3871#endif
Denis Vlasenko1fd1ea42009-04-10 12:03:20 +00003872
Denis Vlasenko0b677d82009-04-10 13:49:10 +00003873 o_reset_to_empty_unquoted(word);
Denis Vlasenko1fd1ea42009-04-10 12:03:20 +00003874
Denis Vlasenkoe725bfe2007-05-03 22:45:39 +00003875 debug_printf_parse("done_word return 0\n");
Eric Andersen25f27032001-04-26 23:22:31 +00003876 return 0;
3877}
3878
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003879
3880/* Peek ahead in the input to find out if we have a "&n" construct,
3881 * as in "2>&1", that represents duplicating a file descriptor.
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00003882 * Return:
3883 * REDIRFD_CLOSE if >&- "close fd" construct is seen,
3884 * REDIRFD_SYNTAX_ERR if syntax error,
3885 * REDIRFD_TO_FILE if no & was seen,
3886 * or the number found.
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003887 */
3888#if BB_MMU
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00003889#define parse_redir_right_fd(as_string, input) \
3890 parse_redir_right_fd(input)
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003891#endif
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00003892static int parse_redir_right_fd(o_string *as_string, struct in_str *input)
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003893{
3894 int ch, d, ok;
3895
3896 ch = i_peek(input);
3897 if (ch != '&')
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00003898 return REDIRFD_TO_FILE;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003899
3900 ch = i_getch(input); /* get the & */
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00003901 nommu_addchr(as_string, ch);
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003902 ch = i_peek(input);
3903 if (ch == '-') {
3904 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00003905 nommu_addchr(as_string, ch);
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +00003906 return REDIRFD_CLOSE;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003907 }
3908 d = 0;
3909 ok = 0;
3910 while (ch != EOF && isdigit(ch)) {
3911 d = d*10 + (ch-'0');
3912 ok = 1;
3913 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00003914 nommu_addchr(as_string, ch);
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003915 ch = i_peek(input);
3916 }
3917 if (ok) return d;
3918
3919//TODO: this is the place to catch ">&file" bashism (redirect both fd 1 and 2)
3920
3921 bb_error_msg("ambiguous redirect");
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00003922 return REDIRFD_SYNTAX_ERR;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003923}
3924
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00003925/* Return code is 0 normal, 1 if a syntax error is detected
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003926 */
3927static int parse_redirect(struct parse_context *ctx,
3928 int fd,
3929 redir_type style,
3930 struct in_str *input)
3931{
3932 struct command *command = ctx->command;
3933 struct redir_struct *redir;
3934 struct redir_struct **redirp;
3935 int dup_num;
3936
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00003937 dup_num = REDIRFD_TO_FILE;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003938 if (style != REDIRECT_HEREDOC) {
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00003939 /* Check for a '>&1' type redirect */
3940 dup_num = parse_redir_right_fd(&ctx->as_string, input);
3941 if (dup_num == REDIRFD_SYNTAX_ERR)
3942 return 1;
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00003943 } else {
3944 int ch = i_peek(input);
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +00003945 dup_num = (ch == '-'); /* HEREDOC_SKIPTABS bit is 1 */
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00003946 if (dup_num) { /* <<-... */
3947 ch = i_getch(input);
3948 nommu_addchr(&ctx->as_string, ch);
3949 ch = i_peek(input);
3950 }
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003951 }
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003952
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00003953 if (style == REDIRECT_OVERWRITE && dup_num == REDIRFD_TO_FILE) {
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003954 int ch = i_peek(input);
3955 if (ch == '|') {
3956 /* >|FILE redirect ("clobbering" >).
3957 * Since we do not support "set -o noclobber" yet,
3958 * >| and > are the same for now. Just eat |.
3959 */
3960 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00003961 nommu_addchr(&ctx->as_string, ch);
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003962 }
3963 }
3964
3965 /* Create a new redir_struct and append it to the linked list */
3966 redirp = &command->redirects;
3967 while ((redir = *redirp) != NULL) {
3968 redirp = &(redir->next);
3969 }
3970 *redirp = redir = xzalloc(sizeof(*redir));
3971 /* redir->next = NULL; */
3972 /* redir->rd_filename = NULL; */
3973 redir->rd_type = style;
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00003974 redir->rd_fd = (fd == -1) ? redir_table[style].default_fd : fd;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003975
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +00003976 debug_printf_parse("redirect type %d %s\n", redir->rd_fd,
3977 redir_table[style].descrip);
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003978
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00003979 redir->rd_dup = dup_num;
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00003980 if (style != REDIRECT_HEREDOC && dup_num != REDIRFD_TO_FILE) {
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003981 /* Erik had a check here that the file descriptor in question
3982 * is legit; I postpone that to "run time"
3983 * A "-" representation of "close me" shows up as a -3 here */
Denis Vlasenko02d6f1a2009-04-07 19:56:55 +00003984 debug_printf_parse("duplicating redirect '%d>&%d'\n",
3985 redir->rd_fd, redir->rd_dup);
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003986 } else {
Denys Vlasenkod6a37d82016-09-20 16:22:24 +02003987#if 0 /* Instead we emit error message at run time */
3988 if (ctx->pending_redirect) {
3989 /* For example, "cmd > <file" */
Denys Vlasenko39701202017-08-02 19:44:05 +02003990 syntax_error("invalid redirect");
Denys Vlasenkod6a37d82016-09-20 16:22:24 +02003991 }
3992#endif
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00003993 /* Set ctx->pending_redirect, so we know what to do at the
3994 * end of the next parsed word. */
3995 ctx->pending_redirect = redir;
3996 }
3997 return 0;
3998}
3999
Eric Andersen25f27032001-04-26 23:22:31 +00004000/* If a redirect is immediately preceded by a number, that number is
4001 * supposed to tell which file descriptor to redirect. This routine
4002 * looks for such preceding numbers. In an ideal world this routine
4003 * needs to handle all the following classes of redirects...
4004 * echo 2>foo # redirects fd 2 to file "foo", nothing passed to echo
4005 * echo 49>foo # redirects fd 49 to file "foo", nothing passed to echo
4006 * echo -2>foo # redirects fd 1 to file "foo", "-2" passed to echo
4007 * echo 49x>foo # redirects fd 1 to file "foo", "49x" passed to echo
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004008 *
4009 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
4010 * "2.7 Redirection
4011 * ... If n is quoted, the number shall not be recognized as part of
4012 * the redirection expression. For example:
4013 * echo \2>a
4014 * writes the character 2 into file a"
Denys Vlasenko38292b62010-09-05 14:49:40 +02004015 * We are getting it right by setting ->has_quoted_part on any \<char>
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004016 *
4017 * A -1 return means no valid number was found,
4018 * the caller should use the appropriate default for this redirection.
Eric Andersen25f27032001-04-26 23:22:31 +00004019 */
4020static int redirect_opt_num(o_string *o)
4021{
4022 int num;
4023
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004024 if (o->data == NULL)
Denis Vlasenkobb81c582007-01-30 22:32:09 +00004025 return -1;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004026 num = bb_strtou(o->data, NULL, 10);
4027 if (errno || num < 0)
4028 return -1;
Denis Vlasenko0b677d82009-04-10 13:49:10 +00004029 o_reset_to_empty_unquoted(o);
Eric Andersen25f27032001-04-26 23:22:31 +00004030 return num;
4031}
4032
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004033#if BB_MMU
4034#define fetch_till_str(as_string, input, word, skip_tabs) \
4035 fetch_till_str(input, word, skip_tabs)
4036#endif
4037static char *fetch_till_str(o_string *as_string,
4038 struct in_str *input,
4039 const char *word,
Denys Vlasenko77b32cc2010-09-06 11:27:32 +02004040 int heredoc_flags)
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004041{
4042 o_string heredoc = NULL_O_STRING;
Denys Vlasenko5b6210c2010-09-09 13:32:21 +02004043 unsigned past_EOL;
Denys Vlasenko77b32cc2010-09-06 11:27:32 +02004044 int prev = 0; /* not \ */
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004045 int ch;
4046
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004047 goto jump_in;
Denys Vlasenkob8709032011-05-08 21:20:01 +02004048
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004049 while (1) {
4050 ch = i_getch(input);
Denys Vlasenko5b6210c2010-09-09 13:32:21 +02004051 if (ch != EOF)
4052 nommu_addchr(as_string, ch);
Denys Vlasenko0f018b32017-07-29 20:43:26 +02004053 if (ch == '\n' || ch == EOF) {
4054 check_heredoc_end:
4055 if ((heredoc_flags & HEREDOC_QUOTED) || prev != '\\') {
4056 if (strcmp(heredoc.data + past_EOL, word) == 0) {
4057 heredoc.data[past_EOL] = '\0';
4058 debug_printf_parse("parsed heredoc '%s'\n", heredoc.data);
4059 return heredoc.data;
4060 }
4061 if (ch == '\n') {
4062 /* This is a new line.
4063 * Remember position and backslash-escaping status.
4064 */
4065 o_addchr(&heredoc, ch);
4066 prev = ch;
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004067 jump_in:
Denys Vlasenko0f018b32017-07-29 20:43:26 +02004068 past_EOL = heredoc.length;
4069 /* Get 1st char of next line, possibly skipping leading tabs */
4070 do {
4071 ch = i_getch(input);
4072 if (ch != EOF)
4073 nommu_addchr(as_string, ch);
4074 } while ((heredoc_flags & HEREDOC_SKIPTABS) && ch == '\t');
4075 /* If this immediately ended the line,
4076 * go back to end-of-line checks.
4077 */
4078 if (ch == '\n')
4079 goto check_heredoc_end;
4080 }
Denys Vlasenko5b6210c2010-09-09 13:32:21 +02004081 }
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004082 }
4083 if (ch == EOF) {
4084 o_free_unsafe(&heredoc);
4085 return NULL;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004086 }
4087 o_addchr(&heredoc, ch);
Denys Vlasenko5b6210c2010-09-09 13:32:21 +02004088 nommu_addchr(as_string, ch);
Denys Vlasenkoc3adfac2010-09-06 11:46:03 +02004089 if (prev == '\\' && ch == '\\')
4090 /* Correctly handle foo\\<eol> (not a line cont.) */
4091 prev = 0; /* not \ */
4092 else
4093 prev = ch;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004094 }
4095}
4096
Denis Vlasenko3dfb0352009-04-08 09:29:14 +00004097/* Look at entire parse tree for not-yet-loaded REDIRECT_HEREDOCs
4098 * and load them all. There should be exactly heredoc_cnt of them.
4099 */
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004100static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_str *input)
4101{
4102 struct pipe *pi = ctx->list_head;
4103
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00004104 while (pi && heredoc_cnt) {
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004105 int i;
4106 struct command *cmd = pi->cmds;
4107
4108 debug_printf_parse("fetch_heredocs: num_cmds:%d cmd argv0:'%s'\n",
4109 pi->num_cmds,
4110 cmd->argv ? cmd->argv[0] : "NONE");
4111 for (i = 0; i < pi->num_cmds; i++) {
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004112 struct redir_struct *redir = cmd->redirects;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004113
4114 debug_printf_parse("fetch_heredocs: %d cmd argv0:'%s'\n",
4115 i, cmd->argv ? cmd->argv[0] : "NONE");
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004116 while (redir) {
4117 if (redir->rd_type == REDIRECT_HEREDOC) {
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004118 char *p;
4119
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004120 redir->rd_type = REDIRECT_HEREDOC2;
Denys Vlasenko764b2f02009-06-07 16:05:04 +02004121 /* redir->rd_dup is (ab)used to indicate <<- */
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004122 p = fetch_till_str(&ctx->as_string, input,
Denys Vlasenko77b32cc2010-09-06 11:27:32 +02004123 redir->rd_filename, redir->rd_dup);
Denis Vlasenko3dfb0352009-04-08 09:29:14 +00004124 if (!p) {
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00004125 syntax_error("unexpected EOF in here document");
Denis Vlasenko3dfb0352009-04-08 09:29:14 +00004126 return 1;
4127 }
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004128 free(redir->rd_filename);
4129 redir->rd_filename = p;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004130 heredoc_cnt--;
4131 }
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004132 redir = redir->next;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004133 }
4134 cmd++;
4135 }
4136 pi = pi->next;
4137 }
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00004138#if 0
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004139 /* Should be 0. If it isn't, it's a parse error */
Denis Vlasenko3dfb0352009-04-08 09:29:14 +00004140 if (heredoc_cnt)
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00004141 bb_error_msg_and_die("heredoc BUG 2");
4142#endif
4143 return 0;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004144}
4145
4146
Denys Vlasenkob36abf22010-09-05 14:50:59 +02004147static int run_list(struct pipe *pi);
4148#if BB_MMU
4149#define parse_stream(pstring, input, end_trigger) \
4150 parse_stream(input, end_trigger)
4151#endif
4152static struct pipe *parse_stream(char **pstring,
4153 struct in_str *input,
4154 int end_trigger);
Denis Vlasenkoba7cf262007-05-25 14:34:30 +00004155
Eric Andersen25f27032001-04-26 23:22:31 +00004156
Denys Vlasenkoc2704542009-11-20 19:14:19 +01004157#if !ENABLE_HUSH_FUNCTIONS
4158#define parse_group(dest, ctx, input, ch) \
4159 parse_group(ctx, input, ch)
4160#endif
Denis Vlasenko9af22c72008-10-09 12:54:58 +00004161static int parse_group(o_string *dest, struct parse_context *ctx,
Eric Andersen25f27032001-04-26 23:22:31 +00004162 struct in_str *input, int ch)
4163{
Denis Vlasenko371de4a2008-10-14 12:43:13 +00004164 /* dest contains characters seen prior to ( or {.
Denis Vlasenko027e3fd2009-04-02 22:50:40 +00004165 * Typically it's empty, but for function defs,
Denis Vlasenko371de4a2008-10-14 12:43:13 +00004166 * it contains function name (without '()'). */
Denis Vlasenkob6e65562009-04-03 16:49:04 +00004167 struct pipe *pipe_list;
Denis Vlasenko240c2552009-04-03 03:45:05 +00004168 int endch;
Denis Vlasenko9af22c72008-10-09 12:54:58 +00004169 struct command *command = ctx->command;
Denis Vlasenkoe725bfe2007-05-03 22:45:39 +00004170
4171 debug_printf_parse("parse_group entered\n");
Denis Vlasenko371de4a2008-10-14 12:43:13 +00004172#if ENABLE_HUSH_FUNCTIONS
Denys Vlasenko38292b62010-09-05 14:49:40 +02004173 if (ch == '(' && !dest->has_quoted_part) {
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00004174 if (dest->length)
Denis Vlasenkobb929512009-04-16 10:59:40 +00004175 if (done_word(dest, ctx))
4176 return 1;
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00004177 if (!command->argv)
4178 goto skip; /* (... */
4179 if (command->argv[1]) { /* word word ... (... */
4180 syntax_error_unexpected_ch('(');
4181 return 1;
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +00004182 }
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00004183 /* it is "word(..." or "word (..." */
4184 do
4185 ch = i_getch(input);
4186 while (ch == ' ' || ch == '\t');
4187 if (ch != ')') {
4188 syntax_error_unexpected_ch(ch);
4189 return 1;
4190 }
4191 nommu_addchr(&ctx->as_string, ch);
4192 do
4193 ch = i_getch(input);
4194 while (ch == ' ' || ch == '\t' || ch == '\n');
4195 if (ch != '{') {
4196 syntax_error_unexpected_ch(ch);
4197 return 1;
4198 }
4199 nommu_addchr(&ctx->as_string, ch);
Denys Vlasenko9d617c42009-06-09 18:40:52 +02004200 command->cmd_type = CMD_FUNCDEF;
Denis Vlasenkoc0ea3292009-04-10 21:22:02 +00004201 goto skip;
Denis Vlasenko371de4a2008-10-14 12:43:13 +00004202 }
4203#endif
Denys Vlasenkod8389ad2009-11-16 03:18:46 +01004204
4205#if 0 /* Prevented by caller */
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +00004206 if (command->argv /* word [word]{... */
4207 || dest->length /* word{... */
Denys Vlasenko38292b62010-09-05 14:49:40 +02004208 || dest->has_quoted_part /* ""{... */
Denis Vlasenko9af22c72008-10-09 12:54:58 +00004209 ) {
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00004210 syntax_error(NULL);
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004211 debug_printf_parse("parse_group return 1: "
4212 "syntax error, groups and arglists don't mix\n");
Denis Vlasenkoe725bfe2007-05-03 22:45:39 +00004213 return 1;
Eric Andersen25f27032001-04-26 23:22:31 +00004214 }
Denys Vlasenkod8389ad2009-11-16 03:18:46 +01004215#endif
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +00004216
4217#if ENABLE_HUSH_FUNCTIONS
4218 skip:
4219#endif
Denis Vlasenko240c2552009-04-03 03:45:05 +00004220 endch = '}';
Denis Vlasenko90e485c2007-05-23 15:22:50 +00004221 if (ch == '(') {
Denis Vlasenko240c2552009-04-03 03:45:05 +00004222 endch = ')';
Denys Vlasenko9d617c42009-06-09 18:40:52 +02004223 command->cmd_type = CMD_SUBSHELL;
Denis Vlasenkof8c1f022009-04-17 11:55:42 +00004224 } else {
4225 /* bash does not allow "{echo...", requires whitespace */
Denys Vlasenko672a55e2016-11-04 18:46:14 +01004226 ch = i_peek(input);
4227 if (ch != ' ' && ch != '\t' && ch != '\n'
4228 && ch != '(' /* but "{(..." is allowed (without whitespace) */
4229 ) {
Denis Vlasenkof8c1f022009-04-17 11:55:42 +00004230 syntax_error_unexpected_ch(ch);
4231 return 1;
4232 }
Denys Vlasenko672a55e2016-11-04 18:46:14 +01004233 if (ch != '(') {
4234 ch = i_getch(input);
4235 nommu_addchr(&ctx->as_string, ch);
4236 }
Eric Andersen25f27032001-04-26 23:22:31 +00004237 }
Denis Vlasenkob7d8c0d2009-04-10 19:05:43 +00004238
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00004239 {
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004240#if BB_MMU
4241# define as_string NULL
4242#else
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00004243 char *as_string = NULL;
4244#endif
4245 pipe_list = parse_stream(&as_string, input, endch);
4246#if !BB_MMU
4247 if (as_string)
4248 o_addstr(&ctx->as_string, as_string);
4249#endif
4250 /* empty ()/{} or parse error? */
4251 if (!pipe_list || pipe_list == ERR_PTR) {
Denis Vlasenkobb929512009-04-16 10:59:40 +00004252 /* parse_stream already emitted error msg */
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004253 if (!BB_MMU)
4254 free(as_string);
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00004255 debug_printf_parse("parse_group return 1: "
4256 "parse_stream returned %p\n", pipe_list);
4257 return 1;
4258 }
4259 command->group = pipe_list;
4260#if !BB_MMU
4261 as_string[strlen(as_string) - 1] = '\0'; /* plink ')' or '}' */
4262 command->group_as_string = as_string;
4263 debug_printf_parse("end of group, remembering as:'%s'\n",
4264 command->group_as_string);
4265#endif
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004266#undef as_string
Denis Vlasenkof8d01d32008-06-14 17:13:20 +00004267 }
Denis Vlasenkob6e65562009-04-03 16:49:04 +00004268 debug_printf_parse("parse_group return 0\n");
4269 return 0;
Denis Vlasenko9af22c72008-10-09 12:54:58 +00004270 /* command remains "open", available for possible redirects */
Eric Andersen25f27032001-04-26 23:22:31 +00004271}
4272
Denys Vlasenko46e64982016-09-29 19:50:55 +02004273static int i_getch_and_eat_bkslash_nl(struct in_str *input)
4274{
4275 for (;;) {
4276 int ch, ch2;
4277
4278 ch = i_getch(input);
4279 if (ch != '\\')
4280 return ch;
4281 ch2 = i_peek(input);
4282 if (ch2 != '\n')
4283 return ch;
4284 /* backslash+newline, skip it */
4285 i_getch(input);
4286 }
4287}
4288
Denys Vlasenko657086a2016-09-29 18:07:42 +02004289static int i_peek_and_eat_bkslash_nl(struct in_str *input)
4290{
4291 for (;;) {
4292 int ch, ch2;
4293
4294 ch = i_peek(input);
4295 if (ch != '\\')
4296 return ch;
4297 ch2 = i_peek2(input);
4298 if (ch2 != '\n')
4299 return ch;
4300 /* backslash+newline, skip it */
4301 i_getch(input);
4302 i_getch(input);
4303 }
4304}
4305
Denys Vlasenko0b883582016-12-23 16:49:07 +01004306#if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004307/* Subroutines for copying $(...) and `...` things */
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004308static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004309/* '...' */
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004310static int add_till_single_quote(o_string *dest, struct in_str *input)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004311{
4312 while (1) {
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004313 int ch = i_getch(input);
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004314 if (ch == EOF) {
Denis Vlasenkod68ae082009-04-09 20:41:34 +00004315 syntax_error_unterm_ch('\'');
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004316 return 0;
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004317 }
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004318 if (ch == '\'')
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004319 return 1;
Denis Vlasenko82dfec32008-06-16 12:47:11 +00004320 o_addchr(dest, ch);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004321 }
4322}
4323/* "...\"...`..`...." - do we need to handle "...$(..)..." too? */
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004324static int add_till_double_quote(o_string *dest, struct in_str *input)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004325{
4326 while (1) {
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004327 int ch = i_getch(input);
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004328 if (ch == EOF) {
Denis Vlasenkod68ae082009-04-09 20:41:34 +00004329 syntax_error_unterm_ch('"');
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004330 return 0;
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004331 }
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004332 if (ch == '"')
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004333 return 1;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004334 if (ch == '\\') { /* \x. Copy both chars. */
Denis Vlasenko82dfec32008-06-16 12:47:11 +00004335 o_addchr(dest, ch);
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004336 ch = i_getch(input);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004337 }
Denis Vlasenko82dfec32008-06-16 12:47:11 +00004338 o_addchr(dest, ch);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004339 if (ch == '`') {
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004340 if (!add_till_backquote(dest, input, /*in_dquote:*/ 1))
4341 return 0;
Denis Vlasenko82dfec32008-06-16 12:47:11 +00004342 o_addchr(dest, ch);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004343 continue;
4344 }
Denis Vlasenko5703c222008-06-15 11:49:42 +00004345 //if (ch == '$') ...
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004346 }
4347}
4348/* Process `cmd` - copy contents until "`" is seen. Complicated by
4349 * \` quoting.
4350 * "Within the backquoted style of command substitution, backslash
4351 * shall retain its literal meaning, except when followed by: '$', '`', or '\'.
4352 * The search for the matching backquote shall be satisfied by the first
4353 * backquote found without a preceding backslash; during this search,
4354 * if a non-escaped backquote is encountered within a shell comment,
4355 * a here-document, an embedded command substitution of the $(command)
4356 * form, or a quoted string, undefined results occur. A single-quoted
4357 * or double-quoted string that begins, but does not end, within the
4358 * "`...`" sequence produces undefined results."
4359 * Example Output
4360 * echo `echo '\'TEST\`echo ZZ\`BEST` \TESTZZBEST
4361 */
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004362static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004363{
4364 while (1) {
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004365 int ch = i_getch(input);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004366 if (ch == '`')
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004367 return 1;
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004368 if (ch == '\\') {
Denys Vlasenkoacd5bc82010-09-12 15:05:39 +02004369 /* \x. Copy both unless it is \`, \$, \\ and maybe \" */
4370 ch = i_getch(input);
4371 if (ch != '`'
4372 && ch != '$'
4373 && ch != '\\'
4374 && (!in_dquote || ch != '"')
4375 ) {
4376 o_addchr(dest, '\\');
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004377 }
Denys Vlasenkoacd5bc82010-09-12 15:05:39 +02004378 }
4379 if (ch == EOF) {
4380 syntax_error_unterm_ch('`');
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004381 return 0;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004382 }
Denis Vlasenko82dfec32008-06-16 12:47:11 +00004383 o_addchr(dest, ch);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004384 }
4385}
4386/* Process $(cmd) - copy contents until ")" is seen. Complicated by
4387 * quoting and nested ()s.
4388 * "With the $(command) style of command substitution, all characters
4389 * following the open parenthesis to the matching closing parenthesis
4390 * constitute the command. Any valid shell script can be used for command,
4391 * except a script consisting solely of redirections which produces
4392 * unspecified results."
4393 * Example Output
4394 * echo $(echo '(TEST)' BEST) (TEST) BEST
4395 * echo $(echo 'TEST)' BEST) TEST) BEST
4396 * echo $(echo \(\(TEST\) BEST) ((TEST) BEST
Denys Vlasenko74369502010-05-21 19:52:01 +02004397 *
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004398 * Also adapted to eat ${var%...} and $((...)) constructs, since ... part
Denys Vlasenkoa6ad3972010-05-22 00:26:06 +02004399 * can contain arbitrary constructs, just like $(cmd).
Denys Vlasenko36f774a2010-09-05 14:45:38 +02004400 * In bash compat mode, it needs to also be able to stop on ':' or '/'
4401 * for ${var:N[:M]} and ${var/P[/R]} parsing.
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004402 */
Denys Vlasenko74369502010-05-21 19:52:01 +02004403#define DOUBLE_CLOSE_CHAR_FLAG 0x80
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004404static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsigned end_ch)
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004405{
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004406 int ch;
Denys Vlasenko74369502010-05-21 19:52:01 +02004407 char dbl = end_ch & DOUBLE_CLOSE_CHAR_FLAG;
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01004408# if BASH_SUBSTR || BASH_PATTERN_SUBST
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004409 char end_char2 = end_ch >> 8;
Denys Vlasenko9297dbc2010-07-05 21:37:12 +02004410# endif
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004411 end_ch &= (DOUBLE_CLOSE_CHAR_FLAG - 1);
4412
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004413 while (1) {
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004414 ch = i_getch(input);
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004415 if (ch == EOF) {
Denys Vlasenkoa6ad3972010-05-22 00:26:06 +02004416 syntax_error_unterm_ch(end_ch);
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004417 return 0;
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004418 }
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01004419 if (ch == end_ch
4420# if BASH_SUBSTR || BASH_PATTERN_SUBST
4421 || ch == end_char2
4422# endif
4423 ) {
Denys Vlasenkoa6ad3972010-05-22 00:26:06 +02004424 if (!dbl)
4425 break;
4426 /* we look for closing )) of $((EXPR)) */
Denys Vlasenko657086a2016-09-29 18:07:42 +02004427 if (i_peek_and_eat_bkslash_nl(input) == end_ch) {
Denys Vlasenkoa6ad3972010-05-22 00:26:06 +02004428 i_getch(input); /* eat second ')' */
4429 break;
Mike Frysinger98c52642009-04-02 10:02:37 +00004430 }
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004431 }
Denis Vlasenko82dfec32008-06-16 12:47:11 +00004432 o_addchr(dest, ch);
Denys Vlasenkoa6ad3972010-05-22 00:26:06 +02004433 if (ch == '(' || ch == '{') {
4434 ch = (ch == '(' ? ')' : '}');
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004435 if (!add_till_closing_bracket(dest, input, ch))
4436 return 0;
Denys Vlasenkoa6ad3972010-05-22 00:26:06 +02004437 o_addchr(dest, ch);
4438 continue;
4439 }
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004440 if (ch == '\'') {
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004441 if (!add_till_single_quote(dest, input))
4442 return 0;
Denis Vlasenko82dfec32008-06-16 12:47:11 +00004443 o_addchr(dest, ch);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004444 continue;
4445 }
4446 if (ch == '"') {
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004447 if (!add_till_double_quote(dest, input))
4448 return 0;
Denis Vlasenko82dfec32008-06-16 12:47:11 +00004449 o_addchr(dest, ch);
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004450 continue;
4451 }
Denys Vlasenkoa6ad3972010-05-22 00:26:06 +02004452 if (ch == '`') {
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004453 if (!add_till_backquote(dest, input, /*in_dquote:*/ 0))
4454 return 0;
Denys Vlasenkoa6ad3972010-05-22 00:26:06 +02004455 o_addchr(dest, ch);
4456 continue;
4457 }
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004458 if (ch == '\\') {
4459 /* \x. Copy verbatim. Important for \(, \) */
Denis Vlasenko76db5ad2008-06-12 12:58:20 +00004460 ch = i_getch(input);
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004461 if (ch == EOF) {
Denis Vlasenkod68ae082009-04-09 20:41:34 +00004462 syntax_error_unterm_ch(')');
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004463 return 0;
Denis Vlasenko5c090a92009-04-08 21:51:33 +00004464 }
Denys Vlasenko657086a2016-09-29 18:07:42 +02004465#if 0
4466 if (ch == '\n') {
4467 /* "backslash+newline", ignore both */
4468 o_delchr(dest); /* undo insertion of '\' */
4469 continue;
4470 }
4471#endif
Denis Vlasenko82dfec32008-06-16 12:47:11 +00004472 o_addchr(dest, ch);
Denis Vlasenko76db5ad2008-06-12 12:58:20 +00004473 continue;
4474 }
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004475 }
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004476 return ch;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004477}
Denys Vlasenko0b883582016-12-23 16:49:07 +01004478#endif /* ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS */
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00004479
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00004480/* Return code: 0 for OK, 1 for syntax error */
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00004481#if BB_MMU
Denys Vlasenko101a4e32010-09-09 14:04:57 +02004482#define parse_dollar(as_string, dest, input, quote_mask) \
4483 parse_dollar(dest, input, quote_mask)
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004484#define as_string NULL
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00004485#endif
Denys Vlasenko2e48d532010-05-22 17:30:39 +02004486static int parse_dollar(o_string *as_string,
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00004487 o_string *dest,
Denys Vlasenko101a4e32010-09-09 14:04:57 +02004488 struct in_str *input, unsigned char quote_mask)
Eric Andersen25f27032001-04-26 23:22:31 +00004489{
Denys Vlasenko657086a2016-09-29 18:07:42 +02004490 int ch = i_peek_and_eat_bkslash_nl(input); /* first character after the $ */
Denis Vlasenkoe0a33672007-05-10 23:06:55 +00004491
Denys Vlasenko2e48d532010-05-22 17:30:39 +02004492 debug_printf_parse("parse_dollar entered: ch='%c'\n", ch);
Denis Vlasenko1f4cf512007-05-16 10:39:24 +00004493 if (isalpha(ch)) {
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00004494 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004495 nommu_addchr(as_string, ch);
Denis Vlasenkod4981312008-07-31 10:34:48 +00004496 make_var:
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004497 o_addchr(dest, SPECIAL_VAR_SYMBOL);
Denis Vlasenkoe0a33672007-05-10 23:06:55 +00004498 while (1) {
Denis Vlasenkoe0a33672007-05-10 23:06:55 +00004499 debug_printf_parse(": '%c'\n", ch);
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004500 o_addchr(dest, ch | quote_mask);
Denis Vlasenko1f4cf512007-05-16 10:39:24 +00004501 quote_mask = 0;
Denys Vlasenko657086a2016-09-29 18:07:42 +02004502 ch = i_peek_and_eat_bkslash_nl(input);
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02004503 if (!isalnum(ch) && ch != '_') {
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02004504 /* End of variable name reached */
Denis Vlasenko602d13c2007-05-13 18:34:53 +00004505 break;
Denys Vlasenkod17a91d2016-09-29 18:02:37 +02004506 }
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00004507 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004508 nommu_addchr(as_string, ch);
Eric Andersen25f27032001-04-26 23:22:31 +00004509 }
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004510 o_addchr(dest, SPECIAL_VAR_SYMBOL);
Eric Andersen25f27032001-04-26 23:22:31 +00004511 } else if (isdigit(ch)) {
Denis Vlasenko602d13c2007-05-13 18:34:53 +00004512 make_one_char_var:
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00004513 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004514 nommu_addchr(as_string, ch);
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004515 o_addchr(dest, SPECIAL_VAR_SYMBOL);
Denis Vlasenko602d13c2007-05-13 18:34:53 +00004516 debug_printf_parse(": '%c'\n", ch);
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004517 o_addchr(dest, ch | quote_mask);
4518 o_addchr(dest, SPECIAL_VAR_SYMBOL);
Eric Andersen25f27032001-04-26 23:22:31 +00004519 } else switch (ch) {
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004520 case '$': /* pid */
4521 case '!': /* last bg pid */
4522 case '?': /* last exit code */
4523 case '#': /* number of args */
4524 case '*': /* args */
4525 case '@': /* args */
4526 goto make_one_char_var;
4527 case '{': {
Denys Vlasenko2093ad22017-07-26 00:07:27 +02004528 char len_single_ch;
4529
Mike Frysingeref3e7fd2009-06-01 14:13:39 -04004530 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4531
Denys Vlasenko74369502010-05-21 19:52:01 +02004532 ch = i_getch(input); /* eat '{' */
4533 nommu_addchr(as_string, ch);
4534
Denys Vlasenko46e64982016-09-29 19:50:55 +02004535 ch = i_getch_and_eat_bkslash_nl(input); /* first char after '{' */
Denys Vlasenko74369502010-05-21 19:52:01 +02004536 /* It should be ${?}, or ${#var},
4537 * or even ${?+subst} - operator acting on a special variable,
4538 * or the beginning of variable name.
4539 */
Denys Vlasenko101a4e32010-09-09 14:04:57 +02004540 if (ch == EOF
4541 || (!strchr(_SPECIAL_VARS_STR, ch) && !isalnum(ch)) /* not one of those */
4542 ) {
Denys Vlasenko74369502010-05-21 19:52:01 +02004543 bad_dollar_syntax:
4544 syntax_error_unterm_str("${name}");
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004545 debug_printf_parse("parse_dollar return 0: unterminated ${name}\n");
4546 return 0;
Denys Vlasenko74369502010-05-21 19:52:01 +02004547 }
Denys Vlasenko101a4e32010-09-09 14:04:57 +02004548 nommu_addchr(as_string, ch);
Denys Vlasenko2093ad22017-07-26 00:07:27 +02004549 len_single_ch = ch;
Denys Vlasenko74369502010-05-21 19:52:01 +02004550 ch |= quote_mask;
4551
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004552 /* It's possible to just call add_till_closing_bracket() at this point.
Denys Vlasenko74369502010-05-21 19:52:01 +02004553 * However, this regresses some of our testsuite cases
4554 * which check invalid constructs like ${%}.
4555 * Oh well... let's check that the var name part is fine... */
4556
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004557 while (1) {
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004558 unsigned pos;
4559
Denys Vlasenko74369502010-05-21 19:52:01 +02004560 o_addchr(dest, ch);
4561 debug_printf_parse(": '%c'\n", ch);
4562
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004563 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004564 nommu_addchr(as_string, ch);
Denys Vlasenko74369502010-05-21 19:52:01 +02004565 if (ch == '}')
Mike Frysinger98c52642009-04-02 10:02:37 +00004566 break;
Mike Frysinger98c52642009-04-02 10:02:37 +00004567
Denys Vlasenko74369502010-05-21 19:52:01 +02004568 if (!isalnum(ch) && ch != '_') {
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004569 unsigned end_ch;
4570 unsigned char last_ch;
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004571 /* handle parameter expansions
4572 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02
4573 */
Denys Vlasenko2093ad22017-07-26 00:07:27 +02004574 if (!strchr(VAR_SUBST_OPS, ch)) { /* ${var<bad_char>... */
4575 if (len_single_ch != '#'
4576 /*|| !strchr(SPECIAL_VARS_STR, ch) - disallow errors like ${#+} ? */
4577 || i_peek(input) != '}'
4578 ) {
4579 goto bad_dollar_syntax;
4580 }
4581 /* else: it's "length of C" ${#C} op,
4582 * where C is a single char
4583 * special var name, e.g. ${#!}.
4584 */
4585 }
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004586 /* Eat everything until closing '}' (or ':') */
4587 end_ch = '}';
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01004588 if (BASH_SUBSTR
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004589 && ch == ':'
Denys Vlasenko36f774a2010-09-05 14:45:38 +02004590 && !strchr(MINUS_PLUS_EQUAL_QUESTION, i_peek(input))
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004591 ) {
4592 /* It's ${var:N[:M]} thing */
4593 end_ch = '}' * 0x100 + ':';
4594 }
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01004595 if (BASH_PATTERN_SUBST
Denys Vlasenko36f774a2010-09-05 14:45:38 +02004596 && ch == '/'
4597 ) {
4598 /* It's ${var/[/]pattern[/repl]} thing */
4599 if (i_peek(input) == '/') { /* ${var//pattern[/repl]}? */
4600 i_getch(input);
4601 nommu_addchr(as_string, '/');
4602 ch = '\\';
4603 }
4604 end_ch = '}' * 0x100 + '/';
4605 }
4606 o_addchr(dest, ch);
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004607 again:
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004608 if (!BB_MMU)
4609 pos = dest->length;
Denys Vlasenko9297dbc2010-07-05 21:37:12 +02004610#if ENABLE_HUSH_DOLLAR_OPS
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004611 last_ch = add_till_closing_bracket(dest, input, end_ch);
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004612 if (last_ch == 0) /* error? */
4613 return 0;
Denys Vlasenko9297dbc2010-07-05 21:37:12 +02004614#else
4615#error Simple code to only allow ${var} is not implemented
4616#endif
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004617 if (as_string) {
4618 o_addstr(as_string, dest->data + pos);
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004619 o_addchr(as_string, last_ch);
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004620 }
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004621
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01004622 if ((BASH_SUBSTR || BASH_PATTERN_SUBST)
4623 && (end_ch & 0xff00)
4624 ) {
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004625 /* close the first block: */
4626 o_addchr(dest, SPECIAL_VAR_SYMBOL);
Denys Vlasenko36f774a2010-09-05 14:45:38 +02004627 /* while parsing N from ${var:N[:M]}
4628 * or pattern from ${var/[/]pattern[/repl]} */
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004629 if ((end_ch & 0xff) == last_ch) {
Denys Vlasenko36f774a2010-09-05 14:45:38 +02004630 /* got ':' or '/'- parse the rest */
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004631 end_ch = '}';
4632 goto again;
4633 }
Denys Vlasenko36f774a2010-09-05 14:45:38 +02004634 /* got '}' */
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01004635 if (BASH_SUBSTR && end_ch == '}' * 0x100 + ':') {
Denys Vlasenko36f774a2010-09-05 14:45:38 +02004636 /* it's ${var:N} - emulate :999999999 */
4637 o_addstr(dest, "999999999");
4638 } /* else: it's ${var/[/]pattern} */
Denys Vlasenko1e811b12010-05-22 03:12:29 +02004639 }
Denys Vlasenko74369502010-05-21 19:52:01 +02004640 break;
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004641 }
Denys Vlasenko2093ad22017-07-26 00:07:27 +02004642 len_single_ch = 0; /* it can't be ${#C} op */
Denys Vlasenko74369502010-05-21 19:52:01 +02004643 }
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004644 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4645 break;
4646 }
Denys Vlasenko0b883582016-12-23 16:49:07 +01004647#if ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_TICK
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004648 case '(': {
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004649 unsigned pos;
4650
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00004651 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004652 nommu_addchr(as_string, ch);
Denys Vlasenko0b883582016-12-23 16:49:07 +01004653# if ENABLE_FEATURE_SH_MATH
Denys Vlasenko657086a2016-09-29 18:07:42 +02004654 if (i_peek_and_eat_bkslash_nl(input) == '(') {
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00004655 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004656 nommu_addchr(as_string, ch);
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004657 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4658 o_addchr(dest, /*quote_mask |*/ '+');
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004659 if (!BB_MMU)
4660 pos = dest->length;
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004661 if (!add_till_closing_bracket(dest, input, ')' | DOUBLE_CLOSE_CHAR_FLAG))
4662 return 0; /* error */
Denis Vlasenkoc4a7af52009-04-05 20:33:27 +00004663 if (as_string) {
4664 o_addstr(as_string, dest->data + pos);
4665 o_addchr(as_string, ')');
4666 o_addchr(as_string, ')');
Denis Vlasenko0bb4a232009-04-05 01:42:59 +00004667 }
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004668 o_addchr(dest, SPECIAL_VAR_SYMBOL);
Eric Andersen25f27032001-04-26 23:22:31 +00004669 break;
Denis Vlasenko76db5ad2008-06-12 12:58:20 +00004670 }
Denis Vlasenkod85a5df2009-04-05 08:43:57 +00004671# endif
4672# if ENABLE_HUSH_TICK
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004673 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4674 o_addchr(dest, quote_mask | '`');
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004675 if (!BB_MMU)
4676 pos = dest->length;
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004677 if (!add_till_closing_bracket(dest, input, ')'))
4678 return 0; /* error */
Denis Vlasenkoc4a7af52009-04-05 20:33:27 +00004679 if (as_string) {
4680 o_addstr(as_string, dest->data + pos);
Denys Vlasenkob70cef72010-01-12 13:45:45 +01004681 o_addchr(as_string, ')');
Denis Vlasenko0bb4a232009-04-05 01:42:59 +00004682 }
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004683 o_addchr(dest, SPECIAL_VAR_SYMBOL);
Denis Vlasenkod85a5df2009-04-05 08:43:57 +00004684# endif
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004685 break;
4686 }
Denis Vlasenkod85a5df2009-04-05 08:43:57 +00004687#endif
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004688 case '_':
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00004689 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004690 nommu_addchr(as_string, ch);
Denys Vlasenko657086a2016-09-29 18:07:42 +02004691 ch = i_peek_and_eat_bkslash_nl(input);
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004692 if (isalnum(ch)) { /* it's $_name or $_123 */
4693 ch = '_';
4694 goto make_var;
4695 }
4696 /* else: it's $_ */
Denys Vlasenko69b1cef2009-09-21 10:21:44 +02004697 /* TODO: $_ and $-: */
4698 /* $_ Shell or shell script name; or last argument of last command
4699 * (if last command wasn't a pipe; if it was, bash sets $_ to "");
4700 * but in command's env, set to full pathname used to invoke it */
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004701 /* $- Option flags set by set builtin or shell options (-i etc) */
4702 default:
4703 o_addQchr(dest, '$');
Eric Andersen25f27032001-04-26 23:22:31 +00004704 }
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004705 debug_printf_parse("parse_dollar return 1 (ok)\n");
4706 return 1;
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004707#undef as_string
Eric Andersen25f27032001-04-26 23:22:31 +00004708}
4709
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00004710#if BB_MMU
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01004711# if BASH_PATTERN_SUBST
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02004712#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \
4713 encode_string(dest, input, dquote_end, process_bkslash)
4714# else
4715/* only ${var/pattern/repl} (its pattern part) needs additional mode */
4716#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \
4717 encode_string(dest, input, dquote_end)
4718# endif
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004719#define as_string NULL
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02004720
4721#else /* !MMU */
4722
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01004723# if BASH_PATTERN_SUBST
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02004724/* all parameters are needed, no macro tricks */
4725# else
4726#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \
4727 encode_string(as_string, dest, input, dquote_end)
4728# endif
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00004729#endif
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02004730static int encode_string(o_string *as_string,
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00004731 o_string *dest,
4732 struct in_str *input,
Denys Vlasenko14e289b2010-09-10 10:15:18 +02004733 int dquote_end,
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02004734 int process_bkslash)
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00004735{
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01004736#if !BASH_PATTERN_SUBST
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02004737 const int process_bkslash = 1;
4738#endif
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00004739 int ch;
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00004740 int next;
4741
4742 again:
4743 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004744 if (ch != EOF)
4745 nommu_addchr(as_string, ch);
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00004746 if (ch == dquote_end) { /* may be only '"' or EOF */
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004747 debug_printf_parse("encode_string return 1 (ok)\n");
4748 return 1;
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00004749 }
Denis Vlasenko3dfb0352009-04-08 09:29:14 +00004750 /* note: can't move it above ch == dquote_end check! */
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00004751 if (ch == EOF) {
Denis Vlasenkod68ae082009-04-09 20:41:34 +00004752 syntax_error_unterm_ch('"');
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004753 return 0; /* error */
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00004754 }
4755 next = '\0';
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00004756 if (ch != '\n') {
4757 next = i_peek(input);
4758 }
Denys Vlasenkof37eb392009-10-18 11:46:35 +02004759 debug_printf_parse("\" ch=%c (%d) escape=%d\n",
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02004760 ch, ch, !!(dest->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02004761 if (process_bkslash && ch == '\\') {
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00004762 if (next == EOF) {
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00004763 syntax_error("\\<eof>");
Denis Vlasenko0b677d82009-04-10 13:49:10 +00004764 xfunc_die();
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00004765 }
4766 /* bash:
4767 * "The backslash retains its special meaning [in "..."]
4768 * only when followed by one of the following characters:
4769 * $, `, ", \, or <newline>. A double quote may be quoted
Denys Vlasenkoe640cb42009-05-28 16:49:11 +02004770 * within double quotes by preceding it with a backslash."
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02004771 * NB: in (unquoted) heredoc, above does not apply to ",
4772 * therefore we check for it by "next == dquote_end" cond.
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00004773 */
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02004774 if (next == dquote_end || strchr("$`\\\n", next)) {
Denys Vlasenko850b15b2010-09-09 12:58:19 +02004775 ch = i_getch(input); /* eat next */
4776 if (ch == '\n')
4777 goto again; /* skip \<newline> */
Denys Vlasenko4f870492010-09-10 11:06:01 +02004778 } /* else: ch remains == '\\', and we double it below: */
4779 o_addqchr(dest, ch); /* \c if c is a glob char, else just c */
Denys Vlasenko850b15b2010-09-09 12:58:19 +02004780 nommu_addchr(as_string, ch);
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00004781 goto again;
4782 }
4783 if (ch == '$') {
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004784 if (!parse_dollar(as_string, dest, input, /*quote_mask:*/ 0x80)) {
4785 debug_printf_parse("encode_string return 0: "
4786 "parse_dollar returned 0 (error)\n");
4787 return 0;
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00004788 }
4789 goto again;
4790 }
4791#if ENABLE_HUSH_TICK
4792 if (ch == '`') {
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004793 //unsigned pos = dest->length;
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00004794 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4795 o_addchr(dest, 0x80 | '`');
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004796 if (!add_till_backquote(dest, input, /*in_dquote:*/ dquote_end == '"'))
4797 return 0; /* error */
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00004798 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4799 //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
Denis Vlasenkof328e002009-04-02 16:55:38 +00004800 goto again;
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00004801 }
4802#endif
Denis Vlasenkof328e002009-04-02 16:55:38 +00004803 o_addQchr(dest, ch);
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00004804 goto again;
Denys Vlasenkoddc62f62010-05-22 00:53:32 +02004805#undef as_string
Denis Vlasenko2f1d3942009-04-02 16:31:29 +00004806}
4807
Denis Vlasenkob6e65562009-04-03 16:49:04 +00004808/*
4809 * Scan input until EOF or end_trigger char.
4810 * Return a list of pipes to execute, or NULL on EOF
4811 * or if end_trigger character is met.
Denys Vlasenkocecbc982011-03-30 18:54:52 +02004812 * On syntax error, exit if shell is not interactive,
Denis Vlasenkob6e65562009-04-03 16:49:04 +00004813 * reset parsing machinery and start parsing anew,
4814 * or return ERR_PTR.
Denis Vlasenko027e3fd2009-04-02 22:50:40 +00004815 */
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00004816static struct pipe *parse_stream(char **pstring,
4817 struct in_str *input,
4818 int end_trigger)
Eric Andersen25f27032001-04-26 23:22:31 +00004819{
Denis Vlasenkob6e65562009-04-03 16:49:04 +00004820 struct parse_context ctx;
4821 o_string dest = NULL_O_STRING;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004822 int heredoc_cnt;
Eric Andersen25f27032001-04-26 23:22:31 +00004823
Denys Vlasenko77a7b552010-09-09 12:40:03 +02004824 /* Single-quote triggers a bypass of the main loop until its mate is
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02004825 * found. When recursing, quote state is passed in via dest->o_expflags.
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00004826 */
Denis Vlasenkob6e65562009-04-03 16:49:04 +00004827 debug_printf_parse("parse_stream entered, end_trigger='%c'\n",
Denys Vlasenko90a99042009-09-06 02:36:23 +02004828 end_trigger ? end_trigger : 'X');
Denis Vlasenko0701dca2009-04-11 10:38:47 +00004829 debug_enter();
Denis Vlasenkoe725bfe2007-05-03 22:45:39 +00004830
Denys Vlasenkof37eb392009-10-18 11:46:35 +02004831 /* If very first arg is "" or '', dest.data may end up NULL.
4832 * Preventing this: */
4833 o_addchr(&dest, '\0');
4834 dest.length = 0;
4835
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02004836 /* We used to separate words on $IFS here. This was wrong.
4837 * $IFS is used only for word splitting when $var is expanded,
Denys Vlasenko77a7b552010-09-09 12:40:03 +02004838 * here we should use blank chars as separators, not $IFS
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02004839 */
Denys Vlasenko77a7b552010-09-09 12:40:03 +02004840
Denys Vlasenko77a7b552010-09-09 12:40:03 +02004841 if (MAYBE_ASSIGNMENT != 0)
4842 dest.o_assignment = MAYBE_ASSIGNMENT;
Denis Vlasenkob6e65562009-04-03 16:49:04 +00004843 initialize_context(&ctx);
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004844 heredoc_cnt = 0;
Denis Vlasenko1a735862007-05-23 00:32:25 +00004845 while (1) {
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02004846 const char *is_blank;
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00004847 const char *is_special;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00004848 int ch;
4849 int next;
4850 int redir_fd;
4851 redir_type redir_style;
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00004852
Denis Vlasenko46ccdcb2008-06-10 18:05:12 +00004853 ch = i_getch(input);
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00004854 debug_printf_parse(": ch=%c (%d) escape=%d\n",
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02004855 ch, ch, !!(dest.o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00004856 if (ch == EOF) {
4857 struct pipe *pi;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004858
4859 if (heredoc_cnt) {
Denis Vlasenkod68ae082009-04-09 20:41:34 +00004860 syntax_error_unterm_str("here document");
Denys Vlasenkob1cfc452009-05-02 17:18:34 +02004861 goto parse_error;
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004862 }
Denys Vlasenkob1cfc452009-05-02 17:18:34 +02004863 if (end_trigger == ')') {
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01004864 syntax_error_unterm_ch('(');
4865 goto parse_error;
Denys Vlasenkob1cfc452009-05-02 17:18:34 +02004866 }
Denys Vlasenko42246472016-11-07 16:22:35 +01004867 if (end_trigger == '}') {
4868 syntax_error_unterm_ch('{');
4869 goto parse_error;
4870 }
Denys Vlasenkob1cfc452009-05-02 17:18:34 +02004871
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00004872 if (done_word(&dest, &ctx)) {
Denys Vlasenkob1cfc452009-05-02 17:18:34 +02004873 goto parse_error;
Denis Vlasenko55789c62008-06-18 16:30:42 +00004874 }
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00004875 o_free(&dest);
4876 done_pipe(&ctx, PIPE_SEQ);
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00004877 pi = ctx.list_head;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00004878 /* If we got nothing... */
Denis Vlasenko0b677d82009-04-10 13:49:10 +00004879 /* (this makes bare "&" cmd a no-op.
4880 * bash says: "syntax error near unexpected token '&'") */
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00004881 if (pi->num_cmds == 0
Denys Vlasenko60cb48c2013-01-14 15:57:44 +01004882 IF_HAS_KEYWORDS(&& pi->res_word == RES_NONE)
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00004883 ) {
Denis Vlasenko0701dca2009-04-11 10:38:47 +00004884 free_pipe_list(pi);
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00004885 pi = NULL;
4886 }
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00004887#if !BB_MMU
Denys Vlasenkob5be13c2015-09-04 06:22:10 +02004888 debug_printf_parse("as_string1 '%s'\n", ctx.as_string.data);
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00004889 if (pstring)
4890 *pstring = ctx.as_string.data;
4891 else
4892 o_free_unsafe(&ctx.as_string);
4893#endif
Denis Vlasenko0701dca2009-04-11 10:38:47 +00004894 debug_leave();
4895 debug_printf_parse("parse_stream return %p\n", pi);
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00004896 return pi;
Denis Vlasenko1a735862007-05-23 00:32:25 +00004897 }
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00004898 nommu_addchr(&ctx.as_string, ch);
Denys Vlasenkod8389ad2009-11-16 03:18:46 +01004899
4900 next = '\0';
4901 if (ch != '\n')
4902 next = i_peek(input);
4903
4904 is_special = "{}<>;&|()#'" /* special outside of "str" */
4905 "\\$\"" IF_HUSH_TICK("`"); /* always special */
4906 /* Are { and } special here? */
Denys Vlasenko3227d3f2010-05-17 09:49:47 +02004907 if (ctx.command->argv /* word [word]{... - non-special */
4908 || dest.length /* word{... - non-special */
Denys Vlasenko38292b62010-09-05 14:49:40 +02004909 || dest.has_quoted_part /* ""{... - non-special */
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02004910 || (next != ';' /* }; - special */
4911 && next != ')' /* }) - special */
Denys Vlasenko672a55e2016-11-04 18:46:14 +01004912 && next != '(' /* {( - special */
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02004913 && next != '&' /* }& and }&& ... - special */
4914 && next != '|' /* }|| ... - special */
4915 && !strchr(defifs, next) /* {word - non-special */
Denys Vlasenko3227d3f2010-05-17 09:49:47 +02004916 )
Denys Vlasenkod8389ad2009-11-16 03:18:46 +01004917 ) {
4918 /* They are not special, skip "{}" */
4919 is_special += 2;
4920 }
4921 is_special = strchr(is_special, ch);
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02004922 is_blank = strchr(defifs, ch);
Denis Vlasenko6da69cd2009-04-04 12:12:58 +00004923
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02004924 if (!is_special && !is_blank) { /* ordinary char */
Denis Vlasenkobf25fbc2009-04-19 13:57:51 +00004925 ordinary_char:
Denis Vlasenkob6e65562009-04-03 16:49:04 +00004926 o_addQchr(&dest, ch);
4927 if ((dest.o_assignment == MAYBE_ASSIGNMENT
4928 || dest.o_assignment == WORD_IS_KEYWORD)
Denis Vlasenko55789c62008-06-18 16:30:42 +00004929 && ch == '='
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00004930 && is_well_formed_var_name(dest.data, '=')
Denis Vlasenko55789c62008-06-18 16:30:42 +00004931 ) {
Denis Vlasenkob6e65562009-04-03 16:49:04 +00004932 dest.o_assignment = DEFINITELY_ASSIGNMENT;
Denys Vlasenko29f9b722011-05-14 11:27:36 +02004933 debug_printf_parse("dest.o_assignment='%s'\n", assignment_flag[dest.o_assignment]);
Denis Vlasenko55789c62008-06-18 16:30:42 +00004934 }
Denis Vlasenkobb81c582007-01-30 22:32:09 +00004935 continue;
4936 }
Denis Vlasenko240c2552009-04-03 03:45:05 +00004937
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02004938 if (is_blank) {
Denis Vlasenkob6e65562009-04-03 16:49:04 +00004939 if (done_word(&dest, &ctx)) {
4940 goto parse_error;
Eric Andersenaac75e52001-04-30 18:18:45 +00004941 }
Denis Vlasenko37181682009-04-03 03:19:15 +00004942 if (ch == '\n') {
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01004943 /* Is this a case when newline is simply ignored?
4944 * Some examples:
4945 * "cmd | <newline> cmd ..."
4946 * "case ... in <newline> word) ..."
4947 */
4948 if (IS_NULL_CMD(ctx.command)
4949 && dest.length == 0 && !dest.has_quoted_part
Denis Vlasenkof1736072008-07-31 10:09:26 +00004950 ) {
Denys Vlasenko642e71a2011-01-07 15:16:05 +01004951 /* This newline can be ignored. But...
Denys Vlasenko98c46d12011-01-18 17:30:07 +01004952 * Without check #1, interactive shell
4953 * ignores even bare <newline>,
4954 * and shows the continuation prompt:
Denys Vlasenko642e71a2011-01-07 15:16:05 +01004955 * ps1_prompt$ <enter>
Denys Vlasenko98c46d12011-01-18 17:30:07 +01004956 * ps2> _ <=== wrong, should be ps1
4957 * Without check #2, "cmd & <newline>"
4958 * is similarly mistreated.
4959 * (BTW, this makes "cmd & cmd"
4960 * and "cmd && cmd" non-orthogonal.
4961 * Really, ask yourself, why
4962 * "cmd && <newline>" doesn't start
4963 * cmd but waits for more input?
Denys Vlasenkob24e55d2017-07-16 20:29:35 +02004964 * The only reason is that it might be
4965 * a "cmd1 && <nl> cmd2 &" construct,
4966 * cmd1 may need to run in BG).
Denys Vlasenko642e71a2011-01-07 15:16:05 +01004967 */
4968 struct pipe *pi = ctx.list_head;
Denys Vlasenko98c46d12011-01-18 17:30:07 +01004969 if (pi->num_cmds != 0 /* check #1 */
4970 && pi->followup != PIPE_BG /* check #2 */
4971 ) {
Denys Vlasenko642e71a2011-01-07 15:16:05 +01004972 continue;
Denys Vlasenko98c46d12011-01-18 17:30:07 +01004973 }
Denis Vlasenkof1736072008-07-31 10:09:26 +00004974 }
Denis Vlasenko240c2552009-04-03 03:45:05 +00004975 /* Treat newline as a command separator. */
Denis Vlasenkob6e65562009-04-03 16:49:04 +00004976 done_pipe(&ctx, PIPE_SEQ);
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004977 debug_printf_parse("heredoc_cnt:%d\n", heredoc_cnt);
4978 if (heredoc_cnt) {
Denis Vlasenko3dfb0352009-04-08 09:29:14 +00004979 if (fetch_heredocs(heredoc_cnt, &ctx, input)) {
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004980 goto parse_error;
Denis Vlasenko3dfb0352009-04-08 09:29:14 +00004981 }
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00004982 heredoc_cnt = 0;
4983 }
Denis Vlasenkob6e65562009-04-03 16:49:04 +00004984 dest.o_assignment = MAYBE_ASSIGNMENT;
Denys Vlasenko29f9b722011-05-14 11:27:36 +02004985 debug_printf_parse("dest.o_assignment='%s'\n", assignment_flag[dest.o_assignment]);
Denis Vlasenko240c2552009-04-03 03:45:05 +00004986 ch = ';';
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02004987 /* note: if (is_blank) continue;
Denis Vlasenko240c2552009-04-03 03:45:05 +00004988 * will still trigger for us */
Denis Vlasenkoe725bfe2007-05-03 22:45:39 +00004989 }
Denis Vlasenkobb81c582007-01-30 22:32:09 +00004990 }
Denis Vlasenko9f8d9382009-04-19 14:03:11 +00004991
4992 /* "cmd}" or "cmd }..." without semicolon or &:
4993 * } is an ordinary char in this case, even inside { cmd; }
4994 * Pathological example: { ""}; } should exec "}" cmd
4995 */
Denis Vlasenkodcd78c42009-04-19 23:07:51 +00004996 if (ch == '}') {
Denys Vlasenko672a55e2016-11-04 18:46:14 +01004997 if (dest.length != 0 /* word} */
Denys Vlasenko38292b62010-09-05 14:49:40 +02004998 || dest.has_quoted_part /* ""} */
Denis Vlasenkodcd78c42009-04-19 23:07:51 +00004999 ) {
5000 goto ordinary_char;
5001 }
Denys Vlasenko672a55e2016-11-04 18:46:14 +01005002 if (!IS_NULL_CMD(ctx.command)) { /* cmd } */
5003 /* Generally, there should be semicolon: "cmd; }"
5004 * However, bash allows to omit it if "cmd" is
5005 * a group. Examples:
5006 * { { echo 1; } }
5007 * {(echo 1)}
5008 * { echo 0 >&2 | { echo 1; } }
5009 * { while false; do :; done }
5010 * { case a in b) ;; esac }
5011 */
5012 if (ctx.command->group)
5013 goto term_group;
5014 goto ordinary_char;
5015 }
Denis Vlasenkodcd78c42009-04-19 23:07:51 +00005016 if (!IS_NULL_PIPE(ctx.pipe)) /* cmd | } */
Denys Vlasenko672a55e2016-11-04 18:46:14 +01005017 /* Can't be an end of {cmd}, skip the check */
Denis Vlasenkodcd78c42009-04-19 23:07:51 +00005018 goto skip_end_trigger;
5019 /* else: } does terminate a group */
Denis Vlasenko9f8d9382009-04-19 14:03:11 +00005020 }
Denys Vlasenko672a55e2016-11-04 18:46:14 +01005021 term_group:
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00005022 if (end_trigger && end_trigger == ch
Denys Vlasenkoe9bda902009-05-23 16:50:07 +02005023 && (ch != ';' || heredoc_cnt == 0)
5024#if ENABLE_HUSH_CASE
5025 && (ch != ')'
5026 || ctx.ctx_res_w != RES_MATCH
Denys Vlasenko38292b62010-09-05 14:49:40 +02005027 || (!dest.has_quoted_part && strcmp(dest.data, "esac") == 0)
Denys Vlasenkoe9bda902009-05-23 16:50:07 +02005028 )
5029#endif
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00005030 ) {
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00005031 if (heredoc_cnt) {
5032 /* This is technically valid:
5033 * { cat <<HERE; }; echo Ok
5034 * heredoc
5035 * heredoc
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00005036 * HERE
5037 * but we don't support this.
5038 * We require heredoc to be in enclosing {}/(),
5039 * if any.
5040 */
Denis Vlasenkod68ae082009-04-09 20:41:34 +00005041 syntax_error_unterm_str("here document");
Denis Vlasenko6c9be7f2009-04-07 02:29:51 +00005042 goto parse_error;
5043 }
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005044 if (done_word(&dest, &ctx)) {
5045 goto parse_error;
5046 }
5047 done_pipe(&ctx, PIPE_SEQ);
5048 dest.o_assignment = MAYBE_ASSIGNMENT;
Denys Vlasenko29f9b722011-05-14 11:27:36 +02005049 debug_printf_parse("dest.o_assignment='%s'\n", assignment_flag[dest.o_assignment]);
Denis Vlasenko240c2552009-04-03 03:45:05 +00005050 /* Do we sit outside of any if's, loops or case's? */
Denis Vlasenko37181682009-04-03 03:19:15 +00005051 if (!HAS_KEYWORDS
Denys Vlasenko60cb48c2013-01-14 15:57:44 +01005052 IF_HAS_KEYWORDS(|| (ctx.ctx_res_w == RES_NONE && ctx.old_flag == 0))
Denis Vlasenko37181682009-04-03 03:19:15 +00005053 ) {
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005054 o_free(&dest);
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005055#if !BB_MMU
Denys Vlasenkob5be13c2015-09-04 06:22:10 +02005056 debug_printf_parse("as_string2 '%s'\n", ctx.as_string.data);
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005057 if (pstring)
5058 *pstring = ctx.as_string.data;
5059 else
5060 o_free_unsafe(&ctx.as_string);
5061#endif
Denys Vlasenko39701202017-08-02 19:44:05 +02005062 if (ch != ';' && IS_NULL_PIPE(ctx.list_head)) {
5063 /* Example: bare "{ }", "()" */
5064 G.last_exitcode = 2; /* bash compat */
5065 syntax_error_unexpected_ch(ch);
5066 goto parse_error2;
5067 }
Denis Vlasenko0701dca2009-04-11 10:38:47 +00005068 debug_printf_parse("parse_stream return %p: "
5069 "end_trigger char found\n",
5070 ctx.list_head);
Denys Vlasenko39701202017-08-02 19:44:05 +02005071 debug_leave();
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005072 return ctx.list_head;
Denis Vlasenkof8d01d32008-06-14 17:13:20 +00005073 }
Denis Vlasenkobb81c582007-01-30 22:32:09 +00005074 }
Denis Vlasenkodcd78c42009-04-19 23:07:51 +00005075 skip_end_trigger:
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005076 if (is_blank)
Denis Vlasenkobb81c582007-01-30 22:32:09 +00005077 continue;
Denis Vlasenko55789c62008-06-18 16:30:42 +00005078
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00005079 /* Catch <, > before deciding whether this word is
5080 * an assignment. a=1 2>z b=2: b=2 is still assignment */
5081 switch (ch) {
5082 case '>':
5083 redir_fd = redirect_opt_num(&dest);
5084 if (done_word(&dest, &ctx)) {
5085 goto parse_error;
5086 }
5087 redir_style = REDIRECT_OVERWRITE;
5088 if (next == '>') {
5089 redir_style = REDIRECT_APPEND;
5090 ch = i_getch(input);
5091 nommu_addchr(&ctx.as_string, ch);
5092 }
5093#if 0
5094 else if (next == '(') {
5095 syntax_error(">(process) not supported");
5096 goto parse_error;
5097 }
5098#endif
5099 if (parse_redirect(&ctx, redir_fd, redir_style, input))
5100 goto parse_error;
5101 continue; /* back to top of while (1) */
5102 case '<':
5103 redir_fd = redirect_opt_num(&dest);
5104 if (done_word(&dest, &ctx)) {
5105 goto parse_error;
5106 }
5107 redir_style = REDIRECT_INPUT;
5108 if (next == '<') {
5109 redir_style = REDIRECT_HEREDOC;
5110 heredoc_cnt++;
5111 debug_printf_parse("++heredoc_cnt=%d\n", heredoc_cnt);
5112 ch = i_getch(input);
5113 nommu_addchr(&ctx.as_string, ch);
5114 } else if (next == '>') {
5115 redir_style = REDIRECT_IO;
5116 ch = i_getch(input);
5117 nommu_addchr(&ctx.as_string, ch);
5118 }
5119#if 0
5120 else if (next == '(') {
5121 syntax_error("<(process) not supported");
5122 goto parse_error;
5123 }
5124#endif
5125 if (parse_redirect(&ctx, redir_fd, redir_style, input))
5126 goto parse_error;
5127 continue; /* back to top of while (1) */
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01005128 case '#':
5129 if (dest.length == 0 && !dest.has_quoted_part) {
5130 /* skip "#comment" */
5131 while (1) {
5132 ch = i_peek(input);
5133 if (ch == EOF || ch == '\n')
5134 break;
5135 i_getch(input);
5136 /* note: we do not add it to &ctx.as_string */
5137 }
5138 nommu_addchr(&ctx.as_string, '\n');
5139 continue; /* back to top of while (1) */
5140 }
5141 break;
5142 case '\\':
5143 if (next == '\n') {
5144 /* It's "\<newline>" */
5145#if !BB_MMU
5146 /* Remove trailing '\' from ctx.as_string */
5147 ctx.as_string.data[--ctx.as_string.length] = '\0';
5148#endif
5149 ch = i_getch(input); /* eat it */
5150 continue; /* back to top of while (1) */
5151 }
5152 break;
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00005153 }
5154
5155 if (dest.o_assignment == MAYBE_ASSIGNMENT
5156 /* check that we are not in word in "a=1 2>word b=1": */
5157 && !ctx.pending_redirect
5158 ) {
5159 /* ch is a special char and thus this word
5160 * cannot be an assignment */
5161 dest.o_assignment = NOT_ASSIGNMENT;
Denys Vlasenko29f9b722011-05-14 11:27:36 +02005162 debug_printf_parse("dest.o_assignment='%s'\n", assignment_flag[dest.o_assignment]);
Denis Vlasenkoc96865f2009-04-10 00:20:58 +00005163 }
5164
Denys Vlasenkocbfe6ad2009-08-12 19:47:44 +02005165 /* Note: nommu_addchr(&ctx.as_string, ch) is already done */
5166
Denis Vlasenkobb81c582007-01-30 22:32:09 +00005167 switch (ch) {
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01005168 case '#': /* non-comment #: "echo a#b" etc */
5169 o_addQchr(&dest, ch);
Eric Andersen25f27032001-04-26 23:22:31 +00005170 break;
5171 case '\\':
5172 if (next == EOF) {
Denis Vlasenko05d3b7c2009-04-09 19:16:15 +00005173 syntax_error("\\<eof>");
Denis Vlasenko0b677d82009-04-10 13:49:10 +00005174 xfunc_die();
Eric Andersen25f27032001-04-26 23:22:31 +00005175 }
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00005176 ch = i_getch(input);
Denys Vlasenko7b4c0fd2010-11-22 17:58:14 +01005177 /* note: ch != '\n' (that case does not reach this place) */
5178 o_addchr(&dest, '\\');
5179 /*nommu_addchr(&ctx.as_string, '\\'); - already done */
5180 o_addchr(&dest, ch);
5181 nommu_addchr(&ctx.as_string, ch);
5182 /* Example: echo Hello \2>file
5183 * we need to know that word 2 is quoted */
5184 dest.has_quoted_part = 1;
Eric Andersen25f27032001-04-26 23:22:31 +00005185 break;
5186 case '$':
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01005187 if (!parse_dollar(&ctx.as_string, &dest, input, /*quote_mask:*/ 0)) {
Denis Vlasenkoa24c8ca2009-04-04 15:24:40 +00005188 debug_printf_parse("parse_stream parse error: "
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01005189 "parse_dollar returned 0 (error)\n");
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005190 goto parse_error;
Denis Vlasenkoe725bfe2007-05-03 22:45:39 +00005191 }
Eric Andersen25f27032001-04-26 23:22:31 +00005192 break;
5193 case '\'':
Denys Vlasenko38292b62010-09-05 14:49:40 +02005194 dest.has_quoted_part = 1;
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005195 if (next == '\'' && !ctx.pending_redirect) {
5196 insert_empty_quoted_str_marker:
5197 nommu_addchr(&ctx.as_string, next);
5198 i_getch(input); /* eat second ' */
5199 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
5200 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
5201 } else {
5202 while (1) {
5203 ch = i_getch(input);
5204 if (ch == EOF) {
5205 syntax_error_unterm_ch('\'');
5206 goto parse_error;
5207 }
5208 nommu_addchr(&ctx.as_string, ch);
5209 if (ch == '\'')
5210 break;
5211 o_addqchr(&dest, ch);
Denis Vlasenkof8d01d32008-06-14 17:13:20 +00005212 }
Eric Andersen25f27032001-04-26 23:22:31 +00005213 }
Eric Andersen25f27032001-04-26 23:22:31 +00005214 break;
5215 case '"':
Denys Vlasenko38292b62010-09-05 14:49:40 +02005216 dest.has_quoted_part = 1;
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005217 if (next == '"' && !ctx.pending_redirect)
5218 goto insert_empty_quoted_str_marker;
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005219 if (dest.o_assignment == NOT_ASSIGNMENT)
Denys Vlasenko5b6210c2010-09-09 13:32:21 +02005220 dest.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS;
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01005221 if (!encode_string(&ctx.as_string, &dest, input, '"', /*process_bkslash:*/ 1))
Denys Vlasenko77a7b552010-09-09 12:40:03 +02005222 goto parse_error;
Denys Vlasenko5b6210c2010-09-09 13:32:21 +02005223 dest.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS;
Eric Andersen25f27032001-04-26 23:22:31 +00005224 break;
Denis Vlasenko14b5dd92007-05-20 21:51:38 +00005225#if ENABLE_HUSH_TICK
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00005226 case '`': {
Denys Vlasenko60a94142011-05-13 20:57:01 +02005227 USE_FOR_NOMMU(unsigned pos;)
Denys Vlasenko2e48d532010-05-22 17:30:39 +02005228
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005229 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
5230 o_addchr(&dest, '`');
Denys Vlasenko60a94142011-05-13 20:57:01 +02005231 USE_FOR_NOMMU(pos = dest.length;)
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01005232 if (!add_till_backquote(&dest, input, /*in_dquote:*/ 0))
5233 goto parse_error;
Denys Vlasenko2e48d532010-05-22 17:30:39 +02005234# if !BB_MMU
Denis Vlasenko5c090a92009-04-08 21:51:33 +00005235 o_addstr(&ctx.as_string, dest.data + pos);
5236 o_addchr(&ctx.as_string, '`');
Denys Vlasenko2e48d532010-05-22 17:30:39 +02005237# endif
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005238 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
5239 //debug_printf_subst("SUBST RES3 '%s'\n", dest.data + pos);
Eric Andersen25f27032001-04-26 23:22:31 +00005240 break;
Denis Vlasenko7b4f3f12008-06-10 18:04:32 +00005241 }
Denis Vlasenko14b5dd92007-05-20 21:51:38 +00005242#endif
Eric Andersen25f27032001-04-26 23:22:31 +00005243 case ';':
Denis Vlasenko17f02e72008-07-14 04:32:29 +00005244#if ENABLE_HUSH_CASE
5245 case_semi:
5246#endif
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005247 if (done_word(&dest, &ctx)) {
5248 goto parse_error;
5249 }
5250 done_pipe(&ctx, PIPE_SEQ);
Denis Vlasenko17f02e72008-07-14 04:32:29 +00005251#if ENABLE_HUSH_CASE
5252 /* Eat multiple semicolons, detect
5253 * whether it means something special */
5254 while (1) {
5255 ch = i_peek(input);
5256 if (ch != ';')
5257 break;
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00005258 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00005259 nommu_addchr(&ctx.as_string, ch);
Denys Vlasenkoe9bda902009-05-23 16:50:07 +02005260 if (ctx.ctx_res_w == RES_CASE_BODY) {
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005261 ctx.ctx_dsemicolon = 1;
5262 ctx.ctx_res_w = RES_MATCH;
Denis Vlasenko17f02e72008-07-14 04:32:29 +00005263 break;
5264 }
5265 }
5266#endif
Denis Vlasenko2b576b82008-08-04 00:46:07 +00005267 new_cmd:
5268 /* We just finished a cmd. New one may start
5269 * with an assignment */
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005270 dest.o_assignment = MAYBE_ASSIGNMENT;
Denys Vlasenko29f9b722011-05-14 11:27:36 +02005271 debug_printf_parse("dest.o_assignment='%s'\n", assignment_flag[dest.o_assignment]);
Eric Andersen25f27032001-04-26 23:22:31 +00005272 break;
5273 case '&':
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005274 if (done_word(&dest, &ctx)) {
5275 goto parse_error;
5276 }
Denis Vlasenkobb81c582007-01-30 22:32:09 +00005277 if (next == '&') {
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00005278 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00005279 nommu_addchr(&ctx.as_string, ch);
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005280 done_pipe(&ctx, PIPE_AND);
Eric Andersen25f27032001-04-26 23:22:31 +00005281 } else {
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005282 done_pipe(&ctx, PIPE_BG);
Eric Andersen25f27032001-04-26 23:22:31 +00005283 }
Denis Vlasenko2b576b82008-08-04 00:46:07 +00005284 goto new_cmd;
Eric Andersen25f27032001-04-26 23:22:31 +00005285 case '|':
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005286 if (done_word(&dest, &ctx)) {
5287 goto parse_error;
5288 }
Denis Vlasenkofbeeb322008-07-31 00:17:01 +00005289#if ENABLE_HUSH_CASE
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005290 if (ctx.ctx_res_w == RES_MATCH)
Denis Vlasenkof1736072008-07-31 10:09:26 +00005291 break; /* we are in case's "word | word)" */
Denis Vlasenkofbeeb322008-07-31 00:17:01 +00005292#endif
Denis Vlasenko2b576b82008-08-04 00:46:07 +00005293 if (next == '|') { /* || */
Denis Vlasenko609f2ab2009-04-04 23:15:14 +00005294 ch = i_getch(input);
Denis Vlasenkoaf07b7c2009-04-07 13:26:18 +00005295 nommu_addchr(&ctx.as_string, ch);
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005296 done_pipe(&ctx, PIPE_OR);
Eric Andersen25f27032001-04-26 23:22:31 +00005297 } else {
5298 /* we could pick up a file descriptor choice here
5299 * with redirect_opt_num(), but bash doesn't do it.
5300 * "echo foo 2| cat" yields "foo 2". */
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005301 done_command(&ctx);
Eric Andersen25f27032001-04-26 23:22:31 +00005302 }
Denis Vlasenko2b576b82008-08-04 00:46:07 +00005303 goto new_cmd;
Eric Andersen25f27032001-04-26 23:22:31 +00005304 case '(':
Denis Vlasenko17f02e72008-07-14 04:32:29 +00005305#if ENABLE_HUSH_CASE
Denis Vlasenkof1736072008-07-31 10:09:26 +00005306 /* "case... in [(]word)..." - skip '(' */
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005307 if (ctx.ctx_res_w == RES_MATCH
5308 && ctx.command->argv == NULL /* not (word|(... */
5309 && dest.length == 0 /* not word(... */
Denys Vlasenko38292b62010-09-05 14:49:40 +02005310 && dest.has_quoted_part == 0 /* not ""(... */
Denis Vlasenko17f02e72008-07-14 04:32:29 +00005311 ) {
5312 continue;
5313 }
5314#endif
Eric Andersen25f27032001-04-26 23:22:31 +00005315 case '{':
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005316 if (parse_group(&dest, &ctx, input, ch) != 0) {
5317 goto parse_error;
Denis Vlasenkoe725bfe2007-05-03 22:45:39 +00005318 }
Denis Vlasenko2b576b82008-08-04 00:46:07 +00005319 goto new_cmd;
Eric Andersen25f27032001-04-26 23:22:31 +00005320 case ')':
Denis Vlasenko17f02e72008-07-14 04:32:29 +00005321#if ENABLE_HUSH_CASE
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005322 if (ctx.ctx_res_w == RES_MATCH)
Denis Vlasenko17f02e72008-07-14 04:32:29 +00005323 goto case_semi;
5324#endif
Eric Andersen25f27032001-04-26 23:22:31 +00005325 case '}':
Denis Vlasenkoc3735272008-10-09 12:58:26 +00005326 /* proper use of this character is caught by end_trigger:
5327 * if we see {, we call parse_group(..., end_trigger='}')
5328 * and it will match } earlier (not here). */
Denys Vlasenkob05bcaf2017-01-03 11:47:50 +01005329 G.last_exitcode = 2;
Denys Vlasenko39701202017-08-02 19:44:05 +02005330 syntax_error_unexpected_ch(ch);
Denys Vlasenko9fda6092017-07-14 13:36:48 +02005331 goto parse_error2;
Eric Andersen25f27032001-04-26 23:22:31 +00005332 default:
Denis Vlasenko5ec61322008-06-24 00:50:07 +00005333 if (HUSH_DEBUG)
Denis Vlasenko90e485c2007-05-23 15:22:50 +00005334 bb_error_msg_and_die("BUG: unexpected %c\n", ch);
Eric Andersen25f27032001-04-26 23:22:31 +00005335 }
Denis Vlasenkof8d01d32008-06-14 17:13:20 +00005336 } /* while (1) */
Denis Vlasenko027e3fd2009-04-02 22:50:40 +00005337
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005338 parse_error:
Denys Vlasenkob05bcaf2017-01-03 11:47:50 +01005339 G.last_exitcode = 1;
Denys Vlasenko9fda6092017-07-14 13:36:48 +02005340 parse_error2:
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005341 {
Denis Vlasenko60b392f2009-04-03 19:14:32 +00005342 struct parse_context *pctx;
5343 IF_HAS_KEYWORDS(struct parse_context *p2;)
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005344
5345 /* Clean up allocated tree.
Denys Vlasenko764b2f02009-06-07 16:05:04 +02005346 * Sample for finding leaks on syntax error recovery path.
5347 * Run it from interactive shell, watch pmap `pidof hush`.
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005348 * while if false; then false; fi; do break; fi
Denis Vlasenkocc4c6932009-04-05 07:38:48 +00005349 * Samples to catch leaks at execution:
Denys Vlasenko5d5a6112016-11-07 19:36:50 +01005350 * while if (true | { true;}); then echo ok; fi; do break; done
5351 * 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 +00005352 */
5353 pctx = &ctx;
5354 do {
5355 /* Update pipe/command counts,
5356 * otherwise freeing may miss some */
5357 done_pipe(pctx, PIPE_SEQ);
5358 debug_printf_clean("freeing list %p from ctx %p\n",
5359 pctx->list_head, pctx);
5360 debug_print_tree(pctx->list_head, 0);
Denis Vlasenko0701dca2009-04-11 10:38:47 +00005361 free_pipe_list(pctx->list_head);
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005362 debug_printf_clean("freed list %p\n", pctx->list_head);
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005363#if !BB_MMU
5364 o_free_unsafe(&pctx->as_string);
5365#endif
Denis Vlasenko60b392f2009-04-03 19:14:32 +00005366 IF_HAS_KEYWORDS(p2 = pctx->stack;)
Denis Vlasenkob6e65562009-04-03 16:49:04 +00005367 if (pctx != &ctx) {
5368 free(pctx);
5369 }
Denis Vlasenko60b392f2009-04-03 19:14:32 +00005370 IF_HAS_KEYWORDS(pctx = p2;)
5371 } while (HAS_KEYWORDS && pctx);
Denys Vlasenkocecbc982011-03-30 18:54:52 +02005372
Denys Vlasenkoa439fa92011-03-30 19:11:46 +02005373 o_free(&dest);
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005374#if !BB_MMU
Denys Vlasenkocecbc982011-03-30 18:54:52 +02005375 if (pstring)
5376 *pstring = NULL;
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00005377#endif
Denys Vlasenkocecbc982011-03-30 18:54:52 +02005378 debug_leave();
5379 return ERR_PTR;
Denis Vlasenko027e3fd2009-04-02 22:50:40 +00005380 }
Eric Andersen25f27032001-04-26 23:22:31 +00005381}
5382
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005383
5384/*** Execution routines ***/
5385
5386/* Expansion can recurse, need forward decls: */
Denys Vlasenko637982f2017-07-06 01:52:23 +02005387#if !BASH_PATTERN_SUBST && !ENABLE_HUSH_CASE
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02005388/* only ${var/pattern/repl} (its pattern part) needs additional mode */
5389#define expand_string_to_string(str, do_unbackslash) \
5390 expand_string_to_string(str)
5391#endif
Denys Vlasenkoebee4102010-09-10 10:17:53 +02005392static char *expand_string_to_string(const char *str, int do_unbackslash);
Denys Vlasenko26777aa2010-11-22 23:49:10 +01005393#if ENABLE_HUSH_TICK
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005394static int process_command_subs(o_string *dest, const char *s);
Denys Vlasenko26777aa2010-11-22 23:49:10 +01005395#endif
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005396
5397/* expand_strvec_to_strvec() takes a list of strings, expands
5398 * all variable references within and returns a pointer to
5399 * a list of expanded strings, possibly with larger number
5400 * of strings. (Think VAR="a b"; echo $VAR).
5401 * This new list is allocated as a single malloc block.
5402 * NULL-terminated list of char* pointers is at the beginning of it,
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005403 * followed by strings themselves.
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005404 * Caller can deallocate entire list by single free(list). */
5405
Denys Vlasenko238081f2010-10-03 14:26:26 +02005406/* A horde of its helpers come first: */
5407
5408static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len)
5409{
5410 while (--len >= 0) {
Denys Vlasenko9e800222010-10-03 14:28:04 +02005411 char c = *str++;
Denys Vlasenko957f79f2010-10-03 17:15:50 +02005412
Denys Vlasenko9e800222010-10-03 14:28:04 +02005413#if ENABLE_HUSH_BRACE_EXPANSION
5414 if (c == '{' || c == '}') {
5415 /* { -> \{, } -> \} */
5416 o_addchr(o, '\\');
Denys Vlasenko957f79f2010-10-03 17:15:50 +02005417 /* And now we want to add { or } and continue:
5418 * o_addchr(o, c);
5419 * continue;
Denys Vlasenko10ad6222017-04-17 16:13:32 +02005420 * luckily, just falling through achieves this.
Denys Vlasenko957f79f2010-10-03 17:15:50 +02005421 */
Denys Vlasenko9e800222010-10-03 14:28:04 +02005422 }
5423#endif
5424 o_addchr(o, c);
5425 if (c == '\\') {
Denys Vlasenko238081f2010-10-03 14:26:26 +02005426 /* \z -> \\\z; \<eol> -> \\<eol> */
5427 o_addchr(o, '\\');
5428 if (len) {
5429 len--;
5430 o_addchr(o, '\\');
5431 o_addchr(o, *str++);
5432 }
5433 }
5434 }
5435}
5436
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005437/* Store given string, finalizing the word and starting new one whenever
5438 * we encounter IFS char(s). This is used for expanding variable values.
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005439 * End-of-string does NOT finalize word: think about 'echo -$VAR-'.
5440 * Return in *ended_with_ifs:
5441 * 1 - ended with IFS char, else 0 (this includes case of empty str).
5442 */
5443static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const char *str)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005444{
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005445 int last_is_ifs = 0;
5446
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005447 while (1) {
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02005448 int word_len;
5449
5450 if (!*str) /* EOL - do not finalize word */
5451 break;
5452 word_len = strcspn(str, G.ifs);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005453 if (word_len) {
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02005454 /* We have WORD_LEN leading non-IFS chars */
Denys Vlasenko238081f2010-10-03 14:26:26 +02005455 if (!(output->o_expflags & EXP_FLAG_GLOB)) {
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02005456 o_addblock(output, str, word_len);
Denys Vlasenko238081f2010-10-03 14:26:26 +02005457 } else {
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02005458 /* Protect backslashes against globbing up :)
Denys Vlasenkoa769e022010-09-10 10:12:34 +02005459 * Example: "v='\*'; echo b$v" prints "b\*"
5460 * (and does not try to glob on "*")
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02005461 */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005462 o_addblock_duplicate_backslash(output, str, word_len);
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02005463 /*/ Why can't we do it easier? */
5464 /*o_addblock(output, str, word_len); - WRONG: "v='\*'; echo Z$v" prints "Z*" instead of "Z\*" */
5465 /*o_addqblock(output, str, word_len); - WRONG: "v='*'; echo Z$v" prints "Z*" instead of Z* files */
5466 }
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005467 last_is_ifs = 0;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005468 str += word_len;
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02005469 if (!*str) /* EOL - do not finalize word */
5470 break;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005471 }
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005472
5473 /* We know str here points to at least one IFS char */
5474 last_is_ifs = 1;
5475 str += strspn(str, G.ifs); /* skip IFS chars */
5476 if (!*str) /* EOL - do not finalize word */
5477 break;
5478
5479 /* Start new word... but not always! */
5480 /* Case "v=' a'; echo ''$v": we do need to finalize empty word: */
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02005481 if (output->has_quoted_part
5482 /* Case "v=' a'; echo $v":
5483 * here nothing precedes the space in $v expansion,
5484 * therefore we should not finish the word
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005485 * (IOW: if there *is* word to finalize, only then do it):
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02005486 */
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005487 || (n > 0 && output->data[output->length - 1])
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02005488 ) {
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02005489 o_addchr(output, '\0');
5490 debug_print_list("expand_on_ifs", output, n);
5491 n = o_save_ptr(output, n);
5492 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005493 }
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005494
5495 if (ended_with_ifs)
5496 *ended_with_ifs = last_is_ifs;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005497 debug_print_list("expand_on_ifs[1]", output, n);
5498 return n;
5499}
5500
5501/* Helper to expand $((...)) and heredoc body. These act as if
5502 * they are in double quotes, with the exception that they are not :).
5503 * Just the rules are similar: "expand only $var and `cmd`"
5504 *
5505 * Returns malloced string.
5506 * As an optimization, we return NULL if expansion is not needed.
5507 */
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01005508#if !BASH_PATTERN_SUBST
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02005509/* only ${var/pattern/repl} (its pattern part) needs additional mode */
5510#define encode_then_expand_string(str, process_bkslash, do_unbackslash) \
5511 encode_then_expand_string(str)
5512#endif
5513static char *encode_then_expand_string(const char *str, int process_bkslash, int do_unbackslash)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005514{
Denys Vlasenko637982f2017-07-06 01:52:23 +02005515#if !BASH_PATTERN_SUBST
5516 const int do_unbackslash = 1;
5517#endif
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005518 char *exp_str;
5519 struct in_str input;
5520 o_string dest = NULL_O_STRING;
5521
5522 if (!strchr(str, '$')
Denys Vlasenko77b32cc2010-09-06 11:27:32 +02005523 && !strchr(str, '\\')
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005524#if ENABLE_HUSH_TICK
5525 && !strchr(str, '`')
5526#endif
5527 ) {
5528 return NULL;
5529 }
5530
5531 /* We need to expand. Example:
5532 * echo $(($a + `echo 1`)) $((1 + $((2)) ))
5533 */
5534 setup_string_in_str(&input, str);
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02005535 encode_string(NULL, &dest, &input, EOF, process_bkslash);
Denys Vlasenko3eab24e2011-03-24 05:25:59 +01005536//TODO: error check (encode_string returns 0 on error)?
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005537 //bb_error_msg("'%s' -> '%s'", str, dest.data);
Denys Vlasenkoebee4102010-09-10 10:17:53 +02005538 exp_str = expand_string_to_string(dest.data, /*unbackslash:*/ do_unbackslash);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005539 //bb_error_msg("'%s' -> '%s'", dest.data, exp_str);
5540 o_free_unsafe(&dest);
5541 return exp_str;
5542}
5543
Denys Vlasenko0b883582016-12-23 16:49:07 +01005544#if ENABLE_FEATURE_SH_MATH
Denys Vlasenko063847d2010-09-15 13:33:02 +02005545static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005546{
Denys Vlasenko06d44d72010-09-13 12:49:03 +02005547 arith_state_t math_state;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005548 arith_t res;
5549 char *exp_str;
5550
Denys Vlasenko06d44d72010-09-13 12:49:03 +02005551 math_state.lookupvar = get_local_var_value;
5552 math_state.setvar = set_local_var_from_halves;
5553 //math_state.endofname = endofname;
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02005554 exp_str = encode_then_expand_string(arg, /*process_bkslash:*/ 1, /*unbackslash:*/ 1);
Denys Vlasenko06d44d72010-09-13 12:49:03 +02005555 res = arith(&math_state, exp_str ? exp_str : arg);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005556 free(exp_str);
Denys Vlasenko063847d2010-09-15 13:33:02 +02005557 if (errmsg_p)
5558 *errmsg_p = math_state.errmsg;
5559 if (math_state.errmsg)
Denys Vlasenko39701202017-08-02 19:44:05 +02005560 msg_and_die_if_script(math_state.errmsg);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005561 return res;
5562}
5563#endif
5564
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01005565#if BASH_PATTERN_SUBST
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005566/* ${var/[/]pattern[/repl]} helpers */
5567static char *strstr_pattern(char *val, const char *pattern, int *size)
5568{
5569 while (1) {
5570 char *end = scan_and_match(val, pattern, SCAN_MOVE_FROM_RIGHT + SCAN_MATCH_LEFT_HALF);
5571 debug_printf_varexp("val:'%s' pattern:'%s' end:'%s'\n", val, pattern, end);
5572 if (end) {
5573 *size = end - val;
5574 return val;
5575 }
5576 if (*val == '\0')
5577 return NULL;
5578 /* Optimization: if "*pat" did not match the start of "string",
5579 * we know that "tring", "ring" etc will not match too:
5580 */
5581 if (pattern[0] == '*')
5582 return NULL;
5583 val++;
5584 }
5585}
5586static char *replace_pattern(char *val, const char *pattern, const char *repl, char exp_op)
5587{
5588 char *result = NULL;
5589 unsigned res_len = 0;
5590 unsigned repl_len = strlen(repl);
5591
5592 while (1) {
5593 int size;
5594 char *s = strstr_pattern(val, pattern, &size);
5595 if (!s)
5596 break;
5597
5598 result = xrealloc(result, res_len + (s - val) + repl_len + 1);
Denys Vlasenko0675b032017-07-24 02:17:05 +02005599 strcpy(mempcpy(result + res_len, val, s - val), repl);
5600 res_len += (s - val) + repl_len;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005601 debug_printf_varexp("val:'%s' s:'%s' result:'%s'\n", val, s, result);
5602
5603 val = s + size;
5604 if (exp_op == '/')
5605 break;
5606 }
Denys Vlasenko0675b032017-07-24 02:17:05 +02005607 if (*val && result) {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005608 result = xrealloc(result, res_len + strlen(val) + 1);
5609 strcpy(result + res_len, val);
5610 debug_printf_varexp("val:'%s' result:'%s'\n", val, result);
5611 }
5612 debug_printf_varexp("result:'%s'\n", result);
5613 return result;
5614}
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01005615#endif /* BASH_PATTERN_SUBST */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005616
5617/* Helper:
5618 * Handles <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct.
5619 */
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02005620static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, char **pp)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005621{
5622 const char *val = NULL;
5623 char *to_be_freed = NULL;
5624 char *p = *pp;
5625 char *var;
5626 char first_char;
5627 char exp_op;
5628 char exp_save = exp_save; /* for compiler */
5629 char *exp_saveptr; /* points to expansion operator */
5630 char *exp_word = exp_word; /* for compiler */
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02005631 char arg0;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005632
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005633 *p = '\0'; /* replace trailing SPECIAL_VAR_SYMBOL */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005634 var = arg;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005635 exp_saveptr = arg[1] ? strchr(VAR_ENCODED_SUBST_OPS, arg[1]) : NULL;
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02005636 arg0 = arg[0];
5637 first_char = arg[0] = arg0 & 0x7f;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005638 exp_op = 0;
5639
Denys Vlasenko2093ad22017-07-26 00:07:27 +02005640 if (first_char == '#' && arg[1] /* ${#...} but not ${#} */
5641 && (!exp_saveptr /* and ( not(${#<op_char>...}) */
5642 || (arg[2] == '\0' && strchr(SPECIAL_VARS_STR, arg[1])) /* or ${#C} "len of $C" ) */
5643 ) /* NB: skipping ^^^specvar check mishandles ${#::2} */
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005644 ) {
5645 /* It must be length operator: ${#var} */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005646 var++;
5647 exp_op = 'L';
5648 } else {
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005649 /* Maybe handle parameter expansion */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005650 if (exp_saveptr /* if 2nd char is one of expansion operators */
5651 && strchr(NUMERIC_SPECVARS_STR, first_char) /* 1st char is special variable */
5652 ) {
5653 /* ${?:0}, ${#[:]%0} etc */
5654 exp_saveptr = var + 1;
5655 } else {
5656 /* ${?}, ${var}, ${var:0}, ${var[:]%0} etc */
5657 exp_saveptr = var+1 + strcspn(var+1, VAR_ENCODED_SUBST_OPS);
5658 }
5659 exp_op = exp_save = *exp_saveptr;
5660 if (exp_op) {
5661 exp_word = exp_saveptr + 1;
5662 if (exp_op == ':') {
5663 exp_op = *exp_word++;
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005664//TODO: try ${var:} and ${var:bogus} in non-bash config
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01005665 if (BASH_SUBSTR
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005666 && (!exp_op || !strchr(MINUS_PLUS_EQUAL_QUESTION, exp_op))
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005667 ) {
5668 /* oops... it's ${var:N[:M]}, not ${var:?xxx} or some such */
5669 exp_op = ':';
5670 exp_word--;
5671 }
5672 }
5673 *exp_saveptr = '\0';
5674 } /* else: it's not an expansion op, but bare ${var} */
5675 }
5676
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005677 /* Look up the variable in question */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005678 if (isdigit(var[0])) {
Denys Vlasenko77a7b552010-09-09 12:40:03 +02005679 /* parse_dollar should have vetted var for us */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005680 int n = xatoi_positive(var);
5681 if (n < G.global_argc)
5682 val = G.global_argv[n];
5683 /* else val remains NULL: $N with too big N */
5684 } else {
5685 switch (var[0]) {
5686 case '$': /* pid */
5687 val = utoa(G.root_pid);
5688 break;
5689 case '!': /* bg pid */
5690 val = G.last_bg_pid ? utoa(G.last_bg_pid) : "";
5691 break;
5692 case '?': /* exitcode */
5693 val = utoa(G.last_exitcode);
5694 break;
5695 case '#': /* argc */
5696 val = utoa(G.global_argc ? G.global_argc-1 : 0);
5697 break;
5698 default:
5699 val = get_local_var_value(var);
5700 }
5701 }
5702
5703 /* Handle any expansions */
5704 if (exp_op == 'L') {
Denys Vlasenkoc538d5b2014-08-13 09:57:44 +02005705 reinit_unicode_for_hush();
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005706 debug_printf_expand("expand: length(%s)=", val);
Denys Vlasenkoc538d5b2014-08-13 09:57:44 +02005707 val = utoa(val ? unicode_strlen(val) : 0);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005708 debug_printf_expand("%s\n", val);
5709 } else if (exp_op) {
5710 if (exp_op == '%' || exp_op == '#') {
5711 /* Standard-mandated substring removal ops:
5712 * ${parameter%word} - remove smallest suffix pattern
5713 * ${parameter%%word} - remove largest suffix pattern
5714 * ${parameter#word} - remove smallest prefix pattern
5715 * ${parameter##word} - remove largest prefix pattern
5716 *
5717 * Word is expanded to produce a glob pattern.
5718 * Then var's value is matched to it and matching part removed.
5719 */
5720 if (val && val[0]) {
Denys Vlasenko4f870492010-09-10 11:06:01 +02005721 char *t;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005722 char *exp_exp_word;
5723 char *loc;
5724 unsigned scan_flags = pick_scan(exp_op, *exp_word);
Denys Vlasenkoe4dcba12010-10-28 18:57:19 +02005725 if (exp_op == *exp_word) /* ## or %% */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005726 exp_word++;
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02005727 exp_exp_word = encode_then_expand_string(exp_word, /*process_bkslash:*/ 1, /*unbackslash:*/ 1);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005728 if (exp_exp_word)
5729 exp_word = exp_exp_word;
Denys Vlasenko4f870492010-09-10 11:06:01 +02005730 /* HACK ALERT. We depend here on the fact that
5731 * G.global_argv and results of utoa and get_local_var_value
5732 * are actually in writable memory:
5733 * scan_and_match momentarily stores NULs there. */
5734 t = (char*)val;
5735 loc = scan_and_match(t, exp_word, scan_flags);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005736 //bb_error_msg("op:%c str:'%s' pat:'%s' res:'%s'",
Denys Vlasenko4f870492010-09-10 11:06:01 +02005737 // exp_op, t, exp_word, loc);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005738 free(exp_exp_word);
5739 if (loc) { /* match was found */
5740 if (scan_flags & SCAN_MATCH_LEFT_HALF) /* #[#] */
Denys Vlasenko4f870492010-09-10 11:06:01 +02005741 val = loc; /* take right part */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005742 else /* %[%] */
Denys Vlasenko4f870492010-09-10 11:06:01 +02005743 val = to_be_freed = xstrndup(val, loc - val); /* left */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005744 }
5745 }
5746 }
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01005747#if BASH_PATTERN_SUBST
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005748 else if (exp_op == '/' || exp_op == '\\') {
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02005749 /* It's ${var/[/]pattern[/repl]} thing.
5750 * Note that in encoded form it has TWO parts:
5751 * var/pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL>
Denys Vlasenko4f870492010-09-10 11:06:01 +02005752 * and if // is used, it is encoded as \:
5753 * var\pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL>
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02005754 */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005755 /* Empty variable always gives nothing: */
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02005756 // "v=''; echo ${v/*/w}" prints "", not "w"
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005757 if (val && val[0]) {
Denys Vlasenko4f870492010-09-10 11:06:01 +02005758 /* pattern uses non-standard expansion.
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02005759 * repl should be unbackslashed and globbed
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02005760 * by the usual expansion rules:
5761 * >az; >bz;
5762 * v='a bz'; echo "${v/a*z/a*z}" prints "a*z"
5763 * v='a bz'; echo "${v/a*z/\z}" prints "\z"
5764 * v='a bz'; echo ${v/a*z/a*z} prints "az"
5765 * v='a bz'; echo ${v/a*z/\z} prints "z"
5766 * (note that a*z _pattern_ is never globbed!)
5767 */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005768 char *pattern, *repl, *t;
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02005769 pattern = encode_then_expand_string(exp_word, /*process_bkslash:*/ 0, /*unbackslash:*/ 0);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005770 if (!pattern)
5771 pattern = xstrdup(exp_word);
5772 debug_printf_varexp("pattern:'%s'->'%s'\n", exp_word, pattern);
5773 *p++ = SPECIAL_VAR_SYMBOL;
5774 exp_word = p;
5775 p = strchr(p, SPECIAL_VAR_SYMBOL);
5776 *p = '\0';
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02005777 repl = encode_then_expand_string(exp_word, /*process_bkslash:*/ arg0 & 0x80, /*unbackslash:*/ 1);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005778 debug_printf_varexp("repl:'%s'->'%s'\n", exp_word, repl);
5779 /* HACK ALERT. We depend here on the fact that
5780 * G.global_argv and results of utoa and get_local_var_value
5781 * are actually in writable memory:
5782 * replace_pattern momentarily stores NULs there. */
5783 t = (char*)val;
5784 to_be_freed = replace_pattern(t,
5785 pattern,
5786 (repl ? repl : exp_word),
5787 exp_op);
5788 if (to_be_freed) /* at least one replace happened */
5789 val = to_be_freed;
5790 free(pattern);
5791 free(repl);
5792 }
5793 }
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01005794#endif /* BASH_PATTERN_SUBST */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005795 else if (exp_op == ':') {
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01005796#if BASH_SUBSTR && ENABLE_FEATURE_SH_MATH
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005797 /* It's ${var:N[:M]} bashism.
5798 * Note that in encoded form it has TWO parts:
5799 * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL>
5800 */
5801 arith_t beg, len;
Denys Vlasenko063847d2010-09-15 13:33:02 +02005802 const char *errmsg;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005803
Denys Vlasenko063847d2010-09-15 13:33:02 +02005804 beg = expand_and_evaluate_arith(exp_word, &errmsg);
5805 if (errmsg)
5806 goto arith_err;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005807 debug_printf_varexp("beg:'%s'=%lld\n", exp_word, (long long)beg);
5808 *p++ = SPECIAL_VAR_SYMBOL;
5809 exp_word = p;
5810 p = strchr(p, SPECIAL_VAR_SYMBOL);
5811 *p = '\0';
Denys Vlasenko063847d2010-09-15 13:33:02 +02005812 len = expand_and_evaluate_arith(exp_word, &errmsg);
5813 if (errmsg)
5814 goto arith_err;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005815 debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len);
Denys Vlasenkoe32b6502017-07-17 16:46:57 +02005816 if (beg < 0) {
5817 /* negative beg counts from the end */
5818 beg = (arith_t)strlen(val) + beg;
5819 if (beg < 0) /* ${v: -999999} is "" */
5820 beg = len = 0;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005821 }
Denys Vlasenkoe32b6502017-07-17 16:46:57 +02005822 debug_printf_varexp("from val:'%s'\n", val);
5823 if (len < 0) {
5824 /* in bash, len=-n means strlen()-n */
5825 len = (arith_t)strlen(val) - beg + len;
5826 if (len < 0) /* bash compat */
Denys Vlasenko39701202017-08-02 19:44:05 +02005827 msg_and_die_if_script("%s: substring expression < 0", var);
Denys Vlasenkoe32b6502017-07-17 16:46:57 +02005828 }
Denys Vlasenko0ba80e42017-07-17 16:50:20 +02005829 if (len <= 0 || !val || beg >= strlen(val)) {
Denys Vlasenkoe32b6502017-07-17 16:46:57 +02005830 arith_err:
5831 val = NULL;
5832 } else {
5833 /* Paranoia. What if user entered 9999999999999
5834 * which fits in arith_t but not int? */
5835 if (len >= INT_MAX)
5836 len = INT_MAX;
5837 val = to_be_freed = xstrndup(val + beg, len);
5838 }
5839 debug_printf_varexp("val:'%s'\n", val);
5840#else /* not (HUSH_SUBSTR_EXPANSION && FEATURE_SH_MATH) */
Denys Vlasenko39701202017-08-02 19:44:05 +02005841 msg_and_die_if_script("malformed ${%s:...}", var);
Denys Vlasenkoe32b6502017-07-17 16:46:57 +02005842 val = NULL;
5843#endif
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005844 } else { /* one of "-=+?" */
5845 /* Standard-mandated substitution ops:
5846 * ${var?word} - indicate error if unset
5847 * If var is unset, word (or a message indicating it is unset
5848 * if word is null) is written to standard error
5849 * and the shell exits with a non-zero exit status.
5850 * Otherwise, the value of var is substituted.
5851 * ${var-word} - use default value
5852 * If var is unset, word is substituted.
5853 * ${var=word} - assign and use default value
5854 * If var is unset, word is assigned to var.
5855 * In all cases, final value of var is substituted.
5856 * ${var+word} - use alternative value
5857 * If var is unset, null is substituted.
5858 * Otherwise, word is substituted.
5859 *
5860 * Word is subjected to tilde expansion, parameter expansion,
5861 * command substitution, and arithmetic expansion.
5862 * If word is not needed, it is not expanded.
5863 *
5864 * Colon forms (${var:-word}, ${var:=word} etc) do the same,
5865 * but also treat null var as if it is unset.
5866 */
5867 int use_word = (!val || ((exp_save == ':') && !val[0]));
5868 if (exp_op == '+')
5869 use_word = !use_word;
5870 debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op,
5871 (exp_save == ':') ? "true" : "false", use_word);
5872 if (use_word) {
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02005873 to_be_freed = encode_then_expand_string(exp_word, /*process_bkslash:*/ 1, /*unbackslash:*/ 1);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005874 if (to_be_freed)
5875 exp_word = to_be_freed;
5876 if (exp_op == '?') {
5877 /* mimic bash message */
Denys Vlasenko39701202017-08-02 19:44:05 +02005878 msg_and_die_if_script("%s: %s",
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005879 var,
Denys Vlasenko645c6972017-07-25 15:18:57 +02005880 exp_word[0]
5881 ? exp_word
5882 : "parameter null or not set"
5883 /* ash has more specific messages, a-la: */
5884 /*: (exp_save == ':' ? "parameter null or not set" : "parameter not set")*/
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005885 );
5886//TODO: how interactive bash aborts expansion mid-command?
5887 } else {
5888 val = exp_word;
5889 }
5890
5891 if (exp_op == '=') {
5892 /* ${var=[word]} or ${var:=[word]} */
5893 if (isdigit(var[0]) || var[0] == '#') {
5894 /* mimic bash message */
Denys Vlasenko39701202017-08-02 19:44:05 +02005895 msg_and_die_if_script("$%s: cannot assign in this way", var);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005896 val = NULL;
5897 } else {
5898 char *new_var = xasprintf("%s=%s", var, val);
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02005899 set_local_var(new_var, /*flag:*/ 0);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005900 }
5901 }
5902 }
5903 } /* one of "-=+?" */
5904
5905 *exp_saveptr = exp_save;
5906 } /* if (exp_op) */
5907
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02005908 arg[0] = arg0;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005909
5910 *pp = p;
5911 *to_be_freed_pp = to_be_freed;
5912 return val;
5913}
5914
5915/* Expand all variable references in given string, adding words to list[]
5916 * at n, n+1,... positions. Return updated n (so that list[n] is next one
5917 * to be filled). This routine is extremely tricky: has to deal with
5918 * variables/parameters with whitespace, $* and $@, and constructs like
5919 * 'echo -$*-'. If you play here, you must run testsuite afterwards! */
Denys Vlasenko95d48f22010-09-08 13:58:55 +02005920static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005921{
Denys Vlasenko95d48f22010-09-08 13:58:55 +02005922 /* output->o_expflags & EXP_FLAG_SINGLEWORD (0x80) if we are in
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005923 * expansion of right-hand side of assignment == 1-element expand.
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005924 */
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02005925 char cant_be_null = 0; /* only bit 0x80 matters */
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005926 int ended_in_ifs = 0; /* did last unquoted expansion end with IFS chars? */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005927 char *p;
5928
Denys Vlasenko95d48f22010-09-08 13:58:55 +02005929 debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg,
5930 !!(output->o_expflags & EXP_FLAG_SINGLEWORD));
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005931 debug_print_list("expand_vars_to_list", output, n);
5932 n = o_save_ptr(output, n);
5933 debug_print_list("expand_vars_to_list[0]", output, n);
5934
5935 while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) {
5936 char first_ch;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005937 char *to_be_freed = NULL;
5938 const char *val = NULL;
5939#if ENABLE_HUSH_TICK
5940 o_string subst_result = NULL_O_STRING;
5941#endif
Denys Vlasenko0b883582016-12-23 16:49:07 +01005942#if ENABLE_FEATURE_SH_MATH
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005943 char arith_buf[sizeof(arith_t)*3 + 2];
5944#endif
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005945
5946 if (ended_in_ifs) {
5947 o_addchr(output, '\0');
5948 n = o_save_ptr(output, n);
5949 ended_in_ifs = 0;
5950 }
5951
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005952 o_addblock(output, arg, p - arg);
5953 debug_print_list("expand_vars_to_list[1]", output, n);
5954 arg = ++p;
5955 p = strchr(p, SPECIAL_VAR_SYMBOL);
5956
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02005957 /* Fetch special var name (if it is indeed one of them)
5958 * and quote bit, force the bit on if singleword expansion -
5959 * important for not getting v=$@ expand to many words. */
Denys Vlasenko95d48f22010-09-08 13:58:55 +02005960 first_ch = arg[0] | (output->o_expflags & EXP_FLAG_SINGLEWORD);
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02005961
5962 /* Is this variable quoted and thus expansion can't be null?
5963 * "$@" is special. Even if quoted, it can still
5964 * expand to nothing (not even an empty string),
5965 * thus it is excluded. */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005966 if ((first_ch & 0x7f) != '@')
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02005967 cant_be_null |= first_ch;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005968
5969 switch (first_ch & 0x7f) {
5970 /* Highest bit in first_ch indicates that var is double-quoted */
5971 case '*':
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02005972 case '@': {
5973 int i;
5974 if (!G.global_argv[1])
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005975 break;
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02005976 i = 1;
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02005977 cant_be_null |= first_ch; /* do it for "$@" _now_, when we know it's not empty */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005978 if (!(first_ch & 0x80)) { /* unquoted $* or $@ */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005979 while (G.global_argv[i]) {
Denys Vlasenko6e42b892011-08-01 18:16:43 +02005980 n = expand_on_ifs(NULL, output, n, G.global_argv[i]);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005981 debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1);
5982 if (G.global_argv[i++][0] && G.global_argv[i]) {
5983 /* this argv[] is not empty and not last:
5984 * put terminating NUL, start new word */
5985 o_addchr(output, '\0');
5986 debug_print_list("expand_vars_to_list[2]", output, n);
5987 n = o_save_ptr(output, n);
5988 debug_print_list("expand_vars_to_list[3]", output, n);
5989 }
5990 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005991 } else
Denys Vlasenko95d48f22010-09-08 13:58:55 +02005992 /* If EXP_FLAG_SINGLEWORD, we handle assignment 'a=....$@.....'
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005993 * and in this case should treat it like '$*' - see 'else...' below */
Denys Vlasenko95d48f22010-09-08 13:58:55 +02005994 if (first_ch == ('@'|0x80) /* quoted $@ */
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02005995 && !(output->o_expflags & EXP_FLAG_SINGLEWORD) /* not v="$@" case */
Denys Vlasenko95d48f22010-09-08 13:58:55 +02005996 ) {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02005997 while (1) {
5998 o_addQstr(output, G.global_argv[i]);
5999 if (++i >= G.global_argc)
6000 break;
6001 o_addchr(output, '\0');
6002 debug_print_list("expand_vars_to_list[4]", output, n);
6003 n = o_save_ptr(output, n);
6004 }
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006005 } else { /* quoted $* (or v="$@" case): add as one word */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006006 while (1) {
6007 o_addQstr(output, G.global_argv[i]);
6008 if (!G.global_argv[++i])
6009 break;
6010 if (G.ifs[0])
6011 o_addchr(output, G.ifs[0]);
6012 }
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02006013 output->has_quoted_part = 1;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006014 }
6015 break;
Denys Vlasenkoc49d2d92010-09-06 10:26:37 +02006016 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006017 case SPECIAL_VAR_SYMBOL: /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_SYMBOL> */
6018 /* "Empty variable", used to make "" etc to not disappear */
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02006019 output->has_quoted_part = 1;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006020 arg++;
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006021 cant_be_null = 0x80;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006022 break;
6023#if ENABLE_HUSH_TICK
6024 case '`': /* <SPECIAL_VAR_SYMBOL>`cmd<SPECIAL_VAR_SYMBOL> */
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006025 *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006026 arg++;
6027 /* Can't just stuff it into output o_string,
6028 * expanded result may need to be globbed
Denys Vlasenko10ad6222017-04-17 16:13:32 +02006029 * and $IFS-split */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006030 debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch);
6031 G.last_exitcode = process_command_subs(&subst_result, arg);
6032 debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data);
6033 val = subst_result.data;
6034 goto store_val;
6035#endif
Denys Vlasenko0b883582016-12-23 16:49:07 +01006036#if ENABLE_FEATURE_SH_MATH
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006037 case '+': { /* <SPECIAL_VAR_SYMBOL>+cmd<SPECIAL_VAR_SYMBOL> */
6038 arith_t res;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006039
6040 arg++; /* skip '+' */
6041 *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */
6042 debug_printf_subst("ARITH '%s' first_ch %x\n", arg, first_ch);
Denys Vlasenko063847d2010-09-15 13:33:02 +02006043 res = expand_and_evaluate_arith(arg, NULL);
Denys Vlasenkobed7c812010-09-16 11:50:46 +02006044 debug_printf_subst("ARITH RES '"ARITH_FMT"'\n", res);
6045 sprintf(arith_buf, ARITH_FMT, res);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006046 val = arith_buf;
6047 break;
6048 }
6049#endif
6050 default:
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006051 val = expand_one_var(&to_be_freed, arg, &p);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006052 IF_HUSH_TICK(store_val:)
6053 if (!(first_ch & 0x80)) { /* unquoted $VAR */
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02006054 debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val,
6055 !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006056 if (val && val[0]) {
Denys Vlasenko6e42b892011-08-01 18:16:43 +02006057 n = expand_on_ifs(&ended_in_ifs, output, n, val);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006058 val = NULL;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006059 }
6060 } else { /* quoted $VAR, val will be appended below */
Denys Vlasenko4fb53fb2011-08-01 14:06:20 +02006061 output->has_quoted_part = 1;
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02006062 debug_printf_expand("quoted '%s', output->o_escape:%d\n", val,
6063 !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006064 }
6065 break;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006066 } /* switch (char after <SPECIAL_VAR_SYMBOL>) */
6067
6068 if (val && val[0]) {
6069 o_addQstr(output, val);
6070 }
6071 free(to_be_freed);
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006072
6073 /* Restore NULL'ed SPECIAL_VAR_SYMBOL.
6074 * Do the check to avoid writing to a const string. */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006075 if (*p != SPECIAL_VAR_SYMBOL)
6076 *p = SPECIAL_VAR_SYMBOL;
6077
6078#if ENABLE_HUSH_TICK
6079 o_free(&subst_result);
6080#endif
6081 arg = ++p;
6082 } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */
6083
6084 if (arg[0]) {
Denys Vlasenko6e42b892011-08-01 18:16:43 +02006085 if (ended_in_ifs) {
6086 o_addchr(output, '\0');
6087 n = o_save_ptr(output, n);
6088 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006089 debug_print_list("expand_vars_to_list[a]", output, n);
6090 /* this part is literal, and it was already pre-quoted
6091 * if needed (much earlier), do not use o_addQstr here! */
6092 o_addstr_with_NUL(output, arg);
6093 debug_print_list("expand_vars_to_list[b]", output, n);
6094 } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */
Denys Vlasenkobfc02a72010-09-09 14:38:46 +02006095 && !(cant_be_null & 0x80) /* and all vars were not quoted. */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006096 ) {
6097 n--;
6098 /* allow to reuse list[n] later without re-growth */
6099 output->has_empty_slot = 1;
6100 } else {
6101 o_addchr(output, '\0');
6102 }
6103
6104 return n;
6105}
6106
Denys Vlasenko95d48f22010-09-08 13:58:55 +02006107static char **expand_variables(char **argv, unsigned expflags)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006108{
6109 int n;
6110 char **list;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006111 o_string output = NULL_O_STRING;
6112
Denys Vlasenko95d48f22010-09-08 13:58:55 +02006113 output.o_expflags = expflags;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006114
6115 n = 0;
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02006116 while (*argv) {
Denys Vlasenko95d48f22010-09-08 13:58:55 +02006117 n = expand_vars_to_list(&output, n, *argv);
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02006118 argv++;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006119 }
6120 debug_print_list("expand_variables", &output, n);
6121
6122 /* output.data (malloced in one block) gets returned in "list" */
6123 list = o_finalize_list(&output, n);
6124 debug_print_strings("expand_variables[1]", list);
6125 return list;
6126}
6127
6128static char **expand_strvec_to_strvec(char **argv)
6129{
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02006130 return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006131}
6132
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01006133#if BASH_TEST2
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006134static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
6135{
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02006136 return expand_variables(argv, EXP_FLAG_SINGLEWORD);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006137}
6138#endif
6139
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02006140/* Used for expansion of right hand of assignments,
6141 * $((...)), heredocs, variable espansion parts.
6142 *
6143 * NB: should NOT do globbing!
6144 * "export v=/bin/c*; env | grep ^v=" outputs "v=/bin/c*"
6145 */
Denys Vlasenkoebee4102010-09-10 10:17:53 +02006146static char *expand_string_to_string(const char *str, int do_unbackslash)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006147{
Denys Vlasenko637982f2017-07-06 01:52:23 +02006148#if !BASH_PATTERN_SUBST && !ENABLE_HUSH_CASE
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02006149 const int do_unbackslash = 1;
6150#endif
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006151 char *argv[2], **list;
6152
Denys Vlasenkoebee4102010-09-10 10:17:53 +02006153 debug_printf_expand("string_to_string<='%s'\n", str);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006154 /* This is generally an optimization, but it also
6155 * handles "", which otherwise trips over !list[0] check below.
6156 * (is this ever happens that we actually get str="" here?)
6157 */
6158 if (!strchr(str, SPECIAL_VAR_SYMBOL) && !strchr(str, '\\')) {
6159 //TODO: Can use on strings with \ too, just unbackslash() them?
Denys Vlasenkoebee4102010-09-10 10:17:53 +02006160 debug_printf_expand("string_to_string(fast)=>'%s'\n", str);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006161 return xstrdup(str);
6162 }
6163
6164 argv[0] = (char*)str;
6165 argv[1] = NULL;
Denys Vlasenkoebee4102010-09-10 10:17:53 +02006166 list = expand_variables(argv, do_unbackslash
6167 ? EXP_FLAG_ESC_GLOB_CHARS | EXP_FLAG_SINGLEWORD
6168 : EXP_FLAG_SINGLEWORD
6169 );
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006170 if (HUSH_DEBUG)
6171 if (!list[0] || list[1])
6172 bb_error_msg_and_die("BUG in varexp2");
6173 /* actually, just move string 2*sizeof(char*) bytes back */
6174 overlapping_strcpy((char*)list, list[0]);
Denys Vlasenkoebee4102010-09-10 10:17:53 +02006175 if (do_unbackslash)
6176 unbackslash((char*)list);
6177 debug_printf_expand("string_to_string=>'%s'\n", (char*)list);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006178 return (char*)list;
6179}
6180
Denys Vlasenkobd43c672017-07-05 23:12:15 +02006181/* Used for "eval" builtin and case string */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006182static char* expand_strvec_to_string(char **argv)
6183{
6184 char **list;
6185
Denys Vlasenko5b686cb2010-09-08 13:44:34 +02006186 list = expand_variables(argv, EXP_FLAG_SINGLEWORD);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006187 /* Convert all NULs to spaces */
6188 if (list[0]) {
6189 int n = 1;
6190 while (list[n]) {
6191 if (HUSH_DEBUG)
6192 if (list[n-1] + strlen(list[n-1]) + 1 != list[n])
6193 bb_error_msg_and_die("BUG in varexp3");
6194 /* bash uses ' ' regardless of $IFS contents */
6195 list[n][-1] = ' ';
6196 n++;
6197 }
6198 }
Denys Vlasenko78c9c732016-09-29 01:44:17 +02006199 overlapping_strcpy((char*)list, list[0] ? list[0] : "");
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006200 debug_printf_expand("strvec_to_string='%s'\n", (char*)list);
6201 return (char*)list;
6202}
6203
6204static char **expand_assignments(char **argv, int count)
6205{
6206 int i;
6207 char **p;
6208
6209 G.expanded_assignments = p = NULL;
6210 /* Expand assignments into one string each */
6211 for (i = 0; i < count; i++) {
Denys Vlasenkoebee4102010-09-10 10:17:53 +02006212 G.expanded_assignments = p = add_string_to_strings(p, expand_string_to_string(argv[i], /*unbackslash:*/ 1));
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006213 }
6214 G.expanded_assignments = NULL;
6215 return p;
6216}
6217
6218
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006219static void switch_off_special_sigs(unsigned mask)
6220{
6221 unsigned sig = 0;
6222 while ((mask >>= 1) != 0) {
6223 sig++;
6224 if (!(mask & 1))
6225 continue;
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006226#if ENABLE_HUSH_TRAP
6227 if (G_traps) {
6228 if (G_traps[sig] && !G_traps[sig][0])
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006229 /* trap is '', has to remain SIG_IGN */
6230 continue;
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006231 free(G_traps[sig]);
6232 G_traps[sig] = NULL;
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006233 }
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006234#endif
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006235 /* We are here only if no trap or trap was not '' */
Denys Vlasenko0806e402011-05-12 23:06:20 +02006236 install_sighandler(sig, SIG_DFL);
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006237 }
6238}
6239
Denys Vlasenkob347df92011-08-09 22:49:15 +02006240#if BB_MMU
6241/* never called */
6242void re_execute_shell(char ***to_free, const char *s,
6243 char *g_argv0, char **g_argv,
6244 char **builtin_argv) NORETURN;
6245
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006246static void reset_traps_to_defaults(void)
6247{
6248 /* This function is always called in a child shell
6249 * after fork (not vfork, NOMMU doesn't use this function).
6250 */
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006251 IF_HUSH_TRAP(unsigned sig;)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006252 unsigned mask;
6253
6254 /* Child shells are not interactive.
6255 * SIGTTIN/SIGTTOU/SIGTSTP should not have special handling.
6256 * Testcase: (while :; do :; done) + ^Z should background.
6257 * Same goes for SIGTERM, SIGHUP, SIGINT.
6258 */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006259 mask = (G.special_sig_mask & SPECIAL_INTERACTIVE_SIGS) | G_fatal_sig_mask;
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006260 if (!G_traps && !mask)
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006261 return; /* already no traps and no special sigs */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006262
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006263 /* Switch off special sigs */
6264 switch_off_special_sigs(mask);
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006265# if ENABLE_HUSH_JOB
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006266 G_fatal_sig_mask = 0;
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006267# endif
Denys Vlasenko10c01312011-05-11 11:49:21 +02006268 G.special_sig_mask &= ~SPECIAL_INTERACTIVE_SIGS;
Denys Vlasenkof58f7052011-05-12 02:10:33 +02006269 /* SIGQUIT,SIGCHLD and maybe SPECIAL_JOBSTOP_SIGS
6270 * remain set in G.special_sig_mask */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006271
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006272# if ENABLE_HUSH_TRAP
6273 if (!G_traps)
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006274 return;
6275
6276 /* Reset all sigs to default except ones with empty traps */
6277 for (sig = 0; sig < NSIG; sig++) {
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006278 if (!G_traps[sig])
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006279 continue; /* no trap: nothing to do */
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006280 if (!G_traps[sig][0])
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006281 continue; /* empty trap: has to remain SIG_IGN */
6282 /* sig has non-empty trap, reset it: */
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006283 free(G_traps[sig]);
6284 G_traps[sig] = NULL;
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02006285 /* There is no signal for trap 0 (EXIT) */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006286 if (sig == 0)
6287 continue;
Denys Vlasenko0806e402011-05-12 23:06:20 +02006288 install_sighandler(sig, pick_sighandler(sig));
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006289 }
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006290# endif
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006291}
6292
6293#else /* !BB_MMU */
6294
6295static void re_execute_shell(char ***to_free, const char *s,
6296 char *g_argv0, char **g_argv,
6297 char **builtin_argv) NORETURN;
6298static void re_execute_shell(char ***to_free, const char *s,
6299 char *g_argv0, char **g_argv,
6300 char **builtin_argv)
6301{
6302# define NOMMU_HACK_FMT ("-$%x:%x:%x:%x:%x:%llx" IF_HUSH_LOOPS(":%x"))
6303 /* delims + 2 * (number of bytes in printed hex numbers) */
6304 char param_buf[sizeof(NOMMU_HACK_FMT) + 2 * (sizeof(int)*6 + sizeof(long long)*1)];
6305 char *heredoc_argv[4];
6306 struct variable *cur;
6307# if ENABLE_HUSH_FUNCTIONS
6308 struct function *funcp;
6309# endif
6310 char **argv, **pp;
6311 unsigned cnt;
6312 unsigned long long empty_trap_mask;
6313
6314 if (!g_argv0) { /* heredoc */
6315 argv = heredoc_argv;
6316 argv[0] = (char *) G.argv0_for_re_execing;
6317 argv[1] = (char *) "-<";
6318 argv[2] = (char *) s;
6319 argv[3] = NULL;
6320 pp = &argv[3]; /* used as pointer to empty environment */
6321 goto do_exec;
6322 }
6323
6324 cnt = 0;
6325 pp = builtin_argv;
6326 if (pp) while (*pp++)
6327 cnt++;
6328
6329 empty_trap_mask = 0;
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006330 if (G_traps) {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006331 int sig;
6332 for (sig = 1; sig < NSIG; sig++) {
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006333 if (G_traps[sig] && !G_traps[sig][0])
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006334 empty_trap_mask |= 1LL << sig;
6335 }
6336 }
6337
6338 sprintf(param_buf, NOMMU_HACK_FMT
6339 , (unsigned) G.root_pid
6340 , (unsigned) G.root_ppid
6341 , (unsigned) G.last_bg_pid
6342 , (unsigned) G.last_exitcode
6343 , cnt
6344 , empty_trap_mask
6345 IF_HUSH_LOOPS(, G.depth_of_loop)
6346 );
6347# undef NOMMU_HACK_FMT
6348 /* 1:hush 2:-$<pid>:<pid>:<exitcode>:<etc...> <vars...> <funcs...>
6349 * 3:-c 4:<cmd> 5:<arg0> <argN...> 6:NULL
6350 */
6351 cnt += 6;
6352 for (cur = G.top_var; cur; cur = cur->next) {
6353 if (!cur->flg_export || cur->flg_read_only)
6354 cnt += 2;
6355 }
6356# if ENABLE_HUSH_FUNCTIONS
6357 for (funcp = G.top_func; funcp; funcp = funcp->next)
6358 cnt += 3;
6359# endif
6360 pp = g_argv;
6361 while (*pp++)
6362 cnt++;
6363 *to_free = argv = pp = xzalloc(sizeof(argv[0]) * cnt);
6364 *pp++ = (char *) G.argv0_for_re_execing;
6365 *pp++ = param_buf;
6366 for (cur = G.top_var; cur; cur = cur->next) {
6367 if (strcmp(cur->varstr, hush_version_str) == 0)
6368 continue;
6369 if (cur->flg_read_only) {
6370 *pp++ = (char *) "-R";
6371 *pp++ = cur->varstr;
6372 } else if (!cur->flg_export) {
6373 *pp++ = (char *) "-V";
6374 *pp++ = cur->varstr;
6375 }
6376 }
6377# if ENABLE_HUSH_FUNCTIONS
6378 for (funcp = G.top_func; funcp; funcp = funcp->next) {
6379 *pp++ = (char *) "-F";
6380 *pp++ = funcp->name;
6381 *pp++ = funcp->body_as_string;
6382 }
6383# endif
6384 /* We can pass activated traps here. Say, -Tnn:trap_string
6385 *
6386 * However, POSIX says that subshells reset signals with traps
6387 * to SIG_DFL.
6388 * I tested bash-3.2 and it not only does that with true subshells
6389 * of the form ( list ), but with any forked children shells.
6390 * I set trap "echo W" WINCH; and then tried:
6391 *
6392 * { echo 1; sleep 20; echo 2; } &
6393 * while true; do echo 1; sleep 20; echo 2; break; done &
6394 * true | { echo 1; sleep 20; echo 2; } | cat
6395 *
6396 * In all these cases sending SIGWINCH to the child shell
6397 * did not run the trap. If I add trap "echo V" WINCH;
6398 * _inside_ group (just before echo 1), it works.
6399 *
6400 * I conclude it means we don't need to pass active traps here.
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006401 */
6402 *pp++ = (char *) "-c";
6403 *pp++ = (char *) s;
6404 if (builtin_argv) {
6405 while (*++builtin_argv)
6406 *pp++ = *builtin_argv;
6407 *pp++ = (char *) "";
6408 }
6409 *pp++ = g_argv0;
6410 while (*g_argv)
6411 *pp++ = *g_argv++;
6412 /* *pp = NULL; - is already there */
6413 pp = environ;
6414
6415 do_exec:
6416 debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
Denys Vlasenko75e77de2011-05-12 13:12:47 +02006417 /* Don't propagate SIG_IGN to the child */
6418 if (SPECIAL_JOBSTOP_SIGS != 0)
6419 switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006420 execve(bb_busybox_exec_path, argv, pp);
6421 /* Fallback. Useful for init=/bin/hush usage etc */
6422 if (argv[0][0] == '/')
6423 execve(argv[0], argv, pp);
6424 xfunc_error_retval = 127;
6425 bb_error_msg_and_die("can't re-execute the shell");
6426}
6427#endif /* !BB_MMU */
6428
6429
6430static int run_and_free_list(struct pipe *pi);
6431
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00006432/* Executing from string: eval, sh -c '...'
Denis Vlasenkob6e65562009-04-03 16:49:04 +00006433 * or from file: /etc/profile, . file, sh <script>, sh (intereactive)
6434 * end_trigger controls how often we stop parsing
6435 * NUL: parse all, execute, return
6436 * ';': parse till ';' or newline, execute, repeat till EOF
6437 */
6438static void parse_and_run_stream(struct in_str *inp, int end_trigger)
Eric Andersen25f27032001-04-26 23:22:31 +00006439{
Denys Vlasenko00243b02009-11-16 02:00:03 +01006440 /* Why we need empty flag?
6441 * An obscure corner case "false; ``; echo $?":
6442 * empty command in `` should still set $? to 0.
6443 * But we can't just set $? to 0 at the start,
6444 * this breaks "false; echo `echo $?`" case.
6445 */
6446 bool empty = 1;
Denis Vlasenkob6e65562009-04-03 16:49:04 +00006447 while (1) {
6448 struct pipe *pipe_list;
Denis Vlasenkof8d01d32008-06-14 17:13:20 +00006449
Denys Vlasenkoa1463192011-01-18 17:55:04 +01006450#if ENABLE_HUSH_INTERACTIVE
6451 if (end_trigger == ';')
6452 inp->promptmode = 0; /* PS1 */
6453#endif
Denis Vlasenko9aa7d6f2009-04-04 22:47:50 +00006454 pipe_list = parse_stream(NULL, inp, end_trigger);
Denys Vlasenkocecbc982011-03-30 18:54:52 +02006455 if (!pipe_list || pipe_list == ERR_PTR) { /* EOF/error */
6456 /* If we are in "big" script
6457 * (not in `cmd` or something similar)...
6458 */
6459 if (pipe_list == ERR_PTR && end_trigger == ';') {
6460 /* Discard cached input (rest of line) */
6461 int ch = inp->last_char;
6462 while (ch != EOF && ch != '\n') {
6463 //bb_error_msg("Discarded:'%c'", ch);
6464 ch = i_getch(inp);
6465 }
6466 /* Force prompt */
6467 inp->p = NULL;
6468 /* This stream isn't empty */
6469 empty = 0;
6470 continue;
6471 }
6472 if (!pipe_list && empty)
Denys Vlasenko00243b02009-11-16 02:00:03 +01006473 G.last_exitcode = 0;
Denis Vlasenkob6e65562009-04-03 16:49:04 +00006474 break;
Denys Vlasenko00243b02009-11-16 02:00:03 +01006475 }
Denis Vlasenkob6e65562009-04-03 16:49:04 +00006476 debug_print_tree(pipe_list, 0);
6477 debug_printf_exec("parse_and_run_stream: run_and_free_list\n");
6478 run_and_free_list(pipe_list);
Denys Vlasenko00243b02009-11-16 02:00:03 +01006479 empty = 0;
Denys Vlasenko04b46bc2016-10-01 22:28:03 +02006480 if (G_flag_return_in_progress == 1)
Denys Vlasenko68d5cb52011-03-24 02:50:03 +01006481 break;
Denis Vlasenkob6e65562009-04-03 16:49:04 +00006482 }
Eric Andersen25f27032001-04-26 23:22:31 +00006483}
6484
Denis Vlasenkob6e65562009-04-03 16:49:04 +00006485static void parse_and_run_string(const char *s)
Eric Andersen25f27032001-04-26 23:22:31 +00006486{
6487 struct in_str input;
6488 setup_string_in_str(&input, s);
Denis Vlasenkob6e65562009-04-03 16:49:04 +00006489 parse_and_run_stream(&input, '\0');
Eric Andersen25f27032001-04-26 23:22:31 +00006490}
6491
Denis Vlasenkob6e65562009-04-03 16:49:04 +00006492static void parse_and_run_file(FILE *f)
Eric Andersen25f27032001-04-26 23:22:31 +00006493{
Eric Andersen25f27032001-04-26 23:22:31 +00006494 struct in_str input;
6495 setup_file_in_str(&input, f);
Denis Vlasenkob6e65562009-04-03 16:49:04 +00006496 parse_and_run_stream(&input, ';');
Eric Andersen25f27032001-04-26 23:22:31 +00006497}
6498
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006499#if ENABLE_HUSH_TICK
6500static FILE *generate_stream_from_string(const char *s, pid_t *pid_p)
6501{
6502 pid_t pid;
6503 int channel[2];
6504# if !BB_MMU
6505 char **to_free = NULL;
6506# endif
6507
6508 xpipe(channel);
6509 pid = BB_MMU ? xfork() : xvfork();
6510 if (pid == 0) { /* child */
6511 disable_restore_tty_pgrp_on_exit();
6512 /* Process substitution is not considered to be usual
6513 * 'command execution'.
6514 * SUSv3 says ctrl-Z should be ignored, ctrl-C should not.
6515 */
6516 bb_signals(0
6517 + (1 << SIGTSTP)
6518 + (1 << SIGTTIN)
6519 + (1 << SIGTTOU)
6520 , SIG_IGN);
6521 CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */
6522 close(channel[0]); /* NB: close _first_, then move fd! */
6523 xmove_fd(channel[1], 1);
6524 /* Prevent it from trying to handle ctrl-z etc */
6525 IF_HUSH_JOB(G.run_list_level = 1;)
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006526# if ENABLE_HUSH_TRAP
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006527 /* Awful hack for `trap` or $(trap).
6528 *
6529 * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
6530 * contains an example where "trap" is executed in a subshell:
6531 *
6532 * save_traps=$(trap)
6533 * ...
6534 * eval "$save_traps"
6535 *
6536 * Standard does not say that "trap" in subshell shall print
6537 * parent shell's traps. It only says that its output
6538 * must have suitable form, but then, in the above example
6539 * (which is not supposed to be normative), it implies that.
6540 *
6541 * bash (and probably other shell) does implement it
6542 * (traps are reset to defaults, but "trap" still shows them),
6543 * but as a result, "trap" logic is hopelessly messed up:
6544 *
6545 * # trap
6546 * trap -- 'echo Ho' SIGWINCH <--- we have a handler
6547 * # (trap) <--- trap is in subshell - no output (correct, traps are reset)
6548 * # true | trap <--- trap is in subshell - no output (ditto)
6549 * # echo `true | trap` <--- in subshell - output (but traps are reset!)
6550 * trap -- 'echo Ho' SIGWINCH
6551 * # echo `(trap)` <--- in subshell in subshell - output
6552 * trap -- 'echo Ho' SIGWINCH
6553 * # echo `true | (trap)` <--- in subshell in subshell in subshell - output!
6554 * trap -- 'echo Ho' SIGWINCH
6555 *
6556 * The rules when to forget and when to not forget traps
6557 * get really complex and nonsensical.
6558 *
6559 * Our solution: ONLY bare $(trap) or `trap` is special.
6560 */
6561 s = skip_whitespace(s);
Denys Vlasenko8dff01d2015-03-12 17:48:34 +01006562 if (is_prefixed_with(s, "trap")
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006563 && skip_whitespace(s + 4)[0] == '\0'
6564 ) {
6565 static const char *const argv[] = { NULL, NULL };
6566 builtin_trap((char**)argv);
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02006567 fflush_all(); /* important */
6568 _exit(0);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006569 }
Denys Vlasenko7a85c602017-01-08 17:40:18 +01006570# endif
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006571# if BB_MMU
6572 reset_traps_to_defaults();
6573 parse_and_run_string(s);
6574 _exit(G.last_exitcode);
6575# else
6576 /* We re-execute after vfork on NOMMU. This makes this script safe:
6577 * yes "0123456789012345678901234567890" | dd bs=32 count=64k >BIG
6578 * huge=`cat BIG` # was blocking here forever
6579 * echo OK
6580 */
6581 re_execute_shell(&to_free,
6582 s,
6583 G.global_argv[0],
6584 G.global_argv + 1,
6585 NULL);
6586# endif
6587 }
6588
6589 /* parent */
6590 *pid_p = pid;
6591# if ENABLE_HUSH_FAST
6592 G.count_SIGCHLD++;
6593//bb_error_msg("[%d] fork in generate_stream_from_string:"
6594// " G.count_SIGCHLD:%d G.handled_SIGCHLD:%d",
6595// getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
6596# endif
6597 enable_restore_tty_pgrp_on_exit();
6598# if !BB_MMU
6599 free(to_free);
6600# endif
6601 close(channel[1]);
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02006602 return remember_FILE(xfdopen_for_read(channel[0]));
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006603}
6604
6605/* Return code is exit status of the process that is run. */
6606static int process_command_subs(o_string *dest, const char *s)
6607{
6608 FILE *fp;
6609 struct in_str pipe_str;
6610 pid_t pid;
6611 int status, ch, eol_cnt;
6612
6613 fp = generate_stream_from_string(s, &pid);
6614
6615 /* Now send results of command back into original context */
6616 setup_file_in_str(&pipe_str, fp);
6617 eol_cnt = 0;
6618 while ((ch = i_getch(&pipe_str)) != EOF) {
6619 if (ch == '\n') {
6620 eol_cnt++;
6621 continue;
6622 }
6623 while (eol_cnt) {
6624 o_addchr(dest, '\n');
6625 eol_cnt--;
6626 }
6627 o_addQchr(dest, ch);
6628 }
6629
6630 debug_printf("done reading from `cmd` pipe, closing it\n");
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02006631 fclose_and_forget(fp);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006632 /* We need to extract exitcode. Test case
6633 * "true; echo `sleep 1; false` $?"
6634 * should print 1 */
6635 safe_waitpid(pid, &status, 0);
6636 debug_printf("child exited. returning its exitcode:%d\n", WEXITSTATUS(status));
6637 return WEXITSTATUS(status);
6638}
6639#endif /* ENABLE_HUSH_TICK */
6640
6641
6642static void setup_heredoc(struct redir_struct *redir)
6643{
6644 struct fd_pair pair;
6645 pid_t pid;
6646 int len, written;
6647 /* the _body_ of heredoc (misleading field name) */
6648 const char *heredoc = redir->rd_filename;
6649 char *expanded;
6650#if !BB_MMU
6651 char **to_free;
6652#endif
6653
6654 expanded = NULL;
6655 if (!(redir->rd_dup & HEREDOC_QUOTED)) {
Denys Vlasenkod98e5c62010-09-10 10:44:23 +02006656 expanded = encode_then_expand_string(heredoc, /*process_bkslash:*/ 1, /*unbackslash:*/ 1);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006657 if (expanded)
6658 heredoc = expanded;
6659 }
6660 len = strlen(heredoc);
6661
6662 close(redir->rd_fd); /* often saves dup2+close in xmove_fd */
6663 xpiped_pair(pair);
6664 xmove_fd(pair.rd, redir->rd_fd);
6665
6666 /* Try writing without forking. Newer kernels have
6667 * dynamically growing pipes. Must use non-blocking write! */
6668 ndelay_on(pair.wr);
6669 while (1) {
6670 written = write(pair.wr, heredoc, len);
6671 if (written <= 0)
6672 break;
6673 len -= written;
6674 if (len == 0) {
6675 close(pair.wr);
6676 free(expanded);
6677 return;
6678 }
6679 heredoc += written;
6680 }
6681 ndelay_off(pair.wr);
6682
6683 /* Okay, pipe buffer was not big enough */
6684 /* Note: we must not create a stray child (bastard? :)
6685 * for the unsuspecting parent process. Child creates a grandchild
6686 * and exits before parent execs the process which consumes heredoc
6687 * (that exec happens after we return from this function) */
6688#if !BB_MMU
6689 to_free = NULL;
6690#endif
6691 pid = xvfork();
6692 if (pid == 0) {
6693 /* child */
6694 disable_restore_tty_pgrp_on_exit();
6695 pid = BB_MMU ? xfork() : xvfork();
6696 if (pid != 0)
6697 _exit(0);
6698 /* grandchild */
6699 close(redir->rd_fd); /* read side of the pipe */
6700#if BB_MMU
6701 full_write(pair.wr, heredoc, len); /* may loop or block */
6702 _exit(0);
6703#else
6704 /* Delegate blocking writes to another process */
6705 xmove_fd(pair.wr, STDOUT_FILENO);
6706 re_execute_shell(&to_free, heredoc, NULL, NULL, NULL);
6707#endif
6708 }
6709 /* parent */
6710#if ENABLE_HUSH_FAST
6711 G.count_SIGCHLD++;
6712//bb_error_msg("[%d] fork in setup_heredoc: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
6713#endif
6714 enable_restore_tty_pgrp_on_exit();
6715#if !BB_MMU
6716 free(to_free);
6717#endif
6718 close(pair.wr);
6719 free(expanded);
6720 wait(NULL); /* wait till child has died */
6721}
6722
Denys Vlasenko2db74612017-07-07 22:07:28 +02006723struct squirrel {
6724 int orig_fd;
6725 int moved_to;
6726 /* moved_to = n: fd was moved to n; restore back to orig_fd after redir */
6727 /* moved_to = -1: fd was opened by redirect; close orig_fd after redir */
6728};
6729
Denys Vlasenko621fc502017-07-24 12:42:17 +02006730static struct squirrel *append_squirrel(struct squirrel *sq, int i, int orig, int moved)
6731{
6732 sq = xrealloc(sq, (i + 2) * sizeof(sq[0]));
6733 sq[i].orig_fd = orig;
6734 sq[i].moved_to = moved;
6735 sq[i+1].orig_fd = -1; /* end marker */
6736 return sq;
6737}
6738
Denys Vlasenko2db74612017-07-07 22:07:28 +02006739static struct squirrel *add_squirrel(struct squirrel *sq, int fd, int avoid_fd)
6740{
Denys Vlasenko621fc502017-07-24 12:42:17 +02006741 int moved_to;
Denys Vlasenko32fdf2f2017-07-31 04:32:06 +02006742 int i;
Denys Vlasenko2db74612017-07-07 22:07:28 +02006743
Denys Vlasenko32fdf2f2017-07-31 04:32:06 +02006744 if (sq) for (i = 0; sq[i].orig_fd >= 0; i++) {
Denys Vlasenko2db74612017-07-07 22:07:28 +02006745 /* If we collide with an already moved fd... */
6746 if (fd == sq[i].moved_to) {
6747 sq[i].moved_to = fcntl_F_DUPFD(sq[i].moved_to, avoid_fd);
6748 debug_printf_redir("redirect_fd %d: already busy, moving to %d\n", fd, sq[i].moved_to);
6749 if (sq[i].moved_to < 0) /* what? */
6750 xfunc_die();
6751 return sq;
6752 }
6753 if (fd == sq[i].orig_fd) {
6754 /* Example: echo Hello >/dev/null 1>&2 */
6755 debug_printf_redir("redirect_fd %d: already moved\n", fd);
6756 return sq;
6757 }
Denys Vlasenko2db74612017-07-07 22:07:28 +02006758 }
6759
Denys Vlasenko2db74612017-07-07 22:07:28 +02006760 /* If this fd is open, we move and remember it; if it's closed, moved_to = -1 */
Denys Vlasenko621fc502017-07-24 12:42:17 +02006761 moved_to = fcntl_F_DUPFD(fd, avoid_fd);
6762 debug_printf_redir("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, moved_to);
6763 if (moved_to < 0 && errno != EBADF)
Denys Vlasenko2db74612017-07-07 22:07:28 +02006764 xfunc_die();
Denys Vlasenko621fc502017-07-24 12:42:17 +02006765 return append_squirrel(sq, i, fd, moved_to);
Denys Vlasenko2db74612017-07-07 22:07:28 +02006766}
6767
Denys Vlasenko657e9002017-07-30 23:34:04 +02006768static struct squirrel *add_squirrel_closed(struct squirrel *sq, int fd)
6769{
6770 int i;
6771
Denys Vlasenko32fdf2f2017-07-31 04:32:06 +02006772 if (sq) for (i = 0; sq[i].orig_fd >= 0; i++) {
Denys Vlasenko657e9002017-07-30 23:34:04 +02006773 /* If we collide with an already moved fd... */
6774 if (fd == sq[i].orig_fd) {
6775 /* Examples:
6776 * "echo 3>FILE 3>&- 3>FILE"
6777 * "echo 3>&- 3>FILE"
6778 * No need for last redirect to insert
6779 * another "need to close 3" indicator.
6780 */
6781 debug_printf_redir("redirect_fd %d: already moved or closed\n", fd);
6782 return sq;
6783 }
Denys Vlasenko657e9002017-07-30 23:34:04 +02006784 }
6785
6786 debug_printf_redir("redirect_fd %d: previous fd was closed\n", fd);
6787 return append_squirrel(sq, i, fd, -1);
6788}
6789
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02006790/* fd: redirect wants this fd to be used (e.g. 3>file).
6791 * Move all conflicting internally used fds,
6792 * and remember them so that we can restore them later.
6793 */
Denys Vlasenko657e9002017-07-30 23:34:04 +02006794static int save_fd_on_redirect(int fd, int avoid_fd, struct squirrel **sqp)
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02006795{
Denys Vlasenko2db74612017-07-07 22:07:28 +02006796 if (avoid_fd < 9) /* the important case here is that it can be -1 */
6797 avoid_fd = 9;
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02006798
6799#if ENABLE_HUSH_INTERACTIVE
Denys Vlasenko32fdf2f2017-07-31 04:32:06 +02006800 if (fd == G.interactive_fd) {
6801 /* Testcase: "ls -l /proc/$$/fd 255>&-" should work */
Denys Vlasenko657e9002017-07-30 23:34:04 +02006802 G.interactive_fd = xdup_CLOEXEC_and_close(G.interactive_fd, avoid_fd);
Denys Vlasenko2db74612017-07-07 22:07:28 +02006803 debug_printf_redir("redirect_fd %d: matches interactive_fd, moving it to %d\n", fd, G.interactive_fd);
6804 return 1; /* "we closed fd" */
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02006805 }
6806#endif
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02006807 /* Are we called from setup_redirects(squirrel==NULL)? Two cases:
6808 * (1) Redirect in a forked child. No need to save FILEs' fds,
6809 * we aren't going to use them anymore, ok to trash.
Denys Vlasenko2db74612017-07-07 22:07:28 +02006810 * (2) "exec 3>FILE". Bummer. We can save script FILEs' fds,
6811 * but how are we doing to restore them?
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02006812 * "fileno(fd) = new_fd" can't be done.
6813 */
Denys Vlasenko2db74612017-07-07 22:07:28 +02006814 if (!sqp)
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02006815 return 0;
6816
Denys Vlasenko2db74612017-07-07 22:07:28 +02006817 /* If this one of script's fds? */
6818 if (save_FILEs_on_redirect(fd, avoid_fd))
6819 return 1; /* yes. "we closed fd" */
6820
6821 /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
6822 *sqp = add_squirrel(*sqp, fd, avoid_fd);
6823 return 0; /* "we did not close fd" */
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02006824}
6825
Denys Vlasenko2db74612017-07-07 22:07:28 +02006826static void restore_redirects(struct squirrel *sq)
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02006827{
Denys Vlasenko2db74612017-07-07 22:07:28 +02006828 if (sq) {
Denys Vlasenko32fdf2f2017-07-31 04:32:06 +02006829 int i;
6830 for (i = 0; sq[i].orig_fd >= 0; i++) {
Denys Vlasenko2db74612017-07-07 22:07:28 +02006831 if (sq[i].moved_to >= 0) {
6832 /* We simply die on error */
6833 debug_printf_redir("restoring redirected fd from %d to %d\n", sq[i].moved_to, sq[i].orig_fd);
6834 xmove_fd(sq[i].moved_to, sq[i].orig_fd);
6835 } else {
6836 /* cmd1 9>FILE; cmd2_should_see_fd9_closed */
6837 debug_printf_redir("restoring redirected fd %d: closing it\n", sq[i].orig_fd);
6838 close(sq[i].orig_fd);
6839 }
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02006840 }
Denys Vlasenko2db74612017-07-07 22:07:28 +02006841 free(sq);
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02006842 }
6843
Denys Vlasenko2db74612017-07-07 22:07:28 +02006844 /* If moved, G.interactive_fd stays on new fd, not restoring it */
Denys Vlasenkoaa3576a2016-08-22 19:54:12 +02006845
6846 restore_redirected_FILEs();
6847}
6848
Denys Vlasenkobf1c3442017-07-31 04:54:53 +02006849#if ENABLE_FEATURE_SH_STANDALONE && BB_MMU
Denys Vlasenko5b3d2eb2017-07-31 18:02:28 +02006850static void close_saved_fds_and_FILE_fds(void)
Denys Vlasenkobf1c3442017-07-31 04:54:53 +02006851{
6852 if (G_interactive_fd)
6853 close(G_interactive_fd);
6854 close_all_FILE_list();
6855}
6856#endif
6857
Denys Vlasenko32fdf2f2017-07-31 04:32:06 +02006858static int internally_opened_fd(int fd, struct squirrel *sq)
6859{
6860 int i;
6861
6862#if ENABLE_HUSH_INTERACTIVE
6863 if (fd == G.interactive_fd)
6864 return 1;
6865#endif
6866 /* If this one of script's fds? */
6867 if (fd_in_FILEs(fd))
6868 return 1;
6869
6870 if (sq) for (i = 0; sq[i].orig_fd >= 0; i++) {
6871 if (fd == sq[i].moved_to)
6872 return 1;
6873 }
6874 return 0;
6875}
6876
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006877/* squirrel != NULL means we squirrel away copies of stdin, stdout,
6878 * and stderr if they are redirected. */
Denys Vlasenko2db74612017-07-07 22:07:28 +02006879static int setup_redirects(struct command *prog, struct squirrel **sqp)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006880{
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006881 struct redir_struct *redir;
6882
6883 for (redir = prog->redirects; redir; redir = redir->next) {
Denys Vlasenko657e9002017-07-30 23:34:04 +02006884 int newfd;
6885 int closed;
6886
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006887 if (redir->rd_type == REDIRECT_HEREDOC2) {
Denys Vlasenko869994c2016-08-20 15:16:00 +02006888 /* "rd_fd<<HERE" case */
Denys Vlasenko657e9002017-07-30 23:34:04 +02006889 save_fd_on_redirect(redir->rd_fd, /*avoid:*/ 0, sqp);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006890 /* for REDIRECT_HEREDOC2, rd_filename holds _contents_
6891 * of the heredoc */
6892 debug_printf_parse("set heredoc '%s'\n",
6893 redir->rd_filename);
6894 setup_heredoc(redir);
6895 continue;
6896 }
6897
6898 if (redir->rd_dup == REDIRFD_TO_FILE) {
Denys Vlasenko869994c2016-08-20 15:16:00 +02006899 /* "rd_fd<*>file" case (<*> is <,>,>>,<>) */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006900 char *p;
Denys Vlasenko657e9002017-07-30 23:34:04 +02006901 int mode;
6902
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006903 if (redir->rd_filename == NULL) {
Denys Vlasenkod6a37d82016-09-20 16:22:24 +02006904 /*
6905 * Examples:
6906 * "cmd >" (no filename)
6907 * "cmd > <file" (2nd redirect starts too early)
6908 */
Denys Vlasenko39701202017-08-02 19:44:05 +02006909 syntax_error("invalid redirect");
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006910 continue;
6911 }
6912 mode = redir_table[redir->rd_type].mode;
Denys Vlasenkoebee4102010-09-10 10:17:53 +02006913 p = expand_string_to_string(redir->rd_filename, /*unbackslash:*/ 1);
Denys Vlasenko657e9002017-07-30 23:34:04 +02006914 newfd = open_or_warn(p, mode);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006915 free(p);
Denys Vlasenko657e9002017-07-30 23:34:04 +02006916 if (newfd < 0) {
Denys Vlasenko869994c2016-08-20 15:16:00 +02006917 /* Error message from open_or_warn can be lost
6918 * if stderr has been redirected, but bash
6919 * and ash both lose it as well
6920 * (though zsh doesn't!)
6921 */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006922 return 1;
6923 }
Denys Vlasenko657e9002017-07-30 23:34:04 +02006924 if (newfd == redir->rd_fd && sqp) {
Denys Vlasenko621fc502017-07-24 12:42:17 +02006925 /* open() gave us precisely the fd we wanted.
6926 * This means that this fd was not busy
6927 * (not opened to anywhere).
6928 * Remember to close it on restore:
6929 */
Denys Vlasenko657e9002017-07-30 23:34:04 +02006930 *sqp = add_squirrel_closed(*sqp, newfd);
6931 debug_printf_redir("redir to previously closed fd %d\n", newfd);
Denys Vlasenko621fc502017-07-24 12:42:17 +02006932 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006933 } else {
Denys Vlasenko657e9002017-07-30 23:34:04 +02006934 /* "rd_fd>&rd_dup" or "rd_fd>&-" case */
6935 newfd = redir->rd_dup;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006936 }
6937
Denys Vlasenko657e9002017-07-30 23:34:04 +02006938 if (newfd == redir->rd_fd)
6939 continue;
6940
6941 /* if "N>FILE": move newfd to redir->rd_fd */
6942 /* if "N>&M": dup newfd to redir->rd_fd */
6943 /* if "N>&-": close redir->rd_fd (newfd is REDIRFD_CLOSE) */
6944
6945 closed = save_fd_on_redirect(redir->rd_fd, /*avoid:*/ newfd, sqp);
6946 if (newfd == REDIRFD_CLOSE) {
6947 /* "N>&-" means "close me" */
6948 if (!closed) {
6949 /* ^^^ optimization: saving may already
6950 * have closed it. If not... */
6951 close(redir->rd_fd);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006952 }
Denys Vlasenko657e9002017-07-30 23:34:04 +02006953 /* Sometimes we do another close on restore, getting EBADF.
6954 * Consider "echo 3>FILE 3>&-"
6955 * first redirect remembers "need to close 3",
6956 * and second redirect closes 3! Restore code then closes 3 again.
6957 */
6958 } else {
Denys Vlasenko32fdf2f2017-07-31 04:32:06 +02006959 /* if newfd is a script fd or saved fd, simulate EBADF */
6960 if (internally_opened_fd(newfd, sqp ? *sqp : NULL)) {
6961 //errno = EBADF;
6962 //bb_perror_msg_and_die("can't duplicate file descriptor");
6963 newfd = -1; /* same effect as code above */
6964 }
Denys Vlasenko657e9002017-07-30 23:34:04 +02006965 xdup2(newfd, redir->rd_fd);
6966 if (redir->rd_dup == REDIRFD_TO_FILE)
6967 /* "rd_fd > FILE" */
6968 close(newfd);
6969 /* else: "rd_fd > rd_dup" */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006970 }
6971 }
6972 return 0;
6973}
6974
Denys Vlasenkob36abf22010-09-05 14:50:59 +02006975static char *find_in_path(const char *arg)
6976{
6977 char *ret = NULL;
6978 const char *PATH = get_local_var_value("PATH");
6979
6980 if (!PATH)
6981 return NULL;
6982
6983 while (1) {
6984 const char *end = strchrnul(PATH, ':');
6985 int sz = end - PATH; /* must be int! */
6986
6987 free(ret);
6988 if (sz != 0) {
6989 ret = xasprintf("%.*s/%s", sz, PATH, arg);
6990 } else {
6991 /* We have xxx::yyyy in $PATH,
6992 * it means "use current dir" */
6993 ret = xstrdup(arg);
6994 }
6995 if (access(ret, F_OK) == 0)
6996 break;
6997
6998 if (*end == '\0') {
6999 free(ret);
7000 return NULL;
7001 }
7002 PATH = end + 1;
7003 }
7004
7005 return ret;
7006}
7007
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02007008static const struct built_in_command *find_builtin_helper(const char *name,
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007009 const struct built_in_command *x,
7010 const struct built_in_command *end)
7011{
7012 while (x != end) {
7013 if (strcmp(name, x->b_cmd) != 0) {
7014 x++;
7015 continue;
7016 }
7017 debug_printf_exec("found builtin '%s'\n", name);
7018 return x;
7019 }
7020 return NULL;
7021}
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02007022static const struct built_in_command *find_builtin1(const char *name)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007023{
7024 return find_builtin_helper(name, bltins1, &bltins1[ARRAY_SIZE(bltins1)]);
7025}
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02007026static const struct built_in_command *find_builtin(const char *name)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007027{
7028 const struct built_in_command *x = find_builtin1(name);
7029 if (x)
7030 return x;
7031 return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]);
7032}
7033
7034#if ENABLE_HUSH_FUNCTIONS
7035static struct function **find_function_slot(const char *name)
7036{
7037 struct function **funcpp = &G.top_func;
7038 while (*funcpp) {
7039 if (strcmp(name, (*funcpp)->name) == 0) {
7040 break;
7041 }
7042 funcpp = &(*funcpp)->next;
7043 }
7044 return funcpp;
7045}
7046
7047static const struct function *find_function(const char *name)
7048{
7049 const struct function *funcp = *find_function_slot(name);
7050 if (funcp)
7051 debug_printf_exec("found function '%s'\n", name);
7052 return funcp;
7053}
7054
7055/* Note: takes ownership on name ptr */
7056static struct function *new_function(char *name)
7057{
7058 struct function **funcpp = find_function_slot(name);
7059 struct function *funcp = *funcpp;
7060
7061 if (funcp != NULL) {
7062 struct command *cmd = funcp->parent_cmd;
7063 debug_printf_exec("func %p parent_cmd %p\n", funcp, cmd);
7064 if (!cmd) {
7065 debug_printf_exec("freeing & replacing function '%s'\n", funcp->name);
7066 free(funcp->name);
7067 /* Note: if !funcp->body, do not free body_as_string!
7068 * This is a special case of "-F name body" function:
7069 * body_as_string was not malloced! */
7070 if (funcp->body) {
7071 free_pipe_list(funcp->body);
7072# if !BB_MMU
7073 free(funcp->body_as_string);
7074# endif
7075 }
7076 } else {
7077 debug_printf_exec("reinserting in tree & replacing function '%s'\n", funcp->name);
7078 cmd->argv[0] = funcp->name;
7079 cmd->group = funcp->body;
7080# if !BB_MMU
7081 cmd->group_as_string = funcp->body_as_string;
7082# endif
7083 }
7084 } else {
7085 debug_printf_exec("remembering new function '%s'\n", name);
7086 funcp = *funcpp = xzalloc(sizeof(*funcp));
7087 /*funcp->next = NULL;*/
7088 }
7089
7090 funcp->name = name;
7091 return funcp;
7092}
7093
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01007094# if ENABLE_HUSH_UNSET
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007095static void unset_func(const char *name)
7096{
7097 struct function **funcpp = find_function_slot(name);
7098 struct function *funcp = *funcpp;
7099
7100 if (funcp != NULL) {
7101 debug_printf_exec("freeing function '%s'\n", funcp->name);
7102 *funcpp = funcp->next;
7103 /* funcp is unlinked now, deleting it.
7104 * Note: if !funcp->body, the function was created by
7105 * "-F name body", do not free ->body_as_string
7106 * and ->name as they were not malloced. */
7107 if (funcp->body) {
7108 free_pipe_list(funcp->body);
7109 free(funcp->name);
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01007110# if !BB_MMU
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007111 free(funcp->body_as_string);
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01007112# endif
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007113 }
7114 free(funcp);
7115 }
7116}
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01007117# endif
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007118
7119# if BB_MMU
7120#define exec_function(to_free, funcp, argv) \
7121 exec_function(funcp, argv)
7122# endif
7123static void exec_function(char ***to_free,
7124 const struct function *funcp,
7125 char **argv) NORETURN;
7126static void exec_function(char ***to_free,
7127 const struct function *funcp,
7128 char **argv)
7129{
7130# if BB_MMU
Denys Vlasenkod4e4fdb2017-07-03 21:31:16 +02007131 int n;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007132
7133 argv[0] = G.global_argv[0];
7134 G.global_argv = argv;
Denys Vlasenkod4e4fdb2017-07-03 21:31:16 +02007135 G.global_argc = n = 1 + string_array_len(argv + 1);
Denys Vlasenko5b3d2eb2017-07-31 18:02:28 +02007136
7137// Example when we are here: "cmd | func"
7138// func will run with saved-redirect fds open.
7139// $ f() { echo /proc/self/fd/*; }
7140// $ true | f
7141// /proc/self/fd/0 /proc/self/fd/1 /proc/self/fd/2 /proc/self/fd/255 /proc/self/fd/3
7142// stdio^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ G_interactive_fd^ DIR fd for glob
7143// Same in script:
7144// $ . ./SCRIPT
7145// /proc/self/fd/0 /proc/self/fd/1 /proc/self/fd/2 /proc/self/fd/255 /proc/self/fd/3 /proc/self/fd/4
7146// stdio^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ G_interactive_fd^ opened ./SCRIPT DIR fd for glob
7147// They are CLOEXEC so external programs won't see them, but
7148// for "more correctness" we might want to close those extra fds here:
7149//? close_saved_fds_and_FILE_fds();
7150
7151 /* "we are in function, ok to use return" */
7152 G_flag_return_in_progress = -1;
7153 IF_HUSH_LOCAL(G.func_nest_level++;)
7154
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007155 /* On MMU, funcp->body is always non-NULL */
7156 n = run_list(funcp->body);
7157 fflush_all();
7158 _exit(n);
7159# else
Denys Vlasenko5b3d2eb2017-07-31 18:02:28 +02007160//? close_saved_fds_and_FILE_fds();
7161
7162//TODO: check whether "true | func_with_return" works
7163
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007164 re_execute_shell(to_free,
7165 funcp->body_as_string,
7166 G.global_argv[0],
7167 argv + 1,
7168 NULL);
7169# endif
7170}
7171
7172static int run_function(const struct function *funcp, char **argv)
7173{
7174 int rc;
7175 save_arg_t sv;
7176 smallint sv_flg;
7177
7178 save_and_replace_G_args(&sv, argv);
7179
7180 /* "we are in function, ok to use return" */
Denys Vlasenko04b46bc2016-10-01 22:28:03 +02007181 sv_flg = G_flag_return_in_progress;
7182 G_flag_return_in_progress = -1;
Denys Vlasenko5b3d2eb2017-07-31 18:02:28 +02007183 IF_HUSH_LOCAL(G.func_nest_level++;)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007184
7185 /* On MMU, funcp->body is always non-NULL */
7186# if !BB_MMU
7187 if (!funcp->body) {
7188 /* Function defined by -F */
7189 parse_and_run_string(funcp->body_as_string);
7190 rc = G.last_exitcode;
7191 } else
7192# endif
7193 {
7194 rc = run_list(funcp->body);
7195 }
7196
7197# if ENABLE_HUSH_LOCAL
7198 {
7199 struct variable *var;
7200 struct variable **var_pp;
7201
7202 var_pp = &G.top_var;
7203 while ((var = *var_pp) != NULL) {
7204 if (var->func_nest_level < G.func_nest_level) {
7205 var_pp = &var->next;
7206 continue;
7207 }
7208 /* Unexport */
7209 if (var->flg_export)
7210 bb_unsetenv(var->varstr);
7211 /* Remove from global list */
7212 *var_pp = var->next;
7213 /* Free */
7214 if (!var->max_len)
7215 free(var->varstr);
7216 free(var);
7217 }
7218 G.func_nest_level--;
7219 }
7220# endif
Denys Vlasenko04b46bc2016-10-01 22:28:03 +02007221 G_flag_return_in_progress = sv_flg;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007222
7223 restore_G_args(&sv, argv);
7224
7225 return rc;
7226}
7227#endif /* ENABLE_HUSH_FUNCTIONS */
7228
7229
7230#if BB_MMU
7231#define exec_builtin(to_free, x, argv) \
7232 exec_builtin(x, argv)
7233#else
7234#define exec_builtin(to_free, x, argv) \
7235 exec_builtin(to_free, argv)
7236#endif
7237static void exec_builtin(char ***to_free,
7238 const struct built_in_command *x,
7239 char **argv) NORETURN;
7240static void exec_builtin(char ***to_free,
7241 const struct built_in_command *x,
7242 char **argv)
7243{
7244#if BB_MMU
Denys Vlasenko8ee2ada2011-02-07 02:03:51 +01007245 int rcode;
7246 fflush_all();
Denys Vlasenko5b3d2eb2017-07-31 18:02:28 +02007247//? close_saved_fds_and_FILE_fds();
Denys Vlasenko8ee2ada2011-02-07 02:03:51 +01007248 rcode = x->b_function(argv);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007249 fflush_all();
7250 _exit(rcode);
7251#else
Denys Vlasenko8ee2ada2011-02-07 02:03:51 +01007252 fflush_all();
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007253 /* On NOMMU, we must never block!
7254 * Example: { sleep 99 | read line; } & echo Ok
7255 */
7256 re_execute_shell(to_free,
7257 argv[0],
7258 G.global_argv[0],
7259 G.global_argv + 1,
7260 argv);
7261#endif
7262}
7263
7264
7265static void execvp_or_die(char **argv) NORETURN;
7266static void execvp_or_die(char **argv)
7267{
Denys Vlasenko04465da2016-10-03 01:01:15 +02007268 int e;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007269 debug_printf_exec("execing '%s'\n", argv[0]);
Denys Vlasenko75e77de2011-05-12 13:12:47 +02007270 /* Don't propagate SIG_IGN to the child */
7271 if (SPECIAL_JOBSTOP_SIGS != 0)
7272 switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007273 execvp(argv[0], argv);
Denys Vlasenko04465da2016-10-03 01:01:15 +02007274 e = 2;
7275 if (errno == EACCES) e = 126;
7276 if (errno == ENOENT) e = 127;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007277 bb_perror_msg("can't execute '%s'", argv[0]);
Denys Vlasenko04465da2016-10-03 01:01:15 +02007278 _exit(e);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007279}
7280
7281#if ENABLE_HUSH_MODE_X
7282static void dump_cmd_in_x_mode(char **argv)
7283{
7284 if (G_x_mode && argv) {
7285 /* We want to output the line in one write op */
7286 char *buf, *p;
7287 int len;
7288 int n;
7289
7290 len = 3;
7291 n = 0;
7292 while (argv[n])
7293 len += strlen(argv[n++]) + 1;
7294 buf = xmalloc(len);
7295 buf[0] = '+';
7296 p = buf + 1;
7297 n = 0;
7298 while (argv[n])
7299 p += sprintf(p, " %s", argv[n++]);
7300 *p++ = '\n';
7301 *p = '\0';
7302 fputs(buf, stderr);
7303 free(buf);
7304 }
7305}
7306#else
7307# define dump_cmd_in_x_mode(argv) ((void)0)
7308#endif
7309
7310#if BB_MMU
7311#define pseudo_exec_argv(nommu_save, argv, assignment_cnt, argv_expanded) \
7312 pseudo_exec_argv(argv, assignment_cnt, argv_expanded)
7313#define pseudo_exec(nommu_save, command, argv_expanded) \
7314 pseudo_exec(command, argv_expanded)
7315#endif
7316
7317/* Called after [v]fork() in run_pipe, or from builtin_exec.
7318 * Never returns.
7319 * Don't exit() here. If you don't exec, use _exit instead.
7320 * The at_exit handlers apparently confuse the calling process,
Denys Vlasenko215b0ca2016-08-19 18:23:56 +02007321 * in particular stdin handling. Not sure why? -- because of vfork! (vda)
Denys Vlasenko215b0ca2016-08-19 18:23:56 +02007322 */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007323static void pseudo_exec_argv(nommu_save_t *nommu_save,
7324 char **argv, int assignment_cnt,
7325 char **argv_expanded) NORETURN;
7326static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save,
7327 char **argv, int assignment_cnt,
7328 char **argv_expanded)
7329{
7330 char **new_env;
7331
7332 new_env = expand_assignments(argv, assignment_cnt);
7333 dump_cmd_in_x_mode(new_env);
7334
7335 if (!argv[assignment_cnt]) {
7336 /* Case when we are here: ... | var=val | ...
7337 * (note that we do not exit early, i.e., do not optimize out
7338 * expand_assignments(): think about ... | var=`sleep 1` | ...
7339 */
7340 free_strings(new_env);
7341 _exit(EXIT_SUCCESS);
7342 }
7343
7344#if BB_MMU
7345 set_vars_and_save_old(new_env);
7346 free(new_env); /* optional */
7347 /* we can also destroy set_vars_and_save_old's return value,
7348 * to save memory */
7349#else
7350 nommu_save->new_env = new_env;
7351 nommu_save->old_vars = set_vars_and_save_old(new_env);
7352#endif
7353
7354 if (argv_expanded) {
7355 argv = argv_expanded;
7356 } else {
7357 argv = expand_strvec_to_strvec(argv + assignment_cnt);
7358#if !BB_MMU
7359 nommu_save->argv = argv;
7360#endif
7361 }
7362 dump_cmd_in_x_mode(argv);
7363
7364#if ENABLE_FEATURE_SH_STANDALONE || BB_MMU
7365 if (strchr(argv[0], '/') != NULL)
7366 goto skip;
7367#endif
7368
Denys Vlasenko75481d32017-07-31 05:27:09 +02007369#if ENABLE_HUSH_FUNCTIONS
7370 /* Check if the command matches any functions (this goes before bltins) */
7371 {
7372 const struct function *funcp = find_function(argv[0]);
7373 if (funcp) {
7374 exec_function(&nommu_save->argv_from_re_execing, funcp, argv);
7375 }
7376 }
7377#endif
7378
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007379 /* Check if the command matches any of the builtins.
7380 * Depending on context, this might be redundant. But it's
7381 * easier to waste a few CPU cycles than it is to figure out
7382 * if this is one of those cases.
7383 */
7384 {
7385 /* On NOMMU, it is more expensive to re-execute shell
7386 * just in order to run echo or test builtin.
7387 * It's better to skip it here and run corresponding
7388 * non-builtin later. */
7389 const struct built_in_command *x;
7390 x = BB_MMU ? find_builtin(argv[0]) : find_builtin1(argv[0]);
7391 if (x) {
7392 exec_builtin(&nommu_save->argv_from_re_execing, x, argv);
7393 }
7394 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007395
7396#if ENABLE_FEATURE_SH_STANDALONE
7397 /* Check if the command matches any busybox applets */
7398 {
7399 int a = find_applet_by_name(argv[0]);
7400 if (a >= 0) {
7401# if BB_MMU /* see above why on NOMMU it is not allowed */
7402 if (APPLET_IS_NOEXEC(a)) {
Denys Vlasenkobf1c3442017-07-31 04:54:53 +02007403 /* Do not leak open fds from opened script files etc.
7404 * Testcase: interactive "ls -l /proc/self/fd"
7405 * should not show tty fd open.
7406 */
Denys Vlasenko5b3d2eb2017-07-31 18:02:28 +02007407 close_saved_fds_and_FILE_fds();
Denys Vlasenko75481d32017-07-31 05:27:09 +02007408//FIXME: should also close saved redir fds
Denys Vlasenko7c40ddd2017-08-02 16:37:39 +02007409 /* Without this, "rm -i FILE" can't be ^C'ed: */
7410 switch_off_special_sigs(G.special_sig_mask);
Denys Vlasenkoc9c1ccc2017-08-07 18:59:35 +02007411 debug_printf_exec("running applet '%s'\n", argv[0]);
Denys Vlasenko80e8e3c2017-08-07 19:24:57 +02007412 run_noexec_applet_and_exit(a, argv[0], argv);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007413 }
7414# endif
7415 /* Re-exec ourselves */
7416 debug_printf_exec("re-execing applet '%s'\n", argv[0]);
Denys Vlasenko75e77de2011-05-12 13:12:47 +02007417 /* Don't propagate SIG_IGN to the child */
7418 if (SPECIAL_JOBSTOP_SIGS != 0)
7419 switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007420 execv(bb_busybox_exec_path, argv);
7421 /* If they called chroot or otherwise made the binary no longer
7422 * executable, fall through */
7423 }
7424 }
7425#endif
7426
7427#if ENABLE_FEATURE_SH_STANDALONE || BB_MMU
7428 skip:
7429#endif
7430 execvp_or_die(argv);
7431}
7432
7433/* Called after [v]fork() in run_pipe
7434 */
7435static void pseudo_exec(nommu_save_t *nommu_save,
7436 struct command *command,
7437 char **argv_expanded) NORETURN;
7438static void pseudo_exec(nommu_save_t *nommu_save,
7439 struct command *command,
7440 char **argv_expanded)
7441{
7442 if (command->argv) {
7443 pseudo_exec_argv(nommu_save, command->argv,
7444 command->assignment_cnt, argv_expanded);
7445 }
7446
7447 if (command->group) {
7448 /* Cases when we are here:
7449 * ( list )
7450 * { list } &
7451 * ... | ( list ) | ...
7452 * ... | { list } | ...
7453 */
7454#if BB_MMU
7455 int rcode;
7456 debug_printf_exec("pseudo_exec: run_list\n");
7457 reset_traps_to_defaults();
7458 rcode = run_list(command->group);
7459 /* OK to leak memory by not calling free_pipe_list,
7460 * since this process is about to exit */
7461 _exit(rcode);
7462#else
7463 re_execute_shell(&nommu_save->argv_from_re_execing,
7464 command->group_as_string,
7465 G.global_argv[0],
7466 G.global_argv + 1,
7467 NULL);
7468#endif
7469 }
7470
7471 /* Case when we are here: ... | >file */
7472 debug_printf_exec("pseudo_exec'ed null command\n");
7473 _exit(EXIT_SUCCESS);
7474}
7475
7476#if ENABLE_HUSH_JOB
7477static const char *get_cmdtext(struct pipe *pi)
7478{
7479 char **argv;
7480 char *p;
7481 int len;
7482
7483 /* This is subtle. ->cmdtext is created only on first backgrounding.
7484 * (Think "cat, <ctrl-z>, fg, <ctrl-z>, fg, <ctrl-z>...." here...)
7485 * On subsequent bg argv is trashed, but we won't use it */
7486 if (pi->cmdtext)
7487 return pi->cmdtext;
Denys Vlasenko1eada9a2016-11-08 17:28:45 +01007488
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007489 argv = pi->cmds[0].argv;
Denys Vlasenko1eada9a2016-11-08 17:28:45 +01007490 if (!argv) {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007491 pi->cmdtext = xzalloc(1);
7492 return pi->cmdtext;
7493 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007494 len = 0;
7495 do {
7496 len += strlen(*argv) + 1;
7497 } while (*++argv);
7498 p = xmalloc(len);
7499 pi->cmdtext = p;
7500 argv = pi->cmds[0].argv;
7501 do {
Denys Vlasenko1eada9a2016-11-08 17:28:45 +01007502 p = stpcpy(p, *argv);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007503 *p++ = ' ';
7504 } while (*++argv);
7505 p[-1] = '\0';
7506 return pi->cmdtext;
7507}
7508
Denys Vlasenko2ed74e22017-07-14 19:58:46 +02007509static void remove_job_from_table(struct pipe *pi)
7510{
7511 struct pipe *prev_pipe;
7512
7513 if (pi == G.job_list) {
7514 G.job_list = pi->next;
7515 } else {
7516 prev_pipe = G.job_list;
7517 while (prev_pipe->next != pi)
7518 prev_pipe = prev_pipe->next;
7519 prev_pipe->next = pi->next;
7520 }
7521 G.last_jobid = 0;
7522 if (G.job_list)
7523 G.last_jobid = G.job_list->jobid;
7524}
7525
7526static void delete_finished_job(struct pipe *pi)
7527{
7528 remove_job_from_table(pi);
7529 free_pipe(pi);
7530}
7531
7532static void clean_up_last_dead_job(void)
7533{
7534 if (G.job_list && !G.job_list->alive_cmds)
7535 delete_finished_job(G.job_list);
7536}
7537
Denys Vlasenko16096292017-07-10 10:00:28 +02007538static void insert_job_into_table(struct pipe *pi)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007539{
7540 struct pipe *job, **jobp;
7541 int i;
7542
Denys Vlasenko2ed74e22017-07-14 19:58:46 +02007543 clean_up_last_dead_job();
7544
Denys Vlasenko9e55a152017-07-10 10:01:12 +02007545 /* Find the end of the list, and find next job ID to use */
7546 i = 0;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007547 jobp = &G.job_list;
Denys Vlasenko9e55a152017-07-10 10:01:12 +02007548 while ((job = *jobp) != NULL) {
7549 if (job->jobid > i)
7550 i = job->jobid;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007551 jobp = &job->next;
Denys Vlasenko9e55a152017-07-10 10:01:12 +02007552 }
7553 pi->jobid = i + 1;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007554
Denys Vlasenko9e55a152017-07-10 10:01:12 +02007555 /* Create a new job struct at the end */
7556 job = *jobp = xmemdup(pi, sizeof(*pi));
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007557 job->next = NULL;
7558 job->cmds = xzalloc(sizeof(pi->cmds[0]) * pi->num_cmds);
7559 /* Cannot copy entire pi->cmds[] vector! This causes double frees */
7560 for (i = 0; i < pi->num_cmds; i++) {
7561 job->cmds[i].pid = pi->cmds[i].pid;
7562 /* all other fields are not used and stay zero */
7563 }
7564 job->cmdtext = xstrdup(get_cmdtext(pi));
7565
7566 if (G_interactive_fd)
Denys Vlasenkod5b5c2f2017-01-08 15:46:04 +01007567 printf("[%u] %u %s\n", job->jobid, (unsigned)job->cmds[0].pid, job->cmdtext);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007568 G.last_jobid = job->jobid;
7569}
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007570#endif /* JOB */
7571
Denys Vlasenko62b717b2016-11-07 22:12:18 +01007572static int job_exited_or_stopped(struct pipe *pi)
7573{
7574 int rcode, i;
7575
7576 if (pi->alive_cmds != pi->stopped_cmds)
7577 return -1;
7578
7579 /* All processes in fg pipe have exited or stopped */
7580 rcode = 0;
7581 i = pi->num_cmds;
7582 while (--i >= 0) {
7583 rcode = pi->cmds[i].cmd_exitcode;
7584 /* usually last process gives overall exitstatus,
7585 * but with "set -o pipefail", last *failed* process does */
7586 if (G.o_opt[OPT_O_PIPEFAIL] == 0 || rcode != 0)
7587 break;
7588 }
7589 IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
7590 return rcode;
7591}
7592
Denys Vlasenko7e675362016-10-28 21:57:31 +02007593static int process_wait_result(struct pipe *fg_pipe, pid_t childpid, int status)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007594{
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007595#if ENABLE_HUSH_JOB
7596 struct pipe *pi;
7597#endif
Denys Vlasenko7e675362016-10-28 21:57:31 +02007598 int i, dead;
7599
7600 dead = WIFEXITED(status) || WIFSIGNALED(status);
7601
7602#if DEBUG_JOBS
7603 if (WIFSTOPPED(status))
7604 debug_printf_jobs("pid %d stopped by sig %d (exitcode %d)\n",
7605 childpid, WSTOPSIG(status), WEXITSTATUS(status));
7606 if (WIFSIGNALED(status))
7607 debug_printf_jobs("pid %d killed by sig %d (exitcode %d)\n",
7608 childpid, WTERMSIG(status), WEXITSTATUS(status));
7609 if (WIFEXITED(status))
7610 debug_printf_jobs("pid %d exited, exitcode %d\n",
7611 childpid, WEXITSTATUS(status));
7612#endif
7613 /* Were we asked to wait for a fg pipe? */
7614 if (fg_pipe) {
7615 i = fg_pipe->num_cmds;
Denys Vlasenko62b717b2016-11-07 22:12:18 +01007616
Denys Vlasenko7e675362016-10-28 21:57:31 +02007617 while (--i >= 0) {
Denys Vlasenko62b717b2016-11-07 22:12:18 +01007618 int rcode;
7619
Denys Vlasenko7e675362016-10-28 21:57:31 +02007620 debug_printf_jobs("check pid %d\n", fg_pipe->cmds[i].pid);
7621 if (fg_pipe->cmds[i].pid != childpid)
7622 continue;
7623 if (dead) {
7624 int ex;
7625 fg_pipe->cmds[i].pid = 0;
7626 fg_pipe->alive_cmds--;
7627 ex = WEXITSTATUS(status);
7628 /* bash prints killer signal's name for *last*
7629 * process in pipe (prints just newline for SIGINT/SIGPIPE).
7630 * Mimic this. Example: "sleep 5" + (^\ or kill -QUIT)
7631 */
7632 if (WIFSIGNALED(status)) {
7633 int sig = WTERMSIG(status);
7634 if (i == fg_pipe->num_cmds-1)
7635 /* TODO: use strsignal() instead for bash compat? but that's bloat... */
7636 puts(sig == SIGINT || sig == SIGPIPE ? "" : get_signame(sig));
7637 /* TODO: if (WCOREDUMP(status)) + " (core dumped)"; */
7638 /* TODO: MIPS has 128 sigs (1..128), what if sig==128 here?
7639 * Maybe we need to use sig | 128? */
7640 ex = sig + 128;
7641 }
7642 fg_pipe->cmds[i].cmd_exitcode = ex;
7643 } else {
7644 fg_pipe->stopped_cmds++;
7645 }
7646 debug_printf_jobs("fg_pipe: alive_cmds %d stopped_cmds %d\n",
7647 fg_pipe->alive_cmds, fg_pipe->stopped_cmds);
Denys Vlasenko62b717b2016-11-07 22:12:18 +01007648 rcode = job_exited_or_stopped(fg_pipe);
7649 if (rcode >= 0) {
Denys Vlasenko7e675362016-10-28 21:57:31 +02007650/* Note: *non-interactive* bash does not continue if all processes in fg pipe
7651 * are stopped. Testcase: "cat | cat" in a script (not on command line!)
7652 * and "killall -STOP cat" */
7653 if (G_interactive_fd) {
7654#if ENABLE_HUSH_JOB
7655 if (fg_pipe->alive_cmds != 0)
Denys Vlasenko16096292017-07-10 10:00:28 +02007656 insert_job_into_table(fg_pipe);
Denys Vlasenko7e675362016-10-28 21:57:31 +02007657#endif
7658 return rcode;
7659 }
7660 if (fg_pipe->alive_cmds == 0)
7661 return rcode;
7662 }
7663 /* There are still running processes in the fg_pipe */
7664 return -1;
7665 }
Denys Vlasenko10ad6222017-04-17 16:13:32 +02007666 /* It wasn't in fg_pipe, look for process in bg pipes */
Denys Vlasenko7e675362016-10-28 21:57:31 +02007667 }
7668
7669#if ENABLE_HUSH_JOB
7670 /* We were asked to wait for bg or orphaned children */
7671 /* No need to remember exitcode in this case */
7672 for (pi = G.job_list; pi; pi = pi->next) {
7673 for (i = 0; i < pi->num_cmds; i++) {
7674 if (pi->cmds[i].pid == childpid)
7675 goto found_pi_and_prognum;
7676 }
7677 }
7678 /* Happens when shell is used as init process (init=/bin/sh) */
7679 debug_printf("checkjobs: pid %d was not in our list!\n", childpid);
7680 return -1; /* this wasn't a process from fg_pipe */
7681
7682 found_pi_and_prognum:
7683 if (dead) {
7684 /* child exited */
Denys Vlasenko840a4352017-07-07 22:56:02 +02007685 int rcode = WEXITSTATUS(status);
Denys Vlasenko7e675362016-10-28 21:57:31 +02007686 if (WIFSIGNALED(status))
Denys Vlasenko840a4352017-07-07 22:56:02 +02007687 rcode = 128 + WTERMSIG(status);
7688 pi->cmds[i].cmd_exitcode = rcode;
7689 if (G.last_bg_pid == pi->cmds[i].pid)
7690 G.last_bg_pid_exitcode = rcode;
7691 pi->cmds[i].pid = 0;
Denys Vlasenko7e675362016-10-28 21:57:31 +02007692 pi->alive_cmds--;
7693 if (!pi->alive_cmds) {
Denys Vlasenko2ed74e22017-07-14 19:58:46 +02007694 if (G_interactive_fd) {
Denys Vlasenko7e675362016-10-28 21:57:31 +02007695 printf(JOB_STATUS_FORMAT, pi->jobid,
7696 "Done", pi->cmdtext);
Denys Vlasenko2ed74e22017-07-14 19:58:46 +02007697 delete_finished_job(pi);
7698 } else {
7699/*
7700 * bash deletes finished jobs from job table only in interactive mode,
7701 * after "jobs" cmd, or if pid of a new process matches one of the old ones
7702 * (see cleanup_dead_jobs(), delete_old_job(), J_NOTIFIED in bash source).
7703 * Testcase script: "(exit 3) & sleep 1; wait %1; echo $?" prints 3 in bash.
7704 * We only retain one "dead" job, if it's the single job on the list.
7705 * This covers most of real-world scenarios where this is useful.
7706 */
7707 if (pi != G.job_list)
7708 delete_finished_job(pi);
7709 }
Denys Vlasenko7e675362016-10-28 21:57:31 +02007710 }
7711 } else {
7712 /* child stopped */
7713 pi->stopped_cmds++;
7714 }
7715#endif
7716 return -1; /* this wasn't a process from fg_pipe */
7717}
7718
7719/* Check to see if any processes have exited -- if they have,
7720 * figure out why and see if a job has completed.
Denys Vlasenko62b717b2016-11-07 22:12:18 +01007721 *
7722 * If non-NULL fg_pipe: wait for its completion or stop.
7723 * Return its exitcode or zero if stopped.
7724 *
7725 * Alternatively (fg_pipe == NULL, waitfor_pid != 0):
7726 * waitpid(WNOHANG), if waitfor_pid exits or stops, return exitcode+1,
7727 * else return <0 if waitpid errors out (e.g. ECHILD: nothing to wait for)
7728 * or 0 if no children changed status.
7729 *
7730 * Alternatively (fg_pipe == NULL, waitfor_pid == 0),
7731 * return <0 if waitpid errors out (e.g. ECHILD: nothing to wait for)
7732 * or 0 if no children changed status.
Denys Vlasenko7e675362016-10-28 21:57:31 +02007733 */
7734static int checkjobs(struct pipe *fg_pipe, pid_t waitfor_pid)
7735{
7736 int attributes;
7737 int status;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007738 int rcode = 0;
7739
7740 debug_printf_jobs("checkjobs %p\n", fg_pipe);
7741
7742 attributes = WUNTRACED;
7743 if (fg_pipe == NULL)
7744 attributes |= WNOHANG;
7745
7746 errno = 0;
7747#if ENABLE_HUSH_FAST
7748 if (G.handled_SIGCHLD == G.count_SIGCHLD) {
7749//bb_error_msg("[%d] checkjobs: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d children?:%d fg_pipe:%p",
7750//getpid(), G.count_SIGCHLD, G.handled_SIGCHLD, G.we_have_children, fg_pipe);
7751 /* There was neither fork nor SIGCHLD since last waitpid */
7752 /* Avoid doing waitpid syscall if possible */
7753 if (!G.we_have_children) {
7754 errno = ECHILD;
7755 return -1;
7756 }
7757 if (fg_pipe == NULL) { /* is WNOHANG set? */
7758 /* We have children, but they did not exit
7759 * or stop yet (we saw no SIGCHLD) */
7760 return 0;
7761 }
7762 /* else: !WNOHANG, waitpid will block, can't short-circuit */
7763 }
7764#endif
7765
7766/* Do we do this right?
7767 * bash-3.00# sleep 20 | false
7768 * <ctrl-Z pressed>
7769 * [3]+ Stopped sleep 20 | false
7770 * bash-3.00# echo $?
7771 * 1 <========== bg pipe is not fully done, but exitcode is already known!
7772 * [hush 1.14.0: yes we do it right]
7773 */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007774 while (1) {
Denys Vlasenko7e675362016-10-28 21:57:31 +02007775 pid_t childpid;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007776#if ENABLE_HUSH_FAST
Denys Vlasenko7e675362016-10-28 21:57:31 +02007777 int i;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007778 i = G.count_SIGCHLD;
7779#endif
7780 childpid = waitpid(-1, &status, attributes);
7781 if (childpid <= 0) {
7782 if (childpid && errno != ECHILD)
7783 bb_perror_msg("waitpid");
7784#if ENABLE_HUSH_FAST
7785 else { /* Until next SIGCHLD, waitpid's are useless */
7786 G.we_have_children = (childpid == 0);
7787 G.handled_SIGCHLD = i;
7788//bb_error_msg("[%d] checkjobs: waitpid returned <= 0, G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
7789 }
7790#endif
Denys Vlasenko7e675362016-10-28 21:57:31 +02007791 /* ECHILD (no children), or 0 (no change in children status) */
7792 rcode = childpid;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007793 break;
7794 }
Denys Vlasenko7e675362016-10-28 21:57:31 +02007795 rcode = process_wait_result(fg_pipe, childpid, status);
7796 if (rcode >= 0) {
7797 /* fg_pipe exited or stopped */
7798 break;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007799 }
Denys Vlasenko7e675362016-10-28 21:57:31 +02007800 if (childpid == waitfor_pid) {
Denys Vlasenko62b717b2016-11-07 22:12:18 +01007801 debug_printf_exec("childpid==waitfor_pid:%d status:0x%08x\n", childpid, status);
Denys Vlasenko7e675362016-10-28 21:57:31 +02007802 rcode = WEXITSTATUS(status);
7803 if (WIFSIGNALED(status))
7804 rcode = 128 + WTERMSIG(status);
Denys Vlasenko62b717b2016-11-07 22:12:18 +01007805 if (WIFSTOPPED(status))
7806 /* bash: "cmd & wait $!" and cmd stops: $? = 128 + stopsig */
7807 rcode = 128 + WSTOPSIG(status);
Denys Vlasenko7e675362016-10-28 21:57:31 +02007808 rcode++;
7809 break; /* "wait PID" called us, give it exitcode+1 */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007810 }
Denys Vlasenko7e675362016-10-28 21:57:31 +02007811 /* This wasn't one of our processes, or */
7812 /* fg_pipe still has running processes, do waitpid again */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007813 } /* while (waitpid succeeds)... */
7814
7815 return rcode;
7816}
7817
7818#if ENABLE_HUSH_JOB
Denys Vlasenkoda463fb2010-09-07 09:53:50 +02007819static int checkjobs_and_fg_shell(struct pipe *fg_pipe)
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007820{
7821 pid_t p;
Denys Vlasenko7e675362016-10-28 21:57:31 +02007822 int rcode = checkjobs(fg_pipe, 0 /*(no pid to wait for)*/);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007823 if (G_saved_tty_pgrp) {
7824 /* Job finished, move the shell to the foreground */
7825 p = getpgrp(); /* our process group id */
7826 debug_printf_jobs("fg'ing ourself: getpgrp()=%d\n", (int)p);
7827 tcsetpgrp(G_interactive_fd, p);
7828 }
7829 return rcode;
7830}
7831#endif
7832
7833/* Start all the jobs, but don't wait for anything to finish.
7834 * See checkjobs().
7835 *
7836 * Return code is normally -1, when the caller has to wait for children
7837 * to finish to determine the exit status of the pipe. If the pipe
7838 * is a simple builtin command, however, the action is done by the
7839 * time run_pipe returns, and the exit code is provided as the
7840 * return value.
7841 *
7842 * Returns -1 only if started some children. IOW: we have to
7843 * mask out retvals of builtins etc with 0xff!
7844 *
7845 * The only case when we do not need to [v]fork is when the pipe
7846 * is single, non-backgrounded, non-subshell command. Examples:
7847 * cmd ; ... { list } ; ...
7848 * cmd && ... { list } && ...
7849 * cmd || ... { list } || ...
Denys Vlasenkob72baeb2011-02-02 18:38:57 +01007850 * If it is, then we can run cmd as a builtin, NOFORK,
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007851 * or (if SH_STANDALONE) an applet, and we can run the { list }
7852 * with run_list. If it isn't one of these, we fork and exec cmd.
7853 *
7854 * Cases when we must fork:
7855 * non-single: cmd | cmd
7856 * backgrounded: cmd & { list } &
7857 * subshell: ( list ) [&]
7858 */
7859#if !ENABLE_HUSH_MODE_X
Denys Vlasenko26777aa2010-11-22 23:49:10 +01007860#define redirect_and_varexp_helper(new_env_p, old_vars_p, command, squirrel, argv_expanded) \
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007861 redirect_and_varexp_helper(new_env_p, old_vars_p, command, squirrel)
7862#endif
7863static int redirect_and_varexp_helper(char ***new_env_p,
7864 struct variable **old_vars_p,
7865 struct command *command,
Denys Vlasenko2db74612017-07-07 22:07:28 +02007866 struct squirrel **sqp,
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007867 char **argv_expanded)
7868{
7869 /* setup_redirects acts on file descriptors, not FILEs.
7870 * This is perfect for work that comes after exec().
7871 * Is it really safe for inline use? Experimentally,
7872 * things seem to work. */
Denys Vlasenko2db74612017-07-07 22:07:28 +02007873 int rcode = setup_redirects(command, sqp);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007874 if (rcode == 0) {
7875 char **new_env = expand_assignments(command->argv, command->assignment_cnt);
7876 *new_env_p = new_env;
7877 dump_cmd_in_x_mode(new_env);
7878 dump_cmd_in_x_mode(argv_expanded);
7879 if (old_vars_p)
7880 *old_vars_p = set_vars_and_save_old(new_env);
7881 }
7882 return rcode;
7883}
7884static NOINLINE int run_pipe(struct pipe *pi)
7885{
7886 static const char *const null_ptr = NULL;
7887
7888 int cmd_no;
7889 int next_infd;
7890 struct command *command;
7891 char **argv_expanded;
7892 char **argv;
Denys Vlasenko2db74612017-07-07 22:07:28 +02007893 struct squirrel *squirrel = NULL;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007894 int rcode;
7895
7896 debug_printf_exec("run_pipe start: members:%d\n", pi->num_cmds);
7897 debug_enter();
7898
Denys Vlasenko1fd3d942010-09-08 13:31:53 +02007899 /* Testcase: set -- q w e; (IFS='' echo "$*"; IFS=''; echo "$*"); echo "$*"
7900 * Result should be 3 lines: q w e, qwe, q w e
7901 */
7902 G.ifs = get_local_var_value("IFS");
7903 if (!G.ifs)
7904 G.ifs = defifs;
7905
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007906 IF_HUSH_JOB(pi->pgrp = -1;)
7907 pi->stopped_cmds = 0;
7908 command = &pi->cmds[0];
7909 argv_expanded = NULL;
7910
7911 if (pi->num_cmds != 1
7912 || pi->followup == PIPE_BG
7913 || command->cmd_type == CMD_SUBSHELL
7914 ) {
7915 goto must_fork;
7916 }
7917
7918 pi->alive_cmds = 1;
7919
7920 debug_printf_exec(": group:%p argv:'%s'\n",
7921 command->group, command->argv ? command->argv[0] : "NONE");
7922
7923 if (command->group) {
7924#if ENABLE_HUSH_FUNCTIONS
7925 if (command->cmd_type == CMD_FUNCDEF) {
7926 /* "executing" func () { list } */
7927 struct function *funcp;
7928
7929 funcp = new_function(command->argv[0]);
7930 /* funcp->name is already set to argv[0] */
7931 funcp->body = command->group;
7932# if !BB_MMU
7933 funcp->body_as_string = command->group_as_string;
7934 command->group_as_string = NULL;
7935# endif
7936 command->group = NULL;
7937 command->argv[0] = NULL;
7938 debug_printf_exec("cmd %p has child func at %p\n", command, funcp);
7939 funcp->parent_cmd = command;
7940 command->child_func = funcp;
7941
7942 debug_printf_exec("run_pipe: return EXIT_SUCCESS\n");
7943 debug_leave();
7944 return EXIT_SUCCESS;
7945 }
7946#endif
7947 /* { list } */
7948 debug_printf("non-subshell group\n");
7949 rcode = 1; /* exitcode if redir failed */
Denys Vlasenko2db74612017-07-07 22:07:28 +02007950 if (setup_redirects(command, &squirrel) == 0) {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007951 debug_printf_exec(": run_list\n");
7952 rcode = run_list(command->group) & 0xff;
7953 }
7954 restore_redirects(squirrel);
7955 IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
7956 debug_leave();
7957 debug_printf_exec("run_pipe: return %d\n", rcode);
7958 return rcode;
7959 }
7960
7961 argv = command->argv ? command->argv : (char **) &null_ptr;
7962 {
7963 const struct built_in_command *x;
7964#if ENABLE_HUSH_FUNCTIONS
7965 const struct function *funcp;
7966#else
7967 enum { funcp = 0 };
7968#endif
7969 char **new_env = NULL;
7970 struct variable *old_vars = NULL;
7971
7972 if (argv[command->assignment_cnt] == NULL) {
7973 /* Assignments, but no command */
7974 /* Ensure redirects take effect (that is, create files).
7975 * Try "a=t >file" */
7976#if 0 /* A few cases in testsuite fail with this code. FIXME */
Denys Vlasenko2db74612017-07-07 22:07:28 +02007977 rcode = redirect_and_varexp_helper(&new_env, /*old_vars:*/ NULL, command, &squirrel, /*argv_expanded:*/ NULL);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007978 /* Set shell variables */
7979 if (new_env) {
7980 argv = new_env;
7981 while (*argv) {
Denys Vlasenko38ef39a2017-07-18 01:40:01 +02007982 if (set_local_var(*argv, /*flag:*/ 0)) {
7983 /* assignment to readonly var / putenv error? */
7984 rcode = 1;
7985 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02007986 argv++;
7987 }
7988 }
7989 /* Redirect error sets $? to 1. Otherwise,
7990 * if evaluating assignment value set $?, retain it.
7991 * Try "false; q=`exit 2`; echo $?" - should print 2: */
7992 if (rcode == 0)
7993 rcode = G.last_exitcode;
7994 /* Exit, _skipping_ variable restoring code: */
7995 goto clean_up_and_ret0;
7996
7997#else /* Older, bigger, but more correct code */
7998
Denys Vlasenko2db74612017-07-07 22:07:28 +02007999 rcode = setup_redirects(command, &squirrel);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008000 restore_redirects(squirrel);
8001 /* Set shell variables */
8002 if (G_x_mode)
8003 bb_putchar_stderr('+');
8004 while (*argv) {
Denys Vlasenkoebee4102010-09-10 10:17:53 +02008005 char *p = expand_string_to_string(*argv, /*unbackslash:*/ 1);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008006 if (G_x_mode)
8007 fprintf(stderr, " %s", p);
8008 debug_printf_exec("set shell var:'%s'->'%s'\n",
8009 *argv, p);
Denys Vlasenko38ef39a2017-07-18 01:40:01 +02008010 if (set_local_var(p, /*flag:*/ 0)) {
8011 /* assignment to readonly var / putenv error? */
8012 rcode = 1;
8013 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008014 argv++;
8015 }
8016 if (G_x_mode)
8017 bb_putchar_stderr('\n');
8018 /* Redirect error sets $? to 1. Otherwise,
8019 * if evaluating assignment value set $?, retain it.
8020 * Try "false; q=`exit 2`; echo $?" - should print 2: */
8021 if (rcode == 0)
8022 rcode = G.last_exitcode;
8023 IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
8024 debug_leave();
8025 debug_printf_exec("run_pipe: return %d\n", rcode);
8026 return rcode;
8027#endif
8028 }
8029
8030 /* Expand the rest into (possibly) many strings each */
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01008031#if BASH_TEST2
Denys Vlasenkob72baeb2011-02-02 18:38:57 +01008032 if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008033 argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt);
Denys Vlasenkob72baeb2011-02-02 18:38:57 +01008034 } else
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008035#endif
Denys Vlasenkob72baeb2011-02-02 18:38:57 +01008036 {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008037 argv_expanded = expand_strvec_to_strvec(argv + command->assignment_cnt);
8038 }
8039
8040 /* if someone gives us an empty string: `cmd with empty output` */
8041 if (!argv_expanded[0]) {
8042 free(argv_expanded);
8043 debug_leave();
8044 return G.last_exitcode;
8045 }
8046
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008047#if ENABLE_HUSH_FUNCTIONS
Denys Vlasenko75481d32017-07-31 05:27:09 +02008048 /* Check if argv[0] matches any functions (this goes before bltins) */
8049 funcp = find_function(argv_expanded[0]);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008050#endif
Denys Vlasenko75481d32017-07-31 05:27:09 +02008051 x = NULL;
8052 if (!funcp)
8053 x = find_builtin(argv_expanded[0]);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008054 if (x || funcp) {
8055 if (!funcp) {
8056 if (x->b_function == builtin_exec && argv_expanded[1] == NULL) {
8057 debug_printf("exec with redirects only\n");
8058 rcode = setup_redirects(command, NULL);
Denys Vlasenko869994c2016-08-20 15:16:00 +02008059 /* rcode=1 can be if redir file can't be opened */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008060 goto clean_up_and_ret1;
8061 }
8062 }
Denys Vlasenko2db74612017-07-07 22:07:28 +02008063 rcode = redirect_and_varexp_helper(&new_env, &old_vars, command, &squirrel, argv_expanded);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008064 if (rcode == 0) {
8065 if (!funcp) {
8066 debug_printf_exec(": builtin '%s' '%s'...\n",
8067 x->b_cmd, argv_expanded[1]);
Denys Vlasenko8ee2ada2011-02-07 02:03:51 +01008068 fflush_all();
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008069 rcode = x->b_function(argv_expanded) & 0xff;
8070 fflush_all();
8071 }
8072#if ENABLE_HUSH_FUNCTIONS
8073 else {
8074# if ENABLE_HUSH_LOCAL
8075 struct variable **sv;
8076 sv = G.shadowed_vars_pp;
8077 G.shadowed_vars_pp = &old_vars;
8078# endif
8079 debug_printf_exec(": function '%s' '%s'...\n",
8080 funcp->name, argv_expanded[1]);
8081 rcode = run_function(funcp, argv_expanded) & 0xff;
8082# if ENABLE_HUSH_LOCAL
8083 G.shadowed_vars_pp = sv;
8084# endif
8085 }
8086#endif
8087 }
8088 clean_up_and_ret:
8089 unset_vars(new_env);
8090 add_vars(old_vars);
8091/* clean_up_and_ret0: */
8092 restore_redirects(squirrel);
Denys Vlasenko7c40ddd2017-08-02 16:37:39 +02008093 /*
8094 * Try "usleep 99999999" + ^C + "echo $?"
8095 * with FEATURE_SH_NOFORK=y.
8096 */
8097 if (!funcp) {
8098 /* It was builtin or nofork.
8099 * if this would be a real fork/execed program,
8100 * it should have died if a fatal sig was received.
8101 * But OTOH, there was no separate process,
8102 * the sig was sent to _shell_, not to non-existing
8103 * child.
8104 * Let's just handle ^C only, this one is obvious:
8105 * we aren't ok with exitcode 0 when ^C was pressed
8106 * during builtin/nofork.
8107 */
8108 if (sigismember(&G.pending_set, SIGINT))
8109 rcode = 128 + SIGINT;
8110 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008111 clean_up_and_ret1:
8112 free(argv_expanded);
8113 IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
8114 debug_leave();
8115 debug_printf_exec("run_pipe return %d\n", rcode);
8116 return rcode;
8117 }
8118
Denys Vlasenkob72baeb2011-02-02 18:38:57 +01008119 if (ENABLE_FEATURE_SH_NOFORK) {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008120 int n = find_applet_by_name(argv_expanded[0]);
8121 if (n >= 0 && APPLET_IS_NOFORK(n)) {
Denys Vlasenko2db74612017-07-07 22:07:28 +02008122 rcode = redirect_and_varexp_helper(&new_env, &old_vars, command, &squirrel, argv_expanded);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008123 if (rcode == 0) {
8124 debug_printf_exec(": run_nofork_applet '%s' '%s'...\n",
8125 argv_expanded[0], argv_expanded[1]);
Denys Vlasenko7c40ddd2017-08-02 16:37:39 +02008126 /*
8127 * Note: signals (^C) can't interrupt here.
8128 * We remember them and they will be acted upon
8129 * after applet returns.
8130 * This makes applets which can run for a long time
8131 * and/or wait for user input ineligible for NOFORK:
8132 * for example, "yes" or "rm" (rm -i waits for input).
8133 */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008134 rcode = run_nofork_applet(n, argv_expanded);
8135 }
8136 goto clean_up_and_ret;
8137 }
8138 }
8139 /* It is neither builtin nor applet. We must fork. */
8140 }
8141
8142 must_fork:
8143 /* NB: argv_expanded may already be created, and that
8144 * might include `cmd` runs! Do not rerun it! We *must*
8145 * use argv_expanded if it's non-NULL */
8146
8147 /* Going to fork a child per each pipe member */
8148 pi->alive_cmds = 0;
8149 next_infd = 0;
8150
8151 cmd_no = 0;
8152 while (cmd_no < pi->num_cmds) {
8153 struct fd_pair pipefds;
8154#if !BB_MMU
8155 volatile nommu_save_t nommu_save;
8156 nommu_save.new_env = NULL;
8157 nommu_save.old_vars = NULL;
8158 nommu_save.argv = NULL;
8159 nommu_save.argv_from_re_execing = NULL;
8160#endif
8161 command = &pi->cmds[cmd_no];
8162 cmd_no++;
8163 if (command->argv) {
8164 debug_printf_exec(": pipe member '%s' '%s'...\n",
8165 command->argv[0], command->argv[1]);
8166 } else {
8167 debug_printf_exec(": pipe member with no argv\n");
8168 }
8169
8170 /* pipes are inserted between pairs of commands */
8171 pipefds.rd = 0;
8172 pipefds.wr = 1;
8173 if (cmd_no < pi->num_cmds)
8174 xpiped_pair(pipefds);
8175
8176 command->pid = BB_MMU ? fork() : vfork();
8177 if (!command->pid) { /* child */
8178#if ENABLE_HUSH_JOB
8179 disable_restore_tty_pgrp_on_exit();
8180 CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */
8181
8182 /* Every child adds itself to new process group
8183 * with pgid == pid_of_first_child_in_pipe */
8184 if (G.run_list_level == 1 && G_interactive_fd) {
8185 pid_t pgrp;
8186 pgrp = pi->pgrp;
8187 if (pgrp < 0) /* true for 1st process only */
8188 pgrp = getpid();
8189 if (setpgid(0, pgrp) == 0
8190 && pi->followup != PIPE_BG
8191 && G_saved_tty_pgrp /* we have ctty */
8192 ) {
8193 /* We do it in *every* child, not just first,
8194 * to avoid races */
8195 tcsetpgrp(G_interactive_fd, pgrp);
8196 }
8197 }
8198#endif
8199 if (pi->alive_cmds == 0 && pi->followup == PIPE_BG) {
8200 /* 1st cmd in backgrounded pipe
8201 * should have its stdin /dev/null'ed */
8202 close(0);
8203 if (open(bb_dev_null, O_RDONLY))
8204 xopen("/", O_RDONLY);
8205 } else {
8206 xmove_fd(next_infd, 0);
8207 }
8208 xmove_fd(pipefds.wr, 1);
8209 if (pipefds.rd > 1)
8210 close(pipefds.rd);
8211 /* Like bash, explicit redirects override pipes,
Denys Vlasenko869994c2016-08-20 15:16:00 +02008212 * and the pipe fd (fd#1) is available for dup'ing:
8213 * "cmd1 2>&1 | cmd2": fd#1 is duped to fd#2, thus stderr
8214 * of cmd1 goes into pipe.
8215 */
8216 if (setup_redirects(command, NULL)) {
8217 /* Happens when redir file can't be opened:
8218 * $ hush -c 'echo FOO >&2 | echo BAR 3>/qwe/rty; echo BAZ'
8219 * FOO
8220 * hush: can't open '/qwe/rty': No such file or directory
8221 * BAZ
8222 * (echo BAR is not executed, it hits _exit(1) below)
8223 */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008224 _exit(1);
Denys Vlasenko869994c2016-08-20 15:16:00 +02008225 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008226
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008227 /* Stores to nommu_save list of env vars putenv'ed
8228 * (NOMMU, on MMU we don't need that) */
8229 /* cast away volatility... */
8230 pseudo_exec((nommu_save_t*) &nommu_save, command, argv_expanded);
8231 /* pseudo_exec() does not return */
8232 }
8233
8234 /* parent or error */
8235#if ENABLE_HUSH_FAST
8236 G.count_SIGCHLD++;
8237//bb_error_msg("[%d] fork in run_pipe: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
8238#endif
8239 enable_restore_tty_pgrp_on_exit();
8240#if !BB_MMU
8241 /* Clean up after vforked child */
8242 free(nommu_save.argv);
8243 free(nommu_save.argv_from_re_execing);
8244 unset_vars(nommu_save.new_env);
8245 add_vars(nommu_save.old_vars);
8246#endif
8247 free(argv_expanded);
8248 argv_expanded = NULL;
8249 if (command->pid < 0) { /* [v]fork failed */
8250 /* Clearly indicate, was it fork or vfork */
8251 bb_perror_msg(BB_MMU ? "vfork"+1 : "vfork");
8252 } else {
8253 pi->alive_cmds++;
8254#if ENABLE_HUSH_JOB
8255 /* Second and next children need to know pid of first one */
8256 if (pi->pgrp < 0)
8257 pi->pgrp = command->pid;
8258#endif
8259 }
8260
8261 if (cmd_no > 1)
8262 close(next_infd);
8263 if (cmd_no < pi->num_cmds)
8264 close(pipefds.wr);
8265 /* Pass read (output) pipe end to next iteration */
8266 next_infd = pipefds.rd;
8267 }
8268
8269 if (!pi->alive_cmds) {
8270 debug_leave();
8271 debug_printf_exec("run_pipe return 1 (all forks failed, no children)\n");
8272 return 1;
8273 }
8274
8275 debug_leave();
8276 debug_printf_exec("run_pipe return -1 (%u children started)\n", pi->alive_cmds);
8277 return -1;
8278}
8279
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008280/* NB: called by pseudo_exec, and therefore must not modify any
8281 * global data until exec/_exit (we can be a child after vfork!) */
8282static int run_list(struct pipe *pi)
8283{
8284#if ENABLE_HUSH_CASE
8285 char *case_word = NULL;
8286#endif
8287#if ENABLE_HUSH_LOOPS
8288 struct pipe *loop_top = NULL;
8289 char **for_lcur = NULL;
8290 char **for_list = NULL;
8291#endif
8292 smallint last_followup;
8293 smalluint rcode;
8294#if ENABLE_HUSH_IF || ENABLE_HUSH_CASE
8295 smalluint cond_code = 0;
8296#else
8297 enum { cond_code = 0 };
8298#endif
8299#if HAS_KEYWORDS
Denys Vlasenko9b782552010-09-08 13:33:26 +02008300 smallint rword; /* RES_foo */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008301 smallint last_rword; /* ditto */
8302#endif
8303
8304 debug_printf_exec("run_list start lvl %d\n", G.run_list_level);
8305 debug_enter();
8306
8307#if ENABLE_HUSH_LOOPS
8308 /* Check syntax for "for" */
Denys Vlasenko0d6a4ec2010-12-18 01:34:49 +01008309 {
8310 struct pipe *cpipe;
8311 for (cpipe = pi; cpipe; cpipe = cpipe->next) {
8312 if (cpipe->res_word != RES_FOR && cpipe->res_word != RES_IN)
8313 continue;
8314 /* current word is FOR or IN (BOLD in comments below) */
8315 if (cpipe->next == NULL) {
8316 syntax_error("malformed for");
8317 debug_leave();
8318 debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level);
8319 return 1;
8320 }
8321 /* "FOR v; do ..." and "for v IN a b; do..." are ok */
8322 if (cpipe->next->res_word == RES_DO)
8323 continue;
8324 /* next word is not "do". It must be "in" then ("FOR v in ...") */
8325 if (cpipe->res_word == RES_IN /* "for v IN a b; not_do..."? */
8326 || cpipe->next->res_word != RES_IN /* FOR v not_do_and_not_in..."? */
8327 ) {
8328 syntax_error("malformed for");
8329 debug_leave();
8330 debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level);
8331 return 1;
8332 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008333 }
8334 }
8335#endif
8336
8337 /* Past this point, all code paths should jump to ret: label
8338 * in order to return, no direct "return" statements please.
8339 * This helps to ensure that no memory is leaked. */
8340
8341#if ENABLE_HUSH_JOB
8342 G.run_list_level++;
8343#endif
8344
8345#if HAS_KEYWORDS
8346 rword = RES_NONE;
8347 last_rword = RES_XXXX;
8348#endif
8349 last_followup = PIPE_SEQ;
8350 rcode = G.last_exitcode;
8351
8352 /* Go through list of pipes, (maybe) executing them. */
8353 for (; pi; pi = IF_HUSH_LOOPS(rword == RES_DONE ? loop_top : ) pi->next) {
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01008354 int r;
Denys Vlasenko9fda6092017-07-14 13:36:48 +02008355 int sv_errexit_depth;
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01008356
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008357 if (G.flag_SIGINT)
8358 break;
Denys Vlasenko04b46bc2016-10-01 22:28:03 +02008359 if (G_flag_return_in_progress == 1)
8360 break;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008361
8362 IF_HAS_KEYWORDS(rword = pi->res_word;)
8363 debug_printf_exec(": rword=%d cond_code=%d last_rword=%d\n",
8364 rword, cond_code, last_rword);
Denys Vlasenko9fda6092017-07-14 13:36:48 +02008365
8366 sv_errexit_depth = G.errexit_depth;
8367 if (IF_HAS_KEYWORDS(rword == RES_IF || rword == RES_ELIF ||)
8368 pi->followup != PIPE_SEQ
8369 ) {
8370 G.errexit_depth++;
8371 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008372#if ENABLE_HUSH_LOOPS
8373 if ((rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR)
8374 && loop_top == NULL /* avoid bumping G.depth_of_loop twice */
8375 ) {
8376 /* start of a loop: remember where loop starts */
8377 loop_top = pi;
8378 G.depth_of_loop++;
8379 }
8380#endif
8381 /* Still in the same "if...", "then..." or "do..." branch? */
8382 if (IF_HAS_KEYWORDS(rword == last_rword &&) 1) {
8383 if ((rcode == 0 && last_followup == PIPE_OR)
8384 || (rcode != 0 && last_followup == PIPE_AND)
8385 ) {
8386 /* It is "<true> || CMD" or "<false> && CMD"
8387 * and we should not execute CMD */
8388 debug_printf_exec("skipped cmd because of || or &&\n");
8389 last_followup = pi->followup;
Denys Vlasenko3beab832013-04-07 18:16:58 +02008390 goto dont_check_jobs_but_continue;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008391 }
8392 }
8393 last_followup = pi->followup;
8394 IF_HAS_KEYWORDS(last_rword = rword;)
8395#if ENABLE_HUSH_IF
8396 if (cond_code) {
8397 if (rword == RES_THEN) {
8398 /* if false; then ... fi has exitcode 0! */
8399 G.last_exitcode = rcode = EXIT_SUCCESS;
8400 /* "if <false> THEN cmd": skip cmd */
8401 continue;
8402 }
8403 } else {
8404 if (rword == RES_ELSE || rword == RES_ELIF) {
8405 /* "if <true> then ... ELSE/ELIF cmd":
8406 * skip cmd and all following ones */
8407 break;
8408 }
8409 }
8410#endif
8411#if ENABLE_HUSH_LOOPS
8412 if (rword == RES_FOR) { /* && pi->num_cmds - always == 1 */
8413 if (!for_lcur) {
8414 /* first loop through for */
8415
8416 static const char encoded_dollar_at[] ALIGN1 = {
8417 SPECIAL_VAR_SYMBOL, '@' | 0x80, SPECIAL_VAR_SYMBOL, '\0'
8418 }; /* encoded representation of "$@" */
8419 static const char *const encoded_dollar_at_argv[] = {
8420 encoded_dollar_at, NULL
8421 }; /* argv list with one element: "$@" */
8422 char **vals;
8423
8424 vals = (char**)encoded_dollar_at_argv;
8425 if (pi->next->res_word == RES_IN) {
8426 /* if no variable values after "in" we skip "for" */
8427 if (!pi->next->cmds[0].argv) {
8428 G.last_exitcode = rcode = EXIT_SUCCESS;
8429 debug_printf_exec(": null FOR: exitcode EXIT_SUCCESS\n");
8430 break;
8431 }
8432 vals = pi->next->cmds[0].argv;
8433 } /* else: "for var; do..." -> assume "$@" list */
8434 /* create list of variable values */
8435 debug_print_strings("for_list made from", vals);
8436 for_list = expand_strvec_to_strvec(vals);
8437 for_lcur = for_list;
8438 debug_print_strings("for_list", for_list);
8439 }
8440 if (!*for_lcur) {
8441 /* "for" loop is over, clean up */
8442 free(for_list);
8443 for_list = NULL;
8444 for_lcur = NULL;
8445 break;
8446 }
8447 /* Insert next value from for_lcur */
8448 /* note: *for_lcur already has quotes removed, $var expanded, etc */
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02008449 set_local_var(xasprintf("%s=%s", pi->cmds[0].argv[0], *for_lcur++), /*flag:*/ 0);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008450 continue;
8451 }
8452 if (rword == RES_IN) {
8453 continue; /* "for v IN list;..." - "in" has no cmds anyway */
8454 }
8455 if (rword == RES_DONE) {
8456 continue; /* "done" has no cmds too */
8457 }
8458#endif
8459#if ENABLE_HUSH_CASE
8460 if (rword == RES_CASE) {
Denys Vlasenkoaeaee432016-11-04 20:14:04 +01008461 debug_printf_exec("CASE cond_code:%d\n", cond_code);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008462 case_word = expand_strvec_to_string(pi->cmds->argv);
Denys Vlasenkobd43c672017-07-05 23:12:15 +02008463 unbackslash(case_word);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008464 continue;
8465 }
8466 if (rword == RES_MATCH) {
8467 char **argv;
8468
Denys Vlasenkoaeaee432016-11-04 20:14:04 +01008469 debug_printf_exec("MATCH cond_code:%d\n", cond_code);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008470 if (!case_word) /* "case ... matched_word) ... WORD)": we executed selected branch, stop */
8471 break;
8472 /* all prev words didn't match, does this one match? */
8473 argv = pi->cmds->argv;
8474 while (*argv) {
Denys Vlasenkobd43c672017-07-05 23:12:15 +02008475 char *pattern = expand_string_to_string(*argv, /*unbackslash:*/ 0);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008476 /* TODO: which FNM_xxx flags to use? */
8477 cond_code = (fnmatch(pattern, case_word, /*flags:*/ 0) != 0);
Denys Vlasenkobd43c672017-07-05 23:12:15 +02008478 debug_printf_exec("fnmatch(pattern:'%s',str:'%s'):%d\n", pattern, case_word, cond_code);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008479 free(pattern);
8480 if (cond_code == 0) { /* match! we will execute this branch */
Denys Vlasenkoaeaee432016-11-04 20:14:04 +01008481 free(case_word);
8482 case_word = NULL; /* make future "word)" stop */
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008483 break;
8484 }
8485 argv++;
8486 }
8487 continue;
8488 }
8489 if (rword == RES_CASE_BODY) { /* inside of a case branch */
Denys Vlasenkoaeaee432016-11-04 20:14:04 +01008490 debug_printf_exec("CASE_BODY cond_code:%d\n", cond_code);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008491 if (cond_code != 0)
8492 continue; /* not matched yet, skip this pipe */
8493 }
Denys Vlasenkoaeaee432016-11-04 20:14:04 +01008494 if (rword == RES_ESAC) {
8495 debug_printf_exec("ESAC cond_code:%d\n", cond_code);
8496 if (case_word) {
8497 /* "case" did not match anything: still set $? (to 0) */
8498 G.last_exitcode = rcode = EXIT_SUCCESS;
8499 }
8500 }
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008501#endif
8502 /* Just pressing <enter> in shell should check for jobs.
8503 * OTOH, in non-interactive shell this is useless
8504 * and only leads to extra job checks */
8505 if (pi->num_cmds == 0) {
8506 if (G_interactive_fd)
8507 goto check_jobs_and_continue;
8508 continue;
8509 }
8510
8511 /* After analyzing all keywords and conditions, we decided
8512 * to execute this pipe. NB: have to do checkjobs(NULL)
8513 * after run_pipe to collect any background children,
8514 * even if list execution is to be stopped. */
8515 debug_printf_exec(": run_pipe with %d members\n", pi->num_cmds);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008516#if ENABLE_HUSH_LOOPS
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01008517 G.flag_break_continue = 0;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008518#endif
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01008519 rcode = r = run_pipe(pi); /* NB: rcode is a smalluint, r is int */
8520 if (r != -1) {
8521 /* We ran a builtin, function, or group.
8522 * rcode is already known
8523 * and we don't need to wait for anything. */
8524 debug_printf_exec(": builtin/func exitcode %d\n", rcode);
8525 G.last_exitcode = rcode;
8526 check_and_run_traps();
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008527#if ENABLE_HUSH_LOOPS
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01008528 /* Was it "break" or "continue"? */
8529 if (G.flag_break_continue) {
8530 smallint fbc = G.flag_break_continue;
8531 /* We might fall into outer *loop*,
8532 * don't want to break it too */
8533 if (loop_top) {
8534 G.depth_break_continue--;
8535 if (G.depth_break_continue == 0)
8536 G.flag_break_continue = 0;
8537 /* else: e.g. "continue 2" should *break* once, *then* continue */
8538 } /* else: "while... do... { we are here (innermost list is not a loop!) };...done" */
8539 if (G.depth_break_continue != 0 || fbc == BC_BREAK) {
Denys Vlasenko7e675362016-10-28 21:57:31 +02008540 checkjobs(NULL, 0 /*(no pid to wait for)*/);
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008541 break;
8542 }
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01008543 /* "continue": simulate end of loop */
8544 rword = RES_DONE;
8545 continue;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008546 }
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01008547#endif
8548 if (G_flag_return_in_progress == 1) {
8549 checkjobs(NULL, 0 /*(no pid to wait for)*/);
8550 break;
8551 }
8552 } else if (pi->followup == PIPE_BG) {
8553 /* What does bash do with attempts to background builtins? */
8554 /* even bash 3.2 doesn't do that well with nested bg:
8555 * try "{ { sleep 10; echo DEEP; } & echo HERE; } &".
8556 * I'm NOT treating inner &'s as jobs */
8557#if ENABLE_HUSH_JOB
8558 if (G.run_list_level == 1)
Denys Vlasenko16096292017-07-10 10:00:28 +02008559 insert_job_into_table(pi);
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01008560#endif
8561 /* Last command's pid goes to $! */
8562 G.last_bg_pid = pi->cmds[pi->num_cmds - 1].pid;
Denys Vlasenko840a4352017-07-07 22:56:02 +02008563 G.last_bg_pid_exitcode = 0;
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01008564 debug_printf_exec(": cmd&: exitcode EXIT_SUCCESS\n");
Denys Vlasenko7c40ddd2017-08-02 16:37:39 +02008565/* Check pi->pi_inverted? "! sleep 1 & echo $?": bash says 1. dash and ash say 0 */
Denys Vlasenko6c635d62016-11-08 20:26:11 +01008566 rcode = EXIT_SUCCESS;
8567 goto check_traps;
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01008568 } else {
8569#if ENABLE_HUSH_JOB
8570 if (G.run_list_level == 1 && G_interactive_fd) {
8571 /* Waits for completion, then fg's main shell */
8572 rcode = checkjobs_and_fg_shell(pi);
8573 debug_printf_exec(": checkjobs_and_fg_shell exitcode %d\n", rcode);
Denys Vlasenko6c635d62016-11-08 20:26:11 +01008574 goto check_traps;
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01008575 }
Denys Vlasenko6c635d62016-11-08 20:26:11 +01008576#endif
8577 /* This one just waits for completion */
8578 rcode = checkjobs(pi, 0 /*(no pid to wait for)*/);
8579 debug_printf_exec(": checkjobs exitcode %d\n", rcode);
8580 check_traps:
Denys Vlasenko5cc9bf62016-11-08 17:34:44 +01008581 G.last_exitcode = rcode;
8582 check_and_run_traps();
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008583 }
8584
Denys Vlasenko9fda6092017-07-14 13:36:48 +02008585 /* Handle "set -e" */
8586 if (rcode != 0 && G.o_opt[OPT_O_ERREXIT]) {
8587 debug_printf_exec("ERREXIT:1 errexit_depth:%d\n", G.errexit_depth);
8588 if (G.errexit_depth == 0)
8589 hush_exit(rcode);
8590 }
8591 G.errexit_depth = sv_errexit_depth;
8592
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008593 /* Analyze how result affects subsequent commands */
8594#if ENABLE_HUSH_IF
8595 if (rword == RES_IF || rword == RES_ELIF)
8596 cond_code = rcode;
8597#endif
Denys Vlasenko3beab832013-04-07 18:16:58 +02008598 check_jobs_and_continue:
Denys Vlasenko7e675362016-10-28 21:57:31 +02008599 checkjobs(NULL, 0 /*(no pid to wait for)*/);
Denys Vlasenko3beab832013-04-07 18:16:58 +02008600 dont_check_jobs_but_continue: ;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008601#if ENABLE_HUSH_LOOPS
8602 /* Beware of "while false; true; do ..."! */
Denys Vlasenko00ae9892011-05-31 17:35:45 +02008603 if (pi->next
8604 && (pi->next->res_word == RES_DO || pi->next->res_word == RES_DONE)
Denys Vlasenko56a3b822011-06-01 12:47:07 +02008605 /* check for RES_DONE is needed for "while ...; do \n done" case */
Denys Vlasenko00ae9892011-05-31 17:35:45 +02008606 ) {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008607 if (rword == RES_WHILE) {
8608 if (rcode) {
8609 /* "while false; do...done" - exitcode 0 */
8610 G.last_exitcode = rcode = EXIT_SUCCESS;
8611 debug_printf_exec(": while expr is false: breaking (exitcode:EXIT_SUCCESS)\n");
Denys Vlasenko3beab832013-04-07 18:16:58 +02008612 break;
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008613 }
8614 }
8615 if (rword == RES_UNTIL) {
8616 if (!rcode) {
8617 debug_printf_exec(": until expr is true: breaking\n");
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008618 break;
8619 }
8620 }
8621 }
8622#endif
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008623 } /* for (pi) */
8624
8625#if ENABLE_HUSH_JOB
8626 G.run_list_level--;
8627#endif
8628#if ENABLE_HUSH_LOOPS
8629 if (loop_top)
8630 G.depth_of_loop--;
8631 free(for_list);
8632#endif
8633#if ENABLE_HUSH_CASE
8634 free(case_word);
8635#endif
8636 debug_leave();
8637 debug_printf_exec("run_list lvl %d return %d\n", G.run_list_level + 1, rcode);
8638 return rcode;
8639}
8640
8641/* Select which version we will use */
8642static int run_and_free_list(struct pipe *pi)
8643{
8644 int rcode = 0;
8645 debug_printf_exec("run_and_free_list entered\n");
Dan Fandrich85c62472010-11-20 13:05:17 -08008646 if (!G.o_opt[OPT_O_NOEXEC]) {
Denys Vlasenkob36abf22010-09-05 14:50:59 +02008647 debug_printf_exec(": run_list: 1st pipe with %d cmds\n", pi->num_cmds);
8648 rcode = run_list(pi);
8649 }
8650 /* free_pipe_list has the side effect of clearing memory.
8651 * In the long run that function can be merged with run_list,
8652 * but doing that now would hobble the debugging effort. */
8653 free_pipe_list(pi);
8654 debug_printf_exec("run_and_free_list return %d\n", rcode);
8655 return rcode;
8656}
8657
8658
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02008659static void install_sighandlers(unsigned mask)
Eric Andersen52a97ca2001-06-22 06:49:26 +00008660{
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02008661 sighandler_t old_handler;
8662 unsigned sig = 0;
8663 while ((mask >>= 1) != 0) {
8664 sig++;
8665 if (!(mask & 1))
8666 continue;
Denys Vlasenko0806e402011-05-12 23:06:20 +02008667 old_handler = install_sighandler(sig, pick_sighandler(sig));
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02008668 /* POSIX allows shell to re-enable SIGCHLD
8669 * even if it was SIG_IGN on entry.
8670 * Therefore we skip IGN check for it:
8671 */
8672 if (sig == SIGCHLD)
8673 continue;
Denys Vlasenko49e6bf22017-08-04 14:28:16 +02008674 /* bash re-enables SIGHUP which is SIG_IGNed on entry.
8675 * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
8676 */
8677 //if (sig == SIGHUP) continue; - TODO?
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02008678 if (old_handler == SIG_IGN) {
8679 /* oops... restore back to IGN, and record this fact */
Denys Vlasenko0806e402011-05-12 23:06:20 +02008680 install_sighandler(sig, old_handler);
Denys Vlasenko7a85c602017-01-08 17:40:18 +01008681#if ENABLE_HUSH_TRAP
8682 if (!G_traps)
8683 G_traps = xzalloc(sizeof(G_traps[0]) * NSIG);
8684 free(G_traps[sig]);
8685 G_traps[sig] = xzalloc(1); /* == xstrdup(""); */
8686#endif
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02008687 }
8688 }
8689}
8690
8691/* Called a few times only (or even once if "sh -c") */
8692static void install_special_sighandlers(void)
8693{
Denis Vlasenkof9375282009-04-05 19:13:39 +00008694 unsigned mask;
Denys Vlasenkoe89a2412010-01-12 15:19:31 +01008695
Denys Vlasenko54e9e122011-05-09 00:52:15 +02008696 /* Which signals are shell-special? */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02008697 mask = (1 << SIGQUIT) | (1 << SIGCHLD);
Denys Vlasenko54e9e122011-05-09 00:52:15 +02008698 if (G_interactive_fd) {
8699 mask |= SPECIAL_INTERACTIVE_SIGS;
8700 if (G_saved_tty_pgrp) /* we have ctty, job control sigs work */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02008701 mask |= SPECIAL_JOBSTOP_SIGS;
Denys Vlasenko54e9e122011-05-09 00:52:15 +02008702 }
Denys Vlasenkof58f7052011-05-12 02:10:33 +02008703 /* Careful, do not re-install handlers we already installed */
8704 if (G.special_sig_mask != mask) {
8705 unsigned diff = mask & ~G.special_sig_mask;
8706 G.special_sig_mask = mask;
8707 install_sighandlers(diff);
8708 }
Denis Vlasenkof9375282009-04-05 19:13:39 +00008709}
8710
8711#if ENABLE_HUSH_JOB
8712/* helper */
Denys Vlasenko54e9e122011-05-09 00:52:15 +02008713/* Set handlers to restore tty pgrp and exit */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02008714static void install_fatal_sighandlers(void)
Denis Vlasenkof9375282009-04-05 19:13:39 +00008715{
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02008716 unsigned mask;
Denys Vlasenko54e9e122011-05-09 00:52:15 +02008717
8718 /* We will restore tty pgrp on these signals */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02008719 mask = 0
Denys Vlasenko830ea352016-11-08 04:59:11 +01008720 /*+ (1 << SIGILL ) * HUSH_DEBUG*/
8721 /*+ (1 << SIGFPE ) * HUSH_DEBUG*/
Denys Vlasenko54e9e122011-05-09 00:52:15 +02008722 + (1 << SIGBUS ) * HUSH_DEBUG
8723 + (1 << SIGSEGV) * HUSH_DEBUG
Denys Vlasenko830ea352016-11-08 04:59:11 +01008724 /*+ (1 << SIGTRAP) * HUSH_DEBUG*/
Denys Vlasenko54e9e122011-05-09 00:52:15 +02008725 + (1 << SIGABRT)
8726 /* bash 3.2 seems to handle these just like 'fatal' ones */
8727 + (1 << SIGPIPE)
8728 + (1 << SIGALRM)
Denys Vlasenkof58f7052011-05-12 02:10:33 +02008729 /* if we are interactive, SIGHUP, SIGTERM and SIGINT are special sigs.
Denys Vlasenko54e9e122011-05-09 00:52:15 +02008730 * if we aren't interactive... but in this case
Denys Vlasenkof58f7052011-05-12 02:10:33 +02008731 * we never want to restore pgrp on exit, and this fn is not called
8732 */
Denys Vlasenko54e9e122011-05-09 00:52:15 +02008733 /*+ (1 << SIGHUP )*/
8734 /*+ (1 << SIGTERM)*/
8735 /*+ (1 << SIGINT )*/
8736 ;
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02008737 G_fatal_sig_mask = mask;
Denys Vlasenko54e9e122011-05-09 00:52:15 +02008738
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02008739 install_sighandlers(mask);
Denis Vlasenkof9375282009-04-05 19:13:39 +00008740}
Denis Vlasenkob81b3df2007-04-28 16:48:04 +00008741#endif
Eric Andersenada18ff2001-05-21 16:18:22 +00008742
Denys Vlasenko6696eac2010-11-14 02:01:50 +01008743static int set_mode(int state, char mode, const char *o_opt)
Denis Vlasenkod5762932009-03-31 11:22:57 +00008744{
Denys Vlasenko6696eac2010-11-14 02:01:50 +01008745 int idx;
Denis Vlasenkod5762932009-03-31 11:22:57 +00008746 switch (mode) {
Denys Vlasenko6696eac2010-11-14 02:01:50 +01008747 case 'n':
Dan Fandrich85c62472010-11-20 13:05:17 -08008748 G.o_opt[OPT_O_NOEXEC] = state;
Denys Vlasenko6696eac2010-11-14 02:01:50 +01008749 break;
8750 case 'x':
8751 IF_HUSH_MODE_X(G_x_mode = state;)
8752 break;
8753 case 'o':
8754 if (!o_opt) {
8755 /* "set -+o" without parameter.
8756 * in bash, set -o produces this output:
8757 * pipefail off
8758 * and set +o:
8759 * set +o pipefail
8760 * We always use the second form.
8761 */
8762 const char *p = o_opt_strings;
8763 idx = 0;
8764 while (*p) {
8765 printf("set %co %s\n", (G.o_opt[idx] ? '-' : '+'), p);
8766 idx++;
8767 p += strlen(p) + 1;
8768 }
8769 break;
8770 }
8771 idx = index_in_strings(o_opt_strings, o_opt);
8772 if (idx >= 0) {
8773 G.o_opt[idx] = state;
8774 break;
8775 }
Denys Vlasenko9fda6092017-07-14 13:36:48 +02008776 case 'e':
8777 G.o_opt[OPT_O_ERREXIT] = state;
8778 break;
Denys Vlasenko6696eac2010-11-14 02:01:50 +01008779 default:
8780 return EXIT_FAILURE;
Denis Vlasenkod5762932009-03-31 11:22:57 +00008781 }
8782 return EXIT_SUCCESS;
8783}
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00008784
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00008785int hush_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Matt Kraai2d91deb2001-08-01 17:21:35 +00008786int hush_main(int argc, char **argv)
Eric Andersen25f27032001-04-26 23:22:31 +00008787{
Denys Vlasenkof58f7052011-05-12 02:10:33 +02008788 enum {
8789 OPT_login = (1 << 0),
8790 };
8791 unsigned flags;
Eric Andersen25f27032001-04-26 23:22:31 +00008792 int opt;
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02008793 unsigned builtin_argc;
Denis Vlasenkofbf6dea2007-04-13 19:56:56 +00008794 char **e;
Denis Vlasenkod76c0492007-05-25 02:16:25 +00008795 struct variable *cur_var;
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01008796 struct variable *shell_ver;
Eric Andersenbc604a22001-05-16 05:24:03 +00008797
Denis Vlasenko574f2f42008-02-27 18:41:59 +00008798 INIT_G();
Denys Vlasenko10c01312011-05-11 11:49:21 +02008799 if (EXIT_SUCCESS != 0) /* if EXIT_SUCCESS == 0, it is already done */
Denis Vlasenkoab2b0642009-04-06 18:42:11 +00008800 G.last_exitcode = EXIT_SUCCESS;
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02008801
Denys Vlasenko10c01312011-05-11 11:49:21 +02008802#if ENABLE_HUSH_FAST
8803 G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
8804#endif
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +00008805#if !BB_MMU
8806 G.argv0_for_re_execing = argv[0];
8807#endif
Denis Vlasenko0a83fc32007-05-25 11:12:32 +00008808 /* Deal with HUSH_VERSION */
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01008809 shell_ver = xzalloc(sizeof(*shell_ver));
8810 shell_ver->flg_export = 1;
8811 shell_ver->flg_read_only = 1;
Denys Vlasenko4f870492010-09-10 11:06:01 +02008812 /* Code which handles ${var<op>...} needs writable values for all variables,
Denys Vlasenko36f774a2010-09-05 14:45:38 +02008813 * therefore we xstrdup: */
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01008814 shell_ver->varstr = xstrdup(hush_version_str);
Denys Vlasenko605067b2010-09-06 12:10:51 +02008815 /* Create shell local variables from the values
8816 * currently living in the environment */
Denis Vlasenkof886fd22008-10-13 12:36:05 +00008817 debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION");
Denis Vlasenko0a83fc32007-05-25 11:12:32 +00008818 unsetenv("HUSH_VERSION"); /* in case it exists in initial env */
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01008819 G.top_var = shell_ver;
Denis Vlasenko87a86552008-07-29 19:43:10 +00008820 cur_var = G.top_var;
Denis Vlasenko0a83fc32007-05-25 11:12:32 +00008821 e = environ;
Denis Vlasenkod76c0492007-05-25 02:16:25 +00008822 if (e) while (*e) {
8823 char *value = strchr(*e, '=');
8824 if (value) { /* paranoia */
8825 cur_var->next = xzalloc(sizeof(*cur_var));
8826 cur_var = cur_var->next;
Denis Vlasenko28c0f0f2007-05-25 02:46:01 +00008827 cur_var->varstr = *e;
Denis Vlasenkod76c0492007-05-25 02:16:25 +00008828 cur_var->max_len = strlen(*e);
8829 cur_var->flg_export = 1;
8830 }
8831 e++;
8832 }
Denys Vlasenko605067b2010-09-06 12:10:51 +02008833 /* (Re)insert HUSH_VERSION into env (AFTER we scanned the env!) */
Denys Vlasenko75eb9d22010-12-21 21:18:12 +01008834 debug_printf_env("putenv '%s'\n", shell_ver->varstr);
8835 putenv(shell_ver->varstr);
Denys Vlasenko6db47842009-09-05 20:15:17 +02008836
8837 /* Export PWD */
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02008838 set_pwd_var(SETFLAG_EXPORT);
Denys Vlasenko3fa97af2014-04-15 11:43:29 +02008839
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01008840#if BASH_HOSTNAME_VAR
Denys Vlasenko3fa97af2014-04-15 11:43:29 +02008841 /* Set (but not export) HOSTNAME unless already set */
8842 if (!get_local_var_value("HOSTNAME")) {
8843 struct utsname uts;
8844 uname(&uts);
8845 set_local_var_from_halves("HOSTNAME", uts.nodename);
8846 }
Denys Vlasenko6db47842009-09-05 20:15:17 +02008847 /* bash also exports SHLVL and _,
8848 * and sets (but doesn't export) the following variables:
8849 * BASH=/bin/bash
8850 * BASH_VERSINFO=([0]="3" [1]="2" [2]="0" [3]="1" [4]="release" [5]="i386-pc-linux-gnu")
8851 * BASH_VERSION='3.2.0(1)-release'
8852 * HOSTTYPE=i386
8853 * MACHTYPE=i386-pc-linux-gnu
8854 * OSTYPE=linux-gnu
Denys Vlasenkodea47882009-10-09 15:40:49 +02008855 * PPID=<NNNNN> - we also do it elsewhere
Denys Vlasenko6db47842009-09-05 20:15:17 +02008856 * EUID=<NNNNN>
8857 * UID=<NNNNN>
8858 * GROUPS=()
8859 * LINES=<NNN>
8860 * COLUMNS=<NNN>
8861 * BASH_ARGC=()
8862 * BASH_ARGV=()
8863 * BASH_LINENO=()
8864 * BASH_SOURCE=()
8865 * DIRSTACK=()
8866 * PIPESTATUS=([0]="0")
8867 * HISTFILE=/<xxx>/.bash_history
8868 * HISTFILESIZE=500
8869 * HISTSIZE=500
8870 * MAILCHECK=60
8871 * PATH=/usr/gnu/bin:/usr/local/bin:/bin:/usr/bin:.
8872 * SHELL=/bin/bash
8873 * SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
8874 * TERM=dumb
8875 * OPTERR=1
8876 * OPTIND=1
8877 * IFS=$' \t\n'
8878 * PS1='\s-\v\$ '
8879 * PS2='> '
8880 * PS4='+ '
8881 */
Denys Vlasenko3fa97af2014-04-15 11:43:29 +02008882#endif
Denys Vlasenko6db47842009-09-05 20:15:17 +02008883
Denis Vlasenko38f63192007-01-22 09:03:07 +00008884#if ENABLE_FEATURE_EDITING
Denys Vlasenkoe45af7a2011-09-04 16:15:24 +02008885 G.line_input_state = new_line_input_t(FOR_SHELL);
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00008886#endif
Denys Vlasenko99862cb2010-09-12 17:34:13 +02008887
Eric Andersen94ac2442001-05-22 19:05:18 +00008888 /* Initialize some more globals to non-zero values */
Mike Frysinger67c1c7b2009-04-24 06:26:18 +00008889 cmdedit_update_prompt();
Denis Vlasenkoc8be5ee2007-05-17 15:38:46 +00008890
Denys Vlasenkoe9abe752016-08-19 20:15:26 +02008891 die_func = restore_ttypgrp_and__exit;
Denis Vlasenkoed782372009-04-10 00:45:02 +00008892
Denis Vlasenkoc4a7af52009-04-05 20:33:27 +00008893 /* Shell is non-interactive at first. We need to call
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02008894 * install_special_sighandlers() if we are going to execute "sh <script>",
Denis Vlasenkod3f973e2009-04-06 10:21:42 +00008895 * "sh -c <cmds>" or login shell's /etc/profile and friends.
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02008896 * If we later decide that we are interactive, we run install_special_sighandlers()
Denis Vlasenkoc4a7af52009-04-05 20:33:27 +00008897 * in order to intercept (more) signals.
8898 */
8899
8900 /* Parse options */
Mike Frysinger19a7ea12009-03-28 13:02:11 +00008901 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */
Denys Vlasenkof58f7052011-05-12 02:10:33 +02008902 flags = (argv[0] && argv[0][0] == '-') ? OPT_login : 0;
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02008903 builtin_argc = 0;
Denis Vlasenko0bb4a232009-04-05 01:42:59 +00008904 while (1) {
Denys Vlasenko9fda6092017-07-14 13:36:48 +02008905 opt = getopt(argc, argv, "+c:exinsl"
Denis Vlasenko0bb4a232009-04-05 01:42:59 +00008906#if !BB_MMU
Denis Vlasenkobc569742009-04-12 20:35:19 +00008907 "<:$:R:V:"
8908# if ENABLE_HUSH_FUNCTIONS
8909 "F:"
8910# endif
Denis Vlasenko0bb4a232009-04-05 01:42:59 +00008911#endif
8912 );
8913 if (opt <= 0)
8914 break;
Eric Andersen25f27032001-04-26 23:22:31 +00008915 switch (opt) {
Denis Vlasenkofbf6dea2007-04-13 19:56:56 +00008916 case 'c':
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02008917 /* Possibilities:
8918 * sh ... -c 'script'
8919 * sh ... -c 'script' ARG0 [ARG1...]
8920 * On NOMMU, if builtin_argc != 0,
Denys Vlasenko17323a62010-01-28 01:57:05 +01008921 * sh ... -c 'builtin' BARGV... "" ARG0 [ARG1...]
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02008922 * "" needs to be replaced with NULL
8923 * and BARGV vector fed to builtin function.
Denys Vlasenko17323a62010-01-28 01:57:05 +01008924 * Note: the form without ARG0 never happens:
8925 * sh ... -c 'builtin' BARGV... ""
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02008926 */
Denys Vlasenkodea47882009-10-09 15:40:49 +02008927 if (!G.root_pid) {
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +00008928 G.root_pid = getpid();
Denys Vlasenkodea47882009-10-09 15:40:49 +02008929 G.root_ppid = getppid();
8930 }
Denis Vlasenko87a86552008-07-29 19:43:10 +00008931 G.global_argv = argv + optind;
8932 G.global_argc = argc - optind;
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02008933 if (builtin_argc) {
8934 /* -c 'builtin' [BARGV...] "" ARG0 [ARG1...] */
8935 const struct built_in_command *x;
8936
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02008937 install_special_sighandlers();
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02008938 x = find_builtin(optarg);
8939 if (x) { /* paranoia */
8940 G.global_argc -= builtin_argc; /* skip [BARGV...] "" */
8941 G.global_argv += builtin_argc;
8942 G.global_argv[-1] = NULL; /* replace "" */
Denys Vlasenko8ee2ada2011-02-07 02:03:51 +01008943 fflush_all();
Denys Vlasenko17323a62010-01-28 01:57:05 +01008944 G.last_exitcode = x->b_function(argv + optind - 1);
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02008945 }
8946 goto final_return;
8947 }
8948 if (!G.global_argv[0]) {
8949 /* -c 'script' (no params): prevent empty $0 */
8950 G.global_argv--; /* points to argv[i] of 'script' */
8951 G.global_argv[0] = argv[0];
Denys Vlasenko5ae8f1c2010-05-22 06:32:11 +02008952 G.global_argc++;
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02008953 } /* else -c 'script' ARG0 [ARG1...]: $0 is ARG0 */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02008954 install_special_sighandlers();
Denis Vlasenkob6e65562009-04-03 16:49:04 +00008955 parse_and_run_string(optarg);
Denis Vlasenkofbf6dea2007-04-13 19:56:56 +00008956 goto final_return;
8957 case 'i':
Denis Vlasenkoc666f712007-05-16 22:18:54 +00008958 /* Well, we cannot just declare interactiveness,
8959 * we have to have some stuff (ctty, etc) */
Denis Vlasenko60b392f2009-04-03 19:14:32 +00008960 /* G_interactive_fd++; */
Denis Vlasenkofbf6dea2007-04-13 19:56:56 +00008961 break;
Mike Frysinger19a7ea12009-03-28 13:02:11 +00008962 case 's':
8963 /* "-s" means "read from stdin", but this is how we always
8964 * operate, so simply do nothing here. */
8965 break;
Denys Vlasenkof58f7052011-05-12 02:10:33 +02008966 case 'l':
8967 flags |= OPT_login;
8968 break;
Denis Vlasenko0bb4a232009-04-05 01:42:59 +00008969#if !BB_MMU
Denis Vlasenko50f3aa42009-04-07 10:52:40 +00008970 case '<': /* "big heredoc" support */
Denys Vlasenko729ecb82010-06-07 14:14:26 +02008971 full_write1_str(optarg);
Denis Vlasenko50f3aa42009-04-07 10:52:40 +00008972 _exit(0);
Denys Vlasenkoe89a2412010-01-12 15:19:31 +01008973 case '$': {
8974 unsigned long long empty_trap_mask;
8975
Denis Vlasenko34e573d2009-04-06 12:56:28 +00008976 G.root_pid = bb_strtou(optarg, &optarg, 16);
8977 optarg++;
Denys Vlasenkodea47882009-10-09 15:40:49 +02008978 G.root_ppid = bb_strtou(optarg, &optarg, 16);
8979 optarg++;
Denis Vlasenko34e573d2009-04-06 12:56:28 +00008980 G.last_bg_pid = bb_strtou(optarg, &optarg, 16);
8981 optarg++;
Denis Vlasenkoab2b0642009-04-06 18:42:11 +00008982 G.last_exitcode = bb_strtou(optarg, &optarg, 16);
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02008983 optarg++;
8984 builtin_argc = bb_strtou(optarg, &optarg, 16);
Denys Vlasenkoe89a2412010-01-12 15:19:31 +01008985 optarg++;
8986 empty_trap_mask = bb_strtoull(optarg, &optarg, 16);
8987 if (empty_trap_mask != 0) {
Denys Vlasenko4ee824f2017-07-03 01:22:13 +02008988 IF_HUSH_TRAP(int sig;)
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02008989 install_special_sighandlers();
Denys Vlasenko4ee824f2017-07-03 01:22:13 +02008990# if ENABLE_HUSH_TRAP
Denys Vlasenko7a85c602017-01-08 17:40:18 +01008991 G_traps = xzalloc(sizeof(G_traps[0]) * NSIG);
Denys Vlasenkoe89a2412010-01-12 15:19:31 +01008992 for (sig = 1; sig < NSIG; sig++) {
8993 if (empty_trap_mask & (1LL << sig)) {
Denys Vlasenko7a85c602017-01-08 17:40:18 +01008994 G_traps[sig] = xzalloc(1); /* == xstrdup(""); */
Denys Vlasenko0806e402011-05-12 23:06:20 +02008995 install_sighandler(sig, SIG_IGN);
Denys Vlasenkoe89a2412010-01-12 15:19:31 +01008996 }
8997 }
Denys Vlasenko4ee824f2017-07-03 01:22:13 +02008998# endif
Denys Vlasenkoe89a2412010-01-12 15:19:31 +01008999 }
Denis Vlasenkod3f973e2009-04-06 10:21:42 +00009000# if ENABLE_HUSH_LOOPS
Denis Vlasenko34e573d2009-04-06 12:56:28 +00009001 optarg++;
9002 G.depth_of_loop = bb_strtou(optarg, &optarg, 16);
Denis Vlasenkod3f973e2009-04-06 10:21:42 +00009003# endif
Denis Vlasenko34e573d2009-04-06 12:56:28 +00009004 break;
Denys Vlasenkoe89a2412010-01-12 15:19:31 +01009005 }
Denis Vlasenko0bb4a232009-04-05 01:42:59 +00009006 case 'R':
9007 case 'V':
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02009008 set_local_var(xstrdup(optarg), opt == 'R' ? SETFLAG_MAKE_RO : 0);
Denis Vlasenko0bb4a232009-04-05 01:42:59 +00009009 break;
Denis Vlasenkobc569742009-04-12 20:35:19 +00009010# if ENABLE_HUSH_FUNCTIONS
9011 case 'F': {
9012 struct function *funcp = new_function(optarg);
9013 /* funcp->name is already set to optarg */
9014 /* funcp->body is set to NULL. It's a special case. */
9015 funcp->body_as_string = argv[optind];
9016 optind++;
9017 break;
9018 }
9019# endif
Denis Vlasenko0bb4a232009-04-05 01:42:59 +00009020#endif
Mike Frysingerad88d5a2009-03-28 13:44:51 +00009021 case 'n':
9022 case 'x':
Denys Vlasenko9fda6092017-07-14 13:36:48 +02009023 case 'e':
Denys Vlasenko6696eac2010-11-14 02:01:50 +01009024 if (set_mode(1, opt, NULL) == 0) /* no error */
Mike Frysingerad88d5a2009-03-28 13:44:51 +00009025 break;
Denis Vlasenkofbf6dea2007-04-13 19:56:56 +00009026 default:
Eric Andersen9ffb7dd2001-05-19 03:00:46 +00009027#ifndef BB_VER
Denis Vlasenkofbf6dea2007-04-13 19:56:56 +00009028 fprintf(stderr, "Usage: sh [FILE]...\n"
9029 " or: sh -c command [args]...\n\n");
9030 exit(EXIT_FAILURE);
Eric Andersen9ffb7dd2001-05-19 03:00:46 +00009031#else
Denis Vlasenkofbf6dea2007-04-13 19:56:56 +00009032 bb_show_usage();
Eric Andersen9ffb7dd2001-05-19 03:00:46 +00009033#endif
Eric Andersen25f27032001-04-26 23:22:31 +00009034 }
Denis Vlasenkof9375282009-04-05 19:13:39 +00009035 } /* option parsing loop */
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +00009036
Denys Vlasenkof58f7052011-05-12 02:10:33 +02009037 /* Skip options. Try "hush -l": $1 should not be "-l"! */
9038 G.global_argc = argc - (optind - 1);
9039 G.global_argv = argv + (optind - 1);
9040 G.global_argv[0] = argv[0];
9041
Denys Vlasenkodea47882009-10-09 15:40:49 +02009042 if (!G.root_pid) {
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +00009043 G.root_pid = getpid();
Denys Vlasenkodea47882009-10-09 15:40:49 +02009044 G.root_ppid = getppid();
9045 }
Denis Vlasenkof9375282009-04-05 19:13:39 +00009046
9047 /* If we are login shell... */
Denys Vlasenkof58f7052011-05-12 02:10:33 +02009048 if (flags & OPT_login) {
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +00009049 FILE *input;
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +00009050 debug_printf("sourcing /etc/profile\n");
9051 input = fopen_for_read("/etc/profile");
9052 if (input != NULL) {
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02009053 remember_FILE(input);
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009054 install_special_sighandlers();
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +00009055 parse_and_run_file(input);
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02009056 fclose_and_forget(input);
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +00009057 }
Denis Vlasenkof9375282009-04-05 19:13:39 +00009058 /* bash: after sourcing /etc/profile,
9059 * tries to source (in the given order):
9060 * ~/.bash_profile, ~/.bash_login, ~/.profile,
Denys Vlasenko28a105d2009-06-01 11:26:30 +02009061 * stopping on first found. --noprofile turns this off.
Denis Vlasenkof9375282009-04-05 19:13:39 +00009062 * bash also sources ~/.bash_logout on exit.
9063 * If called as sh, skips .bash_XXX files.
9064 */
Denis Vlasenko46f9b6d2009-04-05 10:39:03 +00009065 }
9066
Denys Vlasenkof58f7052011-05-12 02:10:33 +02009067 if (G.global_argv[1]) {
Denis Vlasenkof9375282009-04-05 19:13:39 +00009068 FILE *input;
9069 /*
Denis Vlasenkod3f973e2009-04-06 10:21:42 +00009070 * "bash <script>" (which is never interactive (unless -i?))
9071 * sources $BASH_ENV here (without scanning $PATH).
Denis Vlasenkof9375282009-04-05 19:13:39 +00009072 * If called as sh, does the same but with $ENV.
Denys Vlasenko2eb0a7e2016-10-27 11:28:59 +02009073 * Also NB, per POSIX, $ENV should undergo parameter expansion.
Denis Vlasenkof9375282009-04-05 19:13:39 +00009074 */
Denys Vlasenkof58f7052011-05-12 02:10:33 +02009075 G.global_argc--;
9076 G.global_argv++;
9077 debug_printf("running script '%s'\n", G.global_argv[0]);
Denys Vlasenkob7adf7a2016-10-25 17:00:13 +02009078 xfunc_error_retval = 127; /* for "hush /does/not/exist" case */
Denys Vlasenkof58f7052011-05-12 02:10:33 +02009079 input = xfopen_for_read(G.global_argv[0]);
Denys Vlasenkob7adf7a2016-10-25 17:00:13 +02009080 xfunc_error_retval = 1;
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02009081 remember_FILE(input);
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009082 install_special_sighandlers();
Denis Vlasenkof9375282009-04-05 19:13:39 +00009083 parse_and_run_file(input);
9084#if ENABLE_FEATURE_CLEAN_UP
Denys Vlasenko7b25b1c2016-08-20 15:58:34 +02009085 fclose_and_forget(input);
Denis Vlasenkof9375282009-04-05 19:13:39 +00009086#endif
9087 goto final_return;
9088 }
9089
Denis Vlasenkoc4a7af52009-04-05 20:33:27 +00009090 /* Up to here, shell was non-interactive. Now it may become one.
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009091 * NB: don't forget to (re)run install_special_sighandlers() as needed.
Denis Vlasenkoc4a7af52009-04-05 20:33:27 +00009092 */
Denis Vlasenkof9375282009-04-05 19:13:39 +00009093
Denys Vlasenko28a105d2009-06-01 11:26:30 +02009094 /* A shell is interactive if the '-i' flag was given,
9095 * or if all of the following conditions are met:
Denis Vlasenko55b2de72007-04-18 17:21:28 +00009096 * no -c command
Eric Andersen25f27032001-04-26 23:22:31 +00009097 * no arguments remaining or the -s flag given
9098 * standard input is a terminal
9099 * standard output is a terminal
Denis Vlasenkof9375282009-04-05 19:13:39 +00009100 * Refer to Posix.2, the description of the 'sh' utility.
9101 */
9102#if ENABLE_HUSH_JOB
9103 if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
Mike Frysinger38478a62009-05-20 04:48:06 -04009104 G_saved_tty_pgrp = tcgetpgrp(STDIN_FILENO);
9105 debug_printf("saved_tty_pgrp:%d\n", G_saved_tty_pgrp);
9106 if (G_saved_tty_pgrp < 0)
9107 G_saved_tty_pgrp = 0;
Denis Vlasenkoc8653f62009-04-27 23:29:14 +00009108
9109 /* try to dup stdin to high fd#, >= 255 */
Denys Vlasenko2db74612017-07-07 22:07:28 +02009110 G_interactive_fd = fcntl_F_DUPFD(STDIN_FILENO, 254);
Denis Vlasenkoc8653f62009-04-27 23:29:14 +00009111 if (G_interactive_fd < 0) {
9112 /* try to dup to any fd */
9113 G_interactive_fd = dup(STDIN_FILENO);
Denis Vlasenko60b392f2009-04-03 19:14:32 +00009114 if (G_interactive_fd < 0) {
Denis Vlasenkoc8653f62009-04-27 23:29:14 +00009115 /* give up */
9116 G_interactive_fd = 0;
Mike Frysinger38478a62009-05-20 04:48:06 -04009117 G_saved_tty_pgrp = 0;
Denis Vlasenko54e7ffb2007-04-21 00:03:36 +00009118 }
9119 }
Denis Vlasenkoc8653f62009-04-27 23:29:14 +00009120// TODO: track & disallow any attempts of user
9121// to (inadvertently) close/redirect G_interactive_fd
Eric Andersen25f27032001-04-26 23:22:31 +00009122 }
Denis Vlasenkof9375282009-04-05 19:13:39 +00009123 debug_printf("interactive_fd:%d\n", G_interactive_fd);
Denis Vlasenko60b392f2009-04-03 19:14:32 +00009124 if (G_interactive_fd) {
Denis Vlasenkof9375282009-04-05 19:13:39 +00009125 close_on_exec_on(G_interactive_fd);
Denis Vlasenkoc8653f62009-04-27 23:29:14 +00009126
Mike Frysinger38478a62009-05-20 04:48:06 -04009127 if (G_saved_tty_pgrp) {
Denis Vlasenkoc8653f62009-04-27 23:29:14 +00009128 /* If we were run as 'hush &', sleep until we are
9129 * in the foreground (tty pgrp == our pgrp).
9130 * If we get started under a job aware app (like bash),
9131 * make sure we are now in charge so we don't fight over
9132 * who gets the foreground */
9133 while (1) {
9134 pid_t shell_pgrp = getpgrp();
Mike Frysinger38478a62009-05-20 04:48:06 -04009135 G_saved_tty_pgrp = tcgetpgrp(G_interactive_fd);
9136 if (G_saved_tty_pgrp == shell_pgrp)
Denis Vlasenkoc8653f62009-04-27 23:29:14 +00009137 break;
9138 /* send TTIN to ourself (should stop us) */
9139 kill(- shell_pgrp, SIGTTIN);
9140 }
Denis Vlasenkof9375282009-04-05 19:13:39 +00009141 }
Denis Vlasenkoc8653f62009-04-27 23:29:14 +00009142
Denys Vlasenkof58f7052011-05-12 02:10:33 +02009143 /* Install more signal handlers */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009144 install_special_sighandlers();
Denis Vlasenkoc8653f62009-04-27 23:29:14 +00009145
Mike Frysinger38478a62009-05-20 04:48:06 -04009146 if (G_saved_tty_pgrp) {
Denis Vlasenkoc8653f62009-04-27 23:29:14 +00009147 /* Set other signals to restore saved_tty_pgrp */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009148 install_fatal_sighandlers();
Denis Vlasenkoc8653f62009-04-27 23:29:14 +00009149 /* Put ourselves in our own process group
9150 * (bash, too, does this only if ctty is available) */
9151 bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */
9152 /* Grab control of the terminal */
9153 tcsetpgrp(G_interactive_fd, getpid());
9154 }
Denys Vlasenko550bf5b2015-10-09 16:42:57 +02009155 enable_restore_tty_pgrp_on_exit();
Denys Vlasenko4840ae82011-09-04 15:28:03 +02009156
9157# if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0
9158 {
9159 const char *hp = get_local_var_value("HISTFILE");
9160 if (!hp) {
9161 hp = get_local_var_value("HOME");
9162 if (hp)
9163 hp = concat_path_file(hp, ".hush_history");
9164 } else {
9165 hp = xstrdup(hp);
9166 }
9167 if (hp) {
9168 G.line_input_state->hist_file = hp;
Denys Vlasenko4840ae82011-09-04 15:28:03 +02009169 //set_local_var(xasprintf("HISTFILE=%s", ...));
9170 }
9171# if ENABLE_FEATURE_SH_HISTFILESIZE
9172 hp = get_local_var_value("HISTFILESIZE");
9173 G.line_input_state->max_history = size_from_HISTFILESIZE(hp);
9174# endif
9175 }
9176# endif
Denys Vlasenkoe89a2412010-01-12 15:19:31 +01009177 } else {
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009178 install_special_sighandlers();
Denys Vlasenkoe89a2412010-01-12 15:19:31 +01009179 }
Denis Vlasenkoe3f2f892007-04-28 16:48:27 +00009180#elif ENABLE_HUSH_INTERACTIVE
Denis Vlasenkof9375282009-04-05 19:13:39 +00009181 /* No job control compiled in, only prompt/line editing */
9182 if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
Denys Vlasenko2db74612017-07-07 22:07:28 +02009183 G_interactive_fd = fcntl_F_DUPFD(STDIN_FILENO, 254);
Denis Vlasenko60b392f2009-04-03 19:14:32 +00009184 if (G_interactive_fd < 0) {
Denis Vlasenkoe3f2f892007-04-28 16:48:27 +00009185 /* try to dup to any fd */
Denis Vlasenko60b392f2009-04-03 19:14:32 +00009186 G_interactive_fd = dup(STDIN_FILENO);
9187 if (G_interactive_fd < 0)
Denis Vlasenkoe3f2f892007-04-28 16:48:27 +00009188 /* give up */
Denis Vlasenko60b392f2009-04-03 19:14:32 +00009189 G_interactive_fd = 0;
Denis Vlasenkoe3f2f892007-04-28 16:48:27 +00009190 }
9191 }
Denis Vlasenko60b392f2009-04-03 19:14:32 +00009192 if (G_interactive_fd) {
Denis Vlasenkof9375282009-04-05 19:13:39 +00009193 close_on_exec_on(G_interactive_fd);
Denis Vlasenkof9375282009-04-05 19:13:39 +00009194 }
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009195 install_special_sighandlers();
Denis Vlasenkof9375282009-04-05 19:13:39 +00009196#else
9197 /* We have interactiveness code disabled */
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009198 install_special_sighandlers();
Denis Vlasenkof9375282009-04-05 19:13:39 +00009199#endif
9200 /* bash:
9201 * if interactive but not a login shell, sources ~/.bashrc
9202 * (--norc turns this off, --rcfile <file> overrides)
9203 */
9204
9205 if (!ENABLE_FEATURE_SH_EXTRA_QUIET && G_interactive_fd) {
Denys Vlasenkoc34c0332009-09-29 12:25:30 +02009206 /* note: ash and hush share this string */
9207 printf("\n\n%s %s\n"
9208 IF_HUSH_HELP("Enter 'help' for a list of built-in commands.\n")
9209 "\n",
9210 bb_banner,
9211 "hush - the humble shell"
9212 );
Mike Frysingerb2705e12009-03-23 08:44:02 +00009213 }
9214
Denis Vlasenkof9375282009-04-05 19:13:39 +00009215 parse_and_run_file(stdin);
Eric Andersen25f27032001-04-26 23:22:31 +00009216
Denis Vlasenkod76c0492007-05-25 02:16:25 +00009217 final_return:
Denis Vlasenkoab2b0642009-04-06 18:42:11 +00009218 hush_exit(G.last_exitcode);
Eric Andersen25f27032001-04-26 23:22:31 +00009219}
Denis Vlasenko96702ca2007-11-23 23:28:55 +00009220
9221
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009222/*
9223 * Built-ins
9224 */
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02009225static int FAST_FUNC builtin_true(char **argv UNUSED_PARAM)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009226{
9227 return 0;
9228}
9229
Denys Vlasenko265062d2017-01-10 15:13:30 +01009230#if ENABLE_HUSH_TEST || ENABLE_HUSH_ECHO || ENABLE_HUSH_PRINTF || ENABLE_HUSH_KILL
Denys Vlasenko8bc7f2c2009-10-19 13:20:52 +02009231static int run_applet_main(char **argv, int (*applet_main_func)(int argc, char **argv))
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009232{
Denys Vlasenkod4e4fdb2017-07-03 21:31:16 +02009233 int argc = string_array_len(argv);
9234 return applet_main_func(argc, argv);
Mike Frysingerccb19592009-10-15 03:31:15 -04009235}
Denys Vlasenko265062d2017-01-10 15:13:30 +01009236#endif
Kang-Che Sung027d3ab2017-01-11 14:18:15 +01009237#if ENABLE_HUSH_TEST || BASH_TEST2
Mike Frysingerccb19592009-10-15 03:31:15 -04009238static int FAST_FUNC builtin_test(char **argv)
9239{
Denys Vlasenkoc0836532009-10-19 13:13:06 +02009240 return run_applet_main(argv, test_main);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009241}
Denys Vlasenko265062d2017-01-10 15:13:30 +01009242#endif
Denys Vlasenko1cc68042017-01-09 17:10:04 +01009243#if ENABLE_HUSH_ECHO
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02009244static int FAST_FUNC builtin_echo(char **argv)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009245{
Denys Vlasenkoc0836532009-10-19 13:13:06 +02009246 return run_applet_main(argv, echo_main);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009247}
Denys Vlasenko1cc68042017-01-09 17:10:04 +01009248#endif
Denys Vlasenko1125d7d2017-01-08 17:19:38 +01009249#if ENABLE_HUSH_PRINTF
Mike Frysinger4ebc76c2009-10-15 03:32:39 -04009250static int FAST_FUNC builtin_printf(char **argv)
9251{
Denys Vlasenkoc0836532009-10-19 13:13:06 +02009252 return run_applet_main(argv, printf_main);
Mike Frysinger4ebc76c2009-10-15 03:32:39 -04009253}
9254#endif
9255
Denys Vlasenkoa1184af2017-01-10 15:58:02 +01009256#if ENABLE_HUSH_HELP
9257static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM)
9258{
9259 const struct built_in_command *x;
9260
9261 printf(
9262 "Built-in commands:\n"
9263 "------------------\n");
9264 for (x = bltins1; x != &bltins1[ARRAY_SIZE(bltins1)]; x++) {
9265 if (x->b_descr)
9266 printf("%-10s%s\n", x->b_cmd, x->b_descr);
9267 }
9268 return EXIT_SUCCESS;
9269}
9270#endif
9271
9272#if MAX_HISTORY && ENABLE_FEATURE_EDITING
9273static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM)
9274{
9275 show_history(G.line_input_state);
9276 return EXIT_SUCCESS;
9277}
9278#endif
9279
Denys Vlasenkob131cce2010-05-20 03:39:43 +02009280static char **skip_dash_dash(char **argv)
9281{
9282 argv++;
9283 if (argv[0] && argv[0][0] == '-' && argv[0][1] == '-' && argv[0][2] == '\0')
9284 argv++;
9285 return argv;
9286}
9287
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02009288static int FAST_FUNC builtin_cd(char **argv)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009289{
Denys Vlasenkob131cce2010-05-20 03:39:43 +02009290 const char *newdir;
9291
9292 argv = skip_dash_dash(argv);
9293 newdir = argv[0];
Denis Vlasenkobfbc9712009-04-06 12:04:42 +00009294 if (newdir == NULL) {
Denis Vlasenkob6e65562009-04-03 16:49:04 +00009295 /* bash does nothing (exitcode 0) if HOME is ""; if it's unset,
Denis Vlasenko0b677d82009-04-10 13:49:10 +00009296 * bash says "bash: cd: HOME not set" and does nothing
9297 * (exitcode 1)
Denis Vlasenkob6e65562009-04-03 16:49:04 +00009298 */
Denys Vlasenko90a99042009-09-06 02:36:23 +02009299 const char *home = get_local_var_value("HOME");
9300 newdir = home ? home : "/";
Denis Vlasenkob0a64782009-04-06 11:33:07 +00009301 }
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009302 if (chdir(newdir)) {
Denis Vlasenkobfbc9712009-04-06 12:04:42 +00009303 /* Mimic bash message exactly */
9304 bb_perror_msg("cd: %s", newdir);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009305 return EXIT_FAILURE;
9306 }
Denys Vlasenko6db47842009-09-05 20:15:17 +02009307 /* Read current dir (get_cwd(1) is inside) and set PWD.
9308 * Note: do not enforce exporting. If PWD was unset or unexported,
9309 * set it again, but do not export. bash does the same.
9310 */
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02009311 set_pwd_var(/*flag:*/ 0);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009312 return EXIT_SUCCESS;
9313}
9314
Denys Vlasenkoa1184af2017-01-10 15:58:02 +01009315static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM)
9316{
9317 puts(get_cwd(0));
9318 return EXIT_SUCCESS;
9319}
9320
9321static int FAST_FUNC builtin_eval(char **argv)
9322{
9323 int rcode = EXIT_SUCCESS;
9324
9325 argv = skip_dash_dash(argv);
9326 if (*argv) {
9327 char *str = expand_strvec_to_string(argv);
9328 /* bash:
9329 * eval "echo Hi; done" ("done" is syntax error):
9330 * "echo Hi" will not execute too.
9331 */
9332 parse_and_run_string(str);
9333 free(str);
9334 rcode = G.last_exitcode;
9335 }
9336 return rcode;
9337}
9338
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02009339static int FAST_FUNC builtin_exec(char **argv)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009340{
Denys Vlasenkob131cce2010-05-20 03:39:43 +02009341 argv = skip_dash_dash(argv);
9342 if (argv[0] == NULL)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009343 return EXIT_SUCCESS; /* bash does this */
Denys Vlasenkof37eb392009-10-18 11:46:35 +02009344
Denys Vlasenkof37eb392009-10-18 11:46:35 +02009345 /* Careful: we can end up here after [v]fork. Do not restore
9346 * tty pgrp then, only top-level shell process does that */
9347 if (G_saved_tty_pgrp && getpid() == G.root_pid)
9348 tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp);
9349
Denys Vlasenko5b3d2eb2017-07-31 18:02:28 +02009350 /* Saved-redirect fds, script fds and G_interactive_fd are still
9351 * open here. However, they are all CLOEXEC, and execv below
9352 * closes them. Try interactive "exec ls -l /proc/self/fd",
9353 * it should show no extra open fds in the "ls" process.
9354 * If we'd try to run builtins/NOEXECs, this would need improving.
9355 */
9356 //close_saved_fds_and_FILE_fds();
9357
Denys Vlasenko3ef4f772009-10-19 23:09:06 +02009358 /* TODO: if exec fails, bash does NOT exit! We do.
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +02009359 * We'll need to undo trap cleanup (it's inside execvp_or_die)
Denys Vlasenko3ef4f772009-10-19 23:09:06 +02009360 * and tcsetpgrp, and this is inherently racy.
9361 */
9362 execvp_or_die(argv);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009363}
9364
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02009365static int FAST_FUNC builtin_exit(char **argv)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009366{
Denis Vlasenkocd418a22009-04-06 18:08:35 +00009367 debug_printf_exec("%s()\n", __func__);
Denis Vlasenko40e84372009-04-18 11:23:38 +00009368
9369 /* interactive bash:
9370 * # trap "echo EEE" EXIT
9371 * # exit
9372 * exit
9373 * There are stopped jobs.
9374 * (if there are _stopped_ jobs, running ones don't count)
9375 * # exit
9376 * exit
Denys Vlasenko6830ade2013-01-15 13:58:01 +01009377 * EEE (then bash exits)
Denis Vlasenko40e84372009-04-18 11:23:38 +00009378 *
Denys Vlasenkoa110c902010-09-12 15:38:04 +02009379 * TODO: we can use G.exiting = -1 as indicator "last cmd was exit"
Denis Vlasenko40e84372009-04-18 11:23:38 +00009380 */
Denis Vlasenkoefea9d22009-04-09 13:43:11 +00009381
9382 /* note: EXIT trap is run by hush_exit */
Denys Vlasenkob131cce2010-05-20 03:39:43 +02009383 argv = skip_dash_dash(argv);
9384 if (argv[0] == NULL)
Denis Vlasenkoab2b0642009-04-06 18:42:11 +00009385 hush_exit(G.last_exitcode);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009386 /* mimic bash: exit 123abc == exit 255 + error msg */
9387 xfunc_error_retval = 255;
9388 /* bash: exit -2 == exit 254, no error msg */
Denys Vlasenkob131cce2010-05-20 03:39:43 +02009389 hush_exit(xatoi(argv[0]) & 0xff);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009390}
9391
Denys Vlasenkoa1184af2017-01-10 15:58:02 +01009392#if ENABLE_HUSH_TYPE
9393/* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */
9394static int FAST_FUNC builtin_type(char **argv)
9395{
9396 int ret = EXIT_SUCCESS;
9397
9398 while (*++argv) {
9399 const char *type;
9400 char *path = NULL;
9401
9402 if (0) {} /* make conditional compile easier below */
9403 /*else if (find_alias(*argv))
9404 type = "an alias";*/
9405#if ENABLE_HUSH_FUNCTIONS
9406 else if (find_function(*argv))
9407 type = "a function";
9408#endif
9409 else if (find_builtin(*argv))
9410 type = "a shell builtin";
9411 else if ((path = find_in_path(*argv)) != NULL)
9412 type = path;
9413 else {
9414 bb_error_msg("type: %s: not found", *argv);
9415 ret = EXIT_FAILURE;
9416 continue;
9417 }
9418
9419 printf("%s is %s\n", *argv, type);
9420 free(path);
9421 }
9422
9423 return ret;
9424}
9425#endif
9426
9427#if ENABLE_HUSH_READ
9428/* Interruptibility of read builtin in bash
9429 * (tested on bash-4.2.8 by sending signals (not by ^C)):
9430 *
9431 * Empty trap makes read ignore corresponding signal, for any signal.
9432 *
9433 * SIGINT:
9434 * - terminates non-interactive shell;
9435 * - interrupts read in interactive shell;
9436 * if it has non-empty trap:
9437 * - executes trap and returns to command prompt in interactive shell;
9438 * - executes trap and returns to read in non-interactive shell;
9439 * SIGTERM:
9440 * - is ignored (does not interrupt) read in interactive shell;
9441 * - terminates non-interactive shell;
9442 * if it has non-empty trap:
9443 * - executes trap and returns to read;
9444 * SIGHUP:
9445 * - terminates shell (regardless of interactivity);
9446 * if it has non-empty trap:
9447 * - executes trap and returns to read;
Denys Vlasenkof5470412017-05-22 19:34:45 +02009448 * SIGCHLD from children:
9449 * - does not interrupt read regardless of interactivity:
9450 * try: sleep 1 & read x; echo $x
Denys Vlasenkoa1184af2017-01-10 15:58:02 +01009451 */
9452static int FAST_FUNC builtin_read(char **argv)
9453{
9454 const char *r;
9455 char *opt_n = NULL;
9456 char *opt_p = NULL;
9457 char *opt_t = NULL;
9458 char *opt_u = NULL;
Denys Vlasenko1f41c882017-08-09 13:52:36 +02009459 char *opt_d = NULL; /* optimized out if !BASH */
Denys Vlasenkoa1184af2017-01-10 15:58:02 +01009460 const char *ifs;
9461 int read_flags;
9462
9463 /* "!": do not abort on errors.
9464 * Option string must start with "sr" to match BUILTIN_READ_xxx
9465 */
Denys Vlasenko1f41c882017-08-09 13:52:36 +02009466 read_flags = getopt32(argv,
9467#if BASH_READ_D
9468 "!srn:p:t:u:d:", &opt_n, &opt_p, &opt_t, &opt_u, &opt_d
9469#else
9470 "!srn:p:t:u:", &opt_n, &opt_p, &opt_t, &opt_u
9471#endif
9472 );
Denys Vlasenkoa1184af2017-01-10 15:58:02 +01009473 if (read_flags == (uint32_t)-1)
9474 return EXIT_FAILURE;
9475 argv += optind;
9476 ifs = get_local_var_value("IFS"); /* can be NULL */
9477
9478 again:
9479 r = shell_builtin_read(set_local_var_from_halves,
9480 argv,
9481 ifs,
9482 read_flags,
9483 opt_n,
9484 opt_p,
9485 opt_t,
Denys Vlasenko1f41c882017-08-09 13:52:36 +02009486 opt_u,
9487 opt_d
Denys Vlasenkoa1184af2017-01-10 15:58:02 +01009488 );
9489
9490 if ((uintptr_t)r == 1 && errno == EINTR) {
9491 unsigned sig = check_and_run_traps();
Denys Vlasenkof5470412017-05-22 19:34:45 +02009492 if (sig != SIGINT)
Denys Vlasenkoa1184af2017-01-10 15:58:02 +01009493 goto again;
9494 }
9495
9496 if ((uintptr_t)r > 1) {
9497 bb_error_msg("%s", r);
9498 r = (char*)(uintptr_t)1;
9499 }
9500
9501 return (uintptr_t)r;
9502}
9503#endif
9504
9505#if ENABLE_HUSH_UMASK
9506static int FAST_FUNC builtin_umask(char **argv)
9507{
9508 int rc;
9509 mode_t mask;
9510
9511 rc = 1;
9512 mask = umask(0);
9513 argv = skip_dash_dash(argv);
9514 if (argv[0]) {
9515 mode_t old_mask = mask;
9516
9517 /* numeric umasks are taken as-is */
9518 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
9519 if (!isdigit(argv[0][0]))
9520 mask ^= 0777;
9521 mask = bb_parse_mode(argv[0], mask);
9522 if (!isdigit(argv[0][0]))
9523 mask ^= 0777;
9524 if ((unsigned)mask > 0777) {
9525 mask = old_mask;
9526 /* bash messages:
9527 * bash: umask: 'q': invalid symbolic mode operator
9528 * bash: umask: 999: octal number out of range
9529 */
9530 bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]);
9531 rc = 0;
9532 }
9533 } else {
9534 /* Mimic bash */
9535 printf("%04o\n", (unsigned) mask);
9536 /* fall through and restore mask which we set to 0 */
9537 }
9538 umask(mask);
9539
9540 return !rc; /* rc != 0 - success */
9541}
9542#endif
9543
Denys Vlasenko41ade052017-01-08 18:56:24 +01009544#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_TRAP
Denis Vlasenko38e626d2009-04-18 12:58:19 +00009545static void print_escaped(const char *s)
9546{
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02009547 if (*s == '\'')
9548 goto squote;
Denis Vlasenko38e626d2009-04-18 12:58:19 +00009549 do {
Denys Vlasenkod6b05eb2009-06-06 20:59:55 +02009550 const char *p = strchrnul(s, '\'');
9551 /* print 'xxxx', possibly just '' */
9552 printf("'%.*s'", (int)(p - s), s);
9553 if (*p == '\0')
9554 break;
9555 s = p;
9556 squote:
Denis Vlasenko38e626d2009-04-18 12:58:19 +00009557 /* s points to '; print "'''...'''" */
9558 putchar('"');
9559 do putchar('\''); while (*++s == '\'');
9560 putchar('"');
9561 } while (*s);
9562}
Denys Vlasenko41ade052017-01-08 18:56:24 +01009563#endif
Denis Vlasenko38e626d2009-04-18 12:58:19 +00009564
Denys Vlasenko1e660422017-07-17 21:10:50 +02009565#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_LOCAL || ENABLE_HUSH_READONLY
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02009566static int helper_export_local(char **argv, unsigned flags)
Denys Vlasenko295fef82009-06-03 12:47:26 +02009567{
9568 do {
9569 char *name = *argv;
Denys Vlasenko27c56f12010-09-07 09:56:34 +02009570 char *name_end = strchrnul(name, '=');
Denys Vlasenko295fef82009-06-03 12:47:26 +02009571
9572 /* So far we do not check that name is valid (TODO?) */
9573
Denys Vlasenko27c56f12010-09-07 09:56:34 +02009574 if (*name_end == '\0') {
9575 struct variable *var, **vpp;
Denys Vlasenko295fef82009-06-03 12:47:26 +02009576
Denys Vlasenko27c56f12010-09-07 09:56:34 +02009577 vpp = get_ptr_to_local_var(name, name_end - name);
9578 var = vpp ? *vpp : NULL;
9579
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02009580 if (flags & SETFLAG_UNEXPORT) {
Denys Vlasenko295fef82009-06-03 12:47:26 +02009581 /* export -n NAME (without =VALUE) */
9582 if (var) {
9583 var->flg_export = 0;
9584 debug_printf_env("%s: unsetenv '%s'\n", __func__, name);
9585 unsetenv(name);
9586 } /* else: export -n NOT_EXISTING_VAR: no-op */
9587 continue;
9588 }
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02009589 if (flags & SETFLAG_EXPORT) {
Denys Vlasenko295fef82009-06-03 12:47:26 +02009590 /* export NAME (without =VALUE) */
9591 if (var) {
9592 var->flg_export = 1;
9593 debug_printf_env("%s: putenv '%s'\n", __func__, var->varstr);
9594 putenv(var->varstr);
9595 continue;
9596 }
9597 }
Denys Vlasenko38ef39a2017-07-18 01:40:01 +02009598 if (flags & SETFLAG_MAKE_RO) {
9599 /* readonly NAME (without =VALUE) */
9600 if (var) {
9601 var->flg_read_only = 1;
9602 continue;
9603 }
9604 }
Denys Vlasenko6ec76d82017-01-08 18:40:41 +01009605# if ENABLE_HUSH_LOCAL
Denys Vlasenkob95ee962017-07-17 21:19:53 +02009606 /* Is this "local" bltin? */
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02009607 if (!(flags & (SETFLAG_EXPORT|SETFLAG_UNEXPORT|SETFLAG_MAKE_RO))) {
9608 unsigned lvl = flags >> SETFLAG_LOCAL_SHIFT;
Denys Vlasenkob95ee962017-07-17 21:19:53 +02009609 if (var && var->func_nest_level == lvl) {
9610 /* "local x=abc; ...; local x" - ignore second local decl */
9611 continue;
9612 }
Denys Vlasenko61508d92016-10-02 21:12:02 +02009613 }
Denys Vlasenko6ec76d82017-01-08 18:40:41 +01009614# endif
Denys Vlasenko295fef82009-06-03 12:47:26 +02009615 /* Exporting non-existing variable.
9616 * bash does not put it in environment,
9617 * but remembers that it is exported,
9618 * and does put it in env when it is set later.
Denys Vlasenko1e660422017-07-17 21:10:50 +02009619 * We just set it to "" and export.
9620 */
Denys Vlasenko295fef82009-06-03 12:47:26 +02009621 /* Or, it's "local NAME" (without =VALUE).
Denys Vlasenko1e660422017-07-17 21:10:50 +02009622 * bash sets the value to "".
9623 */
9624 /* Or, it's "readonly NAME" (without =VALUE).
9625 * bash remembers NAME and disallows its creation
9626 * in the future.
9627 */
Denys Vlasenko295fef82009-06-03 12:47:26 +02009628 name = xasprintf("%s=", name);
9629 } else {
9630 /* (Un)exporting/making local NAME=VALUE */
9631 name = xstrdup(name);
9632 }
Denys Vlasenko38ef39a2017-07-18 01:40:01 +02009633 if (set_local_var(name, flags))
9634 return EXIT_FAILURE;
Denys Vlasenko295fef82009-06-03 12:47:26 +02009635 } while (*++argv);
Denys Vlasenko1e660422017-07-17 21:10:50 +02009636 return EXIT_SUCCESS;
Denys Vlasenko295fef82009-06-03 12:47:26 +02009637}
Denys Vlasenko6ec76d82017-01-08 18:40:41 +01009638#endif
Denys Vlasenko295fef82009-06-03 12:47:26 +02009639
Denys Vlasenko6ec76d82017-01-08 18:40:41 +01009640#if ENABLE_HUSH_EXPORT
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02009641static int FAST_FUNC builtin_export(char **argv)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009642{
Denis Vlasenkoad4bd052009-04-20 22:04:21 +00009643 unsigned opt_unexport;
9644
Denys Vlasenkodf5131c2009-06-07 16:04:17 +02009645#if ENABLE_HUSH_EXPORT_N
9646 /* "!": do not abort on errors */
9647 opt_unexport = getopt32(argv, "!n");
9648 if (opt_unexport == (uint32_t)-1)
9649 return EXIT_FAILURE;
9650 argv += optind;
9651#else
9652 opt_unexport = 0;
9653 argv++;
9654#endif
9655
9656 if (argv[0] == NULL) {
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009657 char **e = environ;
Denis Vlasenko0b677d82009-04-10 13:49:10 +00009658 if (e) {
9659 while (*e) {
9660#if 0
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009661 puts(*e++);
Denis Vlasenko0b677d82009-04-10 13:49:10 +00009662#else
9663 /* ash emits: export VAR='VAL'
9664 * bash: declare -x VAR="VAL"
9665 * we follow ash example */
9666 const char *s = *e++;
9667 const char *p = strchr(s, '=');
9668
9669 if (!p) /* wtf? take next variable */
9670 continue;
9671 /* export var= */
9672 printf("export %.*s", (int)(p - s) + 1, s);
Denis Vlasenko38e626d2009-04-18 12:58:19 +00009673 print_escaped(p + 1);
Denis Vlasenko0b677d82009-04-10 13:49:10 +00009674 putchar('\n');
9675#endif
9676 }
Denys Vlasenko8131eea2009-11-02 14:19:51 +01009677 /*fflush_all(); - done after each builtin anyway */
Denis Vlasenko0b677d82009-04-10 13:49:10 +00009678 }
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009679 return EXIT_SUCCESS;
9680 }
9681
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02009682 return helper_export_local(argv, opt_unexport ? SETFLAG_UNEXPORT : SETFLAG_EXPORT);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009683}
Denys Vlasenko6ec76d82017-01-08 18:40:41 +01009684#endif
Denis Vlasenkoc7985b72008-06-17 05:43:38 +00009685
Denys Vlasenko295fef82009-06-03 12:47:26 +02009686#if ENABLE_HUSH_LOCAL
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02009687static int FAST_FUNC builtin_local(char **argv)
Denys Vlasenko295fef82009-06-03 12:47:26 +02009688{
9689 if (G.func_nest_level == 0) {
9690 bb_error_msg("%s: not in a function", argv[0]);
9691 return EXIT_FAILURE; /* bash compat */
9692 }
Denys Vlasenko1e660422017-07-17 21:10:50 +02009693 argv++;
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02009694 return helper_export_local(argv, G.func_nest_level << SETFLAG_LOCAL_SHIFT);
Denys Vlasenko295fef82009-06-03 12:47:26 +02009695}
9696#endif
9697
Denys Vlasenko1e660422017-07-17 21:10:50 +02009698#if ENABLE_HUSH_READONLY
9699static int FAST_FUNC builtin_readonly(char **argv)
9700{
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02009701 argv++;
9702 if (*argv == NULL) {
Denys Vlasenko1e660422017-07-17 21:10:50 +02009703 /* bash: readonly [-p]: list all readonly VARs
9704 * (-p has no effect in bash)
9705 */
9706 struct variable *e;
9707 for (e = G.top_var; e; e = e->next) {
9708 if (e->flg_read_only) {
9709//TODO: quote value: readonly VAR='VAL'
9710 printf("readonly %s\n", e->varstr);
9711 }
9712 }
9713 return EXIT_SUCCESS;
9714 }
Denys Vlasenko3bab36b2017-07-18 01:05:24 +02009715 return helper_export_local(argv, SETFLAG_MAKE_RO);
Denys Vlasenko1e660422017-07-17 21:10:50 +02009716}
9717#endif
9718
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01009719#if ENABLE_HUSH_UNSET
Denys Vlasenko61508d92016-10-02 21:12:02 +02009720/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#unset */
9721static int FAST_FUNC builtin_unset(char **argv)
9722{
9723 int ret;
9724 unsigned opts;
9725
9726 /* "!": do not abort on errors */
9727 /* "+": stop at 1st non-option */
9728 opts = getopt32(argv, "!+vf");
9729 if (opts == (unsigned)-1)
9730 return EXIT_FAILURE;
9731 if (opts == 3) {
9732 bb_error_msg("unset: -v and -f are exclusive");
9733 return EXIT_FAILURE;
9734 }
9735 argv += optind;
9736
9737 ret = EXIT_SUCCESS;
9738 while (*argv) {
9739 if (!(opts & 2)) { /* not -f */
9740 if (unset_local_var(*argv)) {
9741 /* unset <nonexistent_var> doesn't fail.
9742 * Error is when one tries to unset RO var.
9743 * Message was printed by unset_local_var. */
9744 ret = EXIT_FAILURE;
9745 }
9746 }
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01009747# if ENABLE_HUSH_FUNCTIONS
Denys Vlasenko61508d92016-10-02 21:12:02 +02009748 else {
9749 unset_func(*argv);
9750 }
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01009751# endif
Denys Vlasenko61508d92016-10-02 21:12:02 +02009752 argv++;
9753 }
9754 return ret;
9755}
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01009756#endif
Denys Vlasenko61508d92016-10-02 21:12:02 +02009757
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01009758#if ENABLE_HUSH_SET
Denys Vlasenko61508d92016-10-02 21:12:02 +02009759/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set
9760 * built-in 'set' handler
9761 * SUSv3 says:
9762 * set [-abCefhmnuvx] [-o option] [argument...]
9763 * set [+abCefhmnuvx] [+o option] [argument...]
9764 * set -- [argument...]
9765 * set -o
9766 * set +o
9767 * Implementations shall support the options in both their hyphen and
9768 * plus-sign forms. These options can also be specified as options to sh.
9769 * Examples:
9770 * Write out all variables and their values: set
9771 * Set $1, $2, and $3 and set "$#" to 3: set c a b
9772 * Turn on the -x and -v options: set -xv
9773 * Unset all positional parameters: set --
9774 * Set $1 to the value of x, even if it begins with '-' or '+': set -- "$x"
9775 * Set the positional parameters to the expansion of x, even if x expands
9776 * with a leading '-' or '+': set -- $x
9777 *
9778 * So far, we only support "set -- [argument...]" and some of the short names.
9779 */
9780static int FAST_FUNC builtin_set(char **argv)
9781{
9782 int n;
9783 char **pp, **g_argv;
9784 char *arg = *++argv;
9785
9786 if (arg == NULL) {
9787 struct variable *e;
9788 for (e = G.top_var; e; e = e->next)
9789 puts(e->varstr);
9790 return EXIT_SUCCESS;
9791 }
9792
9793 do {
9794 if (strcmp(arg, "--") == 0) {
9795 ++argv;
9796 goto set_argv;
9797 }
9798 if (arg[0] != '+' && arg[0] != '-')
9799 break;
9800 for (n = 1; arg[n]; ++n) {
9801 if (set_mode((arg[0] == '-'), arg[n], argv[1]))
9802 goto error;
9803 if (arg[n] == 'o' && argv[1])
9804 argv++;
9805 }
9806 } while ((arg = *++argv) != NULL);
9807 /* Now argv[0] is 1st argument */
9808
9809 if (arg == NULL)
9810 return EXIT_SUCCESS;
9811 set_argv:
9812
9813 /* NB: G.global_argv[0] ($0) is never freed/changed */
9814 g_argv = G.global_argv;
9815 if (G.global_args_malloced) {
9816 pp = g_argv;
9817 while (*++pp)
9818 free(*pp);
9819 g_argv[1] = NULL;
9820 } else {
9821 G.global_args_malloced = 1;
9822 pp = xzalloc(sizeof(pp[0]) * 2);
9823 pp[0] = g_argv[0]; /* retain $0 */
9824 g_argv = pp;
9825 }
9826 /* This realloc's G.global_argv */
9827 G.global_argv = pp = add_strings_to_strings(g_argv, argv, /*dup:*/ 1);
9828
Denys Vlasenkod4e4fdb2017-07-03 21:31:16 +02009829 G.global_argc = 1 + string_array_len(pp + 1);
Denys Vlasenko61508d92016-10-02 21:12:02 +02009830
9831 return EXIT_SUCCESS;
9832
9833 /* Nothing known, so abort */
9834 error:
9835 bb_error_msg("set: %s: invalid option", arg);
9836 return EXIT_FAILURE;
9837}
Denys Vlasenko10d5ece2017-01-08 18:28:43 +01009838#endif
Denys Vlasenko61508d92016-10-02 21:12:02 +02009839
9840static int FAST_FUNC builtin_shift(char **argv)
9841{
9842 int n = 1;
9843 argv = skip_dash_dash(argv);
9844 if (argv[0]) {
Denys Vlasenkoe59591a2017-07-06 20:12:44 +02009845 n = bb_strtou(argv[0], NULL, 10);
9846 if (errno || n < 0) {
9847 /* shared string with ash.c */
9848 bb_error_msg("Illegal number: %s", argv[0]);
9849 /*
9850 * ash aborts in this case.
9851 * bash prints error message and set $? to 1.
9852 * Interestingly, for "shift 99999" bash does not
9853 * print error message, but does set $? to 1
9854 * (and does no shifting at all).
9855 */
9856 }
Denys Vlasenko61508d92016-10-02 21:12:02 +02009857 }
9858 if (n >= 0 && n < G.global_argc) {
Denys Vlasenko4e4f88e2017-01-09 07:57:38 +01009859 if (G_global_args_malloced) {
Denys Vlasenko61508d92016-10-02 21:12:02 +02009860 int m = 1;
9861 while (m <= n)
9862 free(G.global_argv[m++]);
9863 }
9864 G.global_argc -= n;
9865 memmove(&G.global_argv[1], &G.global_argv[n+1],
9866 G.global_argc * sizeof(G.global_argv[0]));
9867 return EXIT_SUCCESS;
9868 }
9869 return EXIT_FAILURE;
9870}
9871
Denys Vlasenko74d40582017-08-11 01:32:46 +02009872#if ENABLE_HUSH_GETOPTS
9873static int FAST_FUNC builtin_getopts(char **argv)
9874{
9875/*
9876TODO:
Denys Vlasenko74d40582017-08-11 01:32:46 +02009877If an invalid option is seen, getopts places ? into VAR and, if
9878not silent, prints an error message and unsets OPTARG. If
9879getopts is silent, the option character found is placed in
9880OPTARG and no diagnostic message is printed.
9881
9882If a required argument is not found, and getopts is not silent,
9883a question mark (?) is placed in VAR, OPTARG is unset, and a
9884diagnostic message is printed. If getopts is silent, then a
9885colon (:) is placed in VAR and OPTARG is set to the option
9886character found.
9887
9888Test that VAR is a valid variable name?
9889*/
9890 char cbuf[2];
9891 const char *cp, *optstring, *var;
9892 int c, exitcode;
9893
9894 optstring = *++argv;
9895 if (!optstring || !(var = *++argv)) {
9896 bb_error_msg("usage: getopts OPTSTRING VAR [ARGS]");
9897 return EXIT_FAILURE;
9898 }
9899
9900 cp = get_local_var_value("OPTERR");
9901 opterr = cp ? atoi(cp) : 1;
9902 cp = get_local_var_value("OPTIND");
9903 optind = cp ? atoi(cp) : 0;
Denys Vlasenko81f962f2017-08-11 02:05:21 +02009904 optarg = NULL;
Denys Vlasenko74d40582017-08-11 01:32:46 +02009905
9906 /* getopts stops on first non-option. Add "+" to force that */
9907 /*if (optstring[0] != '+')*/ {
9908 char *s = alloca(strlen(optstring) + 2);
9909 sprintf(s, "+%s", optstring);
9910 optstring = s;
9911 }
9912
9913 if (argv[1])
9914 argv[0] = G.global_argv[0]; /* for error messages */
9915 else
9916 argv = G.global_argv;
9917 c = getopt(string_array_len(argv), argv, optstring);
9918 exitcode = EXIT_SUCCESS;
9919 if (c < 0) { /* -1: end of options */
9920 exitcode = EXIT_FAILURE;
9921 c = '?';
9922 }
Denys Vlasenko81f962f2017-08-11 02:05:21 +02009923 if (optarg)
9924 set_local_var_from_halves("OPTARG", optarg);
9925 else
9926 unset_local_var("OPTARG");
Denys Vlasenko74d40582017-08-11 01:32:46 +02009927 cbuf[0] = c;
9928 cbuf[1] = '\0';
9929 set_local_var_from_halves(var, cbuf);
9930 set_local_var_from_halves("OPTIND", utoa(optind));
9931 return exitcode;
9932}
9933#endif
9934
Denys Vlasenkoa1184af2017-01-10 15:58:02 +01009935static int FAST_FUNC builtin_source(char **argv)
Denys Vlasenko61508d92016-10-02 21:12:02 +02009936{
Denys Vlasenkoa1184af2017-01-10 15:58:02 +01009937 char *arg_path, *filename;
9938 FILE *input;
9939 save_arg_t sv;
9940 char *args_need_save;
9941#if ENABLE_HUSH_FUNCTIONS
9942 smallint sv_flg;
Denys Vlasenko7a85c602017-01-08 17:40:18 +01009943#endif
Denys Vlasenko61508d92016-10-02 21:12:02 +02009944
Denys Vlasenkoa1184af2017-01-10 15:58:02 +01009945 argv = skip_dash_dash(argv);
9946 filename = argv[0];
9947 if (!filename) {
9948 /* bash says: "bash: .: filename argument required" */
9949 return 2; /* bash compat */
9950 }
9951 arg_path = NULL;
9952 if (!strchr(filename, '/')) {
9953 arg_path = find_in_path(filename);
9954 if (arg_path)
9955 filename = arg_path;
9956 }
9957 input = remember_FILE(fopen_or_warn(filename, "r"));
9958 free(arg_path);
9959 if (!input) {
9960 /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */
9961 /* POSIX: non-interactive shell should abort here,
9962 * not merely fail. So far no one complained :)
9963 */
9964 return EXIT_FAILURE;
9965 }
9966
9967#if ENABLE_HUSH_FUNCTIONS
9968 sv_flg = G_flag_return_in_progress;
9969 /* "we are inside sourced file, ok to use return" */
9970 G_flag_return_in_progress = -1;
9971#endif
9972 args_need_save = argv[1]; /* used as a boolean variable */
9973 if (args_need_save)
9974 save_and_replace_G_args(&sv, argv);
9975
9976 /* "false; . ./empty_line; echo Zero:$?" should print 0 */
9977 G.last_exitcode = 0;
9978 parse_and_run_file(input);
9979 fclose_and_forget(input);
9980
9981 if (args_need_save) /* can't use argv[1] instead: "shift" can mangle it */
9982 restore_G_args(&sv, argv);
9983#if ENABLE_HUSH_FUNCTIONS
9984 G_flag_return_in_progress = sv_flg;
9985#endif
9986
9987 return G.last_exitcode;
9988}
9989
Denys Vlasenko7a85c602017-01-08 17:40:18 +01009990#if ENABLE_HUSH_TRAP
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +02009991static int FAST_FUNC builtin_trap(char **argv)
Denis Vlasenko38e626d2009-04-18 12:58:19 +00009992{
Denis Vlasenko38e626d2009-04-18 12:58:19 +00009993 int sig;
9994 char *new_cmd;
9995
Denys Vlasenko7a85c602017-01-08 17:40:18 +01009996 if (!G_traps)
9997 G_traps = xzalloc(sizeof(G_traps[0]) * NSIG);
Denis Vlasenko38e626d2009-04-18 12:58:19 +00009998
9999 argv++;
10000 if (!*argv) {
Denis Vlasenko6008d8a2009-04-18 13:05:10 +000010001 int i;
Denis Vlasenko38e626d2009-04-18 12:58:19 +000010002 /* No args: print all trapped */
10003 for (i = 0; i < NSIG; ++i) {
Denys Vlasenko7a85c602017-01-08 17:40:18 +010010004 if (G_traps[i]) {
Denis Vlasenko38e626d2009-04-18 12:58:19 +000010005 printf("trap -- ");
Denys Vlasenko7a85c602017-01-08 17:40:18 +010010006 print_escaped(G_traps[i]);
Denys Vlasenkoe74aaf92009-09-27 02:05:45 +020010007 /* note: bash adds "SIG", but only if invoked
10008 * as "bash". If called as "sh", or if set -o posix,
10009 * then it prints short signal names.
10010 * We are printing short names: */
10011 printf(" %s\n", get_signame(i));
Denis Vlasenko38e626d2009-04-18 12:58:19 +000010012 }
10013 }
Denys Vlasenko8131eea2009-11-02 14:19:51 +010010014 /*fflush_all(); - done after each builtin anyway */
Denis Vlasenko38e626d2009-04-18 12:58:19 +000010015 return EXIT_SUCCESS;
10016 }
10017
10018 new_cmd = NULL;
Denis Vlasenko38e626d2009-04-18 12:58:19 +000010019 /* If first arg is a number: reset all specified signals */
10020 sig = bb_strtou(*argv, NULL, 10);
10021 if (errno == 0) {
10022 int ret;
10023 process_sig_list:
10024 ret = EXIT_SUCCESS;
10025 while (*argv) {
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +020010026 sighandler_t handler;
10027
Denis Vlasenko38e626d2009-04-18 12:58:19 +000010028 sig = get_signum(*argv++);
Denys Vlasenko86981e32017-07-25 20:06:17 +020010029 if (sig < 0) {
Denis Vlasenko38e626d2009-04-18 12:58:19 +000010030 ret = EXIT_FAILURE;
10031 /* Mimic bash message exactly */
Denys Vlasenko74562982017-07-06 18:40:45 +020010032 bb_error_msg("trap: %s: invalid signal specification", argv[-1]);
Denis Vlasenko38e626d2009-04-18 12:58:19 +000010033 continue;
10034 }
10035
Denys Vlasenko7a85c602017-01-08 17:40:18 +010010036 free(G_traps[sig]);
10037 G_traps[sig] = xstrdup(new_cmd);
Denis Vlasenko38e626d2009-04-18 12:58:19 +000010038
Denys Vlasenkoe89a2412010-01-12 15:19:31 +010010039 debug_printf("trap: setting SIG%s (%i) to '%s'\n",
Denys Vlasenko7a85c602017-01-08 17:40:18 +010010040 get_signame(sig), sig, G_traps[sig]);
Denis Vlasenko38e626d2009-04-18 12:58:19 +000010041
10042 /* There is no signal for 0 (EXIT) */
10043 if (sig == 0)
10044 continue;
10045
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +020010046 if (new_cmd)
10047 handler = (new_cmd[0] ? record_pending_signo : SIG_IGN);
10048 else
10049 /* We are removing trap handler */
10050 handler = pick_sighandler(sig);
Denys Vlasenko0806e402011-05-12 23:06:20 +020010051 install_sighandler(sig, handler);
Denis Vlasenko38e626d2009-04-18 12:58:19 +000010052 }
10053 return ret;
10054 }
10055
10056 if (!argv[1]) { /* no second arg */
10057 bb_error_msg("trap: invalid arguments");
10058 return EXIT_FAILURE;
10059 }
10060
10061 /* First arg is "-": reset all specified to default */
10062 /* First arg is "--": skip it, the rest is "handler SIGs..." */
10063 /* Everything else: set arg as signal handler
10064 * (includes "" case, which ignores signal) */
10065 if (argv[0][0] == '-') {
10066 if (argv[0][1] == '\0') { /* "-" */
10067 /* new_cmd remains NULL: "reset these sigs" */
10068 goto reset_traps;
10069 }
10070 if (argv[0][1] == '-' && argv[0][2] == '\0') { /* "--" */
10071 argv++;
10072 }
10073 /* else: "-something", no special meaning */
10074 }
10075 new_cmd = *argv;
10076 reset_traps:
10077 argv++;
10078 goto process_sig_list;
10079}
Denys Vlasenko7a85c602017-01-08 17:40:18 +010010080#endif
Denis Vlasenko38e626d2009-04-18 12:58:19 +000010081
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010082#if ENABLE_HUSH_JOB
Denys Vlasenko4e1c8b42016-11-07 20:06:40 +010010083static struct pipe *parse_jobspec(const char *str)
10084{
10085 struct pipe *pi;
Denys Vlasenkod5b5c2f2017-01-08 15:46:04 +010010086 unsigned jobnum;
Denys Vlasenko4e1c8b42016-11-07 20:06:40 +010010087
Denys Vlasenkod5b5c2f2017-01-08 15:46:04 +010010088 if (sscanf(str, "%%%u", &jobnum) != 1) {
10089 if (str[0] != '%'
10090 || (str[1] != '%' && str[1] != '+' && str[1] != '\0')
10091 ) {
10092 bb_error_msg("bad argument '%s'", str);
10093 return NULL;
10094 }
10095 /* It is "%%", "%+" or "%" - current job */
10096 jobnum = G.last_jobid;
10097 if (jobnum == 0) {
10098 bb_error_msg("no current job");
10099 return NULL;
10100 }
Denys Vlasenko4e1c8b42016-11-07 20:06:40 +010010101 }
10102 for (pi = G.job_list; pi; pi = pi->next) {
10103 if (pi->jobid == jobnum) {
10104 return pi;
10105 }
10106 }
Denys Vlasenkofd68f1e2017-01-09 05:47:57 +010010107 bb_error_msg("%u: no such job", jobnum);
Denys Vlasenko4e1c8b42016-11-07 20:06:40 +010010108 return NULL;
10109}
10110
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010010111static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM)
10112{
10113 struct pipe *job;
10114 const char *status_string;
10115
10116 checkjobs(NULL, 0 /*(no pid to wait for)*/);
10117 for (job = G.job_list; job; job = job->next) {
10118 if (job->alive_cmds == job->stopped_cmds)
10119 status_string = "Stopped";
10120 else
10121 status_string = "Running";
10122
10123 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->cmdtext);
10124 }
Denys Vlasenko2ed74e22017-07-14 19:58:46 +020010125
10126 clean_up_last_dead_job();
10127
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010010128 return EXIT_SUCCESS;
10129}
10130
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010131/* built-in 'fg' and 'bg' handler */
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +020010132static int FAST_FUNC builtin_fg_bg(char **argv)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010133{
Denys Vlasenko4e1c8b42016-11-07 20:06:40 +010010134 int i;
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010135 struct pipe *pi;
10136
Denis Vlasenko60b392f2009-04-03 19:14:32 +000010137 if (!G_interactive_fd)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010138 return EXIT_FAILURE;
Denis Vlasenkoc8653f62009-04-27 23:29:14 +000010139
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010140 /* If they gave us no args, assume they want the last backgrounded task */
10141 if (!argv[1]) {
Denis Vlasenko87a86552008-07-29 19:43:10 +000010142 for (pi = G.job_list; pi; pi = pi->next) {
10143 if (pi->jobid == G.last_jobid) {
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010144 goto found;
10145 }
10146 }
10147 bb_error_msg("%s: no current job", argv[0]);
10148 return EXIT_FAILURE;
10149 }
Denys Vlasenko4e1c8b42016-11-07 20:06:40 +010010150
10151 pi = parse_jobspec(argv[1]);
10152 if (!pi)
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010153 return EXIT_FAILURE;
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010154 found:
Denis Vlasenko6b9e0532009-04-18 01:23:21 +000010155 /* TODO: bash prints a string representation
10156 * of job being foregrounded (like "sleep 1 | cat") */
Mike Frysinger38478a62009-05-20 04:48:06 -040010157 if (argv[0][0] == 'f' && G_saved_tty_pgrp) {
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010158 /* Put the job into the foreground. */
Denis Vlasenko60b392f2009-04-03 19:14:32 +000010159 tcsetpgrp(G_interactive_fd, pi->pgrp);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010160 }
10161
10162 /* Restart the processes in the job */
Denis Vlasenko9af22c72008-10-09 12:54:58 +000010163 debug_printf_jobs("reviving %d procs, pgrp %d\n", pi->num_cmds, pi->pgrp);
10164 for (i = 0; i < pi->num_cmds; i++) {
10165 debug_printf_jobs("reviving pid %d\n", pi->cmds[i].pid);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010166 }
Denis Vlasenko9af22c72008-10-09 12:54:58 +000010167 pi->stopped_cmds = 0;
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010168
10169 i = kill(- pi->pgrp, SIGCONT);
10170 if (i < 0) {
10171 if (errno == ESRCH) {
Denys Vlasenko16096292017-07-10 10:00:28 +020010172 delete_finished_job(pi);
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010173 return EXIT_SUCCESS;
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010174 }
Denis Vlasenko34d4d892009-04-04 20:24:37 +000010175 bb_perror_msg("kill (SIGCONT)");
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010176 }
10177
Denis Vlasenko34d4d892009-04-04 20:24:37 +000010178 if (argv[0][0] == 'f') {
Denys Vlasenko16096292017-07-10 10:00:28 +020010179 remove_job_from_table(pi); /* FG job shouldn't be in job table */
Denis Vlasenkoc7985b72008-06-17 05:43:38 +000010180 return checkjobs_and_fg_shell(pi);
10181 }
10182 return EXIT_SUCCESS;
10183}
10184#endif
10185
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010010186#if ENABLE_HUSH_KILL
10187static int FAST_FUNC builtin_kill(char **argv)
10188{
10189 int ret = 0;
10190
Denys Vlasenkofd68f1e2017-01-09 05:47:57 +010010191# if ENABLE_HUSH_JOB
10192 if (argv[1] && strcmp(argv[1], "-l") != 0) {
10193 int i = 1;
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010010194
10195 do {
10196 struct pipe *pi;
10197 char *dst;
10198 int j, n;
10199
10200 if (argv[i][0] != '%')
10201 continue;
10202 /*
10203 * "kill %N" - job kill
10204 * Converting to pgrp / pid kill
10205 */
10206 pi = parse_jobspec(argv[i]);
10207 if (!pi) {
10208 /* Eat bad jobspec */
10209 j = i;
10210 do {
10211 j++;
10212 argv[j - 1] = argv[j];
10213 } while (argv[j]);
10214 ret = 1;
10215 i--;
10216 continue;
10217 }
10218 /*
10219 * In jobs started under job control, we signal
10220 * entire process group by kill -PGRP_ID.
10221 * This happens, f.e., in interactive shell.
10222 *
10223 * Otherwise, we signal each child via
10224 * kill PID1 PID2 PID3.
10225 * Testcases:
10226 * sh -c 'sleep 1|sleep 1 & kill %1'
10227 * sh -c 'true|sleep 2 & sleep 1; kill %1'
10228 * sh -c 'true|sleep 1 & sleep 2; kill %1'
10229 */
Denys Vlasenko5362cc42017-01-09 05:57:13 +010010230 n = G_interactive_fd ? 1 : pi->num_cmds;
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010010231 dst = alloca(n * sizeof(int)*4);
10232 argv[i] = dst;
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010010233 if (G_interactive_fd)
10234 dst += sprintf(dst, " -%u", (int)pi->pgrp);
Denys Vlasenkofd68f1e2017-01-09 05:47:57 +010010235 else for (j = 0; j < n; j++) {
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010010236 struct command *cmd = &pi->cmds[j];
10237 /* Skip exited members of the job */
10238 if (cmd->pid == 0)
10239 continue;
10240 /*
10241 * kill_main has matching code to expect
10242 * leading space. Needed to not confuse
10243 * negative pids with "kill -SIGNAL_NO" syntax
10244 */
10245 dst += sprintf(dst, " %u", (int)cmd->pid);
10246 }
10247 *dst = '\0';
10248 } while (argv[++i]);
10249 }
Denys Vlasenkofd68f1e2017-01-09 05:47:57 +010010250# endif
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010010251
Denys Vlasenkofd68f1e2017-01-09 05:47:57 +010010252 if (argv[1] || ret == 0) {
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010010253 ret = run_applet_main(argv, kill_main);
10254 }
Denys Vlasenkofd68f1e2017-01-09 05:47:57 +010010255 /* else: ret = 1, "kill %bad_jobspec" case */
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010010256 return ret;
10257}
10258#endif
10259
10260#if ENABLE_HUSH_WAIT
Mike Frysinger56bdea12009-03-28 20:01:58 +000010261/* http://www.opengroup.org/onlinepubs/9699919799/utilities/wait.html */
Denys Vlasenko62b717b2016-11-07 22:12:18 +010010262#if !ENABLE_HUSH_JOB
10263# define wait_for_child_or_signal(pipe,pid) wait_for_child_or_signal(pid)
10264#endif
10265static int wait_for_child_or_signal(struct pipe *waitfor_pipe, pid_t waitfor_pid)
Denys Vlasenko7e675362016-10-28 21:57:31 +020010266{
10267 int ret = 0;
10268 for (;;) {
10269 int sig;
Denys Vlasenko62b717b2016-11-07 22:12:18 +010010270 sigset_t oldset;
Denys Vlasenko7e675362016-10-28 21:57:31 +020010271
Denys Vlasenko830ea352016-11-08 04:59:11 +010010272 if (!sigisemptyset(&G.pending_set))
10273 goto check_sig;
10274
Denys Vlasenko7e675362016-10-28 21:57:31 +020010275 /* waitpid is not interruptible by SA_RESTARTed
10276 * signals which we use. Thus, this ugly dance:
10277 */
10278
10279 /* Make sure possible SIGCHLD is stored in kernel's
10280 * pending signal mask before we call waitpid.
10281 * Or else we may race with SIGCHLD, lose it,
Denys Vlasenko62b717b2016-11-07 22:12:18 +010010282 * and get stuck in sigsuspend...
Denys Vlasenko7e675362016-10-28 21:57:31 +020010283 */
Denys Vlasenko62b717b2016-11-07 22:12:18 +010010284 sigfillset(&oldset); /* block all signals, remember old set */
10285 sigprocmask(SIG_SETMASK, &oldset, &oldset);
Denys Vlasenko7e675362016-10-28 21:57:31 +020010286
10287 if (!sigisemptyset(&G.pending_set)) {
10288 /* Crap! we raced with some signal! */
Denys Vlasenko7e675362016-10-28 21:57:31 +020010289 goto restore;
10290 }
10291
10292 /*errno = 0; - checkjobs does this */
Denys Vlasenko62b717b2016-11-07 22:12:18 +010010293/* Can't pass waitfor_pipe into checkjobs(): it won't be interruptible */
Denys Vlasenko7e675362016-10-28 21:57:31 +020010294 ret = checkjobs(NULL, waitfor_pid); /* waitpid(WNOHANG) inside */
Denys Vlasenko62b717b2016-11-07 22:12:18 +010010295 debug_printf_exec("checkjobs:%d\n", ret);
10296#if ENABLE_HUSH_JOB
10297 if (waitfor_pipe) {
10298 int rcode = job_exited_or_stopped(waitfor_pipe);
10299 debug_printf_exec("job_exited_or_stopped:%d\n", rcode);
10300 if (rcode >= 0) {
10301 ret = rcode;
10302 sigprocmask(SIG_SETMASK, &oldset, NULL);
10303 break;
10304 }
10305 }
10306#endif
Denys Vlasenko7e675362016-10-28 21:57:31 +020010307 /* if ECHILD, there are no children (ret is -1 or 0) */
10308 /* if ret == 0, no children changed state */
10309 /* if ret != 0, it's exitcode+1 of exited waitfor_pid child */
Denys Vlasenko62b717b2016-11-07 22:12:18 +010010310 if (errno == ECHILD || ret) {
10311 ret--;
10312 if (ret < 0) /* if ECHILD, may need to fix "ret" */
Denys Vlasenko7e675362016-10-28 21:57:31 +020010313 ret = 0;
10314 sigprocmask(SIG_SETMASK, &oldset, NULL);
10315 break;
10316 }
Denys Vlasenko7e675362016-10-28 21:57:31 +020010317 /* Wait for SIGCHLD or any other signal */
Denys Vlasenko7e675362016-10-28 21:57:31 +020010318 /* It is vitally important for sigsuspend that SIGCHLD has non-DFL handler! */
10319 /* Note: sigsuspend invokes signal handler */
10320 sigsuspend(&oldset);
10321 restore:
10322 sigprocmask(SIG_SETMASK, &oldset, NULL);
Denys Vlasenko830ea352016-11-08 04:59:11 +010010323 check_sig:
Denys Vlasenko7e675362016-10-28 21:57:31 +020010324 /* So, did we get a signal? */
Denys Vlasenko7e675362016-10-28 21:57:31 +020010325 sig = check_and_run_traps();
10326 if (sig /*&& sig != SIGCHLD - always true */) {
Denys Vlasenko7c40ddd2017-08-02 16:37:39 +020010327 /* Do this for any (non-ignored) signal, not only for ^C */
Denys Vlasenko7e675362016-10-28 21:57:31 +020010328 ret = 128 + sig;
10329 break;
10330 }
10331 /* SIGCHLD, or no signal, or ignored one, such as SIGQUIT. Repeat */
10332 }
10333 return ret;
10334}
10335
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +020010336static int FAST_FUNC builtin_wait(char **argv)
Mike Frysinger56bdea12009-03-28 20:01:58 +000010337{
Denys Vlasenko7e675362016-10-28 21:57:31 +020010338 int ret;
Denys Vlasenko9d6cbaf2011-05-11 23:56:11 +020010339 int status;
Mike Frysinger56bdea12009-03-28 20:01:58 +000010340
Denys Vlasenkob131cce2010-05-20 03:39:43 +020010341 argv = skip_dash_dash(argv);
10342 if (argv[0] == NULL) {
Denis Vlasenko7566bae2009-03-31 17:24:49 +000010343 /* Don't care about wait results */
10344 /* Note 1: must wait until there are no more children */
10345 /* Note 2: must be interruptible */
10346 /* Examples:
10347 * $ sleep 3 & sleep 6 & wait
10348 * [1] 30934 sleep 3
10349 * [2] 30935 sleep 6
10350 * [1] Done sleep 3
10351 * [2] Done sleep 6
10352 * $ sleep 3 & sleep 6 & wait
10353 * [1] 30936 sleep 3
10354 * [2] 30937 sleep 6
10355 * [1] Done sleep 3
10356 * ^C <-- after ~4 sec from keyboard
10357 * $
10358 */
Denys Vlasenko62b717b2016-11-07 22:12:18 +010010359 return wait_for_child_or_signal(NULL, 0 /*(no job and no pid to wait for)*/);
Denis Vlasenko7566bae2009-03-31 17:24:49 +000010360 }
Mike Frysinger56bdea12009-03-28 20:01:58 +000010361
Denys Vlasenko7e675362016-10-28 21:57:31 +020010362 do {
Denis Vlasenkod5762932009-03-31 11:22:57 +000010363 pid_t pid = bb_strtou(*argv, NULL, 10);
Denys Vlasenko7e675362016-10-28 21:57:31 +020010364 if (errno || pid <= 0) {
Denys Vlasenko62b717b2016-11-07 22:12:18 +010010365#if ENABLE_HUSH_JOB
10366 if (argv[0][0] == '%') {
Denys Vlasenko02affb42016-11-08 00:59:29 +010010367 struct pipe *wait_pipe;
Denys Vlasenkod5b5c2f2017-01-08 15:46:04 +010010368 ret = 127; /* bash compat for bad jobspecs */
Denys Vlasenko62b717b2016-11-07 22:12:18 +010010369 wait_pipe = parse_jobspec(*argv);
10370 if (wait_pipe) {
Denys Vlasenko02affb42016-11-08 00:59:29 +010010371 ret = job_exited_or_stopped(wait_pipe);
Denys Vlasenko2ed74e22017-07-14 19:58:46 +020010372 if (ret < 0) {
Denys Vlasenko02affb42016-11-08 00:59:29 +010010373 ret = wait_for_child_or_signal(wait_pipe, 0);
Denys Vlasenko2ed74e22017-07-14 19:58:46 +020010374 } else {
10375 /* waiting on "last dead job" removes it */
10376 clean_up_last_dead_job();
Denys Vlasenko13102632017-07-08 00:24:32 +020010377 }
Denys Vlasenko62b717b2016-11-07 22:12:18 +010010378 }
Denys Vlasenkod5b5c2f2017-01-08 15:46:04 +010010379 /* else: parse_jobspec() already emitted error msg */
10380 continue;
Denys Vlasenko62b717b2016-11-07 22:12:18 +010010381 }
10382#endif
Denis Vlasenkod5762932009-03-31 11:22:57 +000010383 /* mimic bash message */
10384 bb_error_msg("wait: '%s': not a pid or valid job spec", *argv);
Denys Vlasenko9db74e42016-10-28 22:39:12 +020010385 ret = EXIT_FAILURE;
10386 continue; /* bash checks all argv[] */
Denis Vlasenkod5762932009-03-31 11:22:57 +000010387 }
Denys Vlasenko02affb42016-11-08 00:59:29 +010010388
Denys Vlasenko7e675362016-10-28 21:57:31 +020010389 /* Do we have such child? */
10390 ret = waitpid(pid, &status, WNOHANG);
10391 if (ret < 0) {
10392 /* No */
Denys Vlasenko840a4352017-07-07 22:56:02 +020010393 ret = 127;
Denys Vlasenko7e675362016-10-28 21:57:31 +020010394 if (errno == ECHILD) {
Denys Vlasenko0c5657e2017-07-14 19:27:03 +020010395 if (pid == G.last_bg_pid) {
Denys Vlasenko9db74e42016-10-28 22:39:12 +020010396 /* "wait $!" but last bg task has already exited. Try:
10397 * (sleep 1; exit 3) & sleep 2; echo $?; wait $!; echo $?
10398 * In bash it prints exitcode 0, then 3.
Denys Vlasenko26ad94b2016-11-07 23:07:21 +010010399 * In dash, it is 127.
Denys Vlasenko9db74e42016-10-28 22:39:12 +020010400 */
Denys Vlasenko840a4352017-07-07 22:56:02 +020010401 ret = G.last_bg_pid_exitcode;
Denys Vlasenko26ad94b2016-11-07 23:07:21 +010010402 } else {
10403 /* Example: "wait 1". mimic bash message */
10404 bb_error_msg("wait: pid %d is not a child of this shell", (int)pid);
Denys Vlasenko9db74e42016-10-28 22:39:12 +020010405 }
Denys Vlasenko7e675362016-10-28 21:57:31 +020010406 } else {
10407 /* ??? */
10408 bb_perror_msg("wait %s", *argv);
10409 }
Denys Vlasenko9db74e42016-10-28 22:39:12 +020010410 continue; /* bash checks all argv[] */
10411 }
10412 if (ret == 0) {
Denys Vlasenko7e675362016-10-28 21:57:31 +020010413 /* Yes, and it still runs */
Denys Vlasenko02affb42016-11-08 00:59:29 +010010414 ret = wait_for_child_or_signal(NULL, pid);
Denys Vlasenko7e675362016-10-28 21:57:31 +020010415 } else {
10416 /* Yes, and it just exited */
Denys Vlasenko02affb42016-11-08 00:59:29 +010010417 process_wait_result(NULL, pid, status);
Denys Vlasenko85378cd2015-10-11 21:47:11 +020010418 ret = WEXITSTATUS(status);
Mike Frysinger56bdea12009-03-28 20:01:58 +000010419 if (WIFSIGNALED(status))
10420 ret = 128 + WTERMSIG(status);
Mike Frysinger56bdea12009-03-28 20:01:58 +000010421 }
Denys Vlasenko9db74e42016-10-28 22:39:12 +020010422 } while (*++argv);
Mike Frysinger56bdea12009-03-28 20:01:58 +000010423
10424 return ret;
10425}
Denys Vlasenko1125d7d2017-01-08 17:19:38 +010010426#endif
Mike Frysinger56bdea12009-03-28 20:01:58 +000010427
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +000010428#if ENABLE_HUSH_LOOPS || ENABLE_HUSH_FUNCTIONS
10429static unsigned parse_numeric_argv1(char **argv, unsigned def, unsigned def_min)
10430{
10431 if (argv[1]) {
10432 def = bb_strtou(argv[1], NULL, 10);
10433 if (errno || def < def_min || argv[2]) {
10434 bb_error_msg("%s: bad arguments", argv[0]);
10435 def = UINT_MAX;
10436 }
10437 }
10438 return def;
10439}
10440#endif
10441
Denis Vlasenkodadfb492008-07-29 10:16:05 +000010442#if ENABLE_HUSH_LOOPS
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +020010443static int FAST_FUNC builtin_break(char **argv)
Denis Vlasenkobcb25532008-07-28 23:04:34 +000010444{
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +000010445 unsigned depth;
Denis Vlasenko87a86552008-07-29 19:43:10 +000010446 if (G.depth_of_loop == 0) {
Denis Vlasenko4f504a92008-07-29 19:48:30 +000010447 bb_error_msg("%s: only meaningful in a loop", argv[0]);
Denys Vlasenko49117b42016-07-21 14:40:08 +020010448 /* if we came from builtin_continue(), need to undo "= 1" */
10449 G.flag_break_continue = 0;
Denis Vlasenkofcf37c32008-07-29 11:37:15 +000010450 return EXIT_SUCCESS; /* bash compat */
10451 }
Denys Vlasenko49117b42016-07-21 14:40:08 +020010452 G.flag_break_continue++; /* BC_BREAK = 1, or BC_CONTINUE = 2 */
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +000010453
10454 G.depth_break_continue = depth = parse_numeric_argv1(argv, 1, 1);
10455 if (depth == UINT_MAX)
10456 G.flag_break_continue = BC_BREAK;
10457 if (G.depth_of_loop < depth)
Denis Vlasenko87a86552008-07-29 19:43:10 +000010458 G.depth_break_continue = G.depth_of_loop;
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +000010459
Denis Vlasenkobcb25532008-07-28 23:04:34 +000010460 return EXIT_SUCCESS;
10461}
10462
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +020010463static int FAST_FUNC builtin_continue(char **argv)
Denis Vlasenkobcb25532008-07-28 23:04:34 +000010464{
Denis Vlasenko4f504a92008-07-29 19:48:30 +000010465 G.flag_break_continue = 1; /* BC_CONTINUE = 2 = 1+1 */
10466 return builtin_break(argv);
Denis Vlasenkobcb25532008-07-28 23:04:34 +000010467}
Denis Vlasenkodadfb492008-07-29 10:16:05 +000010468#endif
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +000010469
10470#if ENABLE_HUSH_FUNCTIONS
Denys Vlasenkod5f1b1b2009-06-05 12:06:05 +020010471static int FAST_FUNC builtin_return(char **argv)
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +000010472{
10473 int rc;
10474
Denys Vlasenko04b46bc2016-10-01 22:28:03 +020010475 if (G_flag_return_in_progress != -1) {
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +000010476 bb_error_msg("%s: not in a function or sourced script", argv[0]);
10477 return EXIT_FAILURE; /* bash compat */
10478 }
10479
Denys Vlasenko04b46bc2016-10-01 22:28:03 +020010480 G_flag_return_in_progress = 1;
Denis Vlasenko3d40d8e2009-04-17 23:44:18 +000010481
10482 /* bash:
10483 * out of range: wraps around at 256, does not error out
10484 * non-numeric param:
10485 * f() { false; return qwe; }; f; echo $?
10486 * bash: return: qwe: numeric argument required <== we do this
10487 * 255 <== we also do this
10488 */
10489 rc = parse_numeric_argv1(argv, G.last_exitcode, 0);
10490 return rc;
10491}
10492#endif
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010010493
Denys Vlasenko11f2e992017-08-10 16:34:03 +020010494#if ENABLE_HUSH_TIMES
10495static int FAST_FUNC builtin_times(char **argv UNUSED_PARAM)
10496{
10497 static const uint8_t times_tbl[] ALIGN1 = {
10498 ' ', offsetof(struct tms, tms_utime),
10499 '\n', offsetof(struct tms, tms_stime),
10500 ' ', offsetof(struct tms, tms_cutime),
10501 '\n', offsetof(struct tms, tms_cstime),
10502 0
10503 };
10504 const uint8_t *p;
10505 unsigned clk_tck;
10506 struct tms buf;
10507
10508 clk_tck = bb_clk_tck();
10509
10510 times(&buf);
10511 p = times_tbl;
10512 do {
10513 unsigned sec, frac;
10514 unsigned long t;
10515 t = *(clock_t *)(((char *) &buf) + p[1]);
10516 sec = t / clk_tck;
10517 frac = t % clk_tck;
10518 printf("%um%u.%03us%c",
10519 sec / 60, sec % 60,
10520 (frac * 1000) / clk_tck,
10521 p[0]);
10522 p += 2;
10523 } while (*p);
10524
10525 return EXIT_SUCCESS;
10526}
10527#endif
10528
Denys Vlasenkoa1184af2017-01-10 15:58:02 +010010529#if ENABLE_HUSH_MEMLEAK
10530static int FAST_FUNC builtin_memleak(char **argv UNUSED_PARAM)
10531{
10532 void *p;
10533 unsigned long l;
10534
10535# ifdef M_TRIM_THRESHOLD
10536 /* Optional. Reduces probability of false positives */
10537 malloc_trim(0);
10538# endif
10539 /* Crude attempt to find where "free memory" starts,
10540 * sans fragmentation. */
10541 p = malloc(240);
10542 l = (unsigned long)p;
10543 free(p);
10544 p = malloc(3400);
10545 if (l < (unsigned long)p) l = (unsigned long)p;
10546 free(p);
10547
10548
10549# if 0 /* debug */
10550 {
10551 struct mallinfo mi = mallinfo();
10552 printf("top alloc:0x%lx malloced:%d+%d=%d\n", l,
10553 mi.arena, mi.hblkhd, mi.arena + mi.hblkhd);
10554 }
10555# endif
10556
10557 if (!G.memleak_value)
10558 G.memleak_value = l;
10559
10560 l -= G.memleak_value;
10561 if ((long)l < 0)
10562 l = 0;
10563 l /= 1024;
10564 if (l > 127)
10565 l = 127;
10566
10567 /* Exitcode is "how many kilobytes we leaked since 1st call" */
10568 return l;
10569}
10570#endif