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

Last change on this file since 3621 was 3621, checked in by Bruno Cornec, 7 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.