1 /* vi: set sw=4 ts=4: */
2 /*
3  * 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.
7  *
8  * Copyright (C) 2000,2001  Larry Doolittle <larry@doolittle.boa.org>
9  * Copyright (C) 2008,2009  Denys Vlasenko <vda.linux@googlemail.com>
10  *
11  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
12  *
13  * Credits:
14  *      The parser routines proper are all original material, first
15  *      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
18  *      Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
19  *      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  *
25  * Other credits:
26  *      o_addchr derived from similar w_addchar function in glibc-2.2.
27  *      parse_redirect, redirect_opt_num, and big chunks of main
28  *      and many builtins derived from contributions by Erik Andersen.
29  *      Miscellaneous bugfixes from Matt Kraai.
30  *
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  *
42  * TODOs:
43  *      grep for "TODO" and fix (some of them are easy)
44  *      make complex ${var%...} constructs support optional
45  *      make here documents optional
46  *      special variables (done: PWD, PPID, RANDOM)
47  *      follow IFS rules more precisely, including update semantics
48  *      tilde expansion
49  *      aliases
50  *      "command" missing features:
51  *          command -p CMD: run CMD using default $PATH
52  *              (can use this to override standalone shell as well?)
53  *          command BLTIN: disables special-ness (e.g. errors do not abort)
54  *          command -V CMD1 CMD2 CMD3 (multiple args) (not in standard)
55  *      builtins mandated by standards we don't support:
56  *          [un]alias, fc:
57  *          fc -l[nr] [BEG] [END]: list range of commands in history
58  *          fc [-e EDITOR] [BEG] [END]: edit/rerun range of commands
59  *          fc -s [PAT=REP] [CMD]: rerun CMD, replacing PAT with REP
60  *
61  * Bash compat TODO:
62  *      redirection of stdout+stderr: &> and >&
63  *      reserved words: function select
64  *      advanced test: [[ ]]
65  *      process substitution: <(list) and >(list)
66  *      let EXPR [EXPR...]
67  *          Each EXPR is an arithmetic expression (ARITHMETIC EVALUATION)
68  *          If the last arg evaluates to 0, let returns 1; 0 otherwise.
69  *          NB: let `echo 'a=a + 1'` - error (IOW: multi-word expansion is used)
70  *      ((EXPR))
71  *          The EXPR is evaluated according to ARITHMETIC EVALUATION.
72  *          This is exactly equivalent to let "EXPR".
73  *      $[EXPR]: synonym for $((EXPR))
74  *      indirect expansion: ${!VAR}
75  *      substring op on @: ${@:n:m}
76  *
77  * Won't do:
78  *      Some builtins mandated by standards:
79  *          newgrp [GRP]: not a builtin in bash but a suid binary
80  *              which spawns a new shell with new group ID
81  *
82  * Status of [[ support:
83  * [[ args ]] are CMD_SINGLEWORD_NOGLOB:
84  *   v='a b'; [[ $v = 'a b' ]]; echo 0:$?
85  *   [[ /bin/n* ]]; echo 0:$?
86  *   = is glob match operator, not equality operator: STR = GLOB
87  *   == same as =
88  *   =~ is regex match operator: STR =~ REGEX
89  * TODO:
90  * quoting needs to be considered (-f is an operator, "-f" and ""-f are not; etc)
91  * in word = GLOB, quoting should be significant on char-by-char basis: a*cd"*"
92  */
93 //config:config HUSH
94 //config:	bool "hush (68 kb)"
95 //config:	default y
96 //config:	select SHELL_HUSH
97 //config:	help
98 //config:	hush is a small shell. It handles the normal flow control
99 //config:	constructs such as if/then/elif/else/fi, for/in/do/done, while loops,
100 //config:	case/esac. Redirections, here documents, $((arithmetic))
101 //config:	and functions are supported.
102 //config:
103 //config:	It will compile and work on no-mmu systems.
104 //config:
105 //config:	It does not handle select, aliases, tilde expansion,
106 //config:	&>file and >&file redirection of stdout+stderr.
107 //config:
108 // This option is visible (has a description) to make it possible to select
109 // a "scripted" applet (such as NOLOGIN) but avoid selecting any shells:
110 //config:config SHELL_HUSH
111 //config:	bool "Internal shell for embedded script support"
112 //config:	default n
113 //config:
114 //config:# hush options
115 //config:# It's only needed to get "nice" menuconfig indenting.
116 //config:if SHELL_HUSH || HUSH || SH_IS_HUSH || BASH_IS_HUSH
117 //config:
118 //config:config HUSH_BASH_COMPAT
119 //config:	bool "bash-compatible extensions"
120 //config:	default y
121 //config:	depends on SHELL_HUSH
122 //config:
123 //config:config HUSH_BRACE_EXPANSION
124 //config:	bool "Brace expansion"
125 //config:	default y
126 //config:	depends on HUSH_BASH_COMPAT
127 //config:	help
128 //config:	Enable {abc,def} extension.
129 //config:
130 //config:config HUSH_BASH_SOURCE_CURDIR
131 //config:	bool "'source' and '.' builtins search current directory after $PATH"
132 //config:	default n   # do not encourage non-standard behavior
133 //config:	depends on HUSH_BASH_COMPAT
134 //config:	help
135 //config:	This is not compliant with standards. Avoid if possible.
136 //config:
137 //config:config HUSH_LINENO_VAR
138 //config:	bool "$LINENO variable (bashism)"
139 //config:	default y
140 //config:	depends on SHELL_HUSH
141 //config:
142 //config:config HUSH_INTERACTIVE
143 //config:	bool "Interactive mode"
144 //config:	default y
145 //config:	depends on SHELL_HUSH
146 //config:	help
147 //config:	Enable interactive mode (prompt and command editing).
148 //config:	Without this, hush simply reads and executes commands
149 //config:	from stdin just like a shell script from a file.
150 //config:	No prompt, no PS1/PS2 magic shell variables.
151 //config:
152 //config:config HUSH_SAVEHISTORY
153 //config:	bool "Save command history to .hush_history"
154 //config:	default y
155 //config:	depends on HUSH_INTERACTIVE && FEATURE_EDITING_SAVEHISTORY
156 //config:
157 //config:config HUSH_JOB
158 //config:	bool "Job control"
159 //config:	default y
160 //config:	depends on HUSH_INTERACTIVE
161 //config:	help
162 //config:	Enable job control: Ctrl-Z backgrounds, Ctrl-C interrupts current
163 //config:	command (not entire shell), fg/bg builtins work. Without this option,
164 //config:	"cmd &" still works by simply spawning a process and immediately
165 //config:	prompting for next command (or executing next command in a script),
166 //config:	but no separate process group is formed.
167 //config:
168 //config:config HUSH_TICK
169 //config:	bool "Support command substitution"
170 //config:	default y
171 //config:	depends on SHELL_HUSH
172 //config:	help
173 //config:	Enable `command` and $(command).
174 //config:
175 //config:config HUSH_IF
176 //config:	bool "Support if/then/elif/else/fi"
177 //config:	default y
178 //config:	depends on SHELL_HUSH
179 //config:
180 //config:config HUSH_LOOPS
181 //config:	bool "Support for, while and until loops"
182 //config:	default y
183 //config:	depends on SHELL_HUSH
184 //config:
185 //config:config HUSH_CASE
186 //config:	bool "Support case ... esac statement"
187 //config:	default y
188 //config:	depends on SHELL_HUSH
189 //config:	help
190 //config:	Enable case ... esac statement. +400 bytes.
191 //config:
192 //config:config HUSH_FUNCTIONS
193 //config:	bool "Support funcname() { commands; } syntax"
194 //config:	default y
195 //config:	depends on SHELL_HUSH
196 //config:	help
197 //config:	Enable support for shell functions. +800 bytes.
198 //config:
199 //config:config HUSH_LOCAL
200 //config:	bool "local builtin"
201 //config:	default y
202 //config:	depends on HUSH_FUNCTIONS
203 //config:	help
204 //config:	Enable support for local variables in functions.
205 //config:
206 //config:config HUSH_RANDOM_SUPPORT
207 //config:	bool "Pseudorandom generator and $RANDOM variable"
208 //config:	default y
209 //config:	depends on SHELL_HUSH
210 //config:	help
211 //config:	Enable pseudorandom generator and dynamic variable "$RANDOM".
212 //config:	Each read of "$RANDOM" will generate a new pseudorandom value.
213 //config:
214 //config:config HUSH_MODE_X
215 //config:	bool "Support 'hush -x' option and 'set -x' command"
216 //config:	default y
217 //config:	depends on SHELL_HUSH
218 //config:	help
219 //config:	This instructs hush to print commands before execution.
220 //config:	Adds ~300 bytes.
221 //config:
222 //config:config HUSH_ECHO
223 //config:	bool "echo builtin"
224 //config:	default y
225 //config:	depends on SHELL_HUSH
226 //config:
227 //config:config HUSH_PRINTF
228 //config:	bool "printf builtin"
229 //config:	default y
230 //config:	depends on SHELL_HUSH
231 //config:
232 //config:config HUSH_TEST
233 //config:	bool "test builtin"
234 //config:	default y
235 //config:	depends on SHELL_HUSH
236 //config:
237 //config:config HUSH_HELP
238 //config:	bool "help builtin"
239 //config:	default y
240 //config:	depends on SHELL_HUSH
241 //config:
242 //config:config HUSH_EXPORT
243 //config:	bool "export builtin"
244 //config:	default y
245 //config:	depends on SHELL_HUSH
246 //config:
247 //config:config HUSH_EXPORT_N
248 //config:	bool "Support 'export -n' option"
249 //config:	default y
250 //config:	depends on HUSH_EXPORT
251 //config:	help
252 //config:	export -n unexports variables. It is a bash extension.
253 //config:
254 //config:config HUSH_READONLY
255 //config:	bool "readonly builtin"
256 //config:	default y
257 //config:	depends on SHELL_HUSH
258 //config:	help
259 //config:	Enable support for read-only variables.
260 //config:
261 //config:config HUSH_KILL
262 //config:	bool "kill builtin (supports kill %jobspec)"
263 //config:	default y
264 //config:	depends on SHELL_HUSH
265 //config:
266 //config:config HUSH_WAIT
267 //config:	bool "wait builtin"
268 //config:	default y
269 //config:	depends on SHELL_HUSH
270 //config:
271 //config:config HUSH_COMMAND
272 //config:	bool "command builtin"
273 //config:	default y
274 //config:	depends on SHELL_HUSH
275 //config:
276 //config:config HUSH_TRAP
277 //config:	bool "trap builtin"
278 //config:	default y
279 //config:	depends on SHELL_HUSH
280 //config:
281 //config:config HUSH_TYPE
282 //config:	bool "type builtin"
283 //config:	default y
284 //config:	depends on SHELL_HUSH
285 //config:
286 //config:config HUSH_TIMES
287 //config:	bool "times builtin"
288 //config:	default y
289 //config:	depends on SHELL_HUSH
290 //config:
291 //config:config HUSH_READ
292 //config:	bool "read builtin"
293 //config:	default y
294 //config:	depends on SHELL_HUSH
295 //config:
296 //config:config HUSH_SET
297 //config:	bool "set builtin"
298 //config:	default y
299 //config:	depends on SHELL_HUSH
300 //config:
301 //config:config HUSH_UNSET
302 //config:	bool "unset builtin"
303 //config:	default y
304 //config:	depends on SHELL_HUSH
305 //config:
306 //config:config HUSH_ULIMIT
307 //config:	bool "ulimit builtin"
308 //config:	default y
309 //config:	depends on SHELL_HUSH
310 //config:
311 //config:config HUSH_UMASK
312 //config:	bool "umask builtin"
313 //config:	default y
314 //config:	depends on SHELL_HUSH
315 //config:
316 //config:config HUSH_GETOPTS
317 //config:	bool "getopts builtin"
318 //config:	default y
319 //config:	depends on SHELL_HUSH
320 //config:
321 //config:config HUSH_MEMLEAK
322 //config:	bool "memleak builtin (debugging)"
323 //config:	default n
324 //config:	depends on SHELL_HUSH
325 //config:
326 //config:endif # hush options
327 
328 //applet:IF_HUSH(APPLET(hush, BB_DIR_BIN, BB_SUID_DROP))
329 //                       APPLET_ODDNAME:name  main  location    suid_type     help
330 //applet:IF_SH_IS_HUSH(  APPLET_ODDNAME(sh,   hush, BB_DIR_BIN, BB_SUID_DROP, hush))
331 //applet:IF_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, hush))
332 
333 //kbuild:lib-$(CONFIG_SHELL_HUSH) += hush.o match.o shell_common.o
334 //kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o
335 
336 /* -i (interactive) is also accepted,
337  * but does nothing, therefore not shown in help.
338  * NOMMU-specific options are not meant to be used by users,
339  * therefore we don't show them either.
340  */
341 //usage:#define hush_trivial_usage
342 //usage:	"[-enxl] [-c 'SCRIPT' [ARG0 ARGS] | FILE ARGS | -s ARGS]"
343 //usage:#define hush_full_usage "\n\n"
344 //usage:	"Unix shell interpreter"
345 
346 #if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
347 	|| defined(__APPLE__) \
348     )
349 # include <malloc.h>   /* for malloc_trim */
350 #endif
351 #include <glob.h>
352 /* #include <dmalloc.h> */
353 #if ENABLE_HUSH_CASE
354 # include <fnmatch.h>
355 #endif
356 #include <sys/times.h>
357 #include <sys/utsname.h> /* for setting $HOSTNAME */
358 
359 #include "busybox.h"  /* for APPLET_IS_NOFORK/NOEXEC */
360 #include "unicode.h"
361 #include "shell_common.h"
362 #include "math.h"
363 #include "match.h"
364 #if ENABLE_HUSH_RANDOM_SUPPORT
365 # include "random.h"
366 #else
367 # define CLEAR_RANDOM_T(rnd) ((void)0)
368 #endif
369 #ifndef O_CLOEXEC
370 # define O_CLOEXEC 0
371 #endif
372 #ifndef F_DUPFD_CLOEXEC
373 # define F_DUPFD_CLOEXEC F_DUPFD
374 #endif
375 
376 #if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !ENABLE_SHELL_ASH
377 # include "embedded_scripts.h"
378 #else
379 # define NUM_SCRIPTS 0
380 #endif
381 
382 /* So far, all bash compat is controlled by one config option */
383 /* Separate defines document which part of code implements what */
384 #define BASH_PATTERN_SUBST ENABLE_HUSH_BASH_COMPAT
385 #define BASH_SUBSTR        ENABLE_HUSH_BASH_COMPAT
386 #define BASH_SOURCE        ENABLE_HUSH_BASH_COMPAT
387 #define BASH_DOLLAR_SQUOTE ENABLE_HUSH_BASH_COMPAT
388 #define BASH_HOSTNAME_VAR  ENABLE_HUSH_BASH_COMPAT
389 #define BASH_EPOCH_VARS    ENABLE_HUSH_BASH_COMPAT
390 #define BASH_TEST2         (ENABLE_HUSH_BASH_COMPAT && ENABLE_HUSH_TEST)
391 #define BASH_READ_D        ENABLE_HUSH_BASH_COMPAT
392 
393 
394 /* Build knobs */
395 #define LEAK_HUNTING 0
396 #define BUILD_AS_NOMMU 0
397 /* Enable/disable sanity checks. Ok to enable in production,
398  * only adds a bit of bloat. Set to >1 to get non-production level verbosity.
399  * Keeping 1 for now even in released versions.
400  */
401 #define HUSH_DEBUG 1
402 /* Slightly bigger (+200 bytes), but faster hush.
403  * So far it only enables a trick with counting SIGCHLDs and forks,
404  * which allows us to do fewer waitpid's.
405  * (we can detect a case where neither forks were done nor SIGCHLDs happened
406  * and therefore waitpid will return the same result as last time)
407  */
408 #define ENABLE_HUSH_FAST 0
409 /* TODO: implement simplified code for users which do not need ${var%...} ops
410  * So far ${var%...} ops are always enabled:
411  */
412 #define ENABLE_HUSH_DOLLAR_OPS 1
413 
414 
415 #if BUILD_AS_NOMMU
416 # undef BB_MMU
417 # undef USE_FOR_NOMMU
418 # undef USE_FOR_MMU
419 # define BB_MMU 0
420 # define USE_FOR_NOMMU(...) __VA_ARGS__
421 # define USE_FOR_MMU(...)
422 #endif
423 
424 #include "NUM_APPLETS.h"
425 #if NUM_APPLETS == 1
426 /* STANDALONE does not make sense, and won't compile */
427 # undef CONFIG_FEATURE_SH_STANDALONE
428 # undef ENABLE_FEATURE_SH_STANDALONE
429 # undef IF_FEATURE_SH_STANDALONE
430 # undef IF_NOT_FEATURE_SH_STANDALONE
431 # define ENABLE_FEATURE_SH_STANDALONE 0
432 # define IF_FEATURE_SH_STANDALONE(...)
433 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
434 #endif
435 
436 #if !ENABLE_HUSH_INTERACTIVE
437 # undef ENABLE_FEATURE_EDITING
438 # define ENABLE_FEATURE_EDITING 0
439 # undef ENABLE_FEATURE_EDITING_FANCY_PROMPT
440 # define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0
441 # undef ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
442 # define ENABLE_FEATURE_EDITING_SAVE_ON_EXIT 0
443 #endif
444 
445 /* Do we support ANY keywords? */
446 #if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
447 # define HAS_KEYWORDS 1
448 # define IF_HAS_KEYWORDS(...) __VA_ARGS__
449 # define IF_HAS_NO_KEYWORDS(...)
450 #else
451 # define HAS_KEYWORDS 0
452 # define IF_HAS_KEYWORDS(...)
453 # define IF_HAS_NO_KEYWORDS(...) __VA_ARGS__
454 #endif
455 
456 /* If you comment out one of these below, it will be #defined later
457  * to perform debug printfs to stderr: */
458 #define debug_printf(...)         do {} while (0)
459 /* Finer-grained debug switches */
460 #define debug_printf_parse(...)   do {} while (0)
461 #define debug_printf_heredoc(...) do {} while (0)
462 #define debug_print_tree(a, b)    do {} while (0)
463 #define debug_printf_exec(...)    do {} while (0)
464 #define debug_printf_env(...)     do {} while (0)
465 #define debug_printf_jobs(...)    do {} while (0)
466 #define debug_printf_expand(...)  do {} while (0)
467 #define debug_printf_varexp(...)  do {} while (0)
468 #define debug_printf_glob(...)    do {} while (0)
469 #define debug_printf_redir(...)   do {} while (0)
470 #define debug_printf_list(...)    do {} while (0)
471 #define debug_printf_subst(...)   do {} while (0)
472 #define debug_printf_prompt(...)  do {} while (0)
473 #define debug_printf_clean(...)   do {} while (0)
474 
475 #define ERR_PTR ((void*)(long)1)
476 
477 #define JOB_STATUS_FORMAT    "[%u] %-22s %.40s\n"
478 
479 #define _SPECIAL_VARS_STR     "_*@$!?#-"
480 #define SPECIAL_VARS_STR     ("_*@$!?#-" + 1)
481 #define NUMERIC_SPECVARS_STR ("_*@$!?#-" + 3)
482 #if BASH_PATTERN_SUBST
483 /* Support / and // replace ops */
484 /* Note that // is stored as \ in "encoded" string representation */
485 # define VAR_ENCODED_SUBST_OPS      "\\/%#:-=+?"
486 # define VAR_SUBST_OPS             ("\\/%#:-=+?" + 1)
487 # define MINUS_PLUS_EQUAL_QUESTION ("\\/%#:-=+?" + 5)
488 #else
489 # define VAR_ENCODED_SUBST_OPS      "%#:-=+?"
490 # define VAR_SUBST_OPS              "%#:-=+?"
491 # define MINUS_PLUS_EQUAL_QUESTION ("%#:-=+?" + 3)
492 #endif
493 
494 #define SPECIAL_VAR_SYMBOL_STR "\3"
495 #define SPECIAL_VAR_SYMBOL       3
496 /* The "variable" with name "\1" emits string "\3". Testcase: "echo ^C" */
497 #define SPECIAL_VAR_QUOTED_SVS   1
498 
499 struct variable;
500 
501 static const char hush_version_str[] ALIGN1 = "HUSH_VERSION="BB_VER;
502 
503 /* This supports saving pointers malloced in vfork child,
504  * to be freed in the parent.
505  */
506 #if !BB_MMU
507 typedef struct nommu_save_t {
508 	struct variable *old_vars;
509 	char **argv;
510 	char **argv_from_re_execing;
511 } nommu_save_t;
512 #endif
513 
514 enum {
515 	RES_NONE  = 0,
516 #if ENABLE_HUSH_IF
517 	RES_IF    ,
518 	RES_THEN  ,
519 	RES_ELIF  ,
520 	RES_ELSE  ,
521 	RES_FI    ,
522 #endif
523 #if ENABLE_HUSH_LOOPS
524 	RES_FOR   ,
525 	RES_WHILE ,
526 	RES_UNTIL ,
527 	RES_DO    ,
528 	RES_DONE  ,
529 #endif
530 #if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
531 	RES_IN    ,
532 #endif
533 #if ENABLE_HUSH_CASE
534 	RES_CASE  ,
535 	/* three pseudo-keywords support contrived "case" syntax: */
536 	RES_CASE_IN,   /* "case ... IN", turns into RES_MATCH when IN is observed */
537 	RES_MATCH ,    /* "word)" */
538 	RES_CASE_BODY, /* "this command is inside CASE" */
539 	RES_ESAC  ,
540 #endif
541 	RES_XXXX  ,
542 	RES_SNTX
543 };
544 
545 typedef struct o_string {
546 	char *data;
547 	int length; /* position where data is appended */
548 	int maxlen;
549 	int o_expflags;
550 	/* At least some part of the string was inside '' or "",
551 	 * possibly empty one: word"", wo''rd etc. */
552 	smallint has_quoted_part;
553 	smallint has_empty_slot;
554 	smallint ended_in_ifs;
555 } o_string;
556 enum {
557 	EXP_FLAG_SINGLEWORD     = 0x80, /* must be 0x80 */
558 	EXP_FLAG_GLOB           = 0x2,
559 	/* Protect newly added chars against globbing
560 	 * by prepending \ to *, ?, [, \ */
561 	EXP_FLAG_ESC_GLOB_CHARS = 0x1,
562 };
563 /* Used for initialization: o_string foo = NULL_O_STRING; */
564 #define NULL_O_STRING { NULL }
565 
566 #ifndef debug_printf_parse
567 static const char *const assignment_flag[] = {
568 	"MAYBE_ASSIGNMENT",
569 	"DEFINITELY_ASSIGNMENT",
570 	"NOT_ASSIGNMENT",
571 	"WORD_IS_KEYWORD",
572 };
573 #endif
574 
575 /* We almost can use standard FILE api, but we need an ability to move
576  * its fd when redirects coincide with it. No api exists for that
577  * (RFE for it at https://sourceware.org/bugzilla/show_bug.cgi?id=21902).
578  * HFILE is our internal alternative. Only supports reading.
579  * Since we now can, we incorporate linked list of all opened HFILEs
580  * into the struct (used to be a separate mini-list).
581  */
582 typedef struct HFILE {
583 	char *cur;
584 	char *end;
585 	struct HFILE *next_hfile;
586 	int fd;
587 	char buf[1024];
588 } HFILE;
589 
590 typedef struct in_str {
591 	const char *p;
592 	int peek_buf[2];
593 	int last_char;
594 	HFILE *file;
595 } in_str;
596 
597 /* The descrip member of this structure is only used to make
598  * debugging output pretty */
599 static const struct {
600 	int32_t mode;
601 	signed char default_fd;
602 	char descrip[3];
603 } redir_table[] ALIGN4 = {
604 	{ O_RDONLY,                  0, "<"  },
605 	{ O_CREAT|O_TRUNC|O_WRONLY,  1, ">"  },
606 	{ O_CREAT|O_APPEND|O_WRONLY, 1, ">>" },
607 	{ O_CREAT|O_RDWR,            1, "<>" },
608 	{ O_RDONLY,                  0, "<<" },
609 /* Should not be needed. Bogus default_fd helps in debugging */
610 /*	{ O_RDONLY,                 77, "<<" }, */
611 };
612 
613 struct redir_struct {
614 	struct redir_struct *next;
615 	char *rd_filename;          /* filename */
616 	int rd_fd;                  /* fd to redirect */
617 	/* fd to redirect to, or -3 if rd_fd is to be closed (n>&-) */
618 	int rd_dup;
619 	smallint rd_type;           /* (enum redir_type) */
620 	/* note: for heredocs, rd_filename contains heredoc delimiter,
621 	 * and subsequently heredoc itself; and rd_dup is a bitmask:
622 	 * bit 0: do we need to trim leading tabs?
623 	 * bit 1: is heredoc quoted (<<'delim' syntax) ?
624 	 */
625 };
626 typedef enum redir_type {
627 	REDIRECT_INPUT     = 0,
628 	REDIRECT_OVERWRITE = 1,
629 	REDIRECT_APPEND    = 2,
630 	REDIRECT_IO        = 3,
631 	REDIRECT_HEREDOC   = 4,
632 	REDIRECT_HEREDOC2  = 5, /* REDIRECT_HEREDOC after heredoc is loaded */
633 
634 	REDIRFD_CLOSE      = -3,
635 	REDIRFD_SYNTAX_ERR = -2,
636 	REDIRFD_TO_FILE    = -1,
637 	/* otherwise, rd_fd is redirected to rd_dup */
638 
639 	HEREDOC_SKIPTABS = 1,
640 	HEREDOC_QUOTED   = 2,
641 } redir_type;
642 
643 
644 struct command {
645 	pid_t pid;                  /* 0 if exited */
646 	unsigned assignment_cnt;    /* how many argv[i] are assignments? */
647 #if ENABLE_HUSH_LINENO_VAR
648 	unsigned lineno;
649 #endif
650 	smallint cmd_type;          /* CMD_xxx */
651 #define CMD_NORMAL   0
652 #define CMD_SUBSHELL 1
653 #if BASH_TEST2
654 /* used for "[[ EXPR ]]" */
655 # define CMD_TEST2_SINGLEWORD_NOGLOB 2
656 #endif
657 #if BASH_TEST2 || ENABLE_HUSH_LOCAL || ENABLE_HUSH_EXPORT || ENABLE_HUSH_READONLY
658 /* used to prevent word splitting and globbing in "export v=t*" */
659 # define CMD_SINGLEWORD_NOGLOB 3
660 #endif
661 #if ENABLE_HUSH_FUNCTIONS
662 # define CMD_FUNCDEF 4
663 #endif
664 
665 	smalluint cmd_exitcode;
666 	/* if non-NULL, this "command" is { list }, ( list ), or a compound statement */
667 	struct pipe *group;
668 #if !BB_MMU
669 	char *group_as_string;
670 #endif
671 #if ENABLE_HUSH_FUNCTIONS
672 	struct function *child_func;
673 /* This field is used to prevent a bug here:
674  * while...do f1() {a;}; f1; f1() {b;}; f1; done
675  * When we execute "f1() {a;}" cmd, we create new function and clear
676  * cmd->group, cmd->group_as_string, cmd->argv[0].
677  * When we execute "f1() {b;}", we notice that f1 exists,
678  * and that its "parent cmd" struct is still "alive",
679  * we put those fields back into cmd->xxx
680  * (struct function has ->parent_cmd ptr to facilitate that).
681  * When we loop back, we can execute "f1() {a;}" again and set f1 correctly.
682  * Without this trick, loop would execute a;b;b;b;...
683  * instead of correct sequence a;b;a;b;...
684  * When command is freed, it severs the link
685  * (sets ->child_func->parent_cmd to NULL).
686  */
687 #endif
688 	char **argv;                /* command name and arguments */
689 /* argv vector may contain variable references (^Cvar^C, ^C0^C etc)
690  * and on execution these are substituted with their values.
691  * Substitution can make _several_ words out of one argv[n]!
692  * Example: argv[0]=='.^C*^C.' here: echo .$*.
693  * References of the form ^C`cmd arg^C are `cmd arg` substitutions.
694  */
695 	struct redir_struct *redirects; /* I/O redirections */
696 };
697 /* Is there anything in this command at all? */
698 #define IS_NULL_CMD(cmd) \
699 	(!(cmd)->group && !(cmd)->argv && !(cmd)->redirects)
700 
701 struct pipe {
702 	struct pipe *next;
703 	int num_cmds;               /* total number of commands in pipe */
704 	int alive_cmds;             /* number of commands running (not exited) */
705 	int stopped_cmds;           /* number of commands alive, but stopped */
706 #if ENABLE_HUSH_JOB
707 	unsigned jobid;             /* job number */
708 	pid_t pgrp;                 /* process group ID for the job */
709 	char *cmdtext;              /* name of job */
710 #endif
711 	struct command *cmds;       /* array of commands in pipe */
712 	smallint followup;          /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
713 	IF_HAS_KEYWORDS(smallint pi_inverted;) /* "! cmd | cmd" */
714 	IF_HAS_KEYWORDS(smallint res_word;) /* needed for if, for, while, until... */
715 };
716 typedef enum pipe_style {
717 	PIPE_SEQ = 0,
718 	PIPE_AND = 1,
719 	PIPE_OR  = 2,
720 	PIPE_BG  = 3,
721 } pipe_style;
722 /* Is there anything in this pipe at all? */
723 #define IS_NULL_PIPE(pi) \
724 	((pi)->num_cmds == 0 IF_HAS_KEYWORDS( && (pi)->res_word == RES_NONE))
725 
726 /* This holds pointers to the various results of parsing */
727 struct parse_context {
728 	/* linked list of pipes */
729 	struct pipe *list_head;
730 	/* last pipe (being constructed right now) */
731 	struct pipe *pipe;
732 	/* last command in pipe (being constructed right now) */
733 	struct command *command;
734 	/* last redirect in command->redirects list */
735 	struct redir_struct *pending_redirect;
736 	o_string word;
737 #if !BB_MMU
738 	o_string as_string;
739 #endif
740 	smallint is_assignment; /* 0:maybe, 1:yes, 2:no, 3:keyword */
741 #if HAS_KEYWORDS
742 	smallint ctx_res_w;
743 	smallint ctx_inverted; /* "! cmd | cmd" */
744 #if ENABLE_HUSH_CASE
745 	smallint ctx_dsemicolon; /* ";;" seen */
746 #endif
747 	/* bitmask of FLAG_xxx, for figuring out valid reserved words */
748 	int old_flag;
749 	/* group we are enclosed in:
750 	 * example: "if pipe1; pipe2; then pipe3; fi"
751 	 * when we see "if" or "then", we malloc and copy current context,
752 	 * and make ->stack point to it. then we parse pipeN.
753 	 * when closing "then" / fi" / whatever is found,
754 	 * we move list_head into ->stack->command->group,
755 	 * copy ->stack into current context, and delete ->stack.
756 	 * (parsing of { list } and ( list ) doesn't use this method)
757 	 */
758 	struct parse_context *stack;
759 #endif
760 };
761 enum {
762 	MAYBE_ASSIGNMENT      = 0,
763 	DEFINITELY_ASSIGNMENT = 1,
764 	NOT_ASSIGNMENT        = 2,
765 	/* Not an assignment, but next word may be: "if v=xyz cmd;" */
766 	WORD_IS_KEYWORD       = 3,
767 };
768 
769 /* On program start, environ points to initial environment.
770  * putenv adds new pointers into it, unsetenv removes them.
771  * Neither of these (de)allocates the strings.
772  * setenv allocates new strings in malloc space and does putenv,
773  * and thus setenv is unusable (leaky) for shell's purposes */
774 #define setenv(...) setenv_is_leaky_dont_use()
775 struct variable {
776 	struct variable *next;
777 	char *varstr;        /* points to "name=" portion */
778 	int max_len;         /* if > 0, name is part of initial env; else name is malloced */
779 	uint16_t var_nest_level;
780 	smallint flg_export; /* putenv should be done on this var */
781 	smallint flg_read_only;
782 };
783 
784 enum {
785 	BC_BREAK = 1,
786 	BC_CONTINUE = 2,
787 };
788 
789 #if ENABLE_HUSH_FUNCTIONS
790 struct function {
791 	struct function *next;
792 	char *name;
793 	struct command *parent_cmd;
794 	struct pipe *body;
795 # if !BB_MMU
796 	char *body_as_string;
797 # endif
798 };
799 #endif
800 
801 
802 /* set -/+o OPT support. (TODO: make it optional)
803  * bash supports the following opts:
804  * allexport       off
805  * braceexpand     on
806  * emacs           on
807  * errexit         off
808  * errtrace        off
809  * functrace       off
810  * hashall         on
811  * histexpand      off
812  * history         on
813  * ignoreeof       off
814  * interactive-comments    on
815  * keyword         off
816  * monitor         on
817  * noclobber       off
818  * noexec          off
819  * noglob          off
820  * nolog           off
821  * notify          off
822  * nounset         off
823  * onecmd          off
824  * physical        off
825  * pipefail        off
826  * posix           off
827  * privileged      off
828  * verbose         off
829  * vi              off
830  * xtrace          off
831  */
832 static const char o_opt_strings[] ALIGN1 =
833 	"pipefail\0"
834 	"noexec\0"
835 	"errexit\0"
836 #if ENABLE_HUSH_MODE_X
837 	"xtrace\0"
838 #endif
839 	;
840 enum {
841 	OPT_O_PIPEFAIL,
842 	OPT_O_NOEXEC,
843 	OPT_O_ERREXIT,
844 #if ENABLE_HUSH_MODE_X
845 	OPT_O_XTRACE,
846 #endif
847 	NUM_OPT_O
848 };
849 
850 /* "Globals" within this file */
851 /* Sorted roughly by size (smaller offsets == smaller code) */
852 struct globals {
853 	/* interactive_fd != 0 means we are an interactive shell.
854 	 * If we are, then saved_tty_pgrp can also be != 0, meaning
855 	 * that controlling tty is available. With saved_tty_pgrp == 0,
856 	 * job control still works, but terminal signals
857 	 * (^C, ^Z, ^Y, ^\) won't work at all, and background
858 	 * process groups can only be created with "cmd &".
859 	 * With saved_tty_pgrp != 0, hush will use tcsetpgrp()
860 	 * to give tty to the foreground process group,
861 	 * and will take it back when the group is stopped (^Z)
862 	 * or killed (^C).
863 	 */
864 #if ENABLE_HUSH_INTERACTIVE
865 	/* 'interactive_fd' is a fd# open to ctty, if we have one
866 	 * _AND_ if we decided to act interactively */
867 	int interactive_fd;
868 	IF_NOT_FEATURE_EDITING_FANCY_PROMPT(char *PS1;)
869 # define G_interactive_fd (G.interactive_fd)
870 #else
871 # define G_interactive_fd 0
872 #endif
873 #if ENABLE_FEATURE_EDITING
874 	line_input_t *line_input_state;
875 #endif
876 	pid_t root_pid;
877 	pid_t root_ppid;
878 	pid_t last_bg_pid;
879 #if ENABLE_HUSH_RANDOM_SUPPORT
880 	random_t random_gen;
881 #endif
882 #if ENABLE_HUSH_JOB
883 	int run_list_level;
884 	unsigned last_jobid;
885 	pid_t saved_tty_pgrp;
886 	struct pipe *job_list;
887 # define G_saved_tty_pgrp (G.saved_tty_pgrp)
888 #else
889 # define G_saved_tty_pgrp 0
890 #endif
891 	/* How deeply are we in context where "set -e" is ignored */
892 	int errexit_depth;
893 	/* "set -e" rules (do we follow them correctly?):
894 	 * Exit if pipe, list, or compound command exits with a non-zero status.
895 	 * Shell does not exit if failed command is part of condition in
896 	 * if/while, part of && or || list except the last command, any command
897 	 * in a pipe but the last, or if the command's return value is being
898 	 * inverted with !. If a compound command other than a subshell returns a
899 	 * non-zero status because a command failed while -e was being ignored, the
900 	 * shell does not exit. A trap on ERR, if set, is executed before the shell
901 	 * exits [ERR is a bashism].
902 	 *
903 	 * If a compound command or function executes in a context where -e is
904 	 * ignored, none of the commands executed within are affected by the -e
905 	 * setting. If a compound command or function sets -e while executing in a
906 	 * context where -e is ignored, that setting does not have any effect until
907 	 * the compound command or the command containing the function call completes.
908 	 */
909 
910 	char o_opt[NUM_OPT_O];
911 #if ENABLE_HUSH_MODE_X
912 # define G_x_mode (G.o_opt[OPT_O_XTRACE])
913 #else
914 # define G_x_mode 0
915 #endif
916 	char opt_s;
917 	char opt_c;
918 #if ENABLE_HUSH_INTERACTIVE
919 	smallint promptmode; /* 0: PS1, 1: PS2 */
920 #endif
921 	smallint flag_SIGINT;
922 #if ENABLE_HUSH_LOOPS
923 	smallint flag_break_continue;
924 #endif
925 #if ENABLE_HUSH_FUNCTIONS
926 	/* 0: outside of a function (or sourced file)
927 	 * -1: inside of a function, ok to use return builtin
928 	 * 1: return is invoked, skip all till end of func
929 	 */
930 	smallint flag_return_in_progress;
931 # define G_flag_return_in_progress (G.flag_return_in_progress)
932 #else
933 # define G_flag_return_in_progress 0
934 #endif
935 	smallint exiting; /* used to prevent EXIT trap recursion */
936 	/* These support $? */
937 	smalluint last_exitcode;
938 	smalluint expand_exitcode;
939 	smalluint last_bg_pid_exitcode;
940 #if ENABLE_HUSH_SET
941 	/* are global_argv and global_argv[1..n] malloced? (note: not [0]) */
942 	smalluint global_args_malloced;
943 # define G_global_args_malloced (G.global_args_malloced)
944 #else
945 # define G_global_args_malloced 0
946 #endif
947 #if ENABLE_HUSH_BASH_COMPAT
948 	int dead_job_exitcode; /* for "wait -n" */
949 #endif
950 	/* how many non-NULL argv's we have. NB: $# + 1 */
951 	int global_argc;
952 	char **global_argv;
953 #if !BB_MMU
954 	char *argv0_for_re_execing;
955 #endif
956 #if ENABLE_HUSH_LOOPS
957 	unsigned depth_break_continue;
958 	unsigned depth_of_loop;
959 #endif
960 #if ENABLE_HUSH_GETOPTS
961 	unsigned getopt_count;
962 #endif
963 	const char *ifs;
964 	char *ifs_whitespace; /* = G.ifs or malloced */
965 	const char *cwd;
966 	struct variable *top_var;
967 	char **expanded_assignments;
968 	struct variable **shadowed_vars_pp;
969 	unsigned var_nest_level;
970 #if ENABLE_HUSH_FUNCTIONS
971 # if ENABLE_HUSH_LOCAL
972 	unsigned func_nest_level; /* solely to prevent "local v" in non-functions */
973 # endif
974 	struct function *top_func;
975 #endif
976 	/* Signal and trap handling */
977 #if ENABLE_HUSH_FAST
978 	unsigned count_SIGCHLD;
979 	unsigned handled_SIGCHLD;
980 	smallint we_have_children;
981 #endif
982 #if ENABLE_HUSH_LINENO_VAR
983 	unsigned parse_lineno;
984 	unsigned execute_lineno;
985 #endif
986 	HFILE *HFILE_list;
987 	HFILE *HFILE_stdin;
988 	/* Which signals have non-DFL handler (even with no traps set)?
989 	 * Set at the start to:
990 	 * (SIGQUIT + maybe SPECIAL_INTERACTIVE_SIGS + maybe SPECIAL_JOBSTOP_SIGS)
991 	 * SPECIAL_INTERACTIVE_SIGS are cleared after fork.
992 	 * The rest is cleared right before execv syscalls.
993 	 * Other than these two times, never modified.
994 	 */
995 	unsigned special_sig_mask;
996 #if ENABLE_HUSH_JOB
997 	unsigned fatal_sig_mask;
998 # define G_fatal_sig_mask (G.fatal_sig_mask)
999 #else
1000 # define G_fatal_sig_mask 0
1001 #endif
1002 #if ENABLE_HUSH_TRAP
1003 	int pre_trap_exitcode;
1004 # if ENABLE_HUSH_FUNCTIONS
1005 	int return_exitcode;
1006 # endif
1007 	char **traps; /* char *traps[NSIG] */
1008 # define G_traps G.traps
1009 #else
1010 # define G_traps ((char**)NULL)
1011 #endif
1012 	sigset_t pending_set;
1013 #if ENABLE_HUSH_MEMLEAK
1014 	unsigned long memleak_value;
1015 #endif
1016 #if ENABLE_HUSH_MODE_X
1017 	unsigned x_mode_depth;
1018 	/* "set -x" output should not be redirectable with subsequent 2>FILE.
1019 	 * We dup fd#2 to x_mode_fd when "set -x" is executed, and use it
1020 	 * for all subsequent output.
1021 	 */
1022 	int x_mode_fd;
1023 	o_string x_mode_buf;
1024 #endif
1025 #if HUSH_DEBUG >= 2
1026 	int debug_indent;
1027 #endif
1028 	struct sigaction sa;
1029 	char optstring_buf[sizeof("eixcs")];
1030 #if BASH_EPOCH_VARS
1031 	char epoch_buf[sizeof("%llu.nnnnnn") + sizeof(long long)*3];
1032 #endif
1033 #if ENABLE_FEATURE_EDITING
1034 	char user_input_buf[CONFIG_FEATURE_EDITING_MAX_LEN];
1035 #endif
1036 };
1037 #define G (*ptr_to_globals)
1038 /* Not #defining name to G.name - this quickly gets unwieldy
1039  * (too many defines). Also, I actually prefer to see when a variable
1040  * is global, thus "G." prefix is a useful hint */
1041 #define INIT_G() do { \
1042 	SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
1043 	/* memset(&G.sa, 0, sizeof(G.sa)); */  \
1044 	sigfillset(&G.sa.sa_mask); \
1045 	G.sa.sa_flags = SA_RESTART; \
1046 } while (0)
1047 
1048 
1049 /* Function prototypes for builtins */
1050 static int builtin_cd(char **argv) FAST_FUNC;
1051 #if ENABLE_HUSH_ECHO
1052 static int builtin_echo(char **argv) FAST_FUNC;
1053 #endif
1054 static int builtin_eval(char **argv) FAST_FUNC;
1055 static int builtin_exec(char **argv) FAST_FUNC;
1056 static int builtin_exit(char **argv) FAST_FUNC;
1057 #if ENABLE_HUSH_EXPORT
1058 static int builtin_export(char **argv) FAST_FUNC;
1059 #endif
1060 #if ENABLE_HUSH_READONLY
1061 static int builtin_readonly(char **argv) FAST_FUNC;
1062 #endif
1063 #if ENABLE_HUSH_JOB
1064 static int builtin_fg_bg(char **argv) FAST_FUNC;
1065 static int builtin_jobs(char **argv) FAST_FUNC;
1066 #endif
1067 #if ENABLE_HUSH_GETOPTS
1068 static int builtin_getopts(char **argv) FAST_FUNC;
1069 #endif
1070 #if ENABLE_HUSH_HELP
1071 static int builtin_help(char **argv) FAST_FUNC;
1072 #endif
1073 #if MAX_HISTORY && ENABLE_FEATURE_EDITING
1074 static int builtin_history(char **argv) FAST_FUNC;
1075 #endif
1076 #if ENABLE_HUSH_LOCAL
1077 static int builtin_local(char **argv) FAST_FUNC;
1078 #endif
1079 #if ENABLE_HUSH_MEMLEAK
1080 static int builtin_memleak(char **argv) FAST_FUNC;
1081 #endif
1082 #if ENABLE_HUSH_PRINTF
1083 static int builtin_printf(char **argv) FAST_FUNC;
1084 #endif
1085 static int builtin_pwd(char **argv) FAST_FUNC;
1086 #if ENABLE_HUSH_READ
1087 static int builtin_read(char **argv) FAST_FUNC;
1088 #endif
1089 #if ENABLE_HUSH_SET
1090 static int builtin_set(char **argv) FAST_FUNC;
1091 #endif
1092 static int builtin_shift(char **argv) FAST_FUNC;
1093 static int builtin_source(char **argv) FAST_FUNC;
1094 #if ENABLE_HUSH_TEST || BASH_TEST2
1095 static int builtin_test(char **argv) FAST_FUNC;
1096 #endif
1097 #if ENABLE_HUSH_TRAP
1098 static int builtin_trap(char **argv) FAST_FUNC;
1099 #endif
1100 #if ENABLE_HUSH_TYPE
1101 static int builtin_type(char **argv) FAST_FUNC;
1102 #endif
1103 #if ENABLE_HUSH_TIMES
1104 static int builtin_times(char **argv) FAST_FUNC;
1105 #endif
1106 static int builtin_true(char **argv) FAST_FUNC;
1107 #if ENABLE_HUSH_UMASK
1108 static int builtin_umask(char **argv) FAST_FUNC;
1109 #endif
1110 #if ENABLE_HUSH_UNSET
1111 static int builtin_unset(char **argv) FAST_FUNC;
1112 #endif
1113 #if ENABLE_HUSH_KILL
1114 static int builtin_kill(char **argv) FAST_FUNC;
1115 #endif
1116 #if ENABLE_HUSH_WAIT
1117 static int builtin_wait(char **argv) FAST_FUNC;
1118 #endif
1119 #if ENABLE_HUSH_LOOPS
1120 static int builtin_break(char **argv) FAST_FUNC;
1121 static int builtin_continue(char **argv) FAST_FUNC;
1122 #endif
1123 #if ENABLE_HUSH_FUNCTIONS
1124 static int builtin_return(char **argv) FAST_FUNC;
1125 #endif
1126 
1127 /* Table of built-in functions.  They can be forked or not, depending on
1128  * context: within pipes, they fork.  As simple commands, they do not.
1129  * When used in non-forking context, they can change global variables
1130  * in the parent shell process.  If forked, of course they cannot.
1131  * For example, 'unset foo | whatever' will parse and run, but foo will
1132  * still be set at the end. */
1133 struct built_in_command {
1134 	const char *b_cmd;
1135 	int (*b_function)(char **argv) FAST_FUNC;
1136 #if ENABLE_HUSH_HELP
1137 	const char *b_descr;
1138 # define BLTIN(cmd, func, help) { cmd, func, help }
1139 #else
1140 # define BLTIN(cmd, func, help) { cmd, func }
1141 #endif
1142 };
1143 
1144 static const struct built_in_command bltins1[] ALIGN_PTR = {
1145 	BLTIN("."        , builtin_source  , "Run commands in file"),
1146 	BLTIN(":"        , builtin_true    , NULL),
1147 #if ENABLE_HUSH_JOB
1148 	BLTIN("bg"       , builtin_fg_bg   , "Resume job in background"),
1149 #endif
1150 #if ENABLE_HUSH_LOOPS
1151 	BLTIN("break"    , builtin_break   , "Exit loop"),
1152 #endif
1153 	BLTIN("cd"       , builtin_cd      , "Change directory"),
1154 #if ENABLE_HUSH_LOOPS
1155 	BLTIN("continue" , builtin_continue, "Start new loop iteration"),
1156 #endif
1157 	BLTIN("eval"     , builtin_eval    , "Construct and run shell command"),
1158 	BLTIN("exec"     , builtin_exec    , "Execute command, don't return to shell"),
1159 	BLTIN("exit"     , builtin_exit    , NULL),
1160 #if ENABLE_HUSH_EXPORT
1161 	BLTIN("export"   , builtin_export  , "Set environment variables"),
1162 #endif
1163 #if ENABLE_HUSH_JOB
1164 	BLTIN("fg"       , builtin_fg_bg   , "Bring job to foreground"),
1165 #endif
1166 #if ENABLE_HUSH_GETOPTS
1167 	BLTIN("getopts"  , builtin_getopts , NULL),
1168 #endif
1169 #if ENABLE_HUSH_HELP
1170 	BLTIN("help"     , builtin_help    , NULL),
1171 #endif
1172 #if MAX_HISTORY && ENABLE_FEATURE_EDITING
1173 	BLTIN("history"  , builtin_history , "Show history"),
1174 #endif
1175 #if ENABLE_HUSH_JOB
1176 	BLTIN("jobs"     , builtin_jobs    , "List jobs"),
1177 #endif
1178 #if ENABLE_HUSH_KILL
1179 	BLTIN("kill"     , builtin_kill    , "Send signals to processes"),
1180 #endif
1181 #if ENABLE_HUSH_LOCAL
1182 	BLTIN("local"    , builtin_local   , "Set local variables"),
1183 #endif
1184 #if ENABLE_HUSH_MEMLEAK
1185 	BLTIN("memleak"  , builtin_memleak , NULL),
1186 #endif
1187 #if ENABLE_HUSH_READ
1188 	BLTIN("read"     , builtin_read    , "Input into variable"),
1189 #endif
1190 #if ENABLE_HUSH_READONLY
1191 	BLTIN("readonly" , builtin_readonly, "Make variables read-only"),
1192 #endif
1193 #if ENABLE_HUSH_FUNCTIONS
1194 	BLTIN("return"   , builtin_return  , "Return from function"),
1195 #endif
1196 #if ENABLE_HUSH_SET
1197 	BLTIN("set"      , builtin_set     , "Set positional parameters"),
1198 #endif
1199 	BLTIN("shift"    , builtin_shift   , "Shift positional parameters"),
1200 #if BASH_SOURCE
1201 	BLTIN("source"   , builtin_source  , NULL),
1202 #endif
1203 #if ENABLE_HUSH_TIMES
1204 	BLTIN("times"    , builtin_times   , NULL),
1205 #endif
1206 #if ENABLE_HUSH_TRAP
1207 	BLTIN("trap"     , builtin_trap    , "Trap signals"),
1208 #endif
1209 	BLTIN("true"     , builtin_true    , NULL),
1210 #if ENABLE_HUSH_TYPE
1211 	BLTIN("type"     , builtin_type    , "Show command type"),
1212 #endif
1213 #if ENABLE_HUSH_ULIMIT
1214 	BLTIN("ulimit"   , shell_builtin_ulimit, "Control resource limits"),
1215 #endif
1216 #if ENABLE_HUSH_UMASK
1217 	BLTIN("umask"    , builtin_umask   , "Set file creation mask"),
1218 #endif
1219 #if ENABLE_HUSH_UNSET
1220 	BLTIN("unset"    , builtin_unset   , "Unset variables"),
1221 #endif
1222 #if ENABLE_HUSH_WAIT
1223 	BLTIN("wait"     , builtin_wait    , "Wait for process to finish"),
1224 #endif
1225 };
1226 /* These builtins won't be used if we are on NOMMU and need to re-exec
1227  * (it's cheaper to run an external program in this case):
1228  */
1229 static const struct built_in_command bltins2[] ALIGN_PTR = {
1230 #if ENABLE_HUSH_TEST
1231 	BLTIN("["        , builtin_test    , NULL),
1232 #endif
1233 #if BASH_TEST2
1234 	BLTIN("[["       , builtin_test    , NULL),
1235 #endif
1236 #if ENABLE_HUSH_ECHO
1237 	BLTIN("echo"     , builtin_echo    , NULL),
1238 #endif
1239 #if ENABLE_HUSH_PRINTF
1240 	BLTIN("printf"   , builtin_printf  , NULL),
1241 #endif
1242 	BLTIN("pwd"      , builtin_pwd     , NULL),
1243 #if ENABLE_HUSH_TEST
1244 	BLTIN("test"     , builtin_test    , NULL),
1245 #endif
1246 };
1247 
1248 
1249 /* Debug printouts.
1250  */
1251 #if HUSH_DEBUG >= 2
1252 /* prevent disasters with G.debug_indent < 0 */
1253 # define indent() fdprintf(2, "%*s", (G.debug_indent * 2) & 0xff, "")
1254 # define debug_enter() (G.debug_indent++)
1255 # define debug_leave() (G.debug_indent--)
1256 #else
1257 # define indent()      ((void)0)
1258 # define debug_enter() ((void)0)
1259 # define debug_leave() ((void)0)
1260 #endif
1261 
1262 #ifndef debug_printf
1263 # define debug_printf(...) (indent(), fdprintf(2, __VA_ARGS__))
1264 #endif
1265 
1266 #ifndef debug_printf_parse
1267 # define debug_printf_parse(...) (indent(), fdprintf(2, __VA_ARGS__))
1268 #endif
1269 
1270 #ifndef debug_printf_heredoc
1271 # define debug_printf_heredoc(...) (indent(), fdprintf(2, __VA_ARGS__))
1272 #endif
1273 
1274 #ifndef debug_printf_exec
1275 #define debug_printf_exec(...) (indent(), fdprintf(2, __VA_ARGS__))
1276 #endif
1277 
1278 #ifndef debug_printf_env
1279 # define debug_printf_env(...) (indent(), fdprintf(2, __VA_ARGS__))
1280 #endif
1281 
1282 #ifndef debug_printf_jobs
1283 # define debug_printf_jobs(...) (indent(), fdprintf(2, __VA_ARGS__))
1284 # define DEBUG_JOBS 1
1285 #else
1286 # define DEBUG_JOBS 0
1287 #endif
1288 
1289 #ifndef debug_printf_expand
1290 # define debug_printf_expand(...) (indent(), fdprintf(2, __VA_ARGS__))
1291 # define DEBUG_EXPAND 1
1292 #else
1293 # define DEBUG_EXPAND 0
1294 #endif
1295 
1296 #ifndef debug_printf_varexp
1297 # define debug_printf_varexp(...) (indent(), fdprintf(2, __VA_ARGS__))
1298 #endif
1299 
1300 #ifndef debug_printf_glob
1301 # define debug_printf_glob(...) (indent(), fdprintf(2, __VA_ARGS__))
1302 # define DEBUG_GLOB 1
1303 #else
1304 # define DEBUG_GLOB 0
1305 #endif
1306 
1307 #ifndef debug_printf_redir
1308 # define debug_printf_redir(...) (indent(), fdprintf(2, __VA_ARGS__))
1309 #endif
1310 
1311 #ifndef debug_printf_list
1312 # define debug_printf_list(...) (indent(), fdprintf(2, __VA_ARGS__))
1313 #endif
1314 
1315 #ifndef debug_printf_subst
1316 # define debug_printf_subst(...) (indent(), fdprintf(2, __VA_ARGS__))
1317 #endif
1318 
1319 #ifndef debug_printf_prompt
1320 # define debug_printf_prompt(...) (indent(), fdprintf(2, __VA_ARGS__))
1321 #endif
1322 
1323 #ifndef debug_printf_clean
1324 # define debug_printf_clean(...) (indent(), fdprintf(2, __VA_ARGS__))
1325 # define DEBUG_CLEAN 1
1326 #else
1327 # define DEBUG_CLEAN 0
1328 #endif
1329 
1330 #if DEBUG_EXPAND
debug_print_strings(const char * prefix,char ** vv)1331 static void debug_print_strings(const char *prefix, char **vv)
1332 {
1333 	indent();
1334 	fdprintf(2, "%s:\n", prefix);
1335 	while (*vv)
1336 		fdprintf(2, " '%s'\n", *vv++);
1337 }
1338 #else
1339 # define debug_print_strings(prefix, vv) ((void)0)
1340 #endif
1341 
1342 
1343 /* Leak hunting. Use hush_leaktool.sh for post-processing.
1344  */
1345 #if LEAK_HUNTING
xxmalloc(int lineno,size_t size)1346 static void *xxmalloc(int lineno, size_t size)
1347 {
1348 	void *ptr = xmalloc((size + 0xff) & ~0xff);
1349 	fdprintf(2, "line %d: malloc %p\n", lineno, ptr);
1350 	return ptr;
1351 }
xxrealloc(int lineno,void * ptr,size_t size)1352 static void *xxrealloc(int lineno, void *ptr, size_t size)
1353 {
1354 	ptr = xrealloc(ptr, (size + 0xff) & ~0xff);
1355 	fdprintf(2, "line %d: realloc %p\n", lineno, ptr);
1356 	return ptr;
1357 }
xxstrdup(int lineno,const char * str)1358 static char *xxstrdup(int lineno, const char *str)
1359 {
1360 	char *ptr = xstrdup(str);
1361 	fdprintf(2, "line %d: strdup %p\n", lineno, ptr);
1362 	return ptr;
1363 }
xxfree(void * ptr)1364 static void xxfree(void *ptr)
1365 {
1366 	fdprintf(2, "free %p\n", ptr);
1367 	free(ptr);
1368 }
1369 # define xmalloc(s)     xxmalloc(__LINE__, s)
1370 # define xrealloc(p, s) xxrealloc(__LINE__, p, s)
1371 # define xstrdup(s)     xxstrdup(__LINE__, s)
1372 # define free(p)        xxfree(p)
1373 #endif
1374 
1375 
1376 /* Syntax and runtime errors. They always abort scripts.
1377  * In interactive use they usually discard unparsed and/or unexecuted commands
1378  * and return to the prompt.
1379  * HUSH_DEBUG >= 2 prints line number in this file where it was detected.
1380  */
1381 #if HUSH_DEBUG < 2
1382 # define msg_and_die_if_script(lineno, ...)     msg_and_die_if_script(__VA_ARGS__)
1383 # define syntax_error(lineno, msg)              syntax_error(msg)
1384 # define syntax_error_at(lineno, msg)           syntax_error_at(msg)
1385 # define syntax_error_unterm_ch(lineno, ch)     syntax_error_unterm_ch(ch)
1386 # define syntax_error_unterm_str(lineno, s)     syntax_error_unterm_str(s)
1387 # define syntax_error_unexpected_ch(lineno, ch) syntax_error_unexpected_ch(ch)
1388 #endif
1389 
die_if_script(void)1390 static void die_if_script(void)
1391 {
1392 	if (!G_interactive_fd) {
1393 		if (G.last_exitcode) /* sometines it's 2, not 1 (bash compat) */
1394 			xfunc_error_retval = G.last_exitcode;
1395 		xfunc_die();
1396 	}
1397 }
1398 
msg_and_die_if_script(unsigned lineno,const char * fmt,...)1399 static void msg_and_die_if_script(unsigned lineno, const char *fmt, ...)
1400 {
1401 	va_list p;
1402 
1403 #if HUSH_DEBUG >= 2
1404 	bb_error_msg("hush.c:%u", lineno);
1405 #endif
1406 	va_start(p, fmt);
1407 	bb_verror_msg(fmt, p, NULL);
1408 	va_end(p);
1409 	die_if_script();
1410 }
1411 
syntax_error(unsigned lineno UNUSED_PARAM,const char * msg)1412 static void syntax_error(unsigned lineno UNUSED_PARAM, const char *msg)
1413 {
1414 	if (msg)
1415 		bb_error_msg("syntax error: %s", msg);
1416 	else
1417 		bb_simple_error_msg("syntax error");
1418 	die_if_script();
1419 }
1420 
syntax_error_at(unsigned lineno UNUSED_PARAM,const char * msg)1421 static void syntax_error_at(unsigned lineno UNUSED_PARAM, const char *msg)
1422 {
1423 	bb_error_msg("syntax error at '%s'", msg);
1424 	die_if_script();
1425 }
1426 
syntax_error_unterm_str(unsigned lineno UNUSED_PARAM,const char * s)1427 static void syntax_error_unterm_str(unsigned lineno UNUSED_PARAM, const char *s)
1428 {
1429 	bb_error_msg("syntax error: unterminated %s", s);
1430 //? source4.tests fails: in bash, echo ${^} in script does not terminate the script
1431 //	die_if_script();
1432 }
1433 
syntax_error_unterm_ch(unsigned lineno,char ch)1434 static void syntax_error_unterm_ch(unsigned lineno, char ch)
1435 {
1436 	char msg[2] = { ch, '\0' };
1437 	syntax_error_unterm_str(lineno, msg);
1438 }
1439 
syntax_error_unexpected_ch(unsigned lineno UNUSED_PARAM,int ch)1440 static void syntax_error_unexpected_ch(unsigned lineno UNUSED_PARAM, int ch)
1441 {
1442 	char msg[2];
1443 	msg[0] = ch;
1444 	msg[1] = '\0';
1445 #if HUSH_DEBUG >= 2
1446 	bb_error_msg("hush.c:%u", lineno);
1447 #endif
1448 	bb_error_msg("syntax error: unexpected %s", ch == EOF ? "EOF" : msg);
1449 	die_if_script();
1450 }
1451 
1452 #if HUSH_DEBUG < 2
1453 # undef msg_and_die_if_script
1454 # undef syntax_error
1455 # undef syntax_error_at
1456 # undef syntax_error_unterm_ch
1457 # undef syntax_error_unterm_str
1458 # undef syntax_error_unexpected_ch
1459 #else
1460 # define msg_and_die_if_script(...)     msg_and_die_if_script(__LINE__, __VA_ARGS__)
1461 # define syntax_error(msg)              syntax_error(__LINE__, msg)
1462 # define syntax_error_at(msg)           syntax_error_at(__LINE__, msg)
1463 # define syntax_error_unterm_ch(ch)     syntax_error_unterm_ch(__LINE__, ch)
1464 # define syntax_error_unterm_str(s)     syntax_error_unterm_str(__LINE__, s)
1465 # define syntax_error_unexpected_ch(ch) syntax_error_unexpected_ch(__LINE__, ch)
1466 #endif
1467 
1468 
1469 /* Utility functions
1470  */
1471 /* Replace each \x with x in place, return ptr past NUL. */
unbackslash(char * src)1472 static char *unbackslash(char *src)
1473 {
1474 	char *dst = src = strchrnul(src, '\\');
1475 	while (1) {
1476 		if (*src == '\\') {
1477 			src++;
1478 			if (*src != '\0') {
1479 				/* \x -> x */
1480 				*dst++ = *src++;
1481 				continue;
1482 			}
1483 			/* else: "\<nul>". Do not delete this backslash.
1484 			 * Testcase: eval 'echo ok\'
1485 			 */
1486 			*dst++ = '\\';
1487 			/* fallthrough */
1488 		}
1489 		if ((*dst++ = *src++) == '\0')
1490 			break;
1491 	}
1492 	return dst;
1493 }
1494 
add_strings_to_strings(char ** strings,char ** add,int need_to_dup)1495 static char **add_strings_to_strings(char **strings, char **add, int need_to_dup)
1496 {
1497 	int i;
1498 	unsigned count1;
1499 	unsigned count2;
1500 	char **v;
1501 
1502 	v = strings;
1503 	count1 = 0;
1504 	if (v) {
1505 		while (*v) {
1506 			count1++;
1507 			v++;
1508 		}
1509 	}
1510 	count2 = 0;
1511 	v = add;
1512 	while (*v) {
1513 		count2++;
1514 		v++;
1515 	}
1516 	v = xrealloc(strings, (count1 + count2 + 1) * sizeof(char*));
1517 	v[count1 + count2] = NULL;
1518 	i = count2;
1519 	while (--i >= 0)
1520 		v[count1 + i] = (need_to_dup ? xstrdup(add[i]) : add[i]);
1521 	return v;
1522 }
1523 #if LEAK_HUNTING
xx_add_strings_to_strings(int lineno,char ** strings,char ** add,int need_to_dup)1524 static char **xx_add_strings_to_strings(int lineno, char **strings, char **add, int need_to_dup)
1525 {
1526 	char **ptr = add_strings_to_strings(strings, add, need_to_dup);
1527 	fdprintf(2, "line %d: add_strings_to_strings %p\n", lineno, ptr);
1528 	return ptr;
1529 }
1530 #define add_strings_to_strings(strings, add, need_to_dup) \
1531 	xx_add_strings_to_strings(__LINE__, strings, add, need_to_dup)
1532 #endif
1533 
1534 /* Note: takes ownership of "add" ptr (it is not strdup'ed) */
add_string_to_strings(char ** strings,char * add)1535 static char **add_string_to_strings(char **strings, char *add)
1536 {
1537 	char *v[2];
1538 	v[0] = add;
1539 	v[1] = NULL;
1540 	return add_strings_to_strings(strings, v, /*dup:*/ 0);
1541 }
1542 #if LEAK_HUNTING
xx_add_string_to_strings(int lineno,char ** strings,char * add)1543 static char **xx_add_string_to_strings(int lineno, char **strings, char *add)
1544 {
1545 	char **ptr = add_string_to_strings(strings, add);
1546 	fdprintf(2, "line %d: add_string_to_strings %p\n", lineno, ptr);
1547 	return ptr;
1548 }
1549 #define add_string_to_strings(strings, add) \
1550 	xx_add_string_to_strings(__LINE__, strings, add)
1551 #endif
1552 
free_strings(char ** strings)1553 static void free_strings(char **strings)
1554 {
1555 	char **v;
1556 
1557 	if (!strings)
1558 		return;
1559 	v = strings;
1560 	while (*v) {
1561 		free(*v);
1562 		v++;
1563 	}
1564 	free(strings);
1565 }
1566 
dup_CLOEXEC(int fd,int avoid_fd)1567 static int dup_CLOEXEC(int fd, int avoid_fd)
1568 {
1569 	int newfd;
1570  repeat:
1571 	newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
1572 	if (newfd >= 0) {
1573 		if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
1574 			fcntl(newfd, F_SETFD, FD_CLOEXEC);
1575 	} else { /* newfd < 0 */
1576 		if (errno == EBUSY)
1577 			goto repeat;
1578 		if (errno == EINTR)
1579 			goto repeat;
1580 	}
1581 	return newfd;
1582 }
1583 
xdup_CLOEXEC_and_close(int fd,int avoid_fd)1584 static int xdup_CLOEXEC_and_close(int fd, int avoid_fd)
1585 {
1586 	int newfd;
1587  repeat:
1588 	newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
1589 	if (newfd < 0) {
1590 		if (errno == EBUSY)
1591 			goto repeat;
1592 		if (errno == EINTR)
1593 			goto repeat;
1594 		/* fd was not open? */
1595 		if (errno == EBADF)
1596 			return fd;
1597 		xfunc_die();
1598 	}
1599 	if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
1600 		fcntl(newfd, F_SETFD, FD_CLOEXEC);
1601 	close(fd);
1602 	return newfd;
1603 }
1604 
1605 
1606 /* Manipulating HFILEs */
hfopen(const char * name)1607 static HFILE *hfopen(const char *name)
1608 {
1609 	HFILE *fp;
1610 	int fd;
1611 
1612 	fd = STDIN_FILENO;
1613 	if (name) {
1614 		fd = open(name, O_RDONLY | O_CLOEXEC);
1615 		if (fd < 0)
1616 			return NULL;
1617 		if (O_CLOEXEC == 0) /* ancient libc */
1618 			close_on_exec_on(fd);
1619 	}
1620 
1621 	fp = xmalloc(sizeof(*fp));
1622 	if (name == NULL)
1623 		G.HFILE_stdin = fp;
1624 	fp->fd = fd;
1625 	fp->cur = fp->end = fp->buf;
1626 	fp->next_hfile = G.HFILE_list;
1627 	G.HFILE_list = fp;
1628 	return fp;
1629 }
hfclose(HFILE * fp)1630 static void hfclose(HFILE *fp)
1631 {
1632 	HFILE **pp = &G.HFILE_list;
1633 	while (*pp) {
1634 		HFILE *cur = *pp;
1635 		if (cur == fp) {
1636 			*pp = cur->next_hfile;
1637 			break;
1638 		}
1639 		pp = &cur->next_hfile;
1640 	}
1641 	if (fp->fd >= 0)
1642 		close(fp->fd);
1643 	free(fp);
1644 }
refill_HFILE_and_getc(HFILE * fp)1645 static int refill_HFILE_and_getc(HFILE *fp)
1646 {
1647 	int n;
1648 
1649 	if (fp->fd < 0) {
1650 		/* Already saw EOF */
1651 		return EOF;
1652 	}
1653 #if ENABLE_HUSH_INTERACTIVE && !ENABLE_FEATURE_EDITING
1654 	/* If user presses ^C, read() restarts after SIGINT (we use SA_RESTART).
1655 	 * IOW: ^C will not immediately stop line input.
1656 	 * But poll() is different: it does NOT restart after signals.
1657 	 */
1658 	if (fp == G.HFILE_stdin) {
1659 		struct pollfd pfd[1];
1660 		pfd[0].fd = fp->fd;
1661 		pfd[0].events = POLLIN;
1662 		n = poll(pfd, 1, -1);
1663 		if (n < 0
1664 		 /*&& errno == EINTR - assumed true */
1665 		 && sigismember(&G.pending_set, SIGINT)
1666 		) {
1667 			return '\0';
1668 		}
1669 	}
1670 #else
1671 /* if FEATURE_EDITING=y, we do not use this routine for interactive input */
1672 #endif
1673 	/* Try to buffer more input */
1674 	n = safe_read(fp->fd, fp->buf, sizeof(fp->buf));
1675 	if (n < 0) {
1676 		bb_simple_perror_msg("read error");
1677 		n = 0;
1678 	}
1679 	fp->cur = fp->buf;
1680 	fp->end = fp->buf + n;
1681 	if (n == 0) {
1682 		/* EOF/error */
1683 		close(fp->fd);
1684 		fp->fd = -1;
1685 		return EOF;
1686 	}
1687 	return (unsigned char)(*fp->cur++);
1688 }
1689 /* Inlined for common case of non-empty buffer.
1690  */
hfgetc(HFILE * fp)1691 static ALWAYS_INLINE int hfgetc(HFILE *fp)
1692 {
1693 	if (fp->cur < fp->end)
1694 		return (unsigned char)(*fp->cur++);
1695 	/* Buffer empty */
1696 	return refill_HFILE_and_getc(fp);
1697 }
move_HFILEs_on_redirect(int fd,int avoid_fd)1698 static int move_HFILEs_on_redirect(int fd, int avoid_fd)
1699 {
1700 	HFILE *fl = G.HFILE_list;
1701 	while (fl) {
1702 		if (fd == fl->fd) {
1703 			/* We use it only on script files, they are all CLOEXEC */
1704 			fl->fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
1705 			debug_printf_redir("redirect_fd %d: matches a script fd, moving it to %d\n", fd, fl->fd);
1706 			return 1; /* "found and moved" */
1707 		}
1708 		fl = fl->next_hfile;
1709 	}
1710 #if ENABLE_HUSH_MODE_X
1711 	if (G.x_mode_fd > 0 && fd == G.x_mode_fd) {
1712 		G.x_mode_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
1713 		return 1; /* "found and moved" */
1714 	}
1715 #endif
1716 	return 0; /* "not in the list" */
1717 }
1718 #if ENABLE_FEATURE_SH_STANDALONE && BB_MMU
close_all_HFILE_list(void)1719 static void close_all_HFILE_list(void)
1720 {
1721 	HFILE *fl = G.HFILE_list;
1722 	while (fl) {
1723 		/* hfclose would also free HFILE object.
1724 		 * It is disastrous if we share memory with a vforked parent.
1725 		 * I'm not sure we never come here after vfork.
1726 		 * Therefore just close fd, nothing more.
1727 		 *
1728 		 * ">" instead of ">=": we don't close fd#0,
1729 		 * interactive shell uses hfopen(NULL) as stdin input
1730 		 * which has fl->fd == 0, but fd#0 gets redirected in pipes.
1731 		 * If we'd close it here, then e.g. interactive "set | sort"
1732 		 * with NOFORKed sort, would have sort's input fd closed.
1733 		 */
1734 		if (fl->fd > 0)
1735 			/*hfclose(fl); - unsafe */
1736 			close(fl->fd);
1737 		fl = fl->next_hfile;
1738 	}
1739 }
1740 #endif
fd_in_HFILEs(int fd)1741 static int fd_in_HFILEs(int fd)
1742 {
1743 	HFILE *fl = G.HFILE_list;
1744 	while (fl) {
1745 		if (fl->fd == fd)
1746 			return 1;
1747 		fl = fl->next_hfile;
1748 	}
1749 	return 0;
1750 }
1751 
1752 
1753 /* Helpers for setting new $n and restoring them back
1754  */
1755 typedef struct save_arg_t {
1756 	char *sv_argv0;
1757 	char **sv_g_argv;
1758 	int sv_g_argc;
1759 	IF_HUSH_SET(smallint sv_g_malloced;)
1760 } save_arg_t;
1761 
save_and_replace_G_args(save_arg_t * sv,char ** argv)1762 static void save_and_replace_G_args(save_arg_t *sv, char **argv)
1763 {
1764 	sv->sv_argv0 = argv[0];
1765 	sv->sv_g_argv = G.global_argv;
1766 	sv->sv_g_argc = G.global_argc;
1767 	IF_HUSH_SET(sv->sv_g_malloced = G.global_args_malloced;)
1768 
1769 	argv[0] = G.global_argv[0]; /* retain $0 */
1770 	G.global_argv = argv;
1771 	IF_HUSH_SET(G.global_args_malloced = 0;)
1772 
1773 	G.global_argc = 1 + string_array_len(argv + 1);
1774 }
1775 
restore_G_args(save_arg_t * sv,char ** argv)1776 static void restore_G_args(save_arg_t *sv, char **argv)
1777 {
1778 #if ENABLE_HUSH_SET
1779 	if (G.global_args_malloced) {
1780 		/* someone ran "set -- arg1 arg2 ...", undo */
1781 		char **pp = G.global_argv;
1782 		while (*++pp) /* note: does not free $0 */
1783 			free(*pp);
1784 		free(G.global_argv);
1785 	}
1786 #endif
1787 	argv[0] = sv->sv_argv0;
1788 	G.global_argv = sv->sv_g_argv;
1789 	G.global_argc = sv->sv_g_argc;
1790 	IF_HUSH_SET(G.global_args_malloced = sv->sv_g_malloced;)
1791 }
1792 
1793 
1794 /* Basic theory of signal handling in shell
1795  * ========================================
1796  * This does not describe what hush does, rather, it is current understanding
1797  * what it _should_ do. If it doesn't, it's a bug.
1798  * http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#trap
1799  *
1800  * Signals are handled only after each pipe ("cmd | cmd | cmd" thing)
1801  * is finished or backgrounded. It is the same in interactive and
1802  * non-interactive shells, and is the same regardless of whether
1803  * a user trap handler is installed or a shell special one is in effect.
1804  * ^C or ^Z from keyboard seems to execute "at once" because it usually
1805  * backgrounds (i.e. stops) or kills all members of currently running
1806  * pipe.
1807  *
1808  * Wait builtin is interruptible by signals for which user trap is set
1809  * or by SIGINT in interactive shell.
1810  *
1811  * Trap handlers will execute even within trap handlers. (right?)
1812  *
1813  * User trap handlers are forgotten when subshell ("(cmd)") is entered,
1814  * except for handlers set to '' (empty string).
1815  *
1816  * If job control is off, backgrounded commands ("cmd &")
1817  * have SIGINT, SIGQUIT set to SIG_IGN.
1818  *
1819  * Commands which are run in command substitution ("`cmd`")
1820  * have SIGTTIN, SIGTTOU, SIGTSTP set to SIG_IGN.
1821  *
1822  * Ordinary commands have signals set to SIG_IGN/DFL as inherited
1823  * by the shell from its parent.
1824  *
1825  * Signals which differ from SIG_DFL action
1826  * (note: child (i.e., [v]forked) shell is not an interactive shell):
1827  *
1828  * SIGQUIT: ignore
1829  * SIGTERM (interactive): ignore
1830  * SIGHUP (interactive):
1831  *    send SIGCONT to stopped jobs, send SIGHUP to all jobs and exit
1832  * SIGTTIN, SIGTTOU, SIGTSTP (if job control is on): ignore
1833  *    Note that ^Z is handled not by trapping SIGTSTP, but by seeing
1834  *    that all pipe members are stopped. Try this in bash:
1835  *    while :; do :; done - ^Z does not background it
1836  *    (while :; do :; done) - ^Z backgrounds it
1837  * SIGINT (interactive): wait for last pipe, ignore the rest
1838  *    of the command line, show prompt. NB: ^C does not send SIGINT
1839  *    to interactive shell while shell is waiting for a pipe,
1840  *    since shell is bg'ed (is not in foreground process group).
1841  *    Example 1: this waits 5 sec, but does not execute ls:
1842  *    "echo $$; sleep 5; ls -l" + "kill -INT <pid>"
1843  *    Example 2: this does not wait and does not execute ls:
1844  *    "echo $$; sleep 5 & wait; ls -l" + "kill -INT <pid>"
1845  *    Example 3: this does not wait 5 sec, but executes ls:
1846  *    "sleep 5; ls -l" + press ^C
1847  *    Example 4: this does not wait and does not execute ls:
1848  *    "sleep 5 & wait; ls -l" + press ^C
1849  *
1850  * (What happens to signals which are IGN on shell start?)
1851  * (What happens with signal mask on shell start?)
1852  *
1853  * Old implementation
1854  * ==================
1855  * We use in-kernel pending signal mask to determine which signals were sent.
1856  * We block all signals which we don't want to take action immediately,
1857  * i.e. we block all signals which need to have special handling as described
1858  * above, and all signals which have traps set.
1859  * After each pipe execution, we extract any pending signals via sigtimedwait()
1860  * and act on them.
1861  *
1862  * unsigned special_sig_mask: a mask of such "special" signals
1863  * sigset_t blocked_set:  current blocked signal set
1864  *
1865  * "trap - SIGxxx":
1866  *    clear bit in blocked_set unless it is also in special_sig_mask
1867  * "trap 'cmd' SIGxxx":
1868  *    set bit in blocked_set (even if 'cmd' is '')
1869  * after [v]fork, if we plan to be a shell:
1870  *    unblock signals with special interactive handling
1871  *    (child shell is not interactive),
1872  *    unset all traps except '' (note: regardless of child shell's type - {}, (), etc)
1873  * after [v]fork, if we plan to exec:
1874  *    POSIX says fork clears pending signal mask in child - no need to clear it.
1875  *    Restore blocked signal set to one inherited by shell just prior to exec.
1876  *
1877  * Note: as a result, we do not use signal handlers much. The only uses
1878  * are to count SIGCHLDs
1879  * and to restore tty pgrp on signal-induced exit.
1880  *
1881  * Note 2 (compat):
1882  * Standard says "When a subshell is entered, traps that are not being ignored
1883  * are set to the default actions". bash interprets it so that traps which
1884  * are set to '' (ignore) are NOT reset to defaults. We do the same.
1885  *
1886  * Problem: the above approach makes it unwieldy to catch signals while
1887  * we are in read builtin, or while we read commands from stdin:
1888  * masked signals are not visible!
1889  *
1890  * New implementation
1891  * ==================
1892  * We record each signal we are interested in by installing signal handler
1893  * for them - a bit like emulating kernel pending signal mask in userspace.
1894  * We are interested in: signals which need to have special handling
1895  * as described above, and all signals which have traps set.
1896  * Signals are recorded in pending_set.
1897  * After each pipe execution, we extract any pending signals
1898  * and act on them.
1899  *
1900  * unsigned special_sig_mask: a mask of shell-special signals.
1901  * unsigned fatal_sig_mask: a mask of signals on which we restore tty pgrp.
1902  * char *traps[sig] if trap for sig is set (even if it's '').
1903  * sigset_t pending_set: set of sigs we received.
1904  *
1905  * "trap - SIGxxx":
1906  *    if sig is in special_sig_mask, set handler back to:
1907  *        record_pending_signo, or to IGN if it's a tty stop signal
1908  *    if sig is in fatal_sig_mask, set handler back to sigexit.
1909  *    else: set handler back to SIG_DFL
1910  * "trap 'cmd' SIGxxx":
1911  *    set handler to record_pending_signo.
1912  * "trap '' SIGxxx":
1913  *    set handler to SIG_IGN.
1914  * after [v]fork, if we plan to be a shell:
1915  *    set signals with special interactive handling to SIG_DFL
1916  *    (because child shell is not interactive),
1917  *    unset all traps except '' (note: regardless of child shell's type - {}, (), etc)
1918  * after [v]fork, if we plan to exec:
1919  *    POSIX says fork clears pending signal mask in child - no need to clear it.
1920  *
1921  * To make wait builtin interruptible, we handle SIGCHLD as special signal,
1922  * otherwise (if we leave it SIG_DFL) sigsuspend in wait builtin will not wake up on it.
1923  *
1924  * Note (compat):
1925  * Standard says "When a subshell is entered, traps that are not being ignored
1926  * are set to the default actions". bash interprets it so that traps which
1927  * are set to '' (ignore) are NOT reset to defaults. We do the same.
1928  */
1929 enum {
1930 	SPECIAL_INTERACTIVE_SIGS = 0
1931 		| (1 << SIGTERM)
1932 		| (1 << SIGINT)
1933 		| (1 << SIGHUP)
1934 		,
1935 	SPECIAL_JOBSTOP_SIGS = 0
1936 #if ENABLE_HUSH_JOB
1937 		| (1 << SIGTTIN)
1938 		| (1 << SIGTTOU)
1939 		| (1 << SIGTSTP)
1940 #endif
1941 		,
1942 };
1943 
record_pending_signo(int sig)1944 static void record_pending_signo(int sig)
1945 {
1946 	sigaddset(&G.pending_set, sig);
1947 #if ENABLE_HUSH_FAST
1948 	if (sig == SIGCHLD) {
1949 		G.count_SIGCHLD++;
1950 //bb_error_msg("[%d] SIGCHLD_handler: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
1951 	}
1952 #endif
1953 }
1954 
install_sighandler(int sig,sighandler_t handler)1955 static sighandler_t install_sighandler(int sig, sighandler_t handler)
1956 {
1957 	struct sigaction old_sa;
1958 
1959 	/* We could use signal() to install handlers... almost:
1960 	 * except that we need to mask ALL signals while handlers run.
1961 	 * I saw signal nesting in strace, race window isn't small.
1962 	 * SA_RESTART is also needed, but in Linux, signal()
1963 	 * sets SA_RESTART too.
1964 	 */
1965 	/* memset(&G.sa, 0, sizeof(G.sa)); - already done */
1966 	/* sigfillset(&G.sa.sa_mask);      - already done */
1967 	/* G.sa.sa_flags = SA_RESTART;     - already done */
1968 	G.sa.sa_handler = handler;
1969 	sigaction(sig, &G.sa, &old_sa);
1970 	return old_sa.sa_handler;
1971 }
1972 
1973 static void hush_exit(int exitcode) NORETURN;
1974 
1975 static void restore_ttypgrp_and__exit(void) NORETURN;
restore_ttypgrp_and__exit(void)1976 static void restore_ttypgrp_and__exit(void)
1977 {
1978 	/* xfunc has failed! die die die */
1979 	/* no EXIT traps, this is an escape hatch! */
1980 	G.exiting = 1;
1981 	hush_exit(xfunc_error_retval);
1982 }
1983 
1984 #if ENABLE_HUSH_JOB
1985 
1986 /* Needed only on some libc:
1987  * It was observed that on exit(), fgetc'ed buffered data
1988  * gets "unwound" via lseek(fd, -NUM, SEEK_CUR).
1989  * With the net effect that even after fork(), not vfork(),
1990  * exit() in NOEXECed applet in "sh SCRIPT":
1991  *	noexec_applet_here
1992  *	echo END_OF_SCRIPT
1993  * lseeks fd in input FILE object from EOF to "e" in "echo END_OF_SCRIPT".
1994  * This makes "echo END_OF_SCRIPT" executed twice.
1995  * Similar problems can be seen with msg_and_die_if_script() -> xfunc_die()
1996  * and in `cmd` handling.
1997  * If set as die_func(), this makes xfunc_die() exit via _exit(), not exit():
1998  */
1999 static void fflush_and__exit(void) NORETURN;
fflush_and__exit(void)2000 static void fflush_and__exit(void)
2001 {
2002 	fflush_all();
2003 	_exit(xfunc_error_retval);
2004 }
2005 
2006 /* After [v]fork, in child: do not restore tty pgrp on xfunc death */
2007 # define disable_restore_tty_pgrp_on_exit() (die_func = fflush_and__exit)
2008 /* After [v]fork, in parent: restore tty pgrp on xfunc death */
2009 # define enable_restore_tty_pgrp_on_exit()  (die_func = restore_ttypgrp_and__exit)
2010 
2011 /* Restores tty foreground process group, and exits.
2012  * May be called as signal handler for fatal signal
2013  * (will resend signal to itself, producing correct exit state)
2014  * or called directly with -EXITCODE.
2015  * We also call it if xfunc is exiting.
2016  */
2017 static void sigexit(int sig) NORETURN;
sigexit(int sig)2018 static void sigexit(int sig)
2019 {
2020 	/* Careful: we can end up here after [v]fork. Do not restore
2021 	 * tty pgrp then, only top-level shell process does that */
2022 	if (G_saved_tty_pgrp && getpid() == G.root_pid) {
2023 		/* Disable all signals: job control, SIGPIPE, etc.
2024 		 * Mostly paranoid measure, to prevent infinite SIGTTOU.
2025 		 */
2026 		sigprocmask_allsigs(SIG_BLOCK);
2027 		tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp);
2028 	}
2029 
2030 	/* Not a signal, just exit */
2031 	if (sig <= 0)
2032 		_exit(- sig);
2033 
2034 	kill_myself_with_sig(sig); /* does not return */
2035 }
2036 #else
2037 
2038 # define disable_restore_tty_pgrp_on_exit() ((void)0)
2039 # define enable_restore_tty_pgrp_on_exit()  ((void)0)
2040 
2041 #endif
2042 
pick_sighandler(unsigned sig)2043 static sighandler_t pick_sighandler(unsigned sig)
2044 {
2045 	sighandler_t handler = SIG_DFL;
2046 	if (sig < sizeof(unsigned)*8) {
2047 		unsigned sigmask = (1 << sig);
2048 
2049 #if ENABLE_HUSH_JOB
2050 		/* is sig fatal? */
2051 		if (G_fatal_sig_mask & sigmask)
2052 			handler = sigexit;
2053 		else
2054 #endif
2055 		/* sig has special handling? */
2056 		if (G.special_sig_mask & sigmask) {
2057 			handler = record_pending_signo;
2058 			/* TTIN/TTOU/TSTP can't be set to record_pending_signo
2059 			 * in order to ignore them: they will be raised
2060 			 * in an endless loop when we try to do some
2061 			 * terminal ioctls! We do have to _ignore_ these.
2062 			 */
2063 			if (SPECIAL_JOBSTOP_SIGS & sigmask)
2064 				handler = SIG_IGN;
2065 		}
2066 	}
2067 	return handler;
2068 }
2069 
2070 /* Restores tty foreground process group, and exits. */
hush_exit(int exitcode)2071 static void hush_exit(int exitcode)
2072 {
2073 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
2074 	save_history(G.line_input_state); /* may be NULL */
2075 #endif
2076 
2077 	fflush_all();
2078 	if (G.exiting <= 0 && G_traps && G_traps[0] && G_traps[0][0]) {
2079 		char *argv[3];
2080 		/* argv[0] is unused */
2081 		argv[1] = xstrdup(G_traps[0]); /* copy, since EXIT trap handler may modify G_traps[0] */
2082 		argv[2] = NULL;
2083 		G.exiting = 1; /* prevent EXIT trap recursion */
2084 		/* Note: G_traps[0] is not cleared!
2085 		 * "trap" will still show it, if executed
2086 		 * in the handler */
2087 		builtin_eval(argv);
2088 	}
2089 
2090 #if ENABLE_FEATURE_CLEAN_UP
2091 	{
2092 		struct variable *cur_var;
2093 		if (G.cwd != bb_msg_unknown)
2094 			free((char*)G.cwd);
2095 		cur_var = G.top_var;
2096 		while (cur_var) {
2097 			struct variable *tmp = cur_var;
2098 			if (!cur_var->max_len)
2099 				free(cur_var->varstr);
2100 			cur_var = cur_var->next;
2101 			free(tmp);
2102 		}
2103 	}
2104 #endif
2105 
2106 	fflush_all();
2107 #if ENABLE_HUSH_JOB
2108 	sigexit(- (exitcode & 0xff));
2109 #else
2110 	_exit(exitcode);
2111 #endif
2112 }
2113 
2114 //TODO: return a mask of ALL handled sigs?
check_and_run_traps(void)2115 static int check_and_run_traps(void)
2116 {
2117 	int last_sig = 0;
2118 
2119 	while (1) {
2120 		int sig;
2121 
2122 		if (sigisemptyset(&G.pending_set))
2123 			break;
2124 		sig = 0;
2125 		do {
2126 			sig++;
2127 			if (sigismember(&G.pending_set, sig)) {
2128 				sigdelset(&G.pending_set, sig);
2129 				goto got_sig;
2130 			}
2131 		} while (sig < NSIG);
2132 		break;
2133  got_sig:
2134 #if ENABLE_HUSH_TRAP
2135 		if (G_traps && G_traps[sig]) {
2136 			debug_printf_exec("%s: sig:%d handler:'%s'\n", __func__, sig, G.traps[sig]);
2137 			if (G_traps[sig][0]) {
2138 				/* We have user-defined handler */
2139 				smalluint save_rcode;
2140 				int save_pre;
2141 				char *argv[3];
2142 				/* argv[0] is unused */
2143 				argv[1] = xstrdup(G_traps[sig]);
2144 				/* why strdup? trap can modify itself: trap 'trap "echo oops" INT' INT */
2145 				argv[2] = NULL;
2146 				save_pre = G.pre_trap_exitcode;
2147 				G.pre_trap_exitcode = save_rcode = G.last_exitcode;
2148 				builtin_eval(argv);
2149 				free(argv[1]);
2150 				G.pre_trap_exitcode = save_pre;
2151 				G.last_exitcode = save_rcode;
2152 # if ENABLE_HUSH_FUNCTIONS
2153 				if (G.return_exitcode >= 0) {
2154 					debug_printf_exec("trap exitcode:%d\n", G.return_exitcode);
2155 					G.last_exitcode = G.return_exitcode;
2156 				}
2157 # endif
2158 				last_sig = sig;
2159 			} /* else: "" trap, ignoring signal */
2160 			continue;
2161 		}
2162 #endif
2163 		/* not a trap: special action */
2164 		switch (sig) {
2165 		case SIGINT:
2166 			debug_printf_exec("%s: sig:%d default SIGINT handler\n", __func__, sig);
2167 			G.flag_SIGINT = 1;
2168 			last_sig = sig;
2169 			break;
2170 #if ENABLE_HUSH_JOB
2171 		case SIGHUP: {
2172 //TODO: why are we doing this? ash and dash don't do this,
2173 //they have no handler for SIGHUP at all,
2174 //they rely on kernel to send SIGHUP+SIGCONT to orphaned process groups
2175 			struct pipe *job;
2176 			debug_printf_exec("%s: sig:%d default SIGHUP handler\n", __func__, sig);
2177 			/* bash is observed to signal whole process groups,
2178 			 * not individual processes */
2179 			for (job = G.job_list; job; job = job->next) {
2180 				if (job->pgrp <= 0)
2181 					continue;
2182 				debug_printf_exec("HUPing pgrp %d\n", job->pgrp);
2183 				if (kill(- job->pgrp, SIGHUP) == 0)
2184 					kill(- job->pgrp, SIGCONT);
2185 			}
2186 			sigexit(SIGHUP);
2187 		}
2188 #endif
2189 #if ENABLE_HUSH_FAST
2190 		case SIGCHLD:
2191 			debug_printf_exec("%s: sig:%d default SIGCHLD handler\n", __func__, sig);
2192 			G.count_SIGCHLD++;
2193 //bb_error_msg("[%d] check_and_run_traps: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
2194 			/* Note:
2195 			 * We don't do 'last_sig = sig' here -> NOT returning this sig.
2196 			 * This simplifies wait builtin a bit.
2197 			 */
2198 			break;
2199 #endif
2200 		default: /* ignored: */
2201 			debug_printf_exec("%s: sig:%d default handling is to ignore\n", __func__, sig);
2202 			/* SIGTERM, SIGQUIT, SIGTTIN, SIGTTOU, SIGTSTP */
2203 			/* Note:
2204 			 * We don't do 'last_sig = sig' here -> NOT returning this sig.
2205 			 * Example: wait is not interrupted by TERM
2206 			 * in interactive shell, because TERM is ignored.
2207 			 */
2208 			break;
2209 		}
2210 	}
2211 	return last_sig;
2212 }
2213 
2214 
get_cwd(int force)2215 static const char *get_cwd(int force)
2216 {
2217 	if (force || G.cwd == NULL) {
2218 		/* xrealloc_getcwd_or_warn(arg) calls free(arg),
2219 		 * we must not try to free(bb_msg_unknown) */
2220 		if (G.cwd == bb_msg_unknown)
2221 			G.cwd = NULL;
2222 		G.cwd = xrealloc_getcwd_or_warn((char *)G.cwd);
2223 		if (!G.cwd)
2224 			G.cwd = bb_msg_unknown;
2225 	}
2226 	return G.cwd;
2227 }
2228 
2229 
2230 /*
2231  * Shell and environment variable support
2232  */
get_ptr_to_local_var(const char * name,unsigned len)2233 static struct variable **get_ptr_to_local_var(const char *name, unsigned len)
2234 {
2235 	struct variable **pp;
2236 	struct variable *cur;
2237 
2238 	pp = &G.top_var;
2239 	while ((cur = *pp) != NULL) {
2240 		if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=')
2241 			return pp;
2242 		pp = &cur->next;
2243 	}
2244 	return NULL;
2245 }
2246 
get_local_var_value(const char * name)2247 static const char* FAST_FUNC get_local_var_value(const char *name)
2248 {
2249 	struct variable **vpp;
2250 	unsigned len = strlen(name);
2251 
2252 	if (G.expanded_assignments) {
2253 		char **cpp = G.expanded_assignments;
2254 		while (*cpp) {
2255 			char *cp = *cpp;
2256 			if (strncmp(cp, name, len) == 0 && cp[len] == '=')
2257 				return cp + len + 1;
2258 			cpp++;
2259 		}
2260 	}
2261 
2262 	vpp = get_ptr_to_local_var(name, len);
2263 	if (vpp)
2264 		return (*vpp)->varstr + len + 1;
2265 
2266 	if (strcmp(name, "PPID") == 0)
2267 		return utoa(G.root_ppid);
2268 	// bash compat: UID? EUID?
2269 #if ENABLE_HUSH_RANDOM_SUPPORT
2270 	if (strcmp(name, "RANDOM") == 0)
2271 		return utoa(next_random(&G.random_gen));
2272 #endif
2273 #if ENABLE_HUSH_LINENO_VAR
2274 	if (strcmp(name, "LINENO") == 0)
2275 		return utoa(G.execute_lineno);
2276 #endif
2277 #if BASH_EPOCH_VARS
2278 	{
2279 		const char *fmt = NULL;
2280 		if (strcmp(name, "EPOCHSECONDS") == 0)
2281 			fmt = "%llu";
2282 		else if (strcmp(name, "EPOCHREALTIME") == 0)
2283 			fmt = "%llu.%06u";
2284 		if (fmt) {
2285 			struct timeval tv;
2286 			xgettimeofday(&tv);
2287 			sprintf(G.epoch_buf, fmt, (unsigned long long)tv.tv_sec,
2288 					(unsigned)tv.tv_usec);
2289 			return G.epoch_buf;
2290 		}
2291 	}
2292 #endif
2293 	return NULL;
2294 }
2295 
2296 #if ENABLE_HUSH_GETOPTS
handle_changed_special_names(const char * name,unsigned name_len)2297 static void handle_changed_special_names(const char *name, unsigned name_len)
2298 {
2299 	if (name_len == 6) {
2300 		if (strncmp(name, "OPTIND", 6) == 0) {
2301 			G.getopt_count = 0;
2302 			return;
2303 		}
2304 	}
2305 }
2306 #else
2307 /* Do not even bother evaluating arguments */
2308 # define handle_changed_special_names(...) ((void)0)
2309 #endif
2310 
2311 /* str holds "NAME=VAL" and is expected to be malloced.
2312  * We take ownership of it.
2313  */
2314 #define SETFLAG_EXPORT   (1 << 0)
2315 #define SETFLAG_UNEXPORT (1 << 1)
2316 #define SETFLAG_MAKE_RO  (1 << 2)
2317 #define SETFLAG_VARLVL_SHIFT   3
set_local_var(char * str,unsigned flags)2318 static int set_local_var(char *str, unsigned flags)
2319 {
2320 	struct variable **cur_pp;
2321 	struct variable *cur;
2322 	char *free_me = NULL;
2323 	char *eq_sign;
2324 	int name_len;
2325 	int retval;
2326 	unsigned local_lvl = (flags >> SETFLAG_VARLVL_SHIFT);
2327 
2328 	eq_sign = strchr(str, '=');
2329 	if (HUSH_DEBUG && !eq_sign)
2330 		bb_simple_error_msg_and_die("BUG in setvar");
2331 
2332 	name_len = eq_sign - str + 1; /* including '=' */
2333 	cur_pp = &G.top_var;
2334 	while ((cur = *cur_pp) != NULL) {
2335 		if (strncmp(cur->varstr, str, name_len) != 0) {
2336 			cur_pp = &cur->next;
2337 			continue;
2338 		}
2339 
2340 		/* We found an existing var with this name */
2341 		if (cur->flg_read_only) {
2342 			bb_error_msg("%s: readonly variable", str);
2343 			free(str);
2344 //NOTE: in bash, assignment in "export READONLY_VAR=Z" fails, and sets $?=1,
2345 //but export per se succeeds (does put the var in env). We don't mimic that.
2346 			return -1;
2347 		}
2348 		if (flags & SETFLAG_UNEXPORT) { // && cur->flg_export ?
2349 			debug_printf_env("%s: unsetenv '%s'\n", __func__, str);
2350 			*eq_sign = '\0';
2351 			unsetenv(str);
2352 			*eq_sign = '=';
2353 		}
2354 		if (cur->var_nest_level < local_lvl) {
2355 			/* bash 3.2.33(1) and exported vars:
2356 			 * # export z=z
2357 			 * # f() { local z=a; env | grep ^z; }
2358 			 * # f
2359 			 * z=a
2360 			 * # env | grep ^z
2361 			 * z=z
2362 			 */
2363 			if (cur->flg_export)
2364 				flags |= SETFLAG_EXPORT;
2365 			/* New variable is local ("local VAR=VAL" or
2366 			 * "VAR=VAL cmd")
2367 			 * and existing one is global, or local
2368 			 * on a lower level that new one.
2369 			 * Remove it from global variable list:
2370 			 */
2371 			*cur_pp = cur->next;
2372 			if (G.shadowed_vars_pp) {
2373 				/* Save in "shadowed" list */
2374 				debug_printf_env("shadowing %s'%s'/%u by '%s'/%u\n",
2375 					cur->flg_export ? "exported " : "",
2376 					cur->varstr, cur->var_nest_level, str, local_lvl
2377 				);
2378 				cur->next = *G.shadowed_vars_pp;
2379 				*G.shadowed_vars_pp = cur;
2380 			} else {
2381 				/* Came from pseudo_exec_argv(), no need to save: delete it */
2382 				debug_printf_env("shadow-deleting %s'%s'/%u by '%s'/%u\n",
2383 					cur->flg_export ? "exported " : "",
2384 					cur->varstr, cur->var_nest_level, str, local_lvl
2385 				);
2386 				if (cur->max_len == 0) /* allocated "VAR=VAL"? */
2387 					free_me = cur->varstr; /* then free it later */
2388 				free(cur);
2389 			}
2390 			break;
2391 		}
2392 
2393 		if (strcmp(cur->varstr + name_len, eq_sign + 1) == 0) {
2394 			debug_printf_env("assignement '%s' does not change anything\n", str);
2395  free_and_exp:
2396 			free(str);
2397 			goto exp;
2398 		}
2399 
2400 		/* Replace the value in the found "struct variable" */
2401 		if (cur->max_len != 0) {
2402 			if (cur->max_len >= strnlen(str, cur->max_len + 1)) {
2403 				/* This one is from startup env, reuse space */
2404 				debug_printf_env("reusing startup env for '%s'\n", str);
2405 				strcpy(cur->varstr, str);
2406 				goto free_and_exp;
2407 			}
2408 			/* Can't reuse */
2409 			cur->max_len = 0;
2410 			goto set_str_and_exp;
2411 		}
2412 		/* max_len == 0 signifies "malloced" var, which we can
2413 		 * (and have to) free. But we can't free(cur->varstr) here:
2414 		 * if cur->flg_export is 1, it is in the environment.
2415 		 * We should either unsetenv+free, or wait until putenv,
2416 		 * then putenv(new)+free(old).
2417 		 */
2418 		free_me = cur->varstr;
2419 		goto set_str_and_exp;
2420 	}
2421 
2422 	/* Not found or shadowed - create new variable struct */
2423 	debug_printf_env("%s: alloc new var '%s'/%u\n", __func__, str, local_lvl);
2424 	cur = xzalloc(sizeof(*cur));
2425 	cur->var_nest_level = local_lvl;
2426 	cur->next = *cur_pp;
2427 	*cur_pp = cur;
2428 
2429  set_str_and_exp:
2430 	cur->varstr = str;
2431  exp:
2432 #if !BB_MMU || ENABLE_HUSH_READONLY
2433 	if (flags & SETFLAG_MAKE_RO) {
2434 		cur->flg_read_only = 1;
2435 	}
2436 #endif
2437 	if (flags & SETFLAG_EXPORT)
2438 		cur->flg_export = 1;
2439 	retval = 0;
2440 	if (cur->flg_export) {
2441 		if (flags & SETFLAG_UNEXPORT) {
2442 			cur->flg_export = 0;
2443 			/* unsetenv was already done */
2444 		} else {
2445 			debug_printf_env("%s: putenv '%s'/%u\n", __func__, cur->varstr, cur->var_nest_level);
2446 			retval = putenv(cur->varstr);
2447 			/* fall through to "free(free_me)" -
2448 			 * only now we can free old exported malloced string
2449 			 */
2450 		}
2451 	}
2452 	free(free_me);
2453 
2454 	handle_changed_special_names(cur->varstr, name_len - 1);
2455 
2456 	return retval;
2457 }
2458 
set_local_var_from_halves(const char * name,const char * val)2459 static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val)
2460 {
2461 	char *var = xasprintf("%s=%s", name, val);
2462 	set_local_var(var, /*flag:*/ 0);
2463 }
2464 
2465 /* Used at startup and after each cd */
set_pwd_var(unsigned flag)2466 static void set_pwd_var(unsigned flag)
2467 {
2468 	set_local_var(xasprintf("PWD=%s", get_cwd(/*force:*/ 1)), flag);
2469 }
2470 
2471 #if ENABLE_HUSH_UNSET || ENABLE_HUSH_GETOPTS
unset_local_var_len(const char * name,int name_len)2472 static int unset_local_var_len(const char *name, int name_len)
2473 {
2474 	struct variable *cur;
2475 	struct variable **cur_pp;
2476 
2477 	cur_pp = &G.top_var;
2478 	while ((cur = *cur_pp) != NULL) {
2479 		if (strncmp(cur->varstr, name, name_len) == 0
2480 		 && cur->varstr[name_len] == '='
2481 		) {
2482 			if (cur->flg_read_only) {
2483 				bb_error_msg("%s: readonly variable", name);
2484 				return EXIT_FAILURE;
2485 			}
2486 
2487 			*cur_pp = cur->next;
2488 			debug_printf_env("%s: unsetenv '%s'\n", __func__, cur->varstr);
2489 			bb_unsetenv(cur->varstr);
2490 			if (!cur->max_len)
2491 				free(cur->varstr);
2492 			free(cur);
2493 
2494 			break;
2495 		}
2496 		cur_pp = &cur->next;
2497 	}
2498 
2499 	/* Handle "unset LINENO" et al even if did not find the variable to unset */
2500 	handle_changed_special_names(name, name_len);
2501 
2502 	return EXIT_SUCCESS;
2503 }
2504 
unset_local_var(const char * name)2505 static int unset_local_var(const char *name)
2506 {
2507 	return unset_local_var_len(name, strlen(name));
2508 }
2509 #endif
2510 
2511 
2512 /*
2513  * Helpers for "var1=val1 var2=val2 cmd" feature
2514  */
add_vars(struct variable * var)2515 static void add_vars(struct variable *var)
2516 {
2517 	struct variable *next;
2518 
2519 	while (var) {
2520 		next = var->next;
2521 		var->next = G.top_var;
2522 		G.top_var = var;
2523 		if (var->flg_export) {
2524 			debug_printf_env("%s: restoring exported '%s'/%u\n", __func__, var->varstr, var->var_nest_level);
2525 			putenv(var->varstr);
2526 		} else {
2527 			debug_printf_env("%s: restoring variable '%s'/%u\n", __func__, var->varstr, var->var_nest_level);
2528 		}
2529 		var = next;
2530 	}
2531 }
2532 
2533 /* We put strings[i] into variable table and possibly putenv them.
2534  * If variable is read only, we can free the strings[i]
2535  * which attempts to overwrite it.
2536  * The strings[] vector itself is freed.
2537  */
set_vars_and_save_old(char ** strings)2538 static void set_vars_and_save_old(char **strings)
2539 {
2540 	char **s;
2541 
2542 	if (!strings)
2543 		return;
2544 
2545 	s = strings;
2546 	while (*s) {
2547 		struct variable *var_p;
2548 		struct variable **var_pp;
2549 		char *eq;
2550 
2551 		eq = strchr(*s, '=');
2552 		if (HUSH_DEBUG && !eq)
2553 			bb_simple_error_msg_and_die("BUG in varexp4");
2554 		var_pp = get_ptr_to_local_var(*s, eq - *s);
2555 		if (var_pp) {
2556 			var_p = *var_pp;
2557 			if (var_p->flg_read_only) {
2558 				char **p;
2559 				bb_error_msg("%s: readonly variable", *s);
2560 				/*
2561 				 * "VAR=V BLTIN" unsets VARs after BLTIN completes.
2562 				 * If VAR is readonly, leaving it in the list
2563 				 * after asssignment error (msg above)
2564 				 * causes doubled error message later, on unset.
2565 				 */
2566 				debug_printf_env("removing/freeing '%s' element\n", *s);
2567 				free(*s);
2568 				p = s;
2569 				do { *p = p[1]; p++; } while (*p);
2570 				goto next;
2571 			}
2572 			/* below, set_local_var() with nest level will
2573 			 * "shadow" (remove) this variable from
2574 			 * global linked list.
2575 			 */
2576 		}
2577 		debug_printf_env("%s: env override '%s'/%u\n", __func__, *s, G.var_nest_level);
2578 		set_local_var(*s, (G.var_nest_level << SETFLAG_VARLVL_SHIFT) | SETFLAG_EXPORT);
2579 		s++;
2580  next: ;
2581 	}
2582 	free(strings);
2583 }
2584 
2585 
2586 /*
2587  * Unicode helper
2588  */
reinit_unicode_for_hush(void)2589 static void reinit_unicode_for_hush(void)
2590 {
2591 	/* Unicode support should be activated even if LANG is set
2592 	 * _during_ shell execution, not only if it was set when
2593 	 * shell was started. Therefore, re-check LANG every time:
2594 	 */
2595 	if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2596 	 || ENABLE_UNICODE_USING_LOCALE
2597 	) {
2598 		const char *s = get_local_var_value("LC_ALL");
2599 		if (!s) s = get_local_var_value("LC_CTYPE");
2600 		if (!s) s = get_local_var_value("LANG");
2601 		reinit_unicode(s);
2602 	}
2603 }
2604 
2605 /*
2606  * in_str support (strings, and "strings" read from files).
2607  */
2608 
2609 #if ENABLE_HUSH_INTERACTIVE
2610 /* To test correct lineedit/interactive behavior, type from command line:
2611  *	echo $P\
2612  *	\
2613  *	AT\
2614  *	H\
2615  *	\
2616  * It exercises a lot of corner cases.
2617  */
setup_prompt_string(void)2618 static const char *setup_prompt_string(void)
2619 {
2620 	const char *prompt_str;
2621 
2622 	debug_printf_prompt("%s promptmode:%d\n", __func__, G.promptmode);
2623 
2624 # if ENABLE_FEATURE_EDITING_FANCY_PROMPT
2625 	prompt_str = get_local_var_value(G.promptmode == 0 ? "PS1" : "PS2");
2626 	if (!prompt_str)
2627 		prompt_str = "";
2628 # else
2629 	prompt_str = "> "; /* if PS2, else... */
2630 	if (G.promptmode == 0) { /* PS1 */
2631 		/* No fancy prompts supported, (re)generate "CURDIR $ " by hand */
2632 		free(G.PS1);
2633 		/* bash uses $PWD value, even if it is set by user.
2634 		 * It uses current dir only if PWD is unset.
2635 		 * We always use current dir. */
2636 		prompt_str = G.PS1 = xasprintf("%s %c ", get_cwd(0), (geteuid() != 0) ? '$' : '#');
2637 	}
2638 # endif
2639 	debug_printf("prompt_str '%s'\n", prompt_str);
2640 	return prompt_str;
2641 }
get_user_input(struct in_str * i)2642 static int get_user_input(struct in_str *i)
2643 {
2644 # if ENABLE_FEATURE_EDITING
2645 	/* In EDITING case, this function reads next input line,
2646 	 * saves it in i->p, then returns 1st char of it.
2647 	 */
2648 	int r;
2649 	const char *prompt_str;
2650 
2651 	prompt_str = setup_prompt_string();
2652 	for (;;) {
2653 		reinit_unicode_for_hush();
2654 		G.flag_SIGINT = 0;
2655 		/* buglet: SIGINT will not make new prompt to appear _at once_,
2656 		 * only after <Enter>. (^C works immediately) */
2657 		r = read_line_input(G.line_input_state, prompt_str,
2658 				G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1
2659 		);
2660 		/* read_line_input intercepts ^C, "convert" it to SIGINT */
2661 		if (r == 0) {
2662 			raise(SIGINT);
2663 		}
2664 		check_and_run_traps();
2665 		if (r != 0 && !G.flag_SIGINT)
2666 			break;
2667 		/* ^C or SIGINT: repeat */
2668 		/* bash prints ^C even on real SIGINT (non-kbd generated) */
2669 		write(STDOUT_FILENO, "^C\n", 3);
2670 		G.last_exitcode = 128 | SIGINT;
2671 	}
2672 	if (r < 0) {
2673 		/* EOF/error detected */
2674 		/* ^D on interactive input goes to next line before exiting: */
2675 		write(STDOUT_FILENO, "\n", 1);
2676 		i->p = NULL;
2677 		i->peek_buf[0] = r = EOF;
2678 		return r;
2679 	}
2680 	i->p = G.user_input_buf;
2681 	return (unsigned char)*i->p++;
2682 # else
2683 	/* In !EDITING case, this function gets called for every char.
2684 	 * Buffering happens deeper in the call chain, in hfgetc(i->file).
2685 	 */
2686 	int r;
2687 
2688 	for (;;) {
2689 		G.flag_SIGINT = 0;
2690 		if (i->last_char == '\0' || i->last_char == '\n') {
2691 			const char *prompt_str = setup_prompt_string();
2692 			/* Why check_and_run_traps here? Try this interactively:
2693 			 * $ trap 'echo INT' INT; (sleep 2; kill -INT $$) &
2694 			 * $ <[enter], repeatedly...>
2695 			 * Without check_and_run_traps, handler never runs.
2696 			 */
2697 			check_and_run_traps();
2698 			fputs_stdout(prompt_str);
2699 			fflush_all();
2700 		}
2701 		r = hfgetc(i->file);
2702 		/* In !ENABLE_FEATURE_EDITING we don't use read_line_input,
2703 		 * no ^C masking happens during fgetc, no special code for ^C:
2704 		 * it generates SIGINT as usual.
2705 		 */
2706 		check_and_run_traps();
2707 		if (r != '\0' && !G.flag_SIGINT)
2708 			break;
2709 		if (G.flag_SIGINT) {
2710 			/* ^C or SIGINT: repeat */
2711 			/* bash prints ^C even on real SIGINT (non-kbd generated) */
2712 			/* kernel prints "^C" itself, just print newline: */
2713 			write(STDOUT_FILENO, "\n", 1);
2714 			G.last_exitcode = 128 | SIGINT;
2715 		}
2716 	}
2717 	return r;
2718 # endif
2719 }
2720 /* This is the magic location that prints prompts
2721  * and gets data back from the user */
fgetc_interactive(struct in_str * i)2722 static int fgetc_interactive(struct in_str *i)
2723 {
2724 	int ch;
2725 	/* If it's interactive stdin, get new line. */
2726 	if (G_interactive_fd && i->file == G.HFILE_stdin) {
2727 		/* Returns first char (or EOF), the rest is in i->p[] */
2728 		ch = get_user_input(i);
2729 		G.promptmode = 1; /* PS2 */
2730 		debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode);
2731 	} else {
2732 		/* Not stdin: script file, sourced file, etc */
2733 		do ch = hfgetc(i->file); while (ch == '\0');
2734 	}
2735 	return ch;
2736 }
2737 #else  /* !INTERACTIVE */
fgetc_interactive(struct in_str * i)2738 static ALWAYS_INLINE int fgetc_interactive(struct in_str *i)
2739 {
2740 	int ch;
2741 	do ch = hfgetc(i->file); while (ch == '\0');
2742 	return ch;
2743 }
2744 #endif  /* !INTERACTIVE */
2745 
i_getch(struct in_str * i)2746 static int i_getch(struct in_str *i)
2747 {
2748 	int ch;
2749 
2750 	if (!i->file) {
2751 		/* string-based in_str */
2752 		ch = (unsigned char)*i->p;
2753 		if (ch != '\0') {
2754 			i->p++;
2755 			i->last_char = ch;
2756 #if ENABLE_HUSH_LINENO_VAR
2757 			if (ch == '\n') {
2758 				G.parse_lineno++;
2759 				debug_printf_parse("G.parse_lineno++ = %u\n", G.parse_lineno);
2760 			}
2761 #endif
2762 			return ch;
2763 		}
2764 		return EOF;
2765 	}
2766 
2767 	/* FILE-based in_str */
2768 
2769 #if ENABLE_FEATURE_EDITING
2770 	/* This can be stdin, check line editing char[] buffer */
2771 	if (i->p && *i->p != '\0') {
2772 		ch = (unsigned char)*i->p++;
2773 		goto out;
2774 	}
2775 #endif
2776 	/* peek_buf[] is an int array, not char. Can contain EOF. */
2777 	ch = i->peek_buf[0];
2778 	if (ch != 0) {
2779 		int ch2 = i->peek_buf[1];
2780 		i->peek_buf[0] = ch2;
2781 		if (ch2 == 0) /* very likely, avoid redundant write */
2782 			goto out;
2783 		i->peek_buf[1] = 0;
2784 		goto out;
2785 	}
2786 
2787 	ch = fgetc_interactive(i);
2788  out:
2789 	debug_printf("file_get: got '%c' %d\n", ch, ch);
2790 	i->last_char = ch;
2791 #if ENABLE_HUSH_LINENO_VAR
2792 	if (ch == '\n') {
2793 		G.parse_lineno++;
2794 		debug_printf_parse("G.parse_lineno++ = %u\n", G.parse_lineno);
2795 	}
2796 #endif
2797 	return ch;
2798 }
2799 
i_peek(struct in_str * i)2800 static int i_peek(struct in_str *i)
2801 {
2802 	int ch;
2803 
2804 	if (!i->file) {
2805 		/* string-based in_str */
2806 		/* Doesn't report EOF on NUL. None of the callers care. */
2807 		return (unsigned char)*i->p;
2808 	}
2809 
2810 	/* FILE-based in_str */
2811 
2812 #if ENABLE_FEATURE_EDITING && ENABLE_HUSH_INTERACTIVE
2813 	/* This can be stdin, check line editing char[] buffer */
2814 	if (i->p && *i->p != '\0')
2815 		return (unsigned char)*i->p;
2816 #endif
2817 	/* peek_buf[] is an int array, not char. Can contain EOF. */
2818 	ch = i->peek_buf[0];
2819 	if (ch != 0)
2820 		return ch;
2821 
2822 	/* Need to get a new char */
2823 	ch = fgetc_interactive(i);
2824 	debug_printf("file_peek: got '%c' %d\n", ch, ch);
2825 
2826 	/* Save it by either rolling back line editing buffer, or in i->peek_buf[0] */
2827 #if ENABLE_FEATURE_EDITING && ENABLE_HUSH_INTERACTIVE
2828 	if (i->p) {
2829 		i->p -= 1;
2830 		return ch;
2831 	}
2832 #endif
2833 	i->peek_buf[0] = ch;
2834 	/*i->peek_buf[1] = 0; - already is */
2835 	return ch;
2836 }
2837 
2838 /* Only ever called if i_peek() was called, and did not return EOF.
2839  * IOW: we know the previous peek saw an ordinary char, not EOF, not NUL,
2840  * not end-of-line. Therefore we never need to read a new editing line here.
2841  */
i_peek2(struct in_str * i)2842 static int i_peek2(struct in_str *i)
2843 {
2844 	int ch;
2845 
2846 	/* There are two cases when i->p[] buffer exists.
2847 	 * (1) it's a string in_str.
2848 	 * (2) It's a file, and we have a saved line editing buffer.
2849 	 * In both cases, we know that i->p[0] exists and not NUL, and
2850 	 * the peek2 result is in i->p[1].
2851 	 */
2852 	if (i->p)
2853 		return (unsigned char)i->p[1];
2854 
2855 	/* Now we know it is a file-based in_str. */
2856 
2857 	/* peek_buf[] is an int array, not char. Can contain EOF. */
2858 	/* Is there 2nd char? */
2859 	ch = i->peek_buf[1];
2860 	if (ch == 0) {
2861 		/* We did not read it yet, get it now */
2862 		do ch = hfgetc(i->file); while (ch == '\0');
2863 		i->peek_buf[1] = ch;
2864 	}
2865 
2866 	debug_printf("file_peek2: got '%c' %d\n", ch, ch);
2867 	return ch;
2868 }
2869 
i_getch_and_eat_bkslash_nl(struct in_str * input)2870 static int i_getch_and_eat_bkslash_nl(struct in_str *input)
2871 {
2872 	for (;;) {
2873 		int ch, ch2;
2874 
2875 		ch = i_getch(input);
2876 		if (ch != '\\')
2877 			return ch;
2878 		ch2 = i_peek(input);
2879 		if (ch2 != '\n')
2880 			return ch;
2881 		/* backslash+newline, skip it */
2882 		i_getch(input);
2883 	}
2884 }
2885 
2886 /* Note: this function _eats_ \<newline> pairs, safe to use plain
2887  * i_getch() after it instead of i_getch_and_eat_bkslash_nl().
2888  */
i_peek_and_eat_bkslash_nl(struct in_str * input)2889 static int i_peek_and_eat_bkslash_nl(struct in_str *input)
2890 {
2891 	for (;;) {
2892 		int ch, ch2;
2893 
2894 		ch = i_peek(input);
2895 		if (ch != '\\')
2896 			return ch;
2897 		ch2 = i_peek2(input);
2898 		if (ch2 != '\n')
2899 			return ch;
2900 		/* backslash+newline, skip it */
2901 		i_getch(input);
2902 		i_getch(input);
2903 	}
2904 }
2905 
setup_file_in_str(struct in_str * i,HFILE * fp)2906 static void setup_file_in_str(struct in_str *i, HFILE *fp)
2907 {
2908 	memset(i, 0, sizeof(*i));
2909 	i->file = fp;
2910 	/* i->p = NULL; */
2911 }
2912 
setup_string_in_str(struct in_str * i,const char * s)2913 static void setup_string_in_str(struct in_str *i, const char *s)
2914 {
2915 	memset(i, 0, sizeof(*i));
2916 	/*i->file = NULL */;
2917 	i->p = s;
2918 }
2919 
2920 
2921 /*
2922  * o_string support
2923  */
2924 #define B_CHUNK  (32 * sizeof(char*))
2925 
o_reset_to_empty_unquoted(o_string * o)2926 static void o_reset_to_empty_unquoted(o_string *o)
2927 {
2928 	o->length = 0;
2929 	o->has_quoted_part = 0;
2930 	if (o->data)
2931 		o->data[0] = '\0';
2932 }
2933 
o_free_and_set_NULL(o_string * o)2934 static void o_free_and_set_NULL(o_string *o)
2935 {
2936 	free(o->data);
2937 	memset(o, 0, sizeof(*o));
2938 }
2939 
o_free(o_string * o)2940 static ALWAYS_INLINE void o_free(o_string *o)
2941 {
2942 	free(o->data);
2943 }
2944 
o_grow_by(o_string * o,int len)2945 static void o_grow_by(o_string *o, int len)
2946 {
2947 	if (o->length + len > o->maxlen) {
2948 		o->maxlen += (2 * len) | (B_CHUNK-1);
2949 		o->data = xrealloc(o->data, 1 + o->maxlen);
2950 	}
2951 }
2952 
o_addchr(o_string * o,int ch)2953 static void o_addchr(o_string *o, int ch)
2954 {
2955 	debug_printf("o_addchr: '%c' o->length=%d o=%p\n", ch, o->length, o);
2956 	if (o->length < o->maxlen) {
2957 		/* likely. avoid o_grow_by() call */
2958  add:
2959 		o->data[o->length] = ch;
2960 		o->length++;
2961 		o->data[o->length] = '\0';
2962 		return;
2963 	}
2964 	o_grow_by(o, 1);
2965 	goto add;
2966 }
2967 
2968 #if 0
2969 /* Valid only if we know o_string is not empty */
2970 static void o_delchr(o_string *o)
2971 {
2972 	o->length--;
2973 	o->data[o->length] = '\0';
2974 }
2975 #endif
2976 
o_addblock(o_string * o,const char * str,int len)2977 static void o_addblock(o_string *o, const char *str, int len)
2978 {
2979 	o_grow_by(o, len);
2980 	((char*)mempcpy(&o->data[o->length], str, len))[0] = '\0';
2981 	o->length += len;
2982 }
2983 
o_addstr(o_string * o,const char * str)2984 static void o_addstr(o_string *o, const char *str)
2985 {
2986 	o_addblock(o, str, strlen(str));
2987 }
2988 
o_addstr_with_NUL(o_string * o,const char * str)2989 static void o_addstr_with_NUL(o_string *o, const char *str)
2990 {
2991 	o_addblock(o, str, strlen(str) + 1);
2992 }
2993 
2994 #if !BB_MMU
nommu_addchr(o_string * o,int ch)2995 static void nommu_addchr(o_string *o, int ch)
2996 {
2997 	if (o)
2998 		o_addchr(o, ch);
2999 }
3000 #else
3001 # define nommu_addchr(o, str) ((void)0)
3002 #endif
3003 
3004 #if ENABLE_HUSH_MODE_X
x_mode_addchr(int ch)3005 static void x_mode_addchr(int ch)
3006 {
3007 	o_addchr(&G.x_mode_buf, ch);
3008 }
x_mode_addstr(const char * str)3009 static void x_mode_addstr(const char *str)
3010 {
3011 	o_addstr(&G.x_mode_buf, str);
3012 }
x_mode_addblock(const char * str,int len)3013 static void x_mode_addblock(const char *str, int len)
3014 {
3015 	o_addblock(&G.x_mode_buf, str, len);
3016 }
x_mode_prefix(void)3017 static void x_mode_prefix(void)
3018 {
3019 	int n = G.x_mode_depth;
3020 	do x_mode_addchr('+'); while (--n >= 0);
3021 }
x_mode_flush(void)3022 static void x_mode_flush(void)
3023 {
3024 	int len = G.x_mode_buf.length;
3025 	if (len <= 0)
3026 		return;
3027 	if (G.x_mode_fd > 0) {
3028 		G.x_mode_buf.data[len] = '\n';
3029 		full_write(G.x_mode_fd, G.x_mode_buf.data, len + 1);
3030 	}
3031 	G.x_mode_buf.length = 0;
3032 }
3033 #endif
3034 
3035 /*
3036  * HUSH_BRACE_EXPANSION code needs corresponding quoting on variable expansion side.
3037  * Currently, "v='{q,w}'; echo $v" erroneously expands braces in $v.
3038  * Apparently, on unquoted $v bash still does globbing
3039  * ("v='*.txt'; echo $v" prints all .txt files),
3040  * but NOT brace expansion! Thus, there should be TWO independent
3041  * quoting mechanisms on $v expansion side: one protects
3042  * $v from brace expansion, and other additionally protects "$v" against globbing.
3043  * We have only second one.
3044  */
3045 
3046 #if ENABLE_HUSH_BRACE_EXPANSION
3047 # define MAYBE_BRACES "{}"
3048 #else
3049 # define MAYBE_BRACES ""
3050 #endif
3051 
3052 /* My analysis of quoting semantics tells me that state information
3053  * is associated with a destination, not a source.
3054  */
o_addqchr(o_string * o,int ch)3055 static void o_addqchr(o_string *o, int ch)
3056 {
3057 	int sz = 1;
3058 	/* '-' is included because of this case:
3059 	 * >filename0 >filename1 >filename9; v='-'; echo filename[0"$v"9]
3060 	 */
3061 	char *found = strchr("*?[-\\" MAYBE_BRACES, ch);
3062 	if (found)
3063 		sz++;
3064 	o_grow_by(o, sz);
3065 	if (found) {
3066 		o->data[o->length] = '\\';
3067 		o->length++;
3068 	}
3069 	o->data[o->length] = ch;
3070 	o->length++;
3071 	o->data[o->length] = '\0';
3072 }
3073 
o_addQchr(o_string * o,int ch)3074 static void o_addQchr(o_string *o, int ch)
3075 {
3076 	int sz = 1;
3077 	if ((o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)
3078 	 && strchr("*?[-\\" MAYBE_BRACES, ch)
3079 	) {
3080 		sz++;
3081 		o->data[o->length] = '\\';
3082 		o->length++;
3083 	}
3084 	o_grow_by(o, sz);
3085 	o->data[o->length] = ch;
3086 	o->length++;
3087 	o->data[o->length] = '\0';
3088 }
3089 
o_addqblock(o_string * o,const char * str,int len)3090 static void o_addqblock(o_string *o, const char *str, int len)
3091 {
3092 	while (len) {
3093 		char ch;
3094 		int sz;
3095 		int ordinary_cnt = strcspn(str, "*?[-\\" MAYBE_BRACES);
3096 		if (ordinary_cnt > len) /* paranoia */
3097 			ordinary_cnt = len;
3098 		o_addblock(o, str, ordinary_cnt);
3099 		if (ordinary_cnt == len)
3100 			return; /* NUL is already added by o_addblock */
3101 		str += ordinary_cnt;
3102 		len -= ordinary_cnt + 1; /* we are processing + 1 char below */
3103 
3104 		ch = *str++;
3105 		sz = 1;
3106 		if (ch) { /* it is necessarily one of "*?[-\\" MAYBE_BRACES */
3107 			sz++;
3108 			o->data[o->length] = '\\';
3109 			o->length++;
3110 		}
3111 		o_grow_by(o, sz);
3112 		o->data[o->length] = ch;
3113 		o->length++;
3114 	}
3115 	o->data[o->length] = '\0';
3116 }
3117 
o_addQblock(o_string * o,const char * str,int len)3118 static void o_addQblock(o_string *o, const char *str, int len)
3119 {
3120 	if (!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)) {
3121 		o_addblock(o, str, len);
3122 		return;
3123 	}
3124 	o_addqblock(o, str, len);
3125 }
3126 
o_addQstr(o_string * o,const char * str)3127 static void o_addQstr(o_string *o, const char *str)
3128 {
3129 	o_addQblock(o, str, strlen(str));
3130 }
3131 
3132 /* A special kind of o_string for $VAR and `cmd` expansion.
3133  * It contains char* list[] at the beginning, which is grown in 16 element
3134  * increments. Actual string data starts at the next multiple of 16 * (char*).
3135  * list[i] contains an INDEX (int!) into this string data.
3136  * It means that if list[] needs to grow, data needs to be moved higher up
3137  * but list[i]'s need not be modified.
3138  * NB: remembering how many list[i]'s you have there is crucial.
3139  * o_finalize_list() operation post-processes this structure - calculates
3140  * and stores actual char* ptrs in list[]. Oh, it NULL terminates it as well.
3141  */
3142 #if DEBUG_EXPAND || DEBUG_GLOB
debug_print_list(const char * prefix,o_string * o,int n)3143 static void debug_print_list(const char *prefix, o_string *o, int n)
3144 {
3145 	char **list = (char**)o->data;
3146 	int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3147 	int i = 0;
3148 
3149 	indent();
3150 	fdprintf(2, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d glob:%d quoted:%d escape:%d\n",
3151 			prefix, list, n, string_start, o->length, o->maxlen,
3152 			!!(o->o_expflags & EXP_FLAG_GLOB),
3153 			o->has_quoted_part,
3154 			!!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
3155 	while (i < n) {
3156 		indent();
3157 		fdprintf(2, " list[%d]=%d '%s' %p\n", i, (int)(uintptr_t)list[i],
3158 				o->data + (int)(uintptr_t)list[i] + string_start,
3159 				o->data + (int)(uintptr_t)list[i] + string_start);
3160 		i++;
3161 	}
3162 	if (n) {
3163 		const char *p = o->data + (int)(uintptr_t)list[n - 1] + string_start;
3164 		indent();
3165 		fdprintf(2, " total_sz:%ld\n", (long)((p + strlen(p) + 1) - o->data));
3166 	}
3167 }
3168 #else
3169 # define debug_print_list(prefix, o, n) ((void)0)
3170 #endif
3171 
3172 /* n = o_save_ptr_helper(str, n) "starts new string" by storing an index value
3173  * in list[n] so that it points past last stored byte so far.
3174  * It returns n+1. */
o_save_ptr_helper(o_string * o,int n)3175 static int o_save_ptr_helper(o_string *o, int n)
3176 {
3177 	char **list = (char**)o->data;
3178 	int string_start;
3179 	int string_len;
3180 
3181 	if (!o->has_empty_slot) {
3182 		string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3183 		string_len = o->length - string_start;
3184 		if (!(n & 0xf)) { /* 0, 0x10, 0x20...? */
3185 			debug_printf_list("list[%d]=%d string_start=%d (growing)\n", n, string_len, string_start);
3186 			/* list[n] points to string_start, make space for 16 more pointers */
3187 			o->maxlen += 0x10 * sizeof(list[0]);
3188 			o->data = xrealloc(o->data, o->maxlen + 1);
3189 			list = (char**)o->data;
3190 			memmove(list + n + 0x10, list + n, string_len);
3191 			/*
3192 			 * expand_on_ifs() has a "previous argv[] ends in IFS?"
3193 			 * check. (grep for -prev-ifs-check-).
3194 			 * Ensure that argv[-1][last] is not garbage
3195 			 * but zero bytes, to save index check there.
3196 			 */
3197 			list[n + 0x10 - 1] = 0;
3198 			o->length += 0x10 * sizeof(list[0]);
3199 		} else {
3200 			debug_printf_list("list[%d]=%d string_start=%d\n",
3201 					n, string_len, string_start);
3202 		}
3203 	} else {
3204 		/* We have empty slot at list[n], reuse without growth */
3205 		string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); /* NB: n+1! */
3206 		string_len = o->length - string_start;
3207 		debug_printf_list("list[%d]=%d string_start=%d (empty slot)\n",
3208 				n, string_len, string_start);
3209 		o->has_empty_slot = 0;
3210 	}
3211 	o->has_quoted_part = 0;
3212 	list[n] = (char*)(uintptr_t)string_len;
3213 	return n + 1;
3214 }
3215 
3216 /* "What was our last o_save_ptr'ed position (byte offset relative o->data)?" */
o_get_last_ptr(o_string * o,int n)3217 static int o_get_last_ptr(o_string *o, int n)
3218 {
3219 	char **list = (char**)o->data;
3220 	int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3221 
3222 	return ((int)(uintptr_t)list[n-1]) + string_start;
3223 }
3224 
3225 /*
3226  * Globbing routines.
3227  *
3228  * Most words in commands need to be globbed, even ones which are
3229  * (single or double) quoted. This stems from the possiblity of
3230  * constructs like "abc"* and 'abc'* - these should be globbed.
3231  * Having a different code path for fully-quoted strings ("abc",
3232  * 'abc') would only help performance-wise, but we still need
3233  * code for partially-quoted strings.
3234  *
3235  * Unfortunately, if we want to match bash and ash behavior in all cases,
3236  * the logic can't be "shell-syntax argument is first transformed
3237  * to a string, then globbed, and if globbing does not match anything,
3238  * it is used verbatim". Here are two examples where it fails:
3239  *
3240  * 	echo 'b\*'?
3241  *
3242  * The globbing can't be avoided (because of '?' at the end).
3243  * The glob pattern is: b\\\*? - IOW, both \ and * are literals
3244  * and are glob-escaped. If this does not match, bash/ash print b\*?
3245  * - IOW: they "unbackslash" the glob pattern.
3246  * Now, look at this:
3247  *
3248  * 	v='\\\*'; echo b$v?
3249  *
3250  * The glob pattern is the same here: b\\\*? - the unquoted $v expansion
3251  * should be used as glob pattern with no changes. However, if glob
3252  * does not match, bash/ash print b\\\*? - NOT THE SAME as first example!
3253  *
3254  * ash implements this by having an encoded representation of the word
3255  * to glob, which IS NOT THE SAME as the glob pattern - it has more data.
3256  * Glob pattern is derived from it. If glob fails, the decision what result
3257  * should be is made using that encoded representation. Not glob pattern.
3258  */
3259 
3260 #if ENABLE_HUSH_BRACE_EXPANSION
3261 /* There in a GNU extension, GLOB_BRACE, but it is not usable:
3262  * first, it processes even {a} (no commas), second,
3263  * I didn't manage to make it return strings when they don't match
3264  * existing files. Need to re-implement it.
3265  */
3266 
3267 /* Helper */
glob_needed(const char * s)3268 static int glob_needed(const char *s)
3269 {
3270 	while (*s) {
3271 		if (*s == '\\') {
3272 			if (!s[1])
3273 				return 0;
3274 			s += 2;
3275 			continue;
3276 		}
3277 		if (*s == '*' || *s == '[' || *s == '?' || *s == '{')
3278 			return 1;
3279 		s++;
3280 	}
3281 	return 0;
3282 }
3283 /* Return pointer to next closing brace or to comma */
next_brace_sub(const char * cp)3284 static const char *next_brace_sub(const char *cp)
3285 {
3286 	unsigned depth = 0;
3287 	cp++;
3288 	while (*cp != '\0') {
3289 		if (*cp == '\\') {
3290 			if (*++cp == '\0')
3291 				break;
3292 			cp++;
3293 			continue;
3294 		}
3295 		if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
3296 			break;
3297 		if (*cp++ == '{')
3298 			depth++;
3299 	}
3300 
3301 	return *cp != '\0' ? cp : NULL;
3302 }
3303 /* Recursive brace globber. Note: may garble pattern[]. */
glob_brace(char * pattern,o_string * o,int n)3304 static int glob_brace(char *pattern, o_string *o, int n)
3305 {
3306 	char *new_pattern_buf;
3307 	const char *begin;
3308 	const char *next;
3309 	const char *rest;
3310 	const char *p;
3311 	size_t rest_len;
3312 
3313 	debug_printf_glob("glob_brace('%s')\n", pattern);
3314 
3315 	begin = pattern;
3316 	while (1) {
3317 		if (*begin == '\0')
3318 			goto simple_glob;
3319 		if (*begin == '{') {
3320 			/* Find the first sub-pattern and at the same time
3321 			 * find the rest after the closing brace */
3322 			next = next_brace_sub(begin);
3323 			if (next == NULL) {
3324 				/* An illegal expression */
3325 				goto simple_glob;
3326 			}
3327 			if (*next == '}') {
3328 				/* "{abc}" with no commas - illegal
3329 				 * brace expr, disregard and skip it */
3330 				begin = next + 1;
3331 				continue;
3332 			}
3333 			break;
3334 		}
3335 		if (*begin == '\\' && begin[1] != '\0')
3336 			begin++;
3337 		begin++;
3338 	}
3339 	debug_printf_glob("begin:%s\n", begin);
3340 	debug_printf_glob("next:%s\n", next);
3341 
3342 	/* Now find the end of the whole brace expression */
3343 	rest = next;
3344 	while (*rest != '}') {
3345 		rest = next_brace_sub(rest);
3346 		if (rest == NULL) {
3347 			/* An illegal expression */
3348 			goto simple_glob;
3349 		}
3350 		debug_printf_glob("rest:%s\n", rest);
3351 	}
3352 	rest_len = strlen(++rest) + 1;
3353 
3354 	/* We are sure the brace expression is well-formed */
3355 
3356 	/* Allocate working buffer large enough for our work */
3357 	new_pattern_buf = xmalloc(strlen(pattern));
3358 
3359 	/* We have a brace expression.  BEGIN points to the opening {,
3360 	 * NEXT points past the terminator of the first element, and REST
3361 	 * points past the final }.  We will accumulate result names from
3362 	 * recursive runs for each brace alternative in the buffer using
3363 	 * GLOB_APPEND. */
3364 
3365 	p = begin + 1;
3366 	while (1) {
3367 		/* Construct the new glob expression */
3368 		memcpy(
3369 			mempcpy(
3370 				mempcpy(new_pattern_buf,
3371 					/* We know the prefix for all sub-patterns */
3372 					pattern, begin - pattern),
3373 				p, next - p),
3374 			rest, rest_len);
3375 
3376 		/* Note: glob_brace() may garble new_pattern_buf[].
3377 		 * That's why we re-copy prefix every time (1st memcpy above).
3378 		 */
3379 		n = glob_brace(new_pattern_buf, o, n);
3380 		if (*next == '}') {
3381 			/* We saw the last entry */
3382 			break;
3383 		}
3384 		p = next + 1;
3385 		next = next_brace_sub(next);
3386 	}
3387 	free(new_pattern_buf);
3388 	return n;
3389 
3390  simple_glob:
3391 	{
3392 		int gr;
3393 		glob_t globdata;
3394 
3395 		memset(&globdata, 0, sizeof(globdata));
3396 		gr = glob(pattern, 0, NULL, &globdata);
3397 		debug_printf_glob("glob('%s'):%d\n", pattern, gr);
3398 		if (gr != 0) {
3399 			if (gr == GLOB_NOMATCH) {
3400 				globfree(&globdata);
3401 				/* NB: garbles parameter */
3402 				unbackslash(pattern);
3403 				o_addstr_with_NUL(o, pattern);
3404 				debug_printf_glob("glob pattern '%s' is literal\n", pattern);
3405 				return o_save_ptr_helper(o, n);
3406 			}
3407 			if (gr == GLOB_NOSPACE)
3408 				bb_die_memory_exhausted();
3409 			/* GLOB_ABORTED? Only happens with GLOB_ERR flag,
3410 			 * but we didn't specify it. Paranoia again. */
3411 			bb_error_msg_and_die("glob error %d on '%s'", gr, pattern);
3412 		}
3413 		if (globdata.gl_pathv && globdata.gl_pathv[0]) {
3414 			char **argv = globdata.gl_pathv;
3415 			while (1) {
3416 				o_addstr_with_NUL(o, *argv);
3417 				n = o_save_ptr_helper(o, n);
3418 				argv++;
3419 				if (!*argv)
3420 					break;
3421 			}
3422 		}
3423 		globfree(&globdata);
3424 	}
3425 	return n;
3426 }
3427 /* Performs globbing on last list[],
3428  * saving each result as a new list[].
3429  */
perform_glob(o_string * o,int n)3430 static int perform_glob(o_string *o, int n)
3431 {
3432 	char *pattern, *copy;
3433 
3434 	debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data);
3435 	if (!o->data)
3436 		return o_save_ptr_helper(o, n);
3437 	pattern = o->data + o_get_last_ptr(o, n);
3438 	debug_printf_glob("glob pattern '%s'\n", pattern);
3439 	if (!glob_needed(pattern)) {
3440 		/* unbackslash last string in o in place, fix length */
3441 		o->length = unbackslash(pattern) - o->data;
3442 		debug_printf_glob("glob pattern '%s' is literal\n", pattern);
3443 		return o_save_ptr_helper(o, n);
3444 	}
3445 
3446 	copy = xstrdup(pattern);
3447 	/* "forget" pattern in o */
3448 	o->length = pattern - o->data;
3449 	n = glob_brace(copy, o, n);
3450 	free(copy);
3451 	if (DEBUG_GLOB)
3452 		debug_print_list("perform_glob returning", o, n);
3453 	return n;
3454 }
3455 
3456 #else /* !HUSH_BRACE_EXPANSION */
3457 
3458 /* Helper */
glob_needed(const char * s)3459 static int glob_needed(const char *s)
3460 {
3461 	while (*s) {
3462 		if (*s == '\\') {
3463 			if (!s[1])
3464 				return 0;
3465 			s += 2;
3466 			continue;
3467 		}
3468 		if (*s == '*' || *s == '[' || *s == '?')
3469 			return 1;
3470 		s++;
3471 	}
3472 	return 0;
3473 }
3474 /* Performs globbing on last list[],
3475  * saving each result as a new list[].
3476  */
perform_glob(o_string * o,int n)3477 static int perform_glob(o_string *o, int n)
3478 {
3479 	glob_t globdata;
3480 	int gr;
3481 	char *pattern;
3482 
3483 	debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data);
3484 	if (!o->data)
3485 		return o_save_ptr_helper(o, n);
3486 	pattern = o->data + o_get_last_ptr(o, n);
3487 	debug_printf_glob("glob pattern '%s'\n", pattern);
3488 	if (!glob_needed(pattern)) {
3489  literal:
3490 		/* unbackslash last string in o in place, fix length */
3491 		o->length = unbackslash(pattern) - o->data;
3492 		debug_printf_glob("glob pattern '%s' is literal\n", pattern);
3493 		return o_save_ptr_helper(o, n);
3494 	}
3495 
3496 	memset(&globdata, 0, sizeof(globdata));
3497 	/* Can't use GLOB_NOCHECK: it does not unescape the string.
3498 	 * If we glob "*.\*" and don't find anything, we need
3499 	 * to fall back to using literal "*.*", but GLOB_NOCHECK
3500 	 * will return "*.\*"!
3501 	 */
3502 	gr = glob(pattern, 0, NULL, &globdata);
3503 	debug_printf_glob("glob('%s'):%d\n", pattern, gr);
3504 	if (gr != 0) {
3505 		if (gr == GLOB_NOMATCH) {
3506 			globfree(&globdata);
3507 			goto literal;
3508 		}
3509 		if (gr == GLOB_NOSPACE)
3510 			bb_die_memory_exhausted();
3511 		/* GLOB_ABORTED? Only happens with GLOB_ERR flag,
3512 		 * but we didn't specify it. Paranoia again. */
3513 		bb_error_msg_and_die("glob error %d on '%s'", gr, pattern);
3514 	}
3515 	if (globdata.gl_pathv && globdata.gl_pathv[0]) {
3516 		char **argv = globdata.gl_pathv;
3517 		/* "forget" pattern in o */
3518 		o->length = pattern - o->data;
3519 		while (1) {
3520 			o_addstr_with_NUL(o, *argv);
3521 			n = o_save_ptr_helper(o, n);
3522 			argv++;
3523 			if (!*argv)
3524 				break;
3525 		}
3526 	}
3527 	globfree(&globdata);
3528 	if (DEBUG_GLOB)
3529 		debug_print_list("perform_glob returning", o, n);
3530 	return n;
3531 }
3532 
3533 #endif /* !HUSH_BRACE_EXPANSION */
3534 
3535 /* If o->o_expflags & EXP_FLAG_GLOB, glob the string so far remembered.
3536  * Otherwise, just finish current list[] and start new */
o_save_ptr(o_string * o,int n)3537 static int o_save_ptr(o_string *o, int n)
3538 {
3539 	if (o->o_expflags & EXP_FLAG_GLOB) {
3540 		/* If o->has_empty_slot, list[n] was already globbed
3541 		 * (if it was requested back then when it was filled)
3542 		 * so don't do that again! */
3543 		if (!o->has_empty_slot)
3544 			return perform_glob(o, n); /* o_save_ptr_helper is inside */
3545 	}
3546 	return o_save_ptr_helper(o, n);
3547 }
3548 
3549 /* "Please convert list[n] to real char* ptrs, and NULL terminate it." */
o_finalize_list(o_string * o,int n)3550 static char **o_finalize_list(o_string *o, int n)
3551 {
3552 	char **list;
3553 	int string_start;
3554 
3555 	if (DEBUG_EXPAND)
3556 		debug_print_list("finalized", o, n);
3557 	debug_printf_expand("finalized n:%d\n", n);
3558 	list = (char**)o->data;
3559 	string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3560 	list[--n] = NULL;
3561 	while (n) {
3562 		n--;
3563 		list[n] = o->data + (int)(uintptr_t)list[n] + string_start;
3564 	}
3565 	return list;
3566 }
3567 
3568 static void free_pipe_list(struct pipe *pi);
3569 
3570 /* Returns pi->next - next pipe in the list */
free_pipe(struct pipe * pi)3571 static struct pipe *free_pipe(struct pipe *pi)
3572 {
3573 	struct pipe *next;
3574 	int i;
3575 
3576 	debug_printf_clean("free_pipe (pid %d)\n", getpid());
3577 	for (i = 0; i < pi->num_cmds; i++) {
3578 		struct command *command;
3579 		struct redir_struct *r, *rnext;
3580 
3581 		command = &pi->cmds[i];
3582 		debug_printf_clean("  command %d:\n", i);
3583 		if (command->argv) {
3584 			if (DEBUG_CLEAN) {
3585 				int a;
3586 				char **p;
3587 				for (a = 0, p = command->argv; *p; a++, p++) {
3588 					debug_printf_clean("   argv[%d] = %s\n", a, *p);
3589 				}
3590 			}
3591 			free_strings(command->argv);
3592 			//command->argv = NULL;
3593 		}
3594 		/* not "else if": on syntax error, we may have both! */
3595 		if (command->group) {
3596 			debug_printf_clean("   begin group (cmd_type:%d)\n",
3597 					command->cmd_type);
3598 			free_pipe_list(command->group);
3599 			debug_printf_clean("   end group\n");
3600 			//command->group = NULL;
3601 		}
3602 		/* else is crucial here.
3603 		 * If group != NULL, child_func is meaningless */
3604 #if ENABLE_HUSH_FUNCTIONS
3605 		else if (command->child_func) {
3606 			debug_printf_exec("cmd %p releases child func at %p\n", command, command->child_func);
3607 			command->child_func->parent_cmd = NULL;
3608 		}
3609 #endif
3610 #if !BB_MMU
3611 		free(command->group_as_string);
3612 		//command->group_as_string = NULL;
3613 #endif
3614 		for (r = command->redirects; r; r = rnext) {
3615 			debug_printf_clean("   redirect %d%s",
3616 					r->rd_fd, redir_table[r->rd_type].descrip);
3617 			/* guard against the case >$FOO, where foo is unset or blank */
3618 			if (r->rd_filename) {
3619 				debug_printf_clean(" fname:'%s'\n", r->rd_filename);
3620 				free(r->rd_filename);
3621 				//r->rd_filename = NULL;
3622 			}
3623 			debug_printf_clean(" rd_dup:%d\n", r->rd_dup);
3624 			rnext = r->next;
3625 			free(r);
3626 		}
3627 		//command->redirects = NULL;
3628 	}
3629 	free(pi->cmds);   /* children are an array, they get freed all at once */
3630 	//pi->cmds = NULL;
3631 #if ENABLE_HUSH_JOB
3632 	free(pi->cmdtext);
3633 	//pi->cmdtext = NULL;
3634 #endif
3635 
3636 	next = pi->next;
3637 	free(pi);
3638 	return next;
3639 }
3640 
free_pipe_list(struct pipe * pi)3641 static void free_pipe_list(struct pipe *pi)
3642 {
3643 	while (pi) {
3644 #if HAS_KEYWORDS
3645 		debug_printf_clean("pipe reserved word %d\n", pi->res_word);
3646 #endif
3647 		debug_printf_clean("pipe followup code %d\n", pi->followup);
3648 		pi = free_pipe(pi);
3649 	}
3650 }
3651 
3652 
3653 /*** Parsing routines ***/
3654 
3655 #ifndef debug_print_tree
debug_print_tree(struct pipe * pi,int lvl)3656 static void debug_print_tree(struct pipe *pi, int lvl)
3657 {
3658 	static const char *const PIPE[] = {
3659 		[PIPE_SEQ] = "SEQ",
3660 		[PIPE_AND] = "AND",
3661 		[PIPE_OR ] = "OR" ,
3662 		[PIPE_BG ] = "BG" ,
3663 	};
3664 	static const char *RES[] = {
3665 		[RES_NONE ] = "NONE" ,
3666 # if ENABLE_HUSH_IF
3667 		[RES_IF   ] = "IF"   ,
3668 		[RES_THEN ] = "THEN" ,
3669 		[RES_ELIF ] = "ELIF" ,
3670 		[RES_ELSE ] = "ELSE" ,
3671 		[RES_FI   ] = "FI"   ,
3672 # endif
3673 # if ENABLE_HUSH_LOOPS
3674 		[RES_FOR  ] = "FOR"  ,
3675 		[RES_WHILE] = "WHILE",
3676 		[RES_UNTIL] = "UNTIL",
3677 		[RES_DO   ] = "DO"   ,
3678 		[RES_DONE ] = "DONE" ,
3679 # endif
3680 # if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
3681 		[RES_IN   ] = "IN"   ,
3682 # endif
3683 # if ENABLE_HUSH_CASE
3684 		[RES_CASE ] = "CASE" ,
3685 		[RES_CASE_IN ] = "CASE_IN" ,
3686 		[RES_MATCH] = "MATCH",
3687 		[RES_CASE_BODY] = "CASE_BODY",
3688 		[RES_ESAC ] = "ESAC" ,
3689 # endif
3690 		[RES_XXXX ] = "XXXX" ,
3691 		[RES_SNTX ] = "SNTX" ,
3692 	};
3693 	static const char *const CMDTYPE[] = {
3694 		"{}",
3695 		"()",
3696 		"[noglob]",
3697 # if ENABLE_HUSH_FUNCTIONS
3698 		"func()",
3699 # endif
3700 	};
3701 
3702 	int pin, prn;
3703 
3704 	pin = 0;
3705 	while (pi) {
3706 		fdprintf(2, "%*spipe %d #cmds:%d %sres_word=%s followup=%d %s\n",
3707 				lvl*2, "",
3708 				pin,
3709 				pi->num_cmds,
3710 				(IF_HAS_KEYWORDS(pi->pi_inverted ? "! " :) ""),
3711 				RES[pi->res_word],
3712 				pi->followup, PIPE[pi->followup]
3713 		);
3714 		prn = 0;
3715 		while (prn < pi->num_cmds) {
3716 			struct command *command = &pi->cmds[prn];
3717 			char **argv = command->argv;
3718 
3719 			fdprintf(2, "%*s cmd %d assignment_cnt:%d",
3720 					lvl*2, "", prn,
3721 					command->assignment_cnt);
3722 # if ENABLE_HUSH_LINENO_VAR
3723 			fdprintf(2, " LINENO:%u", command->lineno);
3724 # endif
3725 			if (command->group) {
3726 				fdprintf(2, " group %s: (argv=%p)%s%s\n",
3727 						CMDTYPE[command->cmd_type],
3728 						argv
3729 # if !BB_MMU
3730 						, " group_as_string:", command->group_as_string
3731 # else
3732 						, "", ""
3733 # endif
3734 				);
3735 				debug_print_tree(command->group, lvl+1);
3736 				prn++;
3737 				continue;
3738 			}
3739 			if (argv) while (*argv) {
3740 				fdprintf(2, " '%s'", *argv);
3741 				argv++;
3742 			}
3743 			if (command->redirects)
3744 				fdprintf(2, " {redir}");
3745 			fdprintf(2, "\n");
3746 			prn++;
3747 		}
3748 		pi = pi->next;
3749 		pin++;
3750 	}
3751 }
3752 #endif /* debug_print_tree */
3753 
new_pipe(void)3754 static struct pipe *new_pipe(void)
3755 {
3756 	struct pipe *pi;
3757 	pi = xzalloc(sizeof(struct pipe));
3758 	/*pi->res_word = RES_NONE; - RES_NONE is 0 anyway */
3759 	return pi;
3760 }
3761 
3762 /* Command (member of a pipe) is complete, or we start a new pipe
3763  * if ctx->command is NULL.
3764  * No errors possible here.
3765  */
done_command(struct parse_context * ctx)3766 static int done_command(struct parse_context *ctx)
3767 {
3768 	/* The command is really already in the pipe structure, so
3769 	 * advance the pipe counter and make a new, null command. */
3770 	struct pipe *pi = ctx->pipe;
3771 	struct command *command = ctx->command;
3772 
3773 #if 0	/* Instead we emit error message at run time */
3774 	if (ctx->pending_redirect) {
3775 		/* For example, "cmd >" (no filename to redirect to) */
3776 		syntax_error("invalid redirect");
3777 		ctx->pending_redirect = NULL;
3778 	}
3779 #endif
3780 
3781 	if (command) {
3782 		if (IS_NULL_CMD(command)) {
3783 			debug_printf_parse("done_command: skipping null cmd, num_cmds=%d\n", pi->num_cmds);
3784 			goto clear_and_ret;
3785 		}
3786 		pi->num_cmds++;
3787 		debug_printf_parse("done_command: ++num_cmds=%d\n", pi->num_cmds);
3788 		//debug_print_tree(ctx->list_head, 20);
3789 	} else {
3790 		debug_printf_parse("done_command: initializing, num_cmds=%d\n", pi->num_cmds);
3791 	}
3792 
3793 	/* Only real trickiness here is that the uncommitted
3794 	 * command structure is not counted in pi->num_cmds. */
3795 	pi->cmds = xrealloc(pi->cmds, sizeof(*pi->cmds) * (pi->num_cmds+1));
3796 	ctx->command = command = &pi->cmds[pi->num_cmds];
3797  clear_and_ret:
3798 	memset(command, 0, sizeof(*command));
3799 #if ENABLE_HUSH_LINENO_VAR
3800 	command->lineno = G.parse_lineno;
3801 	debug_printf_parse("command->lineno = G.parse_lineno (%u)\n", G.parse_lineno);
3802 #endif
3803 	return pi->num_cmds; /* used only for 0/nonzero check */
3804 }
3805 
done_pipe(struct parse_context * ctx,pipe_style type)3806 static void done_pipe(struct parse_context *ctx, pipe_style type)
3807 {
3808 	int not_null;
3809 
3810 	debug_printf_parse("done_pipe entered, followup %d\n", type);
3811 	/* Close previous command */
3812 	not_null = done_command(ctx);
3813 #if HAS_KEYWORDS
3814 	ctx->pipe->pi_inverted = ctx->ctx_inverted;
3815 	ctx->ctx_inverted = 0;
3816 	ctx->pipe->res_word = ctx->ctx_res_w;
3817 #endif
3818 	if (type == PIPE_BG && ctx->list_head != ctx->pipe) {
3819 		/* Necessary since && and || have precedence over &:
3820 		 * "cmd1 && cmd2 &" must spawn both cmds, not only cmd2,
3821 		 * in a backgrounded subshell.
3822 		 */
3823 		struct pipe *pi;
3824 		struct command *command;
3825 
3826 		/* Is this actually this construct, all pipes end with && or ||? */
3827 		pi = ctx->list_head;
3828 		while (pi != ctx->pipe) {
3829 			if (pi->followup != PIPE_AND && pi->followup != PIPE_OR)
3830 				goto no_conv;
3831 			pi = pi->next;
3832 		}
3833 
3834 		debug_printf_parse("BG with more than one pipe, converting to { p1 &&...pN; } &\n");
3835 		pi->followup = PIPE_SEQ; /* close pN _not_ with "&"! */
3836 		pi = xzalloc(sizeof(*pi));
3837 		pi->followup = PIPE_BG;
3838 		pi->num_cmds = 1;
3839 		pi->cmds = xzalloc(sizeof(pi->cmds[0]));
3840 		command = &pi->cmds[0];
3841 		if (CMD_NORMAL != 0) /* "if xzalloc didn't do that already" */
3842 			command->cmd_type = CMD_NORMAL;
3843 		command->group = ctx->list_head;
3844 #if !BB_MMU
3845 		command->group_as_string = xstrndup(
3846 			    ctx->as_string.data,
3847 			    ctx->as_string.length - 1 /* do not copy last char, "&" */
3848 		);
3849 #endif
3850 		/* Replace all pipes in ctx with one newly created */
3851 		ctx->list_head = ctx->pipe = pi;
3852 		/* for cases like "cmd && &", do not be tricked by last command
3853 		 * being null - the entire {...} & is NOT null! */
3854 		not_null = 1;
3855 	} else {
3856  no_conv:
3857 		ctx->pipe->followup = type;
3858 	}
3859 
3860 	/* Without this check, even just <enter> on command line generates
3861 	 * tree of three NOPs (!). Which is harmless but annoying.
3862 	 * IOW: it is safe to do it unconditionally. */
3863 	if (not_null
3864 #if ENABLE_HUSH_IF
3865 	 || ctx->ctx_res_w == RES_FI
3866 #endif
3867 #if ENABLE_HUSH_LOOPS
3868 	 || ctx->ctx_res_w == RES_DONE
3869 	 || ctx->ctx_res_w == RES_FOR
3870 	 || ctx->ctx_res_w == RES_IN
3871 #endif
3872 #if ENABLE_HUSH_CASE
3873 	 || ctx->ctx_res_w == RES_ESAC
3874 #endif
3875 	) {
3876 		struct pipe *new_p;
3877 		debug_printf_parse("done_pipe: adding new pipe: "
3878 				"not_null:%d ctx->ctx_res_w:%d\n",
3879 				not_null, ctx->ctx_res_w);
3880 		new_p = new_pipe();
3881 		ctx->pipe->next = new_p;
3882 		ctx->pipe = new_p;
3883 		/* RES_THEN, RES_DO etc are "sticky" -
3884 		 * they remain set for pipes inside if/while.
3885 		 * This is used to control execution.
3886 		 * RES_FOR and RES_IN are NOT sticky (needed to support
3887 		 * cases where variable or value happens to match a keyword):
3888 		 */
3889 #if ENABLE_HUSH_LOOPS
3890 		if (ctx->ctx_res_w == RES_FOR
3891 		 || ctx->ctx_res_w == RES_IN)
3892 			ctx->ctx_res_w = RES_NONE;
3893 #endif
3894 #if ENABLE_HUSH_CASE
3895 		if (ctx->ctx_res_w == RES_MATCH)
3896 			ctx->ctx_res_w = RES_CASE_BODY;
3897 		if (ctx->ctx_res_w == RES_CASE)
3898 			ctx->ctx_res_w = RES_CASE_IN;
3899 #endif
3900 		ctx->command = NULL; /* trick done_command below */
3901 		/* Create the memory for command, roughly:
3902 		 * ctx->pipe->cmds = new struct command;
3903 		 * ctx->command = &ctx->pipe->cmds[0];
3904 		 */
3905 		done_command(ctx);
3906 		//debug_print_tree(ctx->list_head, 10);
3907 	}
3908 	debug_printf_parse("done_pipe return\n");
3909 }
3910 
initialize_context(struct parse_context * ctx)3911 static void initialize_context(struct parse_context *ctx)
3912 {
3913 	memset(ctx, 0, sizeof(*ctx));
3914 	if (MAYBE_ASSIGNMENT != 0)
3915 		ctx->is_assignment = MAYBE_ASSIGNMENT;
3916 	ctx->pipe = ctx->list_head = new_pipe();
3917 	/* Create the memory for command, roughly:
3918 	 * ctx->pipe->cmds = new struct command;
3919 	 * ctx->command = &ctx->pipe->cmds[0];
3920 	 */
3921 	done_command(ctx);
3922 }
3923 
3924 /* If a reserved word is found and processed, parse context is modified
3925  * and 1 is returned.
3926  */
3927 #if HAS_KEYWORDS
3928 struct reserved_combo {
3929 	char literal[6];
3930 	unsigned char res;
3931 	unsigned char assignment_flag;
3932 	uint32_t flag;
3933 };
3934 enum {
3935 	FLAG_END   = (1 << RES_NONE ),
3936 # if ENABLE_HUSH_IF
3937 	FLAG_IF    = (1 << RES_IF   ),
3938 	FLAG_THEN  = (1 << RES_THEN ),
3939 	FLAG_ELIF  = (1 << RES_ELIF ),
3940 	FLAG_ELSE  = (1 << RES_ELSE ),
3941 	FLAG_FI    = (1 << RES_FI   ),
3942 # endif
3943 # if ENABLE_HUSH_LOOPS
3944 	FLAG_FOR   = (1 << RES_FOR  ),
3945 	FLAG_WHILE = (1 << RES_WHILE),
3946 	FLAG_UNTIL = (1 << RES_UNTIL),
3947 	FLAG_DO    = (1 << RES_DO   ),
3948 	FLAG_DONE  = (1 << RES_DONE ),
3949 	FLAG_IN    = (1 << RES_IN   ),
3950 # endif
3951 # if ENABLE_HUSH_CASE
3952 	FLAG_MATCH = (1 << RES_MATCH),
3953 	FLAG_ESAC  = (1 << RES_ESAC ),
3954 # endif
3955 	FLAG_START = (1 << RES_XXXX ),
3956 };
3957 
match_reserved_word(o_string * word)3958 static const struct reserved_combo* match_reserved_word(o_string *word)
3959 {
3960 	/* Mostly a list of accepted follow-up reserved words.
3961 	 * FLAG_END means we are done with the sequence, and are ready
3962 	 * to turn the compound list into a command.
3963 	 * FLAG_START means the word must start a new compound list.
3964 	 */
3965 	static const struct reserved_combo reserved_list[] ALIGN4 = {
3966 # if ENABLE_HUSH_IF
3967 		{ "!",     RES_NONE,  NOT_ASSIGNMENT  , 0 },
3968 		{ "if",    RES_IF,    MAYBE_ASSIGNMENT, FLAG_THEN | FLAG_START },
3969 		{ "then",  RES_THEN,  MAYBE_ASSIGNMENT, FLAG_ELIF | FLAG_ELSE | FLAG_FI },
3970 		{ "elif",  RES_ELIF,  MAYBE_ASSIGNMENT, FLAG_THEN },
3971 		{ "else",  RES_ELSE,  MAYBE_ASSIGNMENT, FLAG_FI   },
3972 		{ "fi",    RES_FI,    NOT_ASSIGNMENT  , FLAG_END  },
3973 # endif
3974 # if ENABLE_HUSH_LOOPS
3975 		{ "for",   RES_FOR,   NOT_ASSIGNMENT  , FLAG_IN | FLAG_DO | FLAG_START },
3976 		{ "while", RES_WHILE, MAYBE_ASSIGNMENT, FLAG_DO | FLAG_START },
3977 		{ "until", RES_UNTIL, MAYBE_ASSIGNMENT, FLAG_DO | FLAG_START },
3978 		{ "in",    RES_IN,    NOT_ASSIGNMENT  , FLAG_DO   },
3979 		{ "do",    RES_DO,    MAYBE_ASSIGNMENT, FLAG_DONE },
3980 		{ "done",  RES_DONE,  NOT_ASSIGNMENT  , FLAG_END  },
3981 # endif
3982 # if ENABLE_HUSH_CASE
3983 		{ "case",  RES_CASE,  NOT_ASSIGNMENT  , FLAG_MATCH | FLAG_START },
3984 		{ "esac",  RES_ESAC,  NOT_ASSIGNMENT  , FLAG_END  },
3985 # endif
3986 	};
3987 	const struct reserved_combo *r;
3988 
3989 	for (r = reserved_list; r < reserved_list + ARRAY_SIZE(reserved_list); r++) {
3990 		if (strcmp(word->data, r->literal) == 0)
3991 			return r;
3992 	}
3993 	return NULL;
3994 }
3995 /* Return NULL: not a keyword, else: keyword
3996  */
reserved_word(struct parse_context * ctx)3997 static const struct reserved_combo* reserved_word(struct parse_context *ctx)
3998 {
3999 # if ENABLE_HUSH_CASE
4000 	static const struct reserved_combo reserved_match = {
4001 		"",        RES_MATCH, NOT_ASSIGNMENT , FLAG_MATCH | FLAG_ESAC
4002 	};
4003 # endif
4004 	const struct reserved_combo *r;
4005 
4006 	if (ctx->word.has_quoted_part)
4007 		return 0;
4008 	r = match_reserved_word(&ctx->word);
4009 	if (!r)
4010 		return r; /* NULL */
4011 
4012 	debug_printf("found reserved word %s, res %d\n", r->literal, r->res);
4013 # if ENABLE_HUSH_CASE
4014 	if (r->res == RES_IN && ctx->ctx_res_w == RES_CASE_IN) {
4015 		/* "case word IN ..." - IN part starts first MATCH part */
4016 		r = &reserved_match;
4017 	} else
4018 # endif
4019 	if (r->flag == 0) { /* '!' */
4020 		if (ctx->ctx_inverted) { /* bash doesn't accept '! ! true' */
4021 			syntax_error("! ! command");
4022 			ctx->ctx_res_w = RES_SNTX;
4023 		}
4024 		ctx->ctx_inverted = 1;
4025 		return r;
4026 	}
4027 	if (r->flag & FLAG_START) {
4028 		struct parse_context *old;
4029 
4030 		old = xmemdup(ctx, sizeof(*ctx));
4031 		debug_printf_parse("push stack %p\n", old);
4032 		initialize_context(ctx);
4033 		ctx->stack = old;
4034 	} else if (/*ctx->ctx_res_w == RES_NONE ||*/ !(ctx->old_flag & (1 << r->res))) {
4035 		syntax_error_at(ctx->word.data);
4036 		ctx->ctx_res_w = RES_SNTX;
4037 		return r;
4038 	} else {
4039 		/* "{...} fi" is ok. "{...} if" is not
4040 		 * Example:
4041 		 * if { echo foo; } then { echo bar; } fi */
4042 		if (ctx->command->group)
4043 			done_pipe(ctx, PIPE_SEQ);
4044 	}
4045 
4046 	ctx->ctx_res_w = r->res;
4047 	ctx->old_flag = r->flag;
4048 	ctx->is_assignment = r->assignment_flag;
4049 	debug_printf_parse("ctx->is_assignment='%s'\n", assignment_flag[ctx->is_assignment]);
4050 
4051 	if (ctx->old_flag & FLAG_END) {
4052 		struct parse_context *old;
4053 
4054 		done_pipe(ctx, PIPE_SEQ);
4055 		debug_printf_parse("pop stack %p\n", ctx->stack);
4056 		old = ctx->stack;
4057 		old->command->group = ctx->list_head;
4058 		old->command->cmd_type = CMD_NORMAL;
4059 # if !BB_MMU
4060 		/* At this point, the compound command's string is in
4061 		 * ctx->as_string... except for the leading keyword!
4062 		 * Consider this example: "echo a | if true; then echo a; fi"
4063 		 * ctx->as_string will contain "true; then echo a; fi",
4064 		 * with "if " remaining in old->as_string!
4065 		 */
4066 		{
4067 			char *str;
4068 			int len = old->as_string.length;
4069 			/* Concatenate halves */
4070 			o_addstr(&old->as_string, ctx->as_string.data);
4071 			o_free(&ctx->as_string);
4072 			/* Find where leading keyword starts in first half */
4073 			str = old->as_string.data + len;
4074 			if (str > old->as_string.data)
4075 				str--; /* skip whitespace after keyword */
4076 			while (str > old->as_string.data && isalpha(str[-1]))
4077 				str--;
4078 			/* Ugh, we're done with this horrid hack */
4079 			old->command->group_as_string = xstrdup(str);
4080 			debug_printf_parse("pop, remembering as:'%s'\n",
4081 					old->command->group_as_string);
4082 		}
4083 # endif
4084 		*ctx = *old;   /* physical copy */
4085 		free(old);
4086 	}
4087 	return r;
4088 }
4089 #endif /* HAS_KEYWORDS */
4090 
4091 /* Word is complete, look at it and update parsing context.
4092  * Normal return is 0. Syntax errors return 1.
4093  * Note: on return, word is reset, but not o_free'd!
4094  */
done_word(struct parse_context * ctx)4095 static int done_word(struct parse_context *ctx)
4096 {
4097 	struct command *command = ctx->command;
4098 
4099 	debug_printf_parse("done_word entered: '%s' %p\n", ctx->word.data, command);
4100 	if (ctx->word.length == 0 && !ctx->word.has_quoted_part) {
4101 		debug_printf_parse("done_word return 0: true null, ignored\n");
4102 		return 0;
4103 	}
4104 
4105 	if (ctx->pending_redirect) {
4106 		/* We do not glob in e.g. >*.tmp case. bash seems to glob here
4107 		 * only if run as "bash", not "sh" */
4108 		/* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
4109 		 * "2.7 Redirection
4110 		 * If the redirection operator is "<<" or "<<-", the word
4111 		 * that follows the redirection operator shall be
4112 		 * subjected to quote removal; it is unspecified whether
4113 		 * any of the other expansions occur. For the other
4114 		 * redirection operators, the word that follows the
4115 		 * redirection operator shall be subjected to tilde
4116 		 * expansion, parameter expansion, command substitution,
4117 		 * arithmetic expansion, and quote removal.
4118 		 * Pathname expansion shall not be performed
4119 		 * on the word by a non-interactive shell; an interactive
4120 		 * shell may perform it, but shall do so only when
4121 		 * the expansion would result in one word."
4122 		 */
4123 //bash does not do parameter/command substitution or arithmetic expansion
4124 //for _heredoc_ redirection word: these constructs look for exact eof marker
4125 // as written:
4126 // <<EOF$t
4127 // <<EOF$((1))
4128 // <<EOF`true`  [this case also makes heredoc "quoted", a-la <<"EOF". Probably bash-4.3.43 bug]
4129 
4130 		ctx->pending_redirect->rd_filename = xstrdup(ctx->word.data);
4131 		/* Cater for >\file case:
4132 		 * >\a creates file a; >\\a, >"\a", >"\\a" create file \a
4133 		 * Same with heredocs:
4134 		 * for <<\H delim is H; <<\\H, <<"\H", <<"\\H" - \H
4135 		 */
4136 		if (ctx->pending_redirect->rd_type == REDIRECT_HEREDOC) {
4137 			unbackslash(ctx->pending_redirect->rd_filename);
4138 			/* Is it <<"HEREDOC"? */
4139 			if (ctx->word.has_quoted_part) {
4140 				ctx->pending_redirect->rd_dup |= HEREDOC_QUOTED;
4141 			}
4142 		}
4143 		debug_printf_parse("word stored in rd_filename: '%s'\n", ctx->word.data);
4144 		ctx->pending_redirect = NULL;
4145 	} else {
4146 #if HAS_KEYWORDS
4147 # if ENABLE_HUSH_CASE
4148 		if (ctx->ctx_dsemicolon
4149 		 && strcmp(ctx->word.data, "esac") != 0 /* not "... pattern) cmd;; esac" */
4150 		) {
4151 			/* already done when ctx_dsemicolon was set to 1: */
4152 			/* ctx->ctx_res_w = RES_MATCH; */
4153 			ctx->ctx_dsemicolon = 0;
4154 		} else
4155 # endif
4156 # if defined(CMD_TEST2_SINGLEWORD_NOGLOB)
4157 		if (command->cmd_type == CMD_TEST2_SINGLEWORD_NOGLOB
4158 		 && strcmp(ctx->word.data, "]]") == 0
4159 		) {
4160 			/* allow "[[ ]] >file" etc */
4161 			command->cmd_type = CMD_SINGLEWORD_NOGLOB;
4162 		} else
4163 # endif
4164 		if (!command->argv /* if it's the first word... */
4165 # if ENABLE_HUSH_LOOPS
4166 		 && ctx->ctx_res_w != RES_FOR /* ...not after FOR or IN */
4167 		 && ctx->ctx_res_w != RES_IN
4168 # endif
4169 # if ENABLE_HUSH_CASE
4170 		 && ctx->ctx_res_w != RES_CASE
4171 # endif
4172 		) {
4173 			const struct reserved_combo *reserved;
4174 			reserved = reserved_word(ctx);
4175 			debug_printf_parse("checking for reserved-ness: %d\n", !!reserved);
4176 			if (reserved) {
4177 # if ENABLE_HUSH_LINENO_VAR
4178 /* Case:
4179  * "while ...; do
4180  *	cmd ..."
4181  * If we don't close the pipe _now_, immediately after "do", lineno logic
4182  * sees "cmd" as starting at "do" - i.e., at the previous line.
4183  */
4184 				if (0
4185 				 IF_HUSH_IF(|| reserved->res == RES_THEN)
4186 				 IF_HUSH_IF(|| reserved->res == RES_ELIF)
4187 				 IF_HUSH_IF(|| reserved->res == RES_ELSE)
4188 				 IF_HUSH_LOOPS(|| reserved->res == RES_DO)
4189 				) {
4190 					done_pipe(ctx, PIPE_SEQ);
4191 				}
4192 # endif
4193 				o_reset_to_empty_unquoted(&ctx->word);
4194 				debug_printf_parse("done_word return %d\n",
4195 						(ctx->ctx_res_w == RES_SNTX));
4196 				return (ctx->ctx_res_w == RES_SNTX);
4197 			}
4198 # if defined(CMD_TEST2_SINGLEWORD_NOGLOB)
4199 			if (strcmp(ctx->word.data, "[[") == 0) {
4200 				command->cmd_type = CMD_TEST2_SINGLEWORD_NOGLOB;
4201 			} else
4202 # endif
4203 # if defined(CMD_SINGLEWORD_NOGLOB)
4204 			if (0
4205 			/* In bash, local/export/readonly are special, args
4206 			 * are assignments and therefore expansion of them
4207 			 * should be "one-word" expansion:
4208 			 *  $ export i=`echo 'a  b'` # one arg: "i=a  b"
4209 			 * compare with:
4210 			 *  $ ls i=`echo 'a  b'`     # two args: "i=a" and "b"
4211 			 *  ls: cannot access i=a: No such file or directory
4212 			 *  ls: cannot access b: No such file or directory
4213 			 * Note: bash 3.2.33(1) does this only if export word
4214 			 * itself is not quoted:
4215 			 *  $ export i=`echo 'aaa  bbb'`; echo "$i"
4216 			 *  aaa  bbb
4217 			 *  $ "export" i=`echo 'aaa  bbb'`; echo "$i"
4218 			 *  aaa
4219 			 */
4220 			 IF_HUSH_LOCAL(   || strcmp(ctx->word.data, "local") == 0)
4221 			 IF_HUSH_EXPORT(  || strcmp(ctx->word.data, "export") == 0)
4222 			 IF_HUSH_READONLY(|| strcmp(ctx->word.data, "readonly") == 0)
4223 			) {
4224 				command->cmd_type = CMD_SINGLEWORD_NOGLOB;
4225 			}
4226 # else
4227 			{ /* empty block to pair "if ... else" */ }
4228 # endif
4229 		}
4230 #endif /* HAS_KEYWORDS */
4231 
4232 		if (command->group) {
4233 			/* "{ echo foo; } echo bar" - bad */
4234 			syntax_error_at(ctx->word.data);
4235 			debug_printf_parse("done_word return 1: syntax error, "
4236 					"groups and arglists don't mix\n");
4237 			return 1;
4238 		}
4239 
4240 		/* If this word wasn't an assignment, next ones definitely
4241 		 * can't be assignments. Even if they look like ones. */
4242 		if (ctx->is_assignment != DEFINITELY_ASSIGNMENT
4243 		 && ctx->is_assignment != WORD_IS_KEYWORD
4244 		) {
4245 			ctx->is_assignment = NOT_ASSIGNMENT;
4246 		} else {
4247 			if (ctx->is_assignment == DEFINITELY_ASSIGNMENT) {
4248 				command->assignment_cnt++;
4249 				debug_printf_parse("++assignment_cnt=%d\n", command->assignment_cnt);
4250 			}
4251 			debug_printf_parse("ctx->is_assignment was:'%s'\n", assignment_flag[ctx->is_assignment]);
4252 			ctx->is_assignment = MAYBE_ASSIGNMENT;
4253 		}
4254 		debug_printf_parse("ctx->is_assignment='%s'\n", assignment_flag[ctx->is_assignment]);
4255 		command->argv = add_string_to_strings(command->argv, xstrdup(ctx->word.data));
4256 		debug_print_strings("word appended to argv", command->argv);
4257 	}
4258 
4259 #if ENABLE_HUSH_LOOPS
4260 	if (ctx->ctx_res_w == RES_FOR) {
4261 		if (ctx->word.has_quoted_part
4262 		 || endofname(command->argv[0])[0] != '\0'
4263 		) {
4264 			/* bash says just "not a valid identifier" */
4265 			syntax_error("bad variable name in for");
4266 			return 1;
4267 		}
4268 		/* Force FOR to have just one word (variable name) */
4269 		/* NB: basically, this makes hush see "for v in ..."
4270 		 * syntax as if it is "for v; in ...". FOR and IN become
4271 		 * two pipe structs in parse tree. */
4272 		done_pipe(ctx, PIPE_SEQ);
4273 	}
4274 #endif
4275 #if ENABLE_HUSH_CASE
4276 	/* Force CASE to have just one word */
4277 	if (ctx->ctx_res_w == RES_CASE) {
4278 		done_pipe(ctx, PIPE_SEQ);
4279 	}
4280 #endif
4281 
4282 	o_reset_to_empty_unquoted(&ctx->word);
4283 
4284 	debug_printf_parse("done_word return 0\n");
4285 	return 0;
4286 }
4287 
4288 
4289 /* Peek ahead in the input to find out if we have a "&n" construct,
4290  * as in "2>&1", that represents duplicating a file descriptor.
4291  * Return:
4292  * REDIRFD_CLOSE if >&- "close fd" construct is seen,
4293  * REDIRFD_SYNTAX_ERR if syntax error,
4294  * REDIRFD_TO_FILE if no & was seen,
4295  * or the number found.
4296  */
4297 #if BB_MMU
4298 #define parse_redir_right_fd(as_string, input) \
4299 	parse_redir_right_fd(input)
4300 #endif
parse_redir_right_fd(o_string * as_string,struct in_str * input)4301 static int parse_redir_right_fd(o_string *as_string, struct in_str *input)
4302 {
4303 	int ch, d, ok;
4304 
4305 	ch = i_peek(input);
4306 	if (ch != '&')
4307 		return REDIRFD_TO_FILE;
4308 
4309 	ch = i_getch(input);  /* get the & */
4310 	nommu_addchr(as_string, ch);
4311 	ch = i_peek(input);
4312 	if (ch == '-') {
4313 		ch = i_getch(input);
4314 		nommu_addchr(as_string, ch);
4315 		return REDIRFD_CLOSE;
4316 	}
4317 	d = 0;
4318 	ok = 0;
4319 	while (ch != EOF && isdigit(ch)) {
4320 		d = d*10 + (ch-'0');
4321 		ok = 1;
4322 		ch = i_getch(input);
4323 		nommu_addchr(as_string, ch);
4324 		ch = i_peek(input);
4325 	}
4326 	if (ok) return d;
4327 
4328 //TODO: this is the place to catch ">&file" bashism (redirect both fd 1 and 2)
4329 
4330 	bb_simple_error_msg("ambiguous redirect");
4331 	return REDIRFD_SYNTAX_ERR;
4332 }
4333 
4334 /* Return code is 0 normal, 1 if a syntax error is detected
4335  */
parse_redirect(struct parse_context * ctx,int fd,redir_type style,struct in_str * input)4336 static int parse_redirect(struct parse_context *ctx,
4337 		int fd,
4338 		redir_type style,
4339 		struct in_str *input)
4340 {
4341 	struct command *command = ctx->command;
4342 	struct redir_struct *redir;
4343 	struct redir_struct **redirp;
4344 	int dup_num;
4345 
4346 	dup_num = REDIRFD_TO_FILE;
4347 	if (style != REDIRECT_HEREDOC) {
4348 		/* Check for a '>&1' type redirect */
4349 		dup_num = parse_redir_right_fd(&ctx->as_string, input);
4350 		if (dup_num == REDIRFD_SYNTAX_ERR)
4351 			return 1;
4352 	} else {
4353 		int ch = i_peek_and_eat_bkslash_nl(input);
4354 		dup_num = (ch == '-'); /* HEREDOC_SKIPTABS bit is 1 */
4355 		if (dup_num) { /* <<-... */
4356 			ch = i_getch(input);
4357 			nommu_addchr(&ctx->as_string, ch);
4358 			ch = i_peek(input);
4359 		}
4360 	}
4361 
4362 	if (style == REDIRECT_OVERWRITE && dup_num == REDIRFD_TO_FILE) {
4363 		int ch = i_peek_and_eat_bkslash_nl(input);
4364 		if (ch == '|') {
4365 			/* >|FILE redirect ("clobbering" >).
4366 			 * Since we do not support "set -o noclobber" yet,
4367 			 * >| and > are the same for now. Just eat |.
4368 			 */
4369 			ch = i_getch(input);
4370 			nommu_addchr(&ctx->as_string, ch);
4371 		}
4372 	}
4373 
4374 	/* Create a new redir_struct and append it to the linked list */
4375 	redirp = &command->redirects;
4376 	while ((redir = *redirp) != NULL) {
4377 		redirp = &(redir->next);
4378 	}
4379 	*redirp = redir = xzalloc(sizeof(*redir));
4380 	/* redir->next = NULL; */
4381 	/* redir->rd_filename = NULL; */
4382 	redir->rd_type = style;
4383 	redir->rd_fd = (fd == -1) ? redir_table[style].default_fd : fd;
4384 
4385 	debug_printf_parse("redirect type %d %s\n", redir->rd_fd,
4386 				redir_table[style].descrip);
4387 
4388 	redir->rd_dup = dup_num;
4389 	if (style != REDIRECT_HEREDOC && dup_num != REDIRFD_TO_FILE) {
4390 		/* Erik had a check here that the file descriptor in question
4391 		 * is legit; I postpone that to "run time"
4392 		 * A "-" representation of "close me" shows up as a -3 here */
4393 		debug_printf_parse("duplicating redirect '%d>&%d'\n",
4394 				redir->rd_fd, redir->rd_dup);
4395 	} else {
4396 #if 0		/* Instead we emit error message at run time */
4397 		if (ctx->pending_redirect) {
4398 			/* For example, "cmd > <file" */
4399 			syntax_error("invalid redirect");
4400 		}
4401 #endif
4402 		/* Set ctx->pending_redirect, so we know what to do at the
4403 		 * end of the next parsed word. */
4404 		ctx->pending_redirect = redir;
4405 	}
4406 	return 0;
4407 }
4408 
4409 /* If a redirect is immediately preceded by a number, that number is
4410  * supposed to tell which file descriptor to redirect.  This routine
4411  * looks for such preceding numbers.  In an ideal world this routine
4412  * needs to handle all the following classes of redirects...
4413  *     echo 2>foo     # redirects fd  2 to file "foo", nothing passed to echo
4414  *     echo 49>foo    # redirects fd 49 to file "foo", nothing passed to echo
4415  *     echo -2>foo    # redirects fd  1 to file "foo",    "-2" passed to echo
4416  *     echo 49x>foo   # redirects fd  1 to file "foo",   "49x" passed to echo
4417  *
4418  * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
4419  * "2.7 Redirection
4420  * ... If n is quoted, the number shall not be recognized as part of
4421  * the redirection expression. For example:
4422  * echo \2>a
4423  * writes the character 2 into file a"
4424  * We are getting it right by setting ->has_quoted_part on any \<char>
4425  *
4426  * A -1 return means no valid number was found,
4427  * the caller should use the appropriate default for this redirection.
4428  */
redirect_opt_num(o_string * o)4429 static int redirect_opt_num(o_string *o)
4430 {
4431 	int num;
4432 
4433 	if (o->data == NULL)
4434 		return -1;
4435 	num = bb_strtou(o->data, NULL, 10);
4436 	if (errno || num < 0)
4437 		return -1;
4438 	o_reset_to_empty_unquoted(o);
4439 	return num;
4440 }
4441 
4442 #if BB_MMU
4443 #define fetch_till_str(as_string, input, word, skip_tabs) \
4444 	fetch_till_str(input, word, skip_tabs)
4445 #endif
fetch_till_str(o_string * as_string,struct in_str * input,const char * word,int heredoc_flags)4446 static char *fetch_till_str(o_string *as_string,
4447 		struct in_str *input,
4448 		const char *word,
4449 		int heredoc_flags)
4450 {
4451 	o_string heredoc = NULL_O_STRING;
4452 	unsigned past_EOL;
4453 	int prev = 0; /* not \ */
4454 	int ch;
4455 
4456 	/* Starting with "" is necessary for this case:
4457 	 * cat <<EOF
4458 	 *
4459 	 * xxx
4460 	 * EOF
4461 	 */
4462 	heredoc.data = xzalloc(1); /* start as "", not as NULL */
4463 
4464 	goto jump_in;
4465 
4466 	while (1) {
4467 		ch = i_getch(input);
4468 		if (ch != EOF)
4469 			nommu_addchr(as_string, ch);
4470 		if (ch == '\n' || ch == EOF) {
4471  check_heredoc_end:
4472 			if ((heredoc_flags & HEREDOC_QUOTED) || prev != '\\') {
4473 				/* End-of-line, and not a line continuation */
4474 				if (strcmp(heredoc.data + past_EOL, word) == 0) {
4475 					heredoc.data[past_EOL] = '\0';
4476 					debug_printf_heredoc("parsed '%s' heredoc '%s'\n", word, heredoc.data);
4477 					return heredoc.data;
4478 				}
4479 				if (ch == '\n') {
4480 					/* This is a new line.
4481 					 * Remember position and backslash-escaping status.
4482 					 */
4483 					o_addchr(&heredoc, ch);
4484 					prev = ch;
4485  jump_in:
4486 					past_EOL = heredoc.length;
4487 					/* Get 1st char of next line, possibly skipping leading tabs */
4488 					do {
4489 						ch = i_getch(input);
4490 						if (ch != EOF)
4491 							nommu_addchr(as_string, ch);
4492 					} while ((heredoc_flags & HEREDOC_SKIPTABS) && ch == '\t');
4493 					/* If this immediately ended the line,
4494 					 * go back to end-of-line checks.
4495 					 */
4496 					if (ch == '\n')
4497 						goto check_heredoc_end;
4498 				}
4499 			} else {
4500 				/* Backslash-line continuation in an unquoted
4501 				 * heredoc. This does not need special handling
4502 				 * for heredoc body (unquoted heredocs are
4503 				 * expanded on "execution" and that would take
4504 				 * care of this case too), but not the case
4505 				 * of line continuation *in terminator*:
4506 				 *  cat <<EOF
4507 				 *  Ok1
4508 				 *  EO\
4509 				 *  F
4510 				 */
4511 				heredoc.data[--heredoc.length] = '\0';
4512 				prev = 0; /* not '\' */
4513 				continue;
4514 			}
4515 		}
4516 		if (ch == EOF) {
4517 			o_free(&heredoc);
4518 			return NULL; /* error */
4519 		}
4520 		o_addchr(&heredoc, ch);
4521 		nommu_addchr(as_string, ch);
4522 		if (prev == '\\' && ch == '\\')
4523 			/* Correctly handle foo\\<eol> (not a line cont.) */
4524 			prev = 0; /* not '\' */
4525 		else
4526 			prev = ch;
4527 	}
4528 }
4529 
4530 /* Look at entire parse tree for not-yet-loaded REDIRECT_HEREDOCs
4531  * and load them all. There should be exactly heredoc_cnt of them.
4532  */
4533 #if BB_MMU
4534 #define fetch_heredocs(as_string, pi, heredoc_cnt, input) \
4535 	fetch_heredocs(pi, heredoc_cnt, input)
4536 #endif
fetch_heredocs(o_string * as_string,struct pipe * pi,int heredoc_cnt,struct in_str * input)4537 static int fetch_heredocs(o_string *as_string, struct pipe *pi, int heredoc_cnt, struct in_str *input)
4538 {
4539 	while (pi && heredoc_cnt) {
4540 		int i;
4541 		struct command *cmd = pi->cmds;
4542 
4543 		debug_printf_heredoc("fetch_heredocs: num_cmds:%d cmd argv0:'%s'\n",
4544 				pi->num_cmds,
4545 				cmd->argv ? cmd->argv[0] : "NONE"
4546 		);
4547 		for (i = 0; i < pi->num_cmds; i++) {
4548 			struct redir_struct *redir = cmd->redirects;
4549 
4550 			debug_printf_heredoc("fetch_heredocs: %d cmd argv0:'%s'\n",
4551 					i, cmd->argv ? cmd->argv[0] : "NONE");
4552 			while (redir) {
4553 				if (redir->rd_type == REDIRECT_HEREDOC) {
4554 					char *p;
4555 
4556 					redir->rd_type = REDIRECT_HEREDOC2;
4557 					/* redir->rd_dup is (ab)used to indicate <<- */
4558 					p = fetch_till_str(as_string, input,
4559 							redir->rd_filename, redir->rd_dup);
4560 					if (!p) {
4561 						syntax_error("unexpected EOF in here document");
4562 						return -1;
4563 					}
4564 					free(redir->rd_filename);
4565 					redir->rd_filename = p;
4566 					heredoc_cnt--;
4567 				}
4568 				redir = redir->next;
4569 			}
4570 			if (cmd->group) {
4571 				//bb_error_msg("%s:%u heredoc_cnt:%d", __func__, __LINE__, heredoc_cnt);
4572 				heredoc_cnt = fetch_heredocs(as_string, cmd->group, heredoc_cnt, input);
4573 				//bb_error_msg("%s:%u heredoc_cnt:%d", __func__, __LINE__, heredoc_cnt);
4574 				if (heredoc_cnt < 0)
4575 					return heredoc_cnt; /* error */
4576 			}
4577 			cmd++;
4578 		}
4579 		pi = pi->next;
4580 	}
4581 	return heredoc_cnt;
4582 }
4583 
4584 
4585 static int run_list(struct pipe *pi);
4586 #if BB_MMU
4587 #define parse_stream(pstring, heredoc_cnt_ptr, input, end_trigger) \
4588 	parse_stream(heredoc_cnt_ptr, input, end_trigger)
4589 #endif
4590 static struct pipe *parse_stream(char **pstring,
4591 		int *heredoc_cnt_ptr,
4592 		struct in_str *input,
4593 		int end_trigger);
4594 
4595 /* Returns number of heredocs not yet consumed,
4596  * or -1 on error.
4597  */
parse_group(struct parse_context * ctx,struct in_str * input,int ch)4598 static int parse_group(struct parse_context *ctx,
4599 		struct in_str *input, int ch)
4600 {
4601 	/* ctx->word contains characters seen prior to ( or {.
4602 	 * Typically it's empty, but for function defs,
4603 	 * it contains function name (without '()'). */
4604 #if BB_MMU
4605 # define as_string NULL
4606 #else
4607 	char *as_string = NULL;
4608 #endif
4609 	struct pipe *pipe_list;
4610 	int heredoc_cnt = 0;
4611 	int endch;
4612 	struct command *command = ctx->command;
4613 
4614 	debug_printf_parse("parse_group entered\n");
4615 #if ENABLE_HUSH_FUNCTIONS
4616 	if (ch == '(' && !ctx->word.has_quoted_part) {
4617 		if (ctx->word.length)
4618 			if (done_word(ctx))
4619 				return -1;
4620 		if (!command->argv)
4621 			goto skip; /* (... */
4622 		if (command->argv[1]) { /* word word ... (... */
4623 			syntax_error_unexpected_ch('(');
4624 			return -1;
4625 		}
4626 		/* it is "word(..." or "word (..." */
4627 		do
4628 			ch = i_getch(input);
4629 		while (ch == ' ' || ch == '\t');
4630 		if (ch != ')') {
4631 			syntax_error_unexpected_ch(ch);
4632 			return -1;
4633 		}
4634 		nommu_addchr(&ctx->as_string, ch);
4635 		do
4636 			ch = i_getch(input);
4637 		while (ch == ' ' || ch == '\t' || ch == '\n');
4638 		if (ch != '{' && ch != '(') {
4639 			syntax_error_unexpected_ch(ch);
4640 			return -1;
4641 		}
4642 		nommu_addchr(&ctx->as_string, ch);
4643 		command->cmd_type = CMD_FUNCDEF;
4644 		goto skip;
4645 	}
4646 #endif
4647 
4648 #if 0 /* Prevented by caller */
4649 	if (command->argv /* word [word]{... */
4650 	 || ctx->word.length /* word{... */
4651 	 || ctx->word.has_quoted_part /* ""{... */
4652 	) {
4653 		syntax_error(NULL);
4654 		debug_printf_parse("parse_group return -1: "
4655 			"syntax error, groups and arglists don't mix\n");
4656 		return -1;
4657 	}
4658 #endif
4659 
4660  IF_HUSH_FUNCTIONS(skip:)
4661 
4662 	endch = '}';
4663 	if (ch == '(') {
4664 		endch = ')';
4665 		IF_HUSH_FUNCTIONS(if (command->cmd_type != CMD_FUNCDEF))
4666 			command->cmd_type = CMD_SUBSHELL;
4667 	} else {
4668 		/* bash does not allow "{echo...", requires whitespace */
4669 		ch = i_peek(input);
4670 		if (ch != ' ' && ch != '\t' && ch != '\n'
4671 		 && ch != '('	/* but "{(..." is allowed (without whitespace) */
4672 		) {
4673 			syntax_error_unexpected_ch(ch);
4674 			return -1;
4675 		}
4676 		if (ch != '(') {
4677 			ch = i_getch(input);
4678 			nommu_addchr(&ctx->as_string, ch);
4679 		}
4680 	}
4681 
4682 	debug_printf_heredoc("calling parse_stream, heredoc_cnt:%d\n", heredoc_cnt);
4683 	pipe_list = parse_stream(&as_string, &heredoc_cnt, input, endch);
4684 	debug_printf_heredoc("parse_stream returned: heredoc_cnt:%d\n", heredoc_cnt);
4685 #if !BB_MMU
4686 	if (as_string)
4687 		o_addstr(&ctx->as_string, as_string);
4688 #endif
4689 
4690 	/* empty ()/{} or parse error? */
4691 	if (!pipe_list || pipe_list == ERR_PTR) {
4692 		/* parse_stream already emitted error msg */
4693 		if (!BB_MMU)
4694 			free(as_string);
4695 		debug_printf_parse("parse_group return -1: "
4696 			"parse_stream returned %p\n", pipe_list);
4697 		return -1;
4698 	}
4699 #if !BB_MMU
4700 	as_string[strlen(as_string) - 1] = '\0'; /* plink ')' or '}' */
4701 	command->group_as_string = as_string;
4702 	debug_printf_parse("end of group, remembering as:'%s'\n",
4703 			command->group_as_string);
4704 #endif
4705 
4706 #if ENABLE_HUSH_FUNCTIONS
4707 	/* Convert "f() (cmds)" to "f() {(cmds)}" */
4708 	if (command->cmd_type == CMD_FUNCDEF && endch == ')') {
4709 		struct command *cmd2;
4710 
4711 		cmd2 = xzalloc(sizeof(*cmd2));
4712 		cmd2->cmd_type = CMD_SUBSHELL;
4713 		cmd2->group = pipe_list;
4714 # if !BB_MMU
4715 //UNTESTED!
4716 		cmd2->group_as_string = command->group_as_string;
4717 		command->group_as_string = xasprintf("(%s)", command->group_as_string);
4718 # endif
4719 
4720 		pipe_list = new_pipe();
4721 		pipe_list->cmds = cmd2;
4722 		pipe_list->num_cmds = 1;
4723 	}
4724 #endif
4725 
4726 	command->group = pipe_list;
4727 
4728 	debug_printf_parse("parse_group return %d\n", heredoc_cnt);
4729 	return heredoc_cnt;
4730 	/* command remains "open", available for possible redirects */
4731 #undef as_string
4732 }
4733 
4734 #if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS
4735 /* Subroutines for copying $(...) and `...` things */
4736 /* '...' */
add_till_single_quote(o_string * dest,struct in_str * input)4737 static int add_till_single_quote(o_string *dest, struct in_str *input)
4738 {
4739 	while (1) {
4740 		int ch = i_getch(input);
4741 		if (ch == EOF) {
4742 			syntax_error_unterm_ch('\'');
4743 			return 0;
4744 		}
4745 		if (ch == '\'')
4746 			return 1;
4747 		o_addchr(dest, ch);
4748 	}
4749 }
add_till_single_quote_dquoted(o_string * dest,struct in_str * input)4750 static int add_till_single_quote_dquoted(o_string *dest, struct in_str *input)
4751 {
4752 	while (1) {
4753 		int ch = i_getch(input);
4754 		if (ch == EOF) {
4755 			syntax_error_unterm_ch('\'');
4756 			return 0;
4757 		}
4758 		if (ch == '\'')
4759 			return 1;
4760 		o_addqchr(dest, ch);
4761 	}
4762 }
4763 /* "...\"...`..`...." - do we need to handle "...$(..)..." too? */
4764 static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote);
add_till_double_quote(o_string * dest,struct in_str * input)4765 static int add_till_double_quote(o_string *dest, struct in_str *input)
4766 {
4767 	while (1) {
4768 		int ch = i_getch(input);
4769 		if (ch == EOF) {
4770 			syntax_error_unterm_ch('"');
4771 			return 0;
4772 		}
4773 		if (ch == '"')
4774 			return 1;
4775 		if (ch == '\\') {  /* \x. Copy both chars. */
4776 			o_addchr(dest, ch);
4777 			ch = i_getch(input);
4778 		}
4779 		o_addchr(dest, ch);
4780 		if (ch == '`') {
4781 			if (!add_till_backquote(dest, input, /*in_dquote:*/ 1))
4782 				return 0;
4783 			o_addchr(dest, ch);
4784 			continue;
4785 		}
4786 		//if (ch == '$') ...
4787 	}
4788 }
4789 /* Process `cmd` - copy contents until "`" is seen. Complicated by
4790  * \` quoting.
4791  * "Within the backquoted style of command substitution, backslash
4792  * shall retain its literal meaning, except when followed by: '$', '`', or '\'.
4793  * The search for the matching backquote shall be satisfied by the first
4794  * backquote found without a preceding backslash; during this search,
4795  * if a non-escaped backquote is encountered within a shell comment,
4796  * a here-document, an embedded command substitution of the $(command)
4797  * form, or a quoted string, undefined results occur. A single-quoted
4798  * or double-quoted string that begins, but does not end, within the
4799  * "`...`" sequence produces undefined results."
4800  * Example                               Output
4801  * echo `echo '\'TEST\`echo ZZ\`BEST`    \TESTZZBEST
4802  */
add_till_backquote(o_string * dest,struct in_str * input,int in_dquote)4803 static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote)
4804 {
4805 	while (1) {
4806 		int ch = i_getch(input);
4807 		if (ch == '`')
4808 			return 1;
4809 		if (ch == '\\') {
4810 			/* \x. Copy both unless it is \`, \$, \\ and maybe \" */
4811 			ch = i_getch(input);
4812 			if (ch != '`'
4813 			 && ch != '$'
4814 			 && ch != '\\'
4815 			 && (!in_dquote || ch != '"')
4816 			) {
4817 				o_addchr(dest, '\\');
4818 			}
4819 		}
4820 		if (ch == EOF) {
4821 			syntax_error_unterm_ch('`');
4822 			return 0;
4823 		}
4824 		o_addchr(dest, ch);
4825 	}
4826 }
4827 /* Process $(cmd) - copy contents until ")" is seen. Complicated by
4828  * quoting and nested ()s.
4829  * "With the $(command) style of command substitution, all characters
4830  * following the open parenthesis to the matching closing parenthesis
4831  * constitute the command. Any valid shell script can be used for command,
4832  * except a script consisting solely of redirections which produces
4833  * unspecified results."
4834  * Example                              Output
4835  * echo $(echo '(TEST)' BEST)           (TEST) BEST
4836  * echo $(echo 'TEST)' BEST)            TEST) BEST
4837  * echo $(echo \(\(TEST\) BEST)         ((TEST) BEST
4838  *
4839  * Also adapted to eat ${var%...} and $((...)) constructs, since ... part
4840  * can contain arbitrary constructs, just like $(cmd).
4841  * In bash compat mode, it needs to also be able to stop on ':' or '/'
4842  * for ${var:N[:M]} and ${var/P[/R]} parsing.
4843  */
4844 #define DOUBLE_CLOSE_CHAR_FLAG 0x80
add_till_closing_bracket(o_string * dest,struct in_str * input,unsigned end_ch)4845 static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsigned end_ch)
4846 {
4847 	int ch;
4848 	char dbl = end_ch & DOUBLE_CLOSE_CHAR_FLAG;
4849 # if BASH_SUBSTR || BASH_PATTERN_SUBST
4850 	char end_char2 = end_ch >> 8;
4851 # endif
4852 	end_ch &= (DOUBLE_CLOSE_CHAR_FLAG - 1);
4853 
4854 # if ENABLE_HUSH_INTERACTIVE
4855 	G.promptmode = 1; /* PS2 */
4856 # endif
4857 	debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode);
4858 
4859 	while (1) {
4860 		ch = i_getch(input);
4861 		if (ch == EOF) {
4862 			syntax_error_unterm_ch(end_ch);
4863 			return 0;
4864 		}
4865 		if (ch == end_ch
4866 # if BASH_SUBSTR || BASH_PATTERN_SUBST
4867 		 || ch == end_char2
4868 # endif
4869 		) {
4870 			if (!dbl)
4871 				break;
4872 			/* we look for closing )) of $((EXPR)) */
4873 			if (i_peek_and_eat_bkslash_nl(input) == end_ch) {
4874 				i_getch(input); /* eat second ')' */
4875 				break;
4876 			}
4877 		}
4878 		o_addchr(dest, ch);
4879 		//bb_error_msg("%s:o_addchr('%c')", __func__, ch);
4880 		if (ch == '(' || ch == '{') {
4881 			ch = (ch == '(' ? ')' : '}');
4882 			if (!add_till_closing_bracket(dest, input, ch))
4883 				return 0;
4884 			o_addchr(dest, ch);
4885 			continue;
4886 		}
4887 		if (ch == '\'') {
4888 			if (!add_till_single_quote(dest, input))
4889 				return 0;
4890 			o_addchr(dest, ch);
4891 			continue;
4892 		}
4893 		if (ch == '"') {
4894 			if (!add_till_double_quote(dest, input))
4895 				return 0;
4896 			o_addchr(dest, ch);
4897 			continue;
4898 		}
4899 		if (ch == '`') {
4900 			if (!add_till_backquote(dest, input, /*in_dquote:*/ 0))
4901 				return 0;
4902 			o_addchr(dest, ch);
4903 			continue;
4904 		}
4905 		if (ch == '\\') {
4906 			/* \x. Copy verbatim. Important for  \(, \) */
4907 			ch = i_getch(input);
4908 			if (ch == EOF) {
4909 				syntax_error_unterm_ch(end_ch);
4910 				return 0;
4911 			}
4912 # if 0
4913 			if (ch == '\n') {
4914 				/* "backslash+newline", ignore both */
4915 				o_delchr(dest); /* undo insertion of '\' */
4916 				continue;
4917 			}
4918 # endif
4919 			o_addchr(dest, ch);
4920 			//bb_error_msg("%s:o_addchr('%c') after '\\'", __func__, ch);
4921 			continue;
4922 		}
4923 	}
4924 	debug_printf_parse("%s return '%s' ch:'%c'\n", __func__, dest->data, ch);
4925 	return ch;
4926 }
4927 #endif /* ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS */
4928 
4929 #if BASH_DOLLAR_SQUOTE
4930 /* Return code: 1 for "found and parsed", 0 for "seen something else" */
4931 # if BB_MMU
4932 #define parse_dollar_squote(as_string, dest, input) \
4933 	parse_dollar_squote(dest, input)
4934 #define as_string NULL
4935 # endif
parse_dollar_squote(o_string * as_string,o_string * dest,struct in_str * input)4936 static int parse_dollar_squote(o_string *as_string, o_string *dest, struct in_str *input)
4937 {
4938 	int start;
4939 	int ch = i_peek_and_eat_bkslash_nl(input);  /* first character after the $ */
4940 	debug_printf_parse("parse_dollar_squote entered: ch='%c'\n", ch);
4941 	if (ch != '\'')
4942 		return 0;
4943 
4944 	dest->has_quoted_part = 1;
4945 	start = dest->length;
4946 
4947 	ch = i_getch(input); /* eat ' */
4948 	nommu_addchr(as_string, ch);
4949 	while (1) {
4950 		ch = i_getch(input);
4951 		nommu_addchr(as_string, ch);
4952 		if (ch == EOF) {
4953 			syntax_error_unterm_ch('\'');
4954 			return 0;
4955 		}
4956 		if (ch == '\'')
4957 			break;
4958 		if (ch == SPECIAL_VAR_SYMBOL) {
4959 			/* Convert raw ^C to corresponding special variable reference */
4960 			o_addchr(dest, SPECIAL_VAR_SYMBOL);
4961 			o_addchr(dest, SPECIAL_VAR_QUOTED_SVS);
4962 			/* will addchr() another SPECIAL_VAR_SYMBOL (see after the if() block) */
4963 		} else if (ch == '\\') {
4964 			static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
4965 
4966 			ch = i_getch(input);
4967 			nommu_addchr(as_string, ch);
4968 			if (strchr(C_escapes, ch)) {
4969 				char buf[4];
4970 				char *p = buf;
4971 				int cnt = 2;
4972 
4973 				buf[0] = ch;
4974 				if ((unsigned char)(ch - '0') <= 7) { /* \ooo */
4975 					do {
4976 						ch = i_peek(input);
4977 						if ((unsigned char)(ch - '0') > 7)
4978 							break;
4979 						*++p = ch = i_getch(input);
4980 						nommu_addchr(as_string, ch);
4981 					} while (--cnt != 0);
4982 				} else if (ch == 'x') { /* \xHH */
4983 					do {
4984 						ch = i_peek(input);
4985 						if (!isxdigit(ch))
4986 							break;
4987 						*++p = ch = i_getch(input);
4988 						nommu_addchr(as_string, ch);
4989 					} while (--cnt != 0);
4990 					if (cnt == 2) { /* \x but next char is "bad" */
4991 						ch = 'x';
4992 						goto unrecognized;
4993 					}
4994 				} /* else simple seq like \\ or \t */
4995 				*++p = '\0';
4996 				p = buf;
4997 				ch = bb_process_escape_sequence((void*)&p);
4998 				//bb_error_msg("buf:'%s' ch:%x", buf, ch);
4999 				if (ch == '\0')
5000 					continue; /* bash compat: $'...\0...' emits nothing */
5001 			} else { /* unrecognized "\z": encode both chars unless ' or " */
5002 				if (ch != '\'' && ch != '"') {
5003  unrecognized:
5004 					o_addqchr(dest, '\\');
5005 				}
5006 			}
5007 		} /* if (\...) */
5008 		o_addqchr(dest, ch);
5009 	}
5010 
5011 	if (dest->length == start) {
5012 		/* $'', $'\0', $'\000\x00' and the like */
5013 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
5014 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
5015 	}
5016 
5017 	return 1;
5018 # undef as_string
5019 }
5020 #else
5021 # define parse_dollar_squote(as_string, dest, input) 0
5022 #endif /* BASH_DOLLAR_SQUOTE */
5023 
5024 /* Return code: 0 for OK, 1 for syntax error */
5025 #if BB_MMU
5026 #define parse_dollar(as_string, dest, input, quote_mask) \
5027 	parse_dollar(dest, input, quote_mask)
5028 #define as_string NULL
5029 #endif
parse_dollar(o_string * as_string,o_string * dest,struct in_str * input,unsigned char quote_mask)5030 static int parse_dollar(o_string *as_string,
5031 		o_string *dest,
5032 		struct in_str *input, unsigned char quote_mask)
5033 {
5034 	int ch = i_peek_and_eat_bkslash_nl(input);  /* first character after the $ */
5035 
5036 	debug_printf_parse("parse_dollar entered: ch='%c' quote_mask:0x%x\n", ch, quote_mask);
5037 	if (isalpha(ch)) {
5038  make_var:
5039 		ch = i_getch(input);
5040 		nommu_addchr(as_string, ch);
5041  /*make_var1:*/
5042 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
5043 		while (1) {
5044 			debug_printf_parse(": '%c'\n", ch);
5045 			o_addchr(dest, ch | quote_mask);
5046 			quote_mask = 0;
5047 			ch = i_peek_and_eat_bkslash_nl(input);
5048 			if (!isalnum(ch) && ch != '_') {
5049 				/* End of variable name reached */
5050 				break;
5051 			}
5052 			ch = i_getch(input);
5053 			nommu_addchr(as_string, ch);
5054 		}
5055 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
5056 	} else if (isdigit(ch)) {
5057  make_one_char_var:
5058 		ch = i_getch(input);
5059 		nommu_addchr(as_string, ch);
5060 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
5061 		debug_printf_parse(": '%c'\n", ch);
5062 		o_addchr(dest, ch | quote_mask);
5063 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
5064 	} else switch (ch) {
5065 	case '$': /* pid */
5066 	case '!': /* last bg pid */
5067 	case '?': /* last exit code */
5068 	case '#': /* number of args */
5069 	case '*': /* args */
5070 	case '@': /* args */
5071 	case '-': /* $- option flags set by set builtin or shell options (-i etc) */
5072 		goto make_one_char_var;
5073 	case '{': {
5074 		char len_single_ch;
5075 
5076 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
5077 
5078 		ch = i_getch(input); /* eat '{' */
5079 		nommu_addchr(as_string, ch);
5080 
5081 		ch = i_getch_and_eat_bkslash_nl(input); /* first char after '{' */
5082 		/* It should be ${?}, or ${#var},
5083 		 * or even ${?+subst} - operator acting on a special variable,
5084 		 * or the beginning of variable name.
5085 		 */
5086 		if (ch == EOF
5087 		 || (!strchr(_SPECIAL_VARS_STR, ch) && !isalnum(ch)) /* not one of those */
5088 		) {
5089  bad_dollar_syntax:
5090 			syntax_error_unterm_str("${name}");
5091 			debug_printf_parse("parse_dollar return 0: unterminated ${name}\n");
5092 			return 0;
5093 		}
5094 		nommu_addchr(as_string, ch);
5095 		len_single_ch = ch;
5096 		ch |= quote_mask;
5097 
5098 		/* It's possible to just call add_till_closing_bracket() at this point.
5099 		 * However, this regresses some of our testsuite cases
5100 		 * which check invalid constructs like ${%}.
5101 		 * Oh well... let's check that the var name part is fine... */
5102 
5103 		if (isdigit(len_single_ch)
5104 		 || (len_single_ch == '#' && isdigit(i_peek_and_eat_bkslash_nl(input)))
5105 		) {
5106 			/* Execution engine uses plain xatoi_positive()
5107 			 * to interpret ${NNN} and {#NNN},
5108 			 * check syntax here in the parser.
5109 			 * (bash does not support expressions in ${#NN},
5110 			 * e.g. ${#$var} and {#1:+WORD} are not supported).
5111 			 */
5112 			unsigned cnt = 9; /* max 9 digits for ${NN} and 8 for {#NN} */
5113 			while (1) {
5114 				o_addchr(dest, ch);
5115 				debug_printf_parse(": '%c'\n", ch);
5116 				ch = i_getch_and_eat_bkslash_nl(input);
5117 				nommu_addchr(as_string, ch);
5118 				if (ch == '}')
5119 					break;
5120 				if (--cnt == 0)
5121 					goto bad_dollar_syntax;
5122 				if (len_single_ch != '#' && strchr(VAR_SUBST_OPS, ch))
5123 					/* ${NN<op>...} is valid */
5124 					goto eat_until_closing;
5125 				if (!isdigit(ch))
5126 					goto bad_dollar_syntax;
5127 			}
5128 		} else
5129 		while (1) {
5130 			unsigned pos;
5131 
5132 			o_addchr(dest, ch);
5133 			debug_printf_parse(": '%c'\n", ch);
5134 
5135 			ch = i_getch(input);
5136 			nommu_addchr(as_string, ch);
5137 			if (ch == '}')
5138 				break;
5139 			if (!isalnum(ch) && ch != '_') {
5140 				unsigned end_ch;
5141 				unsigned char last_ch;
5142 				/* handle parameter expansions
5143 				 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02
5144 				 */
5145 				if (!strchr(VAR_SUBST_OPS, ch)) { /* ${var<bad_char>... */
5146 					if (len_single_ch != '#'
5147 					/*|| !strchr(SPECIAL_VARS_STR, ch) - disallow errors like ${#+} ? */
5148 					 || i_peek(input) != '}'
5149 					) {
5150 						goto bad_dollar_syntax;
5151 					}
5152 					/* else: it's "length of C" ${#C} op,
5153 					 * where C is a single char
5154 					 * special var name, e.g. ${#!}.
5155 					 */
5156 				}
5157  eat_until_closing:
5158 				/* Eat everything until closing '}' (or ':') */
5159 				end_ch = '}';
5160 				if (BASH_SUBSTR
5161 				 && ch == ':'
5162 				 && !strchr(MINUS_PLUS_EQUAL_QUESTION, i_peek(input))
5163 				) {
5164 					/* It's ${var:N[:M]} thing */
5165 					end_ch = '}' * 0x100 + ':';
5166 				}
5167 				if (BASH_PATTERN_SUBST
5168 				 && ch == '/'
5169 				) {
5170 					/* It's ${var/[/]pattern[/repl]} thing */
5171 					if (i_peek(input) == '/') { /* ${var//pattern[/repl]}? */
5172 						i_getch(input);
5173 						nommu_addchr(as_string, '/');
5174 						ch = '\\';
5175 					}
5176 					end_ch = '}' * 0x100 + '/';
5177 				}
5178 				o_addchr(dest, ch);
5179 				/* The pattern can't be empty.
5180 				 * IOW: if the first char after "${v//" is a slash,
5181 				 * it does not terminate the pattern - it's the first char of the pattern:
5182 				 *  v=/dev/ram; echo ${v////-}  prints -dev-ram (pattern is "/")
5183 				 *  v=/dev/ram; echo ${v///r/-} prints /dev-am  (pattern is "/r")
5184 				 */
5185 				if (i_peek(input) == '/') {
5186 					o_addchr(dest, i_getch(input));
5187 				}
5188  again:
5189 				if (!BB_MMU)
5190 					pos = dest->length;
5191 #if ENABLE_HUSH_DOLLAR_OPS
5192 				last_ch = add_till_closing_bracket(dest, input, end_ch);
5193 				if (last_ch == 0) /* error? */
5194 					return 0;
5195 #else
5196 # error Simple code to only allow ${var} is not implemented
5197 #endif
5198 				if (as_string) {
5199 					o_addstr(as_string, dest->data + pos);
5200 					o_addchr(as_string, last_ch);
5201 				}
5202 
5203 				if ((BASH_SUBSTR || BASH_PATTERN_SUBST)
5204 					 && (end_ch & 0xff00)
5205 				) {
5206 					/* close the first block: */
5207 					o_addchr(dest, SPECIAL_VAR_SYMBOL);
5208 					/* while parsing N from ${var:N[:M]}
5209 					 * or pattern from ${var/[/]pattern[/repl]} */
5210 					if ((end_ch & 0xff) == last_ch) {
5211 						/* got ':' or '/'- parse the rest */
5212 						end_ch = '}';
5213 						goto again;
5214 					}
5215 					/* got '}' */
5216 					if (BASH_SUBSTR && end_ch == '}' * 0x100 + ':') {
5217 						/* it's ${var:N} - emulate :999999999 */
5218 						o_addstr(dest, "999999999");
5219 					} /* else: it's ${var/[/]pattern} */
5220 				}
5221 				break;
5222 			}
5223 			len_single_ch = 0; /* it can't be ${#C} op */
5224 		}
5225 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
5226 		break;
5227 	}
5228 #if ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_TICK
5229 	case '(': {
5230 		unsigned pos;
5231 
5232 		ch = i_getch(input);
5233 		nommu_addchr(as_string, ch);
5234 # if ENABLE_FEATURE_SH_MATH
5235 		if (i_peek_and_eat_bkslash_nl(input) == '(') {
5236 			ch = i_getch(input);
5237 			nommu_addchr(as_string, ch);
5238 			o_addchr(dest, SPECIAL_VAR_SYMBOL);
5239 			o_addchr(dest, quote_mask | '+');
5240 			if (!BB_MMU)
5241 				pos = dest->length;
5242 			if (!add_till_closing_bracket(dest, input, ')' | DOUBLE_CLOSE_CHAR_FLAG))
5243 				return 0; /* error */
5244 			if (as_string) {
5245 				o_addstr(as_string, dest->data + pos);
5246 				o_addchr(as_string, ')');
5247 				o_addchr(as_string, ')');
5248 			}
5249 			o_addchr(dest, SPECIAL_VAR_SYMBOL);
5250 			break;
5251 		}
5252 # endif
5253 # if ENABLE_HUSH_TICK
5254 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
5255 		o_addchr(dest, quote_mask | '`');
5256 		if (!BB_MMU)
5257 			pos = dest->length;
5258 		if (!add_till_closing_bracket(dest, input, ')'))
5259 			return 0; /* error */
5260 		if (as_string) {
5261 			o_addstr(as_string, dest->data + pos);
5262 			o_addchr(as_string, ')');
5263 		}
5264 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
5265 # endif
5266 		break;
5267 	}
5268 #endif
5269 	case '_':
5270 		goto make_var;
5271 #if 0
5272 	/* TODO: $_: */
5273 	/* $_ Shell or shell script name; or last argument of last command
5274 	 * (if last command wasn't a pipe; if it was, bash sets $_ to "");
5275 	 * but in command's env, set to full pathname used to invoke it */
5276 		ch = i_getch(input);
5277 		nommu_addchr(as_string, ch);
5278 		ch = i_peek_and_eat_bkslash_nl(input);
5279 		if (isalnum(ch)) { /* it's $_name or $_123 */
5280 			ch = '_';
5281 			goto make_var1;
5282 		}
5283 		/* else: it's $_ */
5284 #endif
5285 	default:
5286 		o_addQchr(dest, '$');
5287 	}
5288 	debug_printf_parse("parse_dollar return 1 (ok)\n");
5289 	return 1;
5290 #undef as_string
5291 }
5292 
5293 #if BB_MMU
5294 #define encode_string(as_string, dest, input, dquote_end) \
5295 	encode_string(dest, input, dquote_end)
5296 #define as_string NULL
5297 #endif
encode_string(o_string * as_string,o_string * dest,struct in_str * input,int dquote_end)5298 static int encode_string(o_string *as_string,
5299 		o_string *dest,
5300 		struct in_str *input,
5301 		int dquote_end)
5302 {
5303 	int ch;
5304 	int next;
5305 
5306  again:
5307 	ch = i_getch(input);
5308 	if (ch != EOF)
5309 		nommu_addchr(as_string, ch);
5310 	if (ch == dquote_end) { /* may be only '"' or EOF */
5311 		debug_printf_parse("encode_string return 1 (ok)\n");
5312 		return 1;
5313 	}
5314 	/* note: can't move it above ch == dquote_end check! */
5315 	if (ch == EOF) {
5316 		syntax_error_unterm_ch('"');
5317 		return 0; /* error */
5318 	}
5319 	next = '\0';
5320 	if (ch != '\n') {
5321 		next = i_peek(input);
5322 	}
5323 	debug_printf_parse("\" ch=%c (%d) escape=%d\n",
5324 			ch, ch, !!(dest->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
5325 	if (ch == '\\') {
5326 		if (next == EOF) {
5327 			/* Testcase: in interactive shell a file with
5328 			 *  echo "unterminated string\<eof>
5329 			 * is sourced.
5330 			 */
5331 			syntax_error_unterm_ch('"');
5332 			return 0; /* error */
5333 		}
5334 		/* bash:
5335 		 * "The backslash retains its special meaning [in "..."]
5336 		 * only when followed by one of the following characters:
5337 		 * $, `, ", \, or <newline>.  A double quote may be quoted
5338 		 * within double quotes by preceding it with a backslash."
5339 		 * NB: in (unquoted) heredoc, above does not apply to ",
5340 		 * therefore we check for it by "next == dquote_end" cond.
5341 		 */
5342 		if (next == dquote_end || strchr("$`\\\n", next)) {
5343 			ch = i_getch(input); /* eat next */
5344 			if (ch == '\n')
5345 				goto again; /* skip \<newline> */
5346 		} /* else: ch remains == '\\', and we double it below: */
5347 		o_addqchr(dest, ch); /* \c if c is a glob char, else just c */
5348 		nommu_addchr(as_string, ch);
5349 		goto again;
5350 	}
5351 	if (ch == '$') {
5352 		//if (parse_dollar_squote(as_string, dest, input))
5353 		//	goto again;
5354 		if (!parse_dollar(as_string, dest, input, /*quote_mask:*/ 0x80)) {
5355 			debug_printf_parse("encode_string return 0: "
5356 					"parse_dollar returned 0 (error)\n");
5357 			return 0;
5358 		}
5359 		goto again;
5360 	}
5361 #if ENABLE_HUSH_TICK
5362 	if (ch == '`') {
5363 		//unsigned pos = dest->length;
5364 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
5365 		o_addchr(dest, 0x80 | '`');
5366 		if (!add_till_backquote(dest, input, /*in_dquote:*/ dquote_end == '"'))
5367 			return 0; /* error */
5368 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
5369 		//debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
5370 		goto again;
5371 	}
5372 #endif
5373 	o_addQchr(dest, ch);
5374 	if (ch == SPECIAL_VAR_SYMBOL) {
5375 		/* Convert "^C" to corresponding special variable reference */
5376 		o_addchr(dest, SPECIAL_VAR_QUOTED_SVS);
5377 		o_addchr(dest, SPECIAL_VAR_SYMBOL);
5378 	}
5379 	goto again;
5380 #undef as_string
5381 }
5382 
5383 /*
5384  * Scan input until EOF or end_trigger char.
5385  * Return a list of pipes to execute, or NULL on EOF
5386  * or if end_trigger character is met.
5387  * On syntax error, exit if shell is not interactive,
5388  * reset parsing machinery and start parsing anew,
5389  * or return ERR_PTR.
5390  */
parse_stream(char ** pstring,int * heredoc_cnt_ptr,struct in_str * input,int end_trigger)5391 static struct pipe *parse_stream(char **pstring,
5392 		int *heredoc_cnt_ptr,
5393 		struct in_str *input,
5394 		int end_trigger)
5395 {
5396 	struct parse_context ctx;
5397 	int heredoc_cnt;
5398 
5399 	/* Single-quote triggers a bypass of the main loop until its mate is
5400 	 * found.  When recursing, quote state is passed in via ctx.word.o_expflags.
5401 	 */
5402 	debug_printf_parse("parse_stream entered, end_trigger='%c'\n",
5403 			end_trigger ? end_trigger : 'X');
5404 	debug_enter();
5405 
5406 	initialize_context(&ctx);
5407 
5408 	/* If very first arg is "" or '', ctx.word.data may end up NULL.
5409 	 * Preventing this:
5410 	 */
5411 	ctx.word.data = xzalloc(1); /* start as "", not as NULL */
5412 
5413 	/* We used to separate words on $IFS here. This was wrong.
5414 	 * $IFS is used only for word splitting when $var is expanded,
5415 	 * here we should use blank chars as separators, not $IFS
5416 	 */
5417 
5418 	heredoc_cnt = 0;
5419 	while (1) {
5420 		const char *is_blank;
5421 		const char *is_special;
5422 		int ch;
5423 		int next;
5424 		int redir_fd;
5425 		redir_type redir_style;
5426 
5427 		ch = i_getch(input);
5428 		debug_printf_parse(": ch=%c (%d) escape=%d\n",
5429 				ch, ch, !!(ctx.word.o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
5430 		if (ch == EOF) {
5431 			struct pipe *pi;
5432 
5433 			if (heredoc_cnt) {
5434 				syntax_error_unterm_str("here document");
5435 				goto parse_error_exitcode1;
5436 			}
5437 			if (end_trigger == ')') {
5438 				syntax_error_unterm_ch('(');
5439 				goto parse_error_exitcode1;
5440 			}
5441 			if (end_trigger == '}') {
5442 				syntax_error_unterm_ch('{');
5443 				goto parse_error_exitcode1;
5444 			}
5445 
5446 			if (done_word(&ctx)) {
5447 				goto parse_error_exitcode1;
5448 			}
5449 			o_free_and_set_NULL(&ctx.word);
5450 			done_pipe(&ctx, PIPE_SEQ);
5451 			pi = ctx.list_head;
5452 			/* If we got nothing... */
5453 			/* (this makes bare "&" cmd a no-op.
5454 			 * bash says: "syntax error near unexpected token '&'") */
5455 			if (pi->num_cmds == 0
5456 			IF_HAS_KEYWORDS(&& pi->res_word == RES_NONE)
5457 			) {
5458 				free_pipe_list(pi);
5459 				pi = NULL;
5460 			}
5461 #if !BB_MMU
5462 			debug_printf_parse("as_string1 '%s'\n", ctx.as_string.data);
5463 			if (pstring)
5464 				*pstring = ctx.as_string.data;
5465 			else
5466 				o_free(&ctx.as_string);
5467 #endif
5468 			// heredoc_cnt must be 0 here anyway
5469 			//if (heredoc_cnt_ptr)
5470 			//	*heredoc_cnt_ptr = heredoc_cnt;
5471 			debug_leave();
5472 			debug_printf_heredoc("parse_stream return heredoc_cnt:%d\n", heredoc_cnt);
5473 			debug_printf_parse("parse_stream return %p\n", pi);
5474 			return pi;
5475 		}
5476 
5477 		/* Handle "'" and "\" first, as they won't play nice with
5478 		 * i_peek_and_eat_bkslash_nl() anyway:
5479 		 *   echo z\\
5480 		 * and
5481 		 *   echo '\
5482 		 *   '
5483 		 * would break.
5484 		 */
5485 		if (ch == '\\') {
5486 			ch = i_getch(input);
5487 			if (ch == '\n')
5488 				continue; /* drop \<newline>, get next char */
5489 			nommu_addchr(&ctx.as_string, '\\');
5490 			if (ch == SPECIAL_VAR_SYMBOL) {
5491 				nommu_addchr(&ctx.as_string, ch);
5492 				/* Convert \^C to corresponding special variable reference */
5493 				goto case_SPECIAL_VAR_SYMBOL;
5494 			}
5495 			o_addchr(&ctx.word, '\\');
5496 			if (ch == EOF) {
5497 				/* Testcase: eval 'echo Ok\' */
5498 				/* bash-4.3.43 was removing backslash,
5499 				 * but 4.4.19 retains it, most other shells too
5500 				 */
5501 				continue; /* get next char */
5502 			}
5503 			/* Example: echo Hello \2>file
5504 			 * we need to know that word 2 is quoted
5505 			 */
5506 			ctx.word.has_quoted_part = 1;
5507 			nommu_addchr(&ctx.as_string, ch);
5508 			o_addchr(&ctx.word, ch);
5509 			continue; /* get next char */
5510 		}
5511 		nommu_addchr(&ctx.as_string, ch);
5512 		if (ch == '\'') {
5513 			ctx.word.has_quoted_part = 1;
5514 			next = i_getch(input);
5515 			if (next == '\'' && !ctx.pending_redirect)
5516 				goto insert_empty_quoted_str_marker;
5517 
5518 			ch = next;
5519 			while (1) {
5520 				if (ch == EOF) {
5521 					syntax_error_unterm_ch('\'');
5522 					goto parse_error_exitcode1;
5523 				}
5524 				nommu_addchr(&ctx.as_string, ch);
5525 				if (ch == '\'')
5526 					break;
5527 				if (ch == SPECIAL_VAR_SYMBOL) {
5528 					/* Convert raw ^C to corresponding special variable reference */
5529 					o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5530 					o_addchr(&ctx.word, SPECIAL_VAR_QUOTED_SVS);
5531 				}
5532 				o_addqchr(&ctx.word, ch);
5533 				ch = i_getch(input);
5534 			}
5535 			continue; /* get next char */
5536 		}
5537 
5538 		next = '\0';
5539 		if (ch != '\n')
5540 			next = i_peek_and_eat_bkslash_nl(input);
5541 
5542 		is_special = "{}<>&|();#" /* special outside of "str" */
5543 				"$\"" IF_HUSH_TICK("`") /* always special */
5544 				SPECIAL_VAR_SYMBOL_STR;
5545 #if defined(CMD_TEST2_SINGLEWORD_NOGLOB)
5546 		if (ctx.command->cmd_type == CMD_TEST2_SINGLEWORD_NOGLOB) {
5547 			/* In [[ ]], {}<>&|() are not special */
5548 			is_special += 8;
5549 		} else
5550 #endif
5551 		/* Are { and } special here? */
5552 		if (ctx.command->argv /* word [word]{... - non-special */
5553 		 || ctx.word.length       /* word{... - non-special */
5554 		 || ctx.word.has_quoted_part     /* ""{... - non-special */
5555 		 || (next != ';'             /* }; - special */
5556 		    && next != ')'           /* }) - special */
5557 		    && next != '('           /* {( - special */
5558 		    && next != '&'           /* }& and }&& ... - special */
5559 		    && next != '|'           /* }|| ... - special */
5560 		    && !strchr(defifs, next) /* {word - non-special */
5561 		    )
5562 		) {
5563 			/* They are not special, skip "{}" */
5564 			is_special += 2;
5565 		}
5566 		is_special = strchr(is_special, ch);
5567 		is_blank = strchr(defifs, ch);
5568 
5569 		if (!is_special && !is_blank) { /* ordinary char */
5570  ordinary_char:
5571 			o_addQchr(&ctx.word, ch);
5572 			if ((ctx.is_assignment == MAYBE_ASSIGNMENT
5573 			    || ctx.is_assignment == WORD_IS_KEYWORD)
5574 			 && ch == '='
5575 			 && endofname(ctx.word.data)[0] == '='
5576 			) {
5577 				ctx.is_assignment = DEFINITELY_ASSIGNMENT;
5578 				debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5579 			}
5580 			continue;
5581 		}
5582 
5583 		if (is_blank) {
5584 #if ENABLE_HUSH_LINENO_VAR
5585 /* Case:
5586  * "while ...; do<whitespace><newline>
5587  *	cmd ..."
5588  * would think that "cmd" starts in <whitespace> -
5589  * i.e., at the previous line.
5590  * We need to skip all whitespace before newlines.
5591  */
5592 			while (ch != '\n') {
5593 				next = i_peek(input);
5594 				if (next != ' ' && next != '\t' && next != '\n')
5595 					break; /* next char is not ws */
5596 				ch = i_getch(input);
5597 			}
5598 			/* ch == last eaten whitespace char */
5599 #endif
5600 			if (done_word(&ctx)) {
5601 				goto parse_error_exitcode1;
5602 			}
5603 			if (ch == '\n') {
5604 				/* Is this a case when newline is simply ignored?
5605 				 * Some examples:
5606 				 * "cmd | <newline> cmd ..."
5607 				 * "case ... in <newline> word) ..."
5608 				 */
5609 				if (IS_NULL_CMD(ctx.command)
5610 				 && ctx.word.length == 0
5611 				 && !ctx.word.has_quoted_part
5612 				 && heredoc_cnt == 0
5613 				) {
5614 					/* This newline can be ignored. But...
5615 					 * Without check #1, interactive shell
5616 					 * ignores even bare <newline>,
5617 					 * and shows the continuation prompt:
5618 					 * ps1_prompt$ <enter>
5619 					 * ps2> _   <=== wrong, should be ps1
5620 					 * Without check #2, "cmd & <newline>"
5621 					 * is similarly mistreated.
5622 					 * (BTW, this makes "cmd & cmd"
5623 					 * and "cmd && cmd" non-orthogonal.
5624 					 * Really, ask yourself, why
5625 					 * "cmd && <newline>" doesn't start
5626 					 * cmd but waits for more input?
5627 					 * The only reason is that it might be
5628 					 * a "cmd1 && <nl> cmd2 &" construct,
5629 					 * cmd1 may need to run in BG).
5630 					 */
5631 					struct pipe *pi = ctx.list_head;
5632 					if (pi->num_cmds != 0       /* check #1 */
5633 					 && pi->followup != PIPE_BG /* check #2 */
5634 					) {
5635 						continue;
5636 					}
5637 				}
5638 				/* Treat newline as a command separator. */
5639 				done_pipe(&ctx, PIPE_SEQ);
5640 				debug_printf_heredoc("heredoc_cnt:%d\n", heredoc_cnt);
5641 				if (heredoc_cnt) {
5642 					heredoc_cnt = fetch_heredocs(&ctx.as_string, ctx.list_head, heredoc_cnt, input);
5643 					if (heredoc_cnt != 0)
5644 						goto parse_error_exitcode1;
5645 				}
5646 				ctx.is_assignment = MAYBE_ASSIGNMENT;
5647 				debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5648 				ch = ';';
5649 				/* note: if (is_blank) continue;
5650 				 * will still trigger for us */
5651 			}
5652 		}
5653 
5654 		/* "cmd}" or "cmd }..." without semicolon or &:
5655 		 * } is an ordinary char in this case, even inside { cmd; }
5656 		 * Pathological example: { ""}; } should exec "}" cmd
5657 		 */
5658 		if (ch == '}') {
5659 			if (ctx.word.length != 0 /* word} */
5660 			 || ctx.word.has_quoted_part    /* ""} */
5661 			) {
5662 				goto ordinary_char;
5663 			}
5664 			if (!IS_NULL_CMD(ctx.command)) { /* cmd } */
5665 				/* Generally, there should be semicolon: "cmd; }"
5666 				 * However, bash allows to omit it if "cmd" is
5667 				 * a group. Examples:
5668 				 * { { echo 1; } }
5669 				 * {(echo 1)}
5670 				 * { echo 0 >&2 | { echo 1; } }
5671 				 * { while false; do :; done }
5672 				 * { case a in b) ;; esac }
5673 				 */
5674 				if (ctx.command->group)
5675 					goto term_group;
5676 				goto ordinary_char;
5677 			}
5678 			if (!IS_NULL_PIPE(ctx.pipe)) /* cmd | } */
5679 				/* Can't be an end of {cmd}, skip the check */
5680 				goto skip_end_trigger;
5681 			/* else: } does terminate a group */
5682 		}
5683  term_group:
5684 		if (end_trigger && end_trigger == ch
5685 		 && (ch != ';' || heredoc_cnt == 0)
5686 #if ENABLE_HUSH_CASE
5687 		 && (ch != ')'
5688 		    || ctx.ctx_res_w != RES_MATCH
5689 		    || (!ctx.word.has_quoted_part && strcmp(ctx.word.data, "esac") == 0)
5690 		    )
5691 #endif
5692 		) {
5693 			if (done_word(&ctx)) {
5694 				goto parse_error_exitcode1;
5695 			}
5696 			done_pipe(&ctx, PIPE_SEQ);
5697 			ctx.is_assignment = MAYBE_ASSIGNMENT;
5698 			debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5699 			/* Do we sit outside of any if's, loops or case's? */
5700 			if (!HAS_KEYWORDS
5701 			IF_HAS_KEYWORDS(|| (ctx.ctx_res_w == RES_NONE && ctx.old_flag == 0))
5702 			) {
5703 				o_free_and_set_NULL(&ctx.word);
5704 #if !BB_MMU
5705 				debug_printf_parse("as_string2 '%s'\n", ctx.as_string.data);
5706 				if (pstring)
5707 					*pstring = ctx.as_string.data;
5708 				else
5709 					o_free(&ctx.as_string);
5710 #endif
5711 				if (ch != ';' && IS_NULL_PIPE(ctx.list_head)) {
5712 					/* Example: bare "{ }", "()" */
5713 					G.last_exitcode = 2; /* bash compat */
5714 					syntax_error_unexpected_ch(ch);
5715 					goto parse_error;
5716 				}
5717 				if (heredoc_cnt_ptr)
5718 					*heredoc_cnt_ptr = heredoc_cnt;
5719 				debug_printf_heredoc("parse_stream return heredoc_cnt:%d\n", heredoc_cnt);
5720 				debug_printf_parse("parse_stream return %p: "
5721 						"end_trigger char found\n",
5722 						ctx.list_head);
5723 				debug_leave();
5724 				return ctx.list_head;
5725 			}
5726 		}
5727 
5728 		if (is_blank)
5729 			continue;
5730 
5731 		/* Catch <, > before deciding whether this word is
5732 		 * an assignment. a=1 2>z b=2: b=2 is still assignment */
5733 		switch (ch) {
5734 		case '>':
5735 			redir_fd = redirect_opt_num(&ctx.word);
5736 			if (done_word(&ctx)) {
5737 				goto parse_error_exitcode1;
5738 			}
5739 			redir_style = REDIRECT_OVERWRITE;
5740 			if (next == '>') {
5741 				redir_style = REDIRECT_APPEND;
5742 				ch = i_getch(input);
5743 				nommu_addchr(&ctx.as_string, ch);
5744 			}
5745 #if 0
5746 			else if (next == '(') {
5747 				syntax_error(">(process) not supported");
5748 				goto parse_error_exitcode1;
5749 			}
5750 #endif
5751 			if (parse_redirect(&ctx, redir_fd, redir_style, input))
5752 				goto parse_error_exitcode1;
5753 			continue; /* get next char */
5754 		case '<':
5755 			redir_fd = redirect_opt_num(&ctx.word);
5756 			if (done_word(&ctx)) {
5757 				goto parse_error_exitcode1;
5758 			}
5759 			redir_style = REDIRECT_INPUT;
5760 			if (next == '<') {
5761 				redir_style = REDIRECT_HEREDOC;
5762 				heredoc_cnt++;
5763 				debug_printf_heredoc("++heredoc_cnt=%d\n", heredoc_cnt);
5764 				ch = i_getch(input);
5765 				nommu_addchr(&ctx.as_string, ch);
5766 			} else if (next == '>') {
5767 				redir_style = REDIRECT_IO;
5768 				ch = i_getch(input);
5769 				nommu_addchr(&ctx.as_string, ch);
5770 			}
5771 #if 0
5772 			else if (next == '(') {
5773 				syntax_error("<(process) not supported");
5774 				goto parse_error_exitcode1;
5775 			}
5776 #endif
5777 			if (parse_redirect(&ctx, redir_fd, redir_style, input))
5778 				goto parse_error_exitcode1;
5779 			continue; /* get next char */
5780 		case '#':
5781 			if (ctx.word.length == 0 && !ctx.word.has_quoted_part) {
5782 				/* skip "#comment" */
5783 				/* note: we do not add it to &ctx.as_string */
5784 /* TODO: in bash:
5785  * comment inside $() goes to the next \n, even inside quoted string (!):
5786  * cmd "$(cmd2 #comment)" - syntax error
5787  * cmd "`cmd2 #comment`" - ok
5788  * We accept both (comment ends where command subst ends, in both cases).
5789  */
5790 				while (1) {
5791 					ch = i_peek(input);
5792 					if (ch == '\n') {
5793 						nommu_addchr(&ctx.as_string, '\n');
5794 						break;
5795 					}
5796 					ch = i_getch(input);
5797 					if (ch == EOF)
5798 						break;
5799 				}
5800 				continue; /* get next char */
5801 			}
5802 			break;
5803 		}
5804  skip_end_trigger:
5805 
5806 		if (ctx.is_assignment == MAYBE_ASSIGNMENT
5807 		 /* check that we are not in word in "a=1 2>word b=1": */
5808 		 && !ctx.pending_redirect
5809 		) {
5810 			/* ch is a special char and thus this word
5811 			 * cannot be an assignment */
5812 			ctx.is_assignment = NOT_ASSIGNMENT;
5813 			debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5814 		}
5815 
5816 		/* Note: nommu_addchr(&ctx.as_string, ch) is already done */
5817 
5818 		switch (ch) {
5819 		case_SPECIAL_VAR_SYMBOL:
5820 		case SPECIAL_VAR_SYMBOL:
5821 			/* Convert raw ^C to corresponding special variable reference */
5822 			o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5823 			o_addchr(&ctx.word, SPECIAL_VAR_QUOTED_SVS);
5824 			/* fall through */
5825 		case '#':
5826 			/* non-comment #: "echo a#b" etc */
5827 			o_addchr(&ctx.word, ch);
5828 			continue; /* get next char */
5829 		case '$':
5830 			if (parse_dollar_squote(&ctx.as_string, &ctx.word, input))
5831 				continue; /* get next char */
5832 			if (!parse_dollar(&ctx.as_string, &ctx.word, input, /*quote_mask:*/ 0)) {
5833 				debug_printf_parse("parse_stream parse error: "
5834 					"parse_dollar returned 0 (error)\n");
5835 				goto parse_error_exitcode1;
5836 			}
5837 			continue; /* get next char */
5838 		case '"':
5839 			ctx.word.has_quoted_part = 1;
5840 			if (next == '"' && !ctx.pending_redirect) {
5841 				i_getch(input); /* eat second " */
5842  insert_empty_quoted_str_marker:
5843 				nommu_addchr(&ctx.as_string, next);
5844 				o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5845 				o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5846 				continue; /* get next char */
5847 			}
5848 			if (ctx.is_assignment == NOT_ASSIGNMENT)
5849 				ctx.word.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS;
5850 			if (!encode_string(&ctx.as_string, &ctx.word, input, '"'))
5851 				goto parse_error_exitcode1;
5852 			ctx.word.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS;
5853 			continue; /* get next char */
5854 #if ENABLE_HUSH_TICK
5855 		case '`': {
5856 			USE_FOR_NOMMU(unsigned pos;)
5857 
5858 			o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5859 			o_addchr(&ctx.word, '`');
5860 			USE_FOR_NOMMU(pos = ctx.word.length;)
5861 			if (!add_till_backquote(&ctx.word, input, /*in_dquote:*/ 0))
5862 				goto parse_error_exitcode1;
5863 # if !BB_MMU
5864 			o_addstr(&ctx.as_string, ctx.word.data + pos);
5865 			o_addchr(&ctx.as_string, '`');
5866 # endif
5867 			o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5868 			//debug_printf_subst("SUBST RES3 '%s'\n", ctx.word.data + pos);
5869 			continue; /* get next char */
5870 		}
5871 #endif
5872 		case ';':
5873 #if ENABLE_HUSH_CASE
5874  case_semi:
5875 #endif
5876 			if (done_word(&ctx)) {
5877 				goto parse_error_exitcode1;
5878 			}
5879 			done_pipe(&ctx, PIPE_SEQ);
5880 #if ENABLE_HUSH_CASE
5881 			/* Eat multiple semicolons, detect
5882 			 * whether it means something special */
5883 			while (1) {
5884 				ch = i_peek_and_eat_bkslash_nl(input);
5885 				if (ch != ';')
5886 					break;
5887 				ch = i_getch(input);
5888 				nommu_addchr(&ctx.as_string, ch);
5889 				if (ctx.ctx_res_w == RES_CASE_BODY) {
5890 					ctx.ctx_dsemicolon = 1;
5891 					ctx.ctx_res_w = RES_MATCH;
5892 					break;
5893 				}
5894 			}
5895 #endif
5896  new_cmd:
5897 			/* We just finished a cmd. New one may start
5898 			 * with an assignment */
5899 			ctx.is_assignment = MAYBE_ASSIGNMENT;
5900 			debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5901 			continue; /* get next char */
5902 		case '&':
5903 			if (done_word(&ctx)) {
5904 				goto parse_error_exitcode1;
5905 			}
5906 			if (next == '&') {
5907 				ch = i_getch(input);
5908 				nommu_addchr(&ctx.as_string, ch);
5909 				done_pipe(&ctx, PIPE_AND);
5910 			} else {
5911 				done_pipe(&ctx, PIPE_BG);
5912 			}
5913 			goto new_cmd;
5914 		case '|':
5915 			if (done_word(&ctx)) {
5916 				goto parse_error_exitcode1;
5917 			}
5918 #if ENABLE_HUSH_CASE
5919 			if (ctx.ctx_res_w == RES_MATCH)
5920 				break; /* we are in case's "word | word)" */
5921 #endif
5922 			if (next == '|') { /* || */
5923 				ch = i_getch(input);
5924 				nommu_addchr(&ctx.as_string, ch);
5925 				done_pipe(&ctx, PIPE_OR);
5926 			} else {
5927 				/* we could pick up a file descriptor choice here
5928 				 * with redirect_opt_num(), but bash doesn't do it.
5929 				 * "echo foo 2| cat" yields "foo 2". */
5930 				done_command(&ctx);
5931 			}
5932 			goto new_cmd;
5933 		case '(':
5934 #if ENABLE_HUSH_CASE
5935 			/* "case... in [(]word)..." - skip '(' */
5936 			if (ctx.ctx_res_w == RES_MATCH
5937 			 && ctx.command->argv == NULL /* not (word|(... */
5938 			 && ctx.word.length == 0 /* not word(... */
5939 			 && ctx.word.has_quoted_part == 0 /* not ""(... */
5940 			) {
5941 				continue; /* get next char */
5942 			}
5943 #endif
5944 			/* fall through */
5945 		case '{': {
5946 			int n = parse_group(&ctx, input, ch);
5947 			if (n < 0) {
5948 				goto parse_error_exitcode1;
5949 			}
5950 			debug_printf_heredoc("parse_group done, needs heredocs:%d\n", n);
5951 			heredoc_cnt += n;
5952 			goto new_cmd;
5953 		}
5954 		case ')':
5955 #if ENABLE_HUSH_CASE
5956 			if (ctx.ctx_res_w == RES_MATCH)
5957 				goto case_semi;
5958 #endif
5959 		case '}':
5960 			/* proper use of this character is caught by end_trigger:
5961 			 * if we see {, we call parse_group(..., end_trigger='}')
5962 			 * and it will match } earlier (not here). */
5963 			G.last_exitcode = 2;
5964 			syntax_error_unexpected_ch(ch);
5965 			goto parse_error;
5966 		default:
5967 			if (HUSH_DEBUG)
5968 				bb_error_msg_and_die("BUG: unexpected %c", ch);
5969 		}
5970 	} /* while (1) */
5971 
5972  parse_error_exitcode1:
5973 	G.last_exitcode = 1;
5974  parse_error:
5975 	{
5976 		struct parse_context *pctx;
5977 		IF_HAS_KEYWORDS(struct parse_context *p2;)
5978 
5979 		/* Clean up allocated tree.
5980 		 * Sample for finding leaks on syntax error recovery path.
5981 		 * Run it from interactive shell, watch pmap `pidof hush`.
5982 		 * while if false; then false; fi; do break; fi
5983 		 * Samples to catch leaks at execution:
5984 		 * while if (true | { true;}); then echo ok; fi; do break; done
5985 		 * while if (true | { true;}); then echo ok; fi; do (if echo ok; break; then :; fi) | cat; break; done
5986 		 */
5987 		pctx = &ctx;
5988 		do {
5989 			/* Update pipe/command counts,
5990 			 * otherwise freeing may miss some */
5991 			done_pipe(pctx, PIPE_SEQ);
5992 			debug_printf_clean("freeing list %p from ctx %p\n",
5993 					pctx->list_head, pctx);
5994 			debug_print_tree(pctx->list_head, 0);
5995 			free_pipe_list(pctx->list_head);
5996 			debug_printf_clean("freed list %p\n", pctx->list_head);
5997 #if !BB_MMU
5998 			o_free(&pctx->as_string);
5999 #endif
6000 			IF_HAS_KEYWORDS(p2 = pctx->stack;)
6001 			if (pctx != &ctx) {
6002 				free(pctx);
6003 			}
6004 			IF_HAS_KEYWORDS(pctx = p2;)
6005 		} while (HAS_KEYWORDS && pctx);
6006 
6007 		o_free(&ctx.word);
6008 #if !BB_MMU
6009 		if (pstring)
6010 			*pstring = NULL;
6011 #endif
6012 		debug_leave();
6013 		return ERR_PTR;
6014 	}
6015 }
6016 
6017 
6018 /*** Execution routines ***/
6019 
6020 /* Expansion can recurse, need forward decls: */
6021 #if !BASH_PATTERN_SUBST && !ENABLE_HUSH_CASE
6022 #define expand_string_to_string(str, EXP_flags, do_unbackslash) \
6023 	expand_string_to_string(str)
6024 #endif
6025 static char *expand_string_to_string(const char *str, int EXP_flags, int do_unbackslash);
6026 #if ENABLE_HUSH_TICK
6027 static int process_command_subs(o_string *dest, const char *s);
6028 #endif
6029 static int expand_vars_to_list(o_string *output, int n, char *arg);
6030 
6031 /* expand_strvec_to_strvec() takes a list of strings, expands
6032  * all variable references within and returns a pointer to
6033  * a list of expanded strings, possibly with larger number
6034  * of strings. (Think VAR="a b"; echo $VAR).
6035  * This new list is allocated as a single malloc block.
6036  * NULL-terminated list of char* pointers is at the beginning of it,
6037  * followed by strings themselves.
6038  * Caller can deallocate entire list by single free(list). */
6039 
6040 /* A horde of its helpers come first: */
6041 
o_addblock_duplicate_backslash(o_string * o,const char * str,int len)6042 static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len)
6043 {
6044 	while (--len >= 0) {
6045 		char c = *str++;
6046 
6047 #if ENABLE_HUSH_BRACE_EXPANSION
6048 		if (c == '{' || c == '}') {
6049 			/* { -> \{, } -> \} */
6050 			o_addchr(o, '\\');
6051 			/* And now we want to add { or } and continue:
6052 			 *  o_addchr(o, c);
6053 			 *  continue;
6054 			 * luckily, just falling through achieves this.
6055 			 */
6056 		}
6057 #endif
6058 		o_addchr(o, c);
6059 		if (c == '\\') {
6060 			/* \z -> \\\z; \<eol> -> \\<eol> */
6061 			o_addchr(o, '\\');
6062 			if (len) {
6063 				len--;
6064 				o_addchr(o, '\\');
6065 				o_addchr(o, *str++);
6066 			}
6067 		}
6068 	}
6069 }
6070 
6071 /* Store given string, finalizing the word and starting new one whenever
6072  * we encounter IFS char(s). This is used for expanding variable values.
6073  * End-of-string does NOT finalize word: think about 'echo -$VAR-'.
6074  * Return in output->ended_in_ifs:
6075  * 1 - ended with IFS char, else 0 (this includes case of empty str).
6076  */
expand_on_ifs(o_string * output,int n,const char * str)6077 static int expand_on_ifs(o_string *output, int n, const char *str)
6078 {
6079 	int last_is_ifs = 0;
6080 
6081 	while (1) {
6082 		int word_len;
6083 
6084 		if (!*str)  /* EOL - do not finalize word */
6085 			break;
6086 		word_len = strcspn(str, G.ifs);
6087 		if (word_len) {
6088 			/* We have WORD_LEN leading non-IFS chars */
6089 			if (!(output->o_expflags & EXP_FLAG_GLOB)) {
6090 				o_addblock(output, str, word_len);
6091 			} else {
6092 				/* Protect backslashes against globbing up :)
6093 				 * Example: "v='\*'; echo b$v" prints "b\*"
6094 				 * (and does not try to glob on "*")
6095 				 */
6096 				o_addblock_duplicate_backslash(output, str, word_len);
6097 				/*/ Why can't we do it easier? */
6098 				/*o_addblock(output, str, word_len); - WRONG: "v='\*'; echo Z$v" prints "Z*" instead of "Z\*" */
6099 				/*o_addqblock(output, str, word_len); - WRONG: "v='*'; echo Z$v" prints "Z*" instead of Z* files */
6100 			}
6101 			last_is_ifs = 0;
6102 			str += word_len;
6103 			if (!*str)  /* EOL - do not finalize word */
6104 				break;
6105 		}
6106 
6107 		/* We know str here points to at least one IFS char */
6108 		last_is_ifs = 1;
6109 		str += strspn(str, G.ifs_whitespace); /* skip IFS whitespace chars */
6110 		if (!*str)  /* EOL - do not finalize word */
6111 			break;
6112 
6113 		if (G.ifs_whitespace != G.ifs /* usually false ($IFS is usually all whitespace), */
6114 		 && strchr(G.ifs, *str)       /* the second check would fail */
6115 		) {
6116 			/* This is a non-whitespace $IFS char */
6117 			/* Skip it and IFS whitespace chars, start new word */
6118 			str++;
6119 			str += strspn(str, G.ifs_whitespace);
6120 			goto new_word;
6121 		}
6122 
6123 		/* Start new word... but not always! */
6124 		/* Case "v=' a'; echo ''$v": we do need to finalize empty word: */
6125 		if (output->has_quoted_part
6126 		/*
6127 		 * Case "v=' a'; echo $v":
6128 		 * here nothing precedes the space in $v expansion,
6129 		 * therefore we should not finish the word
6130 		 * (IOW: if there *is* word to finalize, only then do it):
6131 		 * It's okay if this accesses the byte before first argv[]:
6132 		 * past call to o_save_ptr() cleared it to zero byte
6133 		 * (grep for -prev-ifs-check-).
6134 		 */
6135 		 || output->data[output->length - 1]
6136 		) {
6137  new_word:
6138 			o_addchr(output, '\0');
6139 			debug_print_list("expand_on_ifs", output, n);
6140 			n = o_save_ptr(output, n);
6141 		}
6142 	}
6143 
6144 	output->ended_in_ifs = last_is_ifs;
6145 	debug_print_list("expand_on_ifs[1]", output, n);
6146 	return n;
6147 }
6148 
6149 /* Helper to expand $((...)) and heredoc body. These act as if
6150  * they are in double quotes, with the exception that they are not :).
6151  * Just the rules are similar: "expand only $var and `cmd`"
6152  *
6153  * Returns malloced string.
6154  * As an optimization, we return NULL if expansion is not needed.
6155  */
encode_then_expand_string(const char * str)6156 static char *encode_then_expand_string(const char *str)
6157 {
6158 	char *exp_str;
6159 	struct in_str input;
6160 	o_string dest = NULL_O_STRING;
6161 	const char *cp;
6162 
6163 	cp = str;
6164 	for (;;) {
6165 		if (!*cp) return NULL; /* string has no special chars */
6166 		if (*cp == '$') break;
6167 		if (*cp == '\\') break;
6168 #if ENABLE_HUSH_TICK
6169 		if (*cp == '`') break;
6170 #endif
6171 		cp++;
6172 	}
6173 
6174 	/* We need to expand. Example:
6175 	 * echo $(($a + `echo 1`)) $((1 + $((2)) ))
6176 	 */
6177 	setup_string_in_str(&input, str);
6178 	encode_string(NULL, &dest, &input, EOF);
6179 //TODO: error check (encode_string returns 0 on error)?
6180 	//bb_error_msg("'%s' -> '%s'", str, dest.data);
6181 	exp_str = expand_string_to_string(dest.data,
6182 			EXP_FLAG_ESC_GLOB_CHARS,
6183 			/*unbackslash:*/ 1
6184 	);
6185 	//bb_error_msg("'%s' -> '%s'", dest.data, exp_str);
6186 	o_free(&dest);
6187 	return exp_str;
6188 }
6189 
first_special_char_in_vararg(const char * cp)6190 static const char *first_special_char_in_vararg(const char *cp)
6191 {
6192 	for (;;) {
6193 		if (!*cp) return NULL; /* string has no special chars */
6194 		if (*cp == '$') return cp;
6195 		if (*cp == '\\') return cp;
6196 		if (*cp == '\'') return cp;
6197 		if (*cp == '"') return cp;
6198 #if ENABLE_HUSH_TICK
6199 		if (*cp == '`') return cp;
6200 #endif
6201 		/* dquoted "${x:+ARG}" should not glob, therefore
6202 		 * '*' et al require some non-literal processing: */
6203 		if (*cp == '*') return cp;
6204 		if (*cp == '?') return cp;
6205 		if (*cp == '[') return cp;
6206 		cp++;
6207 	}
6208 }
6209 
6210 /* Expanding ARG in ${var#ARG}, ${var%ARG}, or ${var/ARG/ARG}.
6211  * These can contain single- and double-quoted strings,
6212  * and treated as if the ARG string is initially unquoted. IOW:
6213  * ${var#ARG} and "${var#ARG}" treat ARG the same (ARG can even be
6214  * a dquoted string: "${var#"zz"}"), the difference only comes later
6215  * (word splitting and globbing of the ${var...} result).
6216  */
6217 #if !BASH_PATTERN_SUBST
6218 #define encode_then_expand_vararg(str, handle_squotes, do_unbackslash) \
6219 	encode_then_expand_vararg(str, handle_squotes)
6220 #endif
encode_then_expand_vararg(const char * str,int handle_squotes,int do_unbackslash)6221 static char *encode_then_expand_vararg(const char *str, int handle_squotes, int do_unbackslash)
6222 {
6223 #if !BASH_PATTERN_SUBST && ENABLE_HUSH_CASE
6224 	const int do_unbackslash = 0;
6225 #endif
6226 	char *exp_str;
6227 	struct in_str input;
6228 	o_string dest = NULL_O_STRING;
6229 
6230 	if (!first_special_char_in_vararg(str)) {
6231 		/* string has no special chars */
6232 		return NULL;
6233 	}
6234 
6235 	setup_string_in_str(&input, str);
6236 	dest.data = xzalloc(1); /* start as "", not as NULL */
6237 	exp_str = NULL;
6238 
6239 	for (;;) {
6240 		int ch;
6241 
6242 		ch = i_getch(&input);
6243 		debug_printf_parse("%s: ch=%c (%d) escape=%d\n",
6244 				__func__, ch, ch, !!dest.o_expflags);
6245 
6246 		if (!dest.o_expflags) {
6247 			if (ch == EOF)
6248 				break;
6249 			if (handle_squotes && ch == '\'') {
6250 				if (!add_till_single_quote_dquoted(&dest, &input))
6251 					goto ret; /* error */
6252 				continue;
6253 			}
6254 		}
6255 		if (ch == EOF) {
6256 			syntax_error_unterm_ch('"');
6257 			goto ret; /* error */
6258 		}
6259 		if (ch == '"') {
6260 			dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS;
6261 			continue;
6262 		}
6263 		if (ch == '\\') {
6264 			ch = i_getch(&input);
6265 			if (ch == EOF) {
6266 //example? error message?	syntax_error_unterm_ch('"');
6267 				debug_printf_parse("%s: error: \\<eof>\n", __func__);
6268 				goto ret;
6269 			}
6270 			o_addqchr(&dest, ch);
6271 			continue;
6272 		}
6273 		if (ch == '$') {
6274 			if (parse_dollar_squote(NULL, &dest, &input))
6275 				continue;
6276 			if (!parse_dollar(NULL, &dest, &input, /*quote_mask:*/ 0x80)) {
6277 				debug_printf_parse("%s: error: parse_dollar returned 0 (error)\n", __func__);
6278 				goto ret;
6279 			}
6280 			continue;
6281 		}
6282 #if ENABLE_HUSH_TICK
6283 		if (ch == '`') {
6284 			//unsigned pos = dest->length;
6285 			o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6286 			o_addchr(&dest, 0x80 | '`');
6287 			if (!add_till_backquote(&dest, &input,
6288 					/*in_dquote:*/ dest.o_expflags /* nonzero if EXP_FLAG_ESC_GLOB_CHARS set */
6289 				)
6290 			) {
6291 				goto ret; /* error */
6292 			}
6293 			o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6294 			//debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
6295 			continue;
6296 		}
6297 #endif
6298 		o_addQchr(&dest, ch);
6299 	} /* for (;;) */
6300 
6301 	debug_printf_parse("encode: '%s' -> '%s'\n", str, dest.data);
6302 	exp_str = expand_string_to_string(dest.data,
6303 			do_unbackslash ? EXP_FLAG_ESC_GLOB_CHARS : 0,
6304 			do_unbackslash
6305 	);
6306  ret:
6307 	debug_printf_parse("expand: '%s' -> '%s'\n", dest.data, exp_str);
6308 	o_free(&dest);
6309 	return exp_str;
6310 }
6311 
6312 /* Expanding ARG in ${var+ARG}, ${var-ARG}
6313  */
encode_then_append_var_plusminus(o_string * output,int n,char * str,int dquoted)6314 static NOINLINE int encode_then_append_var_plusminus(o_string *output, int n,
6315 		char *str, int dquoted)
6316 {
6317 	struct in_str input;
6318 	o_string dest = NULL_O_STRING;
6319 
6320 	if (!first_special_char_in_vararg(str)
6321 	 && '\0' == str[strcspn(str, G.ifs)]
6322 	) {
6323 		/* string has no special chars
6324 		 * && string has no $IFS chars
6325 		 */
6326 		if (dquoted) {
6327 			/* Prints 1 (quoted expansion is a "" word, not nothing):
6328 			 * set -- "${notexist-}"; echo $#
6329 			 */
6330 			output->has_quoted_part = 1;
6331 		}
6332 		return expand_vars_to_list(output, n, str);
6333 	}
6334 
6335 	setup_string_in_str(&input, str);
6336 
6337 	for (;;) {
6338 		int ch;
6339 
6340 		ch = i_getch(&input);
6341 		debug_printf_parse("%s: ch=%c (%d) escape=%x\n",
6342 				__func__, ch, ch, dest.o_expflags);
6343 
6344 		if (!dest.o_expflags) {
6345 			if (ch == EOF)
6346 				break;
6347 			if (!dquoted && strchr(G.ifs, ch)) {
6348 				/* PREFIX${x:d${e}f ...} and we met space: expand "d${e}f" and start new word.
6349 				 * do not assume we are at the start of the word (PREFIX above).
6350 				 */
6351 				if (dest.data) {
6352 					n = expand_vars_to_list(output, n, dest.data);
6353 					o_free_and_set_NULL(&dest);
6354 					o_addchr(output, '\0');
6355 					n = o_save_ptr(output, n); /* create next word */
6356 				} else
6357 				if (output->length != o_get_last_ptr(output, n)
6358 				 || output->has_quoted_part
6359 				) {
6360 					/* For these cases:
6361 					 * f() { for i; do echo "|$i|"; done; }; x=x
6362 					 * f a${x:+ }b  # 1st condition
6363 					 * |a|
6364 					 * |b|
6365 					 * f ""${x:+ }b  # 2nd condition
6366 					 * ||
6367 					 * |b|
6368 					 */
6369 					o_addchr(output, '\0');
6370 					n = o_save_ptr(output, n); /* create next word */
6371 				}
6372 				continue;
6373 			}
6374 			if (!dquoted && ch == '\'') {
6375 				if (!add_till_single_quote_dquoted(&dest, &input))
6376 					goto ret; /* error */
6377 				o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6378 				o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6379 				continue;
6380 			}
6381 		}
6382 		if (ch == EOF) {
6383 			syntax_error_unterm_ch('"');
6384 			goto ret; /* error */
6385 		}
6386 		if (ch == '"') {
6387 			dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS;
6388 			if (dest.o_expflags) {
6389 				o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6390 				o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6391 			}
6392 			continue;
6393 		}
6394 		if (ch == '\\') {
6395 			ch = i_getch(&input);
6396 			if (ch == EOF) {
6397 //example? error message?	syntax_error_unterm_ch('"');
6398 				debug_printf_parse("%s: error: \\<eof>\n", __func__);
6399 				goto ret;
6400 			}
6401 			o_addqchr(&dest, ch);
6402 			continue;
6403 		}
6404 		if (ch == '$') {
6405 			if (!parse_dollar(NULL, &dest, &input, /*quote_mask:*/ (dest.o_expflags || dquoted) ? 0x80 : 0)) {
6406 				debug_printf_parse("%s: error: parse_dollar returned 0 (error)\n", __func__);
6407 				goto ret;
6408 			}
6409 			continue;
6410 		}
6411 #if ENABLE_HUSH_TICK
6412 		if (ch == '`') {
6413 			//unsigned pos = dest->length;
6414 			o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6415 			o_addchr(&dest, (dest.o_expflags || dquoted) ? 0x80 | '`' : '`');
6416 			if (!add_till_backquote(&dest, &input,
6417 					/*in_dquote:*/ dest.o_expflags /* nonzero if EXP_FLAG_ESC_GLOB_CHARS set */
6418 				)
6419 			) {
6420 				goto ret; /* error */
6421 			}
6422 			o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6423 			//debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
6424 			continue;
6425 		}
6426 #endif
6427 		if (dquoted) {
6428 			/* Always glob-protect if in dquotes:
6429 			 * x=x; echo "${x:+/bin/c*}" - prints: /bin/c*
6430 			 * x=x; echo "${x:+"/bin/c*"}" - prints: /bin/c*
6431 			 */
6432 			o_addqchr(&dest, ch);
6433 		} else {
6434 			/* Glob-protect only if char is quoted:
6435 			 * x=x; echo ${x:+/bin/c*} - prints many filenames
6436 			 * x=x; echo ${x:+"/bin/c*"} - prints: /bin/c*
6437 			 */
6438 			o_addQchr(&dest, ch);
6439 		}
6440 	} /* for (;;) */
6441 
6442 	if (dest.data) {
6443 		n = expand_vars_to_list(output, n, dest.data);
6444 	}
6445  ret:
6446 	o_free(&dest);
6447 	return n;
6448 }
6449 
6450 #if ENABLE_FEATURE_SH_MATH
expand_and_evaluate_arith(const char * arg,const char ** errmsg_p)6451 static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p)
6452 {
6453 	arith_state_t math_state;
6454 	arith_t res;
6455 	char *exp_str;
6456 
6457 	math_state.lookupvar = get_local_var_value;
6458 	math_state.setvar = set_local_var_from_halves;
6459 	//math_state.endofname = endofname;
6460 	exp_str = encode_then_expand_string(arg);
6461 	res = arith(&math_state, exp_str ? exp_str : arg);
6462 	free(exp_str);
6463 	if (errmsg_p)
6464 		*errmsg_p = math_state.errmsg;
6465 	if (math_state.errmsg)
6466 		msg_and_die_if_script(math_state.errmsg);
6467 	return res;
6468 }
6469 #endif
6470 
6471 #if BASH_PATTERN_SUBST
6472 /* ${var/[/]pattern[/repl]} helpers */
strstr_pattern(char * val,const char * pattern,int * size)6473 static char *strstr_pattern(char *val, const char *pattern, int *size)
6474 {
6475 	int first_escaped = (pattern[0] == '\\' && pattern[1]);
6476 	/* "first_escaped" trick allows to treat e.g. "\*no_glob_chars"
6477 	 * as literal too (as it is semi-common, and easy to accomodate
6478 	 * by just using str + 1).
6479 	 */
6480 	int sz = strcspn(pattern + first_escaped * 2, "*?[\\");
6481 	if ((pattern + first_escaped * 2)[sz] == '\0') {
6482 		/* Optimization for trivial patterns.
6483 		 * Testcase for very slow replace (performs about 22k replaces):
6484 		 * x=::::::::::::::::::::::
6485 		 * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x}
6486 		 * echo "${x//:/|}"
6487 		 */
6488 		*size = sz + first_escaped;
6489 		return strstr(val, pattern + first_escaped);
6490 	}
6491 
6492 	while (1) {
6493 		char *end = scan_and_match(val, pattern, SCAN_MOVE_FROM_RIGHT + SCAN_MATCH_LEFT_HALF);
6494 		debug_printf_varexp("val:'%s' pattern:'%s' end:'%s'\n", val, pattern, end);
6495 		if (end) {
6496 			*size = end - val;
6497 			return val;
6498 		}
6499 		if (*val == '\0')
6500 			return NULL;
6501 		/* Optimization: if "*pat" did not match the start of "string",
6502 		 * we know that "tring", "ring" etc will not match too:
6503 		 */
6504 		if (pattern[0] == '*')
6505 			return NULL;
6506 		val++;
6507 	}
6508 }
replace_pattern(char * val,const char * pattern,const char * repl,char exp_op)6509 static char *replace_pattern(char *val, const char *pattern, const char *repl, char exp_op)
6510 {
6511 	char *result = NULL;
6512 	unsigned res_len = 0;
6513 	unsigned repl_len = strlen(repl);
6514 
6515 	/* Null pattern never matches, including if "var" is empty */
6516 	if (!pattern[0])
6517 		return result; /* NULL, no replaces happened */
6518 
6519 	while (1) {
6520 		int size;
6521 		char *s = strstr_pattern(val, pattern, &size);
6522 		if (!s)
6523 			break;
6524 
6525 		result = xrealloc(result, res_len + (s - val) + repl_len + 1);
6526 		strcpy(mempcpy(result + res_len, val, s - val), repl);
6527 		res_len += (s - val) + repl_len;
6528 		debug_printf_varexp("val:'%s' s:'%s' result:'%s'\n", val, s, result);
6529 
6530 		val = s + size;
6531 		if (exp_op == '/')
6532 			break;
6533 	}
6534 	if (*val && result) {
6535 		result = xrealloc(result, res_len + strlen(val) + 1);
6536 		strcpy(result + res_len, val);
6537 		debug_printf_varexp("val:'%s' result:'%s'\n", val, result);
6538 	}
6539 	debug_printf_varexp("result:'%s'\n", result);
6540 	return result;
6541 }
6542 #endif /* BASH_PATTERN_SUBST */
6543 
append_str_maybe_ifs_split(o_string * output,int n,int first_ch,const char * val)6544 static int append_str_maybe_ifs_split(o_string *output, int n,
6545 		int first_ch, const char *val)
6546 {
6547 	if (!(first_ch & 0x80)) { /* unquoted $VAR */
6548 		debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val,
6549 				!!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
6550 		if (val && val[0])
6551 			n = expand_on_ifs(output, n, val);
6552 	} else { /* quoted "$VAR" */
6553 		output->has_quoted_part = 1;
6554 		debug_printf_expand("quoted '%s', output->o_escape:%d\n", val,
6555 				!!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
6556 		if (val && val[0])
6557 			o_addQstr(output, val);
6558 	}
6559 	return n;
6560 }
6561 
6562 /* Handle <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct.
6563  */
expand_one_var(o_string * output,int n,int first_ch,char * arg,char ** pp)6564 static NOINLINE int expand_one_var(o_string *output, int n,
6565 		int first_ch, char *arg, char **pp)
6566 {
6567 	const char *val;
6568 	char *to_be_freed;
6569 	char *p;
6570 	char *var;
6571 	char exp_op;
6572 	char exp_save = exp_save; /* for compiler */
6573 	char *exp_saveptr; /* points to expansion operator */
6574 	char *exp_word = exp_word; /* for compiler */
6575 	char arg0;
6576 
6577 	val = NULL;
6578 	to_be_freed = NULL;
6579 	p = *pp;
6580 	*p = '\0'; /* replace trailing SPECIAL_VAR_SYMBOL */
6581 	var = arg;
6582 	exp_saveptr = arg[1] ? strchr(VAR_ENCODED_SUBST_OPS, arg[1]) : NULL;
6583 	arg0 = arg[0];
6584 	arg[0] = (arg0 & 0x7f);
6585 	exp_op = 0;
6586 
6587 	if (arg[0] == '#' && arg[1] /* ${#...} but not ${#} */
6588 	 && (!exp_saveptr               /* and ( not(${#<op_char>...}) */
6589 	    || (arg[2] == '\0' && strchr(SPECIAL_VARS_STR, arg[1])) /* or ${#C} "len of $C" ) */
6590 	    )		/* NB: skipping ^^^specvar check mishandles ${#::2} */
6591 	) {
6592 		/* It must be length operator: ${#var} */
6593 		var++;
6594 		exp_op = 'L';
6595 	} else {
6596 		/* Maybe handle parameter expansion */
6597 		if (exp_saveptr /* if 2nd char is one of expansion operators */
6598 		 && strchr(NUMERIC_SPECVARS_STR, arg[0]) /* 1st char is special variable */
6599 		) {
6600 			/* ${?:0}, ${#[:]%0} etc */
6601 			exp_saveptr = var + 1;
6602 		} else {
6603 			/* ${?}, ${var}, ${var:0}, ${var[:]%0} etc */
6604 			exp_saveptr = var+1 + strcspn(var+1, VAR_ENCODED_SUBST_OPS);
6605 		}
6606 		exp_op = exp_save = *exp_saveptr;
6607 		if (exp_op) {
6608 			exp_word = exp_saveptr + 1;
6609 			if (exp_op == ':') {
6610 				exp_op = *exp_word++;
6611 //TODO: try ${var:} and ${var:bogus} in non-bash config
6612 				if (BASH_SUBSTR
6613 				 && (!exp_op || !strchr(MINUS_PLUS_EQUAL_QUESTION, exp_op))
6614 				) {
6615 					/* oops... it's ${var:N[:M]}, not ${var:?xxx} or some such */
6616 					exp_op = ':';
6617 					exp_word--;
6618 				}
6619 			}
6620 			*exp_saveptr = '\0';
6621 		} /* else: it's not an expansion op, but bare ${var} */
6622 	}
6623 
6624 	/* Look up the variable in question */
6625 	if (isdigit(var[0])) {
6626 		/* parse_dollar should have vetted var for us */
6627 		int nn = xatoi_positive(var);
6628 		if (nn < G.global_argc)
6629 			val = G.global_argv[nn];
6630 		/* else val remains NULL: $N with too big N */
6631 	} else {
6632 		switch (var[0]) {
6633 		case '$': /* pid */
6634 			val = utoa(G.root_pid);
6635 			break;
6636 		case '!': /* bg pid */
6637 			val = G.last_bg_pid ? utoa(G.last_bg_pid) : "";
6638 			break;
6639 		case '?': /* exitcode */
6640 			val = utoa(G.last_exitcode);
6641 			break;
6642 		case '#': /* argc */
6643 			val = utoa(G.global_argc ? G.global_argc-1 : 0);
6644 			break;
6645 		case '-': { /* active options */
6646 			/* Check set_mode() to see what option chars we support */
6647 			char *cp;
6648 			val = cp = G.optstring_buf;
6649 			if (G.o_opt[OPT_O_ERREXIT])
6650 				*cp++ = 'e';
6651 			if (G_interactive_fd)
6652 				*cp++ = 'i';
6653 			if (G_x_mode)
6654 				*cp++ = 'x';
6655 			/* If G.o_opt[OPT_O_NOEXEC] is true,
6656 			 * commands read but are not executed,
6657 			 * so $- can not execute too, 'n' is never seen in $-.
6658 			 */
6659 			if (G.opt_c)
6660 				*cp++ = 'c';
6661 			if (G.opt_s)
6662 				*cp++ = 's';
6663 			*cp = '\0';
6664 			break;
6665 		}
6666 		default:
6667 			val = get_local_var_value(var);
6668 		}
6669 	}
6670 
6671 	/* Handle any expansions */
6672 	if (exp_op == 'L') {
6673 		reinit_unicode_for_hush();
6674 		debug_printf_expand("expand: length(%s)=", val);
6675 		val = utoa(val ? unicode_strlen(val) : 0);
6676 		debug_printf_expand("%s\n", val);
6677 	} else if (exp_op) {
6678 		if (exp_op == '%' || exp_op == '#') {
6679 			/* Standard-mandated substring removal ops:
6680 			 * ${parameter%word} - remove smallest suffix pattern
6681 			 * ${parameter%%word} - remove largest suffix pattern
6682 			 * ${parameter#word} - remove smallest prefix pattern
6683 			 * ${parameter##word} - remove largest prefix pattern
6684 			 *
6685 			 * Word is expanded to produce a glob pattern.
6686 			 * Then var's value is matched to it and matching part removed.
6687 			 */
6688 			/* bash compat: if x is "" and no shrinking of it is possible,
6689 			 * inner ${...} is not evaluated. Example:
6690 			 *  unset b; : ${a%${b=B}}; echo $b
6691 			 * assignment b=B only happens if $a is not "".
6692 			 */
6693 			if (val && val[0]) {
6694 				char *t;
6695 				char *exp_exp_word;
6696 				char *loc;
6697 				unsigned scan_flags = pick_scan(exp_op, *exp_word);
6698 				if (exp_op == *exp_word)  /* ## or %% */
6699 					exp_word++;
6700 				debug_printf_expand("expand: exp_word:'%s'\n", exp_word);
6701 				exp_exp_word = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ 1, /*unbackslash:*/ 0);
6702 				if (exp_exp_word)
6703 					exp_word = exp_exp_word;
6704 				debug_printf_expand("expand: exp_word:'%s'\n", exp_word);
6705 				/*
6706 				 * HACK ALERT. We depend here on the fact that
6707 				 * G.global_argv and results of utoa and get_local_var_value
6708 				 * are actually in writable memory:
6709 				 * scan_and_match momentarily stores NULs there.
6710 				 */
6711 				t = (char*)val;
6712 				loc = scan_and_match(t, exp_word, scan_flags);
6713 				debug_printf_expand("op:%c str:'%s' pat:'%s' res:'%s'\n", exp_op, t, exp_word, loc);
6714 				free(exp_exp_word);
6715 				if (loc) { /* match was found */
6716 					if (scan_flags & SCAN_MATCH_LEFT_HALF) /* #[#] */
6717 						val = loc; /* take right part */
6718 					else /* %[%] */
6719 						val = to_be_freed = xstrndup(val, loc - val); /* left */
6720 				}
6721 			}
6722 		}
6723 #if BASH_PATTERN_SUBST
6724 		else if (exp_op == '/' || exp_op == '\\') {
6725 			/* It's ${var/[/]pattern[/repl]} thing.
6726 			 * Note that in encoded form it has TWO parts:
6727 			 * var/pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL>
6728 			 * and if // is used, it is encoded as \:
6729 			 * var\pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL>
6730 			 */
6731 			/* bash compat: if var is "", both pattern and repl
6732 			 * are still evaluated, if it is unset, then not:
6733 			 * unset b; a=; : ${a/z/${b=3}}; echo $b      # b=3
6734 			 * unset b; unset a; : ${a/z/${b=3}}; echo $b # b not set
6735 			 */
6736 			if (val /*&& val[0]*/) {
6737 				/* pattern uses non-standard expansion.
6738 				 * repl should be unbackslashed and globbed
6739 				 * by the usual expansion rules:
6740 				 *  >az >bz
6741 				 *  v='a bz'; echo "${v/a*z/a*z}" #prints "a*z"
6742 				 *  v='a bz'; echo "${v/a*z/\z}"  #prints "z"
6743 				 *  v='a bz'; echo ${v/a*z/a*z}   #prints "az"
6744 				 *  v='a bz'; echo ${v/a*z/\z}    #prints "z"
6745 				 * (note that a*z _pattern_ is never globbed!)
6746 				 */
6747 				char *pattern, *repl, *t;
6748 				pattern = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ 1, /*unbackslash:*/ 0);
6749 				if (!pattern)
6750 					pattern = xstrdup(exp_word);
6751 				debug_printf_varexp("pattern:'%s'->'%s'\n", exp_word, pattern);
6752 				*p++ = SPECIAL_VAR_SYMBOL;
6753 				exp_word = p;
6754 				p = strchr(p, SPECIAL_VAR_SYMBOL);
6755 				*p = '\0';
6756 				repl = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ 1, /*unbackslash:*/ 1);
6757 				debug_printf_varexp("repl:'%s'->'%s'\n", exp_word, repl);
6758 				/* HACK ALERT. We depend here on the fact that
6759 				 * G.global_argv and results of utoa and get_local_var_value
6760 				 * are actually in writable memory:
6761 				 * replace_pattern momentarily stores NULs there. */
6762 				t = (char*)val;
6763 				to_be_freed = replace_pattern(t,
6764 						pattern,
6765 						(repl ? repl : exp_word),
6766 						exp_op);
6767 				if (to_be_freed) /* at least one replace happened */
6768 					val = to_be_freed;
6769 				free(pattern);
6770 				free(repl);
6771 			} else {
6772 				/* Unset variable always gives nothing */
6773 				//  a=; echo ${a/*/w}      # "w"
6774 				//  unset a; echo ${a/*/w} # ""
6775 				/* Just skip "replace" part */
6776 				*p++ = SPECIAL_VAR_SYMBOL;
6777 				p = strchr(p, SPECIAL_VAR_SYMBOL);
6778 				*p = '\0';
6779 			}
6780 		}
6781 #endif /* BASH_PATTERN_SUBST */
6782 		else if (exp_op == ':') {
6783 #if BASH_SUBSTR && ENABLE_FEATURE_SH_MATH
6784 			/* It's ${var:N[:M]} bashism.
6785 			 * Note that in encoded form it has TWO parts:
6786 			 * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL>
6787 			 */
6788 			arith_t beg, len;
6789 			unsigned vallen;
6790 			const char *errmsg;
6791 
6792 			beg = expand_and_evaluate_arith(exp_word, &errmsg);
6793 			if (errmsg)
6794 				goto empty_result;
6795 			debug_printf_varexp("beg:'%s'=%lld\n", exp_word, (long long)beg);
6796 			*p++ = SPECIAL_VAR_SYMBOL;
6797 			exp_word = p;
6798 			p = strchr(p, SPECIAL_VAR_SYMBOL);
6799 			*p = '\0';
6800 			vallen = val ? strlen(val) : 0;
6801 			if (beg < 0) {
6802 				/* negative beg counts from the end */
6803 				beg = (arith_t)vallen + beg;
6804 			}
6805 			/* If expansion will be empty, do not even evaluate len */
6806 			if (!val || beg < 0 || beg > vallen) {
6807 				/* Why > vallen, not >=? bash:
6808 				 * unset b; a=ab; : ${a:2:${b=3}}; echo $b  # "", b=3 (!!!)
6809 				 * unset b; a=a; : ${a:2:${b=3}}; echo $b   # "", b not set
6810 				 */
6811 				goto empty_result;
6812 			}
6813 			len = expand_and_evaluate_arith(exp_word, &errmsg);
6814 			if (errmsg)
6815 				goto empty_result;
6816 			debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len);
6817 			debug_printf_varexp("from val:'%s'\n", val);
6818 			if (len < 0) {
6819 				/* in bash, len=-n means strlen()-n */
6820 				len = (arith_t)vallen - beg + len;
6821 				if (len < 0) /* bash compat */
6822 					msg_and_die_if_script("%s: substring expression < 0", var);
6823 			}
6824 			if (len <= 0 || !val /*|| beg >= vallen*/) {
6825  empty_result:
6826 				val = NULL;
6827 			} else {
6828 				/* Paranoia. What if user entered 9999999999999
6829 				 * which fits in arith_t but not int? */
6830 				if (len > INT_MAX)
6831 					len = INT_MAX;
6832 				val = to_be_freed = xstrndup(val + beg, len);
6833 			}
6834 			debug_printf_varexp("val:'%s'\n", val);
6835 #else /* not (HUSH_SUBSTR_EXPANSION && FEATURE_SH_MATH) */
6836 			msg_and_die_if_script("malformed ${%s:...}", var);
6837 			val = NULL;
6838 #endif
6839 		} else { /* one of "-=+?" */
6840 			/* Standard-mandated substitution ops:
6841 			 * ${var?word} - indicate error if unset
6842 			 *      If var is unset, word (or a message indicating it is unset
6843 			 *      if word is null) is written to standard error
6844 			 *      and the shell exits with a non-zero exit status.
6845 			 *      Otherwise, the value of var is substituted.
6846 			 * ${var-word} - use default value
6847 			 *      If var is unset, word is substituted.
6848 			 * ${var=word} - assign and use default value
6849 			 *      If var is unset, word is assigned to var.
6850 			 *      In all cases, final value of var is substituted.
6851 			 * ${var+word} - use alternative value
6852 			 *      If var is unset, null is substituted.
6853 			 *      Otherwise, word is substituted.
6854 			 *
6855 			 * Word is subjected to tilde expansion, parameter expansion,
6856 			 * command substitution, and arithmetic expansion.
6857 			 * If word is not needed, it is not expanded.
6858 			 *
6859 			 * Colon forms (${var:-word}, ${var:=word} etc) do the same,
6860 			 * but also treat null var as if it is unset.
6861 			 *
6862 			 * Word-splitting and single quote behavior:
6863 			 *
6864 			 * $ f() { for i; do echo "|$i|"; done; }
6865 			 *
6866 			 * $ x=; f ${x:?'x y' z}; echo $?
6867 			 * bash: x: x y z       # neither f nor "echo $?" executes
6868 			 * (if interactive, bash does not exit, but merely aborts to prompt. $? is set to 1)
6869 			 * $ x=; f "${x:?'x y' z}"
6870 			 * bash: x: x y z       # dash prints: dash: x: 'x y' z
6871 			 *
6872 			 * $ x=; f ${x:='x y' z}
6873 			 * |x|
6874 			 * |y|
6875 			 * |z|
6876 			 * $ x=; f "${x:='x y' z}"
6877 			 * |'x y' z|
6878 			 *
6879 			 * $ x=x; f ${x:+'x y' z}
6880 			 * |x y|
6881 			 * |z|
6882 			 * $ x=x; f "${x:+'x y' z}"
6883 			 * |'x y' z|
6884 			 *
6885 			 * $ x=; f ${x:-'x y' z}
6886 			 * |x y|
6887 			 * |z|
6888 			 * $ x=; f "${x:-'x y' z}"
6889 			 * |'x y' z|
6890 			 */
6891 			int use_word = (!val || ((exp_save == ':') && !val[0]));
6892 			if (exp_op == '+')
6893 				use_word = !use_word;
6894 			debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op,
6895 					(exp_save == ':') ? "true" : "false", use_word);
6896 			if (use_word) {
6897 				if (exp_op == '+' || exp_op == '-') {
6898 					/* ${var+word} - use alternative value */
6899 					/* ${var-word} - use default value */
6900 					n = encode_then_append_var_plusminus(output, n, exp_word,
6901 							/*dquoted:*/ (arg0 & 0x80)
6902 					);
6903 					val = NULL;
6904 				} else {
6905 					/* ${var?word} - indicate error if unset */
6906 					/* ${var=word} - assign and use default value */
6907 					to_be_freed = encode_then_expand_vararg(exp_word,
6908 							/*handle_squotes:*/ !(arg0 & 0x80),
6909 							/*unbackslash:*/ 0
6910 					);
6911 					if (to_be_freed)
6912 						exp_word = to_be_freed;
6913 					if (exp_op == '?') {
6914 						/* mimic bash message */
6915 						msg_and_die_if_script("%s: %s",
6916 							var,
6917 							exp_word[0]
6918 							? exp_word
6919 							: "parameter null or not set"
6920 							/* ash has more specific messages, a-la: */
6921 							/*: (exp_save == ':' ? "parameter null or not set" : "parameter not set")*/
6922 						);
6923 //TODO: how interactive bash aborts expansion mid-command?
6924 //It aborts the entire line, returns to prompt:
6925 // $ f() { for i; do echo "|$i|"; done; }; x=; f "${x:?'x y' z}"; echo YO
6926 // bash: x: x y z
6927 // $
6928 // ("echo YO" is not executed, neither the f function call)
6929 					} else {
6930 						val = exp_word;
6931 					}
6932 					if (exp_op == '=') {
6933 						/* ${var=[word]} or ${var:=[word]} */
6934 						if (isdigit(var[0]) || var[0] == '#') {
6935 							/* mimic bash message */
6936 							msg_and_die_if_script("$%s: cannot assign in this way", var);
6937 							val = NULL;
6938 						} else {
6939 							char *new_var = xasprintf("%s=%s", var, val);
6940 							set_local_var(new_var, /*flag:*/ 0);
6941 						}
6942 					}
6943 				}
6944 			}
6945 		} /* one of "-=+?" */
6946 
6947 		*exp_saveptr = exp_save;
6948 	} /* if (exp_op) */
6949 
6950 	arg[0] = arg0;
6951 	*pp = p;
6952 
6953 	n = append_str_maybe_ifs_split(output, n, first_ch, val);
6954 
6955 	free(to_be_freed);
6956 	return n;
6957 }
6958 
6959 /* Expand all variable references in given string, adding words to list[]
6960  * at n, n+1,... positions. Return updated n (so that list[n] is next one
6961  * to be filled). This routine is extremely tricky: has to deal with
6962  * variables/parameters with whitespace, $* and $@, and constructs like
6963  * 'echo -$*-'. If you play here, you must run testsuite afterwards! */
expand_vars_to_list(o_string * output,int n,char * arg)6964 static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
6965 {
6966 	/* output->o_expflags & EXP_FLAG_SINGLEWORD (0x80) if we are in
6967 	 * expansion of right-hand side of assignment == 1-element expand.
6968 	 */
6969 	char cant_be_null = 0; /* only bit 0x80 matters */
6970 	char *p;
6971 
6972 	debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg,
6973 			!!(output->o_expflags & EXP_FLAG_SINGLEWORD));
6974 	debug_print_list("expand_vars_to_list[0]", output, n);
6975 
6976 	while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) {
6977 		char first_ch;
6978 #if ENABLE_FEATURE_SH_MATH
6979 		char arith_buf[sizeof(arith_t)*3 + 2];
6980 #endif
6981 
6982 		if (output->ended_in_ifs) {
6983 			o_addchr(output, '\0');
6984 			n = o_save_ptr(output, n);
6985 			output->ended_in_ifs = 0;
6986 		}
6987 
6988 		o_addblock(output, arg, p - arg);
6989 		debug_print_list("expand_vars_to_list[1]", output, n);
6990 		arg = ++p;
6991 		p = strchr(p, SPECIAL_VAR_SYMBOL);
6992 
6993 		/* Fetch special var name (if it is indeed one of them)
6994 		 * and quote bit, force the bit on if singleword expansion -
6995 		 * important for not getting v=$@ expand to many words. */
6996 		first_ch = arg[0] | (output->o_expflags & EXP_FLAG_SINGLEWORD);
6997 
6998 		/* Is this variable quoted and thus expansion can't be null?
6999 		 * "$@" is special. Even if quoted, it can still
7000 		 * expand to nothing (not even an empty string),
7001 		 * thus it is excluded. */
7002 		if ((first_ch & 0x7f) != '@')
7003 			cant_be_null |= first_ch;
7004 
7005 		switch (first_ch & 0x7f) {
7006 		/* Highest bit in first_ch indicates that var is double-quoted */
7007 		case '*':
7008 		case '@': {
7009 			int i;
7010 			if (!G.global_argv[1])
7011 				break;
7012 			i = 1;
7013 			cant_be_null |= first_ch; /* do it for "$@" _now_, when we know it's not empty */
7014 			if (!(first_ch & 0x80)) { /* unquoted $* or $@ */
7015 				while (G.global_argv[i]) {
7016 					n = expand_on_ifs(output, n, G.global_argv[i]);
7017 					debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1);
7018 					if (G.global_argv[i++][0] && G.global_argv[i]) {
7019 						/* this argv[] is not empty and not last:
7020 						 * put terminating NUL, start new word */
7021 						o_addchr(output, '\0');
7022 						debug_print_list("expand_vars_to_list[2]", output, n);
7023 						n = o_save_ptr(output, n);
7024 						debug_print_list("expand_vars_to_list[3]", output, n);
7025 					}
7026 				}
7027 			} else
7028 			/* If EXP_FLAG_SINGLEWORD, we handle assignment 'a=....$@.....'
7029 			 * and in this case should treat it like '$*' - see 'else...' below */
7030 			if (first_ch == (char)('@'|0x80)  /* quoted $@ */
7031 			 && !(output->o_expflags & EXP_FLAG_SINGLEWORD) /* not v="$@" case */
7032 			) {
7033 				while (1) {
7034 					o_addQstr(output, G.global_argv[i]);
7035 					if (++i >= G.global_argc)
7036 						break;
7037 					o_addchr(output, '\0');
7038 					debug_print_list("expand_vars_to_list[4]", output, n);
7039 					n = o_save_ptr(output, n);
7040 				}
7041 			} else { /* quoted $* (or v="$@" case): add as one word */
7042 				while (1) {
7043 					o_addQstr(output, G.global_argv[i]);
7044 					if (!G.global_argv[++i])
7045 						break;
7046 					if (G.ifs[0])
7047 						o_addchr(output, G.ifs[0]);
7048 				}
7049 				output->has_quoted_part = 1;
7050 			}
7051 			break;
7052 		}
7053 		case SPECIAL_VAR_SYMBOL: {
7054 			/* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_SYMBOL> */
7055 			/* "Empty variable", used to make "" etc to not disappear */
7056 			output->has_quoted_part = 1;
7057 			cant_be_null = 0x80;
7058 			arg++;
7059 			break;
7060 		}
7061 		case SPECIAL_VAR_QUOTED_SVS:
7062 			/* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_QUOTED_SVS><SPECIAL_VAR_SYMBOL> */
7063 			/* "^C variable", represents literal ^C char (possible in scripts) */
7064 			o_addchr(output, SPECIAL_VAR_SYMBOL);
7065 			arg++;
7066 			break;
7067 #if ENABLE_HUSH_TICK
7068 		case '`': {
7069 			/* <SPECIAL_VAR_SYMBOL>`cmd<SPECIAL_VAR_SYMBOL> */
7070 			o_string subst_result = NULL_O_STRING;
7071 
7072 			*p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */
7073 			arg++;
7074 			/* Can't just stuff it into output o_string,
7075 			 * expanded result may need to be globbed
7076 			 * and $IFS-split */
7077 			debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch);
7078 			G.last_exitcode = process_command_subs(&subst_result, arg);
7079 			G.expand_exitcode = G.last_exitcode;
7080 			debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data);
7081 			n = append_str_maybe_ifs_split(output, n, first_ch, subst_result.data);
7082 			o_free(&subst_result);
7083 			break;
7084 		}
7085 #endif
7086 #if ENABLE_FEATURE_SH_MATH
7087 		case '+': {
7088 			/* <SPECIAL_VAR_SYMBOL>+arith<SPECIAL_VAR_SYMBOL> */
7089 			arith_t res;
7090 
7091 			arg++; /* skip '+' */
7092 			*p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */
7093 			debug_printf_subst("ARITH '%s' first_ch %x\n", arg, first_ch);
7094 			res = expand_and_evaluate_arith(arg, NULL);
7095 			debug_printf_subst("ARITH RES '"ARITH_FMT"'\n", res);
7096 			sprintf(arith_buf, ARITH_FMT, res);
7097 			if (res < 0
7098 			 && first_ch == (char)('+'|0x80)
7099 			/* && (output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS) */
7100 			) {
7101 				/* Quoted negative ariths, like filename[0"$((-9))"],
7102 				 * should not be interpreted as glob ranges.
7103 				 * Convert leading '-' to '\-':
7104 				 */
7105 				o_grow_by(output, 1);
7106 				output->data[output->length++] = '\\';
7107 			}
7108 			o_addstr(output, arith_buf);
7109 			break;
7110 		}
7111 #endif
7112 		default:
7113 			/* <SPECIAL_VAR_SYMBOL>varname[ops]<SPECIAL_VAR_SYMBOL> */
7114 			n = expand_one_var(output, n, first_ch, arg, &p);
7115 			break;
7116 		} /* switch (char after <SPECIAL_VAR_SYMBOL>) */
7117 
7118 		/* Restore NULL'ed SPECIAL_VAR_SYMBOL.
7119 		 * Do the check to avoid writing to a const string. */
7120 		if (*p != SPECIAL_VAR_SYMBOL)
7121 			*p = SPECIAL_VAR_SYMBOL;
7122 		arg = ++p;
7123 	} /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */
7124 
7125 	if (*arg) {
7126 		/* handle trailing string */
7127 		if (output->ended_in_ifs) {
7128 			o_addchr(output, '\0');
7129 			n = o_save_ptr(output, n);
7130 		}
7131 		debug_print_list("expand_vars_to_list[a]", output, n);
7132 		/* this part is literal, and it was already pre-quoted
7133 		 * if needed (much earlier), do not use o_addQstr here!
7134 		 */
7135 		o_addstr(output, arg);
7136 		debug_print_list("expand_vars_to_list[b]", output, n);
7137 	} else
7138 	if (output->length == o_get_last_ptr(output, n) /* expansion is empty */
7139 	 && !(cant_be_null & 0x80)   /* and all vars were not quoted */
7140 	 && !output->has_quoted_part
7141 	) {
7142 		n--;
7143 		/* allow to reuse list[n] later without re-growth */
7144 		output->has_empty_slot = 1;
7145 	}
7146 
7147 	return n;
7148 }
7149 
expand_variables(char ** argv,unsigned expflags)7150 static char **expand_variables(char **argv, unsigned expflags)
7151 {
7152 	int n;
7153 	char **list;
7154 	o_string output = NULL_O_STRING;
7155 
7156 	output.o_expflags = expflags;
7157 
7158 	n = 0;
7159 	for (;;) {
7160 		/* go to next list[n] */
7161 		output.ended_in_ifs = 0;
7162 		n = o_save_ptr(&output, n);
7163 
7164 		if (!*argv)
7165 			break;
7166 
7167 		/* expand argv[i] */
7168 		n = expand_vars_to_list(&output, n, *argv++);
7169 		/* if (!output->has_empty_slot) -- need this?? */
7170 			o_addchr(&output, '\0');
7171 	}
7172 	debug_print_list("expand_variables", &output, n);
7173 
7174 	/* output.data (malloced in one block) gets returned in "list" */
7175 	list = o_finalize_list(&output, n);
7176 	debug_print_strings("expand_variables[1]", list);
7177 	return list;
7178 }
7179 
expand_strvec_to_strvec(char ** argv)7180 static char **expand_strvec_to_strvec(char **argv)
7181 {
7182 	return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS);
7183 }
7184 
7185 #if defined(CMD_SINGLEWORD_NOGLOB) || defined(CMD_TEST2_SINGLEWORD_NOGLOB)
expand_strvec_to_strvec_singleword_noglob(char ** argv)7186 static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
7187 {
7188 	return expand_variables(argv, EXP_FLAG_SINGLEWORD);
7189 }
7190 #endif
7191 
7192 /* Used for expansion of right hand of assignments,
7193  * $((...)), heredocs, variable expansion parts.
7194  *
7195  * NB: should NOT do globbing!
7196  * "export v=/bin/c*; env | grep ^v=" outputs "v=/bin/c*"
7197  */
expand_string_to_string(const char * str,int EXP_flags,int do_unbackslash)7198 static char *expand_string_to_string(const char *str, int EXP_flags, int do_unbackslash)
7199 {
7200 #if !BASH_PATTERN_SUBST && !ENABLE_HUSH_CASE
7201 	const int do_unbackslash = 1;
7202 	const int EXP_flags = EXP_FLAG_ESC_GLOB_CHARS;
7203 #endif
7204 	char *argv[2], **list;
7205 
7206 	debug_printf_expand("string_to_string<='%s'\n", str);
7207 	/* This is generally an optimization, but it also
7208 	 * handles "", which otherwise trips over !list[0] check below.
7209 	 * (is this ever happens that we actually get str="" here?)
7210 	 */
7211 	if (!strchr(str, SPECIAL_VAR_SYMBOL) && !strchr(str, '\\')) {
7212 		//TODO: Can use on strings with \ too, just unbackslash() them?
7213 		debug_printf_expand("string_to_string(fast)=>'%s'\n", str);
7214 		return xstrdup(str);
7215 	}
7216 
7217 	argv[0] = (char*)str;
7218 	argv[1] = NULL;
7219 	list = expand_variables(argv, EXP_flags | EXP_FLAG_SINGLEWORD);
7220 	if (!list[0]) {
7221 		/* Example where it happens:
7222 		 * x=; echo ${x:-"$@"}
7223 		 */
7224 		((char*)list)[0] = '\0';
7225 	} else {
7226 		if (HUSH_DEBUG)
7227 			if (list[1])
7228 				bb_simple_error_msg_and_die("BUG in varexp2");
7229 		/* actually, just move string 2*sizeof(char*) bytes back */
7230 		overlapping_strcpy((char*)list, list[0]);
7231 		if (do_unbackslash)
7232 			unbackslash((char*)list);
7233 	}
7234 	debug_printf_expand("string_to_string=>'%s'\n", (char*)list);
7235 	return (char*)list;
7236 }
7237 
7238 #if 0
7239 static char* expand_strvec_to_string(char **argv)
7240 {
7241 	char **list;
7242 
7243 	list = expand_variables(argv, EXP_FLAG_SINGLEWORD);
7244 	/* Convert all NULs to spaces */
7245 	if (list[0]) {
7246 		int n = 1;
7247 		while (list[n]) {
7248 			if (HUSH_DEBUG)
7249 				if (list[n-1] + strlen(list[n-1]) + 1 != list[n])
7250 					bb_error_msg_and_die("BUG in varexp3");
7251 			/* bash uses ' ' regardless of $IFS contents */
7252 			list[n][-1] = ' ';
7253 			n++;
7254 		}
7255 	}
7256 	overlapping_strcpy((char*)list, list[0] ? list[0] : "");
7257 	debug_printf_expand("strvec_to_string='%s'\n", (char*)list);
7258 	return (char*)list;
7259 }
7260 #endif
7261 
expand_assignments(char ** argv,int count)7262 static char **expand_assignments(char **argv, int count)
7263 {
7264 	int i;
7265 	char **p;
7266 
7267 	G.expanded_assignments = p = NULL;
7268 	/* Expand assignments into one string each */
7269 	for (i = 0; i < count; i++) {
7270 		p = add_string_to_strings(p,
7271 			expand_string_to_string(argv[i],
7272 				EXP_FLAG_ESC_GLOB_CHARS,
7273 				/*unbackslash:*/ 1
7274 			)
7275 		);
7276 		G.expanded_assignments = p;
7277 	}
7278 	G.expanded_assignments = NULL;
7279 	return p;
7280 }
7281 
7282 
switch_off_special_sigs(unsigned mask)7283 static void switch_off_special_sigs(unsigned mask)
7284 {
7285 	unsigned sig = 0;
7286 	while ((mask >>= 1) != 0) {
7287 		sig++;
7288 		if (!(mask & 1))
7289 			continue;
7290 #if ENABLE_HUSH_TRAP
7291 		if (G_traps) {
7292 			if (G_traps[sig] && !G_traps[sig][0])
7293 				/* trap is '', has to remain SIG_IGN */
7294 				continue;
7295 			free(G_traps[sig]);
7296 			G_traps[sig] = NULL;
7297 		}
7298 #endif
7299 		/* We are here only if no trap or trap was not '' */
7300 		install_sighandler(sig, SIG_DFL);
7301 	}
7302 }
7303 
7304 #if BB_MMU
7305 /* never called */
7306 void re_execute_shell(char ***to_free, const char *s,
7307 		char *g_argv0, char **g_argv,
7308 		char **builtin_argv) NORETURN;
7309 
reset_traps_to_defaults(void)7310 static void reset_traps_to_defaults(void)
7311 {
7312 	/* This function is always called in a child shell
7313 	 * after fork (not vfork, NOMMU doesn't use this function).
7314 	 */
7315 	IF_HUSH_TRAP(unsigned sig;)
7316 	unsigned mask;
7317 
7318 	/* Child shells are not interactive.
7319 	 * SIGTTIN/SIGTTOU/SIGTSTP should not have special handling.
7320 	 * Testcase: (while :; do :; done) + ^Z should background.
7321 	 * Same goes for SIGTERM, SIGHUP, SIGINT.
7322 	 */
7323 	mask = (G.special_sig_mask & SPECIAL_INTERACTIVE_SIGS) | G_fatal_sig_mask;
7324 	if (!G_traps && !mask)
7325 		return; /* already no traps and no special sigs */
7326 
7327 	/* Switch off special sigs */
7328 	switch_off_special_sigs(mask);
7329 # if ENABLE_HUSH_JOB
7330 	G_fatal_sig_mask = 0;
7331 # endif
7332 	G.special_sig_mask &= ~SPECIAL_INTERACTIVE_SIGS;
7333 	/* SIGQUIT,SIGCHLD and maybe SPECIAL_JOBSTOP_SIGS
7334 	 * remain set in G.special_sig_mask */
7335 
7336 # if ENABLE_HUSH_TRAP
7337 	if (!G_traps)
7338 		return;
7339 
7340 	/* Reset all sigs to default except ones with empty traps */
7341 	for (sig = 0; sig < NSIG; sig++) {
7342 		if (!G_traps[sig])
7343 			continue; /* no trap: nothing to do */
7344 		if (!G_traps[sig][0])
7345 			continue; /* empty trap: has to remain SIG_IGN */
7346 		/* sig has non-empty trap, reset it: */
7347 		free(G_traps[sig]);
7348 		G_traps[sig] = NULL;
7349 		/* There is no signal for trap 0 (EXIT) */
7350 		if (sig == 0)
7351 			continue;
7352 		install_sighandler(sig, pick_sighandler(sig));
7353 	}
7354 # endif
7355 }
7356 
7357 #else /* !BB_MMU */
7358 
7359 static void re_execute_shell(char ***to_free, const char *s,
7360 		char *g_argv0, char **g_argv,
7361 		char **builtin_argv) NORETURN;
re_execute_shell(char *** to_free,const char * s,char * g_argv0,char ** g_argv,char ** builtin_argv)7362 static void re_execute_shell(char ***to_free, const char *s,
7363 		char *g_argv0, char **g_argv,
7364 		char **builtin_argv)
7365 {
7366 # define NOMMU_HACK_FMT ("-$%x:%x:%x:%x:%x:%llx" IF_HUSH_LOOPS(":%x"))
7367 	/* delims + 2 * (number of bytes in printed hex numbers) */
7368 	char param_buf[sizeof(NOMMU_HACK_FMT) + 2 * (sizeof(int)*6 + sizeof(long long)*1)];
7369 	char *heredoc_argv[4];
7370 	struct variable *cur;
7371 # if ENABLE_HUSH_FUNCTIONS
7372 	struct function *funcp;
7373 # endif
7374 	char **argv, **pp;
7375 	unsigned cnt;
7376 	unsigned long long empty_trap_mask;
7377 
7378 	if (!g_argv0) { /* heredoc */
7379 		argv = heredoc_argv;
7380 		argv[0] = (char *) G.argv0_for_re_execing;
7381 		argv[1] = (char *) "-<";
7382 		argv[2] = (char *) s;
7383 		argv[3] = NULL;
7384 		pp = &argv[3]; /* used as pointer to empty environment */
7385 		goto do_exec;
7386 	}
7387 
7388 	cnt = 0;
7389 	pp = builtin_argv;
7390 	if (pp) while (*pp++)
7391 		cnt++;
7392 
7393 	empty_trap_mask = 0;
7394 	if (G_traps) {
7395 		int sig;
7396 		for (sig = 1; sig < NSIG; sig++) {
7397 			if (G_traps[sig] && !G_traps[sig][0])
7398 				empty_trap_mask |= 1LL << sig;
7399 		}
7400 	}
7401 
7402 	sprintf(param_buf, NOMMU_HACK_FMT
7403 			, (unsigned) G.root_pid
7404 			, (unsigned) G.root_ppid
7405 			, (unsigned) G.last_bg_pid
7406 			, (unsigned) G.last_exitcode
7407 			, cnt
7408 			, empty_trap_mask
7409 			IF_HUSH_LOOPS(, G.depth_of_loop)
7410 			);
7411 # undef NOMMU_HACK_FMT
7412 	/* 1:hush 2:-$<pid>:<pid>:<exitcode>:<etc...> <vars...> <funcs...>
7413 	 * 3:-c 4:<cmd> 5:<arg0> <argN...> 6:NULL
7414 	 */
7415 	cnt += 6;
7416 	for (cur = G.top_var; cur; cur = cur->next) {
7417 		if (!cur->flg_export || cur->flg_read_only)
7418 			cnt += 2;
7419 	}
7420 # if ENABLE_HUSH_FUNCTIONS
7421 	for (funcp = G.top_func; funcp; funcp = funcp->next)
7422 		cnt += 3;
7423 # endif
7424 	pp = g_argv;
7425 	while (*pp++)
7426 		cnt++;
7427 	*to_free = argv = pp = xzalloc(sizeof(argv[0]) * cnt);
7428 	*pp++ = (char *) G.argv0_for_re_execing;
7429 	*pp++ = param_buf;
7430 	for (cur = G.top_var; cur; cur = cur->next) {
7431 		if (strcmp(cur->varstr, hush_version_str) == 0)
7432 			continue;
7433 		if (cur->flg_read_only) {
7434 			*pp++ = (char *) "-R";
7435 			*pp++ = cur->varstr;
7436 		} else if (!cur->flg_export) {
7437 			*pp++ = (char *) "-V";
7438 			*pp++ = cur->varstr;
7439 		}
7440 	}
7441 # if ENABLE_HUSH_FUNCTIONS
7442 	for (funcp = G.top_func; funcp; funcp = funcp->next) {
7443 		*pp++ = (char *) "-F";
7444 		*pp++ = funcp->name;
7445 		*pp++ = funcp->body_as_string;
7446 	}
7447 # endif
7448 	/* We can pass activated traps here. Say, -Tnn:trap_string
7449 	 *
7450 	 * However, POSIX says that subshells reset signals with traps
7451 	 * to SIG_DFL.
7452 	 * I tested bash-3.2 and it not only does that with true subshells
7453 	 * of the form ( list ), but with any forked children shells.
7454 	 * I set trap "echo W" WINCH; and then tried:
7455 	 *
7456 	 * { echo 1; sleep 20; echo 2; } &
7457 	 * while true; do echo 1; sleep 20; echo 2; break; done &
7458 	 * true | { echo 1; sleep 20; echo 2; } | cat
7459 	 *
7460 	 * In all these cases sending SIGWINCH to the child shell
7461 	 * did not run the trap. If I add trap "echo V" WINCH;
7462 	 * _inside_ group (just before echo 1), it works.
7463 	 *
7464 	 * I conclude it means we don't need to pass active traps here.
7465 	 */
7466 	*pp++ = (char *) "-c";
7467 	*pp++ = (char *) s;
7468 	if (builtin_argv) {
7469 		while (*++builtin_argv)
7470 			*pp++ = *builtin_argv;
7471 		*pp++ = (char *) "";
7472 	}
7473 	*pp++ = g_argv0;
7474 	while (*g_argv)
7475 		*pp++ = *g_argv++;
7476 	/* *pp = NULL; - is already there */
7477 	pp = environ;
7478 
7479  do_exec:
7480 	debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
7481 	/* Don't propagate SIG_IGN to the child */
7482 	if (SPECIAL_JOBSTOP_SIGS != 0)
7483 		switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS);
7484 	execve(bb_busybox_exec_path, argv, pp);
7485 	/* Fallback. Useful for init=/bin/hush usage etc */
7486 	if (argv[0][0] == '/')
7487 		execve(argv[0], argv, pp);
7488 	xfunc_error_retval = 127;
7489 	bb_simple_error_msg_and_die("can't re-execute the shell");
7490 }
7491 #endif  /* !BB_MMU */
7492 
7493 
7494 static int run_and_free_list(struct pipe *pi);
7495 
7496 /* Executing from string: eval, sh -c '...'
7497  *          or from file: /etc/profile, . file, sh <script>, sh (intereactive)
7498  * end_trigger controls how often we stop parsing
7499  * NUL: parse all, execute, return
7500  * ';': parse till ';' or newline, execute, repeat till EOF
7501  */
parse_and_run_stream(struct in_str * inp,int end_trigger)7502 static void parse_and_run_stream(struct in_str *inp, int end_trigger)
7503 {
7504 	/* Why we need empty flag?
7505 	 * An obscure corner case "false; ``; echo $?":
7506 	 * empty command in `` should still set $? to 0.
7507 	 * But we can't just set $? to 0 at the start,
7508 	 * this breaks "false; echo `echo $?`" case.
7509 	 */
7510 	bool empty = 1;
7511 	while (1) {
7512 		struct pipe *pipe_list;
7513 
7514 #if ENABLE_HUSH_INTERACTIVE
7515 		if (end_trigger == ';') {
7516 			G.promptmode = 0; /* PS1 */
7517 			debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode);
7518 		}
7519 #endif
7520 		pipe_list = parse_stream(NULL, NULL, inp, end_trigger);
7521 		if (!pipe_list || pipe_list == ERR_PTR) { /* EOF/error */
7522 			/* If we are in "big" script
7523 			 * (not in `cmd` or something similar)...
7524 			 */
7525 			if (pipe_list == ERR_PTR && end_trigger == ';') {
7526 				/* Discard cached input (rest of line) */
7527 				int ch = inp->last_char;
7528 				while (ch != EOF && ch != '\n') {
7529 					//bb_error_msg("Discarded:'%c'", ch);
7530 					ch = i_getch(inp);
7531 				}
7532 				/* Force prompt */
7533 				inp->p = NULL;
7534 				/* This stream isn't empty */
7535 				empty = 0;
7536 				continue;
7537 			}
7538 			if (!pipe_list && empty)
7539 				G.last_exitcode = 0;
7540 			break;
7541 		}
7542 		debug_print_tree(pipe_list, 0);
7543 		debug_printf_exec("parse_and_run_stream: run_and_free_list\n");
7544 		run_and_free_list(pipe_list);
7545 		empty = 0;
7546 		if (G_flag_return_in_progress == 1)
7547 			break;
7548 	}
7549 }
7550 
parse_and_run_string(const char * s)7551 static void parse_and_run_string(const char *s)
7552 {
7553 	struct in_str input;
7554 	IF_HUSH_LINENO_VAR(unsigned sv = G.parse_lineno;)
7555 
7556 	setup_string_in_str(&input, s);
7557 	parse_and_run_stream(&input, '\0');
7558 	IF_HUSH_LINENO_VAR(G.parse_lineno = sv;)
7559 }
7560 
parse_and_run_file(HFILE * fp)7561 static void parse_and_run_file(HFILE *fp)
7562 {
7563 	struct in_str input;
7564 	IF_HUSH_LINENO_VAR(unsigned sv = G.parse_lineno;)
7565 
7566 	IF_HUSH_LINENO_VAR(G.parse_lineno = 1;)
7567 	setup_file_in_str(&input, fp);
7568 	parse_and_run_stream(&input, ';');
7569 	IF_HUSH_LINENO_VAR(G.parse_lineno = sv;)
7570 }
7571 
7572 #if ENABLE_HUSH_TICK
generate_stream_from_string(const char * s,pid_t * pid_p)7573 static int generate_stream_from_string(const char *s, pid_t *pid_p)
7574 {
7575 	pid_t pid;
7576 	int channel[2];
7577 # if !BB_MMU
7578 	char **to_free = NULL;
7579 # endif
7580 
7581 	xpipe(channel);
7582 	pid = BB_MMU ? xfork() : xvfork();
7583 	if (pid == 0) { /* child */
7584 		disable_restore_tty_pgrp_on_exit();
7585 		/* Process substitution is not considered to be usual
7586 		 * 'command execution'.
7587 		 * SUSv3 says ctrl-Z should be ignored, ctrl-C should not.
7588 		 */
7589 		bb_signals(0
7590 			+ (1 << SIGTSTP)
7591 			+ (1 << SIGTTIN)
7592 			+ (1 << SIGTTOU)
7593 			, SIG_IGN);
7594 		close(channel[0]); /* NB: close _first_, then move fd! */
7595 		xmove_fd(channel[1], 1);
7596 # if ENABLE_HUSH_TRAP
7597 		/* Awful hack for `trap` or $(trap).
7598 		 *
7599 		 * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
7600 		 * contains an example where "trap" is executed in a subshell:
7601 		 *
7602 		 * save_traps=$(trap)
7603 		 * ...
7604 		 * eval "$save_traps"
7605 		 *
7606 		 * Standard does not say that "trap" in subshell shall print
7607 		 * parent shell's traps. It only says that its output
7608 		 * must have suitable form, but then, in the above example
7609 		 * (which is not supposed to be normative), it implies that.
7610 		 *
7611 		 * bash (and probably other shell) does implement it
7612 		 * (traps are reset to defaults, but "trap" still shows them),
7613 		 * but as a result, "trap" logic is hopelessly messed up:
7614 		 *
7615 		 * # trap
7616 		 * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
7617 		 * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
7618 		 * # true | trap   <--- trap is in subshell - no output (ditto)
7619 		 * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
7620 		 * trap -- 'echo Ho' SIGWINCH
7621 		 * # echo `(trap)`         <--- in subshell in subshell - output
7622 		 * trap -- 'echo Ho' SIGWINCH
7623 		 * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
7624 		 * trap -- 'echo Ho' SIGWINCH
7625 		 *
7626 		 * The rules when to forget and when to not forget traps
7627 		 * get really complex and nonsensical.
7628 		 *
7629 		 * Our solution: ONLY bare $(trap) or `trap` is special.
7630 		 */
7631 		s = skip_whitespace(s);
7632 		if (is_prefixed_with(s, "trap")
7633 		 && skip_whitespace(s + 4)[0] == '\0'
7634 		) {
7635 			static const char *const argv[] = { NULL, NULL };
7636 			builtin_trap((char**)argv);
7637 			fflush_all(); /* important */
7638 			_exit(0);
7639 		}
7640 # endif
7641 # if BB_MMU
7642 		/* Prevent it from trying to handle ctrl-z etc */
7643 		IF_HUSH_JOB(G.run_list_level = 1;)
7644 		CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */
7645 		reset_traps_to_defaults();
7646 		IF_HUSH_MODE_X(G.x_mode_depth++;)
7647 		//bb_error_msg("%s: ++x_mode_depth=%d", __func__, G.x_mode_depth);
7648 		parse_and_run_string(s);
7649 		_exit(G.last_exitcode);
7650 # else
7651 	/* We re-execute after vfork on NOMMU. This makes this script safe:
7652 	 * yes "0123456789012345678901234567890" | dd bs=32 count=64k >BIG
7653 	 * huge=`cat BIG` # was blocking here forever
7654 	 * echo OK
7655 	 */
7656 		re_execute_shell(&to_free,
7657 				s,
7658 				G.global_argv[0],
7659 				G.global_argv + 1,
7660 				NULL);
7661 # endif
7662 	}
7663 
7664 	/* parent */
7665 	*pid_p = pid;
7666 # if ENABLE_HUSH_FAST
7667 	G.count_SIGCHLD++;
7668 //bb_error_msg("[%d] fork in generate_stream_from_string:"
7669 //		" G.count_SIGCHLD:%d G.handled_SIGCHLD:%d",
7670 //		getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
7671 # endif
7672 	enable_restore_tty_pgrp_on_exit();
7673 # if !BB_MMU
7674 	free(to_free);
7675 # endif
7676 	close(channel[1]);
7677 	return channel[0];
7678 }
7679 
7680 /* Return code is exit status of the process that is run. */
process_command_subs(o_string * dest,const char * s)7681 static int process_command_subs(o_string *dest, const char *s)
7682 {
7683 	FILE *fp;
7684 	pid_t pid;
7685 	int status, ch, eol_cnt;
7686 
7687 	fp = xfdopen_for_read(generate_stream_from_string(s, &pid));
7688 
7689 	/* Now send results of command back into original context */
7690 	eol_cnt = 0;
7691 	while ((ch = getc(fp)) != EOF) {
7692 		if (ch == '\0')
7693 			continue;
7694 		if (ch == '\n') {
7695 			eol_cnt++;
7696 			continue;
7697 		}
7698 		while (eol_cnt) {
7699 			o_addchr(dest, '\n');
7700 			eol_cnt--;
7701 		}
7702 		o_addQchr(dest, ch);
7703 	}
7704 
7705 	debug_printf("done reading from `cmd` pipe, closing it\n");
7706 	fclose(fp);
7707 	/* We need to extract exitcode. Test case
7708 	 * "true; echo `sleep 1; false` $?"
7709 	 * should print 1 */
7710 	safe_waitpid(pid, &status, 0);
7711 	debug_printf("child exited. returning its exitcode:%d\n", WEXITSTATUS(status));
7712 	return WEXITSTATUS(status);
7713 }
7714 #endif /* ENABLE_HUSH_TICK */
7715 
7716 
setup_heredoc(struct redir_struct * redir)7717 static void setup_heredoc(struct redir_struct *redir)
7718 {
7719 	struct fd_pair pair;
7720 	pid_t pid;
7721 	int len, written;
7722 	/* the _body_ of heredoc (misleading field name) */
7723 	const char *heredoc = redir->rd_filename;
7724 	char *expanded;
7725 #if !BB_MMU
7726 	char **to_free;
7727 #endif
7728 
7729 	expanded = NULL;
7730 	if (!(redir->rd_dup & HEREDOC_QUOTED)) {
7731 		expanded = encode_then_expand_string(heredoc);
7732 		if (expanded)
7733 			heredoc = expanded;
7734 	}
7735 	len = strlen(heredoc);
7736 
7737 	close(redir->rd_fd); /* often saves dup2+close in xmove_fd */
7738 	xpiped_pair(pair);
7739 	xmove_fd(pair.rd, redir->rd_fd);
7740 
7741 	/* Try writing without forking. Newer kernels have
7742 	 * dynamically growing pipes. Must use non-blocking write! */
7743 	ndelay_on(pair.wr);
7744 	while (1) {
7745 		written = write(pair.wr, heredoc, len);
7746 		if (written <= 0)
7747 			break;
7748 		len -= written;
7749 		if (len == 0) {
7750 			close(pair.wr);
7751 			free(expanded);
7752 			return;
7753 		}
7754 		heredoc += written;
7755 	}
7756 	ndelay_off(pair.wr);
7757 
7758 	/* Okay, pipe buffer was not big enough */
7759 	/* Note: we must not create a stray child (bastard? :)
7760 	 * for the unsuspecting parent process. Child creates a grandchild
7761 	 * and exits before parent execs the process which consumes heredoc
7762 	 * (that exec happens after we return from this function) */
7763 #if !BB_MMU
7764 	to_free = NULL;
7765 #endif
7766 	pid = xvfork();
7767 	if (pid == 0) {
7768 		/* child */
7769 		disable_restore_tty_pgrp_on_exit();
7770 		pid = BB_MMU ? xfork() : xvfork();
7771 		if (pid != 0)
7772 			_exit(0);
7773 		/* grandchild */
7774 		close(redir->rd_fd); /* read side of the pipe */
7775 #if BB_MMU
7776 		full_write(pair.wr, heredoc, len); /* may loop or block */
7777 		_exit(0);
7778 #else
7779 		/* Delegate blocking writes to another process */
7780 		xmove_fd(pair.wr, STDOUT_FILENO);
7781 		re_execute_shell(&to_free, heredoc, NULL, NULL, NULL);
7782 #endif
7783 	}
7784 	/* parent */
7785 #if ENABLE_HUSH_FAST
7786 	G.count_SIGCHLD++;
7787 //bb_error_msg("[%d] fork in setup_heredoc: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
7788 #endif
7789 	enable_restore_tty_pgrp_on_exit();
7790 #if !BB_MMU
7791 	free(to_free);
7792 #endif
7793 	close(pair.wr);
7794 	free(expanded);
7795 	wait(NULL); /* wait till child has died */
7796 }
7797 
7798 struct squirrel {
7799 	int orig_fd;
7800 	int moved_to;
7801 	/* moved_to = n: fd was moved to n; restore back to orig_fd after redir */
7802 	/* moved_to = -1: fd was opened by redirect; close orig_fd after redir */
7803 };
7804 
append_squirrel(struct squirrel * sq,int i,int orig,int moved)7805 static struct squirrel *append_squirrel(struct squirrel *sq, int i, int orig, int moved)
7806 {
7807 	sq = xrealloc(sq, (i + 2) * sizeof(sq[0]));
7808 	sq[i].orig_fd = orig;
7809 	sq[i].moved_to = moved;
7810 	sq[i+1].orig_fd = -1; /* end marker */
7811 	return sq;
7812 }
7813 
add_squirrel(struct squirrel * sq,int fd,int avoid_fd)7814 static struct squirrel *add_squirrel(struct squirrel *sq, int fd, int avoid_fd)
7815 {
7816 	int moved_to;
7817 	int i;
7818 
7819 	i = 0;
7820 	if (sq) for (; sq[i].orig_fd >= 0; i++) {
7821 		/* If we collide with an already moved fd... */
7822 		if (fd == sq[i].moved_to) {
7823 			sq[i].moved_to = dup_CLOEXEC(sq[i].moved_to, avoid_fd);
7824 			debug_printf_redir("redirect_fd %d: already busy, moving to %d\n", fd, sq[i].moved_to);
7825 			if (sq[i].moved_to < 0) /* what? */
7826 				xfunc_die();
7827 			return sq;
7828 		}
7829 		if (fd == sq[i].orig_fd) {
7830 			/* Example: echo Hello >/dev/null 1>&2 */
7831 			debug_printf_redir("redirect_fd %d: already moved\n", fd);
7832 			return sq;
7833 		}
7834 	}
7835 
7836 	/* If this fd is open, we move and remember it; if it's closed, moved_to = -1 */
7837 	moved_to = dup_CLOEXEC(fd, avoid_fd);
7838 	debug_printf_redir("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, moved_to);
7839 	if (moved_to < 0 && errno != EBADF)
7840 		xfunc_die();
7841 	return append_squirrel(sq, i, fd, moved_to);
7842 }
7843 
add_squirrel_closed(struct squirrel * sq,int fd)7844 static struct squirrel *add_squirrel_closed(struct squirrel *sq, int fd)
7845 {
7846 	int i;
7847 
7848 	i = 0;
7849 	if (sq) for (; sq[i].orig_fd >= 0; i++) {
7850 		/* If we collide with an already moved fd... */
7851 		if (fd == sq[i].orig_fd) {
7852 			/* Examples:
7853 			 * "echo 3>FILE 3>&- 3>FILE"
7854 			 * "echo 3>&- 3>FILE"
7855 			 * No need for last redirect to insert
7856 			 * another "need to close 3" indicator.
7857 			 */
7858 			debug_printf_redir("redirect_fd %d: already moved or closed\n", fd);
7859 			return sq;
7860 		}
7861 	}
7862 
7863 	debug_printf_redir("redirect_fd %d: previous fd was closed\n", fd);
7864 	return append_squirrel(sq, i, fd, -1);
7865 }
7866 
7867 /* fd: redirect wants this fd to be used (e.g. 3>file).
7868  * Move all conflicting internally used fds,
7869  * and remember them so that we can restore them later.
7870  */
save_fd_on_redirect(int fd,int avoid_fd,struct squirrel ** sqp)7871 static int save_fd_on_redirect(int fd, int avoid_fd, struct squirrel **sqp)
7872 {
7873 	if (avoid_fd < 9) /* the important case here is that it can be -1 */
7874 		avoid_fd = 9;
7875 
7876 #if ENABLE_HUSH_INTERACTIVE
7877 	if (fd != 0 /* don't trigger for G_interactive_fd == 0 (that's "not interactive" flag) */
7878 	 && fd == G_interactive_fd
7879 	) {
7880 		/* Testcase: "ls -l /proc/$$/fd 255>&-" should work */
7881 		G_interactive_fd = xdup_CLOEXEC_and_close(G_interactive_fd, avoid_fd);
7882 		debug_printf_redir("redirect_fd %d: matches interactive_fd, moving it to %d\n", fd, G_interactive_fd);
7883 		return 1; /* "we closed fd" */
7884 	}
7885 #endif
7886 	/* Are we called from setup_redirects(squirrel==NULL)
7887 	 * in redirect in a [v]forked child?
7888 	 */
7889 	if (sqp == NULL) {
7890 		/* No need to move script fds.
7891 		 * For NOMMU case, it's actively wrong: we'd change ->fd
7892 		 * fields in memory for the parent, but parent's fds
7893 		 * aren't moved, it would use wrong fd!
7894 		 * Reproducer: "cmd 3>FILE" in script.
7895 		 * If we would call move_HFILEs_on_redirect(), child would:
7896 		 *  fcntl64(3, F_DUPFD_CLOEXEC, 10)   = 10
7897 		 *  close(3)                          = 0
7898 		 * and change ->fd to 10 if fd#3 is a script fd. WRONG.
7899 		 */
7900 		//bb_error_msg("sqp == NULL: [v]forked child");
7901 		return 0;
7902 	}
7903 
7904 	/* If this one of script's fds? */
7905 	if (move_HFILEs_on_redirect(fd, avoid_fd))
7906 		return 1; /* yes. "we closed fd" (actually moved it) */
7907 
7908 	/* Are we called for "exec 3>FILE"? Came through
7909 	 * redirect_and_varexp_helper(squirrel=ERR_PTR) -> setup_redirects(ERR_PTR)
7910 	 * This case used to fail for this script:
7911 	 *  exec 3>FILE
7912 	 *  echo Ok
7913 	 *  ...100000 more lines...
7914 	 *  echo Ok
7915 	 * as follows:
7916 	 *  read(3, "exec 3>FILE\necho Ok\necho Ok"..., 1024) = 1024
7917 	 *  open("FILE", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 4
7918 	 *  dup2(4, 3)                        = 3
7919 	 *  ^^^^^^^^ oops, we lost fd#3 opened to our script!
7920 	 *  close(4)                          = 0
7921 	 *  write(1, "Ok\n", 3)               = 3
7922 	 *  ...                               = 3
7923 	 *  write(1, "Ok\n", 3)               = 3
7924 	 *  read(3, 0x94fbc08, 1024)          = -1 EBADF (Bad file descriptor)
7925 	 *  ^^^^^^^^ oops, wrong fd!!!
7926 	 * With this case separate from sqp == NULL and *after* move_HFILEs,
7927 	 * it now works:
7928 	 */
7929 	if (sqp == ERR_PTR) {
7930 		/* Don't preserve redirected fds: exec is _meant_ to change these */
7931 		//bb_error_msg("sqp == ERR_PTR: exec >FILE");
7932 		return 0;
7933 	}
7934 
7935 	/* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
7936 	*sqp = add_squirrel(*sqp, fd, avoid_fd);
7937 	return 0; /* "we did not close fd" */
7938 }
7939 
restore_redirects(struct squirrel * sq)7940 static void restore_redirects(struct squirrel *sq)
7941 {
7942 	if (sq) {
7943 		int i;
7944 		for (i = 0; sq[i].orig_fd >= 0; i++) {
7945 			if (sq[i].moved_to >= 0) {
7946 				/* We simply die on error */
7947 				debug_printf_redir("restoring redirected fd from %d to %d\n", sq[i].moved_to, sq[i].orig_fd);
7948 				xmove_fd(sq[i].moved_to, sq[i].orig_fd);
7949 			} else {
7950 				/* cmd1 9>FILE; cmd2_should_see_fd9_closed */
7951 				debug_printf_redir("restoring redirected fd %d: closing it\n", sq[i].orig_fd);
7952 				close(sq[i].orig_fd);
7953 			}
7954 		}
7955 		free(sq);
7956 	}
7957 	if (G.HFILE_stdin
7958 	 && G.HFILE_stdin->fd > STDIN_FILENO
7959 	/* we compare > STDIN, not == STDIN, since hfgetc()
7960 	 * closes fd and sets ->fd to -1 if EOF is reached.
7961 	 * Testcase: echo 'pwd' | hush
7962 	 */
7963 	) {
7964 		/* Testcase: interactive "read r <FILE; echo $r; read r; echo $r".
7965 		 * Redirect moves ->fd to e.g. 10,
7966 		 * and it is not restored above (we do not restore script fds
7967 		 * after redirects, we just use new, "moved" fds).
7968 		 * However for stdin, get_user_input() -> read_line_input(),
7969 		 * and read builtin, depend on fd == STDIN_FILENO.
7970 		 */
7971 		debug_printf_redir("restoring %d to stdin\n", G.HFILE_stdin->fd);
7972 		xmove_fd(G.HFILE_stdin->fd, STDIN_FILENO);
7973 		G.HFILE_stdin->fd = STDIN_FILENO;
7974 	}
7975 
7976 	/* If moved, G_interactive_fd stays on new fd, not restoring it */
7977 }
7978 
7979 #if ENABLE_FEATURE_SH_STANDALONE && BB_MMU
close_saved_fds_and_FILE_fds(void)7980 static void close_saved_fds_and_FILE_fds(void)
7981 {
7982 	if (G_interactive_fd)
7983 		close(G_interactive_fd);
7984 	close_all_HFILE_list();
7985 }
7986 #endif
7987 
internally_opened_fd(int fd,struct squirrel * sq)7988 static int internally_opened_fd(int fd, struct squirrel *sq)
7989 {
7990 	int i;
7991 
7992 #if ENABLE_HUSH_INTERACTIVE
7993 	if (fd == G_interactive_fd)
7994 		return 1;
7995 #endif
7996 	/* If this one of script's fds? */
7997 	if (fd_in_HFILEs(fd))
7998 		return 1;
7999 
8000 	if (sq) for (i = 0; sq[i].orig_fd >= 0; i++) {
8001 		if (fd == sq[i].moved_to)
8002 			return 1;
8003 	}
8004 	return 0;
8005 }
8006 
8007 /* squirrel != NULL means we squirrel away copies of stdin, stdout,
8008  * and stderr if they are redirected. */
setup_redirects(struct command * prog,struct squirrel ** sqp)8009 static int setup_redirects(struct command *prog, struct squirrel **sqp)
8010 {
8011 	struct redir_struct *redir;
8012 
8013 	for (redir = prog->redirects; redir; redir = redir->next) {
8014 		int newfd;
8015 		int closed;
8016 
8017 		if (redir->rd_type == REDIRECT_HEREDOC2) {
8018 			/* "rd_fd<<HERE" case */
8019 			save_fd_on_redirect(redir->rd_fd, /*avoid:*/ 0, sqp);
8020 			/* for REDIRECT_HEREDOC2, rd_filename holds _contents_
8021 			 * of the heredoc */
8022 			debug_printf_redir("set heredoc '%s'\n",
8023 					redir->rd_filename);
8024 			setup_heredoc(redir);
8025 			continue;
8026 		}
8027 
8028 		if (redir->rd_dup == REDIRFD_TO_FILE) {
8029 			/* "rd_fd<*>file" case (<*> is <,>,>>,<>) */
8030 			char *p;
8031 			int mode;
8032 
8033 			if (redir->rd_filename == NULL) {
8034 				/* Examples:
8035 				 * "cmd >" (no filename)
8036 				 * "cmd > <file" (2nd redirect starts too early)
8037 				 */
8038 				syntax_error("invalid redirect");
8039 				continue;
8040 			}
8041 			mode = redir_table[redir->rd_type].mode;
8042 			p = expand_string_to_string(redir->rd_filename,
8043 				EXP_FLAG_ESC_GLOB_CHARS, /*unbackslash:*/ 1);
8044 			newfd = open_or_warn(p, mode);
8045 			free(p);
8046 			if (newfd < 0) {
8047 				/* Error message from open_or_warn can be lost
8048 				 * if stderr has been redirected, but bash
8049 				 * and ash both lose it as well
8050 				 * (though zsh doesn't!)
8051 				 */
8052 				return 1;
8053 			}
8054 			if (newfd == redir->rd_fd && sqp) {
8055 				/* open() gave us precisely the fd we wanted.
8056 				 * This means that this fd was not busy
8057 				 * (not opened to anywhere).
8058 				 * Remember to close it on restore:
8059 				 */
8060 				*sqp = add_squirrel_closed(*sqp, newfd);
8061 				debug_printf_redir("redir to previously closed fd %d\n", newfd);
8062 			}
8063 		} else {
8064 			/* "rd_fd>&rd_dup" or "rd_fd>&-" case */
8065 			newfd = redir->rd_dup;
8066 		}
8067 
8068 		if (newfd == redir->rd_fd)
8069 			continue;
8070 
8071 		/* if "N>FILE": move newfd to redir->rd_fd */
8072 		/* if "N>&M": dup newfd to redir->rd_fd */
8073 		/* if "N>&-": close redir->rd_fd (newfd is REDIRFD_CLOSE) */
8074 
8075 		closed = save_fd_on_redirect(redir->rd_fd, /*avoid:*/ newfd, sqp);
8076 		if (newfd == REDIRFD_CLOSE) {
8077 			/* "N>&-" means "close me" */
8078 			if (!closed) {
8079 				/* ^^^ optimization: saving may already
8080 				 * have closed it. If not... */
8081 				close(redir->rd_fd);
8082 			}
8083 			/* Sometimes we do another close on restore, getting EBADF.
8084 			 * Consider "echo 3>FILE 3>&-"
8085 			 * first redirect remembers "need to close 3",
8086 			 * and second redirect closes 3! Restore code then closes 3 again.
8087 			 */
8088 		} else {
8089 			/* if newfd is a script fd or saved fd, simulate EBADF */
8090 			if (internally_opened_fd(newfd, sqp && sqp != ERR_PTR ? *sqp : NULL)) {
8091 				//errno = EBADF;
8092 				//bb_perror_msg_and_die("can't duplicate file descriptor");
8093 				newfd = -1; /* same effect as code above */
8094 			}
8095 			xdup2(newfd, redir->rd_fd);
8096 			if (redir->rd_dup == REDIRFD_TO_FILE)
8097 				/* "rd_fd > FILE" */
8098 				close(newfd);
8099 			/* else: "rd_fd > rd_dup" */
8100 		}
8101 	}
8102 	return 0;
8103 }
8104 
find_in_path(const char * arg)8105 static char *find_in_path(const char *arg)
8106 {
8107 	char *ret = NULL;
8108 	const char *PATH = get_local_var_value("PATH");
8109 
8110 	if (!PATH)
8111 		return NULL;
8112 
8113 	while (1) {
8114 		const char *end = strchrnul(PATH, ':');
8115 		int sz = end - PATH; /* must be int! */
8116 
8117 		free(ret);
8118 		if (sz != 0) {
8119 			ret = xasprintf("%.*s/%s", sz, PATH, arg);
8120 		} else {
8121 			/* We have xxx::yyyy in $PATH,
8122 			 * it means "use current dir" */
8123 			ret = xstrdup(arg);
8124 		}
8125 		if (access(ret, F_OK) == 0)
8126 			break;
8127 
8128 		if (*end == '\0') {
8129 			free(ret);
8130 			return NULL;
8131 		}
8132 		PATH = end + 1;
8133 	}
8134 
8135 	return ret;
8136 }
8137 
find_builtin_helper(const char * name,const struct built_in_command * x,const struct built_in_command * end)8138 static const struct built_in_command *find_builtin_helper(const char *name,
8139 		const struct built_in_command *x,
8140 		const struct built_in_command *end)
8141 {
8142 	while (x != end) {
8143 		if (strcmp(name, x->b_cmd) != 0) {
8144 			x++;
8145 			continue;
8146 		}
8147 		debug_printf_exec("found builtin '%s'\n", name);
8148 		return x;
8149 	}
8150 	return NULL;
8151 }
find_builtin1(const char * name)8152 static const struct built_in_command *find_builtin1(const char *name)
8153 {
8154 	return find_builtin_helper(name, bltins1, &bltins1[ARRAY_SIZE(bltins1)]);
8155 }
find_builtin(const char * name)8156 static const struct built_in_command *find_builtin(const char *name)
8157 {
8158 	const struct built_in_command *x = find_builtin1(name);
8159 	if (x)
8160 		return x;
8161 	return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]);
8162 }
8163 
8164 #if ENABLE_HUSH_JOB && EDITING_HAS_get_exe_name
get_builtin_name(int i)8165 static const char * FAST_FUNC get_builtin_name(int i)
8166 {
8167 	if (/*i >= 0 && */ i < ARRAY_SIZE(bltins1)) {
8168 		return bltins1[i].b_cmd;
8169 	}
8170 	i -= ARRAY_SIZE(bltins1);
8171 	if (i < ARRAY_SIZE(bltins2)) {
8172 		return bltins2[i].b_cmd;
8173 	}
8174 	return NULL;
8175 }
8176 #endif
8177 
remove_nested_vars(void)8178 static void remove_nested_vars(void)
8179 {
8180 	struct variable *cur;
8181 	struct variable **cur_pp;
8182 
8183 	cur_pp = &G.top_var;
8184 	while ((cur = *cur_pp) != NULL) {
8185 		if (cur->var_nest_level <= G.var_nest_level) {
8186 			cur_pp = &cur->next;
8187 			continue;
8188 		}
8189 		/* Unexport */
8190 		if (cur->flg_export) {
8191 			debug_printf_env("unexporting nested '%s'/%u\n", cur->varstr, cur->var_nest_level);
8192 			bb_unsetenv(cur->varstr);
8193 		}
8194 		/* Remove from global list */
8195 		*cur_pp = cur->next;
8196 		/* Free */
8197 		if (!cur->max_len) {
8198 			debug_printf_env("freeing nested '%s'/%u\n", cur->varstr, cur->var_nest_level);
8199 			free(cur->varstr);
8200 		}
8201 		free(cur);
8202 	}
8203 }
8204 
enter_var_nest_level(void)8205 static void enter_var_nest_level(void)
8206 {
8207 	G.var_nest_level++;
8208 	debug_printf_env("var_nest_level++ %u\n", G.var_nest_level);
8209 
8210 	/* Try:	f() { echo -n .; f; }; f
8211 	 * struct variable::var_nest_level is uint16_t,
8212 	 * thus limiting recursion to < 2^16.
8213 	 * In any case, with 8 Mbyte stack SEGV happens
8214 	 * not too long after 2^16 recursions anyway.
8215 	 */
8216 	if (G.var_nest_level > 0xff00)
8217 		bb_error_msg_and_die("fatal recursion (depth %u)", G.var_nest_level);
8218 }
8219 
leave_var_nest_level(void)8220 static void leave_var_nest_level(void)
8221 {
8222 	G.var_nest_level--;
8223 	debug_printf_env("var_nest_level-- %u\n", G.var_nest_level);
8224 	if (HUSH_DEBUG && (int)G.var_nest_level < 0)
8225 		bb_simple_error_msg_and_die("BUG: nesting underflow");
8226 
8227 	remove_nested_vars();
8228 }
8229 
8230 #if ENABLE_HUSH_FUNCTIONS
find_function_slot(const char * name)8231 static struct function **find_function_slot(const char *name)
8232 {
8233 	struct function *funcp;
8234 	struct function **funcpp = &G.top_func;
8235 
8236 	while ((funcp = *funcpp) != NULL) {
8237 		if (strcmp(name, funcp->name) == 0) {
8238 			debug_printf_exec("found function '%s'\n", name);
8239 			break;
8240 		}
8241 		funcpp = &funcp->next;
8242 	}
8243 	return funcpp;
8244 }
8245 
find_function(const char * name)8246 static ALWAYS_INLINE const struct function *find_function(const char *name)
8247 {
8248 	const struct function *funcp = *find_function_slot(name);
8249 	return funcp;
8250 }
8251 
8252 /* Note: takes ownership on name ptr */
new_function(char * name)8253 static struct function *new_function(char *name)
8254 {
8255 	struct function **funcpp = find_function_slot(name);
8256 	struct function *funcp = *funcpp;
8257 
8258 	if (funcp != NULL) {
8259 		struct command *cmd = funcp->parent_cmd;
8260 		debug_printf_exec("func %p parent_cmd %p\n", funcp, cmd);
8261 		if (!cmd) {
8262 			debug_printf_exec("freeing & replacing function '%s'\n", funcp->name);
8263 			free(funcp->name);
8264 			/* Note: if !funcp->body, do not free body_as_string!
8265 			 * This is a special case of "-F name body" function:
8266 			 * body_as_string was not malloced! */
8267 			if (funcp->body) {
8268 				free_pipe_list(funcp->body);
8269 # if !BB_MMU
8270 				free(funcp->body_as_string);
8271 # endif
8272 			}
8273 		} else {
8274 			debug_printf_exec("reinserting in tree & replacing function '%s'\n", funcp->name);
8275 			cmd->argv[0] = funcp->name;
8276 			cmd->group = funcp->body;
8277 # if !BB_MMU
8278 			cmd->group_as_string = funcp->body_as_string;
8279 # endif
8280 		}
8281 	} else {
8282 		debug_printf_exec("remembering new function '%s'\n", name);
8283 		funcp = *funcpp = xzalloc(sizeof(*funcp));
8284 		/*funcp->next = NULL;*/
8285 	}
8286 
8287 	funcp->name = name;
8288 	return funcp;
8289 }
8290 
8291 # if ENABLE_HUSH_UNSET
unset_func(const char * name)8292 static void unset_func(const char *name)
8293 {
8294 	struct function **funcpp = find_function_slot(name);
8295 	struct function *funcp = *funcpp;
8296 
8297 	if (funcp != NULL) {
8298 		debug_printf_exec("freeing function '%s'\n", funcp->name);
8299 		*funcpp = funcp->next;
8300 		/* funcp is unlinked now, deleting it.
8301 		 * Note: if !funcp->body, the function was created by
8302 		 * "-F name body", do not free ->body_as_string
8303 		 * and ->name as they were not malloced. */
8304 		if (funcp->body) {
8305 			free_pipe_list(funcp->body);
8306 			free(funcp->name);
8307 #  if !BB_MMU
8308 			free(funcp->body_as_string);
8309 #  endif
8310 		}
8311 		free(funcp);
8312 	}
8313 }
8314 # endif
8315 
8316 # if BB_MMU
8317 #define exec_function(to_free, funcp, argv) \
8318 	exec_function(funcp, argv)
8319 # endif
8320 static void exec_function(char ***to_free,
8321 		const struct function *funcp,
8322 		char **argv) NORETURN;
exec_function(char *** to_free,const struct function * funcp,char ** argv)8323 static void exec_function(char ***to_free,
8324 		const struct function *funcp,
8325 		char **argv)
8326 {
8327 # if BB_MMU
8328 	int n;
8329 
8330 	argv[0] = G.global_argv[0];
8331 	G.global_argv = argv;
8332 	G.global_argc = n = 1 + string_array_len(argv + 1);
8333 
8334 // Example when we are here: "cmd | func"
8335 // func will run with saved-redirect fds open.
8336 // $ f() { echo /proc/self/fd/*; }
8337 // $ true | f
8338 // /proc/self/fd/0 /proc/self/fd/1 /proc/self/fd/2 /proc/self/fd/255 /proc/self/fd/3
8339 // stdio^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ G_interactive_fd^ DIR fd for glob
8340 // Same in script:
8341 // $ . ./SCRIPT
8342 // /proc/self/fd/0 /proc/self/fd/1 /proc/self/fd/2 /proc/self/fd/255 /proc/self/fd/3 /proc/self/fd/4
8343 // stdio^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ G_interactive_fd^ opened ./SCRIPT DIR fd for glob
8344 // They are CLOEXEC so external programs won't see them, but
8345 // for "more correctness" we might want to close those extra fds here:
8346 //?	close_saved_fds_and_FILE_fds();
8347 
8348 	/* "we are in a function, ok to use return" */
8349 	G_flag_return_in_progress = -1;
8350 	enter_var_nest_level();
8351 	IF_HUSH_LOCAL(G.func_nest_level++;)
8352 
8353 	/* On MMU, funcp->body is always non-NULL */
8354 	n = run_list(funcp->body);
8355 	_exit(n);
8356 # else
8357 //?	close_saved_fds_and_FILE_fds();
8358 
8359 //TODO: check whether "true | func_with_return" works
8360 
8361 	re_execute_shell(to_free,
8362 			funcp->body_as_string,
8363 			G.global_argv[0],
8364 			argv + 1,
8365 			NULL);
8366 # endif
8367 }
8368 
run_function(const struct function * funcp,char ** argv)8369 static int run_function(const struct function *funcp, char **argv)
8370 {
8371 	int rc;
8372 	save_arg_t sv;
8373 	smallint sv_flg;
8374 
8375 	save_and_replace_G_args(&sv, argv);
8376 
8377 	/* "We are in function, ok to use return" */
8378 	sv_flg = G_flag_return_in_progress;
8379 	G_flag_return_in_progress = -1;
8380 
8381 	/* Make "local" variables properly shadow previous ones */
8382 	IF_HUSH_LOCAL(enter_var_nest_level();)
8383 	IF_HUSH_LOCAL(G.func_nest_level++;)
8384 
8385 	/* On MMU, funcp->body is always non-NULL */
8386 # if !BB_MMU
8387 	if (!funcp->body) {
8388 		/* Function defined by -F */
8389 		parse_and_run_string(funcp->body_as_string);
8390 		rc = G.last_exitcode;
8391 	} else
8392 # endif
8393 	{
8394 		rc = run_list(funcp->body);
8395 	}
8396 
8397 	IF_HUSH_LOCAL(G.func_nest_level--;)
8398 	IF_HUSH_LOCAL(leave_var_nest_level();)
8399 
8400 	G_flag_return_in_progress = sv_flg;
8401 # if ENABLE_HUSH_TRAP
8402 	debug_printf_exec("G.return_exitcode=-1\n");
8403 	G.return_exitcode = -1; /* invalidate stashed return value */
8404 # endif
8405 
8406 	restore_G_args(&sv, argv);
8407 
8408 	return rc;
8409 }
8410 #endif /* ENABLE_HUSH_FUNCTIONS */
8411 
8412 
8413 #if BB_MMU
8414 #define exec_builtin(to_free, x, argv) \
8415 	exec_builtin(x, argv)
8416 #else
8417 #define exec_builtin(to_free, x, argv) \
8418 	exec_builtin(to_free, argv)
8419 #endif
8420 static void exec_builtin(char ***to_free,
8421 		const struct built_in_command *x,
8422 		char **argv) NORETURN;
exec_builtin(char *** to_free,const struct built_in_command * x,char ** argv)8423 static void exec_builtin(char ***to_free,
8424 		const struct built_in_command *x,
8425 		char **argv)
8426 {
8427 #if BB_MMU
8428 	int rcode;
8429 //?	close_saved_fds_and_FILE_fds();
8430 	rcode = x->b_function(argv);
8431 	fflush_all();
8432 	_exit(rcode);
8433 #else
8434 	fflush_all();
8435 	/* On NOMMU, we must never block!
8436 	 * Example: { sleep 99 | read line; } & echo Ok
8437 	 */
8438 	re_execute_shell(to_free,
8439 			argv[0],
8440 			G.global_argv[0],
8441 			G.global_argv + 1,
8442 			argv);
8443 #endif
8444 }
8445 
8446 
8447 static void execvp_or_die(char **argv) NORETURN;
execvp_or_die(char ** argv)8448 static void execvp_or_die(char **argv)
8449 {
8450 	int e;
8451 	debug_printf_exec("execing '%s'\n", argv[0]);
8452 	/* Don't propagate SIG_IGN to the child */
8453 	if (SPECIAL_JOBSTOP_SIGS != 0)
8454 		switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS);
8455 	execvp(argv[0], argv);
8456 	e = 2;
8457 	if (errno == EACCES) e = 126;
8458 	if (errno == ENOENT) e = 127;
8459 	bb_perror_msg("can't execute '%s'", argv[0]);
8460 	_exit(e);
8461 }
8462 
8463 #if ENABLE_HUSH_MODE_X
x_mode_print_optionally_squoted(const char * str)8464 static void x_mode_print_optionally_squoted(const char *str)
8465 {
8466 	unsigned len;
8467 	const char *cp;
8468 
8469 	cp = str;
8470 
8471 	/* the set of chars which-cause-string-to-be-squoted mimics bash */
8472 	/* test a char with: bash -c 'set -x; echo "CH"' */
8473 	if (str[strcspn(str, "\\\"'`$(){}[]<>;#&|~*?!^"
8474 			" " "\001\002\003\004\005\006\007"
8475 			"\010\011\012\013\014\015\016\017"
8476 			"\020\021\022\023\024\025\026\027"
8477 			"\030\031\032\033\034\035\036\037"
8478 			)
8479 		] == '\0'
8480 	) {
8481 		/* string has no special chars */
8482 		x_mode_addstr(str);
8483 		return;
8484 	}
8485 
8486 	cp = str;
8487 	for (;;) {
8488 		/* print '....' up to EOL or first squote */
8489 		len = (int)(strchrnul(cp, '\'') - cp);
8490 		if (len != 0) {
8491 			x_mode_addchr('\'');
8492 			x_mode_addblock(cp, len);
8493 			x_mode_addchr('\'');
8494 			cp += len;
8495 		}
8496 		if (*cp == '\0')
8497 			break;
8498 		/* string contains squote(s), print them as \' */
8499 		x_mode_addchr('\\');
8500 		x_mode_addchr('\'');
8501 		cp++;
8502 	}
8503 }
dump_cmd_in_x_mode(char ** argv)8504 static void dump_cmd_in_x_mode(char **argv)
8505 {
8506 	if (G_x_mode && argv) {
8507 		unsigned n;
8508 
8509 		/* "+[+++...][ cmd...]\n\0" */
8510 		x_mode_prefix();
8511 		n = 0;
8512 		while (argv[n]) {
8513 			x_mode_addchr(' ');
8514 			if (argv[n][0] == '\0') {
8515 				x_mode_addchr('\'');
8516 				x_mode_addchr('\'');
8517 			} else {
8518 				x_mode_print_optionally_squoted(argv[n]);
8519 			}
8520 			n++;
8521 		}
8522 		x_mode_flush();
8523 	}
8524 }
8525 #else
8526 # define dump_cmd_in_x_mode(argv) ((void)0)
8527 #endif
8528 
8529 #if ENABLE_HUSH_COMMAND
if_command_vV_print_and_exit(char opt_vV,char * cmd,const char * explanation)8530 static void if_command_vV_print_and_exit(char opt_vV, char *cmd, const char *explanation)
8531 {
8532 	char *to_free;
8533 
8534 	if (!opt_vV)
8535 		return;
8536 
8537 	to_free = NULL;
8538 	if (!explanation) {
8539 		char *path = getenv("PATH");
8540 		explanation = to_free = find_executable(cmd, &path); /* path == NULL is ok */
8541 		if (!explanation)
8542 			_exit(1); /* PROG was not found */
8543 		if (opt_vV != 'V')
8544 			cmd = to_free; /* -v PROG prints "/path/to/PROG" */
8545 	}
8546 	printf((opt_vV == 'V') ? "%s is %s\n" : "%s\n", cmd, explanation);
8547 	free(to_free);
8548 	fflush_all();
8549 	_exit(0);
8550 }
8551 #else
8552 # define if_command_vV_print_and_exit(a,b,c) ((void)0)
8553 #endif
8554 
8555 #if BB_MMU
8556 #define pseudo_exec_argv(nommu_save, argv, assignment_cnt, argv_expanded) \
8557 	pseudo_exec_argv(argv, assignment_cnt, argv_expanded)
8558 #define pseudo_exec(nommu_save, command, argv_expanded) \
8559 	pseudo_exec(command, argv_expanded)
8560 #endif
8561 
8562 /* Called after [v]fork() in run_pipe, or from builtin_exec.
8563  * Never returns.
8564  * Don't exit() here.  If you don't exec, use _exit instead.
8565  * The at_exit handlers apparently confuse the calling process,
8566  * in particular stdin handling. Not sure why? -- because of vfork! (vda)
8567  */
8568 static void pseudo_exec_argv(nommu_save_t *nommu_save,
8569 		char **argv, int assignment_cnt,
8570 		char **argv_expanded) NORETURN;
pseudo_exec_argv(nommu_save_t * nommu_save,char ** argv,int assignment_cnt,char ** argv_expanded)8571 static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save,
8572 		char **argv, int assignment_cnt,
8573 		char **argv_expanded)
8574 {
8575 	const struct built_in_command *x;
8576 	struct variable **sv_shadowed;
8577 	char **new_env;
8578 	IF_HUSH_COMMAND(char opt_vV = 0;)
8579 	IF_HUSH_FUNCTIONS(const struct function *funcp;)
8580 
8581 	new_env = expand_assignments(argv, assignment_cnt);
8582 	dump_cmd_in_x_mode(new_env);
8583 
8584 	if (!argv[assignment_cnt]) {
8585 		/* Case when we are here: ... | var=val | ...
8586 		 * (note that we do not exit early, i.e., do not optimize out
8587 		 * expand_assignments(): think about ... | var=`sleep 1` | ...
8588 		 */
8589 		free_strings(new_env);
8590 		_exit(EXIT_SUCCESS);
8591 	}
8592 
8593 	sv_shadowed = G.shadowed_vars_pp;
8594 #if BB_MMU
8595 	G.shadowed_vars_pp = NULL; /* "don't save, free them instead" */
8596 #else
8597 	G.shadowed_vars_pp = &nommu_save->old_vars;
8598 	G.var_nest_level++;
8599 #endif
8600 	set_vars_and_save_old(new_env);
8601 	G.shadowed_vars_pp = sv_shadowed;
8602 
8603 	if (argv_expanded) {
8604 		argv = argv_expanded;
8605 	} else {
8606 		argv = expand_strvec_to_strvec(argv + assignment_cnt);
8607 #if !BB_MMU
8608 		nommu_save->argv = argv;
8609 #endif
8610 	}
8611 	dump_cmd_in_x_mode(argv);
8612 
8613 #if ENABLE_FEATURE_SH_STANDALONE || BB_MMU
8614 	if (strchr(argv[0], '/') != NULL)
8615 		goto skip;
8616 #endif
8617 
8618 #if ENABLE_HUSH_FUNCTIONS
8619 	/* Check if the command matches any functions (this goes before bltins) */
8620 	funcp = find_function(argv[0]);
8621 	if (funcp)
8622 		exec_function(&nommu_save->argv_from_re_execing, funcp, argv);
8623 #endif
8624 
8625 #if ENABLE_HUSH_COMMAND
8626 	/* "command BAR": run BAR without looking it up among functions
8627 	 * "command -v BAR": print "BAR" or "/path/to/BAR"; or exit 1
8628 	 * "command -V BAR": print "BAR is {a function,a shell builtin,/path/to/BAR}"
8629 	 */
8630 	while (strcmp(argv[0], "command") == 0 && argv[1]) {
8631 		char *p;
8632 
8633 		argv++;
8634 		p = *argv;
8635 		if (p[0] != '-' || !p[1])
8636 			continue; /* bash allows "command command command [-OPT] BAR" */
8637 
8638 		for (;;) {
8639 			p++;
8640 			switch (*p) {
8641 			case '\0':
8642 				argv++;
8643 				p = *argv;
8644 				if (p[0] != '-' || !p[1])
8645 					goto after_opts;
8646 				continue; /* next arg is also -opts, process it too */
8647 			case 'v':
8648 			case 'V':
8649 				opt_vV = *p;
8650 				continue;
8651 			default:
8652 				bb_error_msg_and_die("%s: %s: invalid option", "command", argv[0]);
8653 			}
8654 		}
8655 	}
8656  after_opts:
8657 # if ENABLE_HUSH_FUNCTIONS
8658 	if (opt_vV && find_function(argv[0]))
8659 		if_command_vV_print_and_exit(opt_vV, argv[0], "a function");
8660 # endif
8661 #endif
8662 
8663 	/* Check if the command matches any of the builtins.
8664 	 * Depending on context, this might be redundant.  But it's
8665 	 * easier to waste a few CPU cycles than it is to figure out
8666 	 * if this is one of those cases.
8667 	 */
8668 	/* Why "BB_MMU ? :" difference in logic? -
8669 	 * On NOMMU, it is more expensive to re-execute shell
8670 	 * just in order to run echo or test builtin.
8671 	 * It's better to skip it here and run corresponding
8672 	 * non-builtin later. */
8673 	x = BB_MMU ? find_builtin(argv[0]) : find_builtin1(argv[0]);
8674 	if (x) {
8675 		if_command_vV_print_and_exit(opt_vV, argv[0], "a shell builtin");
8676 		exec_builtin(&nommu_save->argv_from_re_execing, x, argv);
8677 	}
8678 
8679 #if ENABLE_FEATURE_SH_STANDALONE
8680 	/* Check if the command matches any busybox applets */
8681 	{
8682 		int a = find_applet_by_name(argv[0]);
8683 		if (a >= 0) {
8684 			if_command_vV_print_and_exit(opt_vV, argv[0], "an applet");
8685 # if BB_MMU /* see above why on NOMMU it is not allowed */
8686 			if (APPLET_IS_NOEXEC(a)) {
8687 				/* Do not leak open fds from opened script files etc.
8688 				 * Testcase: interactive "ls -l /proc/self/fd"
8689 				 * should not show tty fd open.
8690 				 */
8691 				close_saved_fds_and_FILE_fds();
8692 //FIXME: should also close saved redir fds
8693 //This casuses test failures in
8694 //redir_children_should_not_see_saved_fd_2.tests
8695 //redir_children_should_not_see_saved_fd_3.tests
8696 //if you replace "busybox find" with just "find" in them
8697 				/* Without this, "rm -i FILE" can't be ^C'ed: */
8698 				switch_off_special_sigs(G.special_sig_mask);
8699 				debug_printf_exec("running applet '%s'\n", argv[0]);
8700 				run_noexec_applet_and_exit(a, argv[0], argv);
8701 			}
8702 # endif
8703 			/* Re-exec ourselves */
8704 			debug_printf_exec("re-execing applet '%s'\n", argv[0]);
8705 			/* Don't propagate SIG_IGN to the child */
8706 			if (SPECIAL_JOBSTOP_SIGS != 0)
8707 				switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS);
8708 			execv(bb_busybox_exec_path, argv);
8709 			/* If they called chroot or otherwise made the binary no longer
8710 			 * executable, fall through */
8711 		}
8712 	}
8713 #endif
8714 
8715 #if ENABLE_FEATURE_SH_STANDALONE || BB_MMU
8716  skip:
8717 #endif
8718 	if_command_vV_print_and_exit(opt_vV, argv[0], NULL);
8719 	execvp_or_die(argv);
8720 }
8721 
8722 /* Called after [v]fork() in run_pipe
8723  */
8724 static void pseudo_exec(nommu_save_t *nommu_save,
8725 		struct command *command,
8726 		char **argv_expanded) NORETURN;
pseudo_exec(nommu_save_t * nommu_save,struct command * command,char ** argv_expanded)8727 static void pseudo_exec(nommu_save_t *nommu_save,
8728 		struct command *command,
8729 		char **argv_expanded)
8730 {
8731 #if ENABLE_HUSH_FUNCTIONS
8732 	if (command->cmd_type == CMD_FUNCDEF) {
8733 		/* Ignore funcdefs in pipes:
8734 		 * true | f() { cmd }
8735 		 */
8736 		_exit(0);
8737 	}
8738 #endif
8739 
8740 	if (command->argv) {
8741 		pseudo_exec_argv(nommu_save, command->argv,
8742 				command->assignment_cnt, argv_expanded);
8743 	}
8744 
8745 	if (command->group) {
8746 		/* Cases when we are here:
8747 		 * ( list )
8748 		 * { list } &
8749 		 * ... | ( list ) | ...
8750 		 * ... | { list } | ...
8751 		 */
8752 #if BB_MMU
8753 		int rcode;
8754 		debug_printf_exec("pseudo_exec: run_list\n");
8755 		reset_traps_to_defaults();
8756 		rcode = run_list(command->group);
8757 		/* OK to leak memory by not calling free_pipe_list,
8758 		 * since this process is about to exit */
8759 		_exit(rcode);
8760 #else
8761 		re_execute_shell(&nommu_save->argv_from_re_execing,
8762 				command->group_as_string,
8763 				G.global_argv[0],
8764 				G.global_argv + 1,
8765 				NULL);
8766 #endif
8767 	}
8768 
8769 	/* Case when we are here: ... | >file */
8770 	debug_printf_exec("pseudo_exec'ed null command\n");
8771 	_exit(EXIT_SUCCESS);
8772 }
8773 
8774 #if ENABLE_HUSH_JOB
get_cmdtext(struct pipe * pi)8775 static const char *get_cmdtext(struct pipe *pi)
8776 {
8777 	char **argv;
8778 	char *p;
8779 	int len;
8780 
8781 	/* This is subtle. ->cmdtext is created only on first backgrounding.
8782 	 * (Think "cat, <ctrl-z>, fg, <ctrl-z>, fg, <ctrl-z>...." here...)
8783 	 * On subsequent bg argv is trashed, but we won't use it */
8784 	if (pi->cmdtext)
8785 		return pi->cmdtext;
8786 
8787 	argv = pi->cmds[0].argv;
8788 	if (!argv) {
8789 		pi->cmdtext = xzalloc(1);
8790 		return pi->cmdtext;
8791 	}
8792 	len = 0;
8793 	do {
8794 		len += strlen(*argv) + 1;
8795 	} while (*++argv);
8796 	p = xmalloc(len);
8797 	pi->cmdtext = p;
8798 	argv = pi->cmds[0].argv;
8799 	do {
8800 		p = stpcpy(p, *argv);
8801 		*p++ = ' ';
8802 	} while (*++argv);
8803 	p[-1] = '\0';
8804 	return pi->cmdtext;
8805 }
8806 
remove_job_from_table(struct pipe * pi)8807 static void remove_job_from_table(struct pipe *pi)
8808 {
8809 	struct pipe *prev_pipe;
8810 
8811 	if (pi == G.job_list) {
8812 		G.job_list = pi->next;
8813 	} else {
8814 		prev_pipe = G.job_list;
8815 		while (prev_pipe->next != pi)
8816 			prev_pipe = prev_pipe->next;
8817 		prev_pipe->next = pi->next;
8818 	}
8819 	G.last_jobid = 0;
8820 	if (G.job_list)
8821 		G.last_jobid = G.job_list->jobid;
8822 }
8823 
delete_finished_job(struct pipe * pi)8824 static void delete_finished_job(struct pipe *pi)
8825 {
8826 	remove_job_from_table(pi);
8827 	free_pipe(pi);
8828 }
8829 
clean_up_last_dead_job(void)8830 static void clean_up_last_dead_job(void)
8831 {
8832 	if (G.job_list && !G.job_list->alive_cmds)
8833 		delete_finished_job(G.job_list);
8834 }
8835 
insert_job_into_table(struct pipe * pi)8836 static void insert_job_into_table(struct pipe *pi)
8837 {
8838 	struct pipe *job, **jobp;
8839 	int i;
8840 
8841 	clean_up_last_dead_job();
8842 
8843 	/* Find the end of the list, and find next job ID to use */
8844 	i = 0;
8845 	jobp = &G.job_list;
8846 	while ((job = *jobp) != NULL) {
8847 		if (job->jobid > i)
8848 			i = job->jobid;
8849 		jobp = &job->next;
8850 	}
8851 	pi->jobid = i + 1;
8852 
8853 	/* Create a new job struct at the end */
8854 	job = *jobp = xmemdup(pi, sizeof(*pi));
8855 	job->next = NULL;
8856 	job->cmds = xzalloc(sizeof(pi->cmds[0]) * pi->num_cmds);
8857 	/* Cannot copy entire pi->cmds[] vector! This causes double frees */
8858 	for (i = 0; i < pi->num_cmds; i++) {
8859 		job->cmds[i].pid = pi->cmds[i].pid;
8860 		/* all other fields are not used and stay zero */
8861 	}
8862 	job->cmdtext = xstrdup(get_cmdtext(pi));
8863 
8864 	if (G_interactive_fd)
8865 		printf("[%u] %u %s\n", job->jobid, (unsigned)job->cmds[0].pid, job->cmdtext);
8866 	G.last_jobid = job->jobid;
8867 }
8868 #endif /* JOB */
8869 
job_exited_or_stopped(struct pipe * pi)8870 static int job_exited_or_stopped(struct pipe *pi)
8871 {
8872 	int rcode, i;
8873 
8874 	if (pi->alive_cmds != pi->stopped_cmds)
8875 		return -1;
8876 
8877 	/* All processes in fg pipe have exited or stopped */
8878 	rcode = 0;
8879 	i = pi->num_cmds;
8880 	while (--i >= 0) {
8881 		rcode = pi->cmds[i].cmd_exitcode;
8882 		/* usually last process gives overall exitstatus,
8883 		 * but with "set -o pipefail", last *failed* process does */
8884 		if (G.o_opt[OPT_O_PIPEFAIL] == 0 || rcode != 0)
8885 			break;
8886 	}
8887 	IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
8888 	return rcode;
8889 }
8890 
process_wait_result(struct pipe * fg_pipe,pid_t childpid,int status)8891 static int process_wait_result(struct pipe *fg_pipe, pid_t childpid, int status)
8892 {
8893 #if ENABLE_HUSH_JOB
8894 	struct pipe *pi;
8895 #endif
8896 	int i, dead;
8897 
8898 	dead = WIFEXITED(status) || WIFSIGNALED(status);
8899 
8900 #if DEBUG_JOBS
8901 	if (WIFSTOPPED(status))
8902 		debug_printf_jobs("pid %d stopped by sig %d (exitcode %d)\n",
8903 				childpid, WSTOPSIG(status), WEXITSTATUS(status));
8904 	if (WIFSIGNALED(status))
8905 		debug_printf_jobs("pid %d killed by sig %d (exitcode %d)\n",
8906 				childpid, WTERMSIG(status), WEXITSTATUS(status));
8907 	if (WIFEXITED(status))
8908 		debug_printf_jobs("pid %d exited, exitcode %d\n",
8909 				childpid, WEXITSTATUS(status));
8910 #endif
8911 	/* Were we asked to wait for a fg pipe? */
8912 	if (fg_pipe) {
8913 		i = fg_pipe->num_cmds;
8914 
8915 		while (--i >= 0) {
8916 			int rcode;
8917 
8918 			debug_printf_jobs("check pid %d\n", fg_pipe->cmds[i].pid);
8919 			if (fg_pipe->cmds[i].pid != childpid)
8920 				continue;
8921 			if (dead) {
8922 				int ex;
8923 				fg_pipe->cmds[i].pid = 0;
8924 				fg_pipe->alive_cmds--;
8925 				ex = WEXITSTATUS(status);
8926 				/* bash prints killer signal's name for *last*
8927 				 * process in pipe (prints just newline for SIGINT/SIGPIPE).
8928 				 * Mimic this. Example: "sleep 5" + (^\ or kill -QUIT)
8929 				 */
8930 				if (WIFSIGNALED(status)) {
8931 					int sig = WTERMSIG(status);
8932 #if ENABLE_HUSH_JOB
8933 					if (G.run_list_level == 1
8934 					/* ^^^^^ Do not print in nested contexts, example:
8935 					 * echo `sleep 1; sh -c 'kill -9 $$'` - prints "137", NOT "Killed 137"
8936 					 */
8937 					 && i == fg_pipe->num_cmds-1
8938 					) {
8939 						/* strsignal() is for bash compat. ~600 bloat versus bbox's get_signame() */
8940 						puts(sig == SIGINT || sig == SIGPIPE ? "" : strsignal(sig));
8941 					}
8942 #endif
8943 					/* TODO: if (WCOREDUMP(status)) + " (core dumped)"; */
8944 					/* MIPS has 128 sigs (1..128), if sig==128,
8945 					 * 128 + sig would result in exitcode 256 -> 0!
8946 					 */
8947 					ex = 128 | sig;
8948 				}
8949 				fg_pipe->cmds[i].cmd_exitcode = ex;
8950 			} else {
8951 				fg_pipe->stopped_cmds++;
8952 			}
8953 			debug_printf_jobs("fg_pipe: alive_cmds %d stopped_cmds %d\n",
8954 					fg_pipe->alive_cmds, fg_pipe->stopped_cmds);
8955 			rcode = job_exited_or_stopped(fg_pipe);
8956 			if (rcode >= 0) {
8957 /* Note: *non-interactive* bash does not continue if all processes in fg pipe
8958  * are stopped. Testcase: "cat | cat" in a script (not on command line!)
8959  * and "killall -STOP cat" */
8960 				if (G_interactive_fd) {
8961 #if ENABLE_HUSH_JOB
8962 					if (fg_pipe->alive_cmds != 0)
8963 						insert_job_into_table(fg_pipe);
8964 #endif
8965 					return rcode;
8966 				}
8967 				if (fg_pipe->alive_cmds == 0)
8968 					return rcode;
8969 			}
8970 			/* There are still running processes in the fg_pipe */
8971 			return -1;
8972 		}
8973 		/* It wasn't in fg_pipe, look for process in bg pipes */
8974 	}
8975 
8976 #if ENABLE_HUSH_JOB
8977 	/* We were asked to wait for bg or orphaned children */
8978 	/* No need to remember exitcode in this case */
8979 	for (pi = G.job_list; pi; pi = pi->next) {
8980 		for (i = 0; i < pi->num_cmds; i++) {
8981 			if (pi->cmds[i].pid == childpid)
8982 				goto found_pi_and_prognum;
8983 		}
8984 	}
8985 	/* Happens when shell is used as init process (init=/bin/sh) */
8986 	debug_printf("checkjobs: pid %d was not in our list!\n", childpid);
8987 	return -1; /* this wasn't a process from fg_pipe */
8988 
8989  found_pi_and_prognum:
8990 	if (dead) {
8991 		/* child exited */
8992 		int rcode = WEXITSTATUS(status);
8993 		if (WIFSIGNALED(status))
8994 			/* NB: not 128 + sig, MIPS has sig 128 */
8995 			rcode = 128 | WTERMSIG(status);
8996 		pi->cmds[i].cmd_exitcode = rcode;
8997 		if (G.last_bg_pid == pi->cmds[i].pid)
8998 			G.last_bg_pid_exitcode = rcode;
8999 		pi->cmds[i].pid = 0;
9000 		pi->alive_cmds--;
9001 		if (!pi->alive_cmds) {
9002 # if ENABLE_HUSH_BASH_COMPAT
9003 			G.dead_job_exitcode = job_exited_or_stopped(pi);
9004 # endif
9005 			if (G_interactive_fd) {
9006 				printf(JOB_STATUS_FORMAT, pi->jobid,
9007 						"Done", pi->cmdtext);
9008 				delete_finished_job(pi);
9009 			} else {
9010 /*
9011  * bash deletes finished jobs from job table only in interactive mode,
9012  * after "jobs" cmd, or if pid of a new process matches one of the old ones
9013  * (see cleanup_dead_jobs(), delete_old_job(), J_NOTIFIED in bash source).
9014  * Testcase script: "(exit 3) & sleep 1; wait %1; echo $?" prints 3 in bash.
9015  * We only retain one "dead" job, if it's the single job on the list.
9016  * This covers most of real-world scenarios where this is useful.
9017  */
9018 				if (pi != G.job_list)
9019 					delete_finished_job(pi);
9020 			}
9021 		}
9022 	} else {
9023 		/* child stopped */
9024 		pi->stopped_cmds++;
9025 	}
9026 #endif
9027 	return -1; /* this wasn't a process from fg_pipe */
9028 }
9029 
9030 /* Check to see if any processes have exited -- if they have,
9031  * figure out why and see if a job has completed.
9032  *
9033  * If non-NULL fg_pipe: wait for its completion or stop.
9034  * Return its exitcode or zero if stopped.
9035  *
9036  * Alternatively (fg_pipe == NULL, waitfor_pid != 0):
9037  * waitpid(WNOHANG), if waitfor_pid exits or stops, return exitcode+1,
9038  * else return <0 if waitpid errors out (e.g. ECHILD: nothing to wait for)
9039  * or 0 if no children changed status.
9040  *
9041  * Alternatively (fg_pipe == NULL, waitfor_pid == 0),
9042  * return <0 if waitpid errors out (e.g. ECHILD: nothing to wait for)
9043  * or 0 if no children changed status.
9044  */
checkjobs(struct pipe * fg_pipe,pid_t waitfor_pid)9045 static int checkjobs(struct pipe *fg_pipe, pid_t waitfor_pid)
9046 {
9047 	int attributes;
9048 	int status;
9049 	int rcode = 0;
9050 
9051 	debug_printf_jobs("checkjobs %p\n", fg_pipe);
9052 
9053 	attributes = WUNTRACED;
9054 	if (fg_pipe == NULL)
9055 		attributes |= WNOHANG;
9056 
9057 	errno = 0;
9058 #if ENABLE_HUSH_FAST
9059 	if (G.handled_SIGCHLD == G.count_SIGCHLD) {
9060 //bb_error_msg("[%d] checkjobs: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d children?:%d fg_pipe:%p",
9061 //getpid(), G.count_SIGCHLD, G.handled_SIGCHLD, G.we_have_children, fg_pipe);
9062 		/* There was neither fork nor SIGCHLD since last waitpid */
9063 		/* Avoid doing waitpid syscall if possible */
9064 		if (!G.we_have_children) {
9065 			errno = ECHILD;
9066 			return -1;
9067 		}
9068 		if (fg_pipe == NULL) { /* is WNOHANG set? */
9069 			/* We have children, but they did not exit
9070 			 * or stop yet (we saw no SIGCHLD) */
9071 			return 0;
9072 		}
9073 		/* else: !WNOHANG, waitpid will block, can't short-circuit */
9074 	}
9075 #endif
9076 
9077 /* Do we do this right?
9078  * bash-3.00# sleep 20 | false
9079  * <ctrl-Z pressed>
9080  * [3]+  Stopped          sleep 20 | false
9081  * bash-3.00# echo $?
9082  * 1   <========== bg pipe is not fully done, but exitcode is already known!
9083  * [hush 1.14.0: yes we do it right]
9084  */
9085 	while (1) {
9086 		pid_t childpid;
9087 #if ENABLE_HUSH_FAST
9088 		int i;
9089 		i = G.count_SIGCHLD;
9090 #endif
9091 		childpid = waitpid(-1, &status, attributes);
9092 		if (childpid <= 0) {
9093 			if (childpid && errno != ECHILD)
9094 				bb_simple_perror_msg("waitpid");
9095 #if ENABLE_HUSH_FAST
9096 			else { /* Until next SIGCHLD, waitpid's are useless */
9097 				G.we_have_children = (childpid == 0);
9098 				G.handled_SIGCHLD = i;
9099 //bb_error_msg("[%d] checkjobs: waitpid returned <= 0, G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
9100 			}
9101 #endif
9102 			/* ECHILD (no children), or 0 (no change in children status) */
9103 			rcode = childpid;
9104 			break;
9105 		}
9106 		rcode = process_wait_result(fg_pipe, childpid, status);
9107 		if (rcode >= 0) {
9108 			/* fg_pipe exited or stopped */
9109 			break;
9110 		}
9111 		if (childpid == waitfor_pid) { /* "wait PID" */
9112 			debug_printf_exec("childpid==waitfor_pid:%d status:0x%08x\n", childpid, status);
9113 			rcode = WEXITSTATUS(status);
9114 			if (WIFSIGNALED(status))
9115 				rcode = 128 | WTERMSIG(status);
9116 			if (WIFSTOPPED(status))
9117 				/* bash: "cmd & wait $!" and cmd stops: $? = 128 | stopsig */
9118 				rcode = 128 | WSTOPSIG(status);
9119 			rcode++;
9120 			break; /* "wait PID" called us, give it exitcode+1 */
9121 		}
9122 #if ENABLE_HUSH_BASH_COMPAT
9123 		if (-1 == waitfor_pid /* "wait -n" (wait for any one job) */
9124 		 && G.dead_job_exitcode >= 0 /* some job did finish */
9125 		) {
9126 			debug_printf_exec("waitfor_pid:-1\n");
9127 			rcode = G.dead_job_exitcode + 1;
9128 			break;
9129 		}
9130 #endif
9131 		/* This wasn't one of our processes, or */
9132 		/* fg_pipe still has running processes, do waitpid again */
9133 	} /* while (waitpid succeeds)... */
9134 
9135 	return rcode;
9136 }
9137 
9138 #if ENABLE_HUSH_JOB
checkjobs_and_fg_shell(struct pipe * fg_pipe)9139 static int checkjobs_and_fg_shell(struct pipe *fg_pipe)
9140 {
9141 	pid_t p;
9142 	int rcode = checkjobs(fg_pipe, 0 /*(no pid to wait for)*/);
9143 	if (G_saved_tty_pgrp) {
9144 		/* Job finished, move the shell to the foreground */
9145 		p = getpgrp(); /* our process group id */
9146 		debug_printf_jobs("fg'ing ourself: getpgrp()=%d\n", (int)p);
9147 		tcsetpgrp(G_interactive_fd, p);
9148 	}
9149 	return rcode;
9150 }
9151 #endif
9152 
9153 /* Start all the jobs, but don't wait for anything to finish.
9154  * See checkjobs().
9155  *
9156  * Return code is normally -1, when the caller has to wait for children
9157  * to finish to determine the exit status of the pipe.  If the pipe
9158  * is a simple builtin command, however, the action is done by the
9159  * time run_pipe returns, and the exit code is provided as the
9160  * return value.
9161  *
9162  * Returns -1 only if started some children. IOW: we have to
9163  * mask out retvals of builtins etc with 0xff!
9164  *
9165  * The only case when we do not need to [v]fork is when the pipe
9166  * is single, non-backgrounded, non-subshell command. Examples:
9167  * cmd ; ...   { list } ; ...
9168  * cmd && ...  { list } && ...
9169  * cmd || ...  { list } || ...
9170  * If it is, then we can run cmd as a builtin, NOFORK,
9171  * or (if SH_STANDALONE) an applet, and we can run the { list }
9172  * with run_list. If it isn't one of these, we fork and exec cmd.
9173  *
9174  * Cases when we must fork:
9175  * non-single:   cmd | cmd
9176  * backgrounded: cmd &     { list } &
9177  * subshell:     ( list ) [&]
9178  */
9179 #if !ENABLE_HUSH_MODE_X
9180 #define redirect_and_varexp_helper(command, sqp, argv_expanded) \
9181 	redirect_and_varexp_helper(command, sqp)
9182 #endif
redirect_and_varexp_helper(struct command * command,struct squirrel ** sqp,char ** argv_expanded)9183 static int redirect_and_varexp_helper(
9184 		struct command *command,
9185 		struct squirrel **sqp,
9186 		char **argv_expanded)
9187 {
9188 	/* Assignments occur before redirects. Try:
9189 	 * a=`sleep 1` sleep 2 3>/qwe/rty
9190 	 */
9191 
9192 	char **new_env = expand_assignments(command->argv, command->assignment_cnt);
9193 	dump_cmd_in_x_mode(new_env);
9194 	dump_cmd_in_x_mode(argv_expanded);
9195 	/* this takes ownership of new_env[i] elements, and frees new_env: */
9196 	set_vars_and_save_old(new_env);
9197 
9198 	return setup_redirects(command, sqp);
9199 }
run_pipe(struct pipe * pi)9200 static NOINLINE int run_pipe(struct pipe *pi)
9201 {
9202 	static const char *const null_ptr = NULL;
9203 
9204 	int cmd_no;
9205 	int next_infd;
9206 	struct command *command;
9207 	char **argv_expanded;
9208 	char **argv;
9209 	struct squirrel *squirrel = NULL;
9210 	int rcode;
9211 
9212 	debug_printf_exec("run_pipe start: members:%d\n", pi->num_cmds);
9213 	debug_enter();
9214 
9215 	/* Testcase: set -- q w e; (IFS='' echo "$*"; IFS=''; echo "$*"); echo "$*"
9216 	 * Result should be 3 lines: q w e, qwe, q w e
9217 	 */
9218 	if (G.ifs_whitespace != G.ifs)
9219 		free(G.ifs_whitespace);
9220 	G.ifs = get_local_var_value("IFS");
9221 	if (G.ifs) {
9222 		char *p;
9223 		G.ifs_whitespace = (char*)G.ifs;
9224 		p = skip_whitespace(G.ifs);
9225 		if (*p) {
9226 			/* Not all $IFS is whitespace */
9227 			char *d;
9228 			int len = p - G.ifs;
9229 			p = skip_non_whitespace(p);
9230 			G.ifs_whitespace = xmalloc(len + strlen(p) + 1); /* can overestimate */
9231 			d = mempcpy(G.ifs_whitespace, G.ifs, len);
9232 			while (*p) {
9233 				if (isspace(*p))
9234 					*d++ = *p;
9235 				p++;
9236 			}
9237 			*d = '\0';
9238 		}
9239 	} else {
9240 		G.ifs = defifs;
9241 		G.ifs_whitespace = (char*)G.ifs;
9242 	}
9243 
9244 	IF_HUSH_JOB(pi->pgrp = -1;)
9245 	pi->stopped_cmds = 0;
9246 	command = &pi->cmds[0];
9247 	argv_expanded = NULL;
9248 
9249 	if (pi->num_cmds != 1
9250 	 || pi->followup == PIPE_BG
9251 	 || command->cmd_type == CMD_SUBSHELL
9252 	) {
9253 		goto must_fork;
9254 	}
9255 
9256 	pi->alive_cmds = 1;
9257 
9258 	debug_printf_exec(": group:%p argv:'%s'\n",
9259 		command->group, command->argv ? command->argv[0] : "NONE");
9260 
9261 	if (command->group) {
9262 #if ENABLE_HUSH_FUNCTIONS
9263 		if (command->cmd_type == CMD_FUNCDEF) {
9264 			/* "executing" func () { list } */
9265 			struct function *funcp;
9266 
9267 			funcp = new_function(command->argv[0]);
9268 			/* funcp->name is already set to argv[0] */
9269 			funcp->body = command->group;
9270 # if !BB_MMU
9271 			funcp->body_as_string = command->group_as_string;
9272 			command->group_as_string = NULL;
9273 # endif
9274 			command->group = NULL;
9275 			command->argv[0] = NULL;
9276 			debug_printf_exec("cmd %p has child func at %p\n", command, funcp);
9277 			funcp->parent_cmd = command;
9278 			command->child_func = funcp;
9279 
9280 			debug_printf_exec("run_pipe: return EXIT_SUCCESS\n");
9281 			debug_leave();
9282 			return EXIT_SUCCESS;
9283 		}
9284 #endif
9285 		/* { list } */
9286 		debug_printf_exec("non-subshell group\n");
9287 		rcode = 1; /* exitcode if redir failed */
9288 		if (setup_redirects(command, &squirrel) == 0) {
9289 			debug_printf_exec(": run_list\n");
9290 //FIXME: we need to pass squirrel down into run_list()
9291 //for SH_STANDALONE case, or else this construct:
9292 // { find /proc/self/fd; true; } >FILE; cmd2
9293 //has no way of closing saved fd#1 for "find",
9294 //and in SH_STANDALONE mode, "find" is not execed,
9295 //therefore CLOEXEC on saved fd does not help.
9296 			rcode = run_list(command->group) & 0xff;
9297 		}
9298 		restore_redirects(squirrel);
9299 		IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
9300 		debug_leave();
9301 		debug_printf_exec("run_pipe: return %d\n", rcode);
9302 		return rcode;
9303 	}
9304 
9305 	argv = command->argv ? command->argv : (char **) &null_ptr;
9306 	{
9307 		const struct built_in_command *x;
9308 		IF_HUSH_FUNCTIONS(const struct function *funcp;)
9309 		IF_NOT_HUSH_FUNCTIONS(enum { funcp = 0 };)
9310 		struct variable **sv_shadowed;
9311 		struct variable *old_vars;
9312 
9313 #if ENABLE_HUSH_LINENO_VAR
9314 		G.execute_lineno = command->lineno;
9315 #endif
9316 
9317 		if (argv[command->assignment_cnt] == NULL) {
9318 			/* Assignments, but no command.
9319 			 * Ensure redirects take effect (that is, create files).
9320 			 * Try "a=t >file"
9321 			 */
9322 			unsigned i;
9323 			G.expand_exitcode = 0;
9324  only_assignments:
9325 			rcode = setup_redirects(command, &squirrel);
9326 			restore_redirects(squirrel);
9327 
9328 			/* Set shell variables */
9329 			i = 0;
9330 			while (i < command->assignment_cnt) {
9331 				char *p = expand_string_to_string(argv[i],
9332 						EXP_FLAG_ESC_GLOB_CHARS,
9333 						/*unbackslash:*/ 1
9334 				);
9335 #if ENABLE_HUSH_MODE_X
9336 				if (G_x_mode) {
9337 					char *eq;
9338 					if (i == 0)
9339 						x_mode_prefix();
9340 					x_mode_addchr(' ');
9341 					eq = strchrnul(p, '=');
9342 					if (*eq) eq++;
9343 					x_mode_addblock(p, (eq - p));
9344 					x_mode_print_optionally_squoted(eq);
9345 					x_mode_flush();
9346 				}
9347 #endif
9348 				debug_printf_env("set shell var:'%s'->'%s'\n", *argv, p);
9349 				if (set_local_var(p, /*flag:*/ 0)) {
9350 					/* assignment to readonly var / putenv error? */
9351 					rcode = 1;
9352 				}
9353 				i++;
9354 			}
9355 			/* Redirect error sets $? to 1. Otherwise,
9356 			 * if evaluating assignment value set $?, retain it.
9357 			 * Else, clear $?:
9358 			 *  false; q=`exit 2`; echo $? - should print 2
9359 			 *  false; x=1; echo $? - should print 0
9360 			 * Because of the 2nd case, we can't just use G.last_exitcode.
9361 			 */
9362 			if (rcode == 0)
9363 				rcode = G.expand_exitcode;
9364 			IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
9365 			debug_leave();
9366 			debug_printf_exec("run_pipe: return %d\n", rcode);
9367 			return rcode;
9368 		}
9369 
9370 		/* Expand the rest into (possibly) many strings each */
9371 #if defined(CMD_TEST2_SINGLEWORD_NOGLOB)
9372 		if (command->cmd_type == CMD_TEST2_SINGLEWORD_NOGLOB)
9373 			argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt);
9374 		else
9375 #endif
9376 #if defined(CMD_SINGLEWORD_NOGLOB)
9377 		if (command->cmd_type == CMD_SINGLEWORD_NOGLOB)
9378 			argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt);
9379 		else
9380 #endif
9381 			argv_expanded = expand_strvec_to_strvec(argv + command->assignment_cnt);
9382 
9383 		/* If someone gives us an empty string: `cmd with empty output` */
9384 		if (!argv_expanded[0]) {
9385 			free(argv_expanded);
9386 			/* `false` still has to set exitcode 1 */
9387 			G.expand_exitcode = G.last_exitcode;
9388 			goto only_assignments;
9389 		}
9390 
9391 		old_vars = NULL;
9392 		sv_shadowed = G.shadowed_vars_pp;
9393 
9394 		/* Check if argv[0] matches any functions (this goes before bltins) */
9395 		IF_HUSH_FUNCTIONS(funcp = find_function(argv_expanded[0]);)
9396 		IF_HUSH_FUNCTIONS(x = NULL;)
9397 		IF_HUSH_FUNCTIONS(if (!funcp))
9398 			x = find_builtin(argv_expanded[0]);
9399 		if (x || funcp) {
9400 			if (x && x->b_function == builtin_exec && argv_expanded[1] == NULL) {
9401 				debug_printf("exec with redirects only\n");
9402 				/*
9403 				 * Variable assignments are executed, but then "forgotten":
9404 				 *  a=`sleep 1;echo A` exec 3>&-; echo $a
9405 				 * sleeps, but prints nothing.
9406 				 */
9407 				enter_var_nest_level();
9408 				G.shadowed_vars_pp = &old_vars;
9409 				rcode = redirect_and_varexp_helper(command,
9410 					/*squirrel:*/ ERR_PTR,
9411 					argv_expanded
9412 				);
9413 				G.shadowed_vars_pp = sv_shadowed;
9414 				/* rcode=1 can be if redir file can't be opened */
9415 
9416 				goto clean_up_and_ret1;
9417 			}
9418 
9419 			/* Bump var nesting, or this will leak exported $a:
9420 			 * a=b true; env | grep ^a=
9421 			 */
9422 			enter_var_nest_level();
9423 			/* Collect all variables "shadowed" by helper
9424 			 * (IOW: old vars overridden by "var1=val1 var2=val2 cmd..." syntax)
9425 			 * into old_vars list:
9426 			 */
9427 			G.shadowed_vars_pp = &old_vars;
9428 			rcode = redirect_and_varexp_helper(command, &squirrel, argv_expanded);
9429 			if (rcode == 0) {
9430 				if (!funcp) {
9431 					/* Do not collect *to old_vars list* vars shadowed
9432 					 * by e.g. "local VAR" builtin (collect them
9433 					 * in the previously nested list instead):
9434 					 * don't want them to be restored immediately
9435 					 * after "local" completes.
9436 					 */
9437 					G.shadowed_vars_pp = sv_shadowed;
9438 
9439 					debug_printf_exec(": builtin '%s' '%s'...\n",
9440 						x->b_cmd, argv_expanded[1]);
9441 					fflush_all();
9442 					rcode = x->b_function(argv_expanded) & 0xff;
9443 					fflush_all();
9444 				}
9445 #if ENABLE_HUSH_FUNCTIONS
9446 				else {
9447 					debug_printf_exec(": function '%s' '%s'...\n",
9448 						funcp->name, argv_expanded[1]);
9449 					rcode = run_function(funcp, argv_expanded) & 0xff;
9450 					/*
9451 					 * But do collect *to old_vars list* vars shadowed
9452 					 * within function execution. To that end, restore
9453 					 * this pointer _after_ function run:
9454 					 */
9455 					G.shadowed_vars_pp = sv_shadowed;
9456 				}
9457 #endif
9458 			}
9459 		} else
9460 		if (ENABLE_FEATURE_SH_NOFORK && NUM_APPLETS > 1) {
9461 			int n = find_applet_by_name(argv_expanded[0]);
9462 			if (n < 0 || !APPLET_IS_NOFORK(n))
9463 				goto must_fork;
9464 
9465 			enter_var_nest_level();
9466 			/* Collect all variables "shadowed" by helper into old_vars list */
9467 			G.shadowed_vars_pp = &old_vars;
9468 			rcode = redirect_and_varexp_helper(command, &squirrel, argv_expanded);
9469 			G.shadowed_vars_pp = sv_shadowed;
9470 
9471 			if (rcode == 0) {
9472 				debug_printf_exec(": run_nofork_applet '%s' '%s'...\n",
9473 					argv_expanded[0], argv_expanded[1]);
9474 				/*
9475 				 * Note: signals (^C) can't interrupt here.
9476 				 * We remember them and they will be acted upon
9477 				 * after applet returns.
9478 				 * This makes applets which can run for a long time
9479 				 * and/or wait for user input ineligible for NOFORK:
9480 				 * for example, "yes" or "rm" (rm -i waits for input).
9481 				 */
9482 				rcode = run_nofork_applet(n, argv_expanded);
9483 			}
9484 		} else
9485 			goto must_fork;
9486 
9487 		restore_redirects(squirrel);
9488  clean_up_and_ret1:
9489 		leave_var_nest_level();
9490 		add_vars(old_vars);
9491 
9492 		/*
9493 		 * Try "usleep 99999999" + ^C + "echo $?"
9494 		 * with FEATURE_SH_NOFORK=y.
9495 		 */
9496 		if (!funcp) {
9497 			/* It was builtin or nofork.
9498 			 * if this would be a real fork/execed program,
9499 			 * it should have died if a fatal sig was received.
9500 			 * But OTOH, there was no separate process,
9501 			 * the sig was sent to _shell_, not to non-existing
9502 			 * child.
9503 			 * Let's just handle ^C only, this one is obvious:
9504 			 * we aren't ok with exitcode 0 when ^C was pressed
9505 			 * during builtin/nofork.
9506 			 */
9507 			if (sigismember(&G.pending_set, SIGINT))
9508 				rcode = 128 | SIGINT;
9509 		}
9510 		free(argv_expanded);
9511 		IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
9512 		debug_leave();
9513 		debug_printf_exec("run_pipe return %d\n", rcode);
9514 		return rcode;
9515 	}
9516 
9517  must_fork:
9518 	/* NB: argv_expanded may already be created, and that
9519 	 * might include `cmd` runs! Do not rerun it! We *must*
9520 	 * use argv_expanded if it's non-NULL */
9521 
9522 	/* Going to fork a child per each pipe member */
9523 	pi->alive_cmds = 0;
9524 	next_infd = 0;
9525 
9526 	cmd_no = 0;
9527 	while (cmd_no < pi->num_cmds) {
9528 		struct fd_pair pipefds;
9529 #if !BB_MMU
9530 		int sv_var_nest_level = G.var_nest_level;
9531 		volatile nommu_save_t nommu_save;
9532 		nommu_save.old_vars = NULL;
9533 		nommu_save.argv = NULL;
9534 		nommu_save.argv_from_re_execing = NULL;
9535 #endif
9536 		command = &pi->cmds[cmd_no];
9537 		cmd_no++;
9538 		if (command->argv) {
9539 			debug_printf_exec(": pipe member '%s' '%s'...\n",
9540 					command->argv[0], command->argv[1]);
9541 		} else {
9542 			debug_printf_exec(": pipe member with no argv\n");
9543 		}
9544 
9545 		/* pipes are inserted between pairs of commands */
9546 		pipefds.rd = 0;
9547 		pipefds.wr = 1;
9548 		if (cmd_no < pi->num_cmds)
9549 			xpiped_pair(pipefds);
9550 
9551 #if ENABLE_HUSH_LINENO_VAR
9552 		G.execute_lineno = command->lineno;
9553 #endif
9554 
9555 		command->pid = BB_MMU ? fork() : vfork();
9556 		if (!command->pid) { /* child */
9557 #if ENABLE_HUSH_JOB
9558 			disable_restore_tty_pgrp_on_exit();
9559 			CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */
9560 
9561 			/* Every child adds itself to new process group
9562 			 * with pgid == pid_of_first_child_in_pipe */
9563 			if (G.run_list_level == 1 && G_interactive_fd) {
9564 				pid_t pgrp;
9565 				pgrp = pi->pgrp;
9566 				if (pgrp < 0) /* true for 1st process only */
9567 					pgrp = getpid();
9568 				if (setpgid(0, pgrp) == 0
9569 				 && pi->followup != PIPE_BG
9570 				 && G_saved_tty_pgrp /* we have ctty */
9571 				) {
9572 					/* We do it in *every* child, not just first,
9573 					 * to avoid races */
9574 					tcsetpgrp(G_interactive_fd, pgrp);
9575 				}
9576 			}
9577 #endif
9578 			if (pi->alive_cmds == 0 && pi->followup == PIPE_BG) {
9579 				/* 1st cmd in backgrounded pipe
9580 				 * should have its stdin /dev/null'ed */
9581 				close(0);
9582 				if (open(bb_dev_null, O_RDONLY))
9583 					xopen("/", O_RDONLY);
9584 			} else {
9585 				xmove_fd(next_infd, 0);
9586 			}
9587 			xmove_fd(pipefds.wr, 1);
9588 			if (pipefds.rd > 1)
9589 				close(pipefds.rd);
9590 			/* Like bash, explicit redirects override pipes,
9591 			 * and the pipe fd (fd#1) is available for dup'ing:
9592 			 * "cmd1 2>&1 | cmd2": fd#1 is duped to fd#2, thus stderr
9593 			 * of cmd1 goes into pipe.
9594 			 */
9595 			if (setup_redirects(command, NULL)) {
9596 				/* Happens when redir file can't be opened:
9597 				 * $ hush -c 'echo FOO >&2 | echo BAR 3>/qwe/rty; echo BAZ'
9598 				 * FOO
9599 				 * hush: can't open '/qwe/rty': No such file or directory
9600 				 * BAZ
9601 				 * (echo BAR is not executed, it hits _exit(1) below)
9602 				 */
9603 				_exit(1);
9604 			}
9605 
9606 			/* Stores to nommu_save list of env vars putenv'ed
9607 			 * (NOMMU, on MMU we don't need that) */
9608 			/* cast away volatility... */
9609 			pseudo_exec((nommu_save_t*) &nommu_save, command, argv_expanded);
9610 			/* pseudo_exec() does not return */
9611 		}
9612 
9613 		/* parent or error */
9614 #if ENABLE_HUSH_FAST
9615 		G.count_SIGCHLD++;
9616 //bb_error_msg("[%d] fork in run_pipe: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
9617 #endif
9618 		enable_restore_tty_pgrp_on_exit();
9619 #if !BB_MMU
9620 		/* Clean up after vforked child */
9621 		free(nommu_save.argv);
9622 		free(nommu_save.argv_from_re_execing);
9623 		G.var_nest_level = sv_var_nest_level;
9624 		remove_nested_vars();
9625 		add_vars(nommu_save.old_vars);
9626 #endif
9627 		free(argv_expanded);
9628 		argv_expanded = NULL;
9629 		if (command->pid < 0) { /* [v]fork failed */
9630 			/* Clearly indicate, was it fork or vfork */
9631 			bb_simple_perror_msg(BB_MMU ? "vfork"+1 : "vfork");
9632 		} else {
9633 			pi->alive_cmds++;
9634 #if ENABLE_HUSH_JOB
9635 			/* Second and next children need to know pid of first one */
9636 			if (pi->pgrp < 0)
9637 				pi->pgrp = command->pid;
9638 #endif
9639 		}
9640 
9641 		if (cmd_no > 1)
9642 			close(next_infd);
9643 		if (cmd_no < pi->num_cmds)
9644 			close(pipefds.wr);
9645 		/* Pass read (output) pipe end to next iteration */
9646 		next_infd = pipefds.rd;
9647 	}
9648 
9649 	if (!pi->alive_cmds) {
9650 		debug_leave();
9651 		debug_printf_exec("run_pipe return 1 (all forks failed, no children)\n");
9652 		return 1;
9653 	}
9654 
9655 	debug_leave();
9656 	debug_printf_exec("run_pipe return -1 (%u children started)\n", pi->alive_cmds);
9657 	return -1;
9658 }
9659 
9660 /* NB: called by pseudo_exec, and therefore must not modify any
9661  * global data until exec/_exit (we can be a child after vfork!) */
run_list(struct pipe * pi)9662 static int run_list(struct pipe *pi)
9663 {
9664 #if ENABLE_HUSH_CASE
9665 	char *case_word = NULL;
9666 #endif
9667 #if ENABLE_HUSH_LOOPS
9668 	struct pipe *loop_top = NULL;
9669 	char **for_lcur = NULL;
9670 	char **for_list = NULL;
9671 #endif
9672 	smallint last_followup;
9673 	smalluint rcode;
9674 #if ENABLE_HUSH_IF || ENABLE_HUSH_CASE
9675 	smalluint cond_code = 0;
9676 #else
9677 	enum { cond_code = 0 };
9678 #endif
9679 #if HAS_KEYWORDS
9680 	smallint rword;      /* RES_foo */
9681 	smallint last_rword; /* ditto */
9682 #endif
9683 
9684 	debug_printf_exec("run_list start lvl %d\n", G.run_list_level);
9685 	debug_enter();
9686 
9687 #if ENABLE_HUSH_LOOPS
9688 	/* Check syntax for "for" */
9689 	{
9690 		struct pipe *cpipe;
9691 		for (cpipe = pi; cpipe; cpipe = cpipe->next) {
9692 			if (cpipe->res_word != RES_FOR && cpipe->res_word != RES_IN)
9693 				continue;
9694 			/* current word is FOR or IN (BOLD in comments below) */
9695 			if (cpipe->next == NULL) {
9696 				syntax_error("malformed for");
9697 				debug_leave();
9698 				debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level);
9699 				return 1;
9700 			}
9701 			/* "FOR v; do ..." and "for v IN a b; do..." are ok */
9702 			if (cpipe->next->res_word == RES_DO)
9703 				continue;
9704 			/* next word is not "do". It must be "in" then ("FOR v in ...") */
9705 			if (cpipe->res_word == RES_IN /* "for v IN a b; not_do..."? */
9706 			 || cpipe->next->res_word != RES_IN /* FOR v not_do_and_not_in..."? */
9707 			) {
9708 				syntax_error("malformed for");
9709 				debug_leave();
9710 				debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level);
9711 				return 1;
9712 			}
9713 		}
9714 	}
9715 #endif
9716 
9717 	/* Past this point, all code paths should jump to ret: label
9718 	 * in order to return, no direct "return" statements please.
9719 	 * This helps to ensure that no memory is leaked. */
9720 
9721 #if ENABLE_HUSH_JOB
9722 	G.run_list_level++;
9723 #endif
9724 
9725 #if HAS_KEYWORDS
9726 	rword = RES_NONE;
9727 	last_rword = RES_XXXX;
9728 #endif
9729 	last_followup = PIPE_SEQ;
9730 	rcode = G.last_exitcode;
9731 
9732 	/* Go through list of pipes, (maybe) executing them. */
9733 	for (; pi; pi = IF_HUSH_LOOPS(rword == RES_DONE ? loop_top : ) pi->next) {
9734 		int r;
9735 		int sv_errexit_depth;
9736 
9737 		if (G.flag_SIGINT)
9738 			break;
9739 		if (G_flag_return_in_progress == 1)
9740 			break;
9741 
9742 		IF_HAS_KEYWORDS(rword = pi->res_word;)
9743 		debug_printf_exec(": rword=%d cond_code=%d last_rword=%d\n",
9744 				rword, cond_code, last_rword);
9745 
9746 		sv_errexit_depth = G.errexit_depth;
9747 		if (
9748 #if ENABLE_HUSH_IF
9749 		    rword == RES_IF || rword == RES_ELIF ||
9750 #endif
9751 		    pi->followup != PIPE_SEQ
9752 		) {
9753 			G.errexit_depth++;
9754 		}
9755 #if ENABLE_HUSH_LOOPS
9756 		if ((rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR)
9757 		 && loop_top == NULL /* avoid bumping G.depth_of_loop twice */
9758 		) {
9759 			/* start of a loop: remember where loop starts */
9760 			loop_top = pi;
9761 			G.depth_of_loop++;
9762 		}
9763 #endif
9764 		/* Still in the same "if...", "then..." or "do..." branch? */
9765 		if (IF_HAS_KEYWORDS(rword == last_rword &&) 1) {
9766 			if ((rcode == 0 && last_followup == PIPE_OR)
9767 			 || (rcode != 0 && last_followup == PIPE_AND)
9768 			) {
9769 				/* It is "<true> || CMD" or "<false> && CMD"
9770 				 * and we should not execute CMD */
9771 				debug_printf_exec("skipped cmd because of || or &&\n");
9772 				last_followup = pi->followup;
9773 				goto dont_check_jobs_but_continue;
9774 			}
9775 		}
9776 		last_followup = pi->followup;
9777 		IF_HAS_KEYWORDS(last_rword = rword;)
9778 #if ENABLE_HUSH_IF
9779 		if (cond_code) {
9780 			if (rword == RES_THEN) {
9781 				/* if false; then ... fi has exitcode 0! */
9782 				G.last_exitcode = rcode = EXIT_SUCCESS;
9783 				/* "if <false> THEN cmd": skip cmd */
9784 				continue;
9785 			}
9786 		} else {
9787 			if (rword == RES_ELSE || rword == RES_ELIF) {
9788 				/* "if <true> then ... ELSE/ELIF cmd":
9789 				 * skip cmd and all following ones */
9790 				break;
9791 			}
9792 		}
9793 #endif
9794 #if ENABLE_HUSH_LOOPS
9795 		if (rword == RES_FOR) { /* && pi->num_cmds - always == 1 */
9796 			if (!for_lcur) {
9797 				/* first loop through for */
9798 
9799 				static const char encoded_dollar_at[] ALIGN1 = {
9800 					SPECIAL_VAR_SYMBOL, '@' | 0x80, SPECIAL_VAR_SYMBOL, '\0'
9801 				}; /* encoded representation of "$@" */
9802 				static const char *const encoded_dollar_at_argv[] = {
9803 					encoded_dollar_at, NULL
9804 				}; /* argv list with one element: "$@" */
9805 				char **vals;
9806 
9807 				G.last_exitcode = rcode = EXIT_SUCCESS;
9808 				vals = (char**)encoded_dollar_at_argv;
9809 				if (pi->next->res_word == RES_IN) {
9810 					/* if no variable values after "in" we skip "for" */
9811 					if (!pi->next->cmds[0].argv) {
9812 						debug_printf_exec(": null FOR: exitcode EXIT_SUCCESS\n");
9813 						break;
9814 					}
9815 					vals = pi->next->cmds[0].argv;
9816 				} /* else: "for var; do..." -> assume "$@" list */
9817 				/* create list of variable values */
9818 				debug_print_strings("for_list made from", vals);
9819 				for_list = expand_strvec_to_strvec(vals);
9820 				for_lcur = for_list;
9821 				debug_print_strings("for_list", for_list);
9822 			}
9823 			if (!*for_lcur) {
9824 				/* "for" loop is over, clean up */
9825 				free(for_list);
9826 				for_list = NULL;
9827 				for_lcur = NULL;
9828 				break;
9829 			}
9830 			/* Insert next value from for_lcur */
9831 			/* note: *for_lcur already has quotes removed, $var expanded, etc */
9832 			set_local_var(xasprintf("%s=%s", pi->cmds[0].argv[0], *for_lcur++), /*flag:*/ 0);
9833 			continue;
9834 		}
9835 		if (rword == RES_IN) {
9836 			continue; /* "for v IN list;..." - "in" has no cmds anyway */
9837 		}
9838 		if (rword == RES_DONE) {
9839 			continue; /* "done" has no cmds too */
9840 		}
9841 #endif
9842 #if ENABLE_HUSH_CASE
9843 		if (rword == RES_CASE) {
9844 			debug_printf_exec("CASE cond_code:%d\n", cond_code);
9845 			case_word = expand_string_to_string(pi->cmds->argv[0],
9846 				EXP_FLAG_ESC_GLOB_CHARS, /*unbackslash:*/ 1);
9847 			debug_printf_exec("CASE word1:'%s'\n", case_word);
9848 			//unbackslash(case_word);
9849 			//debug_printf_exec("CASE word2:'%s'\n", case_word);
9850 			continue;
9851 		}
9852 		if (rword == RES_MATCH) {
9853 			char **argv;
9854 
9855 			debug_printf_exec("MATCH cond_code:%d\n", cond_code);
9856 			if (!case_word) /* "case ... matched_word) ... WORD)": we executed selected branch, stop */
9857 				break;
9858 			/* all prev words didn't match, does this one match? */
9859 			argv = pi->cmds->argv;
9860 			while (*argv) {
9861 				char *pattern;
9862 				debug_printf_exec("expand_string_to_string('%s')\n", *argv);
9863 				pattern = expand_string_to_string(*argv,
9864 						EXP_FLAG_ESC_GLOB_CHARS,
9865 						/*unbackslash:*/ 0
9866 				);
9867 				/* TODO: which FNM_xxx flags to use? */
9868 				cond_code = (fnmatch(pattern, case_word, /*flags:*/ 0) != 0);
9869 				debug_printf_exec("fnmatch(pattern:'%s',str:'%s'):%d\n",
9870 						pattern, case_word, cond_code);
9871 				free(pattern);
9872 				if (cond_code == 0) {
9873 					/* match! we will execute this branch */
9874 					free(case_word);
9875 					case_word = NULL; /* make future "word)" stop */
9876 					break;
9877 				}
9878 				argv++;
9879 			}
9880 			continue;
9881 		}
9882 		if (rword == RES_CASE_BODY) { /* inside of a case branch */
9883 			debug_printf_exec("CASE_BODY cond_code:%d\n", cond_code);
9884 			if (cond_code != 0)
9885 				continue; /* not matched yet, skip this pipe */
9886 		}
9887 		if (rword == RES_ESAC) {
9888 			debug_printf_exec("ESAC cond_code:%d\n", cond_code);
9889 			if (case_word) {
9890 				/* "case" did not match anything: still set $? (to 0) */
9891 				G.last_exitcode = rcode = EXIT_SUCCESS;
9892 			}
9893 		}
9894 #endif
9895 		/* Just pressing <enter> in shell should check for jobs.
9896 		 * OTOH, in non-interactive shell this is useless
9897 		 * and only leads to extra job checks */
9898 		if (pi->num_cmds == 0) {
9899 			if (G_interactive_fd)
9900 				goto check_jobs_and_continue;
9901 			continue;
9902 		}
9903 
9904 		/* After analyzing all keywords and conditions, we decided
9905 		 * to execute this pipe. NB: have to do checkjobs(NULL)
9906 		 * after run_pipe to collect any background children,
9907 		 * even if list execution is to be stopped. */
9908 		debug_printf_exec(": run_pipe with %d members\n", pi->num_cmds);
9909 #if ENABLE_HUSH_LOOPS
9910 		G.flag_break_continue = 0;
9911 #endif
9912 		rcode = r = G.o_opt[OPT_O_NOEXEC] ? 0 : run_pipe(pi);
9913 		/* NB: rcode is a smalluint, r is int */
9914 		if (r != -1) {
9915 			/* We ran a builtin, function, or group.
9916 			 * rcode is already known
9917 			 * and we don't need to wait for anything. */
9918 			debug_printf_exec(": builtin/func exitcode %d\n", rcode);
9919 			G.last_exitcode = rcode;
9920 			check_and_run_traps();
9921 #if ENABLE_HUSH_TRAP && ENABLE_HUSH_FUNCTIONS
9922 			rcode = G.last_exitcode; /* "return" in trap can change it, read back */
9923 #endif
9924 #if ENABLE_HUSH_LOOPS
9925 			/* Was it "break" or "continue"? */
9926 			if (G.flag_break_continue) {
9927 				smallint fbc = G.flag_break_continue;
9928 				/* We might fall into outer *loop*,
9929 				 * don't want to break it too */
9930 				if (loop_top) {
9931 					G.depth_break_continue--;
9932 					if (G.depth_break_continue == 0)
9933 						G.flag_break_continue = 0;
9934 					/* else: e.g. "continue 2" should *break* once, *then* continue */
9935 				} /* else: "while... do... { we are here (innermost list is not a loop!) };...done" */
9936 				if (G.depth_break_continue != 0 || fbc == BC_BREAK) {
9937 					checkjobs(NULL, 0 /*(no pid to wait for)*/);
9938 					break;
9939 				}
9940 				/* "continue": simulate end of loop */
9941 				rword = RES_DONE;
9942 				continue;
9943 			}
9944 #endif
9945 			if (G_flag_return_in_progress == 1) {
9946 				checkjobs(NULL, 0 /*(no pid to wait for)*/);
9947 				break;
9948 			}
9949 		} else if (pi->followup == PIPE_BG) {
9950 			/* What does bash do with attempts to background builtins? */
9951 			/* even bash 3.2 doesn't do that well with nested bg:
9952 			 * try "{ { sleep 10; echo DEEP; } & echo HERE; } &".
9953 			 * I'm NOT treating inner &'s as jobs */
9954 #if ENABLE_HUSH_JOB
9955 			if (G.run_list_level == 1)
9956 				insert_job_into_table(pi);
9957 #endif
9958 			/* Last command's pid goes to $! */
9959 			G.last_bg_pid = pi->cmds[pi->num_cmds - 1].pid;
9960 			G.last_bg_pid_exitcode = 0;
9961 			debug_printf_exec(": cmd&: exitcode EXIT_SUCCESS\n");
9962 /* Check pi->pi_inverted? "! sleep 1 & echo $?": bash says 1. dash and ash say 0 */
9963 			rcode = EXIT_SUCCESS;
9964 			goto check_traps;
9965 		} else {
9966 #if ENABLE_HUSH_JOB
9967 			if (G.run_list_level == 1 && G_interactive_fd) {
9968 				/* Waits for completion, then fg's main shell */
9969 				rcode = checkjobs_and_fg_shell(pi);
9970 				debug_printf_exec(": checkjobs_and_fg_shell exitcode %d\n", rcode);
9971 				goto check_traps;
9972 			}
9973 #endif
9974 			/* This one just waits for completion */
9975 			rcode = checkjobs(pi, 0 /*(no pid to wait for)*/);
9976 			debug_printf_exec(": checkjobs exitcode %d\n", rcode);
9977  check_traps:
9978 			G.last_exitcode = rcode;
9979 			check_and_run_traps();
9980 #if ENABLE_HUSH_TRAP && ENABLE_HUSH_FUNCTIONS
9981 			rcode = G.last_exitcode; /* "return" in trap can change it, read back */
9982 #endif
9983 		}
9984 
9985 		/* Handle "set -e" */
9986 		if (rcode != 0 && G.o_opt[OPT_O_ERREXIT]) {
9987 			debug_printf_exec("ERREXIT:1 errexit_depth:%d\n", G.errexit_depth);
9988 			if (G.errexit_depth == 0)
9989 				hush_exit(rcode);
9990 		}
9991 		G.errexit_depth = sv_errexit_depth;
9992 
9993 		/* Analyze how result affects subsequent commands */
9994 #if ENABLE_HUSH_IF
9995 		if (rword == RES_IF || rword == RES_ELIF)
9996 			cond_code = rcode;
9997 #endif
9998  check_jobs_and_continue:
9999 		checkjobs(NULL, 0 /*(no pid to wait for)*/);
10000  dont_check_jobs_but_continue: ;
10001 #if ENABLE_HUSH_LOOPS
10002 		/* Beware of "while false; true; do ..."! */
10003 		if (pi->next
10004 		 && (pi->next->res_word == RES_DO || pi->next->res_word == RES_DONE)
10005 		 /* check for RES_DONE is needed for "while ...; do \n done" case */
10006 		) {
10007 			if (rword == RES_WHILE) {
10008 				if (rcode) {
10009 					/* "while false; do...done" - exitcode 0 */
10010 					G.last_exitcode = rcode = EXIT_SUCCESS;
10011 					debug_printf_exec(": while expr is false: breaking (exitcode:EXIT_SUCCESS)\n");
10012 					break;
10013 				}
10014 			}
10015 			if (rword == RES_UNTIL) {
10016 				if (!rcode) {
10017 					debug_printf_exec(": until expr is true: breaking\n");
10018 					break;
10019 				}
10020 			}
10021 		}
10022 #endif
10023 	} /* for (pi) */
10024 
10025 #if ENABLE_HUSH_JOB
10026 	G.run_list_level--;
10027 #endif
10028 #if ENABLE_HUSH_LOOPS
10029 	if (loop_top)
10030 		G.depth_of_loop--;
10031 	free(for_list);
10032 #endif
10033 #if ENABLE_HUSH_CASE
10034 	free(case_word);
10035 #endif
10036 	debug_leave();
10037 	debug_printf_exec("run_list lvl %d return %d\n", G.run_list_level + 1, rcode);
10038 	return rcode;
10039 }
10040 
10041 /* Select which version we will use */
run_and_free_list(struct pipe * pi)10042 static int run_and_free_list(struct pipe *pi)
10043 {
10044 	int rcode = 0;
10045 	debug_printf_exec("run_and_free_list entered\n");
10046 	if (!G.o_opt[OPT_O_NOEXEC]) {
10047 		debug_printf_exec(": run_list: 1st pipe with %d cmds\n", pi->num_cmds);
10048 		rcode = run_list(pi);
10049 	}
10050 	/* free_pipe_list has the side effect of clearing memory.
10051 	 * In the long run that function can be merged with run_list,
10052 	 * but doing that now would hobble the debugging effort. */
10053 	free_pipe_list(pi);
10054 	debug_printf_exec("run_and_free_list return %d\n", rcode);
10055 	return rcode;
10056 }
10057 
10058 
install_sighandlers(unsigned mask)10059 static void install_sighandlers(unsigned mask)
10060 {
10061 	sighandler_t old_handler;
10062 	unsigned sig = 0;
10063 	while ((mask >>= 1) != 0) {
10064 		sig++;
10065 		if (!(mask & 1))
10066 			continue;
10067 		old_handler = install_sighandler(sig, pick_sighandler(sig));
10068 		/* POSIX allows shell to re-enable SIGCHLD
10069 		 * even if it was SIG_IGN on entry.
10070 		 * Therefore we skip IGN check for it:
10071 		 */
10072 		if (sig == SIGCHLD)
10073 			continue;
10074 		/* Interactive bash re-enables SIGHUP which is SIG_IGNed on entry.
10075 		 * Try:
10076 		 * trap '' hup; bash; echo RET  # type "kill -hup $$", see SIGHUP having effect
10077 		 * trap '' hup; bash -c 'kill -hup $$; echo ALIVE'  # here SIGHUP is SIG_IGNed
10078 		 */
10079 		if (sig == SIGHUP && G_interactive_fd)
10080 			continue;
10081 		/* Unless one of the above signals, is it SIG_IGN? */
10082 		if (old_handler == SIG_IGN) {
10083 			/* oops... restore back to IGN, and record this fact */
10084 			install_sighandler(sig, old_handler);
10085 #if ENABLE_HUSH_TRAP
10086 			if (!G_traps)
10087 				G_traps = xzalloc(sizeof(G_traps[0]) * NSIG);
10088 			free(G_traps[sig]);
10089 			G_traps[sig] = xzalloc(1); /* == xstrdup(""); */
10090 #endif
10091 		}
10092 	}
10093 }
10094 
10095 /* Called a few times only (or even once if "sh -c") */
install_special_sighandlers(void)10096 static void install_special_sighandlers(void)
10097 {
10098 	unsigned mask;
10099 
10100 	/* Which signals are shell-special? */
10101 	mask = (1 << SIGQUIT) | (1 << SIGCHLD);
10102 	if (G_interactive_fd) {
10103 		mask |= SPECIAL_INTERACTIVE_SIGS;
10104 		if (G_saved_tty_pgrp) /* we have ctty, job control sigs work */
10105 			mask |= SPECIAL_JOBSTOP_SIGS;
10106 	}
10107 	/* Careful, do not re-install handlers we already installed */
10108 	if (G.special_sig_mask != mask) {
10109 		unsigned diff = mask & ~G.special_sig_mask;
10110 		G.special_sig_mask = mask;
10111 		install_sighandlers(diff);
10112 	}
10113 }
10114 
10115 #if ENABLE_HUSH_JOB
10116 /* helper */
10117 /* Set handlers to restore tty pgrp and exit */
install_fatal_sighandlers(void)10118 static void install_fatal_sighandlers(void)
10119 {
10120 	unsigned mask;
10121 
10122 	/* We will restore tty pgrp on these signals */
10123 	mask = 0
10124 		/*+ (1 << SIGILL ) * HUSH_DEBUG*/
10125 		/*+ (1 << SIGFPE ) * HUSH_DEBUG*/
10126 		+ (1 << SIGBUS ) * HUSH_DEBUG
10127 		+ (1 << SIGSEGV) * HUSH_DEBUG
10128 		/*+ (1 << SIGTRAP) * HUSH_DEBUG*/
10129 		+ (1 << SIGABRT)
10130 	/* bash 3.2 seems to handle these just like 'fatal' ones */
10131 		+ (1 << SIGPIPE)
10132 		+ (1 << SIGALRM)
10133 	/* if we are interactive, SIGHUP, SIGTERM and SIGINT are special sigs.
10134 	 * if we aren't interactive... but in this case
10135 	 * we never want to restore pgrp on exit, and this fn is not called
10136 	 */
10137 		/*+ (1 << SIGHUP )*/
10138 		/*+ (1 << SIGTERM)*/
10139 		/*+ (1 << SIGINT )*/
10140 	;
10141 	G_fatal_sig_mask = mask;
10142 
10143 	install_sighandlers(mask);
10144 }
10145 #endif
10146 
set_mode(int state,char mode,const char * o_opt)10147 static int set_mode(int state, char mode, const char *o_opt)
10148 {
10149 	int idx;
10150 	switch (mode) {
10151 	case 'n':
10152 		/* set -n has no effect in interactive shell */
10153 		/* Try: while set -n; do echo $-; done */
10154 		if (!G_interactive_fd)
10155 			G.o_opt[OPT_O_NOEXEC] = state;
10156 		break;
10157 	case 'x':
10158 		IF_HUSH_MODE_X(G_x_mode = state;)
10159 		IF_HUSH_MODE_X(if (G.x_mode_fd <= 0) G.x_mode_fd = dup_CLOEXEC(2, 10);)
10160 		break;
10161 	case 'e':
10162 		G.o_opt[OPT_O_ERREXIT] = state;
10163 		break;
10164 	case 'o':
10165 		if (!o_opt) {
10166 			/* "set -o" or "set +o" without parameter.
10167 			 * in bash, set -o produces this output:
10168 			 *  pipefail        off
10169 			 * and set +o:
10170 			 *  set +o pipefail
10171 			 * We always use the second form.
10172 			 */
10173 			const char *p = o_opt_strings;
10174 			idx = 0;
10175 			while (*p) {
10176 				printf("set %co %s\n", (G.o_opt[idx] ? '-' : '+'), p);
10177 				idx++;
10178 				p += strlen(p) + 1;
10179 			}
10180 			break;
10181 		}
10182 		idx = index_in_strings(o_opt_strings, o_opt);
10183 		if (idx >= 0) {
10184 			G.o_opt[idx] = state;
10185 			break;
10186 		}
10187 		/* fall through to error */
10188 	default:
10189 		return EXIT_FAILURE;
10190 	}
10191 	return EXIT_SUCCESS;
10192 }
10193 
10194 int hush_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
hush_main(int argc,char ** argv)10195 int hush_main(int argc, char **argv)
10196 {
10197 	pid_t cached_getpid;
10198 	enum {
10199 		OPT_login = (1 << 0),
10200 	};
10201 	unsigned flags;
10202 #if !BB_MMU
10203 	unsigned builtin_argc = 0;
10204 #endif
10205 	char **e;
10206 	struct variable *cur_var;
10207 	struct variable *shell_ver;
10208 
10209 	INIT_G();
10210 	if (EXIT_SUCCESS != 0) /* if EXIT_SUCCESS == 0, it is already done */
10211 		G.last_exitcode = EXIT_SUCCESS;
10212 #if ENABLE_HUSH_TRAP
10213 # if ENABLE_HUSH_FUNCTIONS
10214 	G.return_exitcode = -1;
10215 # endif
10216 	G.pre_trap_exitcode = -1;
10217 #endif
10218 
10219 #if ENABLE_HUSH_FAST
10220 	G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
10221 #endif
10222 #if !BB_MMU
10223 	G.argv0_for_re_execing = argv[0];
10224 #endif
10225 
10226 	cached_getpid = getpid();   /* for tcsetpgrp() during init */
10227 	G.root_pid = cached_getpid; /* for $PID  (NOMMU can override via -$HEXPID:HEXPPID:...) */
10228 	G.root_ppid = getppid();    /* for $PPID (NOMMU can override) */
10229 
10230 	/* Deal with HUSH_VERSION */
10231 	debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION");
10232 	unsetenv("HUSH_VERSION"); /* in case it exists in initial env */
10233 	shell_ver = xzalloc(sizeof(*shell_ver));
10234 	shell_ver->flg_export = 1;
10235 	shell_ver->flg_read_only = 1;
10236 	/* Code which handles ${var<op>...} needs writable values for all variables,
10237 	 * therefore we xstrdup: */
10238 	shell_ver->varstr = xstrdup(hush_version_str);
10239 
10240 	/* Create shell local variables from the values
10241 	 * currently living in the environment */
10242 	G.top_var = shell_ver;
10243 	cur_var = G.top_var;
10244 	e = environ;
10245 	if (e) while (*e) {
10246 		char *value = strchr(*e, '=');
10247 		if (value) { /* paranoia */
10248 			cur_var->next = xzalloc(sizeof(*cur_var));
10249 			cur_var = cur_var->next;
10250 			cur_var->varstr = *e;
10251 			cur_var->max_len = strlen(*e);
10252 			cur_var->flg_export = 1;
10253 		}
10254 		e++;
10255 	}
10256 	/* (Re)insert HUSH_VERSION into env (AFTER we scanned the env!) */
10257 	debug_printf_env("putenv '%s'\n", shell_ver->varstr);
10258 	putenv(shell_ver->varstr);
10259 
10260 	/* Export PWD */
10261 	set_pwd_var(SETFLAG_EXPORT);
10262 
10263 #if BASH_HOSTNAME_VAR
10264 	/* Set (but not export) HOSTNAME unless already set */
10265 	if (!get_local_var_value("HOSTNAME")) {
10266 		struct utsname uts;
10267 		uname(&uts);
10268 		set_local_var_from_halves("HOSTNAME", uts.nodename);
10269 	}
10270 #endif
10271 	/* IFS is not inherited from the parent environment */
10272 	set_local_var_from_halves("IFS", defifs);
10273 
10274 	if (!get_local_var_value("PATH"))
10275 		set_local_var_from_halves("PATH", bb_default_root_path);
10276 
10277 	/* PS1/PS2 are set later, if we determine that we are interactive */
10278 
10279 	/* bash also exports SHLVL and _,
10280 	 * and sets (but doesn't export) the following variables:
10281 	 * BASH=/bin/bash
10282 	 * BASH_VERSINFO=([0]="3" [1]="2" [2]="0" [3]="1" [4]="release" [5]="i386-pc-linux-gnu")
10283 	 * BASH_VERSION='3.2.0(1)-release'
10284 	 * HOSTTYPE=i386
10285 	 * MACHTYPE=i386-pc-linux-gnu
10286 	 * OSTYPE=linux-gnu
10287 	 * PPID=<NNNNN> - we also do it elsewhere
10288 	 * EUID=<NNNNN>
10289 	 * UID=<NNNNN>
10290 	 * GROUPS=()
10291 	 * LINES=<NNN>
10292 	 * COLUMNS=<NNN>
10293 	 * BASH_ARGC=()
10294 	 * BASH_ARGV=()
10295 	 * BASH_LINENO=()
10296 	 * BASH_SOURCE=()
10297 	 * DIRSTACK=()
10298 	 * PIPESTATUS=([0]="0")
10299 	 * HISTFILE=/<xxx>/.bash_history
10300 	 * HISTFILESIZE=500
10301 	 * HISTSIZE=500
10302 	 * MAILCHECK=60
10303 	 * PATH=/usr/gnu/bin:/usr/local/bin:/bin:/usr/bin:.
10304 	 * SHELL=/bin/bash
10305 	 * SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
10306 	 * TERM=dumb
10307 	 * OPTERR=1
10308 	 * OPTIND=1
10309 	 * PS4='+ '
10310 	 */
10311 
10312 #if NUM_SCRIPTS > 0
10313 	if (argc < 0) {
10314 		char *script = get_script_content(-argc - 1);
10315 		G.global_argv = argv;
10316 		G.global_argc = string_array_len(argv);
10317 		//install_special_sighandlers(); - needed?
10318 		parse_and_run_string(script);
10319 		goto final_return;
10320 	}
10321 #endif
10322 
10323 	/* Initialize some more globals to non-zero values */
10324 	die_func = restore_ttypgrp_and__exit;
10325 
10326 	/* Shell is non-interactive at first. We need to call
10327 	 * install_special_sighandlers() if we are going to execute "sh <script>",
10328 	 * "sh -c <cmds>" or login shell's /etc/profile and friends.
10329 	 * If we later decide that we are interactive, we run install_special_sighandlers()
10330 	 * in order to intercept (more) signals.
10331 	 */
10332 
10333 	/* Parse options */
10334 	/* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */
10335 	flags = (argv[0] && argv[0][0] == '-') ? OPT_login : 0;
10336 	while (1) {
10337 		int opt = getopt(argc, argv, "+" /* stop at 1st non-option */
10338 				"cexinsl"
10339 #if !BB_MMU
10340 				"<:$:R:V:"
10341 # if ENABLE_HUSH_FUNCTIONS
10342 				"F:"
10343 # endif
10344 #endif
10345 		);
10346 		if (opt <= 0)
10347 			break;
10348 		switch (opt) {
10349 		case 'c':
10350 			/* Note: -c is not an option with param!
10351 			 * "hush -c -l SCRIPT" is valid. "hush -cSCRIPT" is not.
10352 			 */
10353 			G.opt_c = 1;
10354 			break;
10355 		case 'i':
10356 			/* Well, we cannot just declare interactiveness,
10357 			 * we have to have some stuff (ctty, etc) */
10358 			/* G_interactive_fd++; */
10359 //There are a few cases where bash -i -c 'SCRIPT'
10360 //has visible effect (differs from bash -c 'SCRIPT'):
10361 //it ignores TERM:
10362 //	bash -i -c 'kill $$; echo ALIVE'
10363 //	ALIVE
10364 //it resets SIG_INGed HUP to SIG_DFL:
10365 //	trap '' hup; bash -i -c 'kill -hup $$; echo ALIVE'
10366 //	Hangup   [the message is not printed by bash, it's the shell which started it]
10367 //is talkative about jobs and exiting:
10368 //	bash -i -c 'sleep 1 & exit'
10369 //	[1] 16170
10370 //	exit
10371 //includes $ENV file (only if run as "sh"):
10372 //	echo last >/tmp/ENV; ENV=/tmp/ENV sh -i -c 'echo HERE'
10373 //	last: cannot open /var/log/wtmp: No such file or directory
10374 //	HERE
10375 //(under "bash", it's the opposite: it runs $BASH_ENV file only *without* -i).
10376 //
10377 //ash -i -c 'sleep 3; sleep 3', on ^C, drops into a prompt instead of exiting
10378 //(this may be a bug, bash does not do this).
10379 //(ash -i -c 'sleep 3' won't show this, the last command gets auto-"exec"ed)
10380 //
10381 //None of the above feel like useful features people would rely on.
10382 			break;
10383 		case 's':
10384 			G.opt_s = 1;
10385 			break;
10386 		case 'l':
10387 			flags |= OPT_login;
10388 			break;
10389 #if !BB_MMU
10390 		case '<': /* "big heredoc" support */
10391 			full_write1_str(optarg);
10392 			_exit(0);
10393 		case '$': {
10394 			unsigned long long empty_trap_mask;
10395 
10396 			G.root_pid = bb_strtou(optarg, &optarg, 16);
10397 			optarg++;
10398 			G.root_ppid = bb_strtou(optarg, &optarg, 16);
10399 			optarg++;
10400 			G.last_bg_pid = bb_strtou(optarg, &optarg, 16);
10401 			optarg++;
10402 			G.last_exitcode = bb_strtou(optarg, &optarg, 16);
10403 			optarg++;
10404 			builtin_argc = bb_strtou(optarg, &optarg, 16);
10405 			optarg++;
10406 			empty_trap_mask = bb_strtoull(optarg, &optarg, 16);
10407 			if (empty_trap_mask != 0) {
10408 				IF_HUSH_TRAP(int sig;)
10409 				install_special_sighandlers();
10410 # if ENABLE_HUSH_TRAP
10411 				G_traps = xzalloc(sizeof(G_traps[0]) * NSIG);
10412 				for (sig = 1; sig < NSIG; sig++) {
10413 					if (empty_trap_mask & (1LL << sig)) {
10414 						G_traps[sig] = xzalloc(1); /* == xstrdup(""); */
10415 						install_sighandler(sig, SIG_IGN);
10416 					}
10417 				}
10418 # endif
10419 			}
10420 # if ENABLE_HUSH_LOOPS
10421 			optarg++;
10422 			G.depth_of_loop = bb_strtou(optarg, &optarg, 16);
10423 # endif
10424 			/* Suppress "killed by signal" message, -$ hack is used
10425 			 * for subshells: echo `sh -c 'kill -9 $$'`
10426 			 * should be silent.
10427 			 */
10428 			IF_HUSH_JOB(G.run_list_level = 1;)
10429 # if ENABLE_HUSH_FUNCTIONS
10430 			/* nommu uses re-exec trick for "... | func | ...",
10431 			 * should allow "return".
10432 			 * This accidentally allows returns in subshells.
10433 			 */
10434 			G_flag_return_in_progress = -1;
10435 # endif
10436 			break;
10437 		}
10438 		case 'R':
10439 		case 'V':
10440 			set_local_var(xstrdup(optarg), opt == 'R' ? SETFLAG_MAKE_RO : 0);
10441 			break;
10442 # if ENABLE_HUSH_FUNCTIONS
10443 		case 'F': {
10444 			struct function *funcp = new_function(optarg);
10445 			/* funcp->name is already set to optarg */
10446 			/* funcp->body is set to NULL. It's a special case. */
10447 			funcp->body_as_string = argv[optind];
10448 			optind++;
10449 			break;
10450 		}
10451 # endif
10452 #endif
10453 		/*case '?': invalid option encountered (set_mode('?') will fail) */
10454 		/*case 'n':*/
10455 		/*case 'x':*/
10456 		/*case 'e':*/
10457 		default:
10458 			if (set_mode(1, opt, NULL) == 0) /* no error */
10459 				break;
10460 			bb_show_usage();
10461 		}
10462 	} /* option parsing loop */
10463 
10464 	/* Skip options. Try "hush -l": $1 should not be "-l"! */
10465 	G.global_argc = argc - (optind - 1);
10466 	G.global_argv = argv + (optind - 1);
10467 	G.global_argv[0] = argv[0];
10468 
10469 	/* If we are login shell... */
10470 	if (flags & OPT_login) {
10471 		const char *hp = NULL;
10472 		HFILE *input;
10473 
10474 		debug_printf("sourcing /etc/profile\n");
10475 		input = hfopen("/etc/profile");
10476  run_profile:
10477 		if (input != NULL) {
10478 			install_special_sighandlers();
10479 			parse_and_run_file(input);
10480 			hfclose(input);
10481 		}
10482 		/* bash: after sourcing /etc/profile,
10483 		 * tries to source (in the given order):
10484 		 * ~/.bash_profile, ~/.bash_login, ~/.profile,
10485 		 * stopping on first found. --noprofile turns this off.
10486 		 * bash also sources ~/.bash_logout on exit.
10487 		 * If called as sh, skips .bash_XXX files.
10488 		 */
10489 		if (!hp) { /* unless we looped on the "goto" already */
10490 			hp = get_local_var_value("HOME");
10491 			if (hp && hp[0]) {
10492 				debug_printf("sourcing ~/.profile\n");
10493 				hp = concat_path_file(hp, ".profile");
10494 				input = hfopen(hp);
10495 				free((char*)hp);
10496 				goto run_profile;
10497 			}
10498 		}
10499 	}
10500 
10501 	/* -c takes effect *after* -l */
10502 	if (G.opt_c) {
10503 		/* Possibilities:
10504 		 * sh ... -c 'script'
10505 		 * sh ... -c 'script' ARG0 [ARG1...]
10506 		 * On NOMMU, if builtin_argc != 0,
10507 		 * sh ... -c 'builtin' BARGV... "" ARG0 [ARG1...]
10508 		 * "" needs to be replaced with NULL
10509 		 * and BARGV vector fed to builtin function.
10510 		 * Note: the form without ARG0 never happens:
10511 		 * sh ... -c 'builtin' BARGV... ""
10512 		 */
10513 		char *script;
10514 
10515 		install_special_sighandlers();
10516 
10517 		G.global_argc--;
10518 		G.global_argv++;
10519 #if !BB_MMU
10520 		if (builtin_argc) {
10521 			/* -c 'builtin' [BARGV...] "" ARG0 [ARG1...] */
10522 			const struct built_in_command *x;
10523 			x = find_builtin(G.global_argv[0]);
10524 			if (x) { /* paranoia */
10525 				argv = G.global_argv;
10526 				G.global_argc -= builtin_argc + 1; /* skip [BARGV...] "" */
10527 				G.global_argv += builtin_argc + 1;
10528 				G.global_argv[-1] = NULL; /* replace "" */
10529 				G.last_exitcode = x->b_function(argv);
10530 			}
10531 			goto final_return;
10532 		}
10533 #endif
10534 
10535 		script = G.global_argv[0];
10536 		if (!script)
10537 			bb_error_msg_and_die(bb_msg_requires_arg, "-c");
10538 		if (!G.global_argv[1]) {
10539 			/* -c 'script' (no params): prevent empty $0 */
10540 			G.global_argv[0] = argv[0];
10541 		} else { /* else -c 'script' ARG0 [ARG1...]: $0 is ARG0 */
10542 			G.global_argc--;
10543 			G.global_argv++;
10544 		}
10545 		parse_and_run_string(script);
10546 		goto final_return;
10547 	}
10548 
10549 	/* -s is: hush -s ARGV1 ARGV2 (no SCRIPT) */
10550 	if (!G.opt_s && G.global_argv[1]) {
10551 		HFILE *input;
10552 		/*
10553 		 * "bash <script>" (which is never interactive (unless -i?))
10554 		 * sources $BASH_ENV here (without scanning $PATH).
10555 		 * If called as sh, does the same but with $ENV.
10556 		 * Also NB, per POSIX, $ENV should undergo parameter expansion.
10557 		 */
10558 		G.global_argc--;
10559 		G.global_argv++;
10560 		debug_printf("running script '%s'\n", G.global_argv[0]);
10561 		xfunc_error_retval = 127; /* for "hush /does/not/exist" case */
10562 		input = hfopen(G.global_argv[0]);
10563 		if (!input) {
10564 			bb_simple_perror_msg_and_die(G.global_argv[0]);
10565 		}
10566 		xfunc_error_retval = 1;
10567 		install_special_sighandlers();
10568 		parse_and_run_file(input);
10569 #if ENABLE_FEATURE_CLEAN_UP
10570 		hfclose(input);
10571 #endif
10572 		goto final_return;
10573 	}
10574 	/* "implicit" -s: bare interactive hush shows 's' in $- */
10575 	G.opt_s = 1;
10576 
10577 	/* Up to here, shell was non-interactive. Now it may become one.
10578 	 * NB: don't forget to (re)run install_special_sighandlers() as needed.
10579 	 */
10580 
10581 	/* A shell is interactive if the '-i' flag was given,
10582 	 * or if all of the following conditions are met:
10583 	 *    no -c command
10584 	 *    no arguments remaining or the -s flag given
10585 	 *    standard input is a terminal
10586 	 *    standard output is a terminal
10587 	 * Refer to Posix.2, the description of the 'sh' utility.
10588 	 */
10589 #if ENABLE_HUSH_JOB
10590 	if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
10591 		G_saved_tty_pgrp = tcgetpgrp(STDIN_FILENO);
10592 		debug_printf("saved_tty_pgrp:%d\n", G_saved_tty_pgrp);
10593 		if (G_saved_tty_pgrp < 0)
10594 			G_saved_tty_pgrp = 0;
10595 
10596 		/* try to dup stdin to high fd#, >= 255 */
10597 		G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254);
10598 		if (G_interactive_fd < 0) {
10599 			/* try to dup to any fd */
10600 			G_interactive_fd = dup(STDIN_FILENO);
10601 			if (G_interactive_fd < 0) {
10602 				/* give up */
10603 				G_interactive_fd = 0;
10604 				G_saved_tty_pgrp = 0;
10605 			}
10606 		}
10607 	}
10608 	debug_printf("interactive_fd:%d\n", G_interactive_fd);
10609 	if (G_interactive_fd) {
10610 		close_on_exec_on(G_interactive_fd);
10611 
10612 		if (G_saved_tty_pgrp) {
10613 			/* If we were run as 'hush &', sleep until we are
10614 			 * in the foreground (tty pgrp == our pgrp).
10615 			 * If we get started under a job aware app (like bash),
10616 			 * make sure we are now in charge so we don't fight over
10617 			 * who gets the foreground */
10618 			while (1) {
10619 				pid_t shell_pgrp = getpgrp();
10620 				G_saved_tty_pgrp = tcgetpgrp(G_interactive_fd);
10621 				if (G_saved_tty_pgrp == shell_pgrp)
10622 					break;
10623 				/* send TTIN to ourself (should stop us) */
10624 				kill(- shell_pgrp, SIGTTIN);
10625 			}
10626 		}
10627 
10628 		/* Install more signal handlers */
10629 		install_special_sighandlers();
10630 
10631 		if (G_saved_tty_pgrp) {
10632 			/* Set other signals to restore saved_tty_pgrp */
10633 			install_fatal_sighandlers();
10634 			/* Put ourselves in our own process group
10635 			 * (bash, too, does this only if ctty is available) */
10636 			bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */
10637 			/* Grab control of the terminal */
10638 			tcsetpgrp(G_interactive_fd, cached_getpid);
10639 		}
10640 		enable_restore_tty_pgrp_on_exit();
10641 
10642 # if ENABLE_FEATURE_EDITING
10643 		G.line_input_state = new_line_input_t(FOR_SHELL);
10644 #  if EDITING_HAS_get_exe_name
10645 		G.line_input_state->get_exe_name = get_builtin_name;
10646 #  endif
10647 # endif
10648 # if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0
10649 		{
10650 			const char *hp = get_local_var_value("HISTFILE");
10651 			if (!hp) {
10652 				hp = get_local_var_value("HOME");
10653 				if (hp)
10654 					hp = concat_path_file(hp, ".hush_history");
10655 			} else {
10656 				hp = xstrdup(hp);
10657 			}
10658 			if (hp) {
10659 				G.line_input_state->hist_file = hp;
10660 				//set_local_var(xasprintf("HISTFILE=%s", ...));
10661 			}
10662 #  if ENABLE_FEATURE_SH_HISTFILESIZE
10663 			hp = get_local_var_value("HISTFILESIZE");
10664 			G.line_input_state->max_history = size_from_HISTFILESIZE(hp);
10665 #  endif
10666 		}
10667 # endif
10668 	} else {
10669 		install_special_sighandlers();
10670 	}
10671 #elif ENABLE_HUSH_INTERACTIVE
10672 	/* No job control compiled in, only prompt/line editing */
10673 	if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
10674 		G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254);
10675 		if (G_interactive_fd < 0) {
10676 			/* try to dup to any fd */
10677 			G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, -1);
10678 			if (G_interactive_fd < 0)
10679 				/* give up */
10680 				G_interactive_fd = 0;
10681 		}
10682 	}
10683 	if (G_interactive_fd) {
10684 		close_on_exec_on(G_interactive_fd);
10685 	}
10686 	install_special_sighandlers();
10687 #else
10688 	/* We have interactiveness code disabled */
10689 	install_special_sighandlers();
10690 #endif
10691 	/* bash:
10692 	 * if interactive but not a login shell, sources ~/.bashrc
10693 	 * (--norc turns this off, --rcfile <file> overrides)
10694 	 */
10695 
10696 	if (G_interactive_fd) {
10697 #if ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT
10698 		/* Set (but not export) PS1/2 unless already set */
10699 		if (!get_local_var_value("PS1"))
10700 			set_local_var_from_halves("PS1", "\\w \\$ ");
10701 		if (!get_local_var_value("PS2"))
10702 			set_local_var_from_halves("PS2", "> ");
10703 #endif
10704 		if (!ENABLE_FEATURE_SH_EXTRA_QUIET) {
10705 			/* note: ash and hush share this string */
10706 			printf("\n\n%s %s\n"
10707 				IF_HUSH_HELP("Enter 'help' for a list of built-in commands.\n")
10708 				"\n",
10709 				bb_banner,
10710 				"hush - the humble shell"
10711 			);
10712 		}
10713 	}
10714 
10715 	parse_and_run_file(hfopen(NULL)); /* stdin */
10716 
10717  final_return:
10718 	hush_exit(G.last_exitcode);
10719 }
10720 
10721 
10722 /*
10723  * Built-ins
10724  */
builtin_true(char ** argv UNUSED_PARAM)10725 static int FAST_FUNC builtin_true(char **argv UNUSED_PARAM)
10726 {
10727 	return 0;
10728 }
10729 
10730 #if ENABLE_HUSH_TEST || ENABLE_HUSH_ECHO || ENABLE_HUSH_PRINTF || ENABLE_HUSH_KILL
run_applet_main(char ** argv,int (* applet_main_func)(int argc,char ** argv))10731 static NOINLINE int run_applet_main(char **argv, int (*applet_main_func)(int argc, char **argv))
10732 {
10733 	int argc = string_array_len(argv);
10734 	return applet_main_func(argc, argv);
10735 }
10736 #endif
10737 #if ENABLE_HUSH_TEST || BASH_TEST2
builtin_test(char ** argv)10738 static int FAST_FUNC builtin_test(char **argv)
10739 {
10740 	return run_applet_main(argv, test_main);
10741 }
10742 #endif
10743 #if ENABLE_HUSH_ECHO
builtin_echo(char ** argv)10744 static int FAST_FUNC builtin_echo(char **argv)
10745 {
10746 	return run_applet_main(argv, echo_main);
10747 }
10748 #endif
10749 #if ENABLE_HUSH_PRINTF
builtin_printf(char ** argv)10750 static int FAST_FUNC builtin_printf(char **argv)
10751 {
10752 	return run_applet_main(argv, printf_main);
10753 }
10754 #endif
10755 
10756 #if ENABLE_HUSH_HELP
builtin_help(char ** argv UNUSED_PARAM)10757 static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM)
10758 {
10759 	const struct built_in_command *x;
10760 
10761 	printf(
10762 		"Built-in commands:\n"
10763 		"------------------\n");
10764 	for (x = bltins1; x != &bltins1[ARRAY_SIZE(bltins1)]; x++) {
10765 		if (x->b_descr)
10766 			printf("%-10s%s\n", x->b_cmd, x->b_descr);
10767 	}
10768 	return EXIT_SUCCESS;
10769 }
10770 #endif
10771 
10772 #if MAX_HISTORY && ENABLE_FEATURE_EDITING
builtin_history(char ** argv UNUSED_PARAM)10773 static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM)
10774 {
10775 	show_history(G.line_input_state);
10776 	return EXIT_SUCCESS;
10777 }
10778 #endif
10779 
skip_dash_dash(char ** argv)10780 static char **skip_dash_dash(char **argv)
10781 {
10782 	argv++;
10783 	if (argv[0] && argv[0][0] == '-' && argv[0][1] == '-' && argv[0][2] == '\0')
10784 		argv++;
10785 	return argv;
10786 }
10787 
builtin_cd(char ** argv)10788 static int FAST_FUNC builtin_cd(char **argv)
10789 {
10790 	const char *newdir;
10791 
10792 	argv = skip_dash_dash(argv);
10793 	newdir = argv[0];
10794 	if (newdir == NULL) {
10795 		/* bash does nothing (exitcode 0) if HOME is ""; if it's unset,
10796 		 * bash says "bash: cd: HOME not set" and does nothing
10797 		 * (exitcode 1)
10798 		 */
10799 		const char *home = get_local_var_value("HOME");
10800 		newdir = home ? home : "/";
10801 	}
10802 	if (chdir(newdir)) {
10803 		/* Mimic bash message exactly */
10804 		bb_perror_msg("cd: %s", newdir);
10805 		return EXIT_FAILURE;
10806 	}
10807 	/* Read current dir (get_cwd(1) is inside) and set PWD.
10808 	 * Note: do not enforce exporting. If PWD was unset or unexported,
10809 	 * set it again, but do not export. bash does the same.
10810 	 */
10811 	set_pwd_var(/*flag:*/ 0);
10812 	return EXIT_SUCCESS;
10813 }
10814 
builtin_pwd(char ** argv UNUSED_PARAM)10815 static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM)
10816 {
10817 	puts(get_cwd(0));
10818 	return EXIT_SUCCESS;
10819 }
10820 
builtin_eval(char ** argv)10821 static int FAST_FUNC builtin_eval(char **argv)
10822 {
10823 	argv = skip_dash_dash(argv);
10824 
10825 	if (!argv[0])
10826 		return EXIT_SUCCESS;
10827 
10828 	IF_HUSH_MODE_X(G.x_mode_depth++;)
10829 	//bb_error_msg("%s: ++x_mode_depth=%d", __func__, G.x_mode_depth);
10830 	if (!argv[1]) {
10831 		/* bash:
10832 		 * eval "echo Hi; done" ("done" is syntax error):
10833 		 * "echo Hi" will not execute too.
10834 		 */
10835 		parse_and_run_string(argv[0]);
10836 	} else {
10837 		/* "The eval utility shall construct a command by
10838 		 * concatenating arguments together, separating
10839 		 * each with a <space> character."
10840 		 */
10841 		char *str, *p;
10842 		unsigned len = 0;
10843 		char **pp = argv;
10844 		do
10845 			len += strlen(*pp) + 1;
10846 		while (*++pp);
10847 		str = p = xmalloc(len);
10848 		pp = argv;
10849 		for (;;) {
10850 			p = stpcpy(p, *pp);
10851 			pp++;
10852 			if (!*pp)
10853 				break;
10854 			*p++ = ' ';
10855 		}
10856 		parse_and_run_string(str);
10857 		free(str);
10858 	}
10859 	IF_HUSH_MODE_X(G.x_mode_depth--;)
10860 	//bb_error_msg("%s: --x_mode_depth=%d", __func__, G.x_mode_depth);
10861 	return G.last_exitcode;
10862 }
10863 
builtin_exec(char ** argv)10864 static int FAST_FUNC builtin_exec(char **argv)
10865 {
10866 	argv = skip_dash_dash(argv);
10867 	if (argv[0] == NULL)
10868 		return EXIT_SUCCESS; /* bash does this */
10869 
10870 	/* Careful: we can end up here after [v]fork. Do not restore
10871 	 * tty pgrp then, only top-level shell process does that */
10872 	if (G_saved_tty_pgrp && getpid() == G.root_pid)
10873 		tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp);
10874 
10875 	/* Saved-redirect fds, script fds and G_interactive_fd are still
10876 	 * open here. However, they are all CLOEXEC, and execv below
10877 	 * closes them. Try interactive "exec ls -l /proc/self/fd",
10878 	 * it should show no extra open fds in the "ls" process.
10879 	 * If we'd try to run builtins/NOEXECs, this would need improving.
10880 	 */
10881 	//close_saved_fds_and_FILE_fds();
10882 
10883 	/* TODO: if exec fails, bash does NOT exit! We do.
10884 	 * We'll need to undo trap cleanup (it's inside execvp_or_die)
10885 	 * and tcsetpgrp, and this is inherently racy.
10886 	 */
10887 	execvp_or_die(argv);
10888 }
10889 
builtin_exit(char ** argv)10890 static int FAST_FUNC builtin_exit(char **argv)
10891 {
10892 	debug_printf_exec("%s()\n", __func__);
10893 
10894 	/* interactive bash:
10895 	 * # trap "echo EEE" EXIT
10896 	 * # exit
10897 	 * exit
10898 	 * There are stopped jobs.
10899 	 * (if there are _stopped_ jobs, running ones don't count)
10900 	 * # exit
10901 	 * exit
10902 	 * EEE (then bash exits)
10903 	 *
10904 	 * TODO: we can use G.exiting = -1 as indicator "last cmd was exit"
10905 	 */
10906 
10907 	/* note: EXIT trap is run by hush_exit */
10908 	argv = skip_dash_dash(argv);
10909 	if (argv[0] == NULL) {
10910 #if ENABLE_HUSH_TRAP
10911 		if (G.pre_trap_exitcode >= 0) /* "exit" in trap uses $? from before the trap */
10912 			hush_exit(G.pre_trap_exitcode);
10913 #endif
10914 		hush_exit(G.last_exitcode);
10915 	}
10916 	/* mimic bash: exit 123abc == exit 255 + error msg */
10917 	xfunc_error_retval = 255;
10918 	/* bash: exit -2 == exit 254, no error msg */
10919 	hush_exit(xatoi(argv[0]) & 0xff);
10920 }
10921 
10922 #if ENABLE_HUSH_TYPE
10923 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */
builtin_type(char ** argv)10924 static int FAST_FUNC builtin_type(char **argv)
10925 {
10926 	int ret = EXIT_SUCCESS;
10927 
10928 	while (*++argv) {
10929 		const char *type;
10930 		char *path = NULL;
10931 
10932 		if (0) {} /* make conditional compile easier below */
10933 		/*else if (find_alias(*argv))
10934 			type = "an alias";*/
10935 # if ENABLE_HUSH_FUNCTIONS
10936 		else if (find_function(*argv))
10937 			type = "a function";
10938 # endif
10939 		else if (find_builtin(*argv))
10940 			type = "a shell builtin";
10941 		else if ((path = find_in_path(*argv)) != NULL)
10942 			type = path;
10943 		else {
10944 			bb_error_msg("type: %s: not found", *argv);
10945 			ret = EXIT_FAILURE;
10946 			continue;
10947 		}
10948 
10949 		printf("%s is %s\n", *argv, type);
10950 		free(path);
10951 	}
10952 
10953 	return ret;
10954 }
10955 #endif
10956 
10957 #if ENABLE_HUSH_READ
10958 /* Interruptibility of read builtin in bash
10959  * (tested on bash-4.2.8 by sending signals (not by ^C)):
10960  *
10961  * Empty trap makes read ignore corresponding signal, for any signal.
10962  *
10963  * SIGINT:
10964  * - terminates non-interactive shell;
10965  * - interrupts read in interactive shell;
10966  * if it has non-empty trap:
10967  * - executes trap and returns to command prompt in interactive shell;
10968  * - executes trap and returns to read in non-interactive shell;
10969  * SIGTERM:
10970  * - is ignored (does not interrupt) read in interactive shell;
10971  * - terminates non-interactive shell;
10972  * if it has non-empty trap:
10973  * - executes trap and returns to read;
10974  * SIGHUP:
10975  * - terminates shell (regardless of interactivity);
10976  * if it has non-empty trap:
10977  * - executes trap and returns to read;
10978  * SIGCHLD from children:
10979  * - does not interrupt read regardless of interactivity:
10980  *   try: sleep 1 & read x; echo $x
10981  */
builtin_read(char ** argv)10982 static int FAST_FUNC builtin_read(char **argv)
10983 {
10984 	const char *r;
10985 	struct builtin_read_params params;
10986 
10987 	memset(&params, 0, sizeof(params));
10988 
10989 	/* "!": do not abort on errors.
10990 	 * Option string must start with "sr" to match BUILTIN_READ_xxx
10991 	 */
10992 	params.read_flags = getopt32(argv,
10993 # if BASH_READ_D
10994 		IF_NOT_HUSH_BASH_COMPAT("^")
10995 		"!srn:p:t:u:d:" IF_NOT_HUSH_BASH_COMPAT("\0" "-1"/*min 1 arg*/),
10996 		&params.opt_n, &params.opt_p, &params.opt_t, &params.opt_u, &params.opt_d
10997 # else
10998 		IF_NOT_HUSH_BASH_COMPAT("^")
10999 		"!srn:p:t:u:" IF_NOT_HUSH_BASH_COMPAT("\0" "-1"/*min 1 arg*/),
11000 		&params.opt_n, &params.opt_p, &params.opt_t, &params.opt_u
11001 # endif
11002 //TODO: print "read: need variable name"
11003 //for the case of !BASH "read" with no args (now it fails silently)
11004 //(or maybe extend getopt32() to emit a message if "-1" fails)
11005 	);
11006 	if ((uint32_t)params.read_flags == (uint32_t)-1)
11007 		return EXIT_FAILURE;
11008 	argv += optind;
11009 	params.argv = argv;
11010 	params.setvar = set_local_var_from_halves;
11011 	params.ifs = get_local_var_value("IFS"); /* can be NULL */
11012 
11013  again:
11014 	r = shell_builtin_read(&params);
11015 
11016 	if ((uintptr_t)r == 1 && errno == EINTR) {
11017 		unsigned sig = check_and_run_traps();
11018 		if (sig != SIGINT)
11019 			goto again;
11020 	}
11021 
11022 	if ((uintptr_t)r > 1) {
11023 		bb_simple_error_msg(r);
11024 		r = (char*)(uintptr_t)1;
11025 	}
11026 
11027 	return (uintptr_t)r;
11028 }
11029 #endif
11030 
11031 #if ENABLE_HUSH_UMASK
builtin_umask(char ** argv)11032 static int FAST_FUNC builtin_umask(char **argv)
11033 {
11034 	int rc;
11035 	mode_t mask;
11036 
11037 	rc = 1;
11038 	mask = umask(0);
11039 	argv = skip_dash_dash(argv);
11040 	if (argv[0]) {
11041 		mode_t old_mask = mask;
11042 
11043 		/* numeric umasks are taken as-is */
11044 		/* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
11045 		if (!isdigit(argv[0][0]))
11046 			mask ^= 0777;
11047 		mask = bb_parse_mode(argv[0], mask);
11048 		if (!isdigit(argv[0][0]))
11049 			mask ^= 0777;
11050 		if ((unsigned)mask > 0777) {
11051 			mask = old_mask;
11052 			/* bash messages:
11053 			 * bash: umask: 'q': invalid symbolic mode operator
11054 			 * bash: umask: 999: octal number out of range
11055 			 */
11056 			bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]);
11057 			rc = 0;
11058 		}
11059 	} else {
11060 		/* Mimic bash */
11061 		printf("%04o\n", (unsigned) mask);
11062 		/* fall through and restore mask which we set to 0 */
11063 	}
11064 	umask(mask);
11065 
11066 	return !rc; /* rc != 0 - success */
11067 }
11068 #endif
11069 
11070 #if ENABLE_HUSH_EXPORT || ENABLE_HUSH_TRAP
print_escaped(const char * s)11071 static void print_escaped(const char *s)
11072 {
11073 	if (*s == '\'')
11074 		goto squote;
11075 	do {
11076 		const char *p = strchrnul(s, '\'');
11077 		/* print 'xxxx', possibly just '' */
11078 		printf("'%.*s'", (int)(p - s), s);
11079 		if (*p == '\0')
11080 			break;
11081 		s = p;
11082  squote:
11083 		/* s points to '; print "'''...'''" */
11084 		putchar('"');
11085 		do putchar('\''); while (*++s == '\'');
11086 		putchar('"');
11087 	} while (*s);
11088 }
11089 #endif
11090 
11091 #if ENABLE_HUSH_EXPORT || ENABLE_HUSH_LOCAL || ENABLE_HUSH_READONLY
helper_export_local(char ** argv,unsigned flags)11092 static int helper_export_local(char **argv, unsigned flags)
11093 {
11094 	do {
11095 		char *name = *argv;
11096 		const char *name_end = endofname(name);
11097 
11098 		if (*name_end == '\0') {
11099 			struct variable *var, **vpp;
11100 
11101 			vpp = get_ptr_to_local_var(name, name_end - name);
11102 			var = vpp ? *vpp : NULL;
11103 
11104 			if (flags & SETFLAG_UNEXPORT) {
11105 				/* export -n NAME (without =VALUE) */
11106 				if (var) {
11107 					var->flg_export = 0;
11108 					debug_printf_env("%s: unsetenv '%s'\n", __func__, name);
11109 					unsetenv(name);
11110 				} /* else: export -n NOT_EXISTING_VAR: no-op */
11111 				continue;
11112 			}
11113 			if (flags & SETFLAG_EXPORT) {
11114 				/* export NAME (without =VALUE) */
11115 				if (var) {
11116 					var->flg_export = 1;
11117 					debug_printf_env("%s: putenv '%s'\n", __func__, var->varstr);
11118 					putenv(var->varstr);
11119 					continue;
11120 				}
11121 			}
11122 			if (flags & SETFLAG_MAKE_RO) {
11123 				/* readonly NAME (without =VALUE) */
11124 				if (var) {
11125 					var->flg_read_only = 1;
11126 					continue;
11127 				}
11128 			}
11129 # if ENABLE_HUSH_LOCAL
11130 			/* Is this "local" bltin? */
11131 			if (!(flags & (SETFLAG_EXPORT|SETFLAG_UNEXPORT|SETFLAG_MAKE_RO))) {
11132 				unsigned lvl = flags >> SETFLAG_VARLVL_SHIFT;
11133 				if (var && var->var_nest_level == lvl) {
11134 					/* "local x=abc; ...; local x" - ignore second local decl */
11135 					continue;
11136 				}
11137 			}
11138 # endif
11139 			/* Exporting non-existing variable.
11140 			 * bash does not put it in environment,
11141 			 * but remembers that it is exported,
11142 			 * and does put it in env when it is set later.
11143 			 * We just set it to "" and export.
11144 			 */
11145 			/* Or, it's "local NAME" (without =VALUE).
11146 			 * bash sets the value to "".
11147 			 */
11148 			/* Or, it's "readonly NAME" (without =VALUE).
11149 			 * bash remembers NAME and disallows its creation
11150 			 * in the future.
11151 			 */
11152 			name = xasprintf("%s=", name);
11153 		} else {
11154 			if (*name_end != '=') {
11155 				bb_error_msg("'%s': bad variable name", name);
11156 				/* do not parse following argv[]s: */
11157 				return 1;
11158 			}
11159 			/* (Un)exporting/making local NAME=VALUE */
11160 			name = xstrdup(name);
11161 			/* Testcase: export PS1='\w \$ ' */
11162 			unbackslash(name);
11163 		}
11164 		debug_printf_env("%s: set_local_var('%s')\n", __func__, name);
11165 		if (set_local_var(name, flags))
11166 			return EXIT_FAILURE;
11167 	} while (*++argv);
11168 	return EXIT_SUCCESS;
11169 }
11170 #endif
11171 
11172 #if ENABLE_HUSH_EXPORT
builtin_export(char ** argv)11173 static int FAST_FUNC builtin_export(char **argv)
11174 {
11175 	unsigned opt_unexport;
11176 
11177 # if ENABLE_HUSH_EXPORT_N
11178 	/* "!": do not abort on errors */
11179 	opt_unexport = getopt32(argv, "!n");
11180 	if (opt_unexport == (uint32_t)-1)
11181 		return EXIT_FAILURE;
11182 	argv += optind;
11183 # else
11184 	opt_unexport = 0;
11185 	argv++;
11186 # endif
11187 
11188 	if (argv[0] == NULL) {
11189 		char **e = environ;
11190 		if (e) {
11191 			while (*e) {
11192 # if 0
11193 				puts(*e++);
11194 # else
11195 				/* ash emits: export VAR='VAL'
11196 				 * bash: declare -x VAR="VAL"
11197 				 * we follow ash example */
11198 				const char *s = *e++;
11199 				const char *p = strchr(s, '=');
11200 
11201 				if (!p) /* wtf? take next variable */
11202 					continue;
11203 				/* export var= */
11204 				printf("export %.*s", (int)(p - s) + 1, s);
11205 				print_escaped(p + 1);
11206 				putchar('\n');
11207 # endif
11208 			}
11209 			/*fflush_all(); - done after each builtin anyway */
11210 		}
11211 		return EXIT_SUCCESS;
11212 	}
11213 
11214 	return helper_export_local(argv, opt_unexport ? SETFLAG_UNEXPORT : SETFLAG_EXPORT);
11215 }
11216 #endif
11217 
11218 #if ENABLE_HUSH_LOCAL
builtin_local(char ** argv)11219 static int FAST_FUNC builtin_local(char **argv)
11220 {
11221 	if (G.func_nest_level == 0) {
11222 		bb_error_msg("%s: not in a function", argv[0]);
11223 		return EXIT_FAILURE; /* bash compat */
11224 	}
11225 	argv++;
11226 	/* Since all builtins run in a nested variable level,
11227 	 * need to use level - 1 here. Or else the variable will be removed at once
11228 	 * after builtin returns.
11229 	 */
11230 	return helper_export_local(argv, (G.var_nest_level - 1) << SETFLAG_VARLVL_SHIFT);
11231 }
11232 #endif
11233 
11234 #if ENABLE_HUSH_READONLY
builtin_readonly(char ** argv)11235 static int FAST_FUNC builtin_readonly(char **argv)
11236 {
11237 	argv++;
11238 	if (*argv == NULL) {
11239 		/* bash: readonly [-p]: list all readonly VARs
11240 		 * (-p has no effect in bash)
11241 		 */
11242 		struct variable *e;
11243 		for (e = G.top_var; e; e = e->next) {
11244 			if (e->flg_read_only) {
11245 //TODO: quote value: readonly VAR='VAL'
11246 				printf("readonly %s\n", e->varstr);
11247 			}
11248 		}
11249 		return EXIT_SUCCESS;
11250 	}
11251 	return helper_export_local(argv, SETFLAG_MAKE_RO);
11252 }
11253 #endif
11254 
11255 #if ENABLE_HUSH_UNSET
11256 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#unset */
builtin_unset(char ** argv)11257 static int FAST_FUNC builtin_unset(char **argv)
11258 {
11259 	int ret;
11260 	unsigned opts;
11261 
11262 	/* "!": do not abort on errors */
11263 	/* "+": stop at 1st non-option */
11264 	opts = getopt32(argv, "!+vf");
11265 	if (opts == (unsigned)-1)
11266 		return EXIT_FAILURE;
11267 	if (opts == 3) {
11268 		bb_simple_error_msg("unset: -v and -f are exclusive");
11269 		return EXIT_FAILURE;
11270 	}
11271 	argv += optind;
11272 
11273 	ret = EXIT_SUCCESS;
11274 	while (*argv) {
11275 		if (!(opts & 2)) { /* not -f */
11276 			if (unset_local_var(*argv)) {
11277 				/* unset <nonexistent_var> doesn't fail.
11278 				 * Error is when one tries to unset RO var.
11279 				 * Message was printed by unset_local_var. */
11280 				ret = EXIT_FAILURE;
11281 			}
11282 		}
11283 # if ENABLE_HUSH_FUNCTIONS
11284 		else {
11285 			unset_func(*argv);
11286 		}
11287 # endif
11288 		argv++;
11289 	}
11290 	return ret;
11291 }
11292 #endif
11293 
11294 #if ENABLE_HUSH_SET
11295 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set
11296  * built-in 'set' handler
11297  * SUSv3 says:
11298  * set [-abCefhmnuvx] [-o option] [argument...]
11299  * set [+abCefhmnuvx] [+o option] [argument...]
11300  * set -- [argument...]
11301  * set -o
11302  * set +o
11303  * Implementations shall support the options in both their hyphen and
11304  * plus-sign forms. These options can also be specified as options to sh.
11305  * Examples:
11306  * Write out all variables and their values: set
11307  * Set $1, $2, and $3 and set "$#" to 3: set c a b
11308  * Turn on the -x and -v options: set -xv
11309  * Unset all positional parameters: set --
11310  * Set $1 to the value of x, even if it begins with '-' or '+': set -- "$x"
11311  * Set the positional parameters to the expansion of x, even if x expands
11312  * with a leading '-' or '+': set -- $x
11313  *
11314  * So far, we only support "set -- [argument...]" and some of the short names.
11315  */
builtin_set(char ** argv)11316 static int FAST_FUNC builtin_set(char **argv)
11317 {
11318 	int n;
11319 	char **pp, **g_argv;
11320 	char *arg = *++argv;
11321 
11322 	if (arg == NULL) {
11323 		struct variable *e;
11324 		for (e = G.top_var; e; e = e->next)
11325 			puts(e->varstr);
11326 		return EXIT_SUCCESS;
11327 	}
11328 
11329 	do {
11330 		if (strcmp(arg, "--") == 0) {
11331 			++argv;
11332 			goto set_argv;
11333 		}
11334 		if (arg[0] != '+' && arg[0] != '-')
11335 			break;
11336 		for (n = 1; arg[n]; ++n) {
11337 			if (set_mode((arg[0] == '-'), arg[n], argv[1])) {
11338 				bb_error_msg("%s: %s: invalid option", "set", arg);
11339 				return EXIT_FAILURE;
11340 			}
11341 			if (arg[n] == 'o' && argv[1])
11342 				argv++;
11343 		}
11344 	} while ((arg = *++argv) != NULL);
11345 	/* Now argv[0] is 1st argument */
11346 
11347 	if (arg == NULL)
11348 		return EXIT_SUCCESS;
11349  set_argv:
11350 
11351 	/* NB: G.global_argv[0] ($0) is never freed/changed */
11352 	g_argv = G.global_argv;
11353 	if (G.global_args_malloced) {
11354 		pp = g_argv;
11355 		while (*++pp)
11356 			free(*pp);
11357 		g_argv[1] = NULL;
11358 	} else {
11359 		G.global_args_malloced = 1;
11360 		pp = xzalloc(sizeof(pp[0]) * 2);
11361 		pp[0] = g_argv[0]; /* retain $0 */
11362 		g_argv = pp;
11363 	}
11364 	/* This realloc's G.global_argv */
11365 	G.global_argv = pp = add_strings_to_strings(g_argv, argv, /*dup:*/ 1);
11366 
11367 	G.global_argc = 1 + string_array_len(pp + 1);
11368 
11369 	return EXIT_SUCCESS;
11370 }
11371 #endif
11372 
builtin_shift(char ** argv)11373 static int FAST_FUNC builtin_shift(char **argv)
11374 {
11375 	int n = 1;
11376 	argv = skip_dash_dash(argv);
11377 	if (argv[0]) {
11378 		n = bb_strtou(argv[0], NULL, 10);
11379 		if (errno || n < 0) {
11380 			/* shared string with ash.c */
11381 			bb_error_msg("Illegal number: %s", argv[0]);
11382 			/*
11383 			 * ash aborts in this case.
11384 			 * bash prints error message and set $? to 1.
11385 			 * Interestingly, for "shift 99999" bash does not
11386 			 * print error message, but does set $? to 1
11387 			 * (and does no shifting at all).
11388 			 */
11389 		}
11390 	}
11391 	if (n >= 0 && n < G.global_argc) {
11392 		if (G_global_args_malloced) {
11393 			int m = 1;
11394 			while (m <= n)
11395 				free(G.global_argv[m++]);
11396 		}
11397 		G.global_argc -= n;
11398 		memmove(&G.global_argv[1], &G.global_argv[n+1],
11399 				G.global_argc * sizeof(G.global_argv[0]));
11400 		return EXIT_SUCCESS;
11401 	}
11402 	return EXIT_FAILURE;
11403 }
11404 
11405 #if ENABLE_HUSH_GETOPTS
builtin_getopts(char ** argv)11406 static int FAST_FUNC builtin_getopts(char **argv)
11407 {
11408 /* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getopts.html
11409 
11410 TODO:
11411 If a required argument is not found, and getopts is not silent,
11412 a question mark (?) is placed in VAR, OPTARG is unset, and a
11413 diagnostic message is printed.  If getopts is silent, then a
11414 colon (:) is placed in VAR and OPTARG is set to the option
11415 character found.
11416 
11417 Test that VAR is a valid variable name?
11418 
11419 "Whenever the shell is invoked, OPTIND shall be initialized to 1"
11420 */
11421 	char cbuf[2];
11422 	const char *cp, *optstring, *var;
11423 	int c, n, exitcode, my_opterr;
11424 	unsigned count;
11425 
11426 	optstring = *++argv;
11427 	if (!optstring || !(var = *++argv)) {
11428 		bb_simple_error_msg("usage: getopts OPTSTRING VAR [ARGS]");
11429 		return EXIT_FAILURE;
11430 	}
11431 
11432 	if (argv[1])
11433 		argv[0] = G.global_argv[0]; /* for error messages in getopt() */
11434 	else
11435 		argv = G.global_argv;
11436 	cbuf[1] = '\0';
11437 
11438 	my_opterr = 0;
11439 	if (optstring[0] != ':') {
11440 		cp = get_local_var_value("OPTERR");
11441 		/* 0 if "OPTERR=0", 1 otherwise */
11442 		my_opterr = (!cp || NOT_LONE_CHAR(cp, '0'));
11443 	}
11444 
11445 	/* getopts stops on first non-option. Add "+" to force that */
11446 	/*if (optstring[0] != '+')*/ {
11447 		char *s = alloca(strlen(optstring) + 2);
11448 		sprintf(s, "+%s", optstring);
11449 		optstring = s;
11450 	}
11451 
11452 	/* Naively, now we should just
11453 	 *	cp = get_local_var_value("OPTIND");
11454 	 *	optind = cp ? atoi(cp) : 0;
11455 	 *	optarg = NULL;
11456 	 *	opterr = my_opterr;
11457 	 *	c = getopt(string_array_len(argv), argv, optstring);
11458 	 * and be done? Not so fast...
11459 	 * Unlike normal getopt() usage in C programs, here
11460 	 * each successive call will (usually) have the same argv[] CONTENTS,
11461 	 * but not the ADDRESSES. Worse yet, it's possible that between
11462 	 * invocations of "getopts", there will be calls to shell builtins
11463 	 * which use getopt() internally. Example:
11464 	 *	while getopts "abc" RES -a -bc -abc de; do
11465 	 *		unset -ff func
11466 	 *	done
11467 	 * This would not work correctly: getopt() call inside "unset"
11468 	 * modifies internal libc state which is tracking position in
11469 	 * multi-option strings ("-abc"). At best, it can skip options
11470 	 * or return the same option infinitely. With glibc implementation
11471 	 * of getopt(), it would use outright invalid pointers and return
11472 	 * garbage even _without_ "unset" mangling internal state.
11473 	 *
11474 	 * We resort to resetting getopt() state and calling it N times,
11475 	 * until we get Nth result (or failure).
11476 	 * (N == G.getopt_count is reset to 0 whenever OPTIND is [un]set).
11477 	 */
11478 	GETOPT_RESET();
11479 	count = 0;
11480 	n = string_array_len(argv);
11481 	do {
11482 		optarg = NULL;
11483 		opterr = (count < G.getopt_count) ? 0 : my_opterr;
11484 		c = getopt(n, argv, optstring);
11485 		if (c < 0)
11486 			break;
11487 		count++;
11488 	} while (count <= G.getopt_count);
11489 
11490 	/* Set OPTIND. Prevent resetting of the magic counter! */
11491 	set_local_var_from_halves("OPTIND", utoa(optind));
11492 	G.getopt_count = count; /* "next time, give me N+1'th result" */
11493 	GETOPT_RESET(); /* just in case */
11494 
11495 	/* Set OPTARG */
11496 	/* Always set or unset, never left as-is, even on exit/error:
11497 	 * "If no option was found, or if the option that was found
11498 	 * does not have an option-argument, OPTARG shall be unset."
11499 	 */
11500 	cp = optarg;
11501 	if (c == '?') {
11502 		/* If ":optstring" and unknown option is seen,
11503 		 * it is stored to OPTARG.
11504 		 */
11505 		if (optstring[1] == ':') {
11506 			cbuf[0] = optopt;
11507 			cp = cbuf;
11508 		}
11509 	}
11510 	if (cp)
11511 		set_local_var_from_halves("OPTARG", cp);
11512 	else
11513 		unset_local_var("OPTARG");
11514 
11515 	/* Convert -1 to "?" */
11516 	exitcode = EXIT_SUCCESS;
11517 	if (c < 0) { /* -1: end of options */
11518 		exitcode = EXIT_FAILURE;
11519 		c = '?';
11520 	}
11521 
11522 	/* Set VAR */
11523 	cbuf[0] = c;
11524 	set_local_var_from_halves(var, cbuf);
11525 
11526 	return exitcode;
11527 }
11528 #endif
11529 
builtin_source(char ** argv)11530 static int FAST_FUNC builtin_source(char **argv)
11531 {
11532 	char *arg_path, *filename;
11533 	HFILE *input;
11534 	save_arg_t sv;
11535 	char *args_need_save;
11536 #if ENABLE_HUSH_FUNCTIONS
11537 	smallint sv_flg;
11538 #endif
11539 
11540 	argv = skip_dash_dash(argv);
11541 	filename = argv[0];
11542 	if (!filename) {
11543 		/* bash says: "bash: .: filename argument required" */
11544 		return 2; /* bash compat */
11545 	}
11546 	arg_path = NULL;
11547 	if (!strchr(filename, '/')) {
11548 		arg_path = find_in_path(filename);
11549 		if (arg_path)
11550 			filename = arg_path;
11551 		else if (!ENABLE_HUSH_BASH_SOURCE_CURDIR) {
11552 			errno = ENOENT;
11553 			bb_simple_perror_msg(filename);
11554 			return EXIT_FAILURE;
11555 		}
11556 	}
11557 	input = hfopen(filename);
11558 	free(arg_path);
11559 	if (!input) {
11560 		bb_perror_msg("%s", filename);
11561 		/* POSIX: non-interactive shell should abort here,
11562 		 * not merely fail. So far no one complained :)
11563 		 */
11564 		return EXIT_FAILURE;
11565 	}
11566 
11567 #if ENABLE_HUSH_FUNCTIONS
11568 	sv_flg = G_flag_return_in_progress;
11569 	/* "we are inside sourced file, ok to use return" */
11570 	G_flag_return_in_progress = -1;
11571 #endif
11572 	args_need_save = argv[1]; /* used as a boolean variable */
11573 	if (args_need_save)
11574 		save_and_replace_G_args(&sv, argv);
11575 
11576 	/* "false; . ./empty_line; echo Zero:$?" should print 0 */
11577 	G.last_exitcode = 0;
11578 	parse_and_run_file(input);
11579 	hfclose(input);
11580 
11581 	if (args_need_save) /* can't use argv[1] instead: "shift" can mangle it */
11582 		restore_G_args(&sv, argv);
11583 #if ENABLE_HUSH_FUNCTIONS
11584 	G_flag_return_in_progress = sv_flg;
11585 #endif
11586 
11587 	return G.last_exitcode;
11588 }
11589 
11590 #if ENABLE_HUSH_TRAP
builtin_trap(char ** argv)11591 static int FAST_FUNC builtin_trap(char **argv)
11592 {
11593 	int sig;
11594 	char *new_cmd;
11595 
11596 	if (!G_traps)
11597 		G_traps = xzalloc(sizeof(G_traps[0]) * NSIG);
11598 
11599 	argv++;
11600 	if (!*argv) {
11601 		int i;
11602 		/* No args: print all trapped */
11603 		for (i = 0; i < NSIG; ++i) {
11604 			if (G_traps[i]) {
11605 				printf("trap -- ");
11606 				print_escaped(G_traps[i]);
11607 				/* note: bash adds "SIG", but only if invoked
11608 				 * as "bash". If called as "sh", or if set -o posix,
11609 				 * then it prints short signal names.
11610 				 * We are printing short names: */
11611 				printf(" %s\n", get_signame(i));
11612 			}
11613 		}
11614 		/*fflush_all(); - done after each builtin anyway */
11615 		return EXIT_SUCCESS;
11616 	}
11617 
11618 	new_cmd = NULL;
11619 	/* If first arg is a number: reset all specified signals */
11620 	sig = bb_strtou(*argv, NULL, 10);
11621 	if (errno == 0) {
11622 		int ret;
11623  process_sig_list:
11624 		ret = EXIT_SUCCESS;
11625 		while (*argv) {
11626 			sighandler_t handler;
11627 
11628 			sig = get_signum(*argv++);
11629 			if (sig < 0) {
11630 				ret = EXIT_FAILURE;
11631 				/* Mimic bash message exactly */
11632 				bb_error_msg("trap: %s: invalid signal specification", argv[-1]);
11633 				continue;
11634 			}
11635 
11636 			free(G_traps[sig]);
11637 			G_traps[sig] = xstrdup(new_cmd);
11638 
11639 			debug_printf("trap: setting SIG%s (%i) to '%s'\n",
11640 				get_signame(sig), sig, G_traps[sig]);
11641 
11642 			/* There is no signal for 0 (EXIT) */
11643 			if (sig == 0)
11644 				continue;
11645 
11646 			if (new_cmd)
11647 				handler = (new_cmd[0] ? record_pending_signo : SIG_IGN);
11648 			else
11649 				/* We are removing trap handler */
11650 				handler = pick_sighandler(sig);
11651 			install_sighandler(sig, handler);
11652 		}
11653 		return ret;
11654 	}
11655 
11656 	if (!argv[1]) { /* no second arg */
11657 		bb_simple_error_msg("trap: invalid arguments");
11658 		return EXIT_FAILURE;
11659 	}
11660 
11661 	/* First arg is "-": reset all specified to default */
11662 	/* First arg is "--": skip it, the rest is "handler SIGs..." */
11663 	/* Everything else: set arg as signal handler
11664 	 * (includes "" case, which ignores signal) */
11665 	if (argv[0][0] == '-') {
11666 		if (argv[0][1] == '\0') { /* "-" */
11667 			/* new_cmd remains NULL: "reset these sigs" */
11668 			goto reset_traps;
11669 		}
11670 		if (argv[0][1] == '-' && argv[0][2] == '\0') { /* "--" */
11671 			argv++;
11672 		}
11673 		/* else: "-something", no special meaning */
11674 	}
11675 	new_cmd = *argv;
11676  reset_traps:
11677 	argv++;
11678 	goto process_sig_list;
11679 }
11680 #endif
11681 
11682 #if ENABLE_HUSH_JOB
parse_jobspec(const char * str)11683 static struct pipe *parse_jobspec(const char *str)
11684 {
11685 	struct pipe *pi;
11686 	unsigned jobnum;
11687 
11688 	if (sscanf(str, "%%%u", &jobnum) != 1) {
11689 		if (str[0] != '%'
11690 		 || (str[1] != '%' && str[1] != '+' && str[1] != '\0')
11691 		) {
11692 			bb_error_msg("bad argument '%s'", str);
11693 			return NULL;
11694 		}
11695 		/* It is "%%", "%+" or "%" - current job */
11696 		jobnum = G.last_jobid;
11697 		if (jobnum == 0) {
11698 			bb_simple_error_msg("no current job");
11699 			return NULL;
11700 		}
11701 	}
11702 	for (pi = G.job_list; pi; pi = pi->next) {
11703 		if (pi->jobid == jobnum) {
11704 			return pi;
11705 		}
11706 	}
11707 	bb_error_msg("%u: no such job", jobnum);
11708 	return NULL;
11709 }
11710 
builtin_jobs(char ** argv UNUSED_PARAM)11711 static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM)
11712 {
11713 	struct pipe *job;
11714 	const char *status_string;
11715 
11716 	checkjobs(NULL, 0 /*(no pid to wait for)*/);
11717 	for (job = G.job_list; job; job = job->next) {
11718 		if (job->alive_cmds == job->stopped_cmds)
11719 			status_string = "Stopped";
11720 		else
11721 			status_string = "Running";
11722 
11723 		printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->cmdtext);
11724 	}
11725 
11726 	clean_up_last_dead_job();
11727 
11728 	return EXIT_SUCCESS;
11729 }
11730 
11731 /* built-in 'fg' and 'bg' handler */
builtin_fg_bg(char ** argv)11732 static int FAST_FUNC builtin_fg_bg(char **argv)
11733 {
11734 	int i;
11735 	struct pipe *pi;
11736 
11737 	if (!G_interactive_fd)
11738 		return EXIT_FAILURE;
11739 
11740 	/* If they gave us no args, assume they want the last backgrounded task */
11741 	if (!argv[1]) {
11742 		for (pi = G.job_list; pi; pi = pi->next) {
11743 			if (pi->jobid == G.last_jobid) {
11744 				goto found;
11745 			}
11746 		}
11747 		bb_error_msg("%s: no current job", argv[0]);
11748 		return EXIT_FAILURE;
11749 	}
11750 
11751 	pi = parse_jobspec(argv[1]);
11752 	if (!pi)
11753 		return EXIT_FAILURE;
11754  found:
11755 	/* TODO: bash prints a string representation
11756 	 * of job being foregrounded (like "sleep 1 | cat") */
11757 	if (argv[0][0] == 'f' && G_saved_tty_pgrp) {
11758 		/* Put the job into the foreground. */
11759 		tcsetpgrp(G_interactive_fd, pi->pgrp);
11760 	}
11761 
11762 	/* Restart the processes in the job */
11763 	debug_printf_jobs("reviving %d procs, pgrp %d\n", pi->num_cmds, pi->pgrp);
11764 	for (i = 0; i < pi->num_cmds; i++) {
11765 		debug_printf_jobs("reviving pid %d\n", pi->cmds[i].pid);
11766 	}
11767 	pi->stopped_cmds = 0;
11768 
11769 	i = kill(- pi->pgrp, SIGCONT);
11770 	if (i < 0) {
11771 		if (errno == ESRCH) {
11772 			delete_finished_job(pi);
11773 			return EXIT_SUCCESS;
11774 		}
11775 		bb_simple_perror_msg("kill (SIGCONT)");
11776 	}
11777 
11778 	if (argv[0][0] == 'f') {
11779 		remove_job_from_table(pi); /* FG job shouldn't be in job table */
11780 		return checkjobs_and_fg_shell(pi);
11781 	}
11782 	return EXIT_SUCCESS;
11783 }
11784 #endif
11785 
11786 #if ENABLE_HUSH_KILL
builtin_kill(char ** argv)11787 static int FAST_FUNC builtin_kill(char **argv)
11788 {
11789 	int ret = 0;
11790 
11791 # if ENABLE_HUSH_JOB
11792 	if (argv[1] && strcmp(argv[1], "-l") != 0) {
11793 		int i = 1;
11794 
11795 		do {
11796 			struct pipe *pi;
11797 			char *dst;
11798 			int j, n;
11799 
11800 			if (argv[i][0] != '%')
11801 				continue;
11802 			/*
11803 			 * "kill %N" - job kill
11804 			 * Converting to pgrp / pid kill
11805 			 */
11806 			pi = parse_jobspec(argv[i]);
11807 			if (!pi) {
11808 				/* Eat bad jobspec */
11809 				j = i;
11810 				do {
11811 					j++;
11812 					argv[j - 1] = argv[j];
11813 				} while (argv[j]);
11814 				ret = 1;
11815 				i--;
11816 				continue;
11817 			}
11818 			/*
11819 			 * In jobs started under job control, we signal
11820 			 * entire process group by kill -PGRP_ID.
11821 			 * This happens, f.e., in interactive shell.
11822 			 *
11823 			 * Otherwise, we signal each child via
11824 			 * kill PID1 PID2 PID3.
11825 			 * Testcases:
11826 			 * sh -c 'sleep 1|sleep 1 & kill %1'
11827 			 * sh -c 'true|sleep 2 & sleep 1; kill %1'
11828 			 * sh -c 'true|sleep 1 & sleep 2; kill %1'
11829 			 */
11830 			n = G_interactive_fd ? 1 : pi->num_cmds;
11831 			dst = alloca(n * sizeof(int)*4);
11832 			argv[i] = dst;
11833 			if (G_interactive_fd)
11834 				dst += sprintf(dst, " -%u", (int)pi->pgrp);
11835 			else for (j = 0; j < n; j++) {
11836 				struct command *cmd = &pi->cmds[j];
11837 				/* Skip exited members of the job */
11838 				if (cmd->pid == 0)
11839 					continue;
11840 				/*
11841 				 * kill_main has matching code to expect
11842 				 * leading space. Needed to not confuse
11843 				 * negative pids with "kill -SIGNAL_NO" syntax
11844 				 */
11845 				dst += sprintf(dst, " %u", (int)cmd->pid);
11846 			}
11847 			*dst = '\0';
11848 		} while (argv[++i]);
11849 	}
11850 # endif
11851 
11852 	if (argv[1] || ret == 0) {
11853 		ret = run_applet_main(argv, kill_main);
11854 	}
11855 	/* else: ret = 1, "kill %bad_jobspec" case */
11856 	return ret;
11857 }
11858 #endif
11859 
11860 #if ENABLE_HUSH_WAIT
11861 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/wait.html */
11862 # if !ENABLE_HUSH_JOB
11863 #  define wait_for_child_or_signal(pipe,pid) wait_for_child_or_signal(pid)
11864 # endif
wait_for_child_or_signal(struct pipe * waitfor_pipe,pid_t waitfor_pid)11865 static int wait_for_child_or_signal(struct pipe *waitfor_pipe, pid_t waitfor_pid)
11866 {
11867 	int ret = 0;
11868 	for (;;) {
11869 		int sig;
11870 		sigset_t oldset;
11871 
11872 		if (!sigisemptyset(&G.pending_set))
11873 			goto check_sig;
11874 
11875 		/* waitpid is not interruptible by SA_RESTARTed
11876 		 * signals which we use. Thus, this ugly dance:
11877 		 */
11878 
11879 		/* Make sure possible SIGCHLD is stored in kernel's
11880 		 * pending signal mask before we call waitpid.
11881 		 * Or else we may race with SIGCHLD, lose it,
11882 		 * and get stuck in sigsuspend...
11883 		 */
11884 		sigfillset(&oldset); /* block all signals, remember old set */
11885 		sigprocmask2(SIG_SETMASK, &oldset);
11886 
11887 		if (!sigisemptyset(&G.pending_set)) {
11888 			/* Crap! we raced with some signal! */
11889 			goto restore;
11890 		}
11891 
11892 		/*errno = 0; - checkjobs does this */
11893 /* Can't pass waitfor_pipe into checkjobs(): it won't be interruptible */
11894 		ret = checkjobs(NULL, waitfor_pid); /* waitpid(WNOHANG) inside */
11895 		debug_printf_exec("checkjobs:%d\n", ret);
11896 # if ENABLE_HUSH_JOB
11897 		if (waitfor_pipe) {
11898 			int rcode = job_exited_or_stopped(waitfor_pipe);
11899 			debug_printf_exec("job_exited_or_stopped:%d\n", rcode);
11900 			if (rcode >= 0) {
11901 				ret = rcode;
11902 				sigprocmask(SIG_SETMASK, &oldset, NULL);
11903 				break;
11904 			}
11905 		}
11906 # endif
11907 		/* if ECHILD, there are no children (ret is -1 or 0) */
11908 		/* if ret == 0, no children changed state */
11909 		/* if ret != 0, it's exitcode+1 of exited waitfor_pid child */
11910 		if (errno == ECHILD || ret) {
11911 			ret--;
11912 			if (ret < 0) /* if ECHILD, may need to fix "ret" */
11913 				ret = 0;
11914 # if ENABLE_HUSH_BASH_COMPAT
11915 			if (waitfor_pid == -1 && errno == ECHILD) {
11916 				/* exitcode of "wait -n" with no children is 127, not 0 */
11917 				ret = 127;
11918 			}
11919 # endif
11920 			sigprocmask(SIG_SETMASK, &oldset, NULL);
11921 			break;
11922 		}
11923 		/* Wait for SIGCHLD or any other signal */
11924 		/* It is vitally important for sigsuspend that SIGCHLD has non-DFL handler! */
11925 		/* Note: sigsuspend invokes signal handler */
11926 		sigsuspend(&oldset);
11927 		/* ^^^ add "sigdelset(&oldset, SIGCHLD)" before sigsuspend
11928 		 * to make sure SIGCHLD is not masked off?
11929 		 * It was reported that this:
11930 		 *	fn() { : | return; }
11931 		 *	shopt -s lastpipe
11932 		 *	fn
11933 		 *	exec hush SCRIPT
11934 		 * under bash 4.4.23 runs SCRIPT with SIGCHLD masked,
11935 		 * making "wait" commands in SCRIPT block forever.
11936 		 */
11937  restore:
11938 		sigprocmask(SIG_SETMASK, &oldset, NULL);
11939  check_sig:
11940 		/* So, did we get a signal? */
11941 		sig = check_and_run_traps();
11942 		if (sig /*&& sig != SIGCHLD - always true */) {
11943 			/* Do this for any (non-ignored) signal, not only for ^C */
11944 			ret = 128 | sig;
11945 			break;
11946 		}
11947 		/* SIGCHLD, or no signal, or ignored one, such as SIGQUIT. Repeat */
11948 	}
11949 	return ret;
11950 }
11951 
builtin_wait(char ** argv)11952 static int FAST_FUNC builtin_wait(char **argv)
11953 {
11954 	int ret;
11955 	int status;
11956 
11957 	argv = skip_dash_dash(argv);
11958 # if ENABLE_HUSH_BASH_COMPAT
11959 	if (argv[0] && strcmp(argv[0], "-n") == 0) {
11960 		/* wait -n */
11961 		/* (bash accepts "wait -n PID" too and ignores PID) */
11962 		G.dead_job_exitcode = -1;
11963 		return wait_for_child_or_signal(NULL, -1 /*no job, wait for one job*/);
11964 	}
11965 # endif
11966 	if (argv[0] == NULL) {
11967 		/* Don't care about wait results */
11968 		/* Note 1: must wait until there are no more children */
11969 		/* Note 2: must be interruptible */
11970 		/* Examples:
11971 		 * $ sleep 3 & sleep 6 & wait
11972 		 * [1] 30934 sleep 3
11973 		 * [2] 30935 sleep 6
11974 		 * [1] Done                   sleep 3
11975 		 * [2] Done                   sleep 6
11976 		 * $ sleep 3 & sleep 6 & wait
11977 		 * [1] 30936 sleep 3
11978 		 * [2] 30937 sleep 6
11979 		 * [1] Done                   sleep 3
11980 		 * ^C <-- after ~4 sec from keyboard
11981 		 * $
11982 		 */
11983 		return wait_for_child_or_signal(NULL, 0 /*no job and no pid to wait for*/);
11984 	}
11985 
11986 	do {
11987 		pid_t pid = bb_strtou(*argv, NULL, 10);
11988 		if (errno || pid <= 0) {
11989 # if ENABLE_HUSH_JOB
11990 			if (argv[0][0] == '%') {
11991 				struct pipe *wait_pipe;
11992 				ret = 127; /* bash compat for bad jobspecs */
11993 				wait_pipe = parse_jobspec(*argv);
11994 				if (wait_pipe) {
11995 					ret = job_exited_or_stopped(wait_pipe);
11996 					if (ret < 0) {
11997 						ret = wait_for_child_or_signal(wait_pipe, 0);
11998 					} else {
11999 						/* waiting on "last dead job" removes it */
12000 						clean_up_last_dead_job();
12001 					}
12002 				}
12003 				/* else: parse_jobspec() already emitted error msg */
12004 				continue;
12005 			}
12006 # endif
12007 			/* mimic bash message */
12008 			bb_error_msg("wait: '%s': not a pid or valid job spec", *argv);
12009 			ret = EXIT_FAILURE;
12010 			continue; /* bash checks all argv[] */
12011 		}
12012 
12013 		/* Do we have such child? */
12014 		ret = waitpid(pid, &status, WNOHANG);
12015 		if (ret < 0) {
12016 			/* No */
12017 			ret = 127;
12018 			if (errno == ECHILD) {
12019 				if (pid == G.last_bg_pid) {
12020 					/* "wait $!" but last bg task has already exited. Try:
12021 					 * (sleep 1; exit 3) & sleep 2; echo $?; wait $!; echo $?
12022 					 * In bash it prints exitcode 0, then 3.
12023 					 * In dash, it is 127.
12024 					 */
12025 					ret = G.last_bg_pid_exitcode;
12026 				} else {
12027 					/* Example: "wait 1". mimic bash message */
12028 					bb_error_msg("wait: pid %u is not a child of this shell", (unsigned)pid);
12029 				}
12030 			} else {
12031 				/* ??? */
12032 				bb_perror_msg("wait %s", *argv);
12033 			}
12034 			continue; /* bash checks all argv[] */
12035 		}
12036 		if (ret == 0) {
12037 			/* Yes, and it still runs */
12038 			ret = wait_for_child_or_signal(NULL, pid);
12039 		} else {
12040 			/* Yes, and it just exited */
12041 			process_wait_result(NULL, pid, status);
12042 			ret = WEXITSTATUS(status);
12043 			if (WIFSIGNALED(status))
12044 				ret = 128 | WTERMSIG(status);
12045 		}
12046 	} while (*++argv);
12047 
12048 	return ret;
12049 }
12050 #endif
12051 
12052 #if ENABLE_HUSH_LOOPS || ENABLE_HUSH_FUNCTIONS
parse_numeric_argv1(char ** argv,unsigned def,unsigned def_min)12053 static unsigned parse_numeric_argv1(char **argv, unsigned def, unsigned def_min)
12054 {
12055 	if (argv[1]) {
12056 		def = bb_strtou(argv[1], NULL, 10);
12057 		if (errno || def < def_min || argv[2]) {
12058 			bb_error_msg("%s: bad arguments", argv[0]);
12059 			def = UINT_MAX;
12060 		}
12061 	}
12062 	return def;
12063 }
12064 #endif
12065 
12066 #if ENABLE_HUSH_LOOPS
builtin_break(char ** argv)12067 static int FAST_FUNC builtin_break(char **argv)
12068 {
12069 	unsigned depth;
12070 	if (G.depth_of_loop == 0) {
12071 		bb_error_msg("%s: only meaningful in a loop", argv[0]);
12072 		/* if we came from builtin_continue(), need to undo "= 1" */
12073 		G.flag_break_continue = 0;
12074 		return EXIT_SUCCESS; /* bash compat */
12075 	}
12076 	G.flag_break_continue++; /* BC_BREAK = 1, or BC_CONTINUE = 2 */
12077 
12078 	G.depth_break_continue = depth = parse_numeric_argv1(argv, 1, 1);
12079 	if (depth == UINT_MAX)
12080 		G.flag_break_continue = BC_BREAK;
12081 	if (G.depth_of_loop < depth)
12082 		G.depth_break_continue = G.depth_of_loop;
12083 
12084 	return EXIT_SUCCESS;
12085 }
12086 
builtin_continue(char ** argv)12087 static int FAST_FUNC builtin_continue(char **argv)
12088 {
12089 	G.flag_break_continue = 1; /* BC_CONTINUE = 2 = 1+1 */
12090 	return builtin_break(argv);
12091 }
12092 #endif
12093 
12094 #if ENABLE_HUSH_FUNCTIONS
builtin_return(char ** argv)12095 static int FAST_FUNC builtin_return(char **argv)
12096 {
12097 	int rc;
12098 
12099 	if (G_flag_return_in_progress != -1) {
12100 		bb_error_msg("%s: not in a function or sourced script", argv[0]);
12101 		return EXIT_FAILURE; /* bash compat */
12102 	}
12103 
12104 	G_flag_return_in_progress = 1;
12105 
12106 	/* bash:
12107 	 * out of range: wraps around at 256, does not error out
12108 	 * non-numeric param:
12109 	 * f() { false; return qwe; }; f; echo $?
12110 	 * bash: return: qwe: numeric argument required  <== we do this
12111 	 * 255  <== we also do this
12112 	 */
12113 	rc = parse_numeric_argv1(argv, G.last_exitcode, 0);
12114 # if ENABLE_HUSH_TRAP
12115 	if (argv[1]) { /* "return ARG" inside a running trap sets $? */
12116 		debug_printf_exec("G.return_exitcode=%d\n", rc);
12117 		G.return_exitcode = rc;
12118 	}
12119 # endif
12120 	return rc;
12121 }
12122 #endif
12123 
12124 #if ENABLE_HUSH_TIMES
builtin_times(char ** argv UNUSED_PARAM)12125 static int FAST_FUNC builtin_times(char **argv UNUSED_PARAM)
12126 {
12127 	static const uint8_t times_tbl[] ALIGN1 = {
12128 		' ',  offsetof(struct tms, tms_utime),
12129 		'\n', offsetof(struct tms, tms_stime),
12130 		' ',  offsetof(struct tms, tms_cutime),
12131 		'\n', offsetof(struct tms, tms_cstime),
12132 		0
12133 	};
12134 	const uint8_t *p;
12135 	unsigned clk_tck;
12136 	struct tms buf;
12137 
12138 	clk_tck = bb_clk_tck();
12139 
12140 	times(&buf);
12141 	p = times_tbl;
12142 	do {
12143 		unsigned sec, frac;
12144 		unsigned long t;
12145 		t = *(clock_t *)(((char *) &buf) + p[1]);
12146 		sec = t / clk_tck;
12147 		frac = t % clk_tck;
12148 		printf("%um%u.%03us%c",
12149 			sec / 60, sec % 60,
12150 			(frac * 1000) / clk_tck,
12151 			p[0]);
12152 		p += 2;
12153 	} while (*p);
12154 
12155 	return EXIT_SUCCESS;
12156 }
12157 #endif
12158 
12159 #if ENABLE_HUSH_MEMLEAK
builtin_memleak(char ** argv UNUSED_PARAM)12160 static int FAST_FUNC builtin_memleak(char **argv UNUSED_PARAM)
12161 {
12162 	void *p;
12163 	unsigned long l;
12164 
12165 # ifdef M_TRIM_THRESHOLD
12166 	/* Optional. Reduces probability of false positives */
12167 	malloc_trim(0);
12168 # endif
12169 	/* Crude attempt to find where "free memory" starts,
12170 	 * sans fragmentation. */
12171 	p = malloc(240);
12172 	l = (unsigned long)p;
12173 	free(p);
12174 	p = malloc(3400);
12175 	if (l < (unsigned long)p) l = (unsigned long)p;
12176 	free(p);
12177 
12178 
12179 # if 0  /* debug */
12180 	{
12181 		struct mallinfo mi = mallinfo();
12182 		printf("top alloc:0x%lx malloced:%d+%d=%d\n", l,
12183 			mi.arena, mi.hblkhd, mi.arena + mi.hblkhd);
12184 	}
12185 # endif
12186 
12187 	if (!G.memleak_value)
12188 		G.memleak_value = l;
12189 
12190 	l -= G.memleak_value;
12191 	if ((long)l < 0)
12192 		l = 0;
12193 	l /= 1024;
12194 	if (l > 127)
12195 		l = 127;
12196 
12197 	/* Exitcode is "how many kilobytes we leaked since 1st call" */
12198 	return l;
12199 }
12200 #endif
12201