source: MondoRescue/branches/3.3/mindi-busybox/shell/hush.c@ 3901

Last change on this file since 3901 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

File size: 250.8 KB
Line 
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 * special variables (done: PWD, PPID, RANDOM)
45 * tilde expansion
46 * aliases
47 * follow IFS rules more precisely, including update semantics
48 * builtins mandated by standards we don't support:
49 * [un]alias, command, fc, getopts, newgrp, readonly, times
50 * make complex ${var%...} constructs support optional
51 * make here documents optional
52 *
53 * Bash compat TODO:
54 * redirection of stdout+stderr: &> and >&
55 * reserved words: function select
56 * advanced test: [[ ]]
57 * process substitution: <(list) and >(list)
58 * =~: regex operator
59 * let EXPR [EXPR...]
60 * Each EXPR is an arithmetic expression (ARITHMETIC EVALUATION)
61 * If the last arg evaluates to 0, let returns 1; 0 otherwise.
62 * NB: let `echo 'a=a + 1'` - error (IOW: multi-word expansion is used)
63 * ((EXPR))
64 * The EXPR is evaluated according to ARITHMETIC EVALUATION.
65 * This is exactly equivalent to let "EXPR".
66 * $[EXPR]: synonym for $((EXPR))
67 *
68 * Won't do:
69 * In bash, export builtin is special, its arguments are assignments
70 * and therefore expansion of them should be "one-word" expansion:
71 * $ export i=`echo 'a b'` # export has one arg: "i=a b"
72 * compare with:
73 * $ ls i=`echo 'a b'` # ls has two args: "i=a" and "b"
74 * ls: cannot access i=a: No such file or directory
75 * ls: cannot access b: No such file or directory
76 * Note1: same applies to local builtin.
77 * Note2: bash 3.2.33(1) does this only if export word itself
78 * is not quoted:
79 * $ export i=`echo 'aaa bbb'`; echo "$i"
80 * aaa bbb
81 * $ "export" i=`echo 'aaa bbb'`; echo "$i"
82 * aaa
83 */
84#if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
85 || defined(__APPLE__) \
86 )
87# include <malloc.h> /* for malloc_trim */
88#endif
89#include <glob.h>
90/* #include <dmalloc.h> */
91#if ENABLE_HUSH_CASE
92# include <fnmatch.h>
93#endif
94#include <sys/utsname.h> /* for setting $HOSTNAME */
95
96#include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */
97#include "unicode.h"
98#include "shell_common.h"
99#include "math.h"
100#include "match.h"
101#if ENABLE_HUSH_RANDOM_SUPPORT
102# include "random.h"
103#else
104# define CLEAR_RANDOM_T(rnd) ((void)0)
105#endif
106#ifndef PIPE_BUF
107# define PIPE_BUF 4096 /* amount of buffering in a pipe */
108#endif
109
110//config:config HUSH
111//config: bool "hush"
112//config: default y
113//config: help
114//config: hush is a small shell (25k). It handles the normal flow control
115//config: constructs such as if/then/elif/else/fi, for/in/do/done, while loops,
116//config: case/esac. Redirections, here documents, $((arithmetic))
117//config: and functions are supported.
118//config:
119//config: It will compile and work on no-mmu systems.
120//config:
121//config: It does not handle select, aliases, tilde expansion,
122//config: &>file and >&file redirection of stdout+stderr.
123//config:
124//config:config HUSH_BASH_COMPAT
125//config: bool "bash-compatible extensions"
126//config: default y
127//config: depends on HUSH
128//config: help
129//config: Enable bash-compatible extensions.
130//config:
131//config:config HUSH_BRACE_EXPANSION
132//config: bool "Brace expansion"
133//config: default y
134//config: depends on HUSH_BASH_COMPAT
135//config: help
136//config: Enable {abc,def} extension.
137//config:
138//config:config HUSH_HELP
139//config: bool "help builtin"
140//config: default y
141//config: depends on HUSH
142//config: help
143//config: Enable help builtin in hush. Code size + ~1 kbyte.
144//config:
145//config:config HUSH_INTERACTIVE
146//config: bool "Interactive mode"
147//config: default y
148//config: depends on HUSH
149//config: help
150//config: Enable interactive mode (prompt and command editing).
151//config: Without this, hush simply reads and executes commands
152//config: from stdin just like a shell script from a file.
153//config: No prompt, no PS1/PS2 magic shell variables.
154//config:
155//config:config HUSH_SAVEHISTORY
156//config: bool "Save command history to .hush_history"
157//config: default y
158//config: depends on HUSH_INTERACTIVE && FEATURE_EDITING_SAVEHISTORY
159//config: help
160//config: Enable history saving in hush.
161//config:
162//config:config HUSH_JOB
163//config: bool "Job control"
164//config: default y
165//config: depends on HUSH_INTERACTIVE
166//config: help
167//config: Enable job control: Ctrl-Z backgrounds, Ctrl-C interrupts current
168//config: command (not entire shell), fg/bg builtins work. Without this option,
169//config: "cmd &" still works by simply spawning a process and immediately
170//config: prompting for next command (or executing next command in a script),
171//config: but no separate process group is formed.
172//config:
173//config:config HUSH_TICK
174//config: bool "Process substitution"
175//config: default y
176//config: depends on HUSH
177//config: help
178//config: Enable process substitution `command` and $(command) in hush.
179//config:
180//config:config HUSH_IF
181//config: bool "Support if/then/elif/else/fi"
182//config: default y
183//config: depends on HUSH
184//config: help
185//config: Enable if/then/elif/else/fi in hush.
186//config:
187//config:config HUSH_LOOPS
188//config: bool "Support for, while and until loops"
189//config: default y
190//config: depends on HUSH
191//config: help
192//config: Enable for, while and until loops in hush.
193//config:
194//config:config HUSH_CASE
195//config: bool "Support case ... esac statement"
196//config: default y
197//config: depends on HUSH
198//config: help
199//config: Enable case ... esac statement in hush. +400 bytes.
200//config:
201//config:config HUSH_FUNCTIONS
202//config: bool "Support funcname() { commands; } syntax"
203//config: default y
204//config: depends on HUSH
205//config: help
206//config: Enable support for shell functions in hush. +800 bytes.
207//config:
208//config:config HUSH_LOCAL
209//config: bool "Support local builtin"
210//config: default y
211//config: depends on HUSH_FUNCTIONS
212//config: help
213//config: Enable support for local variables in functions.
214//config:
215//config:config HUSH_RANDOM_SUPPORT
216//config: bool "Pseudorandom generator and $RANDOM variable"
217//config: default y
218//config: depends on HUSH
219//config: help
220//config: Enable pseudorandom generator and dynamic variable "$RANDOM".
221//config: Each read of "$RANDOM" will generate a new pseudorandom value.
222//config:
223//config:config HUSH_EXPORT_N
224//config: bool "Support 'export -n' option"
225//config: default y
226//config: depends on HUSH
227//config: help
228//config: export -n unexports variables. It is a bash extension.
229//config:
230//config:config HUSH_MODE_X
231//config: bool "Support 'hush -x' option and 'set -x' command"
232//config: default y
233//config: depends on HUSH
234//config: help
235//config: This instructs hush to print commands before execution.
236//config: Adds ~300 bytes.
237//config:
238//config:config MSH
239//config: bool "msh (deprecated: aliased to hush)"
240//config: default n
241//config: select HUSH
242//config: help
243//config: msh is deprecated and will be removed, please migrate to hush.
244//config:
245
246//applet:IF_HUSH(APPLET(hush, BB_DIR_BIN, BB_SUID_DROP))
247//applet:IF_MSH(APPLET(msh, BB_DIR_BIN, BB_SUID_DROP))
248//applet:IF_FEATURE_SH_IS_HUSH(APPLET_ODDNAME(sh, hush, BB_DIR_BIN, BB_SUID_DROP, sh))
249//applet:IF_FEATURE_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, bash))
250
251//kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o
252//kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o
253
254/* -i (interactive) and -s (read stdin) are also accepted,
255 * but currently do nothing, therefore aren't shown in help.
256 * NOMMU-specific options are not meant to be used by users,
257 * therefore we don't show them either.
258 */
259//usage:#define hush_trivial_usage
260//usage: "[-nxl] [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
261//usage:#define hush_full_usage "\n\n"
262//usage: "Unix shell interpreter"
263
264//usage:#define msh_trivial_usage hush_trivial_usage
265//usage:#define msh_full_usage hush_full_usage
266
267//usage:#if ENABLE_FEATURE_SH_IS_HUSH
268//usage:# define sh_trivial_usage hush_trivial_usage
269//usage:# define sh_full_usage hush_full_usage
270//usage:#endif
271//usage:#if ENABLE_FEATURE_BASH_IS_HUSH
272//usage:# define bash_trivial_usage hush_trivial_usage
273//usage:# define bash_full_usage hush_full_usage
274//usage:#endif
275
276
277/* Build knobs */
278#define LEAK_HUNTING 0
279#define BUILD_AS_NOMMU 0
280/* Enable/disable sanity checks. Ok to enable in production,
281 * only adds a bit of bloat. Set to >1 to get non-production level verbosity.
282 * Keeping 1 for now even in released versions.
283 */
284#define HUSH_DEBUG 1
285/* Slightly bigger (+200 bytes), but faster hush.
286 * So far it only enables a trick with counting SIGCHLDs and forks,
287 * which allows us to do fewer waitpid's.
288 * (we can detect a case where neither forks were done nor SIGCHLDs happened
289 * and therefore waitpid will return the same result as last time)
290 */
291#define ENABLE_HUSH_FAST 0
292/* TODO: implement simplified code for users which do not need ${var%...} ops
293 * So far ${var%...} ops are always enabled:
294 */
295#define ENABLE_HUSH_DOLLAR_OPS 1
296
297
298#if BUILD_AS_NOMMU
299# undef BB_MMU
300# undef USE_FOR_NOMMU
301# undef USE_FOR_MMU
302# define BB_MMU 0
303# define USE_FOR_NOMMU(...) __VA_ARGS__
304# define USE_FOR_MMU(...)
305#endif
306
307#include "NUM_APPLETS.h"
308#if NUM_APPLETS == 1
309/* STANDALONE does not make sense, and won't compile */
310# undef CONFIG_FEATURE_SH_STANDALONE
311# undef ENABLE_FEATURE_SH_STANDALONE
312# undef IF_FEATURE_SH_STANDALONE
313# undef IF_NOT_FEATURE_SH_STANDALONE
314# define ENABLE_FEATURE_SH_STANDALONE 0
315# define IF_FEATURE_SH_STANDALONE(...)
316# define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
317#endif
318
319#if !ENABLE_HUSH_INTERACTIVE
320# undef ENABLE_FEATURE_EDITING
321# define ENABLE_FEATURE_EDITING 0
322# undef ENABLE_FEATURE_EDITING_FANCY_PROMPT
323# define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0
324# undef ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
325# define ENABLE_FEATURE_EDITING_SAVE_ON_EXIT 0
326#endif
327
328/* Do we support ANY keywords? */
329#if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
330# define HAS_KEYWORDS 1
331# define IF_HAS_KEYWORDS(...) __VA_ARGS__
332# define IF_HAS_NO_KEYWORDS(...)
333#else
334# define HAS_KEYWORDS 0
335# define IF_HAS_KEYWORDS(...)
336# define IF_HAS_NO_KEYWORDS(...) __VA_ARGS__
337#endif
338
339/* If you comment out one of these below, it will be #defined later
340 * to perform debug printfs to stderr: */
341#define debug_printf(...) do {} while (0)
342/* Finer-grained debug switches */
343#define debug_printf_parse(...) do {} while (0)
344#define debug_print_tree(a, b) do {} while (0)
345#define debug_printf_exec(...) do {} while (0)
346#define debug_printf_env(...) do {} while (0)
347#define debug_printf_jobs(...) do {} while (0)
348#define debug_printf_expand(...) do {} while (0)
349#define debug_printf_varexp(...) do {} while (0)
350#define debug_printf_glob(...) do {} while (0)
351#define debug_printf_list(...) do {} while (0)
352#define debug_printf_subst(...) do {} while (0)
353#define debug_printf_clean(...) do {} while (0)
354
355#define ERR_PTR ((void*)(long)1)
356
357#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
358
359#define _SPECIAL_VARS_STR "_*@$!?#"
360#define SPECIAL_VARS_STR ("_*@$!?#" + 1)
361#define NUMERIC_SPECVARS_STR ("_*@$!?#" + 3)
362#if ENABLE_HUSH_BASH_COMPAT
363/* Support / and // replace ops */
364/* Note that // is stored as \ in "encoded" string representation */
365# define VAR_ENCODED_SUBST_OPS "\\/%#:-=+?"
366# define VAR_SUBST_OPS ("\\/%#:-=+?" + 1)
367# define MINUS_PLUS_EQUAL_QUESTION ("\\/%#:-=+?" + 5)
368#else
369# define VAR_ENCODED_SUBST_OPS "%#:-=+?"
370# define VAR_SUBST_OPS "%#:-=+?"
371# define MINUS_PLUS_EQUAL_QUESTION ("%#:-=+?" + 3)
372#endif
373
374#define SPECIAL_VAR_SYMBOL 3
375
376struct variable;
377
378static const char hush_version_str[] ALIGN1 = "HUSH_VERSION="BB_VER;
379
380/* This supports saving pointers malloced in vfork child,
381 * to be freed in the parent.
382 */
383#if !BB_MMU
384typedef struct nommu_save_t {
385 char **new_env;
386 struct variable *old_vars;
387 char **argv;
388 char **argv_from_re_execing;
389} nommu_save_t;
390#endif
391
392enum {
393 RES_NONE = 0,
394#if ENABLE_HUSH_IF
395 RES_IF ,
396 RES_THEN ,
397 RES_ELIF ,
398 RES_ELSE ,
399 RES_FI ,
400#endif
401#if ENABLE_HUSH_LOOPS
402 RES_FOR ,
403 RES_WHILE ,
404 RES_UNTIL ,
405 RES_DO ,
406 RES_DONE ,
407#endif
408#if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
409 RES_IN ,
410#endif
411#if ENABLE_HUSH_CASE
412 RES_CASE ,
413 /* three pseudo-keywords support contrived "case" syntax: */
414 RES_CASE_IN, /* "case ... IN", turns into RES_MATCH when IN is observed */
415 RES_MATCH , /* "word)" */
416 RES_CASE_BODY, /* "this command is inside CASE" */
417 RES_ESAC ,
418#endif
419 RES_XXXX ,
420 RES_SNTX
421};
422
423typedef struct o_string {
424 char *data;
425 int length; /* position where data is appended */
426 int maxlen;
427 int o_expflags;
428 /* At least some part of the string was inside '' or "",
429 * possibly empty one: word"", wo''rd etc. */
430 smallint has_quoted_part;
431 smallint has_empty_slot;
432 smallint o_assignment; /* 0:maybe, 1:yes, 2:no */
433} o_string;
434enum {
435 EXP_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */
436 EXP_FLAG_GLOB = 0x2,
437 /* Protect newly added chars against globbing
438 * by prepending \ to *, ?, [, \ */
439 EXP_FLAG_ESC_GLOB_CHARS = 0x1,
440};
441enum {
442 MAYBE_ASSIGNMENT = 0,
443 DEFINITELY_ASSIGNMENT = 1,
444 NOT_ASSIGNMENT = 2,
445 /* Not an assignment, but next word may be: "if v=xyz cmd;" */
446 WORD_IS_KEYWORD = 3,
447};
448/* Used for initialization: o_string foo = NULL_O_STRING; */
449#define NULL_O_STRING { NULL }
450
451#ifndef debug_printf_parse
452static const char *const assignment_flag[] = {
453 "MAYBE_ASSIGNMENT",
454 "DEFINITELY_ASSIGNMENT",
455 "NOT_ASSIGNMENT",
456 "WORD_IS_KEYWORD",
457};
458#endif
459
460typedef struct in_str {
461 const char *p;
462 /* eof_flag=1: last char in ->p is really an EOF */
463 char eof_flag; /* meaningless if ->p == NULL */
464 char peek_buf[2];
465#if ENABLE_HUSH_INTERACTIVE
466 smallint promptmode; /* 0: PS1, 1: PS2 */
467#endif
468 int last_char;
469 FILE *file;
470 int (*get) (struct in_str *) FAST_FUNC;
471 int (*peek) (struct in_str *) FAST_FUNC;
472} in_str;
473#define i_getch(input) ((input)->get(input))
474#define i_peek(input) ((input)->peek(input))
475
476/* The descrip member of this structure is only used to make
477 * debugging output pretty */
478static const struct {
479 int mode;
480 signed char default_fd;
481 char descrip[3];
482} redir_table[] = {
483 { O_RDONLY, 0, "<" },
484 { O_CREAT|O_TRUNC|O_WRONLY, 1, ">" },
485 { O_CREAT|O_APPEND|O_WRONLY, 1, ">>" },
486 { O_CREAT|O_RDWR, 1, "<>" },
487 { O_RDONLY, 0, "<<" },
488/* Should not be needed. Bogus default_fd helps in debugging */
489/* { O_RDONLY, 77, "<<" }, */
490};
491
492struct redir_struct {
493 struct redir_struct *next;
494 char *rd_filename; /* filename */
495 int rd_fd; /* fd to redirect */
496 /* fd to redirect to, or -3 if rd_fd is to be closed (n>&-) */
497 int rd_dup;
498 smallint rd_type; /* (enum redir_type) */
499 /* note: for heredocs, rd_filename contains heredoc delimiter,
500 * and subsequently heredoc itself; and rd_dup is a bitmask:
501 * bit 0: do we need to trim leading tabs?
502 * bit 1: is heredoc quoted (<<'delim' syntax) ?
503 */
504};
505typedef enum redir_type {
506 REDIRECT_INPUT = 0,
507 REDIRECT_OVERWRITE = 1,
508 REDIRECT_APPEND = 2,
509 REDIRECT_IO = 3,
510 REDIRECT_HEREDOC = 4,
511 REDIRECT_HEREDOC2 = 5, /* REDIRECT_HEREDOC after heredoc is loaded */
512
513 REDIRFD_CLOSE = -3,
514 REDIRFD_SYNTAX_ERR = -2,
515 REDIRFD_TO_FILE = -1,
516 /* otherwise, rd_fd is redirected to rd_dup */
517
518 HEREDOC_SKIPTABS = 1,
519 HEREDOC_QUOTED = 2,
520} redir_type;
521
522
523struct command {
524 pid_t pid; /* 0 if exited */
525 int assignment_cnt; /* how many argv[i] are assignments? */
526 smallint cmd_type; /* CMD_xxx */
527#define CMD_NORMAL 0
528#define CMD_SUBSHELL 1
529#if ENABLE_HUSH_BASH_COMPAT
530/* used for "[[ EXPR ]]" */
531# define CMD_SINGLEWORD_NOGLOB 2
532#endif
533#if ENABLE_HUSH_FUNCTIONS
534# define CMD_FUNCDEF 3
535#endif
536
537 smalluint cmd_exitcode;
538 /* if non-NULL, this "command" is { list }, ( list ), or a compound statement */
539 struct pipe *group;
540#if !BB_MMU
541 char *group_as_string;
542#endif
543#if ENABLE_HUSH_FUNCTIONS
544 struct function *child_func;
545/* This field is used to prevent a bug here:
546 * while...do f1() {a;}; f1; f1() {b;}; f1; done
547 * When we execute "f1() {a;}" cmd, we create new function and clear
548 * cmd->group, cmd->group_as_string, cmd->argv[0].
549 * When we execute "f1() {b;}", we notice that f1 exists,
550 * and that its "parent cmd" struct is still "alive",
551 * we put those fields back into cmd->xxx
552 * (struct function has ->parent_cmd ptr to facilitate that).
553 * When we loop back, we can execute "f1() {a;}" again and set f1 correctly.
554 * Without this trick, loop would execute a;b;b;b;...
555 * instead of correct sequence a;b;a;b;...
556 * When command is freed, it severs the link
557 * (sets ->child_func->parent_cmd to NULL).
558 */
559#endif
560 char **argv; /* command name and arguments */
561/* argv vector may contain variable references (^Cvar^C, ^C0^C etc)
562 * and on execution these are substituted with their values.
563 * Substitution can make _several_ words out of one argv[n]!
564 * Example: argv[0]=='.^C*^C.' here: echo .$*.
565 * References of the form ^C`cmd arg^C are `cmd arg` substitutions.
566 */
567 struct redir_struct *redirects; /* I/O redirections */
568};
569/* Is there anything in this command at all? */
570#define IS_NULL_CMD(cmd) \
571 (!(cmd)->group && !(cmd)->argv && !(cmd)->redirects)
572
573struct pipe {
574 struct pipe *next;
575 int num_cmds; /* total number of commands in pipe */
576 int alive_cmds; /* number of commands running (not exited) */
577 int stopped_cmds; /* number of commands alive, but stopped */
578#if ENABLE_HUSH_JOB
579 int jobid; /* job number */
580 pid_t pgrp; /* process group ID for the job */
581 char *cmdtext; /* name of job */
582#endif
583 struct command *cmds; /* array of commands in pipe */
584 smallint followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
585 IF_HAS_KEYWORDS(smallint pi_inverted;) /* "! cmd | cmd" */
586 IF_HAS_KEYWORDS(smallint res_word;) /* needed for if, for, while, until... */
587};
588typedef enum pipe_style {
589 PIPE_SEQ = 1,
590 PIPE_AND = 2,
591 PIPE_OR = 3,
592 PIPE_BG = 4,
593} pipe_style;
594/* Is there anything in this pipe at all? */
595#define IS_NULL_PIPE(pi) \
596 ((pi)->num_cmds == 0 IF_HAS_KEYWORDS( && (pi)->res_word == RES_NONE))
597
598/* This holds pointers to the various results of parsing */
599struct parse_context {
600 /* linked list of pipes */
601 struct pipe *list_head;
602 /* last pipe (being constructed right now) */
603 struct pipe *pipe;
604 /* last command in pipe (being constructed right now) */
605 struct command *command;
606 /* last redirect in command->redirects list */
607 struct redir_struct *pending_redirect;
608#if !BB_MMU
609 o_string as_string;
610#endif
611#if HAS_KEYWORDS
612 smallint ctx_res_w;
613 smallint ctx_inverted; /* "! cmd | cmd" */
614#if ENABLE_HUSH_CASE
615 smallint ctx_dsemicolon; /* ";;" seen */
616#endif
617 /* bitmask of FLAG_xxx, for figuring out valid reserved words */
618 int old_flag;
619 /* group we are enclosed in:
620 * example: "if pipe1; pipe2; then pipe3; fi"
621 * when we see "if" or "then", we malloc and copy current context,
622 * and make ->stack point to it. then we parse pipeN.
623 * when closing "then" / fi" / whatever is found,
624 * we move list_head into ->stack->command->group,
625 * copy ->stack into current context, and delete ->stack.
626 * (parsing of { list } and ( list ) doesn't use this method)
627 */
628 struct parse_context *stack;
629#endif
630};
631
632/* On program start, environ points to initial environment.
633 * putenv adds new pointers into it, unsetenv removes them.
634 * Neither of these (de)allocates the strings.
635 * setenv allocates new strings in malloc space and does putenv,
636 * and thus setenv is unusable (leaky) for shell's purposes */
637#define setenv(...) setenv_is_leaky_dont_use()
638struct variable {
639 struct variable *next;
640 char *varstr; /* points to "name=" portion */
641#if ENABLE_HUSH_LOCAL
642 unsigned func_nest_level;
643#endif
644 int max_len; /* if > 0, name is part of initial env; else name is malloced */
645 smallint flg_export; /* putenv should be done on this var */
646 smallint flg_read_only;
647};
648
649enum {
650 BC_BREAK = 1,
651 BC_CONTINUE = 2,
652};
653
654#if ENABLE_HUSH_FUNCTIONS
655struct function {
656 struct function *next;
657 char *name;
658 struct command *parent_cmd;
659 struct pipe *body;
660# if !BB_MMU
661 char *body_as_string;
662# endif
663};
664#endif
665
666
667/* set -/+o OPT support. (TODO: make it optional)
668 * bash supports the following opts:
669 * allexport off
670 * braceexpand on
671 * emacs on
672 * errexit off
673 * errtrace off
674 * functrace off
675 * hashall on
676 * histexpand off
677 * history on
678 * ignoreeof off
679 * interactive-comments on
680 * keyword off
681 * monitor on
682 * noclobber off
683 * noexec off
684 * noglob off
685 * nolog off
686 * notify off
687 * nounset off
688 * onecmd off
689 * physical off
690 * pipefail off
691 * posix off
692 * privileged off
693 * verbose off
694 * vi off
695 * xtrace off
696 */
697static const char o_opt_strings[] ALIGN1 =
698 "pipefail\0"
699 "noexec\0"
700#if ENABLE_HUSH_MODE_X
701 "xtrace\0"
702#endif
703 ;
704enum {
705 OPT_O_PIPEFAIL,
706 OPT_O_NOEXEC,
707#if ENABLE_HUSH_MODE_X
708 OPT_O_XTRACE,
709#endif
710 NUM_OPT_O
711};
712
713
714/* "Globals" within this file */
715/* Sorted roughly by size (smaller offsets == smaller code) */
716struct globals {
717 /* interactive_fd != 0 means we are an interactive shell.
718 * If we are, then saved_tty_pgrp can also be != 0, meaning
719 * that controlling tty is available. With saved_tty_pgrp == 0,
720 * job control still works, but terminal signals
721 * (^C, ^Z, ^Y, ^\) won't work at all, and background
722 * process groups can only be created with "cmd &".
723 * With saved_tty_pgrp != 0, hush will use tcsetpgrp()
724 * to give tty to the foreground process group,
725 * and will take it back when the group is stopped (^Z)
726 * or killed (^C).
727 */
728#if ENABLE_HUSH_INTERACTIVE
729 /* 'interactive_fd' is a fd# open to ctty, if we have one
730 * _AND_ if we decided to act interactively */
731 int interactive_fd;
732 const char *PS1;
733 const char *PS2;
734# define G_interactive_fd (G.interactive_fd)
735#else
736# define G_interactive_fd 0
737#endif
738#if ENABLE_FEATURE_EDITING
739 line_input_t *line_input_state;
740#endif
741 pid_t root_pid;
742 pid_t root_ppid;
743 pid_t last_bg_pid;
744#if ENABLE_HUSH_RANDOM_SUPPORT
745 random_t random_gen;
746#endif
747#if ENABLE_HUSH_JOB
748 int run_list_level;
749 int last_jobid;
750 pid_t saved_tty_pgrp;
751 struct pipe *job_list;
752# define G_saved_tty_pgrp (G.saved_tty_pgrp)
753#else
754# define G_saved_tty_pgrp 0
755#endif
756 char o_opt[NUM_OPT_O];
757#if ENABLE_HUSH_MODE_X
758# define G_x_mode (G.o_opt[OPT_O_XTRACE])
759#else
760# define G_x_mode 0
761#endif
762 smallint flag_SIGINT;
763#if ENABLE_HUSH_LOOPS
764 smallint flag_break_continue;
765#endif
766#if ENABLE_HUSH_FUNCTIONS
767 /* 0: outside of a function (or sourced file)
768 * -1: inside of a function, ok to use return builtin
769 * 1: return is invoked, skip all till end of func
770 */
771 smallint flag_return_in_progress;
772#endif
773 smallint exiting; /* used to prevent EXIT trap recursion */
774 /* These four support $?, $#, and $1 */
775 smalluint last_exitcode;
776 /* are global_argv and global_argv[1..n] malloced? (note: not [0]) */
777 smalluint global_args_malloced;
778 /* how many non-NULL argv's we have. NB: $# + 1 */
779 int global_argc;
780 char **global_argv;
781#if !BB_MMU
782 char *argv0_for_re_execing;
783#endif
784#if ENABLE_HUSH_LOOPS
785 unsigned depth_break_continue;
786 unsigned depth_of_loop;
787#endif
788 const char *ifs;
789 const char *cwd;
790 struct variable *top_var;
791 char **expanded_assignments;
792#if ENABLE_HUSH_FUNCTIONS
793 struct function *top_func;
794# if ENABLE_HUSH_LOCAL
795 struct variable **shadowed_vars_pp;
796 unsigned func_nest_level;
797# endif
798#endif
799 /* Signal and trap handling */
800#if ENABLE_HUSH_FAST
801 unsigned count_SIGCHLD;
802 unsigned handled_SIGCHLD;
803 smallint we_have_children;
804#endif
805 /* Which signals have non-DFL handler (even with no traps set)?
806 * Set at the start to:
807 * (SIGQUIT + maybe SPECIAL_INTERACTIVE_SIGS + maybe SPECIAL_JOBSTOP_SIGS)
808 * SPECIAL_INTERACTIVE_SIGS are cleared after fork.
809 * The rest is cleared right before execv syscalls.
810 * Other than these two times, never modified.
811 */
812 unsigned special_sig_mask;
813#if ENABLE_HUSH_JOB
814 unsigned fatal_sig_mask;
815# define G_fatal_sig_mask G.fatal_sig_mask
816#else
817# define G_fatal_sig_mask 0
818#endif
819 char **traps; /* char *traps[NSIG] */
820 sigset_t pending_set;
821#if HUSH_DEBUG
822 unsigned long memleak_value;
823 int debug_indent;
824#endif
825 struct sigaction sa;
826 char user_input_buf[ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 2];
827};
828#define G (*ptr_to_globals)
829/* Not #defining name to G.name - this quickly gets unwieldy
830 * (too many defines). Also, I actually prefer to see when a variable
831 * is global, thus "G." prefix is a useful hint */
832#define INIT_G() do { \
833 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
834 /* memset(&G.sa, 0, sizeof(G.sa)); */ \
835 sigfillset(&G.sa.sa_mask); \
836 G.sa.sa_flags = SA_RESTART; \
837} while (0)
838
839
840/* Function prototypes for builtins */
841static int builtin_cd(char **argv) FAST_FUNC;
842static int builtin_echo(char **argv) FAST_FUNC;
843static int builtin_eval(char **argv) FAST_FUNC;
844static int builtin_exec(char **argv) FAST_FUNC;
845static int builtin_exit(char **argv) FAST_FUNC;
846static int builtin_export(char **argv) FAST_FUNC;
847#if ENABLE_HUSH_JOB
848static int builtin_fg_bg(char **argv) FAST_FUNC;
849static int builtin_jobs(char **argv) FAST_FUNC;
850#endif
851#if ENABLE_HUSH_HELP
852static int builtin_help(char **argv) FAST_FUNC;
853#endif
854#if MAX_HISTORY && ENABLE_FEATURE_EDITING
855static int builtin_history(char **argv) FAST_FUNC;
856#endif
857#if ENABLE_HUSH_LOCAL
858static int builtin_local(char **argv) FAST_FUNC;
859#endif
860#if HUSH_DEBUG
861static int builtin_memleak(char **argv) FAST_FUNC;
862#endif
863#if ENABLE_PRINTF
864static int builtin_printf(char **argv) FAST_FUNC;
865#endif
866static int builtin_pwd(char **argv) FAST_FUNC;
867static int builtin_read(char **argv) FAST_FUNC;
868static int builtin_set(char **argv) FAST_FUNC;
869static int builtin_shift(char **argv) FAST_FUNC;
870static int builtin_source(char **argv) FAST_FUNC;
871static int builtin_test(char **argv) FAST_FUNC;
872static int builtin_trap(char **argv) FAST_FUNC;
873static int builtin_type(char **argv) FAST_FUNC;
874static int builtin_true(char **argv) FAST_FUNC;
875static int builtin_umask(char **argv) FAST_FUNC;
876static int builtin_unset(char **argv) FAST_FUNC;
877static int builtin_wait(char **argv) FAST_FUNC;
878#if ENABLE_HUSH_LOOPS
879static int builtin_break(char **argv) FAST_FUNC;
880static int builtin_continue(char **argv) FAST_FUNC;
881#endif
882#if ENABLE_HUSH_FUNCTIONS
883static int builtin_return(char **argv) FAST_FUNC;
884#endif
885
886/* Table of built-in functions. They can be forked or not, depending on
887 * context: within pipes, they fork. As simple commands, they do not.
888 * When used in non-forking context, they can change global variables
889 * in the parent shell process. If forked, of course they cannot.
890 * For example, 'unset foo | whatever' will parse and run, but foo will
891 * still be set at the end. */
892struct built_in_command {
893 const char *b_cmd;
894 int (*b_function)(char **argv) FAST_FUNC;
895#if ENABLE_HUSH_HELP
896 const char *b_descr;
897# define BLTIN(cmd, func, help) { cmd, func, help }
898#else
899# define BLTIN(cmd, func, help) { cmd, func }
900#endif
901};
902
903static const struct built_in_command bltins1[] = {
904 BLTIN("." , builtin_source , "Run commands in a file"),
905 BLTIN(":" , builtin_true , NULL),
906#if ENABLE_HUSH_JOB
907 BLTIN("bg" , builtin_fg_bg , "Resume a job in the background"),
908#endif
909#if ENABLE_HUSH_LOOPS
910 BLTIN("break" , builtin_break , "Exit from a loop"),
911#endif
912 BLTIN("cd" , builtin_cd , "Change directory"),
913#if ENABLE_HUSH_LOOPS
914 BLTIN("continue" , builtin_continue, "Start new loop iteration"),
915#endif
916 BLTIN("eval" , builtin_eval , "Construct and run shell command"),
917 BLTIN("exec" , builtin_exec , "Execute command, don't return to shell"),
918 BLTIN("exit" , builtin_exit , "Exit"),
919 BLTIN("export" , builtin_export , "Set environment variables"),
920#if ENABLE_HUSH_JOB
921 BLTIN("fg" , builtin_fg_bg , "Bring job into the foreground"),
922#endif
923#if ENABLE_HUSH_HELP
924 BLTIN("help" , builtin_help , NULL),
925#endif
926#if MAX_HISTORY && ENABLE_FEATURE_EDITING
927 BLTIN("history" , builtin_history , "Show command history"),
928#endif
929#if ENABLE_HUSH_JOB
930 BLTIN("jobs" , builtin_jobs , "List jobs"),
931#endif
932#if ENABLE_HUSH_LOCAL
933 BLTIN("local" , builtin_local , "Set local variables"),
934#endif
935#if HUSH_DEBUG
936 BLTIN("memleak" , builtin_memleak , NULL),
937#endif
938 BLTIN("read" , builtin_read , "Input into variable"),
939#if ENABLE_HUSH_FUNCTIONS
940 BLTIN("return" , builtin_return , "Return from a function"),
941#endif
942 BLTIN("set" , builtin_set , "Set/unset positional parameters"),
943 BLTIN("shift" , builtin_shift , "Shift positional parameters"),
944#if ENABLE_HUSH_BASH_COMPAT
945 BLTIN("source" , builtin_source , "Run commands in a file"),
946#endif
947 BLTIN("trap" , builtin_trap , "Trap signals"),
948 BLTIN("true" , builtin_true , NULL),
949 BLTIN("type" , builtin_type , "Show command type"),
950 BLTIN("ulimit" , shell_builtin_ulimit , "Control resource limits"),
951 BLTIN("umask" , builtin_umask , "Set file creation mask"),
952 BLTIN("unset" , builtin_unset , "Unset variables"),
953 BLTIN("wait" , builtin_wait , "Wait for process"),
954};
955/* For now, echo and test are unconditionally enabled.
956 * Maybe make it configurable? */
957static const struct built_in_command bltins2[] = {
958 BLTIN("[" , builtin_test , NULL),
959 BLTIN("echo" , builtin_echo , NULL),
960#if ENABLE_PRINTF
961 BLTIN("printf" , builtin_printf , NULL),
962#endif
963 BLTIN("pwd" , builtin_pwd , NULL),
964 BLTIN("test" , builtin_test , NULL),
965};
966
967
968/* Debug printouts.
969 */
970#if HUSH_DEBUG
971/* prevent disasters with G.debug_indent < 0 */
972# define indent() fdprintf(2, "%*s", (G.debug_indent * 2) & 0xff, "")
973# define debug_enter() (G.debug_indent++)
974# define debug_leave() (G.debug_indent--)
975#else
976# define indent() ((void)0)
977# define debug_enter() ((void)0)
978# define debug_leave() ((void)0)
979#endif
980
981#ifndef debug_printf
982# define debug_printf(...) (indent(), fdprintf(2, __VA_ARGS__))
983#endif
984
985#ifndef debug_printf_parse
986# define debug_printf_parse(...) (indent(), fdprintf(2, __VA_ARGS__))
987#endif
988
989#ifndef debug_printf_exec
990#define debug_printf_exec(...) (indent(), fdprintf(2, __VA_ARGS__))
991#endif
992
993#ifndef debug_printf_env
994# define debug_printf_env(...) (indent(), fdprintf(2, __VA_ARGS__))
995#endif
996
997#ifndef debug_printf_jobs
998# define debug_printf_jobs(...) (indent(), fdprintf(2, __VA_ARGS__))
999# define DEBUG_JOBS 1
1000#else
1001# define DEBUG_JOBS 0
1002#endif
1003
1004#ifndef debug_printf_expand
1005# define debug_printf_expand(...) (indent(), fdprintf(2, __VA_ARGS__))
1006# define DEBUG_EXPAND 1
1007#else
1008# define DEBUG_EXPAND 0
1009#endif
1010
1011#ifndef debug_printf_varexp
1012# define debug_printf_varexp(...) (indent(), fdprintf(2, __VA_ARGS__))
1013#endif
1014
1015#ifndef debug_printf_glob
1016# define debug_printf_glob(...) (indent(), fdprintf(2, __VA_ARGS__))
1017# define DEBUG_GLOB 1
1018#else
1019# define DEBUG_GLOB 0
1020#endif
1021
1022#ifndef debug_printf_list
1023# define debug_printf_list(...) (indent(), fdprintf(2, __VA_ARGS__))
1024#endif
1025
1026#ifndef debug_printf_subst
1027# define debug_printf_subst(...) (indent(), fdprintf(2, __VA_ARGS__))
1028#endif
1029
1030#ifndef debug_printf_clean
1031# define debug_printf_clean(...) (indent(), fdprintf(2, __VA_ARGS__))
1032# define DEBUG_CLEAN 1
1033#else
1034# define DEBUG_CLEAN 0
1035#endif
1036
1037#if DEBUG_EXPAND
1038static void debug_print_strings(const char *prefix, char **vv)
1039{
1040 indent();
1041 fdprintf(2, "%s:\n", prefix);
1042 while (*vv)
1043 fdprintf(2, " '%s'\n", *vv++);
1044}
1045#else
1046# define debug_print_strings(prefix, vv) ((void)0)
1047#endif
1048
1049
1050/* Leak hunting. Use hush_leaktool.sh for post-processing.
1051 */
1052#if LEAK_HUNTING
1053static void *xxmalloc(int lineno, size_t size)
1054{
1055 void *ptr = xmalloc((size + 0xff) & ~0xff);
1056 fdprintf(2, "line %d: malloc %p\n", lineno, ptr);
1057 return ptr;
1058}
1059static void *xxrealloc(int lineno, void *ptr, size_t size)
1060{
1061 ptr = xrealloc(ptr, (size + 0xff) & ~0xff);
1062 fdprintf(2, "line %d: realloc %p\n", lineno, ptr);
1063 return ptr;
1064}
1065static char *xxstrdup(int lineno, const char *str)
1066{
1067 char *ptr = xstrdup(str);
1068 fdprintf(2, "line %d: strdup %p\n", lineno, ptr);
1069 return ptr;
1070}
1071static void xxfree(void *ptr)
1072{
1073 fdprintf(2, "free %p\n", ptr);
1074 free(ptr);
1075}
1076# define xmalloc(s) xxmalloc(__LINE__, s)
1077# define xrealloc(p, s) xxrealloc(__LINE__, p, s)
1078# define xstrdup(s) xxstrdup(__LINE__, s)
1079# define free(p) xxfree(p)
1080#endif
1081
1082
1083/* Syntax and runtime errors. They always abort scripts.
1084 * In interactive use they usually discard unparsed and/or unexecuted commands
1085 * and return to the prompt.
1086 * HUSH_DEBUG >= 2 prints line number in this file where it was detected.
1087 */
1088#if HUSH_DEBUG < 2
1089# define die_if_script(lineno, ...) die_if_script(__VA_ARGS__)
1090# define syntax_error(lineno, msg) syntax_error(msg)
1091# define syntax_error_at(lineno, msg) syntax_error_at(msg)
1092# define syntax_error_unterm_ch(lineno, ch) syntax_error_unterm_ch(ch)
1093# define syntax_error_unterm_str(lineno, s) syntax_error_unterm_str(s)
1094# define syntax_error_unexpected_ch(lineno, ch) syntax_error_unexpected_ch(ch)
1095#endif
1096
1097static void die_if_script(unsigned lineno, const char *fmt, ...)
1098{
1099 va_list p;
1100
1101#if HUSH_DEBUG >= 2
1102 bb_error_msg("hush.c:%u", lineno);
1103#endif
1104 va_start(p, fmt);
1105 bb_verror_msg(fmt, p, NULL);
1106 va_end(p);
1107 if (!G_interactive_fd)
1108 xfunc_die();
1109}
1110
1111static void syntax_error(unsigned lineno UNUSED_PARAM, const char *msg)
1112{
1113 if (msg)
1114 bb_error_msg("syntax error: %s", msg);
1115 else
1116 bb_error_msg("syntax error");
1117}
1118
1119static void syntax_error_at(unsigned lineno UNUSED_PARAM, const char *msg)
1120{
1121 bb_error_msg("syntax error at '%s'", msg);
1122}
1123
1124static void syntax_error_unterm_str(unsigned lineno UNUSED_PARAM, const char *s)
1125{
1126 bb_error_msg("syntax error: unterminated %s", s);
1127}
1128
1129static void syntax_error_unterm_ch(unsigned lineno, char ch)
1130{
1131 char msg[2] = { ch, '\0' };
1132 syntax_error_unterm_str(lineno, msg);
1133}
1134
1135static void syntax_error_unexpected_ch(unsigned lineno UNUSED_PARAM, int ch)
1136{
1137 char msg[2];
1138 msg[0] = ch;
1139 msg[1] = '\0';
1140 bb_error_msg("syntax error: unexpected %s", ch == EOF ? "EOF" : msg);
1141}
1142
1143#if HUSH_DEBUG < 2
1144# undef die_if_script
1145# undef syntax_error
1146# undef syntax_error_at
1147# undef syntax_error_unterm_ch
1148# undef syntax_error_unterm_str
1149# undef syntax_error_unexpected_ch
1150#else
1151# define die_if_script(...) die_if_script(__LINE__, __VA_ARGS__)
1152# define syntax_error(msg) syntax_error(__LINE__, msg)
1153# define syntax_error_at(msg) syntax_error_at(__LINE__, msg)
1154# define syntax_error_unterm_ch(ch) syntax_error_unterm_ch(__LINE__, ch)
1155# define syntax_error_unterm_str(s) syntax_error_unterm_str(__LINE__, s)
1156# define syntax_error_unexpected_ch(ch) syntax_error_unexpected_ch(__LINE__, ch)
1157#endif
1158
1159
1160#if ENABLE_HUSH_INTERACTIVE
1161static void cmdedit_update_prompt(void);
1162#else
1163# define cmdedit_update_prompt() ((void)0)
1164#endif
1165
1166
1167/* Utility functions
1168 */
1169/* Replace each \x with x in place, return ptr past NUL. */
1170static char *unbackslash(char *src)
1171{
1172 char *dst = src = strchrnul(src, '\\');
1173 while (1) {
1174 if (*src == '\\')
1175 src++;
1176 if ((*dst++ = *src++) == '\0')
1177 break;
1178 }
1179 return dst;
1180}
1181
1182static char **add_strings_to_strings(char **strings, char **add, int need_to_dup)
1183{
1184 int i;
1185 unsigned count1;
1186 unsigned count2;
1187 char **v;
1188
1189 v = strings;
1190 count1 = 0;
1191 if (v) {
1192 while (*v) {
1193 count1++;
1194 v++;
1195 }
1196 }
1197 count2 = 0;
1198 v = add;
1199 while (*v) {
1200 count2++;
1201 v++;
1202 }
1203 v = xrealloc(strings, (count1 + count2 + 1) * sizeof(char*));
1204 v[count1 + count2] = NULL;
1205 i = count2;
1206 while (--i >= 0)
1207 v[count1 + i] = (need_to_dup ? xstrdup(add[i]) : add[i]);
1208 return v;
1209}
1210#if LEAK_HUNTING
1211static char **xx_add_strings_to_strings(int lineno, char **strings, char **add, int need_to_dup)
1212{
1213 char **ptr = add_strings_to_strings(strings, add, need_to_dup);
1214 fdprintf(2, "line %d: add_strings_to_strings %p\n", lineno, ptr);
1215 return ptr;
1216}
1217#define add_strings_to_strings(strings, add, need_to_dup) \
1218 xx_add_strings_to_strings(__LINE__, strings, add, need_to_dup)
1219#endif
1220
1221/* Note: takes ownership of "add" ptr (it is not strdup'ed) */
1222static char **add_string_to_strings(char **strings, char *add)
1223{
1224 char *v[2];
1225 v[0] = add;
1226 v[1] = NULL;
1227 return add_strings_to_strings(strings, v, /*dup:*/ 0);
1228}
1229#if LEAK_HUNTING
1230static char **xx_add_string_to_strings(int lineno, char **strings, char *add)
1231{
1232 char **ptr = add_string_to_strings(strings, add);
1233 fdprintf(2, "line %d: add_string_to_strings %p\n", lineno, ptr);
1234 return ptr;
1235}
1236#define add_string_to_strings(strings, add) \
1237 xx_add_string_to_strings(__LINE__, strings, add)
1238#endif
1239
1240static void free_strings(char **strings)
1241{
1242 char **v;
1243
1244 if (!strings)
1245 return;
1246 v = strings;
1247 while (*v) {
1248 free(*v);
1249 v++;
1250 }
1251 free(strings);
1252}
1253
1254
1255/* Helpers for setting new $n and restoring them back
1256 */
1257typedef struct save_arg_t {
1258 char *sv_argv0;
1259 char **sv_g_argv;
1260 int sv_g_argc;
1261 smallint sv_g_malloced;
1262} save_arg_t;
1263
1264static void save_and_replace_G_args(save_arg_t *sv, char **argv)
1265{
1266 int n;
1267
1268 sv->sv_argv0 = argv[0];
1269 sv->sv_g_argv = G.global_argv;
1270 sv->sv_g_argc = G.global_argc;
1271 sv->sv_g_malloced = G.global_args_malloced;
1272
1273 argv[0] = G.global_argv[0]; /* retain $0 */
1274 G.global_argv = argv;
1275 G.global_args_malloced = 0;
1276
1277 n = 1;
1278 while (*++argv)
1279 n++;
1280 G.global_argc = n;
1281}
1282
1283static void restore_G_args(save_arg_t *sv, char **argv)
1284{
1285 char **pp;
1286
1287 if (G.global_args_malloced) {
1288 /* someone ran "set -- arg1 arg2 ...", undo */
1289 pp = G.global_argv;
1290 while (*++pp) /* note: does not free $0 */
1291 free(*pp);
1292 free(G.global_argv);
1293 }
1294 argv[0] = sv->sv_argv0;
1295 G.global_argv = sv->sv_g_argv;
1296 G.global_argc = sv->sv_g_argc;
1297 G.global_args_malloced = sv->sv_g_malloced;
1298}
1299
1300
1301/* Basic theory of signal handling in shell
1302 * ========================================
1303 * This does not describe what hush does, rather, it is current understanding
1304 * what it _should_ do. If it doesn't, it's a bug.
1305 * http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#trap
1306 *
1307 * Signals are handled only after each pipe ("cmd | cmd | cmd" thing)
1308 * is finished or backgrounded. It is the same in interactive and
1309 * non-interactive shells, and is the same regardless of whether
1310 * a user trap handler is installed or a shell special one is in effect.
1311 * ^C or ^Z from keyboard seems to execute "at once" because it usually
1312 * backgrounds (i.e. stops) or kills all members of currently running
1313 * pipe.
1314 *
1315 * Wait builtin is interruptible by signals for which user trap is set
1316 * or by SIGINT in interactive shell.
1317 *
1318 * Trap handlers will execute even within trap handlers. (right?)
1319 *
1320 * User trap handlers are forgotten when subshell ("(cmd)") is entered,
1321 * except for handlers set to '' (empty string).
1322 *
1323 * If job control is off, backgrounded commands ("cmd &")
1324 * have SIGINT, SIGQUIT set to SIG_IGN.
1325 *
1326 * Commands which are run in command substitution ("`cmd`")
1327 * have SIGTTIN, SIGTTOU, SIGTSTP set to SIG_IGN.
1328 *
1329 * Ordinary commands have signals set to SIG_IGN/DFL as inherited
1330 * by the shell from its parent.
1331 *
1332 * Signals which differ from SIG_DFL action
1333 * (note: child (i.e., [v]forked) shell is not an interactive shell):
1334 *
1335 * SIGQUIT: ignore
1336 * SIGTERM (interactive): ignore
1337 * SIGHUP (interactive):
1338 * send SIGCONT to stopped jobs, send SIGHUP to all jobs and exit
1339 * SIGTTIN, SIGTTOU, SIGTSTP (if job control is on): ignore
1340 * Note that ^Z is handled not by trapping SIGTSTP, but by seeing
1341 * that all pipe members are stopped. Try this in bash:
1342 * while :; do :; done - ^Z does not background it
1343 * (while :; do :; done) - ^Z backgrounds it
1344 * SIGINT (interactive): wait for last pipe, ignore the rest
1345 * of the command line, show prompt. NB: ^C does not send SIGINT
1346 * to interactive shell while shell is waiting for a pipe,
1347 * since shell is bg'ed (is not in foreground process group).
1348 * Example 1: this waits 5 sec, but does not execute ls:
1349 * "echo $$; sleep 5; ls -l" + "kill -INT <pid>"
1350 * Example 2: this does not wait and does not execute ls:
1351 * "echo $$; sleep 5 & wait; ls -l" + "kill -INT <pid>"
1352 * Example 3: this does not wait 5 sec, but executes ls:
1353 * "sleep 5; ls -l" + press ^C
1354 * Example 4: this does not wait and does not execute ls:
1355 * "sleep 5 & wait; ls -l" + press ^C
1356 *
1357 * (What happens to signals which are IGN on shell start?)
1358 * (What happens with signal mask on shell start?)
1359 *
1360 * Old implementation
1361 * ==================
1362 * We use in-kernel pending signal mask to determine which signals were sent.
1363 * We block all signals which we don't want to take action immediately,
1364 * i.e. we block all signals which need to have special handling as described
1365 * above, and all signals which have traps set.
1366 * After each pipe execution, we extract any pending signals via sigtimedwait()
1367 * and act on them.
1368 *
1369 * unsigned special_sig_mask: a mask of such "special" signals
1370 * sigset_t blocked_set: current blocked signal set
1371 *
1372 * "trap - SIGxxx":
1373 * clear bit in blocked_set unless it is also in special_sig_mask
1374 * "trap 'cmd' SIGxxx":
1375 * set bit in blocked_set (even if 'cmd' is '')
1376 * after [v]fork, if we plan to be a shell:
1377 * unblock signals with special interactive handling
1378 * (child shell is not interactive),
1379 * unset all traps except '' (note: regardless of child shell's type - {}, (), etc)
1380 * after [v]fork, if we plan to exec:
1381 * POSIX says fork clears pending signal mask in child - no need to clear it.
1382 * Restore blocked signal set to one inherited by shell just prior to exec.
1383 *
1384 * Note: as a result, we do not use signal handlers much. The only uses
1385 * are to count SIGCHLDs
1386 * and to restore tty pgrp on signal-induced exit.
1387 *
1388 * Note 2 (compat):
1389 * Standard says "When a subshell is entered, traps that are not being ignored
1390 * are set to the default actions". bash interprets it so that traps which
1391 * are set to '' (ignore) are NOT reset to defaults. We do the same.
1392 *
1393 * Problem: the above approach makes it unwieldy to catch signals while
1394 * we are in read builtin, or while we read commands from stdin:
1395 * masked signals are not visible!
1396 *
1397 * New implementation
1398 * ==================
1399 * We record each signal we are interested in by installing signal handler
1400 * for them - a bit like emulating kernel pending signal mask in userspace.
1401 * We are interested in: signals which need to have special handling
1402 * as described above, and all signals which have traps set.
1403 * Signals are recorded in pending_set.
1404 * After each pipe execution, we extract any pending signals
1405 * and act on them.
1406 *
1407 * unsigned special_sig_mask: a mask of shell-special signals.
1408 * unsigned fatal_sig_mask: a mask of signals on which we restore tty pgrp.
1409 * char *traps[sig] if trap for sig is set (even if it's '').
1410 * sigset_t pending_set: set of sigs we received.
1411 *
1412 * "trap - SIGxxx":
1413 * if sig is in special_sig_mask, set handler back to:
1414 * record_pending_signo, or to IGN if it's a tty stop signal
1415 * if sig is in fatal_sig_mask, set handler back to sigexit.
1416 * else: set handler back to SIG_DFL
1417 * "trap 'cmd' SIGxxx":
1418 * set handler to record_pending_signo.
1419 * "trap '' SIGxxx":
1420 * set handler to SIG_IGN.
1421 * after [v]fork, if we plan to be a shell:
1422 * set signals with special interactive handling to SIG_DFL
1423 * (because child shell is not interactive),
1424 * unset all traps except '' (note: regardless of child shell's type - {}, (), etc)
1425 * after [v]fork, if we plan to exec:
1426 * POSIX says fork clears pending signal mask in child - no need to clear it.
1427 *
1428 * To make wait builtin interruptible, we handle SIGCHLD as special signal,
1429 * otherwise (if we leave it SIG_DFL) sigsuspend in wait builtin will not wake up on it.
1430 *
1431 * Note (compat):
1432 * Standard says "When a subshell is entered, traps that are not being ignored
1433 * are set to the default actions". bash interprets it so that traps which
1434 * are set to '' (ignore) are NOT reset to defaults. We do the same.
1435 */
1436enum {
1437 SPECIAL_INTERACTIVE_SIGS = 0
1438 | (1 << SIGTERM)
1439 | (1 << SIGINT)
1440 | (1 << SIGHUP)
1441 ,
1442 SPECIAL_JOBSTOP_SIGS = 0
1443#if ENABLE_HUSH_JOB
1444 | (1 << SIGTTIN)
1445 | (1 << SIGTTOU)
1446 | (1 << SIGTSTP)
1447#endif
1448 ,
1449};
1450
1451static void record_pending_signo(int sig)
1452{
1453 sigaddset(&G.pending_set, sig);
1454#if ENABLE_HUSH_FAST
1455 if (sig == SIGCHLD) {
1456 G.count_SIGCHLD++;
1457//bb_error_msg("[%d] SIGCHLD_handler: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
1458 }
1459#endif
1460}
1461
1462static sighandler_t install_sighandler(int sig, sighandler_t handler)
1463{
1464 struct sigaction old_sa;
1465
1466 /* We could use signal() to install handlers... almost:
1467 * except that we need to mask ALL signals while handlers run.
1468 * I saw signal nesting in strace, race window isn't small.
1469 * SA_RESTART is also needed, but in Linux, signal()
1470 * sets SA_RESTART too.
1471 */
1472 /* memset(&G.sa, 0, sizeof(G.sa)); - already done */
1473 /* sigfillset(&G.sa.sa_mask); - already done */
1474 /* G.sa.sa_flags = SA_RESTART; - already done */
1475 G.sa.sa_handler = handler;
1476 sigaction(sig, &G.sa, &old_sa);
1477 return old_sa.sa_handler;
1478}
1479
1480static void hush_exit(int exitcode) NORETURN;
1481static void fflush_and__exit(void) NORETURN;
1482static void restore_ttypgrp_and__exit(void) NORETURN;
1483
1484static void restore_ttypgrp_and__exit(void)
1485{
1486 /* xfunc has failed! die die die */
1487 /* no EXIT traps, this is an escape hatch! */
1488 G.exiting = 1;
1489 hush_exit(xfunc_error_retval);
1490}
1491
1492/* Needed only on some libc:
1493 * It was observed that on exit(), fgetc'ed buffered data
1494 * gets "unwound" via lseek(fd, -NUM, SEEK_CUR).
1495 * With the net effect that even after fork(), not vfork(),
1496 * exit() in NOEXECed applet in "sh SCRIPT":
1497 * noexec_applet_here
1498 * echo END_OF_SCRIPT
1499 * lseeks fd in input FILE object from EOF to "e" in "echo END_OF_SCRIPT".
1500 * This makes "echo END_OF_SCRIPT" executed twice.
1501 * Similar problems can be seen with die_if_script() -> xfunc_die()
1502 * and in `cmd` handling.
1503 * If set as die_func(), this makes xfunc_die() exit via _exit(), not exit():
1504 */
1505static void fflush_and__exit(void)
1506{
1507 fflush_all();
1508 _exit(xfunc_error_retval);
1509}
1510
1511#if ENABLE_HUSH_JOB
1512
1513/* After [v]fork, in child: do not restore tty pgrp on xfunc death */
1514# define disable_restore_tty_pgrp_on_exit() (die_func = fflush_and__exit)
1515/* After [v]fork, in parent: restore tty pgrp on xfunc death */
1516# define enable_restore_tty_pgrp_on_exit() (die_func = restore_ttypgrp_and__exit)
1517
1518/* Restores tty foreground process group, and exits.
1519 * May be called as signal handler for fatal signal
1520 * (will resend signal to itself, producing correct exit state)
1521 * or called directly with -EXITCODE.
1522 * We also call it if xfunc is exiting.
1523 */
1524static void sigexit(int sig) NORETURN;
1525static void sigexit(int sig)
1526{
1527 /* Careful: we can end up here after [v]fork. Do not restore
1528 * tty pgrp then, only top-level shell process does that */
1529 if (G_saved_tty_pgrp && getpid() == G.root_pid) {
1530 /* Disable all signals: job control, SIGPIPE, etc.
1531 * Mostly paranoid measure, to prevent infinite SIGTTOU.
1532 */
1533 sigprocmask_allsigs(SIG_BLOCK);
1534 tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp);
1535 }
1536
1537 /* Not a signal, just exit */
1538 if (sig <= 0)
1539 _exit(- sig);
1540
1541 kill_myself_with_sig(sig); /* does not return */
1542}
1543#else
1544
1545# define disable_restore_tty_pgrp_on_exit() ((void)0)
1546# define enable_restore_tty_pgrp_on_exit() ((void)0)
1547
1548#endif
1549
1550static sighandler_t pick_sighandler(unsigned sig)
1551{
1552 sighandler_t handler = SIG_DFL;
1553 if (sig < sizeof(unsigned)*8) {
1554 unsigned sigmask = (1 << sig);
1555
1556#if ENABLE_HUSH_JOB
1557 /* is sig fatal? */
1558 if (G_fatal_sig_mask & sigmask)
1559 handler = sigexit;
1560 else
1561#endif
1562 /* sig has special handling? */
1563 if (G.special_sig_mask & sigmask) {
1564 handler = record_pending_signo;
1565 /* TTIN/TTOU/TSTP can't be set to record_pending_signo
1566 * in order to ignore them: they will be raised
1567 * in an endless loop when we try to do some
1568 * terminal ioctls! We do have to _ignore_ these.
1569 */
1570 if (SPECIAL_JOBSTOP_SIGS & sigmask)
1571 handler = SIG_IGN;
1572 }
1573 }
1574 return handler;
1575}
1576
1577/* Restores tty foreground process group, and exits. */
1578static void hush_exit(int exitcode)
1579{
1580#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
1581 save_history(G.line_input_state);
1582#endif
1583
1584 fflush_all();
1585 if (G.exiting <= 0 && G.traps && G.traps[0] && G.traps[0][0]) {
1586 char *argv[3];
1587 /* argv[0] is unused */
1588 argv[1] = G.traps[0];
1589 argv[2] = NULL;
1590 G.exiting = 1; /* prevent EXIT trap recursion */
1591 /* Note: G.traps[0] is not cleared!
1592 * "trap" will still show it, if executed
1593 * in the handler */
1594 builtin_eval(argv);
1595 }
1596
1597#if ENABLE_FEATURE_CLEAN_UP
1598 {
1599 struct variable *cur_var;
1600 if (G.cwd != bb_msg_unknown)
1601 free((char*)G.cwd);
1602 cur_var = G.top_var;
1603 while (cur_var) {
1604 struct variable *tmp = cur_var;
1605 if (!cur_var->max_len)
1606 free(cur_var->varstr);
1607 cur_var = cur_var->next;
1608 free(tmp);
1609 }
1610 }
1611#endif
1612
1613 fflush_all();
1614#if ENABLE_HUSH_JOB
1615 sigexit(- (exitcode & 0xff));
1616#else
1617 _exit(exitcode);
1618#endif
1619}
1620
1621
1622//TODO: return a mask of ALL handled sigs?
1623static int check_and_run_traps(void)
1624{
1625 int last_sig = 0;
1626
1627 while (1) {
1628 int sig;
1629
1630 if (sigisemptyset(&G.pending_set))
1631 break;
1632 sig = 0;
1633 do {
1634 sig++;
1635 if (sigismember(&G.pending_set, sig)) {
1636 sigdelset(&G.pending_set, sig);
1637 goto got_sig;
1638 }
1639 } while (sig < NSIG);
1640 break;
1641 got_sig:
1642 if (G.traps && G.traps[sig]) {
1643 if (G.traps[sig][0]) {
1644 /* We have user-defined handler */
1645 smalluint save_rcode;
1646 char *argv[3];
1647 /* argv[0] is unused */
1648 argv[1] = G.traps[sig];
1649 argv[2] = NULL;
1650 save_rcode = G.last_exitcode;
1651 builtin_eval(argv);
1652 G.last_exitcode = save_rcode;
1653 last_sig = sig;
1654 } /* else: "" trap, ignoring signal */
1655 continue;
1656 }
1657 /* not a trap: special action */
1658 switch (sig) {
1659 case SIGINT:
1660 /* Builtin was ^C'ed, make it look prettier: */
1661 bb_putchar('\n');
1662 G.flag_SIGINT = 1;
1663 last_sig = sig;
1664 break;
1665#if ENABLE_HUSH_JOB
1666 case SIGHUP: {
1667 struct pipe *job;
1668 /* bash is observed to signal whole process groups,
1669 * not individual processes */
1670 for (job = G.job_list; job; job = job->next) {
1671 if (job->pgrp <= 0)
1672 continue;
1673 debug_printf_exec("HUPing pgrp %d\n", job->pgrp);
1674 if (kill(- job->pgrp, SIGHUP) == 0)
1675 kill(- job->pgrp, SIGCONT);
1676 }
1677 sigexit(SIGHUP);
1678 }
1679#endif
1680#if ENABLE_HUSH_FAST
1681 case SIGCHLD:
1682 G.count_SIGCHLD++;
1683//bb_error_msg("[%d] check_and_run_traps: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
1684 /* Note:
1685 * We dont do 'last_sig = sig' here -> NOT returning this sig.
1686 * This simplifies wait builtin a bit.
1687 */
1688 break;
1689#endif
1690 default: /* ignored: */
1691 /* SIGTERM, SIGQUIT, SIGTTIN, SIGTTOU, SIGTSTP */
1692 /* Note:
1693 * We dont do 'last_sig = sig' here -> NOT returning this sig.
1694 * Example: wait is not interrupted by TERM
1695 * in interactive shell, because TERM is ignored.
1696 */
1697 break;
1698 }
1699 }
1700 return last_sig;
1701}
1702
1703
1704static const char *get_cwd(int force)
1705{
1706 if (force || G.cwd == NULL) {
1707 /* xrealloc_getcwd_or_warn(arg) calls free(arg),
1708 * we must not try to free(bb_msg_unknown) */
1709 if (G.cwd == bb_msg_unknown)
1710 G.cwd = NULL;
1711 G.cwd = xrealloc_getcwd_or_warn((char *)G.cwd);
1712 if (!G.cwd)
1713 G.cwd = bb_msg_unknown;
1714 }
1715 return G.cwd;
1716}
1717
1718
1719/*
1720 * Shell and environment variable support
1721 */
1722static struct variable **get_ptr_to_local_var(const char *name, unsigned len)
1723{
1724 struct variable **pp;
1725 struct variable *cur;
1726
1727 pp = &G.top_var;
1728 while ((cur = *pp) != NULL) {
1729 if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=')
1730 return pp;
1731 pp = &cur->next;
1732 }
1733 return NULL;
1734}
1735
1736static const char* FAST_FUNC get_local_var_value(const char *name)
1737{
1738 struct variable **vpp;
1739 unsigned len = strlen(name);
1740
1741 if (G.expanded_assignments) {
1742 char **cpp = G.expanded_assignments;
1743 while (*cpp) {
1744 char *cp = *cpp;
1745 if (strncmp(cp, name, len) == 0 && cp[len] == '=')
1746 return cp + len + 1;
1747 cpp++;
1748 }
1749 }
1750
1751 vpp = get_ptr_to_local_var(name, len);
1752 if (vpp)
1753 return (*vpp)->varstr + len + 1;
1754
1755 if (strcmp(name, "PPID") == 0)
1756 return utoa(G.root_ppid);
1757 // bash compat: UID? EUID?
1758#if ENABLE_HUSH_RANDOM_SUPPORT
1759 if (strcmp(name, "RANDOM") == 0)
1760 return utoa(next_random(&G.random_gen));
1761#endif
1762 return NULL;
1763}
1764
1765/* str holds "NAME=VAL" and is expected to be malloced.
1766 * We take ownership of it.
1767 * flg_export:
1768 * 0: do not change export flag
1769 * (if creating new variable, flag will be 0)
1770 * 1: set export flag and putenv the variable
1771 * -1: clear export flag and unsetenv the variable
1772 * flg_read_only is set only when we handle -R var=val
1773 */
1774#if !BB_MMU && ENABLE_HUSH_LOCAL
1775/* all params are used */
1776#elif BB_MMU && ENABLE_HUSH_LOCAL
1777#define set_local_var(str, flg_export, local_lvl, flg_read_only) \
1778 set_local_var(str, flg_export, local_lvl)
1779#elif BB_MMU && !ENABLE_HUSH_LOCAL
1780#define set_local_var(str, flg_export, local_lvl, flg_read_only) \
1781 set_local_var(str, flg_export)
1782#elif !BB_MMU && !ENABLE_HUSH_LOCAL
1783#define set_local_var(str, flg_export, local_lvl, flg_read_only) \
1784 set_local_var(str, flg_export, flg_read_only)
1785#endif
1786static int set_local_var(char *str, int flg_export, int local_lvl, int flg_read_only)
1787{
1788 struct variable **var_pp;
1789 struct variable *cur;
1790 char *free_me = NULL;
1791 char *eq_sign;
1792 int name_len;
1793
1794 eq_sign = strchr(str, '=');
1795 if (!eq_sign) { /* not expected to ever happen? */
1796 free(str);
1797 return -1;
1798 }
1799
1800 name_len = eq_sign - str + 1; /* including '=' */
1801 var_pp = &G.top_var;
1802 while ((cur = *var_pp) != NULL) {
1803 if (strncmp(cur->varstr, str, name_len) != 0) {
1804 var_pp = &cur->next;
1805 continue;
1806 }
1807
1808 /* We found an existing var with this name */
1809 if (cur->flg_read_only) {
1810#if !BB_MMU
1811 if (!flg_read_only)
1812#endif
1813 bb_error_msg("%s: readonly variable", str);
1814 free(str);
1815 return -1;
1816 }
1817 if (flg_export == -1) { // "&& cur->flg_export" ?
1818 debug_printf_env("%s: unsetenv '%s'\n", __func__, str);
1819 *eq_sign = '\0';
1820 unsetenv(str);
1821 *eq_sign = '=';
1822 }
1823#if ENABLE_HUSH_LOCAL
1824 if (cur->func_nest_level < local_lvl) {
1825 /* New variable is declared as local,
1826 * and existing one is global, or local
1827 * from enclosing function.
1828 * Remove and save old one: */
1829 *var_pp = cur->next;
1830 cur->next = *G.shadowed_vars_pp;
1831 *G.shadowed_vars_pp = cur;
1832 /* bash 3.2.33(1) and exported vars:
1833 * # export z=z
1834 * # f() { local z=a; env | grep ^z; }
1835 * # f
1836 * z=a
1837 * # env | grep ^z
1838 * z=z
1839 */
1840 if (cur->flg_export)
1841 flg_export = 1;
1842 break;
1843 }
1844#endif
1845 if (strcmp(cur->varstr + name_len, eq_sign + 1) == 0) {
1846 free_and_exp:
1847 free(str);
1848 goto exp;
1849 }
1850 if (cur->max_len != 0) {
1851 if (cur->max_len >= strlen(str)) {
1852 /* This one is from startup env, reuse space */
1853 strcpy(cur->varstr, str);
1854 goto free_and_exp;
1855 }
1856 /* Can't reuse */
1857 cur->max_len = 0;
1858 goto set_str_and_exp;
1859 }
1860 /* max_len == 0 signifies "malloced" var, which we can
1861 * (and have to) free. But we can't free(cur->varstr) here:
1862 * if cur->flg_export is 1, it is in the environment.
1863 * We should either unsetenv+free, or wait until putenv,
1864 * then putenv(new)+free(old).
1865 */
1866 free_me = cur->varstr;
1867 goto set_str_and_exp;
1868 }
1869
1870 /* Not found - create new variable struct */
1871 cur = xzalloc(sizeof(*cur));
1872#if ENABLE_HUSH_LOCAL
1873 cur->func_nest_level = local_lvl;
1874#endif
1875 cur->next = *var_pp;
1876 *var_pp = cur;
1877
1878 set_str_and_exp:
1879 cur->varstr = str;
1880#if !BB_MMU
1881 cur->flg_read_only = flg_read_only;
1882#endif
1883 exp:
1884 if (flg_export == 1)
1885 cur->flg_export = 1;
1886 if (name_len == 4 && cur->varstr[0] == 'P' && cur->varstr[1] == 'S')
1887 cmdedit_update_prompt();
1888 if (cur->flg_export) {
1889 if (flg_export == -1) {
1890 cur->flg_export = 0;
1891 /* unsetenv was already done */
1892 } else {
1893 int i;
1894 debug_printf_env("%s: putenv '%s'\n", __func__, cur->varstr);
1895 i = putenv(cur->varstr);
1896 /* only now we can free old exported malloced string */
1897 free(free_me);
1898 return i;
1899 }
1900 }
1901 free(free_me);
1902 return 0;
1903}
1904
1905/* Used at startup and after each cd */
1906static void set_pwd_var(int exp)
1907{
1908 set_local_var(xasprintf("PWD=%s", get_cwd(/*force:*/ 1)),
1909 /*exp:*/ exp, /*lvl:*/ 0, /*ro:*/ 0);
1910}
1911
1912static int unset_local_var_len(const char *name, int name_len)
1913{
1914 struct variable *cur;
1915 struct variable **var_pp;
1916
1917 if (!name)
1918 return EXIT_SUCCESS;
1919 var_pp = &G.top_var;
1920 while ((cur = *var_pp) != NULL) {
1921 if (strncmp(cur->varstr, name, name_len) == 0 && cur->varstr[name_len] == '=') {
1922 if (cur->flg_read_only) {
1923 bb_error_msg("%s: readonly variable", name);
1924 return EXIT_FAILURE;
1925 }
1926 *var_pp = cur->next;
1927 debug_printf_env("%s: unsetenv '%s'\n", __func__, cur->varstr);
1928 bb_unsetenv(cur->varstr);
1929 if (name_len == 3 && cur->varstr[0] == 'P' && cur->varstr[1] == 'S')
1930 cmdedit_update_prompt();
1931 if (!cur->max_len)
1932 free(cur->varstr);
1933 free(cur);
1934 return EXIT_SUCCESS;
1935 }
1936 var_pp = &cur->next;
1937 }
1938 return EXIT_SUCCESS;
1939}
1940
1941static int unset_local_var(const char *name)
1942{
1943 return unset_local_var_len(name, strlen(name));
1944}
1945
1946static void unset_vars(char **strings)
1947{
1948 char **v;
1949
1950 if (!strings)
1951 return;
1952 v = strings;
1953 while (*v) {
1954 const char *eq = strchrnul(*v, '=');
1955 unset_local_var_len(*v, (int)(eq - *v));
1956 v++;
1957 }
1958 free(strings);
1959}
1960
1961static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val)
1962{
1963 char *var = xasprintf("%s=%s", name, val);
1964 set_local_var(var, /*flags:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
1965}
1966
1967
1968/*
1969 * Helpers for "var1=val1 var2=val2 cmd" feature
1970 */
1971static void add_vars(struct variable *var)
1972{
1973 struct variable *next;
1974
1975 while (var) {
1976 next = var->next;
1977 var->next = G.top_var;
1978 G.top_var = var;
1979 if (var->flg_export) {
1980 debug_printf_env("%s: restoring exported '%s'\n", __func__, var->varstr);
1981 putenv(var->varstr);
1982 } else {
1983 debug_printf_env("%s: restoring variable '%s'\n", __func__, var->varstr);
1984 }
1985 var = next;
1986 }
1987}
1988
1989static struct variable *set_vars_and_save_old(char **strings)
1990{
1991 char **s;
1992 struct variable *old = NULL;
1993
1994 if (!strings)
1995 return old;
1996 s = strings;
1997 while (*s) {
1998 struct variable *var_p;
1999 struct variable **var_pp;
2000 char *eq;
2001
2002 eq = strchr(*s, '=');
2003 if (eq) {
2004 var_pp = get_ptr_to_local_var(*s, eq - *s);
2005 if (var_pp) {
2006 /* Remove variable from global linked list */
2007 var_p = *var_pp;
2008 debug_printf_env("%s: removing '%s'\n", __func__, var_p->varstr);
2009 *var_pp = var_p->next;
2010 /* Add it to returned list */
2011 var_p->next = old;
2012 old = var_p;
2013 }
2014 set_local_var(*s, /*exp:*/ 1, /*lvl:*/ 0, /*ro:*/ 0);
2015 }
2016 s++;
2017 }
2018 return old;
2019}
2020
2021
2022/*
2023 * Unicode helper
2024 */
2025static void reinit_unicode_for_hush(void)
2026{
2027 /* Unicode support should be activated even if LANG is set
2028 * _during_ shell execution, not only if it was set when
2029 * shell was started. Therefore, re-check LANG every time:
2030 */
2031 if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2032 || ENABLE_UNICODE_USING_LOCALE
2033 ) {
2034 const char *s = get_local_var_value("LC_ALL");
2035 if (!s) s = get_local_var_value("LC_CTYPE");
2036 if (!s) s = get_local_var_value("LANG");
2037 reinit_unicode(s);
2038 }
2039}
2040
2041
2042/*
2043 * in_str support
2044 */
2045static int FAST_FUNC static_get(struct in_str *i)
2046{
2047 int ch = *i->p;
2048 if (ch != '\0') {
2049 i->p++;
2050 i->last_char = ch;
2051 return ch;
2052 }
2053 return EOF;
2054}
2055
2056static int FAST_FUNC static_peek(struct in_str *i)
2057{
2058 return *i->p;
2059}
2060
2061#if ENABLE_HUSH_INTERACTIVE
2062
2063static void cmdedit_update_prompt(void)
2064{
2065 if (ENABLE_FEATURE_EDITING_FANCY_PROMPT) {
2066 G.PS1 = get_local_var_value("PS1");
2067 if (G.PS1 == NULL)
2068 G.PS1 = "\\w \\$ ";
2069 G.PS2 = get_local_var_value("PS2");
2070 } else {
2071 G.PS1 = NULL;
2072 }
2073 if (G.PS2 == NULL)
2074 G.PS2 = "> ";
2075}
2076
2077static const char *setup_prompt_string(int promptmode)
2078{
2079 const char *prompt_str;
2080 debug_printf("setup_prompt_string %d ", promptmode);
2081 if (!ENABLE_FEATURE_EDITING_FANCY_PROMPT) {
2082 /* Set up the prompt */
2083 if (promptmode == 0) { /* PS1 */
2084 free((char*)G.PS1);
2085 /* bash uses $PWD value, even if it is set by user.
2086 * It uses current dir only if PWD is unset.
2087 * We always use current dir. */
2088 G.PS1 = xasprintf("%s %c ", get_cwd(0), (geteuid() != 0) ? '$' : '#');
2089 prompt_str = G.PS1;
2090 } else
2091 prompt_str = G.PS2;
2092 } else
2093 prompt_str = (promptmode == 0) ? G.PS1 : G.PS2;
2094 debug_printf("result '%s'\n", prompt_str);
2095 return prompt_str;
2096}
2097
2098static void get_user_input(struct in_str *i)
2099{
2100 int r;
2101 const char *prompt_str;
2102
2103 prompt_str = setup_prompt_string(i->promptmode);
2104# if ENABLE_FEATURE_EDITING
2105 /* Enable command line editing only while a command line
2106 * is actually being read */
2107 do {
2108 reinit_unicode_for_hush();
2109 G.flag_SIGINT = 0;
2110 /* buglet: SIGINT will not make new prompt to appear _at once_,
2111 * only after <Enter>. (^C will work) */
2112 r = read_line_input(G.line_input_state, prompt_str, G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1, /*timeout*/ -1);
2113 /* catch *SIGINT* etc (^C is handled by read_line_input) */
2114 check_and_run_traps();
2115 } while (r == 0 || G.flag_SIGINT); /* repeat if ^C or SIGINT */
2116 i->eof_flag = (r < 0);
2117 if (i->eof_flag) { /* EOF/error detected */
2118 G.user_input_buf[0] = EOF; /* yes, it will be truncated, it's ok */
2119 G.user_input_buf[1] = '\0';
2120 }
2121# else
2122 do {
2123 G.flag_SIGINT = 0;
2124 if (i->last_char == '\0' || i->last_char == '\n') {
2125 /* Why check_and_run_traps here? Try this interactively:
2126 * $ trap 'echo INT' INT; (sleep 2; kill -INT $$) &
2127 * $ <[enter], repeatedly...>
2128 * Without check_and_run_traps, handler never runs.
2129 */
2130 check_and_run_traps();
2131 fputs(prompt_str, stdout);
2132 }
2133 fflush_all();
2134 G.user_input_buf[0] = r = fgetc(i->file);
2135 /*G.user_input_buf[1] = '\0'; - already is and never changed */
2136 } while (G.flag_SIGINT);
2137 i->eof_flag = (r == EOF);
2138# endif
2139 i->p = G.user_input_buf;
2140}
2141
2142#endif /* INTERACTIVE */
2143
2144/* This is the magic location that prints prompts
2145 * and gets data back from the user */
2146static int FAST_FUNC file_get(struct in_str *i)
2147{
2148 int ch;
2149
2150 /* If there is data waiting, eat it up */
2151 if (i->p && *i->p) {
2152#if ENABLE_HUSH_INTERACTIVE
2153 take_cached:
2154#endif
2155 ch = *i->p++;
2156 if (i->eof_flag && !*i->p)
2157 ch = EOF;
2158 /* note: ch is never NUL */
2159 } else {
2160 /* need to double check i->file because we might be doing something
2161 * more complicated by now, like sourcing or substituting. */
2162#if ENABLE_HUSH_INTERACTIVE
2163 if (G_interactive_fd && i->file == stdin) {
2164 do {
2165 get_user_input(i);
2166 } while (!*i->p); /* need non-empty line */
2167 i->promptmode = 1; /* PS2 */
2168 goto take_cached;
2169 }
2170#endif
2171 do ch = fgetc(i->file); while (ch == '\0');
2172 }
2173 debug_printf("file_get: got '%c' %d\n", ch, ch);
2174 i->last_char = ch;
2175 return ch;
2176}
2177
2178/* All callers guarantee this routine will never
2179 * be used right after a newline, so prompting is not needed.
2180 */
2181static int FAST_FUNC file_peek(struct in_str *i)
2182{
2183 int ch;
2184 if (i->p && *i->p) {
2185 if (i->eof_flag && !i->p[1])
2186 return EOF;
2187 return *i->p;
2188 /* note: ch is never NUL */
2189 }
2190 do ch = fgetc(i->file); while (ch == '\0');
2191 i->eof_flag = (ch == EOF);
2192 i->peek_buf[0] = ch;
2193 i->peek_buf[1] = '\0';
2194 i->p = i->peek_buf;
2195 debug_printf("file_peek: got '%c' %d\n", ch, ch);
2196 return ch;
2197}
2198
2199static void setup_file_in_str(struct in_str *i, FILE *f)
2200{
2201 memset(i, 0, sizeof(*i));
2202 i->peek = file_peek;
2203 i->get = file_get;
2204 /* i->promptmode = 0; - PS1 (memset did it) */
2205 i->file = f;
2206 /* i->p = NULL; */
2207}
2208
2209static void setup_string_in_str(struct in_str *i, const char *s)
2210{
2211 memset(i, 0, sizeof(*i));
2212 i->peek = static_peek;
2213 i->get = static_get;
2214 /* i->promptmode = 0; - PS1 (memset did it) */
2215 i->p = s;
2216 /* i->eof_flag = 0; */
2217}
2218
2219
2220/*
2221 * o_string support
2222 */
2223#define B_CHUNK (32 * sizeof(char*))
2224
2225static void o_reset_to_empty_unquoted(o_string *o)
2226{
2227 o->length = 0;
2228 o->has_quoted_part = 0;
2229 if (o->data)
2230 o->data[0] = '\0';
2231}
2232
2233static void o_free(o_string *o)
2234{
2235 free(o->data);
2236 memset(o, 0, sizeof(*o));
2237}
2238
2239static ALWAYS_INLINE void o_free_unsafe(o_string *o)
2240{
2241 free(o->data);
2242}
2243
2244static void o_grow_by(o_string *o, int len)
2245{
2246 if (o->length + len > o->maxlen) {
2247 o->maxlen += (2*len > B_CHUNK ? 2*len : B_CHUNK);
2248 o->data = xrealloc(o->data, 1 + o->maxlen);
2249 }
2250}
2251
2252static void o_addchr(o_string *o, int ch)
2253{
2254 debug_printf("o_addchr: '%c' o->length=%d o=%p\n", ch, o->length, o);
2255 o_grow_by(o, 1);
2256 o->data[o->length] = ch;
2257 o->length++;
2258 o->data[o->length] = '\0';
2259}
2260
2261static void o_addblock(o_string *o, const char *str, int len)
2262{
2263 o_grow_by(o, len);
2264 memcpy(&o->data[o->length], str, len);
2265 o->length += len;
2266 o->data[o->length] = '\0';
2267}
2268
2269static void o_addstr(o_string *o, const char *str)
2270{
2271 o_addblock(o, str, strlen(str));
2272}
2273
2274#if !BB_MMU
2275static void nommu_addchr(o_string *o, int ch)
2276{
2277 if (o)
2278 o_addchr(o, ch);
2279}
2280#else
2281# define nommu_addchr(o, str) ((void)0)
2282#endif
2283
2284static void o_addstr_with_NUL(o_string *o, const char *str)
2285{
2286 o_addblock(o, str, strlen(str) + 1);
2287}
2288
2289/*
2290 * HUSH_BRACE_EXPANSION code needs corresponding quoting on variable expansion side.
2291 * Currently, "v='{q,w}'; echo $v" erroneously expands braces in $v.
2292 * Apparently, on unquoted $v bash still does globbing
2293 * ("v='*.txt'; echo $v" prints all .txt files),
2294 * but NOT brace expansion! Thus, there should be TWO independent
2295 * quoting mechanisms on $v expansion side: one protects
2296 * $v from brace expansion, and other additionally protects "$v" against globbing.
2297 * We have only second one.
2298 */
2299
2300#if ENABLE_HUSH_BRACE_EXPANSION
2301# define MAYBE_BRACES "{}"
2302#else
2303# define MAYBE_BRACES ""
2304#endif
2305
2306/* My analysis of quoting semantics tells me that state information
2307 * is associated with a destination, not a source.
2308 */
2309static void o_addqchr(o_string *o, int ch)
2310{
2311 int sz = 1;
2312 char *found = strchr("*?[\\" MAYBE_BRACES, ch);
2313 if (found)
2314 sz++;
2315 o_grow_by(o, sz);
2316 if (found) {
2317 o->data[o->length] = '\\';
2318 o->length++;
2319 }
2320 o->data[o->length] = ch;
2321 o->length++;
2322 o->data[o->length] = '\0';
2323}
2324
2325static void o_addQchr(o_string *o, int ch)
2326{
2327 int sz = 1;
2328 if ((o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)
2329 && strchr("*?[\\" MAYBE_BRACES, ch)
2330 ) {
2331 sz++;
2332 o->data[o->length] = '\\';
2333 o->length++;
2334 }
2335 o_grow_by(o, sz);
2336 o->data[o->length] = ch;
2337 o->length++;
2338 o->data[o->length] = '\0';
2339}
2340
2341static void o_addqblock(o_string *o, const char *str, int len)
2342{
2343 while (len) {
2344 char ch;
2345 int sz;
2346 int ordinary_cnt = strcspn(str, "*?[\\" MAYBE_BRACES);
2347 if (ordinary_cnt > len) /* paranoia */
2348 ordinary_cnt = len;
2349 o_addblock(o, str, ordinary_cnt);
2350 if (ordinary_cnt == len)
2351 return; /* NUL is already added by o_addblock */
2352 str += ordinary_cnt;
2353 len -= ordinary_cnt + 1; /* we are processing + 1 char below */
2354
2355 ch = *str++;
2356 sz = 1;
2357 if (ch) { /* it is necessarily one of "*?[\\" MAYBE_BRACES */
2358 sz++;
2359 o->data[o->length] = '\\';
2360 o->length++;
2361 }
2362 o_grow_by(o, sz);
2363 o->data[o->length] = ch;
2364 o->length++;
2365 }
2366 o->data[o->length] = '\0';
2367}
2368
2369static void o_addQblock(o_string *o, const char *str, int len)
2370{
2371 if (!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)) {
2372 o_addblock(o, str, len);
2373 return;
2374 }
2375 o_addqblock(o, str, len);
2376}
2377
2378static void o_addQstr(o_string *o, const char *str)
2379{
2380 o_addQblock(o, str, strlen(str));
2381}
2382
2383/* A special kind of o_string for $VAR and `cmd` expansion.
2384 * It contains char* list[] at the beginning, which is grown in 16 element
2385 * increments. Actual string data starts at the next multiple of 16 * (char*).
2386 * list[i] contains an INDEX (int!) into this string data.
2387 * It means that if list[] needs to grow, data needs to be moved higher up
2388 * but list[i]'s need not be modified.
2389 * NB: remembering how many list[i]'s you have there is crucial.
2390 * o_finalize_list() operation post-processes this structure - calculates
2391 * and stores actual char* ptrs in list[]. Oh, it NULL terminates it as well.
2392 */
2393#if DEBUG_EXPAND || DEBUG_GLOB
2394static void debug_print_list(const char *prefix, o_string *o, int n)
2395{
2396 char **list = (char**)o->data;
2397 int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
2398 int i = 0;
2399
2400 indent();
2401 fdprintf(2, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d glob:%d quoted:%d escape:%d\n",
2402 prefix, list, n, string_start, o->length, o->maxlen,
2403 !!(o->o_expflags & EXP_FLAG_GLOB),
2404 o->has_quoted_part,
2405 !!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
2406 while (i < n) {
2407 indent();
2408 fdprintf(2, " list[%d]=%d '%s' %p\n", i, (int)(uintptr_t)list[i],
2409 o->data + (int)(uintptr_t)list[i] + string_start,
2410 o->data + (int)(uintptr_t)list[i] + string_start);
2411 i++;
2412 }
2413 if (n) {
2414 const char *p = o->data + (int)(uintptr_t)list[n - 1] + string_start;
2415 indent();
2416 fdprintf(2, " total_sz:%ld\n", (long)((p + strlen(p) + 1) - o->data));
2417 }
2418}
2419#else
2420# define debug_print_list(prefix, o, n) ((void)0)
2421#endif
2422
2423/* n = o_save_ptr_helper(str, n) "starts new string" by storing an index value
2424 * in list[n] so that it points past last stored byte so far.
2425 * It returns n+1. */
2426static int o_save_ptr_helper(o_string *o, int n)
2427{
2428 char **list = (char**)o->data;
2429 int string_start;
2430 int string_len;
2431
2432 if (!o->has_empty_slot) {
2433 string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
2434 string_len = o->length - string_start;
2435 if (!(n & 0xf)) { /* 0, 0x10, 0x20...? */
2436 debug_printf_list("list[%d]=%d string_start=%d (growing)\n", n, string_len, string_start);
2437 /* list[n] points to string_start, make space for 16 more pointers */
2438 o->maxlen += 0x10 * sizeof(list[0]);
2439 o->data = xrealloc(o->data, o->maxlen + 1);
2440 list = (char**)o->data;
2441 memmove(list + n + 0x10, list + n, string_len);
2442 o->length += 0x10 * sizeof(list[0]);
2443 } else {
2444 debug_printf_list("list[%d]=%d string_start=%d\n",
2445 n, string_len, string_start);
2446 }
2447 } else {
2448 /* We have empty slot at list[n], reuse without growth */
2449 string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); /* NB: n+1! */
2450 string_len = o->length - string_start;
2451 debug_printf_list("list[%d]=%d string_start=%d (empty slot)\n",
2452 n, string_len, string_start);
2453 o->has_empty_slot = 0;
2454 }
2455 o->has_quoted_part = 0;
2456 list[n] = (char*)(uintptr_t)string_len;
2457 return n + 1;
2458}
2459
2460/* "What was our last o_save_ptr'ed position (byte offset relative o->data)?" */
2461static int o_get_last_ptr(o_string *o, int n)
2462{
2463 char **list = (char**)o->data;
2464 int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
2465
2466 return ((int)(uintptr_t)list[n-1]) + string_start;
2467}
2468
2469#if ENABLE_HUSH_BRACE_EXPANSION
2470/* There in a GNU extension, GLOB_BRACE, but it is not usable:
2471 * first, it processes even {a} (no commas), second,
2472 * I didn't manage to make it return strings when they don't match
2473 * existing files. Need to re-implement it.
2474 */
2475
2476/* Helper */
2477static int glob_needed(const char *s)
2478{
2479 while (*s) {
2480 if (*s == '\\') {
2481 if (!s[1])
2482 return 0;
2483 s += 2;
2484 continue;
2485 }
2486 if (*s == '*' || *s == '[' || *s == '?' || *s == '{')
2487 return 1;
2488 s++;
2489 }
2490 return 0;
2491}
2492/* Return pointer to next closing brace or to comma */
2493static const char *next_brace_sub(const char *cp)
2494{
2495 unsigned depth = 0;
2496 cp++;
2497 while (*cp != '\0') {
2498 if (*cp == '\\') {
2499 if (*++cp == '\0')
2500 break;
2501 cp++;
2502 continue;
2503 }
2504 if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
2505 break;
2506 if (*cp++ == '{')
2507 depth++;
2508 }
2509
2510 return *cp != '\0' ? cp : NULL;
2511}
2512/* Recursive brace globber. Note: may garble pattern[]. */
2513static int glob_brace(char *pattern, o_string *o, int n)
2514{
2515 char *new_pattern_buf;
2516 const char *begin;
2517 const char *next;
2518 const char *rest;
2519 const char *p;
2520 size_t rest_len;
2521
2522 debug_printf_glob("glob_brace('%s')\n", pattern);
2523
2524 begin = pattern;
2525 while (1) {
2526 if (*begin == '\0')
2527 goto simple_glob;
2528 if (*begin == '{') {
2529 /* Find the first sub-pattern and at the same time
2530 * find the rest after the closing brace */
2531 next = next_brace_sub(begin);
2532 if (next == NULL) {
2533 /* An illegal expression */
2534 goto simple_glob;
2535 }
2536 if (*next == '}') {
2537 /* "{abc}" with no commas - illegal
2538 * brace expr, disregard and skip it */
2539 begin = next + 1;
2540 continue;
2541 }
2542 break;
2543 }
2544 if (*begin == '\\' && begin[1] != '\0')
2545 begin++;
2546 begin++;
2547 }
2548 debug_printf_glob("begin:%s\n", begin);
2549 debug_printf_glob("next:%s\n", next);
2550
2551 /* Now find the end of the whole brace expression */
2552 rest = next;
2553 while (*rest != '}') {
2554 rest = next_brace_sub(rest);
2555 if (rest == NULL) {
2556 /* An illegal expression */
2557 goto simple_glob;
2558 }
2559 debug_printf_glob("rest:%s\n", rest);
2560 }
2561 rest_len = strlen(++rest) + 1;
2562
2563 /* We are sure the brace expression is well-formed */
2564
2565 /* Allocate working buffer large enough for our work */
2566 new_pattern_buf = xmalloc(strlen(pattern));
2567
2568 /* We have a brace expression. BEGIN points to the opening {,
2569 * NEXT points past the terminator of the first element, and REST
2570 * points past the final }. We will accumulate result names from
2571 * recursive runs for each brace alternative in the buffer using
2572 * GLOB_APPEND. */
2573
2574 p = begin + 1;
2575 while (1) {
2576 /* Construct the new glob expression */
2577 memcpy(
2578 mempcpy(
2579 mempcpy(new_pattern_buf,
2580 /* We know the prefix for all sub-patterns */
2581 pattern, begin - pattern),
2582 p, next - p),
2583 rest, rest_len);
2584
2585 /* Note: glob_brace() may garble new_pattern_buf[].
2586 * That's why we re-copy prefix every time (1st memcpy above).
2587 */
2588 n = glob_brace(new_pattern_buf, o, n);
2589 if (*next == '}') {
2590 /* We saw the last entry */
2591 break;
2592 }
2593 p = next + 1;
2594 next = next_brace_sub(next);
2595 }
2596 free(new_pattern_buf);
2597 return n;
2598
2599 simple_glob:
2600 {
2601 int gr;
2602 glob_t globdata;
2603
2604 memset(&globdata, 0, sizeof(globdata));
2605 gr = glob(pattern, 0, NULL, &globdata);
2606 debug_printf_glob("glob('%s'):%d\n", pattern, gr);
2607 if (gr != 0) {
2608 if (gr == GLOB_NOMATCH) {
2609 globfree(&globdata);
2610 /* NB: garbles parameter */
2611 unbackslash(pattern);
2612 o_addstr_with_NUL(o, pattern);
2613 debug_printf_glob("glob pattern '%s' is literal\n", pattern);
2614 return o_save_ptr_helper(o, n);
2615 }
2616 if (gr == GLOB_NOSPACE)
2617 bb_error_msg_and_die(bb_msg_memory_exhausted);
2618 /* GLOB_ABORTED? Only happens with GLOB_ERR flag,
2619 * but we didn't specify it. Paranoia again. */
2620 bb_error_msg_and_die("glob error %d on '%s'", gr, pattern);
2621 }
2622 if (globdata.gl_pathv && globdata.gl_pathv[0]) {
2623 char **argv = globdata.gl_pathv;
2624 while (1) {
2625 o_addstr_with_NUL(o, *argv);
2626 n = o_save_ptr_helper(o, n);
2627 argv++;
2628 if (!*argv)
2629 break;
2630 }
2631 }
2632 globfree(&globdata);
2633 }
2634 return n;
2635}
2636/* Performs globbing on last list[],
2637 * saving each result as a new list[].
2638 */
2639static int perform_glob(o_string *o, int n)
2640{
2641 char *pattern, *copy;
2642
2643 debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data);
2644 if (!o->data)
2645 return o_save_ptr_helper(o, n);
2646 pattern = o->data + o_get_last_ptr(o, n);
2647 debug_printf_glob("glob pattern '%s'\n", pattern);
2648 if (!glob_needed(pattern)) {
2649 /* unbackslash last string in o in place, fix length */
2650 o->length = unbackslash(pattern) - o->data;
2651 debug_printf_glob("glob pattern '%s' is literal\n", pattern);
2652 return o_save_ptr_helper(o, n);
2653 }
2654
2655 copy = xstrdup(pattern);
2656 /* "forget" pattern in o */
2657 o->length = pattern - o->data;
2658 n = glob_brace(copy, o, n);
2659 free(copy);
2660 if (DEBUG_GLOB)
2661 debug_print_list("perform_glob returning", o, n);
2662 return n;
2663}
2664
2665#else /* !HUSH_BRACE_EXPANSION */
2666
2667/* Helper */
2668static int glob_needed(const char *s)
2669{
2670 while (*s) {
2671 if (*s == '\\') {
2672 if (!s[1])
2673 return 0;
2674 s += 2;
2675 continue;
2676 }
2677 if (*s == '*' || *s == '[' || *s == '?')
2678 return 1;
2679 s++;
2680 }
2681 return 0;
2682}
2683/* Performs globbing on last list[],
2684 * saving each result as a new list[].
2685 */
2686static int perform_glob(o_string *o, int n)
2687{
2688 glob_t globdata;
2689 int gr;
2690 char *pattern;
2691
2692 debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data);
2693 if (!o->data)
2694 return o_save_ptr_helper(o, n);
2695 pattern = o->data + o_get_last_ptr(o, n);
2696 debug_printf_glob("glob pattern '%s'\n", pattern);
2697 if (!glob_needed(pattern)) {
2698 literal:
2699 /* unbackslash last string in o in place, fix length */
2700 o->length = unbackslash(pattern) - o->data;
2701 debug_printf_glob("glob pattern '%s' is literal\n", pattern);
2702 return o_save_ptr_helper(o, n);
2703 }
2704
2705 memset(&globdata, 0, sizeof(globdata));
2706 /* Can't use GLOB_NOCHECK: it does not unescape the string.
2707 * If we glob "*.\*" and don't find anything, we need
2708 * to fall back to using literal "*.*", but GLOB_NOCHECK
2709 * will return "*.\*"!
2710 */
2711 gr = glob(pattern, 0, NULL, &globdata);
2712 debug_printf_glob("glob('%s'):%d\n", pattern, gr);
2713 if (gr != 0) {
2714 if (gr == GLOB_NOMATCH) {
2715 globfree(&globdata);
2716 goto literal;
2717 }
2718 if (gr == GLOB_NOSPACE)
2719 bb_error_msg_and_die(bb_msg_memory_exhausted);
2720 /* GLOB_ABORTED? Only happens with GLOB_ERR flag,
2721 * but we didn't specify it. Paranoia again. */
2722 bb_error_msg_and_die("glob error %d on '%s'", gr, pattern);
2723 }
2724 if (globdata.gl_pathv && globdata.gl_pathv[0]) {
2725 char **argv = globdata.gl_pathv;
2726 /* "forget" pattern in o */
2727 o->length = pattern - o->data;
2728 while (1) {
2729 o_addstr_with_NUL(o, *argv);
2730 n = o_save_ptr_helper(o, n);
2731 argv++;
2732 if (!*argv)
2733 break;
2734 }
2735 }
2736 globfree(&globdata);
2737 if (DEBUG_GLOB)
2738 debug_print_list("perform_glob returning", o, n);
2739 return n;
2740}
2741
2742#endif /* !HUSH_BRACE_EXPANSION */
2743
2744/* If o->o_expflags & EXP_FLAG_GLOB, glob the string so far remembered.
2745 * Otherwise, just finish current list[] and start new */
2746static int o_save_ptr(o_string *o, int n)
2747{
2748 if (o->o_expflags & EXP_FLAG_GLOB) {
2749 /* If o->has_empty_slot, list[n] was already globbed
2750 * (if it was requested back then when it was filled)
2751 * so don't do that again! */
2752 if (!o->has_empty_slot)
2753 return perform_glob(o, n); /* o_save_ptr_helper is inside */
2754 }
2755 return o_save_ptr_helper(o, n);
2756}
2757
2758/* "Please convert list[n] to real char* ptrs, and NULL terminate it." */
2759static char **o_finalize_list(o_string *o, int n)
2760{
2761 char **list;
2762 int string_start;
2763
2764 n = o_save_ptr(o, n); /* force growth for list[n] if necessary */
2765 if (DEBUG_EXPAND)
2766 debug_print_list("finalized", o, n);
2767 debug_printf_expand("finalized n:%d\n", n);
2768 list = (char**)o->data;
2769 string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
2770 list[--n] = NULL;
2771 while (n) {
2772 n--;
2773 list[n] = o->data + (int)(uintptr_t)list[n] + string_start;
2774 }
2775 return list;
2776}
2777
2778static void free_pipe_list(struct pipe *pi);
2779
2780/* Returns pi->next - next pipe in the list */
2781static struct pipe *free_pipe(struct pipe *pi)
2782{
2783 struct pipe *next;
2784 int i;
2785
2786 debug_printf_clean("free_pipe (pid %d)\n", getpid());
2787 for (i = 0; i < pi->num_cmds; i++) {
2788 struct command *command;
2789 struct redir_struct *r, *rnext;
2790
2791 command = &pi->cmds[i];
2792 debug_printf_clean(" command %d:\n", i);
2793 if (command->argv) {
2794 if (DEBUG_CLEAN) {
2795 int a;
2796 char **p;
2797 for (a = 0, p = command->argv; *p; a++, p++) {
2798 debug_printf_clean(" argv[%d] = %s\n", a, *p);
2799 }
2800 }
2801 free_strings(command->argv);
2802 //command->argv = NULL;
2803 }
2804 /* not "else if": on syntax error, we may have both! */
2805 if (command->group) {
2806 debug_printf_clean(" begin group (cmd_type:%d)\n",
2807 command->cmd_type);
2808 free_pipe_list(command->group);
2809 debug_printf_clean(" end group\n");
2810 //command->group = NULL;
2811 }
2812 /* else is crucial here.
2813 * If group != NULL, child_func is meaningless */
2814#if ENABLE_HUSH_FUNCTIONS
2815 else if (command->child_func) {
2816 debug_printf_exec("cmd %p releases child func at %p\n", command, command->child_func);
2817 command->child_func->parent_cmd = NULL;
2818 }
2819#endif
2820#if !BB_MMU
2821 free(command->group_as_string);
2822 //command->group_as_string = NULL;
2823#endif
2824 for (r = command->redirects; r; r = rnext) {
2825 debug_printf_clean(" redirect %d%s",
2826 r->rd_fd, redir_table[r->rd_type].descrip);
2827 /* guard against the case >$FOO, where foo is unset or blank */
2828 if (r->rd_filename) {
2829 debug_printf_clean(" fname:'%s'\n", r->rd_filename);
2830 free(r->rd_filename);
2831 //r->rd_filename = NULL;
2832 }
2833 debug_printf_clean(" rd_dup:%d\n", r->rd_dup);
2834 rnext = r->next;
2835 free(r);
2836 }
2837 //command->redirects = NULL;
2838 }
2839 free(pi->cmds); /* children are an array, they get freed all at once */
2840 //pi->cmds = NULL;
2841#if ENABLE_HUSH_JOB
2842 free(pi->cmdtext);
2843 //pi->cmdtext = NULL;
2844#endif
2845
2846 next = pi->next;
2847 free(pi);
2848 return next;
2849}
2850
2851static void free_pipe_list(struct pipe *pi)
2852{
2853 while (pi) {
2854#if HAS_KEYWORDS
2855 debug_printf_clean("pipe reserved word %d\n", pi->res_word);
2856#endif
2857 debug_printf_clean("pipe followup code %d\n", pi->followup);
2858 pi = free_pipe(pi);
2859 }
2860}
2861
2862
2863/*** Parsing routines ***/
2864
2865#ifndef debug_print_tree
2866static void debug_print_tree(struct pipe *pi, int lvl)
2867{
2868 static const char *const PIPE[] = {
2869 [PIPE_SEQ] = "SEQ",
2870 [PIPE_AND] = "AND",
2871 [PIPE_OR ] = "OR" ,
2872 [PIPE_BG ] = "BG" ,
2873 };
2874 static const char *RES[] = {
2875 [RES_NONE ] = "NONE" ,
2876# if ENABLE_HUSH_IF
2877 [RES_IF ] = "IF" ,
2878 [RES_THEN ] = "THEN" ,
2879 [RES_ELIF ] = "ELIF" ,
2880 [RES_ELSE ] = "ELSE" ,
2881 [RES_FI ] = "FI" ,
2882# endif
2883# if ENABLE_HUSH_LOOPS
2884 [RES_FOR ] = "FOR" ,
2885 [RES_WHILE] = "WHILE",
2886 [RES_UNTIL] = "UNTIL",
2887 [RES_DO ] = "DO" ,
2888 [RES_DONE ] = "DONE" ,
2889# endif
2890# if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
2891 [RES_IN ] = "IN" ,
2892# endif
2893# if ENABLE_HUSH_CASE
2894 [RES_CASE ] = "CASE" ,
2895 [RES_CASE_IN ] = "CASE_IN" ,
2896 [RES_MATCH] = "MATCH",
2897 [RES_CASE_BODY] = "CASE_BODY",
2898 [RES_ESAC ] = "ESAC" ,
2899# endif
2900 [RES_XXXX ] = "XXXX" ,
2901 [RES_SNTX ] = "SNTX" ,
2902 };
2903 static const char *const CMDTYPE[] = {
2904 "{}",
2905 "()",
2906 "[noglob]",
2907# if ENABLE_HUSH_FUNCTIONS
2908 "func()",
2909# endif
2910 };
2911
2912 int pin, prn;
2913
2914 pin = 0;
2915 while (pi) {
2916 fdprintf(2, "%*spipe %d res_word=%s followup=%d %s\n", lvl*2, "",
2917 pin, RES[pi->res_word], pi->followup, PIPE[pi->followup]);
2918 prn = 0;
2919 while (prn < pi->num_cmds) {
2920 struct command *command = &pi->cmds[prn];
2921 char **argv = command->argv;
2922
2923 fdprintf(2, "%*s cmd %d assignment_cnt:%d",
2924 lvl*2, "", prn,
2925 command->assignment_cnt);
2926 if (command->group) {
2927 fdprintf(2, " group %s: (argv=%p)%s%s\n",
2928 CMDTYPE[command->cmd_type],
2929 argv
2930# if !BB_MMU
2931 , " group_as_string:", command->group_as_string
2932# else
2933 , "", ""
2934# endif
2935 );
2936 debug_print_tree(command->group, lvl+1);
2937 prn++;
2938 continue;
2939 }
2940 if (argv) while (*argv) {
2941 fdprintf(2, " '%s'", *argv);
2942 argv++;
2943 }
2944 fdprintf(2, "\n");
2945 prn++;
2946 }
2947 pi = pi->next;
2948 pin++;
2949 }
2950}
2951#endif /* debug_print_tree */
2952
2953static struct pipe *new_pipe(void)
2954{
2955 struct pipe *pi;
2956 pi = xzalloc(sizeof(struct pipe));
2957 /*pi->followup = 0; - deliberately invalid value */
2958 /*pi->res_word = RES_NONE; - RES_NONE is 0 anyway */
2959 return pi;
2960}
2961
2962/* Command (member of a pipe) is complete, or we start a new pipe
2963 * if ctx->command is NULL.
2964 * No errors possible here.
2965 */
2966static int done_command(struct parse_context *ctx)
2967{
2968 /* The command is really already in the pipe structure, so
2969 * advance the pipe counter and make a new, null command. */
2970 struct pipe *pi = ctx->pipe;
2971 struct command *command = ctx->command;
2972
2973 if (command) {
2974 if (IS_NULL_CMD(command)) {
2975 debug_printf_parse("done_command: skipping null cmd, num_cmds=%d\n", pi->num_cmds);
2976 goto clear_and_ret;
2977 }
2978 pi->num_cmds++;
2979 debug_printf_parse("done_command: ++num_cmds=%d\n", pi->num_cmds);
2980 //debug_print_tree(ctx->list_head, 20);
2981 } else {
2982 debug_printf_parse("done_command: initializing, num_cmds=%d\n", pi->num_cmds);
2983 }
2984
2985 /* Only real trickiness here is that the uncommitted
2986 * command structure is not counted in pi->num_cmds. */
2987 pi->cmds = xrealloc(pi->cmds, sizeof(*pi->cmds) * (pi->num_cmds+1));
2988 ctx->command = command = &pi->cmds[pi->num_cmds];
2989 clear_and_ret:
2990 memset(command, 0, sizeof(*command));
2991 return pi->num_cmds; /* used only for 0/nonzero check */
2992}
2993
2994static void done_pipe(struct parse_context *ctx, pipe_style type)
2995{
2996 int not_null;
2997
2998 debug_printf_parse("done_pipe entered, followup %d\n", type);
2999 /* Close previous command */
3000 not_null = done_command(ctx);
3001 ctx->pipe->followup = type;
3002#if HAS_KEYWORDS
3003 ctx->pipe->pi_inverted = ctx->ctx_inverted;
3004 ctx->ctx_inverted = 0;
3005 ctx->pipe->res_word = ctx->ctx_res_w;
3006#endif
3007
3008 /* Without this check, even just <enter> on command line generates
3009 * tree of three NOPs (!). Which is harmless but annoying.
3010 * IOW: it is safe to do it unconditionally. */
3011 if (not_null
3012#if ENABLE_HUSH_IF
3013 || ctx->ctx_res_w == RES_FI
3014#endif
3015#if ENABLE_HUSH_LOOPS
3016 || ctx->ctx_res_w == RES_DONE
3017 || ctx->ctx_res_w == RES_FOR
3018 || ctx->ctx_res_w == RES_IN
3019#endif
3020#if ENABLE_HUSH_CASE
3021 || ctx->ctx_res_w == RES_ESAC
3022#endif
3023 ) {
3024 struct pipe *new_p;
3025 debug_printf_parse("done_pipe: adding new pipe: "
3026 "not_null:%d ctx->ctx_res_w:%d\n",
3027 not_null, ctx->ctx_res_w);
3028 new_p = new_pipe();
3029 ctx->pipe->next = new_p;
3030 ctx->pipe = new_p;
3031 /* RES_THEN, RES_DO etc are "sticky" -
3032 * they remain set for pipes inside if/while.
3033 * This is used to control execution.
3034 * RES_FOR and RES_IN are NOT sticky (needed to support
3035 * cases where variable or value happens to match a keyword):
3036 */
3037#if ENABLE_HUSH_LOOPS
3038 if (ctx->ctx_res_w == RES_FOR
3039 || ctx->ctx_res_w == RES_IN)
3040 ctx->ctx_res_w = RES_NONE;
3041#endif
3042#if ENABLE_HUSH_CASE
3043 if (ctx->ctx_res_w == RES_MATCH)
3044 ctx->ctx_res_w = RES_CASE_BODY;
3045 if (ctx->ctx_res_w == RES_CASE)
3046 ctx->ctx_res_w = RES_CASE_IN;
3047#endif
3048 ctx->command = NULL; /* trick done_command below */
3049 /* Create the memory for command, roughly:
3050 * ctx->pipe->cmds = new struct command;
3051 * ctx->command = &ctx->pipe->cmds[0];
3052 */
3053 done_command(ctx);
3054 //debug_print_tree(ctx->list_head, 10);
3055 }
3056 debug_printf_parse("done_pipe return\n");
3057}
3058
3059static void initialize_context(struct parse_context *ctx)
3060{
3061 memset(ctx, 0, sizeof(*ctx));
3062 ctx->pipe = ctx->list_head = new_pipe();
3063 /* Create the memory for command, roughly:
3064 * ctx->pipe->cmds = new struct command;
3065 * ctx->command = &ctx->pipe->cmds[0];
3066 */
3067 done_command(ctx);
3068}
3069
3070/* If a reserved word is found and processed, parse context is modified
3071 * and 1 is returned.
3072 */
3073#if HAS_KEYWORDS
3074struct reserved_combo {
3075 char literal[6];
3076 unsigned char res;
3077 unsigned char assignment_flag;
3078 int flag;
3079};
3080enum {
3081 FLAG_END = (1 << RES_NONE ),
3082# if ENABLE_HUSH_IF
3083 FLAG_IF = (1 << RES_IF ),
3084 FLAG_THEN = (1 << RES_THEN ),
3085 FLAG_ELIF = (1 << RES_ELIF ),
3086 FLAG_ELSE = (1 << RES_ELSE ),
3087 FLAG_FI = (1 << RES_FI ),
3088# endif
3089# if ENABLE_HUSH_LOOPS
3090 FLAG_FOR = (1 << RES_FOR ),
3091 FLAG_WHILE = (1 << RES_WHILE),
3092 FLAG_UNTIL = (1 << RES_UNTIL),
3093 FLAG_DO = (1 << RES_DO ),
3094 FLAG_DONE = (1 << RES_DONE ),
3095 FLAG_IN = (1 << RES_IN ),
3096# endif
3097# if ENABLE_HUSH_CASE
3098 FLAG_MATCH = (1 << RES_MATCH),
3099 FLAG_ESAC = (1 << RES_ESAC ),
3100# endif
3101 FLAG_START = (1 << RES_XXXX ),
3102};
3103
3104static const struct reserved_combo* match_reserved_word(o_string *word)
3105{
3106 /* Mostly a list of accepted follow-up reserved words.
3107 * FLAG_END means we are done with the sequence, and are ready
3108 * to turn the compound list into a command.
3109 * FLAG_START means the word must start a new compound list.
3110 */
3111 static const struct reserved_combo reserved_list[] = {
3112# if ENABLE_HUSH_IF
3113 { "!", RES_NONE, NOT_ASSIGNMENT , 0 },
3114 { "if", RES_IF, MAYBE_ASSIGNMENT, FLAG_THEN | FLAG_START },
3115 { "then", RES_THEN, MAYBE_ASSIGNMENT, FLAG_ELIF | FLAG_ELSE | FLAG_FI },
3116 { "elif", RES_ELIF, MAYBE_ASSIGNMENT, FLAG_THEN },
3117 { "else", RES_ELSE, MAYBE_ASSIGNMENT, FLAG_FI },
3118 { "fi", RES_FI, NOT_ASSIGNMENT , FLAG_END },
3119# endif
3120# if ENABLE_HUSH_LOOPS
3121 { "for", RES_FOR, NOT_ASSIGNMENT , FLAG_IN | FLAG_DO | FLAG_START },
3122 { "while", RES_WHILE, MAYBE_ASSIGNMENT, FLAG_DO | FLAG_START },
3123 { "until", RES_UNTIL, MAYBE_ASSIGNMENT, FLAG_DO | FLAG_START },
3124 { "in", RES_IN, NOT_ASSIGNMENT , FLAG_DO },
3125 { "do", RES_DO, MAYBE_ASSIGNMENT, FLAG_DONE },
3126 { "done", RES_DONE, NOT_ASSIGNMENT , FLAG_END },
3127# endif
3128# if ENABLE_HUSH_CASE
3129 { "case", RES_CASE, NOT_ASSIGNMENT , FLAG_MATCH | FLAG_START },
3130 { "esac", RES_ESAC, NOT_ASSIGNMENT , FLAG_END },
3131# endif
3132 };
3133 const struct reserved_combo *r;
3134
3135 for (r = reserved_list; r < reserved_list + ARRAY_SIZE(reserved_list); r++) {
3136 if (strcmp(word->data, r->literal) == 0)
3137 return r;
3138 }
3139 return NULL;
3140}
3141/* Return 0: not a keyword, 1: keyword
3142 */
3143static int reserved_word(o_string *word, struct parse_context *ctx)
3144{
3145# if ENABLE_HUSH_CASE
3146 static const struct reserved_combo reserved_match = {
3147 "", RES_MATCH, NOT_ASSIGNMENT , FLAG_MATCH | FLAG_ESAC
3148 };
3149# endif
3150 const struct reserved_combo *r;
3151
3152 if (word->has_quoted_part)
3153 return 0;
3154 r = match_reserved_word(word);
3155 if (!r)
3156 return 0;
3157
3158 debug_printf("found reserved word %s, res %d\n", r->literal, r->res);
3159# if ENABLE_HUSH_CASE
3160 if (r->res == RES_IN && ctx->ctx_res_w == RES_CASE_IN) {
3161 /* "case word IN ..." - IN part starts first MATCH part */
3162 r = &reserved_match;
3163 } else
3164# endif
3165 if (r->flag == 0) { /* '!' */
3166 if (ctx->ctx_inverted) { /* bash doesn't accept '! ! true' */
3167 syntax_error("! ! command");
3168 ctx->ctx_res_w = RES_SNTX;
3169 }
3170 ctx->ctx_inverted = 1;
3171 return 1;
3172 }
3173 if (r->flag & FLAG_START) {
3174 struct parse_context *old;
3175
3176 old = xmalloc(sizeof(*old));
3177 debug_printf_parse("push stack %p\n", old);
3178 *old = *ctx; /* physical copy */
3179 initialize_context(ctx);
3180 ctx->stack = old;
3181 } else if (/*ctx->ctx_res_w == RES_NONE ||*/ !(ctx->old_flag & (1 << r->res))) {
3182 syntax_error_at(word->data);
3183 ctx->ctx_res_w = RES_SNTX;
3184 return 1;
3185 } else {
3186 /* "{...} fi" is ok. "{...} if" is not
3187 * Example:
3188 * if { echo foo; } then { echo bar; } fi */
3189 if (ctx->command->group)
3190 done_pipe(ctx, PIPE_SEQ);
3191 }
3192
3193 ctx->ctx_res_w = r->res;
3194 ctx->old_flag = r->flag;
3195 word->o_assignment = r->assignment_flag;
3196 debug_printf_parse("word->o_assignment='%s'\n", assignment_flag[word->o_assignment]);
3197
3198 if (ctx->old_flag & FLAG_END) {
3199 struct parse_context *old;
3200
3201 done_pipe(ctx, PIPE_SEQ);
3202 debug_printf_parse("pop stack %p\n", ctx->stack);
3203 old = ctx->stack;
3204 old->command->group = ctx->list_head;
3205 old->command->cmd_type = CMD_NORMAL;
3206# if !BB_MMU
3207 /* At this point, the compound command's string is in
3208 * ctx->as_string... except for the leading keyword!
3209 * Consider this example: "echo a | if true; then echo a; fi"
3210 * ctx->as_string will contain "true; then echo a; fi",
3211 * with "if " remaining in old->as_string!
3212 */
3213 {
3214 char *str;
3215 int len = old->as_string.length;
3216 /* Concatenate halves */
3217 o_addstr(&old->as_string, ctx->as_string.data);
3218 o_free_unsafe(&ctx->as_string);
3219 /* Find where leading keyword starts in first half */
3220 str = old->as_string.data + len;
3221 if (str > old->as_string.data)
3222 str--; /* skip whitespace after keyword */
3223 while (str > old->as_string.data && isalpha(str[-1]))
3224 str--;
3225 /* Ugh, we're done with this horrid hack */
3226 old->command->group_as_string = xstrdup(str);
3227 debug_printf_parse("pop, remembering as:'%s'\n",
3228 old->command->group_as_string);
3229 }
3230# endif
3231 *ctx = *old; /* physical copy */
3232 free(old);
3233 }
3234 return 1;
3235}
3236#endif /* HAS_KEYWORDS */
3237
3238/* Word is complete, look at it and update parsing context.
3239 * Normal return is 0. Syntax errors return 1.
3240 * Note: on return, word is reset, but not o_free'd!
3241 */
3242static int done_word(o_string *word, struct parse_context *ctx)
3243{
3244 struct command *command = ctx->command;
3245
3246 debug_printf_parse("done_word entered: '%s' %p\n", word->data, command);
3247 if (word->length == 0 && !word->has_quoted_part) {
3248 debug_printf_parse("done_word return 0: true null, ignored\n");
3249 return 0;
3250 }
3251
3252 if (ctx->pending_redirect) {
3253 /* We do not glob in e.g. >*.tmp case. bash seems to glob here
3254 * only if run as "bash", not "sh" */
3255 /* http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
3256 * "2.7 Redirection
3257 * ...the word that follows the redirection operator
3258 * shall be subjected to tilde expansion, parameter expansion,
3259 * command substitution, arithmetic expansion, and quote
3260 * removal. Pathname expansion shall not be performed
3261 * on the word by a non-interactive shell; an interactive
3262 * shell may perform it, but shall do so only when
3263 * the expansion would result in one word."
3264 */
3265 ctx->pending_redirect->rd_filename = xstrdup(word->data);
3266 /* Cater for >\file case:
3267 * >\a creates file a; >\\a, >"\a", >"\\a" create file \a
3268 * Same with heredocs:
3269 * for <<\H delim is H; <<\\H, <<"\H", <<"\\H" - \H
3270 */
3271 if (ctx->pending_redirect->rd_type == REDIRECT_HEREDOC) {
3272 unbackslash(ctx->pending_redirect->rd_filename);
3273 /* Is it <<"HEREDOC"? */
3274 if (word->has_quoted_part) {
3275 ctx->pending_redirect->rd_dup |= HEREDOC_QUOTED;
3276 }
3277 }
3278 debug_printf_parse("word stored in rd_filename: '%s'\n", word->data);
3279 ctx->pending_redirect = NULL;
3280 } else {
3281#if HAS_KEYWORDS
3282# if ENABLE_HUSH_CASE
3283 if (ctx->ctx_dsemicolon
3284 && strcmp(word->data, "esac") != 0 /* not "... pattern) cmd;; esac" */
3285 ) {
3286 /* already done when ctx_dsemicolon was set to 1: */
3287 /* ctx->ctx_res_w = RES_MATCH; */
3288 ctx->ctx_dsemicolon = 0;
3289 } else
3290# endif
3291 if (!command->argv /* if it's the first word... */
3292# if ENABLE_HUSH_LOOPS
3293 && ctx->ctx_res_w != RES_FOR /* ...not after FOR or IN */
3294 && ctx->ctx_res_w != RES_IN
3295# endif
3296# if ENABLE_HUSH_CASE
3297 && ctx->ctx_res_w != RES_CASE
3298# endif
3299 ) {
3300 int reserved = reserved_word(word, ctx);
3301 debug_printf_parse("checking for reserved-ness: %d\n", reserved);
3302 if (reserved) {
3303 o_reset_to_empty_unquoted(word);
3304 debug_printf_parse("done_word return %d\n",
3305 (ctx->ctx_res_w == RES_SNTX));
3306 return (ctx->ctx_res_w == RES_SNTX);
3307 }
3308# if ENABLE_HUSH_BASH_COMPAT
3309 if (strcmp(word->data, "[[") == 0) {
3310 command->cmd_type = CMD_SINGLEWORD_NOGLOB;
3311 }
3312 /* fall through */
3313# endif
3314 }
3315#endif
3316 if (command->group) {
3317 /* "{ echo foo; } echo bar" - bad */
3318 syntax_error_at(word->data);
3319 debug_printf_parse("done_word return 1: syntax error, "
3320 "groups and arglists don't mix\n");
3321 return 1;
3322 }
3323
3324 /* If this word wasn't an assignment, next ones definitely
3325 * can't be assignments. Even if they look like ones. */
3326 if (word->o_assignment != DEFINITELY_ASSIGNMENT
3327 && word->o_assignment != WORD_IS_KEYWORD
3328 ) {
3329 word->o_assignment = NOT_ASSIGNMENT;
3330 } else {
3331 if (word->o_assignment == DEFINITELY_ASSIGNMENT) {
3332 command->assignment_cnt++;
3333 debug_printf_parse("++assignment_cnt=%d\n", command->assignment_cnt);
3334 }
3335 debug_printf_parse("word->o_assignment was:'%s'\n", assignment_flag[word->o_assignment]);
3336 word->o_assignment = MAYBE_ASSIGNMENT;
3337 }
3338 debug_printf_parse("word->o_assignment='%s'\n", assignment_flag[word->o_assignment]);
3339
3340 if (word->has_quoted_part
3341 /* optimization: and if it's ("" or '') or ($v... or `cmd`...): */
3342 && (word->data[0] == '\0' || word->data[0] == SPECIAL_VAR_SYMBOL)
3343 /* (otherwise it's known to be not empty and is already safe) */
3344 ) {
3345 /* exclude "$@" - it can expand to no word despite "" */
3346 char *p = word->data;
3347 while (p[0] == SPECIAL_VAR_SYMBOL
3348 && (p[1] & 0x7f) == '@'
3349 && p[2] == SPECIAL_VAR_SYMBOL
3350 ) {
3351 p += 3;
3352 }
3353 }
3354 command->argv = add_string_to_strings(command->argv, xstrdup(word->data));
3355 debug_print_strings("word appended to argv", command->argv);
3356 }
3357
3358#if ENABLE_HUSH_LOOPS
3359 if (ctx->ctx_res_w == RES_FOR) {
3360 if (word->has_quoted_part
3361 || !is_well_formed_var_name(command->argv[0], '\0')
3362 ) {
3363 /* bash says just "not a valid identifier" */
3364 syntax_error("not a valid identifier in for");
3365 return 1;
3366 }
3367 /* Force FOR to have just one word (variable name) */
3368 /* NB: basically, this makes hush see "for v in ..."
3369 * syntax as if it is "for v; in ...". FOR and IN become
3370 * two pipe structs in parse tree. */
3371 done_pipe(ctx, PIPE_SEQ);
3372 }
3373#endif
3374#if ENABLE_HUSH_CASE
3375 /* Force CASE to have just one word */
3376 if (ctx->ctx_res_w == RES_CASE) {
3377 done_pipe(ctx, PIPE_SEQ);
3378 }
3379#endif
3380
3381 o_reset_to_empty_unquoted(word);
3382
3383 debug_printf_parse("done_word return 0\n");
3384 return 0;
3385}
3386
3387
3388/* Peek ahead in the input to find out if we have a "&n" construct,
3389 * as in "2>&1", that represents duplicating a file descriptor.
3390 * Return:
3391 * REDIRFD_CLOSE if >&- "close fd" construct is seen,
3392 * REDIRFD_SYNTAX_ERR if syntax error,
3393 * REDIRFD_TO_FILE if no & was seen,
3394 * or the number found.
3395 */
3396#if BB_MMU
3397#define parse_redir_right_fd(as_string, input) \
3398 parse_redir_right_fd(input)
3399#endif
3400static int parse_redir_right_fd(o_string *as_string, struct in_str *input)
3401{
3402 int ch, d, ok;
3403
3404 ch = i_peek(input);
3405 if (ch != '&')
3406 return REDIRFD_TO_FILE;
3407
3408 ch = i_getch(input); /* get the & */
3409 nommu_addchr(as_string, ch);
3410 ch = i_peek(input);
3411 if (ch == '-') {
3412 ch = i_getch(input);
3413 nommu_addchr(as_string, ch);
3414 return REDIRFD_CLOSE;
3415 }
3416 d = 0;
3417 ok = 0;
3418 while (ch != EOF && isdigit(ch)) {
3419 d = d*10 + (ch-'0');
3420 ok = 1;
3421 ch = i_getch(input);
3422 nommu_addchr(as_string, ch);
3423 ch = i_peek(input);
3424 }
3425 if (ok) return d;
3426
3427//TODO: this is the place to catch ">&file" bashism (redirect both fd 1 and 2)
3428
3429 bb_error_msg("ambiguous redirect");
3430 return REDIRFD_SYNTAX_ERR;
3431}
3432
3433/* Return code is 0 normal, 1 if a syntax error is detected
3434 */
3435static int parse_redirect(struct parse_context *ctx,
3436 int fd,
3437 redir_type style,
3438 struct in_str *input)
3439{
3440 struct command *command = ctx->command;
3441 struct redir_struct *redir;
3442 struct redir_struct **redirp;
3443 int dup_num;
3444
3445 dup_num = REDIRFD_TO_FILE;
3446 if (style != REDIRECT_HEREDOC) {
3447 /* Check for a '>&1' type redirect */
3448 dup_num = parse_redir_right_fd(&ctx->as_string, input);
3449 if (dup_num == REDIRFD_SYNTAX_ERR)
3450 return 1;
3451 } else {
3452 int ch = i_peek(input);
3453 dup_num = (ch == '-'); /* HEREDOC_SKIPTABS bit is 1 */
3454 if (dup_num) { /* <<-... */
3455 ch = i_getch(input);
3456 nommu_addchr(&ctx->as_string, ch);
3457 ch = i_peek(input);
3458 }
3459 }
3460
3461 if (style == REDIRECT_OVERWRITE && dup_num == REDIRFD_TO_FILE) {
3462 int ch = i_peek(input);
3463 if (ch == '|') {
3464 /* >|FILE redirect ("clobbering" >).
3465 * Since we do not support "set -o noclobber" yet,
3466 * >| and > are the same for now. Just eat |.
3467 */
3468 ch = i_getch(input);
3469 nommu_addchr(&ctx->as_string, ch);
3470 }
3471 }
3472
3473 /* Create a new redir_struct and append it to the linked list */
3474 redirp = &command->redirects;
3475 while ((redir = *redirp) != NULL) {
3476 redirp = &(redir->next);
3477 }
3478 *redirp = redir = xzalloc(sizeof(*redir));
3479 /* redir->next = NULL; */
3480 /* redir->rd_filename = NULL; */
3481 redir->rd_type = style;
3482 redir->rd_fd = (fd == -1) ? redir_table[style].default_fd : fd;
3483
3484 debug_printf_parse("redirect type %d %s\n", redir->rd_fd,
3485 redir_table[style].descrip);
3486
3487 redir->rd_dup = dup_num;
3488 if (style != REDIRECT_HEREDOC && dup_num != REDIRFD_TO_FILE) {
3489 /* Erik had a check here that the file descriptor in question
3490 * is legit; I postpone that to "run time"
3491 * A "-" representation of "close me" shows up as a -3 here */
3492 debug_printf_parse("duplicating redirect '%d>&%d'\n",
3493 redir->rd_fd, redir->rd_dup);
3494 } else {
3495 /* Set ctx->pending_redirect, so we know what to do at the
3496 * end of the next parsed word. */
3497 ctx->pending_redirect = redir;
3498 }
3499 return 0;
3500}
3501
3502/* If a redirect is immediately preceded by a number, that number is
3503 * supposed to tell which file descriptor to redirect. This routine
3504 * looks for such preceding numbers. In an ideal world this routine
3505 * needs to handle all the following classes of redirects...
3506 * echo 2>foo # redirects fd 2 to file "foo", nothing passed to echo
3507 * echo 49>foo # redirects fd 49 to file "foo", nothing passed to echo
3508 * echo -2>foo # redirects fd 1 to file "foo", "-2" passed to echo
3509 * echo 49x>foo # redirects fd 1 to file "foo", "49x" passed to echo
3510 *
3511 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
3512 * "2.7 Redirection
3513 * ... If n is quoted, the number shall not be recognized as part of
3514 * the redirection expression. For example:
3515 * echo \2>a
3516 * writes the character 2 into file a"
3517 * We are getting it right by setting ->has_quoted_part on any \<char>
3518 *
3519 * A -1 return means no valid number was found,
3520 * the caller should use the appropriate default for this redirection.
3521 */
3522static int redirect_opt_num(o_string *o)
3523{
3524 int num;
3525
3526 if (o->data == NULL)
3527 return -1;
3528 num = bb_strtou(o->data, NULL, 10);
3529 if (errno || num < 0)
3530 return -1;
3531 o_reset_to_empty_unquoted(o);
3532 return num;
3533}
3534
3535#if BB_MMU
3536#define fetch_till_str(as_string, input, word, skip_tabs) \
3537 fetch_till_str(input, word, skip_tabs)
3538#endif
3539static char *fetch_till_str(o_string *as_string,
3540 struct in_str *input,
3541 const char *word,
3542 int heredoc_flags)
3543{
3544 o_string heredoc = NULL_O_STRING;
3545 unsigned past_EOL;
3546 int prev = 0; /* not \ */
3547 int ch;
3548
3549 goto jump_in;
3550
3551 while (1) {
3552 ch = i_getch(input);
3553 if (ch != EOF)
3554 nommu_addchr(as_string, ch);
3555 if ((ch == '\n' || ch == EOF)
3556 && ((heredoc_flags & HEREDOC_QUOTED) || prev != '\\')
3557 ) {
3558 if (strcmp(heredoc.data + past_EOL, word) == 0) {
3559 heredoc.data[past_EOL] = '\0';
3560 debug_printf_parse("parsed heredoc '%s'\n", heredoc.data);
3561 return heredoc.data;
3562 }
3563 while (ch == '\n') {
3564 o_addchr(&heredoc, ch);
3565 prev = ch;
3566 jump_in:
3567 past_EOL = heredoc.length;
3568 do {
3569 ch = i_getch(input);
3570 if (ch != EOF)
3571 nommu_addchr(as_string, ch);
3572 } while ((heredoc_flags & HEREDOC_SKIPTABS) && ch == '\t');
3573 }
3574 }
3575 if (ch == EOF) {
3576 o_free_unsafe(&heredoc);
3577 return NULL;
3578 }
3579 o_addchr(&heredoc, ch);
3580 nommu_addchr(as_string, ch);
3581 if (prev == '\\' && ch == '\\')
3582 /* Correctly handle foo\\<eol> (not a line cont.) */
3583 prev = 0; /* not \ */
3584 else
3585 prev = ch;
3586 }
3587}
3588
3589/* Look at entire parse tree for not-yet-loaded REDIRECT_HEREDOCs
3590 * and load them all. There should be exactly heredoc_cnt of them.
3591 */
3592static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_str *input)
3593{
3594 struct pipe *pi = ctx->list_head;
3595
3596 while (pi && heredoc_cnt) {
3597 int i;
3598 struct command *cmd = pi->cmds;
3599
3600 debug_printf_parse("fetch_heredocs: num_cmds:%d cmd argv0:'%s'\n",
3601 pi->num_cmds,
3602 cmd->argv ? cmd->argv[0] : "NONE");
3603 for (i = 0; i < pi->num_cmds; i++) {
3604 struct redir_struct *redir = cmd->redirects;
3605
3606 debug_printf_parse("fetch_heredocs: %d cmd argv0:'%s'\n",
3607 i, cmd->argv ? cmd->argv[0] : "NONE");
3608 while (redir) {
3609 if (redir->rd_type == REDIRECT_HEREDOC) {
3610 char *p;
3611
3612 redir->rd_type = REDIRECT_HEREDOC2;
3613 /* redir->rd_dup is (ab)used to indicate <<- */
3614 p = fetch_till_str(&ctx->as_string, input,
3615 redir->rd_filename, redir->rd_dup);
3616 if (!p) {
3617 syntax_error("unexpected EOF in here document");
3618 return 1;
3619 }
3620 free(redir->rd_filename);
3621 redir->rd_filename = p;
3622 heredoc_cnt--;
3623 }
3624 redir = redir->next;
3625 }
3626 cmd++;
3627 }
3628 pi = pi->next;
3629 }
3630#if 0
3631 /* Should be 0. If it isn't, it's a parse error */
3632 if (heredoc_cnt)
3633 bb_error_msg_and_die("heredoc BUG 2");
3634#endif
3635 return 0;
3636}
3637
3638
3639static int run_list(struct pipe *pi);
3640#if BB_MMU
3641#define parse_stream(pstring, input, end_trigger) \
3642 parse_stream(input, end_trigger)
3643#endif
3644static struct pipe *parse_stream(char **pstring,
3645 struct in_str *input,
3646 int end_trigger);
3647
3648
3649#if !ENABLE_HUSH_FUNCTIONS
3650#define parse_group(dest, ctx, input, ch) \
3651 parse_group(ctx, input, ch)
3652#endif
3653static int parse_group(o_string *dest, struct parse_context *ctx,
3654 struct in_str *input, int ch)
3655{
3656 /* dest contains characters seen prior to ( or {.
3657 * Typically it's empty, but for function defs,
3658 * it contains function name (without '()'). */
3659 struct pipe *pipe_list;
3660 int endch;
3661 struct command *command = ctx->command;
3662
3663 debug_printf_parse("parse_group entered\n");
3664#if ENABLE_HUSH_FUNCTIONS
3665 if (ch == '(' && !dest->has_quoted_part) {
3666 if (dest->length)
3667 if (done_word(dest, ctx))
3668 return 1;
3669 if (!command->argv)
3670 goto skip; /* (... */
3671 if (command->argv[1]) { /* word word ... (... */
3672 syntax_error_unexpected_ch('(');
3673 return 1;
3674 }
3675 /* it is "word(..." or "word (..." */
3676 do
3677 ch = i_getch(input);
3678 while (ch == ' ' || ch == '\t');
3679 if (ch != ')') {
3680 syntax_error_unexpected_ch(ch);
3681 return 1;
3682 }
3683 nommu_addchr(&ctx->as_string, ch);
3684 do
3685 ch = i_getch(input);
3686 while (ch == ' ' || ch == '\t' || ch == '\n');
3687 if (ch != '{') {
3688 syntax_error_unexpected_ch(ch);
3689 return 1;
3690 }
3691 nommu_addchr(&ctx->as_string, ch);
3692 command->cmd_type = CMD_FUNCDEF;
3693 goto skip;
3694 }
3695#endif
3696
3697#if 0 /* Prevented by caller */
3698 if (command->argv /* word [word]{... */
3699 || dest->length /* word{... */
3700 || dest->has_quoted_part /* ""{... */
3701 ) {
3702 syntax_error(NULL);
3703 debug_printf_parse("parse_group return 1: "
3704 "syntax error, groups and arglists don't mix\n");
3705 return 1;
3706 }
3707#endif
3708
3709#if ENABLE_HUSH_FUNCTIONS
3710 skip:
3711#endif
3712 endch = '}';
3713 if (ch == '(') {
3714 endch = ')';
3715 command->cmd_type = CMD_SUBSHELL;
3716 } else {
3717 /* bash does not allow "{echo...", requires whitespace */
3718 ch = i_getch(input);
3719 if (ch != ' ' && ch != '\t' && ch != '\n') {
3720 syntax_error_unexpected_ch(ch);
3721 return 1;
3722 }
3723 nommu_addchr(&ctx->as_string, ch);
3724 }
3725
3726 {
3727#if BB_MMU
3728# define as_string NULL
3729#else
3730 char *as_string = NULL;
3731#endif
3732 pipe_list = parse_stream(&as_string, input, endch);
3733#if !BB_MMU
3734 if (as_string)
3735 o_addstr(&ctx->as_string, as_string);
3736#endif
3737 /* empty ()/{} or parse error? */
3738 if (!pipe_list || pipe_list == ERR_PTR) {
3739 /* parse_stream already emitted error msg */
3740 if (!BB_MMU)
3741 free(as_string);
3742 debug_printf_parse("parse_group return 1: "
3743 "parse_stream returned %p\n", pipe_list);
3744 return 1;
3745 }
3746 command->group = pipe_list;
3747#if !BB_MMU
3748 as_string[strlen(as_string) - 1] = '\0'; /* plink ')' or '}' */
3749 command->group_as_string = as_string;
3750 debug_printf_parse("end of group, remembering as:'%s'\n",
3751 command->group_as_string);
3752#endif
3753#undef as_string
3754 }
3755 debug_printf_parse("parse_group return 0\n");
3756 return 0;
3757 /* command remains "open", available for possible redirects */
3758}
3759
3760#if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS
3761/* Subroutines for copying $(...) and `...` things */
3762static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote);
3763/* '...' */
3764static int add_till_single_quote(o_string *dest, struct in_str *input)
3765{
3766 while (1) {
3767 int ch = i_getch(input);
3768 if (ch == EOF) {
3769 syntax_error_unterm_ch('\'');
3770 return 0;
3771 }
3772 if (ch == '\'')
3773 return 1;
3774 o_addchr(dest, ch);
3775 }
3776}
3777/* "...\"...`..`...." - do we need to handle "...$(..)..." too? */
3778static int add_till_double_quote(o_string *dest, struct in_str *input)
3779{
3780 while (1) {
3781 int ch = i_getch(input);
3782 if (ch == EOF) {
3783 syntax_error_unterm_ch('"');
3784 return 0;
3785 }
3786 if (ch == '"')
3787 return 1;
3788 if (ch == '\\') { /* \x. Copy both chars. */
3789 o_addchr(dest, ch);
3790 ch = i_getch(input);
3791 }
3792 o_addchr(dest, ch);
3793 if (ch == '`') {
3794 if (!add_till_backquote(dest, input, /*in_dquote:*/ 1))
3795 return 0;
3796 o_addchr(dest, ch);
3797 continue;
3798 }
3799 //if (ch == '$') ...
3800 }
3801}
3802/* Process `cmd` - copy contents until "`" is seen. Complicated by
3803 * \` quoting.
3804 * "Within the backquoted style of command substitution, backslash
3805 * shall retain its literal meaning, except when followed by: '$', '`', or '\'.
3806 * The search for the matching backquote shall be satisfied by the first
3807 * backquote found without a preceding backslash; during this search,
3808 * if a non-escaped backquote is encountered within a shell comment,
3809 * a here-document, an embedded command substitution of the $(command)
3810 * form, or a quoted string, undefined results occur. A single-quoted
3811 * or double-quoted string that begins, but does not end, within the
3812 * "`...`" sequence produces undefined results."
3813 * Example Output
3814 * echo `echo '\'TEST\`echo ZZ\`BEST` \TESTZZBEST
3815 */
3816static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote)
3817{
3818 while (1) {
3819 int ch = i_getch(input);
3820 if (ch == '`')
3821 return 1;
3822 if (ch == '\\') {
3823 /* \x. Copy both unless it is \`, \$, \\ and maybe \" */
3824 ch = i_getch(input);
3825 if (ch != '`'
3826 && ch != '$'
3827 && ch != '\\'
3828 && (!in_dquote || ch != '"')
3829 ) {
3830 o_addchr(dest, '\\');
3831 }
3832 }
3833 if (ch == EOF) {
3834 syntax_error_unterm_ch('`');
3835 return 0;
3836 }
3837 o_addchr(dest, ch);
3838 }
3839}
3840/* Process $(cmd) - copy contents until ")" is seen. Complicated by
3841 * quoting and nested ()s.
3842 * "With the $(command) style of command substitution, all characters
3843 * following the open parenthesis to the matching closing parenthesis
3844 * constitute the command. Any valid shell script can be used for command,
3845 * except a script consisting solely of redirections which produces
3846 * unspecified results."
3847 * Example Output
3848 * echo $(echo '(TEST)' BEST) (TEST) BEST
3849 * echo $(echo 'TEST)' BEST) TEST) BEST
3850 * echo $(echo \(\(TEST\) BEST) ((TEST) BEST
3851 *
3852 * Also adapted to eat ${var%...} and $((...)) constructs, since ... part
3853 * can contain arbitrary constructs, just like $(cmd).
3854 * In bash compat mode, it needs to also be able to stop on ':' or '/'
3855 * for ${var:N[:M]} and ${var/P[/R]} parsing.
3856 */
3857#define DOUBLE_CLOSE_CHAR_FLAG 0x80
3858static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsigned end_ch)
3859{
3860 int ch;
3861 char dbl = end_ch & DOUBLE_CLOSE_CHAR_FLAG;
3862# if ENABLE_HUSH_BASH_COMPAT
3863 char end_char2 = end_ch >> 8;
3864# endif
3865 end_ch &= (DOUBLE_CLOSE_CHAR_FLAG - 1);
3866
3867 while (1) {
3868 ch = i_getch(input);
3869 if (ch == EOF) {
3870 syntax_error_unterm_ch(end_ch);
3871 return 0;
3872 }
3873 if (ch == end_ch IF_HUSH_BASH_COMPAT( || ch == end_char2)) {
3874 if (!dbl)
3875 break;
3876 /* we look for closing )) of $((EXPR)) */
3877 if (i_peek(input) == end_ch) {
3878 i_getch(input); /* eat second ')' */
3879 break;
3880 }
3881 }
3882 o_addchr(dest, ch);
3883 if (ch == '(' || ch == '{') {
3884 ch = (ch == '(' ? ')' : '}');
3885 if (!add_till_closing_bracket(dest, input, ch))
3886 return 0;
3887 o_addchr(dest, ch);
3888 continue;
3889 }
3890 if (ch == '\'') {
3891 if (!add_till_single_quote(dest, input))
3892 return 0;
3893 o_addchr(dest, ch);
3894 continue;
3895 }
3896 if (ch == '"') {
3897 if (!add_till_double_quote(dest, input))
3898 return 0;
3899 o_addchr(dest, ch);
3900 continue;
3901 }
3902 if (ch == '`') {
3903 if (!add_till_backquote(dest, input, /*in_dquote:*/ 0))
3904 return 0;
3905 o_addchr(dest, ch);
3906 continue;
3907 }
3908 if (ch == '\\') {
3909 /* \x. Copy verbatim. Important for \(, \) */
3910 ch = i_getch(input);
3911 if (ch == EOF) {
3912 syntax_error_unterm_ch(')');
3913 return 0;
3914 }
3915 o_addchr(dest, ch);
3916 continue;
3917 }
3918 }
3919 return ch;
3920}
3921#endif /* ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS */
3922
3923/* Return code: 0 for OK, 1 for syntax error */
3924#if BB_MMU
3925#define parse_dollar(as_string, dest, input, quote_mask) \
3926 parse_dollar(dest, input, quote_mask)
3927#define as_string NULL
3928#endif
3929static int parse_dollar(o_string *as_string,
3930 o_string *dest,
3931 struct in_str *input, unsigned char quote_mask)
3932{
3933 int ch = i_peek(input); /* first character after the $ */
3934
3935 debug_printf_parse("parse_dollar entered: ch='%c'\n", ch);
3936 if (isalpha(ch)) {
3937 ch = i_getch(input);
3938 nommu_addchr(as_string, ch);
3939 make_var:
3940 o_addchr(dest, SPECIAL_VAR_SYMBOL);
3941 while (1) {
3942 debug_printf_parse(": '%c'\n", ch);
3943 o_addchr(dest, ch | quote_mask);
3944 quote_mask = 0;
3945 ch = i_peek(input);
3946 if (!isalnum(ch) && ch != '_')
3947 break;
3948 ch = i_getch(input);
3949 nommu_addchr(as_string, ch);
3950 }
3951 o_addchr(dest, SPECIAL_VAR_SYMBOL);
3952 } else if (isdigit(ch)) {
3953 make_one_char_var:
3954 ch = i_getch(input);
3955 nommu_addchr(as_string, ch);
3956 o_addchr(dest, SPECIAL_VAR_SYMBOL);
3957 debug_printf_parse(": '%c'\n", ch);
3958 o_addchr(dest, ch | quote_mask);
3959 o_addchr(dest, SPECIAL_VAR_SYMBOL);
3960 } else switch (ch) {
3961 case '$': /* pid */
3962 case '!': /* last bg pid */
3963 case '?': /* last exit code */
3964 case '#': /* number of args */
3965 case '*': /* args */
3966 case '@': /* args */
3967 goto make_one_char_var;
3968 case '{': {
3969 o_addchr(dest, SPECIAL_VAR_SYMBOL);
3970
3971 ch = i_getch(input); /* eat '{' */
3972 nommu_addchr(as_string, ch);
3973
3974 ch = i_getch(input); /* first char after '{' */
3975 /* It should be ${?}, or ${#var},
3976 * or even ${?+subst} - operator acting on a special variable,
3977 * or the beginning of variable name.
3978 */
3979 if (ch == EOF
3980 || (!strchr(_SPECIAL_VARS_STR, ch) && !isalnum(ch)) /* not one of those */
3981 ) {
3982 bad_dollar_syntax:
3983 syntax_error_unterm_str("${name}");
3984 debug_printf_parse("parse_dollar return 0: unterminated ${name}\n");
3985 return 0;
3986 }
3987 nommu_addchr(as_string, ch);
3988 ch |= quote_mask;
3989
3990 /* It's possible to just call add_till_closing_bracket() at this point.
3991 * However, this regresses some of our testsuite cases
3992 * which check invalid constructs like ${%}.
3993 * Oh well... let's check that the var name part is fine... */
3994
3995 while (1) {
3996 unsigned pos;
3997
3998 o_addchr(dest, ch);
3999 debug_printf_parse(": '%c'\n", ch);
4000
4001 ch = i_getch(input);
4002 nommu_addchr(as_string, ch);
4003 if (ch == '}')
4004 break;
4005
4006 if (!isalnum(ch) && ch != '_') {
4007 unsigned end_ch;
4008 unsigned char last_ch;
4009 /* handle parameter expansions
4010 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02
4011 */
4012 if (!strchr(VAR_SUBST_OPS, ch)) /* ${var<bad_char>... */
4013 goto bad_dollar_syntax;
4014
4015 /* Eat everything until closing '}' (or ':') */
4016 end_ch = '}';
4017 if (ENABLE_HUSH_BASH_COMPAT
4018 && ch == ':'
4019 && !strchr(MINUS_PLUS_EQUAL_QUESTION, i_peek(input))
4020 ) {
4021 /* It's ${var:N[:M]} thing */
4022 end_ch = '}' * 0x100 + ':';
4023 }
4024 if (ENABLE_HUSH_BASH_COMPAT
4025 && ch == '/'
4026 ) {
4027 /* It's ${var/[/]pattern[/repl]} thing */
4028 if (i_peek(input) == '/') { /* ${var//pattern[/repl]}? */
4029 i_getch(input);
4030 nommu_addchr(as_string, '/');
4031 ch = '\\';
4032 }
4033 end_ch = '}' * 0x100 + '/';
4034 }
4035 o_addchr(dest, ch);
4036 again:
4037 if (!BB_MMU)
4038 pos = dest->length;
4039#if ENABLE_HUSH_DOLLAR_OPS
4040 last_ch = add_till_closing_bracket(dest, input, end_ch);
4041 if (last_ch == 0) /* error? */
4042 return 0;
4043#else
4044#error Simple code to only allow ${var} is not implemented
4045#endif
4046 if (as_string) {
4047 o_addstr(as_string, dest->data + pos);
4048 o_addchr(as_string, last_ch);
4049 }
4050
4051 if (ENABLE_HUSH_BASH_COMPAT && (end_ch & 0xff00)) {
4052 /* close the first block: */
4053 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4054 /* while parsing N from ${var:N[:M]}
4055 * or pattern from ${var/[/]pattern[/repl]} */
4056 if ((end_ch & 0xff) == last_ch) {
4057 /* got ':' or '/'- parse the rest */
4058 end_ch = '}';
4059 goto again;
4060 }
4061 /* got '}' */
4062 if (end_ch == '}' * 0x100 + ':') {
4063 /* it's ${var:N} - emulate :999999999 */
4064 o_addstr(dest, "999999999");
4065 } /* else: it's ${var/[/]pattern} */
4066 }
4067 break;
4068 }
4069 }
4070 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4071 break;
4072 }
4073#if ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_TICK
4074 case '(': {
4075 unsigned pos;
4076
4077 ch = i_getch(input);
4078 nommu_addchr(as_string, ch);
4079# if ENABLE_SH_MATH_SUPPORT
4080 if (i_peek(input) == '(') {
4081 ch = i_getch(input);
4082 nommu_addchr(as_string, ch);
4083 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4084 o_addchr(dest, /*quote_mask |*/ '+');
4085 if (!BB_MMU)
4086 pos = dest->length;
4087 if (!add_till_closing_bracket(dest, input, ')' | DOUBLE_CLOSE_CHAR_FLAG))
4088 return 0; /* error */
4089 if (as_string) {
4090 o_addstr(as_string, dest->data + pos);
4091 o_addchr(as_string, ')');
4092 o_addchr(as_string, ')');
4093 }
4094 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4095 break;
4096 }
4097# endif
4098# if ENABLE_HUSH_TICK
4099 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4100 o_addchr(dest, quote_mask | '`');
4101 if (!BB_MMU)
4102 pos = dest->length;
4103 if (!add_till_closing_bracket(dest, input, ')'))
4104 return 0; /* error */
4105 if (as_string) {
4106 o_addstr(as_string, dest->data + pos);
4107 o_addchr(as_string, ')');
4108 }
4109 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4110# endif
4111 break;
4112 }
4113#endif
4114 case '_':
4115 ch = i_getch(input);
4116 nommu_addchr(as_string, ch);
4117 ch = i_peek(input);
4118 if (isalnum(ch)) { /* it's $_name or $_123 */
4119 ch = '_';
4120 goto make_var;
4121 }
4122 /* else: it's $_ */
4123 /* TODO: $_ and $-: */
4124 /* $_ Shell or shell script name; or last argument of last command
4125 * (if last command wasn't a pipe; if it was, bash sets $_ to "");
4126 * but in command's env, set to full pathname used to invoke it */
4127 /* $- Option flags set by set builtin or shell options (-i etc) */
4128 default:
4129 o_addQchr(dest, '$');
4130 }
4131 debug_printf_parse("parse_dollar return 1 (ok)\n");
4132 return 1;
4133#undef as_string
4134}
4135
4136#if BB_MMU
4137# if ENABLE_HUSH_BASH_COMPAT
4138#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \
4139 encode_string(dest, input, dquote_end, process_bkslash)
4140# else
4141/* only ${var/pattern/repl} (its pattern part) needs additional mode */
4142#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \
4143 encode_string(dest, input, dquote_end)
4144# endif
4145#define as_string NULL
4146
4147#else /* !MMU */
4148
4149# if ENABLE_HUSH_BASH_COMPAT
4150/* all parameters are needed, no macro tricks */
4151# else
4152#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \
4153 encode_string(as_string, dest, input, dquote_end)
4154# endif
4155#endif
4156static int encode_string(o_string *as_string,
4157 o_string *dest,
4158 struct in_str *input,
4159 int dquote_end,
4160 int process_bkslash)
4161{
4162#if !ENABLE_HUSH_BASH_COMPAT
4163 const int process_bkslash = 1;
4164#endif
4165 int ch;
4166 int next;
4167
4168 again:
4169 ch = i_getch(input);
4170 if (ch != EOF)
4171 nommu_addchr(as_string, ch);
4172 if (ch == dquote_end) { /* may be only '"' or EOF */
4173 debug_printf_parse("encode_string return 1 (ok)\n");
4174 return 1;
4175 }
4176 /* note: can't move it above ch == dquote_end check! */
4177 if (ch == EOF) {
4178 syntax_error_unterm_ch('"');
4179 return 0; /* error */
4180 }
4181 next = '\0';
4182 if (ch != '\n') {
4183 next = i_peek(input);
4184 }
4185 debug_printf_parse("\" ch=%c (%d) escape=%d\n",
4186 ch, ch, !!(dest->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
4187 if (process_bkslash && ch == '\\') {
4188 if (next == EOF) {
4189 syntax_error("\\<eof>");
4190 xfunc_die();
4191 }
4192 /* bash:
4193 * "The backslash retains its special meaning [in "..."]
4194 * only when followed by one of the following characters:
4195 * $, `, ", \, or <newline>. A double quote may be quoted
4196 * within double quotes by preceding it with a backslash."
4197 * NB: in (unquoted) heredoc, above does not apply to ",
4198 * therefore we check for it by "next == dquote_end" cond.
4199 */
4200 if (next == dquote_end || strchr("$`\\\n", next)) {
4201 ch = i_getch(input); /* eat next */
4202 if (ch == '\n')
4203 goto again; /* skip \<newline> */
4204 } /* else: ch remains == '\\', and we double it below: */
4205 o_addqchr(dest, ch); /* \c if c is a glob char, else just c */
4206 nommu_addchr(as_string, ch);
4207 goto again;
4208 }
4209 if (ch == '$') {
4210 if (!parse_dollar(as_string, dest, input, /*quote_mask:*/ 0x80)) {
4211 debug_printf_parse("encode_string return 0: "
4212 "parse_dollar returned 0 (error)\n");
4213 return 0;
4214 }
4215 goto again;
4216 }
4217#if ENABLE_HUSH_TICK
4218 if (ch == '`') {
4219 //unsigned pos = dest->length;
4220 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4221 o_addchr(dest, 0x80 | '`');
4222 if (!add_till_backquote(dest, input, /*in_dquote:*/ dquote_end == '"'))
4223 return 0; /* error */
4224 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4225 //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
4226 goto again;
4227 }
4228#endif
4229 o_addQchr(dest, ch);
4230 goto again;
4231#undef as_string
4232}
4233
4234/*
4235 * Scan input until EOF or end_trigger char.
4236 * Return a list of pipes to execute, or NULL on EOF
4237 * or if end_trigger character is met.
4238 * On syntax error, exit if shell is not interactive,
4239 * reset parsing machinery and start parsing anew,
4240 * or return ERR_PTR.
4241 */
4242static struct pipe *parse_stream(char **pstring,
4243 struct in_str *input,
4244 int end_trigger)
4245{
4246 struct parse_context ctx;
4247 o_string dest = NULL_O_STRING;
4248 int heredoc_cnt;
4249
4250 /* Single-quote triggers a bypass of the main loop until its mate is
4251 * found. When recursing, quote state is passed in via dest->o_expflags.
4252 */
4253 debug_printf_parse("parse_stream entered, end_trigger='%c'\n",
4254 end_trigger ? end_trigger : 'X');
4255 debug_enter();
4256
4257 /* If very first arg is "" or '', dest.data may end up NULL.
4258 * Preventing this: */
4259 o_addchr(&dest, '\0');
4260 dest.length = 0;
4261
4262 /* We used to separate words on $IFS here. This was wrong.
4263 * $IFS is used only for word splitting when $var is expanded,
4264 * here we should use blank chars as separators, not $IFS
4265 */
4266
4267 if (MAYBE_ASSIGNMENT != 0)
4268 dest.o_assignment = MAYBE_ASSIGNMENT;
4269 initialize_context(&ctx);
4270 heredoc_cnt = 0;
4271 while (1) {
4272 const char *is_blank;
4273 const char *is_special;
4274 int ch;
4275 int next;
4276 int redir_fd;
4277 redir_type redir_style;
4278
4279 ch = i_getch(input);
4280 debug_printf_parse(": ch=%c (%d) escape=%d\n",
4281 ch, ch, !!(dest.o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
4282 if (ch == EOF) {
4283 struct pipe *pi;
4284
4285 if (heredoc_cnt) {
4286 syntax_error_unterm_str("here document");
4287 goto parse_error;
4288 }
4289 /* end_trigger == '}' case errors out earlier,
4290 * checking only ')' */
4291 if (end_trigger == ')') {
4292 syntax_error_unterm_ch('(');
4293 goto parse_error;
4294 }
4295
4296 if (done_word(&dest, &ctx)) {
4297 goto parse_error;
4298 }
4299 o_free(&dest);
4300 done_pipe(&ctx, PIPE_SEQ);
4301 pi = ctx.list_head;
4302 /* If we got nothing... */
4303 /* (this makes bare "&" cmd a no-op.
4304 * bash says: "syntax error near unexpected token '&'") */
4305 if (pi->num_cmds == 0
4306 IF_HAS_KEYWORDS(&& pi->res_word == RES_NONE)
4307 ) {
4308 free_pipe_list(pi);
4309 pi = NULL;
4310 }
4311#if !BB_MMU
4312 debug_printf_parse("as_string1 '%s'\n", ctx.as_string.data);
4313 if (pstring)
4314 *pstring = ctx.as_string.data;
4315 else
4316 o_free_unsafe(&ctx.as_string);
4317#endif
4318 debug_leave();
4319 debug_printf_parse("parse_stream return %p\n", pi);
4320 return pi;
4321 }
4322 nommu_addchr(&ctx.as_string, ch);
4323
4324 next = '\0';
4325 if (ch != '\n')
4326 next = i_peek(input);
4327
4328 is_special = "{}<>;&|()#'" /* special outside of "str" */
4329 "\\$\"" IF_HUSH_TICK("`"); /* always special */
4330 /* Are { and } special here? */
4331 if (ctx.command->argv /* word [word]{... - non-special */
4332 || dest.length /* word{... - non-special */
4333 || dest.has_quoted_part /* ""{... - non-special */
4334 || (next != ';' /* }; - special */
4335 && next != ')' /* }) - special */
4336 && next != '&' /* }& and }&& ... - special */
4337 && next != '|' /* }|| ... - special */
4338 && !strchr(defifs, next) /* {word - non-special */
4339 )
4340 ) {
4341 /* They are not special, skip "{}" */
4342 is_special += 2;
4343 }
4344 is_special = strchr(is_special, ch);
4345 is_blank = strchr(defifs, ch);
4346
4347 if (!is_special && !is_blank) { /* ordinary char */
4348 ordinary_char:
4349 o_addQchr(&dest, ch);
4350 if ((dest.o_assignment == MAYBE_ASSIGNMENT
4351 || dest.o_assignment == WORD_IS_KEYWORD)
4352 && ch == '='
4353 && is_well_formed_var_name(dest.data, '=')
4354 ) {
4355 dest.o_assignment = DEFINITELY_ASSIGNMENT;
4356 debug_printf_parse("dest.o_assignment='%s'\n", assignment_flag[dest.o_assignment]);
4357 }
4358 continue;
4359 }
4360
4361 if (is_blank) {
4362 if (done_word(&dest, &ctx)) {
4363 goto parse_error;
4364 }
4365 if (ch == '\n') {
4366 /* Is this a case when newline is simply ignored?
4367 * Some examples:
4368 * "cmd | <newline> cmd ..."
4369 * "case ... in <newline> word) ..."
4370 */
4371 if (IS_NULL_CMD(ctx.command)
4372 && dest.length == 0 && !dest.has_quoted_part
4373 ) {
4374 /* This newline can be ignored. But...
4375 * Without check #1, interactive shell
4376 * ignores even bare <newline>,
4377 * and shows the continuation prompt:
4378 * ps1_prompt$ <enter>
4379 * ps2> _ <=== wrong, should be ps1
4380 * Without check #2, "cmd & <newline>"
4381 * is similarly mistreated.
4382 * (BTW, this makes "cmd & cmd"
4383 * and "cmd && cmd" non-orthogonal.
4384 * Really, ask yourself, why
4385 * "cmd && <newline>" doesn't start
4386 * cmd but waits for more input?
4387 * No reason...)
4388 */
4389 struct pipe *pi = ctx.list_head;
4390 if (pi->num_cmds != 0 /* check #1 */
4391 && pi->followup != PIPE_BG /* check #2 */
4392 ) {
4393 continue;
4394 }
4395 }
4396 /* Treat newline as a command separator. */
4397 done_pipe(&ctx, PIPE_SEQ);
4398 debug_printf_parse("heredoc_cnt:%d\n", heredoc_cnt);
4399 if (heredoc_cnt) {
4400 if (fetch_heredocs(heredoc_cnt, &ctx, input)) {
4401 goto parse_error;
4402 }
4403 heredoc_cnt = 0;
4404 }
4405 dest.o_assignment = MAYBE_ASSIGNMENT;
4406 debug_printf_parse("dest.o_assignment='%s'\n", assignment_flag[dest.o_assignment]);
4407 ch = ';';
4408 /* note: if (is_blank) continue;
4409 * will still trigger for us */
4410 }
4411 }
4412
4413 /* "cmd}" or "cmd }..." without semicolon or &:
4414 * } is an ordinary char in this case, even inside { cmd; }
4415 * Pathological example: { ""}; } should exec "}" cmd
4416 */
4417 if (ch == '}') {
4418 if (!IS_NULL_CMD(ctx.command) /* cmd } */
4419 || dest.length != 0 /* word} */
4420 || dest.has_quoted_part /* ""} */
4421 ) {
4422 goto ordinary_char;
4423 }
4424 if (!IS_NULL_PIPE(ctx.pipe)) /* cmd | } */
4425 goto skip_end_trigger;
4426 /* else: } does terminate a group */
4427 }
4428
4429 if (end_trigger && end_trigger == ch
4430 && (ch != ';' || heredoc_cnt == 0)
4431#if ENABLE_HUSH_CASE
4432 && (ch != ')'
4433 || ctx.ctx_res_w != RES_MATCH
4434 || (!dest.has_quoted_part && strcmp(dest.data, "esac") == 0)
4435 )
4436#endif
4437 ) {
4438 if (heredoc_cnt) {
4439 /* This is technically valid:
4440 * { cat <<HERE; }; echo Ok
4441 * heredoc
4442 * heredoc
4443 * HERE
4444 * but we don't support this.
4445 * We require heredoc to be in enclosing {}/(),
4446 * if any.
4447 */
4448 syntax_error_unterm_str("here document");
4449 goto parse_error;
4450 }
4451 if (done_word(&dest, &ctx)) {
4452 goto parse_error;
4453 }
4454 done_pipe(&ctx, PIPE_SEQ);
4455 dest.o_assignment = MAYBE_ASSIGNMENT;
4456 debug_printf_parse("dest.o_assignment='%s'\n", assignment_flag[dest.o_assignment]);
4457 /* Do we sit outside of any if's, loops or case's? */
4458 if (!HAS_KEYWORDS
4459 IF_HAS_KEYWORDS(|| (ctx.ctx_res_w == RES_NONE && ctx.old_flag == 0))
4460 ) {
4461 o_free(&dest);
4462#if !BB_MMU
4463 debug_printf_parse("as_string2 '%s'\n", ctx.as_string.data);
4464 if (pstring)
4465 *pstring = ctx.as_string.data;
4466 else
4467 o_free_unsafe(&ctx.as_string);
4468#endif
4469 debug_leave();
4470 debug_printf_parse("parse_stream return %p: "
4471 "end_trigger char found\n",
4472 ctx.list_head);
4473 return ctx.list_head;
4474 }
4475 }
4476 skip_end_trigger:
4477 if (is_blank)
4478 continue;
4479
4480 /* Catch <, > before deciding whether this word is
4481 * an assignment. a=1 2>z b=2: b=2 is still assignment */
4482 switch (ch) {
4483 case '>':
4484 redir_fd = redirect_opt_num(&dest);
4485 if (done_word(&dest, &ctx)) {
4486 goto parse_error;
4487 }
4488 redir_style = REDIRECT_OVERWRITE;
4489 if (next == '>') {
4490 redir_style = REDIRECT_APPEND;
4491 ch = i_getch(input);
4492 nommu_addchr(&ctx.as_string, ch);
4493 }
4494#if 0
4495 else if (next == '(') {
4496 syntax_error(">(process) not supported");
4497 goto parse_error;
4498 }
4499#endif
4500 if (parse_redirect(&ctx, redir_fd, redir_style, input))
4501 goto parse_error;
4502 continue; /* back to top of while (1) */
4503 case '<':
4504 redir_fd = redirect_opt_num(&dest);
4505 if (done_word(&dest, &ctx)) {
4506 goto parse_error;
4507 }
4508 redir_style = REDIRECT_INPUT;
4509 if (next == '<') {
4510 redir_style = REDIRECT_HEREDOC;
4511 heredoc_cnt++;
4512 debug_printf_parse("++heredoc_cnt=%d\n", heredoc_cnt);
4513 ch = i_getch(input);
4514 nommu_addchr(&ctx.as_string, ch);
4515 } else if (next == '>') {
4516 redir_style = REDIRECT_IO;
4517 ch = i_getch(input);
4518 nommu_addchr(&ctx.as_string, ch);
4519 }
4520#if 0
4521 else if (next == '(') {
4522 syntax_error("<(process) not supported");
4523 goto parse_error;
4524 }
4525#endif
4526 if (parse_redirect(&ctx, redir_fd, redir_style, input))
4527 goto parse_error;
4528 continue; /* back to top of while (1) */
4529 case '#':
4530 if (dest.length == 0 && !dest.has_quoted_part) {
4531 /* skip "#comment" */
4532 while (1) {
4533 ch = i_peek(input);
4534 if (ch == EOF || ch == '\n')
4535 break;
4536 i_getch(input);
4537 /* note: we do not add it to &ctx.as_string */
4538 }
4539 nommu_addchr(&ctx.as_string, '\n');
4540 continue; /* back to top of while (1) */
4541 }
4542 break;
4543 case '\\':
4544 if (next == '\n') {
4545 /* It's "\<newline>" */
4546#if !BB_MMU
4547 /* Remove trailing '\' from ctx.as_string */
4548 ctx.as_string.data[--ctx.as_string.length] = '\0';
4549#endif
4550 ch = i_getch(input); /* eat it */
4551 continue; /* back to top of while (1) */
4552 }
4553 break;
4554 }
4555
4556 if (dest.o_assignment == MAYBE_ASSIGNMENT
4557 /* check that we are not in word in "a=1 2>word b=1": */
4558 && !ctx.pending_redirect
4559 ) {
4560 /* ch is a special char and thus this word
4561 * cannot be an assignment */
4562 dest.o_assignment = NOT_ASSIGNMENT;
4563 debug_printf_parse("dest.o_assignment='%s'\n", assignment_flag[dest.o_assignment]);
4564 }
4565
4566 /* Note: nommu_addchr(&ctx.as_string, ch) is already done */
4567
4568 switch (ch) {
4569 case '#': /* non-comment #: "echo a#b" etc */
4570 o_addQchr(&dest, ch);
4571 break;
4572 case '\\':
4573 if (next == EOF) {
4574 syntax_error("\\<eof>");
4575 xfunc_die();
4576 }
4577 ch = i_getch(input);
4578 /* note: ch != '\n' (that case does not reach this place) */
4579 o_addchr(&dest, '\\');
4580 /*nommu_addchr(&ctx.as_string, '\\'); - already done */
4581 o_addchr(&dest, ch);
4582 nommu_addchr(&ctx.as_string, ch);
4583 /* Example: echo Hello \2>file
4584 * we need to know that word 2 is quoted */
4585 dest.has_quoted_part = 1;
4586 break;
4587 case '$':
4588 if (!parse_dollar(&ctx.as_string, &dest, input, /*quote_mask:*/ 0)) {
4589 debug_printf_parse("parse_stream parse error: "
4590 "parse_dollar returned 0 (error)\n");
4591 goto parse_error;
4592 }
4593 break;
4594 case '\'':
4595 dest.has_quoted_part = 1;
4596 if (next == '\'' && !ctx.pending_redirect) {
4597 insert_empty_quoted_str_marker:
4598 nommu_addchr(&ctx.as_string, next);
4599 i_getch(input); /* eat second ' */
4600 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
4601 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
4602 } else {
4603 while (1) {
4604 ch = i_getch(input);
4605 if (ch == EOF) {
4606 syntax_error_unterm_ch('\'');
4607 goto parse_error;
4608 }
4609 nommu_addchr(&ctx.as_string, ch);
4610 if (ch == '\'')
4611 break;
4612 o_addqchr(&dest, ch);
4613 }
4614 }
4615 break;
4616 case '"':
4617 dest.has_quoted_part = 1;
4618 if (next == '"' && !ctx.pending_redirect)
4619 goto insert_empty_quoted_str_marker;
4620 if (dest.o_assignment == NOT_ASSIGNMENT)
4621 dest.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS;
4622 if (!encode_string(&ctx.as_string, &dest, input, '"', /*process_bkslash:*/ 1))
4623 goto parse_error;
4624 dest.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS;
4625 break;
4626#if ENABLE_HUSH_TICK
4627 case '`': {
4628 USE_FOR_NOMMU(unsigned pos;)
4629
4630 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
4631 o_addchr(&dest, '`');
4632 USE_FOR_NOMMU(pos = dest.length;)
4633 if (!add_till_backquote(&dest, input, /*in_dquote:*/ 0))
4634 goto parse_error;
4635# if !BB_MMU
4636 o_addstr(&ctx.as_string, dest.data + pos);
4637 o_addchr(&ctx.as_string, '`');
4638# endif
4639 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
4640 //debug_printf_subst("SUBST RES3 '%s'\n", dest.data + pos);
4641 break;
4642 }
4643#endif
4644 case ';':
4645#if ENABLE_HUSH_CASE
4646 case_semi:
4647#endif
4648 if (done_word(&dest, &ctx)) {
4649 goto parse_error;
4650 }
4651 done_pipe(&ctx, PIPE_SEQ);
4652#if ENABLE_HUSH_CASE
4653 /* Eat multiple semicolons, detect
4654 * whether it means something special */
4655 while (1) {
4656 ch = i_peek(input);
4657 if (ch != ';')
4658 break;
4659 ch = i_getch(input);
4660 nommu_addchr(&ctx.as_string, ch);
4661 if (ctx.ctx_res_w == RES_CASE_BODY) {
4662 ctx.ctx_dsemicolon = 1;
4663 ctx.ctx_res_w = RES_MATCH;
4664 break;
4665 }
4666 }
4667#endif
4668 new_cmd:
4669 /* We just finished a cmd. New one may start
4670 * with an assignment */
4671 dest.o_assignment = MAYBE_ASSIGNMENT;
4672 debug_printf_parse("dest.o_assignment='%s'\n", assignment_flag[dest.o_assignment]);
4673 break;
4674 case '&':
4675 if (done_word(&dest, &ctx)) {
4676 goto parse_error;
4677 }
4678 if (next == '&') {
4679 ch = i_getch(input);
4680 nommu_addchr(&ctx.as_string, ch);
4681 done_pipe(&ctx, PIPE_AND);
4682 } else {
4683 done_pipe(&ctx, PIPE_BG);
4684 }
4685 goto new_cmd;
4686 case '|':
4687 if (done_word(&dest, &ctx)) {
4688 goto parse_error;
4689 }
4690#if ENABLE_HUSH_CASE
4691 if (ctx.ctx_res_w == RES_MATCH)
4692 break; /* we are in case's "word | word)" */
4693#endif
4694 if (next == '|') { /* || */
4695 ch = i_getch(input);
4696 nommu_addchr(&ctx.as_string, ch);
4697 done_pipe(&ctx, PIPE_OR);
4698 } else {
4699 /* we could pick up a file descriptor choice here
4700 * with redirect_opt_num(), but bash doesn't do it.
4701 * "echo foo 2| cat" yields "foo 2". */
4702 done_command(&ctx);
4703 }
4704 goto new_cmd;
4705 case '(':
4706#if ENABLE_HUSH_CASE
4707 /* "case... in [(]word)..." - skip '(' */
4708 if (ctx.ctx_res_w == RES_MATCH
4709 && ctx.command->argv == NULL /* not (word|(... */
4710 && dest.length == 0 /* not word(... */
4711 && dest.has_quoted_part == 0 /* not ""(... */
4712 ) {
4713 continue;
4714 }
4715#endif
4716 case '{':
4717 if (parse_group(&dest, &ctx, input, ch) != 0) {
4718 goto parse_error;
4719 }
4720 goto new_cmd;
4721 case ')':
4722#if ENABLE_HUSH_CASE
4723 if (ctx.ctx_res_w == RES_MATCH)
4724 goto case_semi;
4725#endif
4726 case '}':
4727 /* proper use of this character is caught by end_trigger:
4728 * if we see {, we call parse_group(..., end_trigger='}')
4729 * and it will match } earlier (not here). */
4730 syntax_error_unexpected_ch(ch);
4731 goto parse_error;
4732 default:
4733 if (HUSH_DEBUG)
4734 bb_error_msg_and_die("BUG: unexpected %c\n", ch);
4735 }
4736 } /* while (1) */
4737
4738 parse_error:
4739 {
4740 struct parse_context *pctx;
4741 IF_HAS_KEYWORDS(struct parse_context *p2;)
4742
4743 /* Clean up allocated tree.
4744 * Sample for finding leaks on syntax error recovery path.
4745 * Run it from interactive shell, watch pmap `pidof hush`.
4746 * while if false; then false; fi; do break; fi
4747 * Samples to catch leaks at execution:
4748 * while if (true | {true;}); then echo ok; fi; do break; done
4749 * while if (true | {true;}); then echo ok; fi; do (if echo ok; break; then :; fi) | cat; break; done
4750 */
4751 pctx = &ctx;
4752 do {
4753 /* Update pipe/command counts,
4754 * otherwise freeing may miss some */
4755 done_pipe(pctx, PIPE_SEQ);
4756 debug_printf_clean("freeing list %p from ctx %p\n",
4757 pctx->list_head, pctx);
4758 debug_print_tree(pctx->list_head, 0);
4759 free_pipe_list(pctx->list_head);
4760 debug_printf_clean("freed list %p\n", pctx->list_head);
4761#if !BB_MMU
4762 o_free_unsafe(&pctx->as_string);
4763#endif
4764 IF_HAS_KEYWORDS(p2 = pctx->stack;)
4765 if (pctx != &ctx) {
4766 free(pctx);
4767 }
4768 IF_HAS_KEYWORDS(pctx = p2;)
4769 } while (HAS_KEYWORDS && pctx);
4770
4771 o_free(&dest);
4772 G.last_exitcode = 1;
4773#if !BB_MMU
4774 if (pstring)
4775 *pstring = NULL;
4776#endif
4777 debug_leave();
4778 return ERR_PTR;
4779 }
4780}
4781
4782
4783/*** Execution routines ***/
4784
4785/* Expansion can recurse, need forward decls: */
4786#if !ENABLE_HUSH_BASH_COMPAT
4787/* only ${var/pattern/repl} (its pattern part) needs additional mode */
4788#define expand_string_to_string(str, do_unbackslash) \
4789 expand_string_to_string(str)
4790#endif
4791static char *expand_string_to_string(const char *str, int do_unbackslash);
4792#if ENABLE_HUSH_TICK
4793static int process_command_subs(o_string *dest, const char *s);
4794#endif
4795
4796/* expand_strvec_to_strvec() takes a list of strings, expands
4797 * all variable references within and returns a pointer to
4798 * a list of expanded strings, possibly with larger number
4799 * of strings. (Think VAR="a b"; echo $VAR).
4800 * This new list is allocated as a single malloc block.
4801 * NULL-terminated list of char* pointers is at the beginning of it,
4802 * followed by strings themselves.
4803 * Caller can deallocate entire list by single free(list). */
4804
4805/* A horde of its helpers come first: */
4806
4807static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len)
4808{
4809 while (--len >= 0) {
4810 char c = *str++;
4811
4812#if ENABLE_HUSH_BRACE_EXPANSION
4813 if (c == '{' || c == '}') {
4814 /* { -> \{, } -> \} */
4815 o_addchr(o, '\\');
4816 /* And now we want to add { or } and continue:
4817 * o_addchr(o, c);
4818 * continue;
4819 * luckily, just falling throught achieves this.
4820 */
4821 }
4822#endif
4823 o_addchr(o, c);
4824 if (c == '\\') {
4825 /* \z -> \\\z; \<eol> -> \\<eol> */
4826 o_addchr(o, '\\');
4827 if (len) {
4828 len--;
4829 o_addchr(o, '\\');
4830 o_addchr(o, *str++);
4831 }
4832 }
4833 }
4834}
4835
4836/* Store given string, finalizing the word and starting new one whenever
4837 * we encounter IFS char(s). This is used for expanding variable values.
4838 * End-of-string does NOT finalize word: think about 'echo -$VAR-'.
4839 * Return in *ended_with_ifs:
4840 * 1 - ended with IFS char, else 0 (this includes case of empty str).
4841 */
4842static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const char *str)
4843{
4844 int last_is_ifs = 0;
4845
4846 while (1) {
4847 int word_len;
4848
4849 if (!*str) /* EOL - do not finalize word */
4850 break;
4851 word_len = strcspn(str, G.ifs);
4852 if (word_len) {
4853 /* We have WORD_LEN leading non-IFS chars */
4854 if (!(output->o_expflags & EXP_FLAG_GLOB)) {
4855 o_addblock(output, str, word_len);
4856 } else {
4857 /* Protect backslashes against globbing up :)
4858 * Example: "v='\*'; echo b$v" prints "b\*"
4859 * (and does not try to glob on "*")
4860 */
4861 o_addblock_duplicate_backslash(output, str, word_len);
4862 /*/ Why can't we do it easier? */
4863 /*o_addblock(output, str, word_len); - WRONG: "v='\*'; echo Z$v" prints "Z*" instead of "Z\*" */
4864 /*o_addqblock(output, str, word_len); - WRONG: "v='*'; echo Z$v" prints "Z*" instead of Z* files */
4865 }
4866 last_is_ifs = 0;
4867 str += word_len;
4868 if (!*str) /* EOL - do not finalize word */
4869 break;
4870 }
4871
4872 /* We know str here points to at least one IFS char */
4873 last_is_ifs = 1;
4874 str += strspn(str, G.ifs); /* skip IFS chars */
4875 if (!*str) /* EOL - do not finalize word */
4876 break;
4877
4878 /* Start new word... but not always! */
4879 /* Case "v=' a'; echo ''$v": we do need to finalize empty word: */
4880 if (output->has_quoted_part
4881 /* Case "v=' a'; echo $v":
4882 * here nothing precedes the space in $v expansion,
4883 * therefore we should not finish the word
4884 * (IOW: if there *is* word to finalize, only then do it):
4885 */
4886 || (n > 0 && output->data[output->length - 1])
4887 ) {
4888 o_addchr(output, '\0');
4889 debug_print_list("expand_on_ifs", output, n);
4890 n = o_save_ptr(output, n);
4891 }
4892 }
4893
4894 if (ended_with_ifs)
4895 *ended_with_ifs = last_is_ifs;
4896 debug_print_list("expand_on_ifs[1]", output, n);
4897 return n;
4898}
4899
4900/* Helper to expand $((...)) and heredoc body. These act as if
4901 * they are in double quotes, with the exception that they are not :).
4902 * Just the rules are similar: "expand only $var and `cmd`"
4903 *
4904 * Returns malloced string.
4905 * As an optimization, we return NULL if expansion is not needed.
4906 */
4907#if !ENABLE_HUSH_BASH_COMPAT
4908/* only ${var/pattern/repl} (its pattern part) needs additional mode */
4909#define encode_then_expand_string(str, process_bkslash, do_unbackslash) \
4910 encode_then_expand_string(str)
4911#endif
4912static char *encode_then_expand_string(const char *str, int process_bkslash, int do_unbackslash)
4913{
4914 char *exp_str;
4915 struct in_str input;
4916 o_string dest = NULL_O_STRING;
4917
4918 if (!strchr(str, '$')
4919 && !strchr(str, '\\')
4920#if ENABLE_HUSH_TICK
4921 && !strchr(str, '`')
4922#endif
4923 ) {
4924 return NULL;
4925 }
4926
4927 /* We need to expand. Example:
4928 * echo $(($a + `echo 1`)) $((1 + $((2)) ))
4929 */
4930 setup_string_in_str(&input, str);
4931 encode_string(NULL, &dest, &input, EOF, process_bkslash);
4932//TODO: error check (encode_string returns 0 on error)?
4933 //bb_error_msg("'%s' -> '%s'", str, dest.data);
4934 exp_str = expand_string_to_string(dest.data, /*unbackslash:*/ do_unbackslash);
4935 //bb_error_msg("'%s' -> '%s'", dest.data, exp_str);
4936 o_free_unsafe(&dest);
4937 return exp_str;
4938}
4939
4940#if ENABLE_SH_MATH_SUPPORT
4941static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p)
4942{
4943 arith_state_t math_state;
4944 arith_t res;
4945 char *exp_str;
4946
4947 math_state.lookupvar = get_local_var_value;
4948 math_state.setvar = set_local_var_from_halves;
4949 //math_state.endofname = endofname;
4950 exp_str = encode_then_expand_string(arg, /*process_bkslash:*/ 1, /*unbackslash:*/ 1);
4951 res = arith(&math_state, exp_str ? exp_str : arg);
4952 free(exp_str);
4953 if (errmsg_p)
4954 *errmsg_p = math_state.errmsg;
4955 if (math_state.errmsg)
4956 die_if_script(math_state.errmsg);
4957 return res;
4958}
4959#endif
4960
4961#if ENABLE_HUSH_BASH_COMPAT
4962/* ${var/[/]pattern[/repl]} helpers */
4963static char *strstr_pattern(char *val, const char *pattern, int *size)
4964{
4965 while (1) {
4966 char *end = scan_and_match(val, pattern, SCAN_MOVE_FROM_RIGHT + SCAN_MATCH_LEFT_HALF);
4967 debug_printf_varexp("val:'%s' pattern:'%s' end:'%s'\n", val, pattern, end);
4968 if (end) {
4969 *size = end - val;
4970 return val;
4971 }
4972 if (*val == '\0')
4973 return NULL;
4974 /* Optimization: if "*pat" did not match the start of "string",
4975 * we know that "tring", "ring" etc will not match too:
4976 */
4977 if (pattern[0] == '*')
4978 return NULL;
4979 val++;
4980 }
4981}
4982static char *replace_pattern(char *val, const char *pattern, const char *repl, char exp_op)
4983{
4984 char *result = NULL;
4985 unsigned res_len = 0;
4986 unsigned repl_len = strlen(repl);
4987
4988 while (1) {
4989 int size;
4990 char *s = strstr_pattern(val, pattern, &size);
4991 if (!s)
4992 break;
4993
4994 result = xrealloc(result, res_len + (s - val) + repl_len + 1);
4995 memcpy(result + res_len, val, s - val);
4996 res_len += s - val;
4997 strcpy(result + res_len, repl);
4998 res_len += repl_len;
4999 debug_printf_varexp("val:'%s' s:'%s' result:'%s'\n", val, s, result);
5000
5001 val = s + size;
5002 if (exp_op == '/')
5003 break;
5004 }
5005 if (val[0] && result) {
5006 result = xrealloc(result, res_len + strlen(val) + 1);
5007 strcpy(result + res_len, val);
5008 debug_printf_varexp("val:'%s' result:'%s'\n", val, result);
5009 }
5010 debug_printf_varexp("result:'%s'\n", result);
5011 return result;
5012}
5013#endif
5014
5015/* Helper:
5016 * Handles <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct.
5017 */
5018static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, char **pp)
5019{
5020 const char *val = NULL;
5021 char *to_be_freed = NULL;
5022 char *p = *pp;
5023 char *var;
5024 char first_char;
5025 char exp_op;
5026 char exp_save = exp_save; /* for compiler */
5027 char *exp_saveptr; /* points to expansion operator */
5028 char *exp_word = exp_word; /* for compiler */
5029 char arg0;
5030
5031 *p = '\0'; /* replace trailing SPECIAL_VAR_SYMBOL */
5032 var = arg;
5033 exp_saveptr = arg[1] ? strchr(VAR_ENCODED_SUBST_OPS, arg[1]) : NULL;
5034 arg0 = arg[0];
5035 first_char = arg[0] = arg0 & 0x7f;
5036 exp_op = 0;
5037
5038 if (first_char == '#' /* ${#... */
5039 && arg[1] && !exp_saveptr /* not ${#} and not ${#<op_char>...} */
5040 ) {
5041 /* It must be length operator: ${#var} */
5042 var++;
5043 exp_op = 'L';
5044 } else {
5045 /* Maybe handle parameter expansion */
5046 if (exp_saveptr /* if 2nd char is one of expansion operators */
5047 && strchr(NUMERIC_SPECVARS_STR, first_char) /* 1st char is special variable */
5048 ) {
5049 /* ${?:0}, ${#[:]%0} etc */
5050 exp_saveptr = var + 1;
5051 } else {
5052 /* ${?}, ${var}, ${var:0}, ${var[:]%0} etc */
5053 exp_saveptr = var+1 + strcspn(var+1, VAR_ENCODED_SUBST_OPS);
5054 }
5055 exp_op = exp_save = *exp_saveptr;
5056 if (exp_op) {
5057 exp_word = exp_saveptr + 1;
5058 if (exp_op == ':') {
5059 exp_op = *exp_word++;
5060//TODO: try ${var:} and ${var:bogus} in non-bash config
5061 if (ENABLE_HUSH_BASH_COMPAT
5062 && (!exp_op || !strchr(MINUS_PLUS_EQUAL_QUESTION, exp_op))
5063 ) {
5064 /* oops... it's ${var:N[:M]}, not ${var:?xxx} or some such */
5065 exp_op = ':';
5066 exp_word--;
5067 }
5068 }
5069 *exp_saveptr = '\0';
5070 } /* else: it's not an expansion op, but bare ${var} */
5071 }
5072
5073 /* Look up the variable in question */
5074 if (isdigit(var[0])) {
5075 /* parse_dollar should have vetted var for us */
5076 int n = xatoi_positive(var);
5077 if (n < G.global_argc)
5078 val = G.global_argv[n];
5079 /* else val remains NULL: $N with too big N */
5080 } else {
5081 switch (var[0]) {
5082 case '$': /* pid */
5083 val = utoa(G.root_pid);
5084 break;
5085 case '!': /* bg pid */
5086 val = G.last_bg_pid ? utoa(G.last_bg_pid) : "";
5087 break;
5088 case '?': /* exitcode */
5089 val = utoa(G.last_exitcode);
5090 break;
5091 case '#': /* argc */
5092 val = utoa(G.global_argc ? G.global_argc-1 : 0);
5093 break;
5094 default:
5095 val = get_local_var_value(var);
5096 }
5097 }
5098
5099 /* Handle any expansions */
5100 if (exp_op == 'L') {
5101 reinit_unicode_for_hush();
5102 debug_printf_expand("expand: length(%s)=", val);
5103 val = utoa(val ? unicode_strlen(val) : 0);
5104 debug_printf_expand("%s\n", val);
5105 } else if (exp_op) {
5106 if (exp_op == '%' || exp_op == '#') {
5107 /* Standard-mandated substring removal ops:
5108 * ${parameter%word} - remove smallest suffix pattern
5109 * ${parameter%%word} - remove largest suffix pattern
5110 * ${parameter#word} - remove smallest prefix pattern
5111 * ${parameter##word} - remove largest prefix pattern
5112 *
5113 * Word is expanded to produce a glob pattern.
5114 * Then var's value is matched to it and matching part removed.
5115 */
5116 if (val && val[0]) {
5117 char *t;
5118 char *exp_exp_word;
5119 char *loc;
5120 unsigned scan_flags = pick_scan(exp_op, *exp_word);
5121 if (exp_op == *exp_word) /* ## or %% */
5122 exp_word++;
5123 exp_exp_word = encode_then_expand_string(exp_word, /*process_bkslash:*/ 1, /*unbackslash:*/ 1);
5124 if (exp_exp_word)
5125 exp_word = exp_exp_word;
5126 /* HACK ALERT. We depend here on the fact that
5127 * G.global_argv and results of utoa and get_local_var_value
5128 * are actually in writable memory:
5129 * scan_and_match momentarily stores NULs there. */
5130 t = (char*)val;
5131 loc = scan_and_match(t, exp_word, scan_flags);
5132 //bb_error_msg("op:%c str:'%s' pat:'%s' res:'%s'",
5133 // exp_op, t, exp_word, loc);
5134 free(exp_exp_word);
5135 if (loc) { /* match was found */
5136 if (scan_flags & SCAN_MATCH_LEFT_HALF) /* #[#] */
5137 val = loc; /* take right part */
5138 else /* %[%] */
5139 val = to_be_freed = xstrndup(val, loc - val); /* left */
5140 }
5141 }
5142 }
5143#if ENABLE_HUSH_BASH_COMPAT
5144 else if (exp_op == '/' || exp_op == '\\') {
5145 /* It's ${var/[/]pattern[/repl]} thing.
5146 * Note that in encoded form it has TWO parts:
5147 * var/pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL>
5148 * and if // is used, it is encoded as \:
5149 * var\pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL>
5150 */
5151 /* Empty variable always gives nothing: */
5152 // "v=''; echo ${v/*/w}" prints "", not "w"
5153 if (val && val[0]) {
5154 /* pattern uses non-standard expansion.
5155 * repl should be unbackslashed and globbed
5156 * by the usual expansion rules:
5157 * >az; >bz;
5158 * v='a bz'; echo "${v/a*z/a*z}" prints "a*z"
5159 * v='a bz'; echo "${v/a*z/\z}" prints "\z"
5160 * v='a bz'; echo ${v/a*z/a*z} prints "az"
5161 * v='a bz'; echo ${v/a*z/\z} prints "z"
5162 * (note that a*z _pattern_ is never globbed!)
5163 */
5164 char *pattern, *repl, *t;
5165 pattern = encode_then_expand_string(exp_word, /*process_bkslash:*/ 0, /*unbackslash:*/ 0);
5166 if (!pattern)
5167 pattern = xstrdup(exp_word);
5168 debug_printf_varexp("pattern:'%s'->'%s'\n", exp_word, pattern);
5169 *p++ = SPECIAL_VAR_SYMBOL;
5170 exp_word = p;
5171 p = strchr(p, SPECIAL_VAR_SYMBOL);
5172 *p = '\0';
5173 repl = encode_then_expand_string(exp_word, /*process_bkslash:*/ arg0 & 0x80, /*unbackslash:*/ 1);
5174 debug_printf_varexp("repl:'%s'->'%s'\n", exp_word, repl);
5175 /* HACK ALERT. We depend here on the fact that
5176 * G.global_argv and results of utoa and get_local_var_value
5177 * are actually in writable memory:
5178 * replace_pattern momentarily stores NULs there. */
5179 t = (char*)val;
5180 to_be_freed = replace_pattern(t,
5181 pattern,
5182 (repl ? repl : exp_word),
5183 exp_op);
5184 if (to_be_freed) /* at least one replace happened */
5185 val = to_be_freed;
5186 free(pattern);
5187 free(repl);
5188 }
5189 }
5190#endif
5191 else if (exp_op == ':') {
5192#if ENABLE_HUSH_BASH_COMPAT && ENABLE_SH_MATH_SUPPORT
5193 /* It's ${var:N[:M]} bashism.
5194 * Note that in encoded form it has TWO parts:
5195 * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL>
5196 */
5197 arith_t beg, len;
5198 const char *errmsg;
5199
5200 beg = expand_and_evaluate_arith(exp_word, &errmsg);
5201 if (errmsg)
5202 goto arith_err;
5203 debug_printf_varexp("beg:'%s'=%lld\n", exp_word, (long long)beg);
5204 *p++ = SPECIAL_VAR_SYMBOL;
5205 exp_word = p;
5206 p = strchr(p, SPECIAL_VAR_SYMBOL);
5207 *p = '\0';
5208 len = expand_and_evaluate_arith(exp_word, &errmsg);
5209 if (errmsg)
5210 goto arith_err;
5211 debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len);
5212 if (len >= 0) { /* bash compat: len < 0 is illegal */
5213 if (beg < 0) /* bash compat */
5214 beg = 0;
5215 debug_printf_varexp("from val:'%s'\n", val);
5216 if (len == 0 || !val || beg >= strlen(val)) {
5217 arith_err:
5218 val = NULL;
5219 } else {
5220 /* Paranoia. What if user entered 9999999999999
5221 * which fits in arith_t but not int? */
5222 if (len >= INT_MAX)
5223 len = INT_MAX;
5224 val = to_be_freed = xstrndup(val + beg, len);
5225 }
5226 debug_printf_varexp("val:'%s'\n", val);
5227 } else
5228#endif
5229 {
5230 die_if_script("malformed ${%s:...}", var);
5231 val = NULL;
5232 }
5233 } else { /* one of "-=+?" */
5234 /* Standard-mandated substitution ops:
5235 * ${var?word} - indicate error if unset
5236 * If var is unset, word (or a message indicating it is unset
5237 * if word is null) is written to standard error
5238 * and the shell exits with a non-zero exit status.
5239 * Otherwise, the value of var is substituted.
5240 * ${var-word} - use default value
5241 * If var is unset, word is substituted.
5242 * ${var=word} - assign and use default value
5243 * If var is unset, word is assigned to var.
5244 * In all cases, final value of var is substituted.
5245 * ${var+word} - use alternative value
5246 * If var is unset, null is substituted.
5247 * Otherwise, word is substituted.
5248 *
5249 * Word is subjected to tilde expansion, parameter expansion,
5250 * command substitution, and arithmetic expansion.
5251 * If word is not needed, it is not expanded.
5252 *
5253 * Colon forms (${var:-word}, ${var:=word} etc) do the same,
5254 * but also treat null var as if it is unset.
5255 */
5256 int use_word = (!val || ((exp_save == ':') && !val[0]));
5257 if (exp_op == '+')
5258 use_word = !use_word;
5259 debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op,
5260 (exp_save == ':') ? "true" : "false", use_word);
5261 if (use_word) {
5262 to_be_freed = encode_then_expand_string(exp_word, /*process_bkslash:*/ 1, /*unbackslash:*/ 1);
5263 if (to_be_freed)
5264 exp_word = to_be_freed;
5265 if (exp_op == '?') {
5266 /* mimic bash message */
5267 die_if_script("%s: %s",
5268 var,
5269 exp_word[0] ? exp_word : "parameter null or not set"
5270 );
5271//TODO: how interactive bash aborts expansion mid-command?
5272 } else {
5273 val = exp_word;
5274 }
5275
5276 if (exp_op == '=') {
5277 /* ${var=[word]} or ${var:=[word]} */
5278 if (isdigit(var[0]) || var[0] == '#') {
5279 /* mimic bash message */
5280 die_if_script("$%s: cannot assign in this way", var);
5281 val = NULL;
5282 } else {
5283 char *new_var = xasprintf("%s=%s", var, val);
5284 set_local_var(new_var, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
5285 }
5286 }
5287 }
5288 } /* one of "-=+?" */
5289
5290 *exp_saveptr = exp_save;
5291 } /* if (exp_op) */
5292
5293 arg[0] = arg0;
5294
5295 *pp = p;
5296 *to_be_freed_pp = to_be_freed;
5297 return val;
5298}
5299
5300/* Expand all variable references in given string, adding words to list[]
5301 * at n, n+1,... positions. Return updated n (so that list[n] is next one
5302 * to be filled). This routine is extremely tricky: has to deal with
5303 * variables/parameters with whitespace, $* and $@, and constructs like
5304 * 'echo -$*-'. If you play here, you must run testsuite afterwards! */
5305static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
5306{
5307 /* output->o_expflags & EXP_FLAG_SINGLEWORD (0x80) if we are in
5308 * expansion of right-hand side of assignment == 1-element expand.
5309 */
5310 char cant_be_null = 0; /* only bit 0x80 matters */
5311 int ended_in_ifs = 0; /* did last unquoted expansion end with IFS chars? */
5312 char *p;
5313
5314 debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg,
5315 !!(output->o_expflags & EXP_FLAG_SINGLEWORD));
5316 debug_print_list("expand_vars_to_list", output, n);
5317 n = o_save_ptr(output, n);
5318 debug_print_list("expand_vars_to_list[0]", output, n);
5319
5320 while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) {
5321 char first_ch;
5322 char *to_be_freed = NULL;
5323 const char *val = NULL;
5324#if ENABLE_HUSH_TICK
5325 o_string subst_result = NULL_O_STRING;
5326#endif
5327#if ENABLE_SH_MATH_SUPPORT
5328 char arith_buf[sizeof(arith_t)*3 + 2];
5329#endif
5330
5331 if (ended_in_ifs) {
5332 o_addchr(output, '\0');
5333 n = o_save_ptr(output, n);
5334 ended_in_ifs = 0;
5335 }
5336
5337 o_addblock(output, arg, p - arg);
5338 debug_print_list("expand_vars_to_list[1]", output, n);
5339 arg = ++p;
5340 p = strchr(p, SPECIAL_VAR_SYMBOL);
5341
5342 /* Fetch special var name (if it is indeed one of them)
5343 * and quote bit, force the bit on if singleword expansion -
5344 * important for not getting v=$@ expand to many words. */
5345 first_ch = arg[0] | (output->o_expflags & EXP_FLAG_SINGLEWORD);
5346
5347 /* Is this variable quoted and thus expansion can't be null?
5348 * "$@" is special. Even if quoted, it can still
5349 * expand to nothing (not even an empty string),
5350 * thus it is excluded. */
5351 if ((first_ch & 0x7f) != '@')
5352 cant_be_null |= first_ch;
5353
5354 switch (first_ch & 0x7f) {
5355 /* Highest bit in first_ch indicates that var is double-quoted */
5356 case '*':
5357 case '@': {
5358 int i;
5359 if (!G.global_argv[1])
5360 break;
5361 i = 1;
5362 cant_be_null |= first_ch; /* do it for "$@" _now_, when we know it's not empty */
5363 if (!(first_ch & 0x80)) { /* unquoted $* or $@ */
5364 while (G.global_argv[i]) {
5365 n = expand_on_ifs(NULL, output, n, G.global_argv[i]);
5366 debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1);
5367 if (G.global_argv[i++][0] && G.global_argv[i]) {
5368 /* this argv[] is not empty and not last:
5369 * put terminating NUL, start new word */
5370 o_addchr(output, '\0');
5371 debug_print_list("expand_vars_to_list[2]", output, n);
5372 n = o_save_ptr(output, n);
5373 debug_print_list("expand_vars_to_list[3]", output, n);
5374 }
5375 }
5376 } else
5377 /* If EXP_FLAG_SINGLEWORD, we handle assignment 'a=....$@.....'
5378 * and in this case should treat it like '$*' - see 'else...' below */
5379 if (first_ch == ('@'|0x80) /* quoted $@ */
5380 && !(output->o_expflags & EXP_FLAG_SINGLEWORD) /* not v="$@" case */
5381 ) {
5382 while (1) {
5383 o_addQstr(output, G.global_argv[i]);
5384 if (++i >= G.global_argc)
5385 break;
5386 o_addchr(output, '\0');
5387 debug_print_list("expand_vars_to_list[4]", output, n);
5388 n = o_save_ptr(output, n);
5389 }
5390 } else { /* quoted $* (or v="$@" case): add as one word */
5391 while (1) {
5392 o_addQstr(output, G.global_argv[i]);
5393 if (!G.global_argv[++i])
5394 break;
5395 if (G.ifs[0])
5396 o_addchr(output, G.ifs[0]);
5397 }
5398 output->has_quoted_part = 1;
5399 }
5400 break;
5401 }
5402 case SPECIAL_VAR_SYMBOL: /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_SYMBOL> */
5403 /* "Empty variable", used to make "" etc to not disappear */
5404 output->has_quoted_part = 1;
5405 arg++;
5406 cant_be_null = 0x80;
5407 break;
5408#if ENABLE_HUSH_TICK
5409 case '`': /* <SPECIAL_VAR_SYMBOL>`cmd<SPECIAL_VAR_SYMBOL> */
5410 *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */
5411 arg++;
5412 /* Can't just stuff it into output o_string,
5413 * expanded result may need to be globbed
5414 * and $IFS-splitted */
5415 debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch);
5416 G.last_exitcode = process_command_subs(&subst_result, arg);
5417 debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data);
5418 val = subst_result.data;
5419 goto store_val;
5420#endif
5421#if ENABLE_SH_MATH_SUPPORT
5422 case '+': { /* <SPECIAL_VAR_SYMBOL>+cmd<SPECIAL_VAR_SYMBOL> */
5423 arith_t res;
5424
5425 arg++; /* skip '+' */
5426 *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */
5427 debug_printf_subst("ARITH '%s' first_ch %x\n", arg, first_ch);
5428 res = expand_and_evaluate_arith(arg, NULL);
5429 debug_printf_subst("ARITH RES '"ARITH_FMT"'\n", res);
5430 sprintf(arith_buf, ARITH_FMT, res);
5431 val = arith_buf;
5432 break;
5433 }
5434#endif
5435 default:
5436 val = expand_one_var(&to_be_freed, arg, &p);
5437 IF_HUSH_TICK(store_val:)
5438 if (!(first_ch & 0x80)) { /* unquoted $VAR */
5439 debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val,
5440 !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
5441 if (val && val[0]) {
5442 n = expand_on_ifs(&ended_in_ifs, output, n, val);
5443 val = NULL;
5444 }
5445 } else { /* quoted $VAR, val will be appended below */
5446 output->has_quoted_part = 1;
5447 debug_printf_expand("quoted '%s', output->o_escape:%d\n", val,
5448 !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
5449 }
5450 break;
5451 } /* switch (char after <SPECIAL_VAR_SYMBOL>) */
5452
5453 if (val && val[0]) {
5454 o_addQstr(output, val);
5455 }
5456 free(to_be_freed);
5457
5458 /* Restore NULL'ed SPECIAL_VAR_SYMBOL.
5459 * Do the check to avoid writing to a const string. */
5460 if (*p != SPECIAL_VAR_SYMBOL)
5461 *p = SPECIAL_VAR_SYMBOL;
5462
5463#if ENABLE_HUSH_TICK
5464 o_free(&subst_result);
5465#endif
5466 arg = ++p;
5467 } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */
5468
5469 if (arg[0]) {
5470 if (ended_in_ifs) {
5471 o_addchr(output, '\0');
5472 n = o_save_ptr(output, n);
5473 }
5474 debug_print_list("expand_vars_to_list[a]", output, n);
5475 /* this part is literal, and it was already pre-quoted
5476 * if needed (much earlier), do not use o_addQstr here! */
5477 o_addstr_with_NUL(output, arg);
5478 debug_print_list("expand_vars_to_list[b]", output, n);
5479 } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */
5480 && !(cant_be_null & 0x80) /* and all vars were not quoted. */
5481 ) {
5482 n--;
5483 /* allow to reuse list[n] later without re-growth */
5484 output->has_empty_slot = 1;
5485 } else {
5486 o_addchr(output, '\0');
5487 }
5488
5489 return n;
5490}
5491
5492static char **expand_variables(char **argv, unsigned expflags)
5493{
5494 int n;
5495 char **list;
5496 o_string output = NULL_O_STRING;
5497
5498 output.o_expflags = expflags;
5499
5500 n = 0;
5501 while (*argv) {
5502 n = expand_vars_to_list(&output, n, *argv);
5503 argv++;
5504 }
5505 debug_print_list("expand_variables", &output, n);
5506
5507 /* output.data (malloced in one block) gets returned in "list" */
5508 list = o_finalize_list(&output, n);
5509 debug_print_strings("expand_variables[1]", list);
5510 return list;
5511}
5512
5513static char **expand_strvec_to_strvec(char **argv)
5514{
5515 return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS);
5516}
5517
5518#if ENABLE_HUSH_BASH_COMPAT
5519static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
5520{
5521 return expand_variables(argv, EXP_FLAG_SINGLEWORD);
5522}
5523#endif
5524
5525/* Used for expansion of right hand of assignments,
5526 * $((...)), heredocs, variable espansion parts.
5527 *
5528 * NB: should NOT do globbing!
5529 * "export v=/bin/c*; env | grep ^v=" outputs "v=/bin/c*"
5530 */
5531static char *expand_string_to_string(const char *str, int do_unbackslash)
5532{
5533#if !ENABLE_HUSH_BASH_COMPAT
5534 const int do_unbackslash = 1;
5535#endif
5536 char *argv[2], **list;
5537
5538 debug_printf_expand("string_to_string<='%s'\n", str);
5539 /* This is generally an optimization, but it also
5540 * handles "", which otherwise trips over !list[0] check below.
5541 * (is this ever happens that we actually get str="" here?)
5542 */
5543 if (!strchr(str, SPECIAL_VAR_SYMBOL) && !strchr(str, '\\')) {
5544 //TODO: Can use on strings with \ too, just unbackslash() them?
5545 debug_printf_expand("string_to_string(fast)=>'%s'\n", str);
5546 return xstrdup(str);
5547 }
5548
5549 argv[0] = (char*)str;
5550 argv[1] = NULL;
5551 list = expand_variables(argv, do_unbackslash
5552 ? EXP_FLAG_ESC_GLOB_CHARS | EXP_FLAG_SINGLEWORD
5553 : EXP_FLAG_SINGLEWORD
5554 );
5555 if (HUSH_DEBUG)
5556 if (!list[0] || list[1])
5557 bb_error_msg_and_die("BUG in varexp2");
5558 /* actually, just move string 2*sizeof(char*) bytes back */
5559 overlapping_strcpy((char*)list, list[0]);
5560 if (do_unbackslash)
5561 unbackslash((char*)list);
5562 debug_printf_expand("string_to_string=>'%s'\n", (char*)list);
5563 return (char*)list;
5564}
5565
5566/* Used for "eval" builtin */
5567static char* expand_strvec_to_string(char **argv)
5568{
5569 char **list;
5570
5571 list = expand_variables(argv, EXP_FLAG_SINGLEWORD);
5572 /* Convert all NULs to spaces */
5573 if (list[0]) {
5574 int n = 1;
5575 while (list[n]) {
5576 if (HUSH_DEBUG)
5577 if (list[n-1] + strlen(list[n-1]) + 1 != list[n])
5578 bb_error_msg_and_die("BUG in varexp3");
5579 /* bash uses ' ' regardless of $IFS contents */
5580 list[n][-1] = ' ';
5581 n++;
5582 }
5583 }
5584 overlapping_strcpy((char*)list, list[0]);
5585 debug_printf_expand("strvec_to_string='%s'\n", (char*)list);
5586 return (char*)list;
5587}
5588
5589static char **expand_assignments(char **argv, int count)
5590{
5591 int i;
5592 char **p;
5593
5594 G.expanded_assignments = p = NULL;
5595 /* Expand assignments into one string each */
5596 for (i = 0; i < count; i++) {
5597 G.expanded_assignments = p = add_string_to_strings(p, expand_string_to_string(argv[i], /*unbackslash:*/ 1));
5598 }
5599 G.expanded_assignments = NULL;
5600 return p;
5601}
5602
5603
5604static void switch_off_special_sigs(unsigned mask)
5605{
5606 unsigned sig = 0;
5607 while ((mask >>= 1) != 0) {
5608 sig++;
5609 if (!(mask & 1))
5610 continue;
5611 if (G.traps) {
5612 if (G.traps[sig] && !G.traps[sig][0])
5613 /* trap is '', has to remain SIG_IGN */
5614 continue;
5615 free(G.traps[sig]);
5616 G.traps[sig] = NULL;
5617 }
5618 /* We are here only if no trap or trap was not '' */
5619 install_sighandler(sig, SIG_DFL);
5620 }
5621}
5622
5623#if BB_MMU
5624/* never called */
5625void re_execute_shell(char ***to_free, const char *s,
5626 char *g_argv0, char **g_argv,
5627 char **builtin_argv) NORETURN;
5628
5629static void reset_traps_to_defaults(void)
5630{
5631 /* This function is always called in a child shell
5632 * after fork (not vfork, NOMMU doesn't use this function).
5633 */
5634 unsigned sig;
5635 unsigned mask;
5636
5637 /* Child shells are not interactive.
5638 * SIGTTIN/SIGTTOU/SIGTSTP should not have special handling.
5639 * Testcase: (while :; do :; done) + ^Z should background.
5640 * Same goes for SIGTERM, SIGHUP, SIGINT.
5641 */
5642 mask = (G.special_sig_mask & SPECIAL_INTERACTIVE_SIGS) | G_fatal_sig_mask;
5643 if (!G.traps && !mask)
5644 return; /* already no traps and no special sigs */
5645
5646 /* Switch off special sigs */
5647 switch_off_special_sigs(mask);
5648#if ENABLE_HUSH_JOB
5649 G_fatal_sig_mask = 0;
5650#endif
5651 G.special_sig_mask &= ~SPECIAL_INTERACTIVE_SIGS;
5652 /* SIGQUIT,SIGCHLD and maybe SPECIAL_JOBSTOP_SIGS
5653 * remain set in G.special_sig_mask */
5654
5655 if (!G.traps)
5656 return;
5657
5658 /* Reset all sigs to default except ones with empty traps */
5659 for (sig = 0; sig < NSIG; sig++) {
5660 if (!G.traps[sig])
5661 continue; /* no trap: nothing to do */
5662 if (!G.traps[sig][0])
5663 continue; /* empty trap: has to remain SIG_IGN */
5664 /* sig has non-empty trap, reset it: */
5665 free(G.traps[sig]);
5666 G.traps[sig] = NULL;
5667 /* There is no signal for trap 0 (EXIT) */
5668 if (sig == 0)
5669 continue;
5670 install_sighandler(sig, pick_sighandler(sig));
5671 }
5672}
5673
5674#else /* !BB_MMU */
5675
5676static void re_execute_shell(char ***to_free, const char *s,
5677 char *g_argv0, char **g_argv,
5678 char **builtin_argv) NORETURN;
5679static void re_execute_shell(char ***to_free, const char *s,
5680 char *g_argv0, char **g_argv,
5681 char **builtin_argv)
5682{
5683# define NOMMU_HACK_FMT ("-$%x:%x:%x:%x:%x:%llx" IF_HUSH_LOOPS(":%x"))
5684 /* delims + 2 * (number of bytes in printed hex numbers) */
5685 char param_buf[sizeof(NOMMU_HACK_FMT) + 2 * (sizeof(int)*6 + sizeof(long long)*1)];
5686 char *heredoc_argv[4];
5687 struct variable *cur;
5688# if ENABLE_HUSH_FUNCTIONS
5689 struct function *funcp;
5690# endif
5691 char **argv, **pp;
5692 unsigned cnt;
5693 unsigned long long empty_trap_mask;
5694
5695 if (!g_argv0) { /* heredoc */
5696 argv = heredoc_argv;
5697 argv[0] = (char *) G.argv0_for_re_execing;
5698 argv[1] = (char *) "-<";
5699 argv[2] = (char *) s;
5700 argv[3] = NULL;
5701 pp = &argv[3]; /* used as pointer to empty environment */
5702 goto do_exec;
5703 }
5704
5705 cnt = 0;
5706 pp = builtin_argv;
5707 if (pp) while (*pp++)
5708 cnt++;
5709
5710 empty_trap_mask = 0;
5711 if (G.traps) {
5712 int sig;
5713 for (sig = 1; sig < NSIG; sig++) {
5714 if (G.traps[sig] && !G.traps[sig][0])
5715 empty_trap_mask |= 1LL << sig;
5716 }
5717 }
5718
5719 sprintf(param_buf, NOMMU_HACK_FMT
5720 , (unsigned) G.root_pid
5721 , (unsigned) G.root_ppid
5722 , (unsigned) G.last_bg_pid
5723 , (unsigned) G.last_exitcode
5724 , cnt
5725 , empty_trap_mask
5726 IF_HUSH_LOOPS(, G.depth_of_loop)
5727 );
5728# undef NOMMU_HACK_FMT
5729 /* 1:hush 2:-$<pid>:<pid>:<exitcode>:<etc...> <vars...> <funcs...>
5730 * 3:-c 4:<cmd> 5:<arg0> <argN...> 6:NULL
5731 */
5732 cnt += 6;
5733 for (cur = G.top_var; cur; cur = cur->next) {
5734 if (!cur->flg_export || cur->flg_read_only)
5735 cnt += 2;
5736 }
5737# if ENABLE_HUSH_FUNCTIONS
5738 for (funcp = G.top_func; funcp; funcp = funcp->next)
5739 cnt += 3;
5740# endif
5741 pp = g_argv;
5742 while (*pp++)
5743 cnt++;
5744 *to_free = argv = pp = xzalloc(sizeof(argv[0]) * cnt);
5745 *pp++ = (char *) G.argv0_for_re_execing;
5746 *pp++ = param_buf;
5747 for (cur = G.top_var; cur; cur = cur->next) {
5748 if (strcmp(cur->varstr, hush_version_str) == 0)
5749 continue;
5750 if (cur->flg_read_only) {
5751 *pp++ = (char *) "-R";
5752 *pp++ = cur->varstr;
5753 } else if (!cur->flg_export) {
5754 *pp++ = (char *) "-V";
5755 *pp++ = cur->varstr;
5756 }
5757 }
5758# if ENABLE_HUSH_FUNCTIONS
5759 for (funcp = G.top_func; funcp; funcp = funcp->next) {
5760 *pp++ = (char *) "-F";
5761 *pp++ = funcp->name;
5762 *pp++ = funcp->body_as_string;
5763 }
5764# endif
5765 /* We can pass activated traps here. Say, -Tnn:trap_string
5766 *
5767 * However, POSIX says that subshells reset signals with traps
5768 * to SIG_DFL.
5769 * I tested bash-3.2 and it not only does that with true subshells
5770 * of the form ( list ), but with any forked children shells.
5771 * I set trap "echo W" WINCH; and then tried:
5772 *
5773 * { echo 1; sleep 20; echo 2; } &
5774 * while true; do echo 1; sleep 20; echo 2; break; done &
5775 * true | { echo 1; sleep 20; echo 2; } | cat
5776 *
5777 * In all these cases sending SIGWINCH to the child shell
5778 * did not run the trap. If I add trap "echo V" WINCH;
5779 * _inside_ group (just before echo 1), it works.
5780 *
5781 * I conclude it means we don't need to pass active traps here.
5782 */
5783 *pp++ = (char *) "-c";
5784 *pp++ = (char *) s;
5785 if (builtin_argv) {
5786 while (*++builtin_argv)
5787 *pp++ = *builtin_argv;
5788 *pp++ = (char *) "";
5789 }
5790 *pp++ = g_argv0;
5791 while (*g_argv)
5792 *pp++ = *g_argv++;
5793 /* *pp = NULL; - is already there */
5794 pp = environ;
5795
5796 do_exec:
5797 debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
5798 /* Don't propagate SIG_IGN to the child */
5799 if (SPECIAL_JOBSTOP_SIGS != 0)
5800 switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS);
5801 execve(bb_busybox_exec_path, argv, pp);
5802 /* Fallback. Useful for init=/bin/hush usage etc */
5803 if (argv[0][0] == '/')
5804 execve(argv[0], argv, pp);
5805 xfunc_error_retval = 127;
5806 bb_error_msg_and_die("can't re-execute the shell");
5807}
5808#endif /* !BB_MMU */
5809
5810
5811static int run_and_free_list(struct pipe *pi);
5812
5813/* Executing from string: eval, sh -c '...'
5814 * or from file: /etc/profile, . file, sh <script>, sh (intereactive)
5815 * end_trigger controls how often we stop parsing
5816 * NUL: parse all, execute, return
5817 * ';': parse till ';' or newline, execute, repeat till EOF
5818 */
5819static void parse_and_run_stream(struct in_str *inp, int end_trigger)
5820{
5821 /* Why we need empty flag?
5822 * An obscure corner case "false; ``; echo $?":
5823 * empty command in `` should still set $? to 0.
5824 * But we can't just set $? to 0 at the start,
5825 * this breaks "false; echo `echo $?`" case.
5826 */
5827 bool empty = 1;
5828 while (1) {
5829 struct pipe *pipe_list;
5830
5831#if ENABLE_HUSH_INTERACTIVE
5832 if (end_trigger == ';')
5833 inp->promptmode = 0; /* PS1 */
5834#endif
5835 pipe_list = parse_stream(NULL, inp, end_trigger);
5836 if (!pipe_list || pipe_list == ERR_PTR) { /* EOF/error */
5837 /* If we are in "big" script
5838 * (not in `cmd` or something similar)...
5839 */
5840 if (pipe_list == ERR_PTR && end_trigger == ';') {
5841 /* Discard cached input (rest of line) */
5842 int ch = inp->last_char;
5843 while (ch != EOF && ch != '\n') {
5844 //bb_error_msg("Discarded:'%c'", ch);
5845 ch = i_getch(inp);
5846 }
5847 /* Force prompt */
5848 inp->p = NULL;
5849 /* This stream isn't empty */
5850 empty = 0;
5851 continue;
5852 }
5853 if (!pipe_list && empty)
5854 G.last_exitcode = 0;
5855 break;
5856 }
5857 debug_print_tree(pipe_list, 0);
5858 debug_printf_exec("parse_and_run_stream: run_and_free_list\n");
5859 run_and_free_list(pipe_list);
5860 empty = 0;
5861#if ENABLE_HUSH_FUNCTIONS
5862 if (G.flag_return_in_progress == 1)
5863 break;
5864#endif
5865 }
5866}
5867
5868static void parse_and_run_string(const char *s)
5869{
5870 struct in_str input;
5871 setup_string_in_str(&input, s);
5872 parse_and_run_stream(&input, '\0');
5873}
5874
5875static void parse_and_run_file(FILE *f)
5876{
5877 struct in_str input;
5878 setup_file_in_str(&input, f);
5879 parse_and_run_stream(&input, ';');
5880}
5881
5882#if ENABLE_HUSH_TICK
5883static FILE *generate_stream_from_string(const char *s, pid_t *pid_p)
5884{
5885 pid_t pid;
5886 int channel[2];
5887# if !BB_MMU
5888 char **to_free = NULL;
5889# endif
5890
5891 xpipe(channel);
5892 pid = BB_MMU ? xfork() : xvfork();
5893 if (pid == 0) { /* child */
5894 disable_restore_tty_pgrp_on_exit();
5895 /* Process substitution is not considered to be usual
5896 * 'command execution'.
5897 * SUSv3 says ctrl-Z should be ignored, ctrl-C should not.
5898 */
5899 bb_signals(0
5900 + (1 << SIGTSTP)
5901 + (1 << SIGTTIN)
5902 + (1 << SIGTTOU)
5903 , SIG_IGN);
5904 CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */
5905 close(channel[0]); /* NB: close _first_, then move fd! */
5906 xmove_fd(channel[1], 1);
5907 /* Prevent it from trying to handle ctrl-z etc */
5908 IF_HUSH_JOB(G.run_list_level = 1;)
5909 /* Awful hack for `trap` or $(trap).
5910 *
5911 * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
5912 * contains an example where "trap" is executed in a subshell:
5913 *
5914 * save_traps=$(trap)
5915 * ...
5916 * eval "$save_traps"
5917 *
5918 * Standard does not say that "trap" in subshell shall print
5919 * parent shell's traps. It only says that its output
5920 * must have suitable form, but then, in the above example
5921 * (which is not supposed to be normative), it implies that.
5922 *
5923 * bash (and probably other shell) does implement it
5924 * (traps are reset to defaults, but "trap" still shows them),
5925 * but as a result, "trap" logic is hopelessly messed up:
5926 *
5927 * # trap
5928 * trap -- 'echo Ho' SIGWINCH <--- we have a handler
5929 * # (trap) <--- trap is in subshell - no output (correct, traps are reset)
5930 * # true | trap <--- trap is in subshell - no output (ditto)
5931 * # echo `true | trap` <--- in subshell - output (but traps are reset!)
5932 * trap -- 'echo Ho' SIGWINCH
5933 * # echo `(trap)` <--- in subshell in subshell - output
5934 * trap -- 'echo Ho' SIGWINCH
5935 * # echo `true | (trap)` <--- in subshell in subshell in subshell - output!
5936 * trap -- 'echo Ho' SIGWINCH
5937 *
5938 * The rules when to forget and when to not forget traps
5939 * get really complex and nonsensical.
5940 *
5941 * Our solution: ONLY bare $(trap) or `trap` is special.
5942 */
5943 s = skip_whitespace(s);
5944 if (is_prefixed_with(s, "trap")
5945 && skip_whitespace(s + 4)[0] == '\0'
5946 ) {
5947 static const char *const argv[] = { NULL, NULL };
5948 builtin_trap((char**)argv);
5949 fflush_all(); /* important */
5950 _exit(0);
5951 }
5952# if BB_MMU
5953 reset_traps_to_defaults();
5954 parse_and_run_string(s);
5955 _exit(G.last_exitcode);
5956# else
5957 /* We re-execute after vfork on NOMMU. This makes this script safe:
5958 * yes "0123456789012345678901234567890" | dd bs=32 count=64k >BIG
5959 * huge=`cat BIG` # was blocking here forever
5960 * echo OK
5961 */
5962 re_execute_shell(&to_free,
5963 s,
5964 G.global_argv[0],
5965 G.global_argv + 1,
5966 NULL);
5967# endif
5968 }
5969
5970 /* parent */
5971 *pid_p = pid;
5972# if ENABLE_HUSH_FAST
5973 G.count_SIGCHLD++;
5974//bb_error_msg("[%d] fork in generate_stream_from_string:"
5975// " G.count_SIGCHLD:%d G.handled_SIGCHLD:%d",
5976// getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
5977# endif
5978 enable_restore_tty_pgrp_on_exit();
5979# if !BB_MMU
5980 free(to_free);
5981# endif
5982 close(channel[1]);
5983 close_on_exec_on(channel[0]);
5984 return xfdopen_for_read(channel[0]);
5985}
5986
5987/* Return code is exit status of the process that is run. */
5988static int process_command_subs(o_string *dest, const char *s)
5989{
5990 FILE *fp;
5991 struct in_str pipe_str;
5992 pid_t pid;
5993 int status, ch, eol_cnt;
5994
5995 fp = generate_stream_from_string(s, &pid);
5996
5997 /* Now send results of command back into original context */
5998 setup_file_in_str(&pipe_str, fp);
5999 eol_cnt = 0;
6000 while ((ch = i_getch(&pipe_str)) != EOF) {
6001 if (ch == '\n') {
6002 eol_cnt++;
6003 continue;
6004 }
6005 while (eol_cnt) {
6006 o_addchr(dest, '\n');
6007 eol_cnt--;
6008 }
6009 o_addQchr(dest, ch);
6010 }
6011
6012 debug_printf("done reading from `cmd` pipe, closing it\n");
6013 fclose(fp);
6014 /* We need to extract exitcode. Test case
6015 * "true; echo `sleep 1; false` $?"
6016 * should print 1 */
6017 safe_waitpid(pid, &status, 0);
6018 debug_printf("child exited. returning its exitcode:%d\n", WEXITSTATUS(status));
6019 return WEXITSTATUS(status);
6020}
6021#endif /* ENABLE_HUSH_TICK */
6022
6023
6024static void setup_heredoc(struct redir_struct *redir)
6025{
6026 struct fd_pair pair;
6027 pid_t pid;
6028 int len, written;
6029 /* the _body_ of heredoc (misleading field name) */
6030 const char *heredoc = redir->rd_filename;
6031 char *expanded;
6032#if !BB_MMU
6033 char **to_free;
6034#endif
6035
6036 expanded = NULL;
6037 if (!(redir->rd_dup & HEREDOC_QUOTED)) {
6038 expanded = encode_then_expand_string(heredoc, /*process_bkslash:*/ 1, /*unbackslash:*/ 1);
6039 if (expanded)
6040 heredoc = expanded;
6041 }
6042 len = strlen(heredoc);
6043
6044 close(redir->rd_fd); /* often saves dup2+close in xmove_fd */
6045 xpiped_pair(pair);
6046 xmove_fd(pair.rd, redir->rd_fd);
6047
6048 /* Try writing without forking. Newer kernels have
6049 * dynamically growing pipes. Must use non-blocking write! */
6050 ndelay_on(pair.wr);
6051 while (1) {
6052 written = write(pair.wr, heredoc, len);
6053 if (written <= 0)
6054 break;
6055 len -= written;
6056 if (len == 0) {
6057 close(pair.wr);
6058 free(expanded);
6059 return;
6060 }
6061 heredoc += written;
6062 }
6063 ndelay_off(pair.wr);
6064
6065 /* Okay, pipe buffer was not big enough */
6066 /* Note: we must not create a stray child (bastard? :)
6067 * for the unsuspecting parent process. Child creates a grandchild
6068 * and exits before parent execs the process which consumes heredoc
6069 * (that exec happens after we return from this function) */
6070#if !BB_MMU
6071 to_free = NULL;
6072#endif
6073 pid = xvfork();
6074 if (pid == 0) {
6075 /* child */
6076 disable_restore_tty_pgrp_on_exit();
6077 pid = BB_MMU ? xfork() : xvfork();
6078 if (pid != 0)
6079 _exit(0);
6080 /* grandchild */
6081 close(redir->rd_fd); /* read side of the pipe */
6082#if BB_MMU
6083 full_write(pair.wr, heredoc, len); /* may loop or block */
6084 _exit(0);
6085#else
6086 /* Delegate blocking writes to another process */
6087 xmove_fd(pair.wr, STDOUT_FILENO);
6088 re_execute_shell(&to_free, heredoc, NULL, NULL, NULL);
6089#endif
6090 }
6091 /* parent */
6092#if ENABLE_HUSH_FAST
6093 G.count_SIGCHLD++;
6094//bb_error_msg("[%d] fork in setup_heredoc: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
6095#endif
6096 enable_restore_tty_pgrp_on_exit();
6097#if !BB_MMU
6098 free(to_free);
6099#endif
6100 close(pair.wr);
6101 free(expanded);
6102 wait(NULL); /* wait till child has died */
6103}
6104
6105/* squirrel != NULL means we squirrel away copies of stdin, stdout,
6106 * and stderr if they are redirected. */
6107static int setup_redirects(struct command *prog, int squirrel[])
6108{
6109 int openfd, mode;
6110 struct redir_struct *redir;
6111
6112 for (redir = prog->redirects; redir; redir = redir->next) {
6113 if (redir->rd_type == REDIRECT_HEREDOC2) {
6114 /* rd_fd<<HERE case */
6115 if (squirrel && redir->rd_fd < 3
6116 && squirrel[redir->rd_fd] < 0
6117 ) {
6118 squirrel[redir->rd_fd] = dup(redir->rd_fd);
6119 }
6120 /* for REDIRECT_HEREDOC2, rd_filename holds _contents_
6121 * of the heredoc */
6122 debug_printf_parse("set heredoc '%s'\n",
6123 redir->rd_filename);
6124 setup_heredoc(redir);
6125 continue;
6126 }
6127
6128 if (redir->rd_dup == REDIRFD_TO_FILE) {
6129 /* rd_fd<*>file case (<*> is <,>,>>,<>) */
6130 char *p;
6131 if (redir->rd_filename == NULL) {
6132 /* Something went wrong in the parse.
6133 * Pretend it didn't happen */
6134 bb_error_msg("bug in redirect parse");
6135 continue;
6136 }
6137 mode = redir_table[redir->rd_type].mode;
6138 p = expand_string_to_string(redir->rd_filename, /*unbackslash:*/ 1);
6139 openfd = open_or_warn(p, mode);
6140 free(p);
6141 if (openfd < 0) {
6142 /* this could get lost if stderr has been redirected, but
6143 * bash and ash both lose it as well (though zsh doesn't!) */
6144//what the above comment tries to say?
6145 return 1;
6146 }
6147 } else {
6148 /* rd_fd<*>rd_dup or rd_fd<*>- cases */
6149 openfd = redir->rd_dup;
6150 }
6151
6152 if (openfd != redir->rd_fd) {
6153 if (squirrel && redir->rd_fd < 3
6154 && squirrel[redir->rd_fd] < 0
6155 ) {
6156 squirrel[redir->rd_fd] = dup(redir->rd_fd);
6157 }
6158 if (openfd == REDIRFD_CLOSE) {
6159 /* "n>-" means "close me" */
6160 close(redir->rd_fd);
6161 } else {
6162 xdup2(openfd, redir->rd_fd);
6163 if (redir->rd_dup == REDIRFD_TO_FILE)
6164 close(openfd);
6165 }
6166 }
6167 }
6168 return 0;
6169}
6170
6171static void restore_redirects(int squirrel[])
6172{
6173 int i, fd;
6174 for (i = 0; i < 3; i++) {
6175 fd = squirrel[i];
6176 if (fd != -1) {
6177 /* We simply die on error */
6178 xmove_fd(fd, i);
6179 }
6180 }
6181}
6182
6183static char *find_in_path(const char *arg)
6184{
6185 char *ret = NULL;
6186 const char *PATH = get_local_var_value("PATH");
6187
6188 if (!PATH)
6189 return NULL;
6190
6191 while (1) {
6192 const char *end = strchrnul(PATH, ':');
6193 int sz = end - PATH; /* must be int! */
6194
6195 free(ret);
6196 if (sz != 0) {
6197 ret = xasprintf("%.*s/%s", sz, PATH, arg);
6198 } else {
6199 /* We have xxx::yyyy in $PATH,
6200 * it means "use current dir" */
6201 ret = xstrdup(arg);
6202 }
6203 if (access(ret, F_OK) == 0)
6204 break;
6205
6206 if (*end == '\0') {
6207 free(ret);
6208 return NULL;
6209 }
6210 PATH = end + 1;
6211 }
6212
6213 return ret;
6214}
6215
6216static const struct built_in_command *find_builtin_helper(const char *name,
6217 const struct built_in_command *x,
6218 const struct built_in_command *end)
6219{
6220 while (x != end) {
6221 if (strcmp(name, x->b_cmd) != 0) {
6222 x++;
6223 continue;
6224 }
6225 debug_printf_exec("found builtin '%s'\n", name);
6226 return x;
6227 }
6228 return NULL;
6229}
6230static const struct built_in_command *find_builtin1(const char *name)
6231{
6232 return find_builtin_helper(name, bltins1, &bltins1[ARRAY_SIZE(bltins1)]);
6233}
6234static const struct built_in_command *find_builtin(const char *name)
6235{
6236 const struct built_in_command *x = find_builtin1(name);
6237 if (x)
6238 return x;
6239 return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]);
6240}
6241
6242#if ENABLE_HUSH_FUNCTIONS
6243static struct function **find_function_slot(const char *name)
6244{
6245 struct function **funcpp = &G.top_func;
6246 while (*funcpp) {
6247 if (strcmp(name, (*funcpp)->name) == 0) {
6248 break;
6249 }
6250 funcpp = &(*funcpp)->next;
6251 }
6252 return funcpp;
6253}
6254
6255static const struct function *find_function(const char *name)
6256{
6257 const struct function *funcp = *find_function_slot(name);
6258 if (funcp)
6259 debug_printf_exec("found function '%s'\n", name);
6260 return funcp;
6261}
6262
6263/* Note: takes ownership on name ptr */
6264static struct function *new_function(char *name)
6265{
6266 struct function **funcpp = find_function_slot(name);
6267 struct function *funcp = *funcpp;
6268
6269 if (funcp != NULL) {
6270 struct command *cmd = funcp->parent_cmd;
6271 debug_printf_exec("func %p parent_cmd %p\n", funcp, cmd);
6272 if (!cmd) {
6273 debug_printf_exec("freeing & replacing function '%s'\n", funcp->name);
6274 free(funcp->name);
6275 /* Note: if !funcp->body, do not free body_as_string!
6276 * This is a special case of "-F name body" function:
6277 * body_as_string was not malloced! */
6278 if (funcp->body) {
6279 free_pipe_list(funcp->body);
6280# if !BB_MMU
6281 free(funcp->body_as_string);
6282# endif
6283 }
6284 } else {
6285 debug_printf_exec("reinserting in tree & replacing function '%s'\n", funcp->name);
6286 cmd->argv[0] = funcp->name;
6287 cmd->group = funcp->body;
6288# if !BB_MMU
6289 cmd->group_as_string = funcp->body_as_string;
6290# endif
6291 }
6292 } else {
6293 debug_printf_exec("remembering new function '%s'\n", name);
6294 funcp = *funcpp = xzalloc(sizeof(*funcp));
6295 /*funcp->next = NULL;*/
6296 }
6297
6298 funcp->name = name;
6299 return funcp;
6300}
6301
6302static void unset_func(const char *name)
6303{
6304 struct function **funcpp = find_function_slot(name);
6305 struct function *funcp = *funcpp;
6306
6307 if (funcp != NULL) {
6308 debug_printf_exec("freeing function '%s'\n", funcp->name);
6309 *funcpp = funcp->next;
6310 /* funcp is unlinked now, deleting it.
6311 * Note: if !funcp->body, the function was created by
6312 * "-F name body", do not free ->body_as_string
6313 * and ->name as they were not malloced. */
6314 if (funcp->body) {
6315 free_pipe_list(funcp->body);
6316 free(funcp->name);
6317# if !BB_MMU
6318 free(funcp->body_as_string);
6319# endif
6320 }
6321 free(funcp);
6322 }
6323}
6324
6325# if BB_MMU
6326#define exec_function(to_free, funcp, argv) \
6327 exec_function(funcp, argv)
6328# endif
6329static void exec_function(char ***to_free,
6330 const struct function *funcp,
6331 char **argv) NORETURN;
6332static void exec_function(char ***to_free,
6333 const struct function *funcp,
6334 char **argv)
6335{
6336# if BB_MMU
6337 int n = 1;
6338
6339 argv[0] = G.global_argv[0];
6340 G.global_argv = argv;
6341 while (*++argv)
6342 n++;
6343 G.global_argc = n;
6344 /* On MMU, funcp->body is always non-NULL */
6345 n = run_list(funcp->body);
6346 fflush_all();
6347 _exit(n);
6348# else
6349 re_execute_shell(to_free,
6350 funcp->body_as_string,
6351 G.global_argv[0],
6352 argv + 1,
6353 NULL);
6354# endif
6355}
6356
6357static int run_function(const struct function *funcp, char **argv)
6358{
6359 int rc;
6360 save_arg_t sv;
6361 smallint sv_flg;
6362
6363 save_and_replace_G_args(&sv, argv);
6364
6365 /* "we are in function, ok to use return" */
6366 sv_flg = G.flag_return_in_progress;
6367 G.flag_return_in_progress = -1;
6368# if ENABLE_HUSH_LOCAL
6369 G.func_nest_level++;
6370# endif
6371
6372 /* On MMU, funcp->body is always non-NULL */
6373# if !BB_MMU
6374 if (!funcp->body) {
6375 /* Function defined by -F */
6376 parse_and_run_string(funcp->body_as_string);
6377 rc = G.last_exitcode;
6378 } else
6379# endif
6380 {
6381 rc = run_list(funcp->body);
6382 }
6383
6384# if ENABLE_HUSH_LOCAL
6385 {
6386 struct variable *var;
6387 struct variable **var_pp;
6388
6389 var_pp = &G.top_var;
6390 while ((var = *var_pp) != NULL) {
6391 if (var->func_nest_level < G.func_nest_level) {
6392 var_pp = &var->next;
6393 continue;
6394 }
6395 /* Unexport */
6396 if (var->flg_export)
6397 bb_unsetenv(var->varstr);
6398 /* Remove from global list */
6399 *var_pp = var->next;
6400 /* Free */
6401 if (!var->max_len)
6402 free(var->varstr);
6403 free(var);
6404 }
6405 G.func_nest_level--;
6406 }
6407# endif
6408 G.flag_return_in_progress = sv_flg;
6409
6410 restore_G_args(&sv, argv);
6411
6412 return rc;
6413}
6414#endif /* ENABLE_HUSH_FUNCTIONS */
6415
6416
6417#if BB_MMU
6418#define exec_builtin(to_free, x, argv) \
6419 exec_builtin(x, argv)
6420#else
6421#define exec_builtin(to_free, x, argv) \
6422 exec_builtin(to_free, argv)
6423#endif
6424static void exec_builtin(char ***to_free,
6425 const struct built_in_command *x,
6426 char **argv) NORETURN;
6427static void exec_builtin(char ***to_free,
6428 const struct built_in_command *x,
6429 char **argv)
6430{
6431#if BB_MMU
6432 int rcode;
6433 fflush_all();
6434 rcode = x->b_function(argv);
6435 fflush_all();
6436 _exit(rcode);
6437#else
6438 fflush_all();
6439 /* On NOMMU, we must never block!
6440 * Example: { sleep 99 | read line; } & echo Ok
6441 */
6442 re_execute_shell(to_free,
6443 argv[0],
6444 G.global_argv[0],
6445 G.global_argv + 1,
6446 argv);
6447#endif
6448}
6449
6450
6451static void execvp_or_die(char **argv) NORETURN;
6452static void execvp_or_die(char **argv)
6453{
6454 debug_printf_exec("execing '%s'\n", argv[0]);
6455 /* Don't propagate SIG_IGN to the child */
6456 if (SPECIAL_JOBSTOP_SIGS != 0)
6457 switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS);
6458 execvp(argv[0], argv);
6459 bb_perror_msg("can't execute '%s'", argv[0]);
6460 _exit(127); /* bash compat */
6461}
6462
6463#if ENABLE_HUSH_MODE_X
6464static void dump_cmd_in_x_mode(char **argv)
6465{
6466 if (G_x_mode && argv) {
6467 /* We want to output the line in one write op */
6468 char *buf, *p;
6469 int len;
6470 int n;
6471
6472 len = 3;
6473 n = 0;
6474 while (argv[n])
6475 len += strlen(argv[n++]) + 1;
6476 buf = xmalloc(len);
6477 buf[0] = '+';
6478 p = buf + 1;
6479 n = 0;
6480 while (argv[n])
6481 p += sprintf(p, " %s", argv[n++]);
6482 *p++ = '\n';
6483 *p = '\0';
6484 fputs(buf, stderr);
6485 free(buf);
6486 }
6487}
6488#else
6489# define dump_cmd_in_x_mode(argv) ((void)0)
6490#endif
6491
6492#if BB_MMU
6493#define pseudo_exec_argv(nommu_save, argv, assignment_cnt, argv_expanded) \
6494 pseudo_exec_argv(argv, assignment_cnt, argv_expanded)
6495#define pseudo_exec(nommu_save, command, argv_expanded) \
6496 pseudo_exec(command, argv_expanded)
6497#endif
6498
6499/* Called after [v]fork() in run_pipe, or from builtin_exec.
6500 * Never returns.
6501 * Don't exit() here. If you don't exec, use _exit instead.
6502 * The at_exit handlers apparently confuse the calling process,
6503 * in particular stdin handling. Not sure why? -- because of vfork! (vda)
6504 */
6505static void pseudo_exec_argv(nommu_save_t *nommu_save,
6506 char **argv, int assignment_cnt,
6507 char **argv_expanded) NORETURN;
6508static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save,
6509 char **argv, int assignment_cnt,
6510 char **argv_expanded)
6511{
6512 char **new_env;
6513
6514 new_env = expand_assignments(argv, assignment_cnt);
6515 dump_cmd_in_x_mode(new_env);
6516
6517 if (!argv[assignment_cnt]) {
6518 /* Case when we are here: ... | var=val | ...
6519 * (note that we do not exit early, i.e., do not optimize out
6520 * expand_assignments(): think about ... | var=`sleep 1` | ...
6521 */
6522 free_strings(new_env);
6523 _exit(EXIT_SUCCESS);
6524 }
6525
6526#if BB_MMU
6527 set_vars_and_save_old(new_env);
6528 free(new_env); /* optional */
6529 /* we can also destroy set_vars_and_save_old's return value,
6530 * to save memory */
6531#else
6532 nommu_save->new_env = new_env;
6533 nommu_save->old_vars = set_vars_and_save_old(new_env);
6534#endif
6535
6536 if (argv_expanded) {
6537 argv = argv_expanded;
6538 } else {
6539 argv = expand_strvec_to_strvec(argv + assignment_cnt);
6540#if !BB_MMU
6541 nommu_save->argv = argv;
6542#endif
6543 }
6544 dump_cmd_in_x_mode(argv);
6545
6546#if ENABLE_FEATURE_SH_STANDALONE || BB_MMU
6547 if (strchr(argv[0], '/') != NULL)
6548 goto skip;
6549#endif
6550
6551 /* Check if the command matches any of the builtins.
6552 * Depending on context, this might be redundant. But it's
6553 * easier to waste a few CPU cycles than it is to figure out
6554 * if this is one of those cases.
6555 */
6556 {
6557 /* On NOMMU, it is more expensive to re-execute shell
6558 * just in order to run echo or test builtin.
6559 * It's better to skip it here and run corresponding
6560 * non-builtin later. */
6561 const struct built_in_command *x;
6562 x = BB_MMU ? find_builtin(argv[0]) : find_builtin1(argv[0]);
6563 if (x) {
6564 exec_builtin(&nommu_save->argv_from_re_execing, x, argv);
6565 }
6566 }
6567#if ENABLE_HUSH_FUNCTIONS
6568 /* Check if the command matches any functions */
6569 {
6570 const struct function *funcp = find_function(argv[0]);
6571 if (funcp) {
6572 exec_function(&nommu_save->argv_from_re_execing, funcp, argv);
6573 }
6574 }
6575#endif
6576
6577#if ENABLE_FEATURE_SH_STANDALONE
6578 /* Check if the command matches any busybox applets */
6579 {
6580 int a = find_applet_by_name(argv[0]);
6581 if (a >= 0) {
6582# if BB_MMU /* see above why on NOMMU it is not allowed */
6583 if (APPLET_IS_NOEXEC(a)) {
6584 debug_printf_exec("running applet '%s'\n", argv[0]);
6585 run_applet_no_and_exit(a, argv);
6586 }
6587# endif
6588 /* Re-exec ourselves */
6589 debug_printf_exec("re-execing applet '%s'\n", argv[0]);
6590 /* Don't propagate SIG_IGN to the child */
6591 if (SPECIAL_JOBSTOP_SIGS != 0)
6592 switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS);
6593 execv(bb_busybox_exec_path, argv);
6594 /* If they called chroot or otherwise made the binary no longer
6595 * executable, fall through */
6596 }
6597 }
6598#endif
6599
6600#if ENABLE_FEATURE_SH_STANDALONE || BB_MMU
6601 skip:
6602#endif
6603 execvp_or_die(argv);
6604}
6605
6606/* Called after [v]fork() in run_pipe
6607 */
6608static void pseudo_exec(nommu_save_t *nommu_save,
6609 struct command *command,
6610 char **argv_expanded) NORETURN;
6611static void pseudo_exec(nommu_save_t *nommu_save,
6612 struct command *command,
6613 char **argv_expanded)
6614{
6615 if (command->argv) {
6616 pseudo_exec_argv(nommu_save, command->argv,
6617 command->assignment_cnt, argv_expanded);
6618 }
6619
6620 if (command->group) {
6621 /* Cases when we are here:
6622 * ( list )
6623 * { list } &
6624 * ... | ( list ) | ...
6625 * ... | { list } | ...
6626 */
6627#if BB_MMU
6628 int rcode;
6629 debug_printf_exec("pseudo_exec: run_list\n");
6630 reset_traps_to_defaults();
6631 rcode = run_list(command->group);
6632 /* OK to leak memory by not calling free_pipe_list,
6633 * since this process is about to exit */
6634 _exit(rcode);
6635#else
6636 re_execute_shell(&nommu_save->argv_from_re_execing,
6637 command->group_as_string,
6638 G.global_argv[0],
6639 G.global_argv + 1,
6640 NULL);
6641#endif
6642 }
6643
6644 /* Case when we are here: ... | >file */
6645 debug_printf_exec("pseudo_exec'ed null command\n");
6646 _exit(EXIT_SUCCESS);
6647}
6648
6649#if ENABLE_HUSH_JOB
6650static const char *get_cmdtext(struct pipe *pi)
6651{
6652 char **argv;
6653 char *p;
6654 int len;
6655
6656 /* This is subtle. ->cmdtext is created only on first backgrounding.
6657 * (Think "cat, <ctrl-z>, fg, <ctrl-z>, fg, <ctrl-z>...." here...)
6658 * On subsequent bg argv is trashed, but we won't use it */
6659 if (pi->cmdtext)
6660 return pi->cmdtext;
6661 argv = pi->cmds[0].argv;
6662 if (!argv || !argv[0]) {
6663 pi->cmdtext = xzalloc(1);
6664 return pi->cmdtext;
6665 }
6666
6667 len = 0;
6668 do {
6669 len += strlen(*argv) + 1;
6670 } while (*++argv);
6671 p = xmalloc(len);
6672 pi->cmdtext = p;
6673 argv = pi->cmds[0].argv;
6674 do {
6675 len = strlen(*argv);
6676 memcpy(p, *argv, len);
6677 p += len;
6678 *p++ = ' ';
6679 } while (*++argv);
6680 p[-1] = '\0';
6681 return pi->cmdtext;
6682}
6683
6684static void insert_bg_job(struct pipe *pi)
6685{
6686 struct pipe *job, **jobp;
6687 int i;
6688
6689 /* Linear search for the ID of the job to use */
6690 pi->jobid = 1;
6691 for (job = G.job_list; job; job = job->next)
6692 if (job->jobid >= pi->jobid)
6693 pi->jobid = job->jobid + 1;
6694
6695 /* Add job to the list of running jobs */
6696 jobp = &G.job_list;
6697 while ((job = *jobp) != NULL)
6698 jobp = &job->next;
6699 job = *jobp = xmalloc(sizeof(*job));
6700
6701 *job = *pi; /* physical copy */
6702 job->next = NULL;
6703 job->cmds = xzalloc(sizeof(pi->cmds[0]) * pi->num_cmds);
6704 /* Cannot copy entire pi->cmds[] vector! This causes double frees */
6705 for (i = 0; i < pi->num_cmds; i++) {
6706 job->cmds[i].pid = pi->cmds[i].pid;
6707 /* all other fields are not used and stay zero */
6708 }
6709 job->cmdtext = xstrdup(get_cmdtext(pi));
6710
6711 if (G_interactive_fd)
6712 printf("[%d] %d %s\n", job->jobid, job->cmds[0].pid, job->cmdtext);
6713 G.last_jobid = job->jobid;
6714}
6715
6716static void remove_bg_job(struct pipe *pi)
6717{
6718 struct pipe *prev_pipe;
6719
6720 if (pi == G.job_list) {
6721 G.job_list = pi->next;
6722 } else {
6723 prev_pipe = G.job_list;
6724 while (prev_pipe->next != pi)
6725 prev_pipe = prev_pipe->next;
6726 prev_pipe->next = pi->next;
6727 }
6728 if (G.job_list)
6729 G.last_jobid = G.job_list->jobid;
6730 else
6731 G.last_jobid = 0;
6732}
6733
6734/* Remove a backgrounded job */
6735static void delete_finished_bg_job(struct pipe *pi)
6736{
6737 remove_bg_job(pi);
6738 free_pipe(pi);
6739}
6740#endif /* JOB */
6741
6742/* Check to see if any processes have exited -- if they
6743 * have, figure out why and see if a job has completed */
6744static int checkjobs(struct pipe *fg_pipe)
6745{
6746 int attributes;
6747 int status;
6748#if ENABLE_HUSH_JOB
6749 struct pipe *pi;
6750#endif
6751 pid_t childpid;
6752 int rcode = 0;
6753
6754 debug_printf_jobs("checkjobs %p\n", fg_pipe);
6755
6756 attributes = WUNTRACED;
6757 if (fg_pipe == NULL)
6758 attributes |= WNOHANG;
6759
6760 errno = 0;
6761#if ENABLE_HUSH_FAST
6762 if (G.handled_SIGCHLD == G.count_SIGCHLD) {
6763//bb_error_msg("[%d] checkjobs: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d children?:%d fg_pipe:%p",
6764//getpid(), G.count_SIGCHLD, G.handled_SIGCHLD, G.we_have_children, fg_pipe);
6765 /* There was neither fork nor SIGCHLD since last waitpid */
6766 /* Avoid doing waitpid syscall if possible */
6767 if (!G.we_have_children) {
6768 errno = ECHILD;
6769 return -1;
6770 }
6771 if (fg_pipe == NULL) { /* is WNOHANG set? */
6772 /* We have children, but they did not exit
6773 * or stop yet (we saw no SIGCHLD) */
6774 return 0;
6775 }
6776 /* else: !WNOHANG, waitpid will block, can't short-circuit */
6777 }
6778#endif
6779
6780/* Do we do this right?
6781 * bash-3.00# sleep 20 | false
6782 * <ctrl-Z pressed>
6783 * [3]+ Stopped sleep 20 | false
6784 * bash-3.00# echo $?
6785 * 1 <========== bg pipe is not fully done, but exitcode is already known!
6786 * [hush 1.14.0: yes we do it right]
6787 */
6788 wait_more:
6789 while (1) {
6790 int i;
6791 int dead;
6792
6793#if ENABLE_HUSH_FAST
6794 i = G.count_SIGCHLD;
6795#endif
6796 childpid = waitpid(-1, &status, attributes);
6797 if (childpid <= 0) {
6798 if (childpid && errno != ECHILD)
6799 bb_perror_msg("waitpid");
6800#if ENABLE_HUSH_FAST
6801 else { /* Until next SIGCHLD, waitpid's are useless */
6802 G.we_have_children = (childpid == 0);
6803 G.handled_SIGCHLD = i;
6804//bb_error_msg("[%d] checkjobs: waitpid returned <= 0, G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
6805 }
6806#endif
6807 break;
6808 }
6809 dead = WIFEXITED(status) || WIFSIGNALED(status);
6810
6811#if DEBUG_JOBS
6812 if (WIFSTOPPED(status))
6813 debug_printf_jobs("pid %d stopped by sig %d (exitcode %d)\n",
6814 childpid, WSTOPSIG(status), WEXITSTATUS(status));
6815 if (WIFSIGNALED(status))
6816 debug_printf_jobs("pid %d killed by sig %d (exitcode %d)\n",
6817 childpid, WTERMSIG(status), WEXITSTATUS(status));
6818 if (WIFEXITED(status))
6819 debug_printf_jobs("pid %d exited, exitcode %d\n",
6820 childpid, WEXITSTATUS(status));
6821#endif
6822 /* Were we asked to wait for fg pipe? */
6823 if (fg_pipe) {
6824 i = fg_pipe->num_cmds;
6825 while (--i >= 0) {
6826 debug_printf_jobs("check pid %d\n", fg_pipe->cmds[i].pid);
6827 if (fg_pipe->cmds[i].pid != childpid)
6828 continue;
6829 if (dead) {
6830 int ex;
6831 fg_pipe->cmds[i].pid = 0;
6832 fg_pipe->alive_cmds--;
6833 ex = WEXITSTATUS(status);
6834 /* bash prints killer signal's name for *last*
6835 * process in pipe (prints just newline for SIGINT/SIGPIPE).
6836 * Mimic this. Example: "sleep 5" + (^\ or kill -QUIT)
6837 */
6838 if (WIFSIGNALED(status)) {
6839 int sig = WTERMSIG(status);
6840 if (i == fg_pipe->num_cmds-1)
6841 /* TODO: use strsignal() instead for bash compat? but that's bloat... */
6842 puts(sig == SIGINT || sig == SIGPIPE ? "" : get_signame(sig));
6843 /* TODO: if (WCOREDUMP(status)) + " (core dumped)"; */
6844 /* TODO: MIPS has 128 sigs (1..128), what if sig==128 here?
6845 * Maybe we need to use sig | 128? */
6846 ex = sig + 128;
6847 }
6848 fg_pipe->cmds[i].cmd_exitcode = ex;
6849 } else {
6850 fg_pipe->stopped_cmds++;
6851 }
6852 debug_printf_jobs("fg_pipe: alive_cmds %d stopped_cmds %d\n",
6853 fg_pipe->alive_cmds, fg_pipe->stopped_cmds);
6854 if (fg_pipe->alive_cmds == fg_pipe->stopped_cmds) {
6855 /* All processes in fg pipe have exited or stopped */
6856 i = fg_pipe->num_cmds;
6857 while (--i >= 0) {
6858 rcode = fg_pipe->cmds[i].cmd_exitcode;
6859 /* usually last process gives overall exitstatus,
6860 * but with "set -o pipefail", last *failed* process does */
6861 if (G.o_opt[OPT_O_PIPEFAIL] == 0 || rcode != 0)
6862 break;
6863 }
6864 IF_HAS_KEYWORDS(if (fg_pipe->pi_inverted) rcode = !rcode;)
6865/* Note: *non-interactive* bash does not continue if all processes in fg pipe
6866 * are stopped. Testcase: "cat | cat" in a script (not on command line!)
6867 * and "killall -STOP cat" */
6868 if (G_interactive_fd) {
6869#if ENABLE_HUSH_JOB
6870 if (fg_pipe->alive_cmds != 0)
6871 insert_bg_job(fg_pipe);
6872#endif
6873 return rcode;
6874 }
6875 if (fg_pipe->alive_cmds == 0)
6876 return rcode;
6877 }
6878 /* There are still running processes in the fg pipe */
6879 goto wait_more; /* do waitpid again */
6880 }
6881 /* it wasnt fg_pipe, look for process in bg pipes */
6882 }
6883
6884#if ENABLE_HUSH_JOB
6885 /* We asked to wait for bg or orphaned children */
6886 /* No need to remember exitcode in this case */
6887 for (pi = G.job_list; pi; pi = pi->next) {
6888 for (i = 0; i < pi->num_cmds; i++) {
6889 if (pi->cmds[i].pid == childpid)
6890 goto found_pi_and_prognum;
6891 }
6892 }
6893 /* Happens when shell is used as init process (init=/bin/sh) */
6894 debug_printf("checkjobs: pid %d was not in our list!\n", childpid);
6895 continue; /* do waitpid again */
6896
6897 found_pi_and_prognum:
6898 if (dead) {
6899 /* child exited */
6900 pi->cmds[i].pid = 0;
6901 pi->alive_cmds--;
6902 if (!pi->alive_cmds) {
6903 if (G_interactive_fd)
6904 printf(JOB_STATUS_FORMAT, pi->jobid,
6905 "Done", pi->cmdtext);
6906 delete_finished_bg_job(pi);
6907 }
6908 } else {
6909 /* child stopped */
6910 pi->stopped_cmds++;
6911 }
6912#endif
6913 } /* while (waitpid succeeds)... */
6914
6915 return rcode;
6916}
6917
6918#if ENABLE_HUSH_JOB
6919static int checkjobs_and_fg_shell(struct pipe *fg_pipe)
6920{
6921 pid_t p;
6922 int rcode = checkjobs(fg_pipe);
6923 if (G_saved_tty_pgrp) {
6924 /* Job finished, move the shell to the foreground */
6925 p = getpgrp(); /* our process group id */
6926 debug_printf_jobs("fg'ing ourself: getpgrp()=%d\n", (int)p);
6927 tcsetpgrp(G_interactive_fd, p);
6928 }
6929 return rcode;
6930}
6931#endif
6932
6933/* Start all the jobs, but don't wait for anything to finish.
6934 * See checkjobs().
6935 *
6936 * Return code is normally -1, when the caller has to wait for children
6937 * to finish to determine the exit status of the pipe. If the pipe
6938 * is a simple builtin command, however, the action is done by the
6939 * time run_pipe returns, and the exit code is provided as the
6940 * return value.
6941 *
6942 * Returns -1 only if started some children. IOW: we have to
6943 * mask out retvals of builtins etc with 0xff!
6944 *
6945 * The only case when we do not need to [v]fork is when the pipe
6946 * is single, non-backgrounded, non-subshell command. Examples:
6947 * cmd ; ... { list } ; ...
6948 * cmd && ... { list } && ...
6949 * cmd || ... { list } || ...
6950 * If it is, then we can run cmd as a builtin, NOFORK,
6951 * or (if SH_STANDALONE) an applet, and we can run the { list }
6952 * with run_list. If it isn't one of these, we fork and exec cmd.
6953 *
6954 * Cases when we must fork:
6955 * non-single: cmd | cmd
6956 * backgrounded: cmd & { list } &
6957 * subshell: ( list ) [&]
6958 */
6959#if !ENABLE_HUSH_MODE_X
6960#define redirect_and_varexp_helper(new_env_p, old_vars_p, command, squirrel, argv_expanded) \
6961 redirect_and_varexp_helper(new_env_p, old_vars_p, command, squirrel)
6962#endif
6963static int redirect_and_varexp_helper(char ***new_env_p,
6964 struct variable **old_vars_p,
6965 struct command *command,
6966 int squirrel[3],
6967 char **argv_expanded)
6968{
6969 /* setup_redirects acts on file descriptors, not FILEs.
6970 * This is perfect for work that comes after exec().
6971 * Is it really safe for inline use? Experimentally,
6972 * things seem to work. */
6973 int rcode = setup_redirects(command, squirrel);
6974 if (rcode == 0) {
6975 char **new_env = expand_assignments(command->argv, command->assignment_cnt);
6976 *new_env_p = new_env;
6977 dump_cmd_in_x_mode(new_env);
6978 dump_cmd_in_x_mode(argv_expanded);
6979 if (old_vars_p)
6980 *old_vars_p = set_vars_and_save_old(new_env);
6981 }
6982 return rcode;
6983}
6984static NOINLINE int run_pipe(struct pipe *pi)
6985{
6986 static const char *const null_ptr = NULL;
6987
6988 int cmd_no;
6989 int next_infd;
6990 struct command *command;
6991 char **argv_expanded;
6992 char **argv;
6993 /* it is not always needed, but we aim to smaller code */
6994 int squirrel[] = { -1, -1, -1 };
6995 int rcode;
6996
6997 debug_printf_exec("run_pipe start: members:%d\n", pi->num_cmds);
6998 debug_enter();
6999
7000 /* Testcase: set -- q w e; (IFS='' echo "$*"; IFS=''; echo "$*"); echo "$*"
7001 * Result should be 3 lines: q w e, qwe, q w e
7002 */
7003 G.ifs = get_local_var_value("IFS");
7004 if (!G.ifs)
7005 G.ifs = defifs;
7006
7007 IF_HUSH_JOB(pi->pgrp = -1;)
7008 pi->stopped_cmds = 0;
7009 command = &pi->cmds[0];
7010 argv_expanded = NULL;
7011
7012 if (pi->num_cmds != 1
7013 || pi->followup == PIPE_BG
7014 || command->cmd_type == CMD_SUBSHELL
7015 ) {
7016 goto must_fork;
7017 }
7018
7019 pi->alive_cmds = 1;
7020
7021 debug_printf_exec(": group:%p argv:'%s'\n",
7022 command->group, command->argv ? command->argv[0] : "NONE");
7023
7024 if (command->group) {
7025#if ENABLE_HUSH_FUNCTIONS
7026 if (command->cmd_type == CMD_FUNCDEF) {
7027 /* "executing" func () { list } */
7028 struct function *funcp;
7029
7030 funcp = new_function(command->argv[0]);
7031 /* funcp->name is already set to argv[0] */
7032 funcp->body = command->group;
7033# if !BB_MMU
7034 funcp->body_as_string = command->group_as_string;
7035 command->group_as_string = NULL;
7036# endif
7037 command->group = NULL;
7038 command->argv[0] = NULL;
7039 debug_printf_exec("cmd %p has child func at %p\n", command, funcp);
7040 funcp->parent_cmd = command;
7041 command->child_func = funcp;
7042
7043 debug_printf_exec("run_pipe: return EXIT_SUCCESS\n");
7044 debug_leave();
7045 return EXIT_SUCCESS;
7046 }
7047#endif
7048 /* { list } */
7049 debug_printf("non-subshell group\n");
7050 rcode = 1; /* exitcode if redir failed */
7051 if (setup_redirects(command, squirrel) == 0) {
7052 debug_printf_exec(": run_list\n");
7053 rcode = run_list(command->group) & 0xff;
7054 }
7055 restore_redirects(squirrel);
7056 IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
7057 debug_leave();
7058 debug_printf_exec("run_pipe: return %d\n", rcode);
7059 return rcode;
7060 }
7061
7062 argv = command->argv ? command->argv : (char **) &null_ptr;
7063 {
7064 const struct built_in_command *x;
7065#if ENABLE_HUSH_FUNCTIONS
7066 const struct function *funcp;
7067#else
7068 enum { funcp = 0 };
7069#endif
7070 char **new_env = NULL;
7071 struct variable *old_vars = NULL;
7072
7073 if (argv[command->assignment_cnt] == NULL) {
7074 /* Assignments, but no command */
7075 /* Ensure redirects take effect (that is, create files).
7076 * Try "a=t >file" */
7077#if 0 /* A few cases in testsuite fail with this code. FIXME */
7078 rcode = redirect_and_varexp_helper(&new_env, /*old_vars:*/ NULL, command, squirrel, /*argv_expanded:*/ NULL);
7079 /* Set shell variables */
7080 if (new_env) {
7081 argv = new_env;
7082 while (*argv) {
7083 set_local_var(*argv, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
7084 /* Do we need to flag set_local_var() errors?
7085 * "assignment to readonly var" and "putenv error"
7086 */
7087 argv++;
7088 }
7089 }
7090 /* Redirect error sets $? to 1. Otherwise,
7091 * if evaluating assignment value set $?, retain it.
7092 * Try "false; q=`exit 2`; echo $?" - should print 2: */
7093 if (rcode == 0)
7094 rcode = G.last_exitcode;
7095 /* Exit, _skipping_ variable restoring code: */
7096 goto clean_up_and_ret0;
7097
7098#else /* Older, bigger, but more correct code */
7099
7100 rcode = setup_redirects(command, squirrel);
7101 restore_redirects(squirrel);
7102 /* Set shell variables */
7103 if (G_x_mode)
7104 bb_putchar_stderr('+');
7105 while (*argv) {
7106 char *p = expand_string_to_string(*argv, /*unbackslash:*/ 1);
7107 if (G_x_mode)
7108 fprintf(stderr, " %s", p);
7109 debug_printf_exec("set shell var:'%s'->'%s'\n",
7110 *argv, p);
7111 set_local_var(p, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
7112 /* Do we need to flag set_local_var() errors?
7113 * "assignment to readonly var" and "putenv error"
7114 */
7115 argv++;
7116 }
7117 if (G_x_mode)
7118 bb_putchar_stderr('\n');
7119 /* Redirect error sets $? to 1. Otherwise,
7120 * if evaluating assignment value set $?, retain it.
7121 * Try "false; q=`exit 2`; echo $?" - should print 2: */
7122 if (rcode == 0)
7123 rcode = G.last_exitcode;
7124 IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
7125 debug_leave();
7126 debug_printf_exec("run_pipe: return %d\n", rcode);
7127 return rcode;
7128#endif
7129 }
7130
7131 /* Expand the rest into (possibly) many strings each */
7132#if ENABLE_HUSH_BASH_COMPAT
7133 if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) {
7134 argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt);
7135 } else
7136#endif
7137 {
7138 argv_expanded = expand_strvec_to_strvec(argv + command->assignment_cnt);
7139 }
7140
7141 /* if someone gives us an empty string: `cmd with empty output` */
7142 if (!argv_expanded[0]) {
7143 free(argv_expanded);
7144 debug_leave();
7145 return G.last_exitcode;
7146 }
7147
7148 x = find_builtin(argv_expanded[0]);
7149#if ENABLE_HUSH_FUNCTIONS
7150 funcp = NULL;
7151 if (!x)
7152 funcp = find_function(argv_expanded[0]);
7153#endif
7154 if (x || funcp) {
7155 if (!funcp) {
7156 if (x->b_function == builtin_exec && argv_expanded[1] == NULL) {
7157 debug_printf("exec with redirects only\n");
7158 rcode = setup_redirects(command, NULL);
7159 goto clean_up_and_ret1;
7160 }
7161 }
7162 rcode = redirect_and_varexp_helper(&new_env, &old_vars, command, squirrel, argv_expanded);
7163 if (rcode == 0) {
7164 if (!funcp) {
7165 debug_printf_exec(": builtin '%s' '%s'...\n",
7166 x->b_cmd, argv_expanded[1]);
7167 fflush_all();
7168 rcode = x->b_function(argv_expanded) & 0xff;
7169 fflush_all();
7170 }
7171#if ENABLE_HUSH_FUNCTIONS
7172 else {
7173# if ENABLE_HUSH_LOCAL
7174 struct variable **sv;
7175 sv = G.shadowed_vars_pp;
7176 G.shadowed_vars_pp = &old_vars;
7177# endif
7178 debug_printf_exec(": function '%s' '%s'...\n",
7179 funcp->name, argv_expanded[1]);
7180 rcode = run_function(funcp, argv_expanded) & 0xff;
7181# if ENABLE_HUSH_LOCAL
7182 G.shadowed_vars_pp = sv;
7183# endif
7184 }
7185#endif
7186 }
7187 clean_up_and_ret:
7188 unset_vars(new_env);
7189 add_vars(old_vars);
7190/* clean_up_and_ret0: */
7191 restore_redirects(squirrel);
7192 clean_up_and_ret1:
7193 free(argv_expanded);
7194 IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
7195 debug_leave();
7196 debug_printf_exec("run_pipe return %d\n", rcode);
7197 return rcode;
7198 }
7199
7200 if (ENABLE_FEATURE_SH_NOFORK) {
7201 int n = find_applet_by_name(argv_expanded[0]);
7202 if (n >= 0 && APPLET_IS_NOFORK(n)) {
7203 rcode = redirect_and_varexp_helper(&new_env, &old_vars, command, squirrel, argv_expanded);
7204 if (rcode == 0) {
7205 debug_printf_exec(": run_nofork_applet '%s' '%s'...\n",
7206 argv_expanded[0], argv_expanded[1]);
7207 rcode = run_nofork_applet(n, argv_expanded);
7208 }
7209 goto clean_up_and_ret;
7210 }
7211 }
7212 /* It is neither builtin nor applet. We must fork. */
7213 }
7214
7215 must_fork:
7216 /* NB: argv_expanded may already be created, and that
7217 * might include `cmd` runs! Do not rerun it! We *must*
7218 * use argv_expanded if it's non-NULL */
7219
7220 /* Going to fork a child per each pipe member */
7221 pi->alive_cmds = 0;
7222 next_infd = 0;
7223
7224 cmd_no = 0;
7225 while (cmd_no < pi->num_cmds) {
7226 struct fd_pair pipefds;
7227#if !BB_MMU
7228 volatile nommu_save_t nommu_save;
7229 nommu_save.new_env = NULL;
7230 nommu_save.old_vars = NULL;
7231 nommu_save.argv = NULL;
7232 nommu_save.argv_from_re_execing = NULL;
7233#endif
7234 command = &pi->cmds[cmd_no];
7235 cmd_no++;
7236 if (command->argv) {
7237 debug_printf_exec(": pipe member '%s' '%s'...\n",
7238 command->argv[0], command->argv[1]);
7239 } else {
7240 debug_printf_exec(": pipe member with no argv\n");
7241 }
7242
7243 /* pipes are inserted between pairs of commands */
7244 pipefds.rd = 0;
7245 pipefds.wr = 1;
7246 if (cmd_no < pi->num_cmds)
7247 xpiped_pair(pipefds);
7248
7249 command->pid = BB_MMU ? fork() : vfork();
7250 if (!command->pid) { /* child */
7251#if ENABLE_HUSH_JOB
7252 disable_restore_tty_pgrp_on_exit();
7253 CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */
7254
7255 /* Every child adds itself to new process group
7256 * with pgid == pid_of_first_child_in_pipe */
7257 if (G.run_list_level == 1 && G_interactive_fd) {
7258 pid_t pgrp;
7259 pgrp = pi->pgrp;
7260 if (pgrp < 0) /* true for 1st process only */
7261 pgrp = getpid();
7262 if (setpgid(0, pgrp) == 0
7263 && pi->followup != PIPE_BG
7264 && G_saved_tty_pgrp /* we have ctty */
7265 ) {
7266 /* We do it in *every* child, not just first,
7267 * to avoid races */
7268 tcsetpgrp(G_interactive_fd, pgrp);
7269 }
7270 }
7271#endif
7272 if (pi->alive_cmds == 0 && pi->followup == PIPE_BG) {
7273 /* 1st cmd in backgrounded pipe
7274 * should have its stdin /dev/null'ed */
7275 close(0);
7276 if (open(bb_dev_null, O_RDONLY))
7277 xopen("/", O_RDONLY);
7278 } else {
7279 xmove_fd(next_infd, 0);
7280 }
7281 xmove_fd(pipefds.wr, 1);
7282 if (pipefds.rd > 1)
7283 close(pipefds.rd);
7284 /* Like bash, explicit redirects override pipes,
7285 * and the pipe fd is available for dup'ing. */
7286 if (setup_redirects(command, NULL))
7287 _exit(1);
7288
7289 /* Stores to nommu_save list of env vars putenv'ed
7290 * (NOMMU, on MMU we don't need that) */
7291 /* cast away volatility... */
7292 pseudo_exec((nommu_save_t*) &nommu_save, command, argv_expanded);
7293 /* pseudo_exec() does not return */
7294 }
7295
7296 /* parent or error */
7297#if ENABLE_HUSH_FAST
7298 G.count_SIGCHLD++;
7299//bb_error_msg("[%d] fork in run_pipe: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
7300#endif
7301 enable_restore_tty_pgrp_on_exit();
7302#if !BB_MMU
7303 /* Clean up after vforked child */
7304 free(nommu_save.argv);
7305 free(nommu_save.argv_from_re_execing);
7306 unset_vars(nommu_save.new_env);
7307 add_vars(nommu_save.old_vars);
7308#endif
7309 free(argv_expanded);
7310 argv_expanded = NULL;
7311 if (command->pid < 0) { /* [v]fork failed */
7312 /* Clearly indicate, was it fork or vfork */
7313 bb_perror_msg(BB_MMU ? "vfork"+1 : "vfork");
7314 } else {
7315 pi->alive_cmds++;
7316#if ENABLE_HUSH_JOB
7317 /* Second and next children need to know pid of first one */
7318 if (pi->pgrp < 0)
7319 pi->pgrp = command->pid;
7320#endif
7321 }
7322
7323 if (cmd_no > 1)
7324 close(next_infd);
7325 if (cmd_no < pi->num_cmds)
7326 close(pipefds.wr);
7327 /* Pass read (output) pipe end to next iteration */
7328 next_infd = pipefds.rd;
7329 }
7330
7331 if (!pi->alive_cmds) {
7332 debug_leave();
7333 debug_printf_exec("run_pipe return 1 (all forks failed, no children)\n");
7334 return 1;
7335 }
7336
7337 debug_leave();
7338 debug_printf_exec("run_pipe return -1 (%u children started)\n", pi->alive_cmds);
7339 return -1;
7340}
7341
7342/* NB: called by pseudo_exec, and therefore must not modify any
7343 * global data until exec/_exit (we can be a child after vfork!) */
7344static int run_list(struct pipe *pi)
7345{
7346#if ENABLE_HUSH_CASE
7347 char *case_word = NULL;
7348#endif
7349#if ENABLE_HUSH_LOOPS
7350 struct pipe *loop_top = NULL;
7351 char **for_lcur = NULL;
7352 char **for_list = NULL;
7353#endif
7354 smallint last_followup;
7355 smalluint rcode;
7356#if ENABLE_HUSH_IF || ENABLE_HUSH_CASE
7357 smalluint cond_code = 0;
7358#else
7359 enum { cond_code = 0 };
7360#endif
7361#if HAS_KEYWORDS
7362 smallint rword; /* RES_foo */
7363 smallint last_rword; /* ditto */
7364#endif
7365
7366 debug_printf_exec("run_list start lvl %d\n", G.run_list_level);
7367 debug_enter();
7368
7369#if ENABLE_HUSH_LOOPS
7370 /* Check syntax for "for" */
7371 {
7372 struct pipe *cpipe;
7373 for (cpipe = pi; cpipe; cpipe = cpipe->next) {
7374 if (cpipe->res_word != RES_FOR && cpipe->res_word != RES_IN)
7375 continue;
7376 /* current word is FOR or IN (BOLD in comments below) */
7377 if (cpipe->next == NULL) {
7378 syntax_error("malformed for");
7379 debug_leave();
7380 debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level);
7381 return 1;
7382 }
7383 /* "FOR v; do ..." and "for v IN a b; do..." are ok */
7384 if (cpipe->next->res_word == RES_DO)
7385 continue;
7386 /* next word is not "do". It must be "in" then ("FOR v in ...") */
7387 if (cpipe->res_word == RES_IN /* "for v IN a b; not_do..."? */
7388 || cpipe->next->res_word != RES_IN /* FOR v not_do_and_not_in..."? */
7389 ) {
7390 syntax_error("malformed for");
7391 debug_leave();
7392 debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level);
7393 return 1;
7394 }
7395 }
7396 }
7397#endif
7398
7399 /* Past this point, all code paths should jump to ret: label
7400 * in order to return, no direct "return" statements please.
7401 * This helps to ensure that no memory is leaked. */
7402
7403#if ENABLE_HUSH_JOB
7404 G.run_list_level++;
7405#endif
7406
7407#if HAS_KEYWORDS
7408 rword = RES_NONE;
7409 last_rword = RES_XXXX;
7410#endif
7411 last_followup = PIPE_SEQ;
7412 rcode = G.last_exitcode;
7413
7414 /* Go through list of pipes, (maybe) executing them. */
7415 for (; pi; pi = IF_HUSH_LOOPS(rword == RES_DONE ? loop_top : ) pi->next) {
7416 if (G.flag_SIGINT)
7417 break;
7418
7419 IF_HAS_KEYWORDS(rword = pi->res_word;)
7420 debug_printf_exec(": rword=%d cond_code=%d last_rword=%d\n",
7421 rword, cond_code, last_rword);
7422#if ENABLE_HUSH_LOOPS
7423 if ((rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR)
7424 && loop_top == NULL /* avoid bumping G.depth_of_loop twice */
7425 ) {
7426 /* start of a loop: remember where loop starts */
7427 loop_top = pi;
7428 G.depth_of_loop++;
7429 }
7430#endif
7431 /* Still in the same "if...", "then..." or "do..." branch? */
7432 if (IF_HAS_KEYWORDS(rword == last_rword &&) 1) {
7433 if ((rcode == 0 && last_followup == PIPE_OR)
7434 || (rcode != 0 && last_followup == PIPE_AND)
7435 ) {
7436 /* It is "<true> || CMD" or "<false> && CMD"
7437 * and we should not execute CMD */
7438 debug_printf_exec("skipped cmd because of || or &&\n");
7439 last_followup = pi->followup;
7440 goto dont_check_jobs_but_continue;
7441 }
7442 }
7443 last_followup = pi->followup;
7444 IF_HAS_KEYWORDS(last_rword = rword;)
7445#if ENABLE_HUSH_IF
7446 if (cond_code) {
7447 if (rword == RES_THEN) {
7448 /* if false; then ... fi has exitcode 0! */
7449 G.last_exitcode = rcode = EXIT_SUCCESS;
7450 /* "if <false> THEN cmd": skip cmd */
7451 continue;
7452 }
7453 } else {
7454 if (rword == RES_ELSE || rword == RES_ELIF) {
7455 /* "if <true> then ... ELSE/ELIF cmd":
7456 * skip cmd and all following ones */
7457 break;
7458 }
7459 }
7460#endif
7461#if ENABLE_HUSH_LOOPS
7462 if (rword == RES_FOR) { /* && pi->num_cmds - always == 1 */
7463 if (!for_lcur) {
7464 /* first loop through for */
7465
7466 static const char encoded_dollar_at[] ALIGN1 = {
7467 SPECIAL_VAR_SYMBOL, '@' | 0x80, SPECIAL_VAR_SYMBOL, '\0'
7468 }; /* encoded representation of "$@" */
7469 static const char *const encoded_dollar_at_argv[] = {
7470 encoded_dollar_at, NULL
7471 }; /* argv list with one element: "$@" */
7472 char **vals;
7473
7474 vals = (char**)encoded_dollar_at_argv;
7475 if (pi->next->res_word == RES_IN) {
7476 /* if no variable values after "in" we skip "for" */
7477 if (!pi->next->cmds[0].argv) {
7478 G.last_exitcode = rcode = EXIT_SUCCESS;
7479 debug_printf_exec(": null FOR: exitcode EXIT_SUCCESS\n");
7480 break;
7481 }
7482 vals = pi->next->cmds[0].argv;
7483 } /* else: "for var; do..." -> assume "$@" list */
7484 /* create list of variable values */
7485 debug_print_strings("for_list made from", vals);
7486 for_list = expand_strvec_to_strvec(vals);
7487 for_lcur = for_list;
7488 debug_print_strings("for_list", for_list);
7489 }
7490 if (!*for_lcur) {
7491 /* "for" loop is over, clean up */
7492 free(for_list);
7493 for_list = NULL;
7494 for_lcur = NULL;
7495 break;
7496 }
7497 /* Insert next value from for_lcur */
7498 /* note: *for_lcur already has quotes removed, $var expanded, etc */
7499 set_local_var(xasprintf("%s=%s", pi->cmds[0].argv[0], *for_lcur++), /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
7500 continue;
7501 }
7502 if (rword == RES_IN) {
7503 continue; /* "for v IN list;..." - "in" has no cmds anyway */
7504 }
7505 if (rword == RES_DONE) {
7506 continue; /* "done" has no cmds too */
7507 }
7508#endif
7509#if ENABLE_HUSH_CASE
7510 if (rword == RES_CASE) {
7511 case_word = expand_strvec_to_string(pi->cmds->argv);
7512 continue;
7513 }
7514 if (rword == RES_MATCH) {
7515 char **argv;
7516
7517 if (!case_word) /* "case ... matched_word) ... WORD)": we executed selected branch, stop */
7518 break;
7519 /* all prev words didn't match, does this one match? */
7520 argv = pi->cmds->argv;
7521 while (*argv) {
7522 char *pattern = expand_string_to_string(*argv, /*unbackslash:*/ 1);
7523 /* TODO: which FNM_xxx flags to use? */
7524 cond_code = (fnmatch(pattern, case_word, /*flags:*/ 0) != 0);
7525 free(pattern);
7526 if (cond_code == 0) { /* match! we will execute this branch */
7527 free(case_word); /* make future "word)" stop */
7528 case_word = NULL;
7529 break;
7530 }
7531 argv++;
7532 }
7533 continue;
7534 }
7535 if (rword == RES_CASE_BODY) { /* inside of a case branch */
7536 if (cond_code != 0)
7537 continue; /* not matched yet, skip this pipe */
7538 }
7539#endif
7540 /* Just pressing <enter> in shell should check for jobs.
7541 * OTOH, in non-interactive shell this is useless
7542 * and only leads to extra job checks */
7543 if (pi->num_cmds == 0) {
7544 if (G_interactive_fd)
7545 goto check_jobs_and_continue;
7546 continue;
7547 }
7548
7549 /* After analyzing all keywords and conditions, we decided
7550 * to execute this pipe. NB: have to do checkjobs(NULL)
7551 * after run_pipe to collect any background children,
7552 * even if list execution is to be stopped. */
7553 debug_printf_exec(": run_pipe with %d members\n", pi->num_cmds);
7554 {
7555 int r;
7556#if ENABLE_HUSH_LOOPS
7557 G.flag_break_continue = 0;
7558#endif
7559 rcode = r = run_pipe(pi); /* NB: rcode is a smallint */
7560 if (r != -1) {
7561 /* We ran a builtin, function, or group.
7562 * rcode is already known
7563 * and we don't need to wait for anything. */
7564 G.last_exitcode = rcode;
7565 debug_printf_exec(": builtin/func exitcode %d\n", rcode);
7566 check_and_run_traps();
7567#if ENABLE_HUSH_LOOPS
7568 /* Was it "break" or "continue"? */
7569 if (G.flag_break_continue) {
7570 smallint fbc = G.flag_break_continue;
7571 /* We might fall into outer *loop*,
7572 * don't want to break it too */
7573 if (loop_top) {
7574 G.depth_break_continue--;
7575 if (G.depth_break_continue == 0)
7576 G.flag_break_continue = 0;
7577 /* else: e.g. "continue 2" should *break* once, *then* continue */
7578 } /* else: "while... do... { we are here (innermost list is not a loop!) };...done" */
7579 if (G.depth_break_continue != 0 || fbc == BC_BREAK) {
7580 checkjobs(NULL);
7581 break;
7582 }
7583 /* "continue": simulate end of loop */
7584 rword = RES_DONE;
7585 continue;
7586 }
7587#endif
7588#if ENABLE_HUSH_FUNCTIONS
7589 if (G.flag_return_in_progress == 1) {
7590 checkjobs(NULL);
7591 break;
7592 }
7593#endif
7594 } else if (pi->followup == PIPE_BG) {
7595 /* What does bash do with attempts to background builtins? */
7596 /* even bash 3.2 doesn't do that well with nested bg:
7597 * try "{ { sleep 10; echo DEEP; } & echo HERE; } &".
7598 * I'm NOT treating inner &'s as jobs */
7599 check_and_run_traps();
7600#if ENABLE_HUSH_JOB
7601 if (G.run_list_level == 1)
7602 insert_bg_job(pi);
7603#endif
7604 /* Last command's pid goes to $! */
7605 G.last_bg_pid = pi->cmds[pi->num_cmds - 1].pid;
7606 G.last_exitcode = rcode = EXIT_SUCCESS;
7607 debug_printf_exec(": cmd&: exitcode EXIT_SUCCESS\n");
7608 } else {
7609#if ENABLE_HUSH_JOB
7610 if (G.run_list_level == 1 && G_interactive_fd) {
7611 /* Waits for completion, then fg's main shell */
7612 rcode = checkjobs_and_fg_shell(pi);
7613 debug_printf_exec(": checkjobs_and_fg_shell exitcode %d\n", rcode);
7614 check_and_run_traps();
7615 } else
7616#endif
7617 { /* This one just waits for completion */
7618 rcode = checkjobs(pi);
7619 debug_printf_exec(": checkjobs exitcode %d\n", rcode);
7620 check_and_run_traps();
7621 }
7622 G.last_exitcode = rcode;
7623 }
7624 }
7625
7626 /* Analyze how result affects subsequent commands */
7627#if ENABLE_HUSH_IF
7628 if (rword == RES_IF || rword == RES_ELIF)
7629 cond_code = rcode;
7630#endif
7631 check_jobs_and_continue:
7632 checkjobs(NULL);
7633 dont_check_jobs_but_continue: ;
7634#if ENABLE_HUSH_LOOPS
7635 /* Beware of "while false; true; do ..."! */
7636 if (pi->next
7637 && (pi->next->res_word == RES_DO || pi->next->res_word == RES_DONE)
7638 /* check for RES_DONE is needed for "while ...; do \n done" case */
7639 ) {
7640 if (rword == RES_WHILE) {
7641 if (rcode) {
7642 /* "while false; do...done" - exitcode 0 */
7643 G.last_exitcode = rcode = EXIT_SUCCESS;
7644 debug_printf_exec(": while expr is false: breaking (exitcode:EXIT_SUCCESS)\n");
7645 break;
7646 }
7647 }
7648 if (rword == RES_UNTIL) {
7649 if (!rcode) {
7650 debug_printf_exec(": until expr is true: breaking\n");
7651 break;
7652 }
7653 }
7654 }
7655#endif
7656 } /* for (pi) */
7657
7658#if ENABLE_HUSH_JOB
7659 G.run_list_level--;
7660#endif
7661#if ENABLE_HUSH_LOOPS
7662 if (loop_top)
7663 G.depth_of_loop--;
7664 free(for_list);
7665#endif
7666#if ENABLE_HUSH_CASE
7667 free(case_word);
7668#endif
7669 debug_leave();
7670 debug_printf_exec("run_list lvl %d return %d\n", G.run_list_level + 1, rcode);
7671 return rcode;
7672}
7673
7674/* Select which version we will use */
7675static int run_and_free_list(struct pipe *pi)
7676{
7677 int rcode = 0;
7678 debug_printf_exec("run_and_free_list entered\n");
7679 if (!G.o_opt[OPT_O_NOEXEC]) {
7680 debug_printf_exec(": run_list: 1st pipe with %d cmds\n", pi->num_cmds);
7681 rcode = run_list(pi);
7682 }
7683 /* free_pipe_list has the side effect of clearing memory.
7684 * In the long run that function can be merged with run_list,
7685 * but doing that now would hobble the debugging effort. */
7686 free_pipe_list(pi);
7687 debug_printf_exec("run_and_free_list return %d\n", rcode);
7688 return rcode;
7689}
7690
7691
7692static void install_sighandlers(unsigned mask)
7693{
7694 sighandler_t old_handler;
7695 unsigned sig = 0;
7696 while ((mask >>= 1) != 0) {
7697 sig++;
7698 if (!(mask & 1))
7699 continue;
7700 old_handler = install_sighandler(sig, pick_sighandler(sig));
7701 /* POSIX allows shell to re-enable SIGCHLD
7702 * even if it was SIG_IGN on entry.
7703 * Therefore we skip IGN check for it:
7704 */
7705 if (sig == SIGCHLD)
7706 continue;
7707 if (old_handler == SIG_IGN) {
7708 /* oops... restore back to IGN, and record this fact */
7709 install_sighandler(sig, old_handler);
7710 if (!G.traps)
7711 G.traps = xzalloc(sizeof(G.traps[0]) * NSIG);
7712 free(G.traps[sig]);
7713 G.traps[sig] = xzalloc(1); /* == xstrdup(""); */
7714 }
7715 }
7716}
7717
7718/* Called a few times only (or even once if "sh -c") */
7719static void install_special_sighandlers(void)
7720{
7721 unsigned mask;
7722
7723 /* Which signals are shell-special? */
7724 mask = (1 << SIGQUIT) | (1 << SIGCHLD);
7725 if (G_interactive_fd) {
7726 mask |= SPECIAL_INTERACTIVE_SIGS;
7727 if (G_saved_tty_pgrp) /* we have ctty, job control sigs work */
7728 mask |= SPECIAL_JOBSTOP_SIGS;
7729 }
7730 /* Careful, do not re-install handlers we already installed */
7731 if (G.special_sig_mask != mask) {
7732 unsigned diff = mask & ~G.special_sig_mask;
7733 G.special_sig_mask = mask;
7734 install_sighandlers(diff);
7735 }
7736}
7737
7738#if ENABLE_HUSH_JOB
7739/* helper */
7740/* Set handlers to restore tty pgrp and exit */
7741static void install_fatal_sighandlers(void)
7742{
7743 unsigned mask;
7744
7745 /* We will restore tty pgrp on these signals */
7746 mask = 0
7747 + (1 << SIGILL ) * HUSH_DEBUG
7748 + (1 << SIGFPE ) * HUSH_DEBUG
7749 + (1 << SIGBUS ) * HUSH_DEBUG
7750 + (1 << SIGSEGV) * HUSH_DEBUG
7751 + (1 << SIGTRAP) * HUSH_DEBUG
7752 + (1 << SIGABRT)
7753 /* bash 3.2 seems to handle these just like 'fatal' ones */
7754 + (1 << SIGPIPE)
7755 + (1 << SIGALRM)
7756 /* if we are interactive, SIGHUP, SIGTERM and SIGINT are special sigs.
7757 * if we aren't interactive... but in this case
7758 * we never want to restore pgrp on exit, and this fn is not called
7759 */
7760 /*+ (1 << SIGHUP )*/
7761 /*+ (1 << SIGTERM)*/
7762 /*+ (1 << SIGINT )*/
7763 ;
7764 G_fatal_sig_mask = mask;
7765
7766 install_sighandlers(mask);
7767}
7768#endif
7769
7770static int set_mode(int state, char mode, const char *o_opt)
7771{
7772 int idx;
7773 switch (mode) {
7774 case 'n':
7775 G.o_opt[OPT_O_NOEXEC] = state;
7776 break;
7777 case 'x':
7778 IF_HUSH_MODE_X(G_x_mode = state;)
7779 break;
7780 case 'o':
7781 if (!o_opt) {
7782 /* "set -+o" without parameter.
7783 * in bash, set -o produces this output:
7784 * pipefail off
7785 * and set +o:
7786 * set +o pipefail
7787 * We always use the second form.
7788 */
7789 const char *p = o_opt_strings;
7790 idx = 0;
7791 while (*p) {
7792 printf("set %co %s\n", (G.o_opt[idx] ? '-' : '+'), p);
7793 idx++;
7794 p += strlen(p) + 1;
7795 }
7796 break;
7797 }
7798 idx = index_in_strings(o_opt_strings, o_opt);
7799 if (idx >= 0) {
7800 G.o_opt[idx] = state;
7801 break;
7802 }
7803 default:
7804 return EXIT_FAILURE;
7805 }
7806 return EXIT_SUCCESS;
7807}
7808
7809int hush_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
7810int hush_main(int argc, char **argv)
7811{
7812 enum {
7813 OPT_login = (1 << 0),
7814 };
7815 unsigned flags;
7816 int opt;
7817 unsigned builtin_argc;
7818 char **e;
7819 struct variable *cur_var;
7820 struct variable *shell_ver;
7821
7822 INIT_G();
7823 if (EXIT_SUCCESS != 0) /* if EXIT_SUCCESS == 0, it is already done */
7824 G.last_exitcode = EXIT_SUCCESS;
7825
7826#if ENABLE_HUSH_FAST
7827 G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
7828#endif
7829#if !BB_MMU
7830 G.argv0_for_re_execing = argv[0];
7831#endif
7832 /* Deal with HUSH_VERSION */
7833 shell_ver = xzalloc(sizeof(*shell_ver));
7834 shell_ver->flg_export = 1;
7835 shell_ver->flg_read_only = 1;
7836 /* Code which handles ${var<op>...} needs writable values for all variables,
7837 * therefore we xstrdup: */
7838 shell_ver->varstr = xstrdup(hush_version_str);
7839 /* Create shell local variables from the values
7840 * currently living in the environment */
7841 debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION");
7842 unsetenv("HUSH_VERSION"); /* in case it exists in initial env */
7843 G.top_var = shell_ver;
7844 cur_var = G.top_var;
7845 e = environ;
7846 if (e) while (*e) {
7847 char *value = strchr(*e, '=');
7848 if (value) { /* paranoia */
7849 cur_var->next = xzalloc(sizeof(*cur_var));
7850 cur_var = cur_var->next;
7851 cur_var->varstr = *e;
7852 cur_var->max_len = strlen(*e);
7853 cur_var->flg_export = 1;
7854 }
7855 e++;
7856 }
7857 /* (Re)insert HUSH_VERSION into env (AFTER we scanned the env!) */
7858 debug_printf_env("putenv '%s'\n", shell_ver->varstr);
7859 putenv(shell_ver->varstr);
7860
7861 /* Export PWD */
7862 set_pwd_var(/*exp:*/ 1);
7863
7864#if ENABLE_HUSH_BASH_COMPAT
7865 /* Set (but not export) HOSTNAME unless already set */
7866 if (!get_local_var_value("HOSTNAME")) {
7867 struct utsname uts;
7868 uname(&uts);
7869 set_local_var_from_halves("HOSTNAME", uts.nodename);
7870 }
7871 /* bash also exports SHLVL and _,
7872 * and sets (but doesn't export) the following variables:
7873 * BASH=/bin/bash
7874 * BASH_VERSINFO=([0]="3" [1]="2" [2]="0" [3]="1" [4]="release" [5]="i386-pc-linux-gnu")
7875 * BASH_VERSION='3.2.0(1)-release'
7876 * HOSTTYPE=i386
7877 * MACHTYPE=i386-pc-linux-gnu
7878 * OSTYPE=linux-gnu
7879 * PPID=<NNNNN> - we also do it elsewhere
7880 * EUID=<NNNNN>
7881 * UID=<NNNNN>
7882 * GROUPS=()
7883 * LINES=<NNN>
7884 * COLUMNS=<NNN>
7885 * BASH_ARGC=()
7886 * BASH_ARGV=()
7887 * BASH_LINENO=()
7888 * BASH_SOURCE=()
7889 * DIRSTACK=()
7890 * PIPESTATUS=([0]="0")
7891 * HISTFILE=/<xxx>/.bash_history
7892 * HISTFILESIZE=500
7893 * HISTSIZE=500
7894 * MAILCHECK=60
7895 * PATH=/usr/gnu/bin:/usr/local/bin:/bin:/usr/bin:.
7896 * SHELL=/bin/bash
7897 * SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
7898 * TERM=dumb
7899 * OPTERR=1
7900 * OPTIND=1
7901 * IFS=$' \t\n'
7902 * PS1='\s-\v\$ '
7903 * PS2='> '
7904 * PS4='+ '
7905 */
7906#endif
7907
7908#if ENABLE_FEATURE_EDITING
7909 G.line_input_state = new_line_input_t(FOR_SHELL);
7910#endif
7911
7912 /* Initialize some more globals to non-zero values */
7913 cmdedit_update_prompt();
7914
7915 die_func = restore_ttypgrp_and__exit;
7916
7917 /* Shell is non-interactive at first. We need to call
7918 * install_special_sighandlers() if we are going to execute "sh <script>",
7919 * "sh -c <cmds>" or login shell's /etc/profile and friends.
7920 * If we later decide that we are interactive, we run install_special_sighandlers()
7921 * in order to intercept (more) signals.
7922 */
7923
7924 /* Parse options */
7925 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */
7926 flags = (argv[0] && argv[0][0] == '-') ? OPT_login : 0;
7927 builtin_argc = 0;
7928 while (1) {
7929 opt = getopt(argc, argv, "+c:xinsl"
7930#if !BB_MMU
7931 "<:$:R:V:"
7932# if ENABLE_HUSH_FUNCTIONS
7933 "F:"
7934# endif
7935#endif
7936 );
7937 if (opt <= 0)
7938 break;
7939 switch (opt) {
7940 case 'c':
7941 /* Possibilities:
7942 * sh ... -c 'script'
7943 * sh ... -c 'script' ARG0 [ARG1...]
7944 * On NOMMU, if builtin_argc != 0,
7945 * sh ... -c 'builtin' BARGV... "" ARG0 [ARG1...]
7946 * "" needs to be replaced with NULL
7947 * and BARGV vector fed to builtin function.
7948 * Note: the form without ARG0 never happens:
7949 * sh ... -c 'builtin' BARGV... ""
7950 */
7951 if (!G.root_pid) {
7952 G.root_pid = getpid();
7953 G.root_ppid = getppid();
7954 }
7955 G.global_argv = argv + optind;
7956 G.global_argc = argc - optind;
7957 if (builtin_argc) {
7958 /* -c 'builtin' [BARGV...] "" ARG0 [ARG1...] */
7959 const struct built_in_command *x;
7960
7961 install_special_sighandlers();
7962 x = find_builtin(optarg);
7963 if (x) { /* paranoia */
7964 G.global_argc -= builtin_argc; /* skip [BARGV...] "" */
7965 G.global_argv += builtin_argc;
7966 G.global_argv[-1] = NULL; /* replace "" */
7967 fflush_all();
7968 G.last_exitcode = x->b_function(argv + optind - 1);
7969 }
7970 goto final_return;
7971 }
7972 if (!G.global_argv[0]) {
7973 /* -c 'script' (no params): prevent empty $0 */
7974 G.global_argv--; /* points to argv[i] of 'script' */
7975 G.global_argv[0] = argv[0];
7976 G.global_argc++;
7977 } /* else -c 'script' ARG0 [ARG1...]: $0 is ARG0 */
7978 install_special_sighandlers();
7979 parse_and_run_string(optarg);
7980 goto final_return;
7981 case 'i':
7982 /* Well, we cannot just declare interactiveness,
7983 * we have to have some stuff (ctty, etc) */
7984 /* G_interactive_fd++; */
7985 break;
7986 case 's':
7987 /* "-s" means "read from stdin", but this is how we always
7988 * operate, so simply do nothing here. */
7989 break;
7990 case 'l':
7991 flags |= OPT_login;
7992 break;
7993#if !BB_MMU
7994 case '<': /* "big heredoc" support */
7995 full_write1_str(optarg);
7996 _exit(0);
7997 case '$': {
7998 unsigned long long empty_trap_mask;
7999
8000 G.root_pid = bb_strtou(optarg, &optarg, 16);
8001 optarg++;
8002 G.root_ppid = bb_strtou(optarg, &optarg, 16);
8003 optarg++;
8004 G.last_bg_pid = bb_strtou(optarg, &optarg, 16);
8005 optarg++;
8006 G.last_exitcode = bb_strtou(optarg, &optarg, 16);
8007 optarg++;
8008 builtin_argc = bb_strtou(optarg, &optarg, 16);
8009 optarg++;
8010 empty_trap_mask = bb_strtoull(optarg, &optarg, 16);
8011 if (empty_trap_mask != 0) {
8012 int sig;
8013 install_special_sighandlers();
8014 G.traps = xzalloc(sizeof(G.traps[0]) * NSIG);
8015 for (sig = 1; sig < NSIG; sig++) {
8016 if (empty_trap_mask & (1LL << sig)) {
8017 G.traps[sig] = xzalloc(1); /* == xstrdup(""); */
8018 install_sighandler(sig, SIG_IGN);
8019 }
8020 }
8021 }
8022# if ENABLE_HUSH_LOOPS
8023 optarg++;
8024 G.depth_of_loop = bb_strtou(optarg, &optarg, 16);
8025# endif
8026 break;
8027 }
8028 case 'R':
8029 case 'V':
8030 set_local_var(xstrdup(optarg), /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ opt == 'R');
8031 break;
8032# if ENABLE_HUSH_FUNCTIONS
8033 case 'F': {
8034 struct function *funcp = new_function(optarg);
8035 /* funcp->name is already set to optarg */
8036 /* funcp->body is set to NULL. It's a special case. */
8037 funcp->body_as_string = argv[optind];
8038 optind++;
8039 break;
8040 }
8041# endif
8042#endif
8043 case 'n':
8044 case 'x':
8045 if (set_mode(1, opt, NULL) == 0) /* no error */
8046 break;
8047 default:
8048#ifndef BB_VER
8049 fprintf(stderr, "Usage: sh [FILE]...\n"
8050 " or: sh -c command [args]...\n\n");
8051 exit(EXIT_FAILURE);
8052#else
8053 bb_show_usage();
8054#endif
8055 }
8056 } /* option parsing loop */
8057
8058 /* Skip options. Try "hush -l": $1 should not be "-l"! */
8059 G.global_argc = argc - (optind - 1);
8060 G.global_argv = argv + (optind - 1);
8061 G.global_argv[0] = argv[0];
8062
8063 if (!G.root_pid) {
8064 G.root_pid = getpid();
8065 G.root_ppid = getppid();
8066 }
8067
8068 /* If we are login shell... */
8069 if (flags & OPT_login) {
8070 FILE *input;
8071 debug_printf("sourcing /etc/profile\n");
8072 input = fopen_for_read("/etc/profile");
8073 if (input != NULL) {
8074 close_on_exec_on(fileno(input));
8075 install_special_sighandlers();
8076 parse_and_run_file(input);
8077 fclose(input);
8078 }
8079 /* bash: after sourcing /etc/profile,
8080 * tries to source (in the given order):
8081 * ~/.bash_profile, ~/.bash_login, ~/.profile,
8082 * stopping on first found. --noprofile turns this off.
8083 * bash also sources ~/.bash_logout on exit.
8084 * If called as sh, skips .bash_XXX files.
8085 */
8086 }
8087
8088 if (G.global_argv[1]) {
8089 FILE *input;
8090 /*
8091 * "bash <script>" (which is never interactive (unless -i?))
8092 * sources $BASH_ENV here (without scanning $PATH).
8093 * If called as sh, does the same but with $ENV.
8094 */
8095 G.global_argc--;
8096 G.global_argv++;
8097 debug_printf("running script '%s'\n", G.global_argv[0]);
8098 input = xfopen_for_read(G.global_argv[0]);
8099 close_on_exec_on(fileno(input));
8100 install_special_sighandlers();
8101 parse_and_run_file(input);
8102#if ENABLE_FEATURE_CLEAN_UP
8103 fclose(input);
8104#endif
8105 goto final_return;
8106 }
8107
8108 /* Up to here, shell was non-interactive. Now it may become one.
8109 * NB: don't forget to (re)run install_special_sighandlers() as needed.
8110 */
8111
8112 /* A shell is interactive if the '-i' flag was given,
8113 * or if all of the following conditions are met:
8114 * no -c command
8115 * no arguments remaining or the -s flag given
8116 * standard input is a terminal
8117 * standard output is a terminal
8118 * Refer to Posix.2, the description of the 'sh' utility.
8119 */
8120#if ENABLE_HUSH_JOB
8121 if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
8122 G_saved_tty_pgrp = tcgetpgrp(STDIN_FILENO);
8123 debug_printf("saved_tty_pgrp:%d\n", G_saved_tty_pgrp);
8124 if (G_saved_tty_pgrp < 0)
8125 G_saved_tty_pgrp = 0;
8126
8127 /* try to dup stdin to high fd#, >= 255 */
8128 G_interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255);
8129 if (G_interactive_fd < 0) {
8130 /* try to dup to any fd */
8131 G_interactive_fd = dup(STDIN_FILENO);
8132 if (G_interactive_fd < 0) {
8133 /* give up */
8134 G_interactive_fd = 0;
8135 G_saved_tty_pgrp = 0;
8136 }
8137 }
8138// TODO: track & disallow any attempts of user
8139// to (inadvertently) close/redirect G_interactive_fd
8140 }
8141 debug_printf("interactive_fd:%d\n", G_interactive_fd);
8142 if (G_interactive_fd) {
8143 close_on_exec_on(G_interactive_fd);
8144
8145 if (G_saved_tty_pgrp) {
8146 /* If we were run as 'hush &', sleep until we are
8147 * in the foreground (tty pgrp == our pgrp).
8148 * If we get started under a job aware app (like bash),
8149 * make sure we are now in charge so we don't fight over
8150 * who gets the foreground */
8151 while (1) {
8152 pid_t shell_pgrp = getpgrp();
8153 G_saved_tty_pgrp = tcgetpgrp(G_interactive_fd);
8154 if (G_saved_tty_pgrp == shell_pgrp)
8155 break;
8156 /* send TTIN to ourself (should stop us) */
8157 kill(- shell_pgrp, SIGTTIN);
8158 }
8159 }
8160
8161 /* Install more signal handlers */
8162 install_special_sighandlers();
8163
8164 if (G_saved_tty_pgrp) {
8165 /* Set other signals to restore saved_tty_pgrp */
8166 install_fatal_sighandlers();
8167 /* Put ourselves in our own process group
8168 * (bash, too, does this only if ctty is available) */
8169 bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */
8170 /* Grab control of the terminal */
8171 tcsetpgrp(G_interactive_fd, getpid());
8172 }
8173 enable_restore_tty_pgrp_on_exit();
8174
8175# if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0
8176 {
8177 const char *hp = get_local_var_value("HISTFILE");
8178 if (!hp) {
8179 hp = get_local_var_value("HOME");
8180 if (hp)
8181 hp = concat_path_file(hp, ".hush_history");
8182 } else {
8183 hp = xstrdup(hp);
8184 }
8185 if (hp) {
8186 G.line_input_state->hist_file = hp;
8187 //set_local_var(xasprintf("HISTFILE=%s", ...));
8188 }
8189# if ENABLE_FEATURE_SH_HISTFILESIZE
8190 hp = get_local_var_value("HISTFILESIZE");
8191 G.line_input_state->max_history = size_from_HISTFILESIZE(hp);
8192# endif
8193 }
8194# endif
8195 } else {
8196 install_special_sighandlers();
8197 }
8198#elif ENABLE_HUSH_INTERACTIVE
8199 /* No job control compiled in, only prompt/line editing */
8200 if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
8201 G_interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255);
8202 if (G_interactive_fd < 0) {
8203 /* try to dup to any fd */
8204 G_interactive_fd = dup(STDIN_FILENO);
8205 if (G_interactive_fd < 0)
8206 /* give up */
8207 G_interactive_fd = 0;
8208 }
8209 }
8210 if (G_interactive_fd) {
8211 close_on_exec_on(G_interactive_fd);
8212 }
8213 install_special_sighandlers();
8214#else
8215 /* We have interactiveness code disabled */
8216 install_special_sighandlers();
8217#endif
8218 /* bash:
8219 * if interactive but not a login shell, sources ~/.bashrc
8220 * (--norc turns this off, --rcfile <file> overrides)
8221 */
8222
8223 if (!ENABLE_FEATURE_SH_EXTRA_QUIET && G_interactive_fd) {
8224 /* note: ash and hush share this string */
8225 printf("\n\n%s %s\n"
8226 IF_HUSH_HELP("Enter 'help' for a list of built-in commands.\n")
8227 "\n",
8228 bb_banner,
8229 "hush - the humble shell"
8230 );
8231 }
8232
8233 parse_and_run_file(stdin);
8234
8235 final_return:
8236 hush_exit(G.last_exitcode);
8237}
8238
8239
8240#if ENABLE_MSH
8241int msh_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
8242int msh_main(int argc, char **argv)
8243{
8244 //bb_error_msg("msh is deprecated, please use hush instead");
8245 return hush_main(argc, argv);
8246}
8247#endif
8248
8249
8250/*
8251 * Built-ins
8252 */
8253static int FAST_FUNC builtin_true(char **argv UNUSED_PARAM)
8254{
8255 return 0;
8256}
8257
8258static int run_applet_main(char **argv, int (*applet_main_func)(int argc, char **argv))
8259{
8260 int argc = 0;
8261 while (*argv) {
8262 argc++;
8263 argv++;
8264 }
8265 return applet_main_func(argc, argv - argc);
8266}
8267
8268static int FAST_FUNC builtin_test(char **argv)
8269{
8270 return run_applet_main(argv, test_main);
8271}
8272
8273static int FAST_FUNC builtin_echo(char **argv)
8274{
8275 return run_applet_main(argv, echo_main);
8276}
8277
8278#if ENABLE_PRINTF
8279static int FAST_FUNC builtin_printf(char **argv)
8280{
8281 return run_applet_main(argv, printf_main);
8282}
8283#endif
8284
8285static char **skip_dash_dash(char **argv)
8286{
8287 argv++;
8288 if (argv[0] && argv[0][0] == '-' && argv[0][1] == '-' && argv[0][2] == '\0')
8289 argv++;
8290 return argv;
8291}
8292
8293static int FAST_FUNC builtin_eval(char **argv)
8294{
8295 int rcode = EXIT_SUCCESS;
8296
8297 argv = skip_dash_dash(argv);
8298 if (*argv) {
8299 char *str = expand_strvec_to_string(argv);
8300 /* bash:
8301 * eval "echo Hi; done" ("done" is syntax error):
8302 * "echo Hi" will not execute too.
8303 */
8304 parse_and_run_string(str);
8305 free(str);
8306 rcode = G.last_exitcode;
8307 }
8308 return rcode;
8309}
8310
8311static int FAST_FUNC builtin_cd(char **argv)
8312{
8313 const char *newdir;
8314
8315 argv = skip_dash_dash(argv);
8316 newdir = argv[0];
8317 if (newdir == NULL) {
8318 /* bash does nothing (exitcode 0) if HOME is ""; if it's unset,
8319 * bash says "bash: cd: HOME not set" and does nothing
8320 * (exitcode 1)
8321 */
8322 const char *home = get_local_var_value("HOME");
8323 newdir = home ? home : "/";
8324 }
8325 if (chdir(newdir)) {
8326 /* Mimic bash message exactly */
8327 bb_perror_msg("cd: %s", newdir);
8328 return EXIT_FAILURE;
8329 }
8330 /* Read current dir (get_cwd(1) is inside) and set PWD.
8331 * Note: do not enforce exporting. If PWD was unset or unexported,
8332 * set it again, but do not export. bash does the same.
8333 */
8334 set_pwd_var(/*exp:*/ 0);
8335 return EXIT_SUCCESS;
8336}
8337
8338static int FAST_FUNC builtin_exec(char **argv)
8339{
8340 argv = skip_dash_dash(argv);
8341 if (argv[0] == NULL)
8342 return EXIT_SUCCESS; /* bash does this */
8343
8344 /* Careful: we can end up here after [v]fork. Do not restore
8345 * tty pgrp then, only top-level shell process does that */
8346 if (G_saved_tty_pgrp && getpid() == G.root_pid)
8347 tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp);
8348
8349 /* TODO: if exec fails, bash does NOT exit! We do.
8350 * We'll need to undo trap cleanup (it's inside execvp_or_die)
8351 * and tcsetpgrp, and this is inherently racy.
8352 */
8353 execvp_or_die(argv);
8354}
8355
8356static int FAST_FUNC builtin_exit(char **argv)
8357{
8358 debug_printf_exec("%s()\n", __func__);
8359
8360 /* interactive bash:
8361 * # trap "echo EEE" EXIT
8362 * # exit
8363 * exit
8364 * There are stopped jobs.
8365 * (if there are _stopped_ jobs, running ones don't count)
8366 * # exit
8367 * exit
8368 * EEE (then bash exits)
8369 *
8370 * TODO: we can use G.exiting = -1 as indicator "last cmd was exit"
8371 */
8372
8373 /* note: EXIT trap is run by hush_exit */
8374 argv = skip_dash_dash(argv);
8375 if (argv[0] == NULL)
8376 hush_exit(G.last_exitcode);
8377 /* mimic bash: exit 123abc == exit 255 + error msg */
8378 xfunc_error_retval = 255;
8379 /* bash: exit -2 == exit 254, no error msg */
8380 hush_exit(xatoi(argv[0]) & 0xff);
8381}
8382
8383static void print_escaped(const char *s)
8384{
8385 if (*s == '\'')
8386 goto squote;
8387 do {
8388 const char *p = strchrnul(s, '\'');
8389 /* print 'xxxx', possibly just '' */
8390 printf("'%.*s'", (int)(p - s), s);
8391 if (*p == '\0')
8392 break;
8393 s = p;
8394 squote:
8395 /* s points to '; print "'''...'''" */
8396 putchar('"');
8397 do putchar('\''); while (*++s == '\'');
8398 putchar('"');
8399 } while (*s);
8400}
8401
8402#if !ENABLE_HUSH_LOCAL
8403#define helper_export_local(argv, exp, lvl) \
8404 helper_export_local(argv, exp)
8405#endif
8406static void helper_export_local(char **argv, int exp, int lvl)
8407{
8408 do {
8409 char *name = *argv;
8410 char *name_end = strchrnul(name, '=');
8411
8412 /* So far we do not check that name is valid (TODO?) */
8413
8414 if (*name_end == '\0') {
8415 struct variable *var, **vpp;
8416
8417 vpp = get_ptr_to_local_var(name, name_end - name);
8418 var = vpp ? *vpp : NULL;
8419
8420 if (exp == -1) { /* unexporting? */
8421 /* export -n NAME (without =VALUE) */
8422 if (var) {
8423 var->flg_export = 0;
8424 debug_printf_env("%s: unsetenv '%s'\n", __func__, name);
8425 unsetenv(name);
8426 } /* else: export -n NOT_EXISTING_VAR: no-op */
8427 continue;
8428 }
8429 if (exp == 1) { /* exporting? */
8430 /* export NAME (without =VALUE) */
8431 if (var) {
8432 var->flg_export = 1;
8433 debug_printf_env("%s: putenv '%s'\n", __func__, var->varstr);
8434 putenv(var->varstr);
8435 continue;
8436 }
8437 }
8438 /* Exporting non-existing variable.
8439 * bash does not put it in environment,
8440 * but remembers that it is exported,
8441 * and does put it in env when it is set later.
8442 * We just set it to "" and export. */
8443 /* Or, it's "local NAME" (without =VALUE).
8444 * bash sets the value to "". */
8445 name = xasprintf("%s=", name);
8446 } else {
8447 /* (Un)exporting/making local NAME=VALUE */
8448 name = xstrdup(name);
8449 }
8450 set_local_var(name, /*exp:*/ exp, /*lvl:*/ lvl, /*ro:*/ 0);
8451 } while (*++argv);
8452}
8453
8454static int FAST_FUNC builtin_export(char **argv)
8455{
8456 unsigned opt_unexport;
8457
8458#if ENABLE_HUSH_EXPORT_N
8459 /* "!": do not abort on errors */
8460 opt_unexport = getopt32(argv, "!n");
8461 if (opt_unexport == (uint32_t)-1)
8462 return EXIT_FAILURE;
8463 argv += optind;
8464#else
8465 opt_unexport = 0;
8466 argv++;
8467#endif
8468
8469 if (argv[0] == NULL) {
8470 char **e = environ;
8471 if (e) {
8472 while (*e) {
8473#if 0
8474 puts(*e++);
8475#else
8476 /* ash emits: export VAR='VAL'
8477 * bash: declare -x VAR="VAL"
8478 * we follow ash example */
8479 const char *s = *e++;
8480 const char *p = strchr(s, '=');
8481
8482 if (!p) /* wtf? take next variable */
8483 continue;
8484 /* export var= */
8485 printf("export %.*s", (int)(p - s) + 1, s);
8486 print_escaped(p + 1);
8487 putchar('\n');
8488#endif
8489 }
8490 /*fflush_all(); - done after each builtin anyway */
8491 }
8492 return EXIT_SUCCESS;
8493 }
8494
8495 helper_export_local(argv, (opt_unexport ? -1 : 1), 0);
8496
8497 return EXIT_SUCCESS;
8498}
8499
8500#if ENABLE_HUSH_LOCAL
8501static int FAST_FUNC builtin_local(char **argv)
8502{
8503 if (G.func_nest_level == 0) {
8504 bb_error_msg("%s: not in a function", argv[0]);
8505 return EXIT_FAILURE; /* bash compat */
8506 }
8507 helper_export_local(argv, 0, G.func_nest_level);
8508 return EXIT_SUCCESS;
8509}
8510#endif
8511
8512static int FAST_FUNC builtin_trap(char **argv)
8513{
8514 int sig;
8515 char *new_cmd;
8516
8517 if (!G.traps)
8518 G.traps = xzalloc(sizeof(G.traps[0]) * NSIG);
8519
8520 argv++;
8521 if (!*argv) {
8522 int i;
8523 /* No args: print all trapped */
8524 for (i = 0; i < NSIG; ++i) {
8525 if (G.traps[i]) {
8526 printf("trap -- ");
8527 print_escaped(G.traps[i]);
8528 /* note: bash adds "SIG", but only if invoked
8529 * as "bash". If called as "sh", or if set -o posix,
8530 * then it prints short signal names.
8531 * We are printing short names: */
8532 printf(" %s\n", get_signame(i));
8533 }
8534 }
8535 /*fflush_all(); - done after each builtin anyway */
8536 return EXIT_SUCCESS;
8537 }
8538
8539 new_cmd = NULL;
8540 /* If first arg is a number: reset all specified signals */
8541 sig = bb_strtou(*argv, NULL, 10);
8542 if (errno == 0) {
8543 int ret;
8544 process_sig_list:
8545 ret = EXIT_SUCCESS;
8546 while (*argv) {
8547 sighandler_t handler;
8548
8549 sig = get_signum(*argv++);
8550 if (sig < 0 || sig >= NSIG) {
8551 ret = EXIT_FAILURE;
8552 /* Mimic bash message exactly */
8553 bb_perror_msg("trap: %s: invalid signal specification", argv[-1]);
8554 continue;
8555 }
8556
8557 free(G.traps[sig]);
8558 G.traps[sig] = xstrdup(new_cmd);
8559
8560 debug_printf("trap: setting SIG%s (%i) to '%s'\n",
8561 get_signame(sig), sig, G.traps[sig]);
8562
8563 /* There is no signal for 0 (EXIT) */
8564 if (sig == 0)
8565 continue;
8566
8567 if (new_cmd)
8568 handler = (new_cmd[0] ? record_pending_signo : SIG_IGN);
8569 else
8570 /* We are removing trap handler */
8571 handler = pick_sighandler(sig);
8572 install_sighandler(sig, handler);
8573 }
8574 return ret;
8575 }
8576
8577 if (!argv[1]) { /* no second arg */
8578 bb_error_msg("trap: invalid arguments");
8579 return EXIT_FAILURE;
8580 }
8581
8582 /* First arg is "-": reset all specified to default */
8583 /* First arg is "--": skip it, the rest is "handler SIGs..." */
8584 /* Everything else: set arg as signal handler
8585 * (includes "" case, which ignores signal) */
8586 if (argv[0][0] == '-') {
8587 if (argv[0][1] == '\0') { /* "-" */
8588 /* new_cmd remains NULL: "reset these sigs" */
8589 goto reset_traps;
8590 }
8591 if (argv[0][1] == '-' && argv[0][2] == '\0') { /* "--" */
8592 argv++;
8593 }
8594 /* else: "-something", no special meaning */
8595 }
8596 new_cmd = *argv;
8597 reset_traps:
8598 argv++;
8599 goto process_sig_list;
8600}
8601
8602/* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */
8603static int FAST_FUNC builtin_type(char **argv)
8604{
8605 int ret = EXIT_SUCCESS;
8606
8607 while (*++argv) {
8608 const char *type;
8609 char *path = NULL;
8610
8611 if (0) {} /* make conditional compile easier below */
8612 /*else if (find_alias(*argv))
8613 type = "an alias";*/
8614#if ENABLE_HUSH_FUNCTIONS
8615 else if (find_function(*argv))
8616 type = "a function";
8617#endif
8618 else if (find_builtin(*argv))
8619 type = "a shell builtin";
8620 else if ((path = find_in_path(*argv)) != NULL)
8621 type = path;
8622 else {
8623 bb_error_msg("type: %s: not found", *argv);
8624 ret = EXIT_FAILURE;
8625 continue;
8626 }
8627
8628 printf("%s is %s\n", *argv, type);
8629 free(path);
8630 }
8631
8632 return ret;
8633}
8634
8635#if ENABLE_HUSH_JOB
8636/* built-in 'fg' and 'bg' handler */
8637static int FAST_FUNC builtin_fg_bg(char **argv)
8638{
8639 int i, jobnum;
8640 struct pipe *pi;
8641
8642 if (!G_interactive_fd)
8643 return EXIT_FAILURE;
8644
8645 /* If they gave us no args, assume they want the last backgrounded task */
8646 if (!argv[1]) {
8647 for (pi = G.job_list; pi; pi = pi->next) {
8648 if (pi->jobid == G.last_jobid) {
8649 goto found;
8650 }
8651 }
8652 bb_error_msg("%s: no current job", argv[0]);
8653 return EXIT_FAILURE;
8654 }
8655 if (sscanf(argv[1], "%%%d", &jobnum) != 1) {
8656 bb_error_msg("%s: bad argument '%s'", argv[0], argv[1]);
8657 return EXIT_FAILURE;
8658 }
8659 for (pi = G.job_list; pi; pi = pi->next) {
8660 if (pi->jobid == jobnum) {
8661 goto found;
8662 }
8663 }
8664 bb_error_msg("%s: %d: no such job", argv[0], jobnum);
8665 return EXIT_FAILURE;
8666 found:
8667 /* TODO: bash prints a string representation
8668 * of job being foregrounded (like "sleep 1 | cat") */
8669 if (argv[0][0] == 'f' && G_saved_tty_pgrp) {
8670 /* Put the job into the foreground. */
8671 tcsetpgrp(G_interactive_fd, pi->pgrp);
8672 }
8673
8674 /* Restart the processes in the job */
8675 debug_printf_jobs("reviving %d procs, pgrp %d\n", pi->num_cmds, pi->pgrp);
8676 for (i = 0; i < pi->num_cmds; i++) {
8677 debug_printf_jobs("reviving pid %d\n", pi->cmds[i].pid);
8678 }
8679 pi->stopped_cmds = 0;
8680
8681 i = kill(- pi->pgrp, SIGCONT);
8682 if (i < 0) {
8683 if (errno == ESRCH) {
8684 delete_finished_bg_job(pi);
8685 return EXIT_SUCCESS;
8686 }
8687 bb_perror_msg("kill (SIGCONT)");
8688 }
8689
8690 if (argv[0][0] == 'f') {
8691 remove_bg_job(pi);
8692 return checkjobs_and_fg_shell(pi);
8693 }
8694 return EXIT_SUCCESS;
8695}
8696#endif
8697
8698#if ENABLE_HUSH_HELP
8699static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM)
8700{
8701 const struct built_in_command *x;
8702
8703 printf(
8704 "Built-in commands:\n"
8705 "------------------\n");
8706 for (x = bltins1; x != &bltins1[ARRAY_SIZE(bltins1)]; x++) {
8707 if (x->b_descr)
8708 printf("%-10s%s\n", x->b_cmd, x->b_descr);
8709 }
8710 bb_putchar('\n');
8711 return EXIT_SUCCESS;
8712}
8713#endif
8714
8715#if MAX_HISTORY && ENABLE_FEATURE_EDITING
8716static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM)
8717{
8718 show_history(G.line_input_state);
8719 return EXIT_SUCCESS;
8720}
8721#endif
8722
8723#if ENABLE_HUSH_JOB
8724static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM)
8725{
8726 struct pipe *job;
8727 const char *status_string;
8728
8729 for (job = G.job_list; job; job = job->next) {
8730 if (job->alive_cmds == job->stopped_cmds)
8731 status_string = "Stopped";
8732 else
8733 status_string = "Running";
8734
8735 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->cmdtext);
8736 }
8737 return EXIT_SUCCESS;
8738}
8739#endif
8740
8741#if HUSH_DEBUG
8742static int FAST_FUNC builtin_memleak(char **argv UNUSED_PARAM)
8743{
8744 void *p;
8745 unsigned long l;
8746
8747# ifdef M_TRIM_THRESHOLD
8748 /* Optional. Reduces probability of false positives */
8749 malloc_trim(0);
8750# endif
8751 /* Crude attempt to find where "free memory" starts,
8752 * sans fragmentation. */
8753 p = malloc(240);
8754 l = (unsigned long)p;
8755 free(p);
8756 p = malloc(3400);
8757 if (l < (unsigned long)p) l = (unsigned long)p;
8758 free(p);
8759
8760 if (!G.memleak_value)
8761 G.memleak_value = l;
8762
8763 l -= G.memleak_value;
8764 if ((long)l < 0)
8765 l = 0;
8766 l /= 1024;
8767 if (l > 127)
8768 l = 127;
8769
8770 /* Exitcode is "how many kilobytes we leaked since 1st call" */
8771 return l;
8772}
8773#endif
8774
8775static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM)
8776{
8777 puts(get_cwd(0));
8778 return EXIT_SUCCESS;
8779}
8780
8781/* Interruptibility of read builtin in bash
8782 * (tested on bash-4.2.8 by sending signals (not by ^C)):
8783 *
8784 * Empty trap makes read ignore corresponding signal, for any signal.
8785 *
8786 * SIGINT:
8787 * - terminates non-interactive shell;
8788 * - interrupts read in interactive shell;
8789 * if it has non-empty trap:
8790 * - executes trap and returns to command prompt in interactive shell;
8791 * - executes trap and returns to read in non-interactive shell;
8792 * SIGTERM:
8793 * - is ignored (does not interrupt) read in interactive shell;
8794 * - terminates non-interactive shell;
8795 * if it has non-empty trap:
8796 * - executes trap and returns to read;
8797 * SIGHUP:
8798 * - terminates shell (regardless of interactivity);
8799 * if it has non-empty trap:
8800 * - executes trap and returns to read;
8801 */
8802static int FAST_FUNC builtin_read(char **argv)
8803{
8804 const char *r;
8805 char *opt_n = NULL;
8806 char *opt_p = NULL;
8807 char *opt_t = NULL;
8808 char *opt_u = NULL;
8809 const char *ifs;
8810 int read_flags;
8811
8812 /* "!": do not abort on errors.
8813 * Option string must start with "sr" to match BUILTIN_READ_xxx
8814 */
8815 read_flags = getopt32(argv, "!srn:p:t:u:", &opt_n, &opt_p, &opt_t, &opt_u);
8816 if (read_flags == (uint32_t)-1)
8817 return EXIT_FAILURE;
8818 argv += optind;
8819 ifs = get_local_var_value("IFS"); /* can be NULL */
8820
8821 again:
8822 r = shell_builtin_read(set_local_var_from_halves,
8823 argv,
8824 ifs,
8825 read_flags,
8826 opt_n,
8827 opt_p,
8828 opt_t,
8829 opt_u
8830 );
8831
8832 if ((uintptr_t)r == 1 && errno == EINTR) {
8833 unsigned sig = check_and_run_traps();
8834 if (sig && sig != SIGINT)
8835 goto again;
8836 }
8837
8838 if ((uintptr_t)r > 1) {
8839 bb_error_msg("%s", r);
8840 r = (char*)(uintptr_t)1;
8841 }
8842
8843 return (uintptr_t)r;
8844}
8845
8846/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set
8847 * built-in 'set' handler
8848 * SUSv3 says:
8849 * set [-abCefhmnuvx] [-o option] [argument...]
8850 * set [+abCefhmnuvx] [+o option] [argument...]
8851 * set -- [argument...]
8852 * set -o
8853 * set +o
8854 * Implementations shall support the options in both their hyphen and
8855 * plus-sign forms. These options can also be specified as options to sh.
8856 * Examples:
8857 * Write out all variables and their values: set
8858 * Set $1, $2, and $3 and set "$#" to 3: set c a b
8859 * Turn on the -x and -v options: set -xv
8860 * Unset all positional parameters: set --
8861 * Set $1 to the value of x, even if it begins with '-' or '+': set -- "$x"
8862 * Set the positional parameters to the expansion of x, even if x expands
8863 * with a leading '-' or '+': set -- $x
8864 *
8865 * So far, we only support "set -- [argument...]" and some of the short names.
8866 */
8867static int FAST_FUNC builtin_set(char **argv)
8868{
8869 int n;
8870 char **pp, **g_argv;
8871 char *arg = *++argv;
8872
8873 if (arg == NULL) {
8874 struct variable *e;
8875 for (e = G.top_var; e; e = e->next)
8876 puts(e->varstr);
8877 return EXIT_SUCCESS;
8878 }
8879
8880 do {
8881 if (strcmp(arg, "--") == 0) {
8882 ++argv;
8883 goto set_argv;
8884 }
8885 if (arg[0] != '+' && arg[0] != '-')
8886 break;
8887 for (n = 1; arg[n]; ++n) {
8888 if (set_mode((arg[0] == '-'), arg[n], argv[1]))
8889 goto error;
8890 if (arg[n] == 'o' && argv[1])
8891 argv++;
8892 }
8893 } while ((arg = *++argv) != NULL);
8894 /* Now argv[0] is 1st argument */
8895
8896 if (arg == NULL)
8897 return EXIT_SUCCESS;
8898 set_argv:
8899
8900 /* NB: G.global_argv[0] ($0) is never freed/changed */
8901 g_argv = G.global_argv;
8902 if (G.global_args_malloced) {
8903 pp = g_argv;
8904 while (*++pp)
8905 free(*pp);
8906 g_argv[1] = NULL;
8907 } else {
8908 G.global_args_malloced = 1;
8909 pp = xzalloc(sizeof(pp[0]) * 2);
8910 pp[0] = g_argv[0]; /* retain $0 */
8911 g_argv = pp;
8912 }
8913 /* This realloc's G.global_argv */
8914 G.global_argv = pp = add_strings_to_strings(g_argv, argv, /*dup:*/ 1);
8915
8916 n = 1;
8917 while (*++pp)
8918 n++;
8919 G.global_argc = n;
8920
8921 return EXIT_SUCCESS;
8922
8923 /* Nothing known, so abort */
8924 error:
8925 bb_error_msg("set: %s: invalid option", arg);
8926 return EXIT_FAILURE;
8927}
8928
8929static int FAST_FUNC builtin_shift(char **argv)
8930{
8931 int n = 1;
8932 argv = skip_dash_dash(argv);
8933 if (argv[0]) {
8934 n = atoi(argv[0]);
8935 }
8936 if (n >= 0 && n < G.global_argc) {
8937 if (G.global_args_malloced) {
8938 int m = 1;
8939 while (m <= n)
8940 free(G.global_argv[m++]);
8941 }
8942 G.global_argc -= n;
8943 memmove(&G.global_argv[1], &G.global_argv[n+1],
8944 G.global_argc * sizeof(G.global_argv[0]));
8945 return EXIT_SUCCESS;
8946 }
8947 return EXIT_FAILURE;
8948}
8949
8950static int FAST_FUNC builtin_source(char **argv)
8951{
8952 char *arg_path, *filename;
8953 FILE *input;
8954 save_arg_t sv;
8955#if ENABLE_HUSH_FUNCTIONS
8956 smallint sv_flg;
8957#endif
8958
8959 argv = skip_dash_dash(argv);
8960 filename = argv[0];
8961 if (!filename) {
8962 /* bash says: "bash: .: filename argument required" */
8963 return 2; /* bash compat */
8964 }
8965 arg_path = NULL;
8966 if (!strchr(filename, '/')) {
8967 arg_path = find_in_path(filename);
8968 if (arg_path)
8969 filename = arg_path;
8970 }
8971 input = fopen_or_warn(filename, "r");
8972 free(arg_path);
8973 if (!input) {
8974 /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */
8975 /* POSIX: non-interactive shell should abort here,
8976 * not merely fail. So far no one complained :)
8977 */
8978 return EXIT_FAILURE;
8979 }
8980 close_on_exec_on(fileno(input));
8981
8982#if ENABLE_HUSH_FUNCTIONS
8983 sv_flg = G.flag_return_in_progress;
8984 /* "we are inside sourced file, ok to use return" */
8985 G.flag_return_in_progress = -1;
8986#endif
8987 if (argv[1])
8988 save_and_replace_G_args(&sv, argv);
8989
8990 parse_and_run_file(input);
8991 fclose(input);
8992
8993 if (argv[1])
8994 restore_G_args(&sv, argv);
8995#if ENABLE_HUSH_FUNCTIONS
8996 G.flag_return_in_progress = sv_flg;
8997#endif
8998
8999 return G.last_exitcode;
9000}
9001
9002static int FAST_FUNC builtin_umask(char **argv)
9003{
9004 int rc;
9005 mode_t mask;
9006
9007 rc = 1;
9008 mask = umask(0);
9009 argv = skip_dash_dash(argv);
9010 if (argv[0]) {
9011 mode_t old_mask = mask;
9012
9013 /* numeric umasks are taken as-is */
9014 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
9015 if (!isdigit(argv[0][0]))
9016 mask ^= 0777;
9017 mask = bb_parse_mode(argv[0], mask);
9018 if (!isdigit(argv[0][0]))
9019 mask ^= 0777;
9020 if ((unsigned)mask > 0777) {
9021 mask = old_mask;
9022 /* bash messages:
9023 * bash: umask: 'q': invalid symbolic mode operator
9024 * bash: umask: 999: octal number out of range
9025 */
9026 bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]);
9027 rc = 0;
9028 }
9029 } else {
9030 /* Mimic bash */
9031 printf("%04o\n", (unsigned) mask);
9032 /* fall through and restore mask which we set to 0 */
9033 }
9034 umask(mask);
9035
9036 return !rc; /* rc != 0 - success */
9037}
9038
9039/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#unset */
9040static int FAST_FUNC builtin_unset(char **argv)
9041{
9042 int ret;
9043 unsigned opts;
9044
9045 /* "!": do not abort on errors */
9046 /* "+": stop at 1st non-option */
9047 opts = getopt32(argv, "!+vf");
9048 if (opts == (unsigned)-1)
9049 return EXIT_FAILURE;
9050 if (opts == 3) {
9051 bb_error_msg("unset: -v and -f are exclusive");
9052 return EXIT_FAILURE;
9053 }
9054 argv += optind;
9055
9056 ret = EXIT_SUCCESS;
9057 while (*argv) {
9058 if (!(opts & 2)) { /* not -f */
9059 if (unset_local_var(*argv)) {
9060 /* unset <nonexistent_var> doesn't fail.
9061 * Error is when one tries to unset RO var.
9062 * Message was printed by unset_local_var. */
9063 ret = EXIT_FAILURE;
9064 }
9065 }
9066#if ENABLE_HUSH_FUNCTIONS
9067 else {
9068 unset_func(*argv);
9069 }
9070#endif
9071 argv++;
9072 }
9073 return ret;
9074}
9075
9076/* http://www.opengroup.org/onlinepubs/9699919799/utilities/wait.html */
9077static int FAST_FUNC builtin_wait(char **argv)
9078{
9079 int ret = EXIT_SUCCESS;
9080 int status;
9081
9082 argv = skip_dash_dash(argv);
9083 if (argv[0] == NULL) {
9084 /* Don't care about wait results */
9085 /* Note 1: must wait until there are no more children */
9086 /* Note 2: must be interruptible */
9087 /* Examples:
9088 * $ sleep 3 & sleep 6 & wait
9089 * [1] 30934 sleep 3
9090 * [2] 30935 sleep 6
9091 * [1] Done sleep 3
9092 * [2] Done sleep 6
9093 * $ sleep 3 & sleep 6 & wait
9094 * [1] 30936 sleep 3
9095 * [2] 30937 sleep 6
9096 * [1] Done sleep 3
9097 * ^C <-- after ~4 sec from keyboard
9098 * $
9099 */
9100 while (1) {
9101 int sig;
9102 sigset_t oldset, allsigs;
9103
9104 /* waitpid is not interruptible by SA_RESTARTed
9105 * signals which we use. Thus, this ugly dance:
9106 */
9107
9108 /* Make sure possible SIGCHLD is stored in kernel's
9109 * pending signal mask before we call waitpid.
9110 * Or else we may race with SIGCHLD, lose it,
9111 * and get stuck in sigwaitinfo...
9112 */
9113 sigfillset(&allsigs);
9114 sigprocmask(SIG_SETMASK, &allsigs, &oldset);
9115
9116 if (!sigisemptyset(&G.pending_set)) {
9117 /* Crap! we raced with some signal! */
9118 // sig = 0;
9119 goto restore;
9120 }
9121
9122 checkjobs(NULL); /* waitpid(WNOHANG) inside */
9123 if (errno == ECHILD) {
9124 sigprocmask(SIG_SETMASK, &oldset, NULL);
9125 break;
9126 }
9127
9128 /* Wait for SIGCHLD or any other signal */
9129 //sig = sigwaitinfo(&allsigs, NULL);
9130 /* It is vitally important for sigsuspend that SIGCHLD has non-DFL handler! */
9131 /* Note: sigsuspend invokes signal handler */
9132 sigsuspend(&oldset);
9133 restore:
9134 sigprocmask(SIG_SETMASK, &oldset, NULL);
9135
9136 /* So, did we get a signal? */
9137 //if (sig > 0)
9138 // raise(sig); /* run handler */
9139 sig = check_and_run_traps();
9140 if (sig /*&& sig != SIGCHLD - always true */) {
9141 /* see note 2 */
9142 ret = 128 + sig;
9143 break;
9144 }
9145 /* SIGCHLD, or no signal, or ignored one, such as SIGQUIT. Repeat */
9146 }
9147 return ret;
9148 }
9149
9150 /* This is probably buggy wrt interruptible-ness */
9151 while (*argv) {
9152 pid_t pid = bb_strtou(*argv, NULL, 10);
9153 if (errno) {
9154 /* mimic bash message */
9155 bb_error_msg("wait: '%s': not a pid or valid job spec", *argv);
9156 return EXIT_FAILURE;
9157 }
9158 if (waitpid(pid, &status, 0) == pid) {
9159 ret = WEXITSTATUS(status);
9160 if (WIFSIGNALED(status))
9161 ret = 128 + WTERMSIG(status);
9162 } else {
9163 bb_perror_msg("wait %s", *argv);
9164 ret = 127;
9165 }
9166 argv++;
9167 }
9168
9169 return ret;
9170}
9171
9172#if ENABLE_HUSH_LOOPS || ENABLE_HUSH_FUNCTIONS
9173static unsigned parse_numeric_argv1(char **argv, unsigned def, unsigned def_min)
9174{
9175 if (argv[1]) {
9176 def = bb_strtou(argv[1], NULL, 10);
9177 if (errno || def < def_min || argv[2]) {
9178 bb_error_msg("%s: bad arguments", argv[0]);
9179 def = UINT_MAX;
9180 }
9181 }
9182 return def;
9183}
9184#endif
9185
9186#if ENABLE_HUSH_LOOPS
9187static int FAST_FUNC builtin_break(char **argv)
9188{
9189 unsigned depth;
9190 if (G.depth_of_loop == 0) {
9191 bb_error_msg("%s: only meaningful in a loop", argv[0]);
9192 return EXIT_SUCCESS; /* bash compat */
9193 }
9194 G.flag_break_continue++; /* BC_BREAK = 1 */
9195
9196 G.depth_break_continue = depth = parse_numeric_argv1(argv, 1, 1);
9197 if (depth == UINT_MAX)
9198 G.flag_break_continue = BC_BREAK;
9199 if (G.depth_of_loop < depth)
9200 G.depth_break_continue = G.depth_of_loop;
9201
9202 return EXIT_SUCCESS;
9203}
9204
9205static int FAST_FUNC builtin_continue(char **argv)
9206{
9207 G.flag_break_continue = 1; /* BC_CONTINUE = 2 = 1+1 */
9208 return builtin_break(argv);
9209}
9210#endif
9211
9212#if ENABLE_HUSH_FUNCTIONS
9213static int FAST_FUNC builtin_return(char **argv)
9214{
9215 int rc;
9216
9217 if (G.flag_return_in_progress != -1) {
9218 bb_error_msg("%s: not in a function or sourced script", argv[0]);
9219 return EXIT_FAILURE; /* bash compat */
9220 }
9221
9222 G.flag_return_in_progress = 1;
9223
9224 /* bash:
9225 * out of range: wraps around at 256, does not error out
9226 * non-numeric param:
9227 * f() { false; return qwe; }; f; echo $?
9228 * bash: return: qwe: numeric argument required <== we do this
9229 * 255 <== we also do this
9230 */
9231 rc = parse_numeric_argv1(argv, G.last_exitcode, 0);
9232 return rc;
9233}
9234#endif
Note: See TracBrowser for help on using the repository browser.