Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/shell/hush.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/shell/hush.c
r1765 r2725 1 1 /* vi: set sw=4 ts=4: */ 2 2 /* 3 * sh.c -- a prototype Bourne shell grammar parser4 * 5 * 6 * 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 7 * 8 * Copyright (C) 2000,2001 Larry Doolittle <larry@doolittle.boa.org> 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. 9 12 * 10 13 * Credits: … … 21 24 * 22 25 * Other credits: 23 * b_addchr() derived from similar w_addchar function in glibc-2.224 * setup_redirect(), redirect_opt_num(), and big chunks of main()25 * and many builtins derived from contributions by Erik Andersen 26 * miscellaneous bugfixes from Matt Kraai26 * 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. 27 30 * 28 31 * There are two big (and related) architecture differences between … … 37 40 * across continuation lines. 38 41 * 39 * Bash grammar not implemented: (how many of these were in original sh?) 40 * $_ 41 * ! negation operator for pipes 42 * &> and >& redirection of stdout+stderr 43 * Brace Expansion 44 * Tilde Expansion 45 * fancy forms of Parameter Expansion 42 * TODOs: 43 * grep for "TODO" and fix (some of them are easy) 44 * special variables (done: PWD, PPID, RANDOM) 45 * tilde expansion 46 46 * aliases 47 * Arithmetic Expansion48 * <(list) and >(list) Process Substitution49 * reserved words: case, esac, select, function50 * Here Documents ( << word )51 * Functions52 * Major bugs:53 * job handling woefully incomplete and buggy (improved --vda)54 * reserved word execution woefully incomplete and buggy55 * to-do:56 * port selected bugfixes from post-0.49 busybox lash - done?57 * finish implementing reserved words: for, while, until, do, done58 * change { and } from special chars to reserved words59 * builtins: break, continue, eval, return, set, trap, ulimit60 * test magic exec61 * handle children going into background62 * clean up recognition of null pipes63 * check setting of global_argc and global_argv64 * control-C handling, probably with longjmp65 47 * follow IFS rules more precisely, including update semantics 66 * figure out what to do with backslash-newline 67 * explain why we use signal instead of sigaction 68 * propagate syntax errors, die on resource errors? 69 * continuation lines, both explicit and implicit - done? 70 * memory leak finding and plugging - done? 71 * more testing, especially quoting rules and redirection 72 * document how quoting rules not precisely followed for variable assignments 73 * maybe change charmap[] to use 2-bit entries 74 * (eventually) remove all the printf's 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 75 52 * 76 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. 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 77 83 */ 78 79 80 #include <glob.h> /* glob, of course */ 81 #include <getopt.h> /* should be pretty obvious */ 84 #include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */ 85 #include <malloc.h> /* for malloc_trim */ 86 #include <glob.h> 82 87 /* #include <dmalloc.h> */ 83 84 extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */ 85 86 #include "busybox.h" /* for struct bb_applet */ 87 88 #if ENABLE_HUSH_CASE 89 # include <fnmatch.h> 90 #endif 91 92 #include "shell_common.h" 93 #include "math.h" 94 #include "match.h" 95 #if ENABLE_HUSH_RANDOM_SUPPORT 96 # include "random.h" 97 #else 98 # define CLEAR_RANDOM_T(rnd) ((void)0) 99 #endif 100 #ifndef PIPE_BUF 101 # define PIPE_BUF 4096 /* amount of buffering in a pipe */ 102 #endif 103 104 //applet:IF_HUSH(APPLET(hush, _BB_DIR_BIN, _BB_SUID_DROP)) 105 //applet:IF_MSH(APPLET(msh, _BB_DIR_BIN, _BB_SUID_DROP)) 106 //applet:IF_FEATURE_SH_IS_HUSH(APPLET_ODDNAME(sh, hush, _BB_DIR_BIN, _BB_SUID_DROP, sh)) 107 //applet:IF_FEATURE_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, _BB_DIR_BIN, _BB_SUID_DROP, bash)) 108 109 //kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o 110 //kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o 111 112 //config:config HUSH 113 //config: bool "hush" 114 //config: default y 115 //config: help 116 //config: hush is a small shell (25k). It handles the normal flow control 117 //config: constructs such as if/then/elif/else/fi, for/in/do/done, while loops, 118 //config: case/esac. Redirections, here documents, $((arithmetic)) 119 //config: and functions are supported. 120 //config: 121 //config: It will compile and work on no-mmu systems. 122 //config: 123 //config: It does not handle select, aliases, tilde expansion, 124 //config: &>file and >&file redirection of stdout+stderr. 125 //config: 126 //config:config HUSH_BASH_COMPAT 127 //config: bool "bash-compatible extensions" 128 //config: default y 129 //config: depends on HUSH 130 //config: help 131 //config: Enable bash-compatible extensions. 132 //config: 133 //config:config HUSH_BRACE_EXPANSION 134 //config: bool "Brace expansion" 135 //config: default y 136 //config: depends on HUSH_BASH_COMPAT 137 //config: help 138 //config: Enable {abc,def} extension. 139 //config: 140 //config:config HUSH_HELP 141 //config: bool "help builtin" 142 //config: default y 143 //config: depends on HUSH 144 //config: help 145 //config: Enable help builtin in hush. Code size + ~1 kbyte. 146 //config: 147 //config:config HUSH_INTERACTIVE 148 //config: bool "Interactive mode" 149 //config: default y 150 //config: depends on HUSH 151 //config: help 152 //config: Enable interactive mode (prompt and command editing). 153 //config: Without this, hush simply reads and executes commands 154 //config: from stdin just like a shell script from a file. 155 //config: No prompt, no PS1/PS2 magic shell variables. 156 //config: 157 //config:config HUSH_SAVEHISTORY 158 //config: bool "Save command history to .hush_history" 159 //config: default y 160 //config: depends on HUSH_INTERACTIVE && FEATURE_EDITING_SAVEHISTORY 161 //config: help 162 //config: Enable history saving in hush. 163 //config: 164 //config:config HUSH_JOB 165 //config: bool "Job control" 166 //config: default y 167 //config: depends on HUSH_INTERACTIVE 168 //config: help 169 //config: Enable job control: Ctrl-Z backgrounds, Ctrl-C interrupts current 170 //config: command (not entire shell), fg/bg builtins work. Without this option, 171 //config: "cmd &" still works by simply spawning a process and immediately 172 //config: prompting for next command (or executing next command in a script), 173 //config: but no separate process group is formed. 174 //config: 175 //config:config HUSH_TICK 176 //config: bool "Process substitution" 177 //config: default y 178 //config: depends on HUSH 179 //config: help 180 //config: Enable process substitution `command` and $(command) in hush. 181 //config: 182 //config:config HUSH_IF 183 //config: bool "Support if/then/elif/else/fi" 184 //config: default y 185 //config: depends on HUSH 186 //config: help 187 //config: Enable if/then/elif/else/fi in hush. 188 //config: 189 //config:config HUSH_LOOPS 190 //config: bool "Support for, while and until loops" 191 //config: default y 192 //config: depends on HUSH 193 //config: help 194 //config: Enable for, while and until loops in hush. 195 //config: 196 //config:config HUSH_CASE 197 //config: bool "Support case ... esac statement" 198 //config: default y 199 //config: depends on HUSH 200 //config: help 201 //config: Enable case ... esac statement in hush. +400 bytes. 202 //config: 203 //config:config HUSH_FUNCTIONS 204 //config: bool "Support funcname() { commands; } syntax" 205 //config: default y 206 //config: depends on HUSH 207 //config: help 208 //config: Enable support for shell functions in hush. +800 bytes. 209 //config: 210 //config:config HUSH_LOCAL 211 //config: bool "Support local builtin" 212 //config: default y 213 //config: depends on HUSH_FUNCTIONS 214 //config: help 215 //config: Enable support for local variables in functions. 216 //config: 217 //config:config HUSH_RANDOM_SUPPORT 218 //config: bool "Pseudorandom generator and $RANDOM variable" 219 //config: default y 220 //config: depends on HUSH 221 //config: help 222 //config: Enable pseudorandom generator and dynamic variable "$RANDOM". 223 //config: Each read of "$RANDOM" will generate a new pseudorandom value. 224 //config: 225 //config:config HUSH_EXPORT_N 226 //config: bool "Support 'export -n' option" 227 //config: default y 228 //config: depends on HUSH 229 //config: help 230 //config: export -n unexports variables. It is a bash extension. 231 //config: 232 //config:config HUSH_MODE_X 233 //config: bool "Support 'hush -x' option and 'set -x' command" 234 //config: default y 235 //config: depends on HUSH 236 //config: help 237 //config: This instructs hush to print commands before execution. 238 //config: Adds ~300 bytes. 239 //config: 240 //config:config MSH 241 //config: bool "msh (deprecated: aliased to hush)" 242 //config: default n 243 //config: select HUSH 244 //config: help 245 //config: msh is deprecated and will be removed, please migrate to hush. 246 //config: 247 248 //usage:#define hush_trivial_usage NOUSAGE_STR 249 //usage:#define hush_full_usage "" 250 //usage:#define msh_trivial_usage NOUSAGE_STR 251 //usage:#define msh_full_usage "" 252 //usage:#define sh_trivial_usage NOUSAGE_STR 253 //usage:#define sh_full_usage "" 254 //usage:#define bash_trivial_usage NOUSAGE_STR 255 //usage:#define bash_full_usage "" 256 257 258 /* Build knobs */ 259 #define LEAK_HUNTING 0 260 #define BUILD_AS_NOMMU 0 261 /* Enable/disable sanity checks. Ok to enable in production, 262 * only adds a bit of bloat. Set to >1 to get non-production level verbosity. 263 * Keeping 1 for now even in released versions. 264 */ 265 #define HUSH_DEBUG 1 266 /* Slightly bigger (+200 bytes), but faster hush. 267 * So far it only enables a trick with counting SIGCHLDs and forks, 268 * which allows us to do fewer waitpid's. 269 * (we can detect a case where neither forks were done nor SIGCHLDs happened 270 * and therefore waitpid will return the same result as last time) 271 */ 272 #define ENABLE_HUSH_FAST 0 273 /* TODO: implement simplified code for users which do not need ${var%...} ops 274 * So far ${var%...} ops are always enabled: 275 */ 276 #define ENABLE_HUSH_DOLLAR_OPS 1 277 278 279 #if BUILD_AS_NOMMU 280 # undef BB_MMU 281 # undef USE_FOR_NOMMU 282 # undef USE_FOR_MMU 283 # define BB_MMU 0 284 # define USE_FOR_NOMMU(...) __VA_ARGS__ 285 # define USE_FOR_MMU(...) 286 #endif 287 288 #include "NUM_APPLETS.h" 289 #if NUM_APPLETS == 1 290 /* STANDALONE does not make sense, and won't compile */ 291 # undef CONFIG_FEATURE_SH_STANDALONE 292 # undef ENABLE_FEATURE_SH_STANDALONE 293 # undef IF_FEATURE_SH_STANDALONE 294 # undef IF_NOT_FEATURE_SH_STANDALONE 295 # define ENABLE_FEATURE_SH_STANDALONE 0 296 # define IF_FEATURE_SH_STANDALONE(...) 297 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__ 298 #endif 299 300 #if !ENABLE_HUSH_INTERACTIVE 301 # undef ENABLE_FEATURE_EDITING 302 # define ENABLE_FEATURE_EDITING 0 303 # undef ENABLE_FEATURE_EDITING_FANCY_PROMPT 304 # define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0 305 #endif 306 307 /* Do we support ANY keywords? */ 308 #if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE 309 # define HAS_KEYWORDS 1 310 # define IF_HAS_KEYWORDS(...) __VA_ARGS__ 311 # define IF_HAS_NO_KEYWORDS(...) 312 #else 313 # define HAS_KEYWORDS 0 314 # define IF_HAS_KEYWORDS(...) 315 # define IF_HAS_NO_KEYWORDS(...) __VA_ARGS__ 316 #endif 88 317 89 318 /* If you comment out one of these below, it will be #defined later … … 94 323 #define debug_print_tree(a, b) do {} while (0) 95 324 #define debug_printf_exec(...) do {} while (0) 325 #define debug_printf_env(...) do {} while (0) 96 326 #define debug_printf_jobs(...) do {} while (0) 97 327 #define debug_printf_expand(...) do {} while (0) 328 #define debug_printf_varexp(...) do {} while (0) 329 #define debug_printf_glob(...) do {} while (0) 330 #define debug_printf_list(...) do {} while (0) 331 #define debug_printf_subst(...) do {} while (0) 98 332 #define debug_printf_clean(...) do {} while (0) 99 333 100 #ifndef debug_printf 101 #define debug_printf(...) fprintf(stderr, __VA_ARGS__) 102 #endif 103 104 #ifndef debug_printf_parse 105 #define debug_printf_parse(...) fprintf(stderr, __VA_ARGS__) 106 #endif 107 108 #ifndef debug_printf_exec 109 #define debug_printf_exec(...) fprintf(stderr, __VA_ARGS__) 110 #endif 111 112 #ifndef debug_printf_jobs 113 #define debug_printf_jobs(...) fprintf(stderr, __VA_ARGS__) 114 #define DEBUG_SHELL_JOBS 1 115 #endif 116 117 #ifndef debug_printf_expand 118 #define debug_printf_expand(...) fprintf(stderr, __VA_ARGS__) 119 #define DEBUG_EXPAND 1 120 #endif 121 122 /* Keep unconditionally on for now */ 123 #define ENABLE_HUSH_DEBUG 1 124 125 #ifndef debug_printf_clean 126 /* broken, of course, but OK for testing */ 127 static const char *indenter(int i) 128 { 129 static const char blanks[] ALIGN1 = 130 " "; 131 return &blanks[sizeof(blanks) - i - 1]; 132 } 133 #define debug_printf_clean(...) fprintf(stderr, __VA_ARGS__) 134 #define DEBUG_CLEAN 1 135 #endif 136 137 138 #if !ENABLE_HUSH_INTERACTIVE 139 #undef ENABLE_FEATURE_EDITING 140 #define ENABLE_FEATURE_EDITING 0 141 #undef ENABLE_FEATURE_EDITING_FANCY_PROMPT 142 #define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0 334 #define ERR_PTR ((void*)(long)1) 335 336 #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" 337 338 #define _SPECIAL_VARS_STR "_*@$!?#" 339 #define SPECIAL_VARS_STR ("_*@$!?#" + 1) 340 #define NUMERIC_SPECVARS_STR ("_*@$!?#" + 3) 341 #if ENABLE_HUSH_BASH_COMPAT 342 /* Support / and // replace ops */ 343 /* Note that // is stored as \ in "encoded" string representation */ 344 # define VAR_ENCODED_SUBST_OPS "\\/%#:-=+?" 345 # define VAR_SUBST_OPS ("\\/%#:-=+?" + 1) 346 # define MINUS_PLUS_EQUAL_QUESTION ("\\/%#:-=+?" + 5) 347 #else 348 # define VAR_ENCODED_SUBST_OPS "%#:-=+?" 349 # define VAR_SUBST_OPS "%#:-=+?" 350 # define MINUS_PLUS_EQUAL_QUESTION ("%#:-=+?" + 3) 143 351 #endif 144 352 145 353 #define SPECIAL_VAR_SYMBOL 3 146 354 147 #define PARSEFLAG_EXIT_FROM_LOOP 1 148 #define PARSEFLAG_SEMICOLON (1 << 1) /* symbol ';' is special for parser */ 149 #define PARSEFLAG_REPARSING (1 << 2) /* >= 2nd pass */ 150 151 typedef enum { 152 REDIRECT_INPUT = 1, 153 REDIRECT_OVERWRITE = 2, 154 REDIRECT_APPEND = 3, 155 REDIRECT_HEREIS = 4, 156 REDIRECT_IO = 5 157 } redir_type; 158 159 /* The descrip member of this structure is only used to make debugging 160 * output pretty */ 355 struct variable; 356 357 static const char hush_version_str[] ALIGN1 = "HUSH_VERSION="BB_VER; 358 359 /* This supports saving pointers malloced in vfork child, 360 * to be freed in the parent. 361 */ 362 #if !BB_MMU 363 typedef struct nommu_save_t { 364 char **new_env; 365 struct variable *old_vars; 366 char **argv; 367 char **argv_from_re_execing; 368 } nommu_save_t; 369 #endif 370 371 enum { 372 RES_NONE = 0, 373 #if ENABLE_HUSH_IF 374 RES_IF , 375 RES_THEN , 376 RES_ELIF , 377 RES_ELSE , 378 RES_FI , 379 #endif 380 #if ENABLE_HUSH_LOOPS 381 RES_FOR , 382 RES_WHILE , 383 RES_UNTIL , 384 RES_DO , 385 RES_DONE , 386 #endif 387 #if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE 388 RES_IN , 389 #endif 390 #if ENABLE_HUSH_CASE 391 RES_CASE , 392 /* three pseudo-keywords support contrived "case" syntax: */ 393 RES_CASE_IN, /* "case ... IN", turns into RES_MATCH when IN is observed */ 394 RES_MATCH , /* "word)" */ 395 RES_CASE_BODY, /* "this command is inside CASE" */ 396 RES_ESAC , 397 #endif 398 RES_XXXX , 399 RES_SNTX 400 }; 401 402 typedef struct o_string { 403 char *data; 404 int length; /* position where data is appended */ 405 int maxlen; 406 int o_expflags; 407 /* At least some part of the string was inside '' or "", 408 * possibly empty one: word"", wo''rd etc. */ 409 smallint has_quoted_part; 410 smallint has_empty_slot; 411 smallint o_assignment; /* 0:maybe, 1:yes, 2:no */ 412 } o_string; 413 enum { 414 EXP_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */ 415 EXP_FLAG_GLOB = 0x2, 416 /* Protect newly added chars against globbing 417 * by prepending \ to *, ?, [, \ */ 418 EXP_FLAG_ESC_GLOB_CHARS = 0x1, 419 }; 420 enum { 421 MAYBE_ASSIGNMENT = 0, 422 DEFINITELY_ASSIGNMENT = 1, 423 NOT_ASSIGNMENT = 2, 424 /* Not an assigment, but next word may be: "if v=xyz cmd;" */ 425 WORD_IS_KEYWORD = 3, 426 }; 427 /* Used for initialization: o_string foo = NULL_O_STRING; */ 428 #define NULL_O_STRING { NULL } 429 430 /* I can almost use ordinary FILE*. Is open_memstream() universally 431 * available? Where is it documented? */ 432 typedef struct in_str { 433 const char *p; 434 /* eof_flag=1: last char in ->p is really an EOF */ 435 char eof_flag; /* meaningless if ->p == NULL */ 436 char peek_buf[2]; 437 #if ENABLE_HUSH_INTERACTIVE 438 smallint promptme; 439 smallint promptmode; /* 0: PS1, 1: PS2 */ 440 #endif 441 FILE *file; 442 int (*get) (struct in_str *) FAST_FUNC; 443 int (*peek) (struct in_str *) FAST_FUNC; 444 } in_str; 445 #define i_getch(input) ((input)->get(input)) 446 #define i_peek(input) ((input)->peek(input)) 447 448 /* The descrip member of this structure is only used to make 449 * debugging output pretty */ 161 450 static const struct { 162 451 int mode; … … 164 453 char descrip[3]; 165 454 } redir_table[] = { 166 { 0, 0, "()" },167 455 { O_RDONLY, 0, "<" }, 168 456 { O_CREAT|O_TRUNC|O_WRONLY, 1, ">" }, 169 457 { O_CREAT|O_APPEND|O_WRONLY, 1, ">>" }, 170 { O_RDONLY, -1, "<<" }, 171 { O_RDWR, 1, "<>" } 458 { O_CREAT|O_RDWR, 1, "<>" }, 459 { O_RDONLY, 0, "<<" }, 460 /* Should not be needed. Bogus default_fd helps in debugging */ 461 /* { O_RDONLY, 77, "<<" }, */ 172 462 }; 173 463 174 typedef enum { 464 struct redir_struct { 465 struct redir_struct *next; 466 char *rd_filename; /* filename */ 467 int rd_fd; /* fd to redirect */ 468 /* fd to redirect to, or -3 if rd_fd is to be closed (n>&-) */ 469 int rd_dup; 470 smallint rd_type; /* (enum redir_type) */ 471 /* note: for heredocs, rd_filename contains heredoc delimiter, 472 * and subsequently heredoc itself; and rd_dup is a bitmask: 473 * bit 0: do we need to trim leading tabs? 474 * bit 1: is heredoc quoted (<<'delim' syntax) ? 475 */ 476 }; 477 typedef enum redir_type { 478 REDIRECT_INPUT = 0, 479 REDIRECT_OVERWRITE = 1, 480 REDIRECT_APPEND = 2, 481 REDIRECT_IO = 3, 482 REDIRECT_HEREDOC = 4, 483 REDIRECT_HEREDOC2 = 5, /* REDIRECT_HEREDOC after heredoc is loaded */ 484 485 REDIRFD_CLOSE = -3, 486 REDIRFD_SYNTAX_ERR = -2, 487 REDIRFD_TO_FILE = -1, 488 /* otherwise, rd_fd is redirected to rd_dup */ 489 490 HEREDOC_SKIPTABS = 1, 491 HEREDOC_QUOTED = 2, 492 } redir_type; 493 494 495 struct command { 496 pid_t pid; /* 0 if exited */ 497 int assignment_cnt; /* how many argv[i] are assignments? */ 498 smallint is_stopped; /* is the command currently running? */ 499 smallint cmd_type; /* CMD_xxx */ 500 #define CMD_NORMAL 0 501 #define CMD_SUBSHELL 1 502 #if ENABLE_HUSH_BASH_COMPAT 503 /* used for "[[ EXPR ]]" */ 504 # define CMD_SINGLEWORD_NOGLOB 2 505 #endif 506 #if ENABLE_HUSH_FUNCTIONS 507 # define CMD_FUNCDEF 3 508 #endif 509 510 smalluint cmd_exitcode; 511 /* if non-NULL, this "command" is { list }, ( list ), or a compound statement */ 512 struct pipe *group; 513 #if !BB_MMU 514 char *group_as_string; 515 #endif 516 #if ENABLE_HUSH_FUNCTIONS 517 struct function *child_func; 518 /* This field is used to prevent a bug here: 519 * while...do f1() {a;}; f1; f1() {b;}; f1; done 520 * When we execute "f1() {a;}" cmd, we create new function and clear 521 * cmd->group, cmd->group_as_string, cmd->argv[0]. 522 * When we execute "f1() {b;}", we notice that f1 exists, 523 * and that its "parent cmd" struct is still "alive", 524 * we put those fields back into cmd->xxx 525 * (struct function has ->parent_cmd ptr to facilitate that). 526 * When we loop back, we can execute "f1() {a;}" again and set f1 correctly. 527 * Without this trick, loop would execute a;b;b;b;... 528 * instead of correct sequence a;b;a;b;... 529 * When command is freed, it severs the link 530 * (sets ->child_func->parent_cmd to NULL). 531 */ 532 #endif 533 char **argv; /* command name and arguments */ 534 /* argv vector may contain variable references (^Cvar^C, ^C0^C etc) 535 * and on execution these are substituted with their values. 536 * Substitution can make _several_ words out of one argv[n]! 537 * Example: argv[0]=='.^C*^C.' here: echo .$*. 538 * References of the form ^C`cmd arg^C are `cmd arg` substitutions. 539 */ 540 struct redir_struct *redirects; /* I/O redirections */ 541 }; 542 /* Is there anything in this command at all? */ 543 #define IS_NULL_CMD(cmd) \ 544 (!(cmd)->group && !(cmd)->argv && !(cmd)->redirects) 545 546 struct pipe { 547 struct pipe *next; 548 int num_cmds; /* total number of commands in pipe */ 549 int alive_cmds; /* number of commands running (not exited) */ 550 int stopped_cmds; /* number of commands alive, but stopped */ 551 #if ENABLE_HUSH_JOB 552 int jobid; /* job number */ 553 pid_t pgrp; /* process group ID for the job */ 554 char *cmdtext; /* name of job */ 555 #endif 556 struct command *cmds; /* array of commands in pipe */ 557 smallint followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */ 558 IF_HAS_KEYWORDS(smallint pi_inverted;) /* "! cmd | cmd" */ 559 IF_HAS_KEYWORDS(smallint res_word;) /* needed for if, for, while, until... */ 560 }; 561 typedef enum pipe_style { 175 562 PIPE_SEQ = 1, 176 563 PIPE_AND = 2, … … 178 565 PIPE_BG = 4, 179 566 } pipe_style; 180 181 /* might eventually control execution */ 182 typedef enum { 183 RES_NONE = 0, 184 #if ENABLE_HUSH_IF 185 RES_IF = 1, 186 RES_THEN = 2, 187 RES_ELIF = 3, 188 RES_ELSE = 4, 189 RES_FI = 5, 190 #endif 191 #if ENABLE_HUSH_LOOPS 192 RES_FOR = 6, 193 RES_WHILE = 7, 194 RES_UNTIL = 8, 195 RES_DO = 9, 196 RES_DONE = 10, 197 RES_IN = 11, 198 #endif 199 RES_XXXX = 12, 200 RES_SNTX = 13 201 } reserved_style; 202 enum { 203 FLAG_END = (1 << RES_NONE ), 204 #if ENABLE_HUSH_IF 205 FLAG_IF = (1 << RES_IF ), 206 FLAG_THEN = (1 << RES_THEN ), 207 FLAG_ELIF = (1 << RES_ELIF ), 208 FLAG_ELSE = (1 << RES_ELSE ), 209 FLAG_FI = (1 << RES_FI ), 210 #endif 211 #if ENABLE_HUSH_LOOPS 212 FLAG_FOR = (1 << RES_FOR ), 213 FLAG_WHILE = (1 << RES_WHILE), 214 FLAG_UNTIL = (1 << RES_UNTIL), 215 FLAG_DO = (1 << RES_DO ), 216 FLAG_DONE = (1 << RES_DONE ), 217 FLAG_IN = (1 << RES_IN ), 218 #endif 219 FLAG_START = (1 << RES_XXXX ), 220 }; 567 /* Is there anything in this pipe at all? */ 568 #define IS_NULL_PIPE(pi) \ 569 ((pi)->num_cmds == 0 IF_HAS_KEYWORDS( && (pi)->res_word == RES_NONE)) 221 570 222 571 /* This holds pointers to the various results of parsing */ 223 struct p _context {224 struct child_prog *child;572 struct parse_context { 573 /* linked list of pipes */ 225 574 struct pipe *list_head; 575 /* last pipe (being constructed right now) */ 226 576 struct pipe *pipe; 577 /* last command in pipe (being constructed right now) */ 578 struct command *command; 579 /* last redirect in command->redirects list */ 227 580 struct redir_struct *pending_redirect; 228 smallint res_w; 229 smallint parse_type; /* bitmask of PARSEFLAG_xxx, defines type of parser : ";$" common or special symbol */ 230 int old_flag; /* bitmask of FLAG_xxx, for figuring out valid reserved words */ 231 struct p_context *stack; 232 /* How about quoting status? */ 233 }; 234 235 struct redir_struct { 236 struct redir_struct *next; /* pointer to the next redirect in the list */ 237 redir_type type; /* type of redirection */ 238 int fd; /* file descriptor being redirected */ 239 int dup; /* -1, or file descriptor being duplicated */ 240 glob_t word; /* *word.gl_pathv is the filename */ 241 }; 242 243 struct child_prog { 244 pid_t pid; /* 0 if exited */ 245 char **argv; /* program name and arguments */ 246 struct pipe *group; /* if non-NULL, first in group or subshell */ 247 smallint subshell; /* flag, non-zero if group must be forked */ 248 smallint is_stopped; /* is the program currently running? */ 249 struct redir_struct *redirects; /* I/O redirections */ 250 glob_t glob_result; /* result of parameter globbing */ 251 struct pipe *family; /* pointer back to the child's parent pipe */ 252 //sp counting seems to be broken... so commented out, grep for '//sp:' 253 //sp: int sp; /* number of SPECIAL_VAR_SYMBOL */ 254 //seems to be unused, grep for '//pt:' 255 //pt: int parse_type; 256 }; 257 /* argv vector may contain variable references (^Cvar^C, ^C0^C etc) 258 * and on execution these are substituted with their values. 259 * Substitution can make _several_ words out of one argv[n]! 260 * Example: argv[0]=='.^C*^C.' here: echo .$*. 261 */ 262 263 struct pipe { 264 struct pipe *next; 265 int num_progs; /* total number of programs in job */ 266 int running_progs; /* number of programs running (not exited) */ 267 int stopped_progs; /* number of programs alive, but stopped */ 268 #if ENABLE_HUSH_JOB 269 int jobid; /* job number */ 270 pid_t pgrp; /* process group ID for the job */ 271 char *cmdtext; /* name of job */ 272 #endif 273 char *cmdbuf; /* buffer various argv's point into */ 274 struct child_prog *progs; /* array of commands in pipe */ 275 int job_context; /* bitmask defining current context */ 276 smallint followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */ 277 smallint res_word; /* needed for if, for, while, until... */ 278 }; 279 280 struct close_me { 281 struct close_me *next; 282 int fd; 581 #if !BB_MMU 582 o_string as_string; 583 #endif 584 #if HAS_KEYWORDS 585 smallint ctx_res_w; 586 smallint ctx_inverted; /* "! cmd | cmd" */ 587 #if ENABLE_HUSH_CASE 588 smallint ctx_dsemicolon; /* ";;" seen */ 589 #endif 590 /* bitmask of FLAG_xxx, for figuring out valid reserved words */ 591 int old_flag; 592 /* group we are enclosed in: 593 * example: "if pipe1; pipe2; then pipe3; fi" 594 * when we see "if" or "then", we malloc and copy current context, 595 * and make ->stack point to it. then we parse pipeN. 596 * when closing "then" / fi" / whatever is found, 597 * we move list_head into ->stack->command->group, 598 * copy ->stack into current context, and delete ->stack. 599 * (parsing of { list } and ( list ) doesn't use this method) 600 */ 601 struct parse_context *stack; 602 #endif 283 603 }; 284 604 … … 292 612 struct variable *next; 293 613 char *varstr; /* points to "name=" portion */ 614 #if ENABLE_HUSH_LOCAL 615 unsigned func_nest_level; 616 #endif 294 617 int max_len; /* if > 0, name is part of initial env; else name is malloced */ 295 618 smallint flg_export; /* putenv should be done on this var */ … … 297 620 }; 298 621 299 typedef struct { 300 char *data; 301 int length; 302 int maxlen; 303 int quote; 304 int nonnull; 305 } o_string; 306 #define NULL_O_STRING {NULL,0,0,0,0} 307 /* used for initialization: o_string foo = NULL_O_STRING; */ 308 309 /* I can almost use ordinary FILE *. Is open_memstream() universally 310 * available? Where is it documented? */ 311 struct in_str { 312 const char *p; 313 /* eof_flag=1: last char in ->p is really an EOF */ 314 char eof_flag; /* meaningless if ->p == NULL */ 315 char peek_buf[2]; 316 #if ENABLE_HUSH_INTERACTIVE 317 smallint promptme; 318 smallint promptmode; /* 0: PS1, 1: PS2 */ 319 #endif 320 FILE *file; 321 int (*get) (struct in_str *); 322 int (*peek) (struct in_str *); 622 enum { 623 BC_BREAK = 1, 624 BC_CONTINUE = 2, 323 625 }; 324 #define b_getch(input) ((input)->get(input)) 325 #define b_peek(input) ((input)->peek(input)) 326 626 627 #if ENABLE_HUSH_FUNCTIONS 628 struct function { 629 struct function *next; 630 char *name; 631 struct command *parent_cmd; 632 struct pipe *body; 633 # if !BB_MMU 634 char *body_as_string; 635 # endif 636 }; 637 #endif 638 639 640 /* set -/+o OPT support. (TODO: make it optional) 641 * bash supports the following opts: 642 * allexport off 643 * braceexpand on 644 * emacs on 645 * errexit off 646 * errtrace off 647 * functrace off 648 * hashall on 649 * histexpand off 650 * history on 651 * ignoreeof off 652 * interactive-comments on 653 * keyword off 654 * monitor on 655 * noclobber off 656 * noexec off 657 * noglob off 658 * nolog off 659 * notify off 660 * nounset off 661 * onecmd off 662 * physical off 663 * pipefail off 664 * posix off 665 * privileged off 666 * verbose off 667 * vi off 668 * xtrace off 669 */ 670 static const char o_opt_strings[] ALIGN1 = "pipefail\0"; 327 671 enum { 328 CHAR_ORDINARY = 0, 329 CHAR_ORDINARY_IF_QUOTED = 1, /* example: *, # */ 330 CHAR_IFS = 2, /* treated as ordinary if quoted */ 331 CHAR_SPECIAL = 3, /* example: $ */ 672 OPT_O_PIPEFAIL, 673 NUM_OPT_O 332 674 }; 333 675 334 #define HUSH_VER_STR "0.02"335 676 336 677 /* "Globals" within this file */ 337 338 678 /* Sorted roughly by size (smaller offsets == smaller code) */ 339 679 struct globals { 680 /* interactive_fd != 0 means we are an interactive shell. 681 * If we are, then saved_tty_pgrp can also be != 0, meaning 682 * that controlling tty is available. With saved_tty_pgrp == 0, 683 * job control still works, but terminal signals 684 * (^C, ^Z, ^Y, ^\) won't work at all, and background 685 * process groups can only be created with "cmd &". 686 * With saved_tty_pgrp != 0, hush will use tcsetpgrp() 687 * to give tty to the foreground process group, 688 * and will take it back when the group is stopped (^Z) 689 * or killed (^C). 690 */ 340 691 #if ENABLE_HUSH_INTERACTIVE 341 692 /* 'interactive_fd' is a fd# open to ctty, if we have one … … 344 695 const char *PS1; 345 696 const char *PS2; 697 # define G_interactive_fd (G.interactive_fd) 698 #else 699 # define G_interactive_fd 0 346 700 #endif 347 701 #if ENABLE_FEATURE_EDITING 348 702 line_input_t *line_input_state; 349 703 #endif 704 pid_t root_pid; 705 pid_t root_ppid; 706 pid_t last_bg_pid; 707 #if ENABLE_HUSH_RANDOM_SUPPORT 708 random_t random_gen; 709 #endif 350 710 #if ENABLE_HUSH_JOB 351 711 int run_list_level; 352 pid_t saved_task_pgrp;712 int last_jobid; 353 713 pid_t saved_tty_pgrp; 354 int last_jobid;355 714 struct pipe *job_list; 356 struct pipe *toplevel_list; 357 smallint ctrl_z_flag; 358 #endif 359 smallint fake_mode; 360 /* these three support $?, $#, and $1 */ 715 # define G_saved_tty_pgrp (G.saved_tty_pgrp) 716 #else 717 # define G_saved_tty_pgrp 0 718 #endif 719 char o_opt[NUM_OPT_O]; 720 smallint flag_SIGINT; 721 #if ENABLE_HUSH_LOOPS 722 smallint flag_break_continue; 723 #endif 724 #if ENABLE_HUSH_FUNCTIONS 725 /* 0: outside of a function (or sourced file) 726 * -1: inside of a function, ok to use return builtin 727 * 1: return is invoked, skip all till end of func 728 */ 729 smallint flag_return_in_progress; 730 #endif 731 smallint n_mode; 732 #if ENABLE_HUSH_MODE_X 733 smallint x_mode; 734 # define G_x_mode (G.x_mode) 735 #else 736 # define G_x_mode 0 737 #endif 738 smallint exiting; /* used to prevent EXIT trap recursion */ 739 /* These four support $?, $#, and $1 */ 740 smalluint last_exitcode; 741 /* are global_argv and global_argv[1..n] malloced? (note: not [0]) */ 742 smalluint global_args_malloced; 743 smalluint inherited_set_is_saved; 744 /* how many non-NULL argv's we have. NB: $# + 1 */ 745 int global_argc; 361 746 char **global_argv; 362 int global_argc; 363 int last_return_code; 747 #if !BB_MMU 748 char *argv0_for_re_execing; 749 #endif 750 #if ENABLE_HUSH_LOOPS 751 unsigned depth_break_continue; 752 unsigned depth_of_loop; 753 #endif 364 754 const char *ifs; 365 struct close_me *close_me_head;366 755 const char *cwd; 367 unsigned last_bg_pid; 368 struct variable *top_var; /* = &shell_ver (set in main()) */ 369 struct variable shell_ver; 370 #if ENABLE_FEATURE_SH_STANDALONE 371 struct nofork_save_area nofork_save; 372 #endif 756 struct variable *top_var; 757 char **expanded_assignments; 758 #if ENABLE_HUSH_FUNCTIONS 759 struct function *top_func; 760 # if ENABLE_HUSH_LOCAL 761 struct variable **shadowed_vars_pp; 762 unsigned func_nest_level; 763 # endif 764 #endif 765 /* Signal and trap handling */ 766 #if ENABLE_HUSH_FAST 767 unsigned count_SIGCHLD; 768 unsigned handled_SIGCHLD; 769 smallint we_have_children; 770 #endif 771 /* which signals have non-DFL handler (even with no traps set)? */ 772 unsigned non_DFL_mask; 773 char **traps; /* char *traps[NSIG] */ 774 sigset_t blocked_set; 775 sigset_t inherited_set; 776 #if HUSH_DEBUG 777 unsigned long memleak_value; 778 int debug_indent; 779 #endif 780 char user_input_buf[ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 2]; 781 }; 782 #define G (*ptr_to_globals) 783 /* Not #defining name to G.name - this quickly gets unwieldy 784 * (too many defines). Also, I actually prefer to see when a variable 785 * is global, thus "G." prefix is a useful hint */ 786 #define INIT_G() do { \ 787 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ 788 } while (0) 789 790 791 /* Function prototypes for builtins */ 792 static int builtin_cd(char **argv) FAST_FUNC; 793 static int builtin_echo(char **argv) FAST_FUNC; 794 static int builtin_eval(char **argv) FAST_FUNC; 795 static int builtin_exec(char **argv) FAST_FUNC; 796 static int builtin_exit(char **argv) FAST_FUNC; 797 static int builtin_export(char **argv) FAST_FUNC; 373 798 #if ENABLE_HUSH_JOB 374 sigjmp_buf toplevel_jb; 375 #endif 376 unsigned char charmap[256]; 377 char user_input_buf[ENABLE_FEATURE_EDITING ? BUFSIZ : 2]; 378 }; 379 380 #define G (*ptr_to_globals) 381 382 #if !ENABLE_HUSH_INTERACTIVE 383 enum { interactive_fd = 0 }; 384 #endif 385 #if !ENABLE_HUSH_JOB 386 enum { run_list_level = 0 }; 387 #endif 388 389 #if ENABLE_HUSH_INTERACTIVE 390 #define interactive_fd (G.interactive_fd ) 391 #define PS1 (G.PS1 ) 392 #define PS2 (G.PS2 ) 393 #endif 394 #if ENABLE_FEATURE_EDITING 395 #define line_input_state (G.line_input_state) 396 #endif 397 #if ENABLE_HUSH_JOB 398 #define run_list_level (G.run_list_level ) 399 #define saved_task_pgrp (G.saved_task_pgrp ) 400 #define saved_tty_pgrp (G.saved_tty_pgrp ) 401 #define last_jobid (G.last_jobid ) 402 #define job_list (G.job_list ) 403 #define toplevel_list (G.toplevel_list ) 404 #define toplevel_jb (G.toplevel_jb ) 405 #define ctrl_z_flag (G.ctrl_z_flag ) 406 #endif /* JOB */ 407 #define global_argv (G.global_argv ) 408 #define global_argc (G.global_argc ) 409 #define last_return_code (G.last_return_code) 410 #define ifs (G.ifs ) 411 #define fake_mode (G.fake_mode ) 412 #define close_me_head (G.close_me_head ) 413 #define cwd (G.cwd ) 414 #define last_bg_pid (G.last_bg_pid ) 415 #define top_var (G.top_var ) 416 #define shell_ver (G.shell_ver ) 417 #if ENABLE_FEATURE_SH_STANDALONE 418 #define nofork_save (G.nofork_save ) 419 #endif 420 #if ENABLE_HUSH_JOB 421 #define toplevel_jb (G.toplevel_jb ) 422 #endif 423 #define charmap (G.charmap ) 424 #define user_input_buf (G.user_input_buf ) 425 426 427 #define B_CHUNK 100 428 #define B_NOSPAC 1 429 #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" 430 431 #if 1 432 /* Normal */ 433 static void syntax(const char *msg) 434 { 435 /* Was using fancy stuff: 436 * (interactive_fd ? bb_error_msg : bb_error_msg_and_die)(...params...) 437 * but it SEGVs. ?! Oh well... explicit temp ptr works around that */ 438 void (*fp)(const char *s, ...); 439 440 fp = (interactive_fd ? bb_error_msg : bb_error_msg_and_die); 441 fp(msg ? "%s: %s" : "syntax error", "syntax error", msg); 442 } 443 444 #else 445 /* Debug */ 446 static void syntax_lineno(int line) 447 { 448 void (*fp)(const char *s, ...); 449 450 fp = (interactive_fd ? bb_error_msg : bb_error_msg_and_die); 451 fp("syntax error hush.c:%d", line); 452 } 453 #define syntax(str) syntax_lineno(__LINE__) 454 #endif 455 456 /* Index of subroutines: */ 457 /* function prototypes for builtins */ 458 static int builtin_cd(char **argv); 459 static int builtin_eval(char **argv); 460 static int builtin_exec(char **argv); 461 static int builtin_exit(char **argv); 462 static int builtin_export(char **argv); 463 #if ENABLE_HUSH_JOB 464 static int builtin_fg_bg(char **argv); 465 static int builtin_jobs(char **argv); 799 static int builtin_fg_bg(char **argv) FAST_FUNC; 800 static int builtin_jobs(char **argv) FAST_FUNC; 466 801 #endif 467 802 #if ENABLE_HUSH_HELP 468 static int builtin_help(char **argv); 469 #endif 470 static int builtin_pwd(char **argv); 471 static int builtin_read(char **argv); 472 static int builtin_set(char **argv); 473 static int builtin_shift(char **argv); 474 static int builtin_source(char **argv); 475 static int builtin_umask(char **argv); 476 static int builtin_unset(char **argv); 477 //static int builtin_not_written(char **argv); 478 /* o_string manipulation: */ 479 static int b_check_space(o_string *o, int len); 480 static int b_addchr(o_string *o, int ch); 481 static void b_reset(o_string *o); 482 static int b_addqchr(o_string *o, int ch, int quote); 483 /* in_str manipulations: */ 484 static int static_get(struct in_str *i); 485 static int static_peek(struct in_str *i); 486 static int file_get(struct in_str *i); 487 static int file_peek(struct in_str *i); 488 static void setup_file_in_str(struct in_str *i, FILE *f); 489 static void setup_string_in_str(struct in_str *i, const char *s); 490 /* close_me manipulations: */ 491 static void mark_open(int fd); 492 static void mark_closed(int fd); 493 static void close_all(void); 494 /* "run" the final data structures: */ 495 #if !defined(DEBUG_CLEAN) 496 #define free_pipe_list(head, indent) free_pipe_list(head) 497 #define free_pipe(pi, indent) free_pipe(pi) 498 #endif 499 static int free_pipe_list(struct pipe *head, int indent); 500 static int free_pipe(struct pipe *pi, int indent); 501 /* really run the final data structures: */ 502 static int setup_redirects(struct child_prog *prog, int squirrel[]); 503 static int run_list_real(struct pipe *pi); 504 static void pseudo_exec_argv(char **argv) ATTRIBUTE_NORETURN; 505 static void pseudo_exec(struct child_prog *child) ATTRIBUTE_NORETURN; 506 static int run_pipe_real(struct pipe *pi); 507 /* extended glob support: */ 508 static int globhack(const char *src, int flags, glob_t *pglob); 509 static int glob_needed(const char *s); 510 static int xglob(o_string *dest, int flags, glob_t *pglob); 511 /* variable assignment: */ 512 static int is_assignment(const char *s); 513 /* data structure manipulation: */ 514 static int setup_redirect(struct p_context *ctx, int fd, redir_type style, struct in_str *input); 515 static void initialize_context(struct p_context *ctx); 516 static int done_word(o_string *dest, struct p_context *ctx); 517 static int done_command(struct p_context *ctx); 518 static int done_pipe(struct p_context *ctx, pipe_style type); 519 /* primary string parsing: */ 520 static int redirect_dup_num(struct in_str *input); 521 static int redirect_opt_num(o_string *o); 522 #if ENABLE_HUSH_TICK 523 static int process_command_subs(o_string *dest, struct p_context *ctx, struct in_str *input, const char *subst_end); 524 #endif 525 static int parse_group(o_string *dest, struct p_context *ctx, struct in_str *input, int ch); 526 static const char *lookup_param(const char *src); 527 static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input); 528 static int parse_stream(o_string *dest, struct p_context *ctx, struct in_str *input0, const char *end_trigger); 529 /* setup: */ 530 static int parse_and_run_stream(struct in_str *inp, int parse_flag); 531 static int parse_and_run_string(const char *s, int parse_flag); 532 static int parse_and_run_file(FILE *f); 533 /* job management: */ 534 static int checkjobs(struct pipe* fg_pipe); 535 #if ENABLE_HUSH_JOB 536 static int checkjobs_and_fg_shell(struct pipe* fg_pipe); 537 static void insert_bg_job(struct pipe *pi); 538 static void remove_bg_job(struct pipe *pi); 539 static void delete_finished_bg_job(struct pipe *pi); 540 #else 541 int checkjobs_and_fg_shell(struct pipe* fg_pipe); /* never called */ 542 #endif 543 /* local variable support */ 544 static char **expand_strvec_to_strvec(char **argv); 545 /* used for eval */ 546 static char *expand_strvec_to_string(char **argv); 547 /* used for expansion of right hand of assignments */ 548 static char *expand_string_to_string(const char *str); 549 static struct variable *get_local_var(const char *name); 550 static int set_local_var(char *str, int flg_export); 551 static void unset_local_var(const char *name); 803 static int builtin_help(char **argv) FAST_FUNC; 804 #endif 805 #if ENABLE_HUSH_LOCAL 806 static int builtin_local(char **argv) FAST_FUNC; 807 #endif 808 #if HUSH_DEBUG 809 static int builtin_memleak(char **argv) FAST_FUNC; 810 #endif 811 #if ENABLE_PRINTF 812 static int builtin_printf(char **argv) FAST_FUNC; 813 #endif 814 static int builtin_pwd(char **argv) FAST_FUNC; 815 static int builtin_read(char **argv) FAST_FUNC; 816 static int builtin_set(char **argv) FAST_FUNC; 817 static int builtin_shift(char **argv) FAST_FUNC; 818 static int builtin_source(char **argv) FAST_FUNC; 819 static int builtin_test(char **argv) FAST_FUNC; 820 static int builtin_trap(char **argv) FAST_FUNC; 821 static int builtin_type(char **argv) FAST_FUNC; 822 static int builtin_true(char **argv) FAST_FUNC; 823 static int builtin_umask(char **argv) FAST_FUNC; 824 static int builtin_unset(char **argv) FAST_FUNC; 825 static int builtin_wait(char **argv) FAST_FUNC; 826 #if ENABLE_HUSH_LOOPS 827 static int builtin_break(char **argv) FAST_FUNC; 828 static int builtin_continue(char **argv) FAST_FUNC; 829 #endif 830 #if ENABLE_HUSH_FUNCTIONS 831 static int builtin_return(char **argv) FAST_FUNC; 832 #endif 552 833 553 834 /* Table of built-in functions. They can be forked or not, depending on … … 558 839 * still be set at the end. */ 559 840 struct built_in_command { 560 const char * cmd; /* name */561 int (* function) (char **argv); /* function ptr */841 const char *b_cmd; 842 int (*b_function)(char **argv) FAST_FUNC; 562 843 #if ENABLE_HUSH_HELP 563 const char * descr; /* description */564 # define BLTIN(cmd, func, help) { cmd, func, help }844 const char *b_descr; 845 # define BLTIN(cmd, func, help) { cmd, func, help } 565 846 #else 566 # define BLTIN(cmd, func, help) { cmd, func }847 # define BLTIN(cmd, func, help) { cmd, func } 567 848 #endif 568 849 }; 569 850 570 static const struct built_in_command bltins[] = { 851 static const struct built_in_command bltins1[] = { 852 BLTIN("." , builtin_source , "Run commands in a file"), 853 BLTIN(":" , builtin_true , NULL), 571 854 #if ENABLE_HUSH_JOB 572 BLTIN("bg" , builtin_fg_bg, "Resume a job in the background"), 573 #endif 574 // BLTIN("break" , builtin_not_written, "Exit for, while or until loop"), 575 BLTIN("cd" , builtin_cd, "Change working directory"), 576 // BLTIN("continue", builtin_not_written, "Continue for, while or until loop"), 577 BLTIN("eval" , builtin_eval, "Construct and run shell command"), 578 BLTIN("exec" , builtin_exec, "Exec command, replacing this shell with the exec'd process"), 579 BLTIN("exit" , builtin_exit, "Exit from shell"), 580 BLTIN("export", builtin_export, "Set environment variable"), 855 BLTIN("bg" , builtin_fg_bg , "Resume a job in the background"), 856 #endif 857 #if ENABLE_HUSH_LOOPS 858 BLTIN("break" , builtin_break , "Exit from a loop"), 859 #endif 860 BLTIN("cd" , builtin_cd , "Change directory"), 861 #if ENABLE_HUSH_LOOPS 862 BLTIN("continue" , builtin_continue, "Start new loop iteration"), 863 #endif 864 BLTIN("eval" , builtin_eval , "Construct and run shell command"), 865 BLTIN("exec" , builtin_exec , "Execute command, don't return to shell"), 866 BLTIN("exit" , builtin_exit , "Exit"), 867 BLTIN("export" , builtin_export , "Set environment variables"), 581 868 #if ENABLE_HUSH_JOB 582 BLTIN("fg" , builtin_fg_bg, "Bring job into the foreground"), 583 BLTIN("jobs" , builtin_jobs, "Lists the active jobs"), 584 #endif 585 // TODO: remove pwd? we have it as an applet... 586 BLTIN("pwd" , builtin_pwd, "Print current directory"), 587 BLTIN("read" , builtin_read, "Input environment variable"), 588 // BLTIN("return", builtin_not_written, "Return from a function"), 589 BLTIN("set" , builtin_set, "Set/unset shell local variables"), 590 BLTIN("shift" , builtin_shift, "Shift positional parameters"), 591 // BLTIN("trap" , builtin_not_written, "Trap signals"), 592 // BLTIN("ulimit", builtin_not_written, "Controls resource limits"), 593 BLTIN("umask" , builtin_umask, "Sets file creation mask"), 594 BLTIN("unset" , builtin_unset, "Unset environment variable"), 595 BLTIN("." , builtin_source, "Source-in and run commands in a file"), 869 BLTIN("fg" , builtin_fg_bg , "Bring job into the foreground"), 870 #endif 596 871 #if ENABLE_HUSH_HELP 597 BLTIN("help" , builtin_help, "List shell built-in commands"), 598 #endif 599 BLTIN(NULL, NULL, NULL) 872 BLTIN("help" , builtin_help , NULL), 873 #endif 874 #if ENABLE_HUSH_JOB 875 BLTIN("jobs" , builtin_jobs , "List jobs"), 876 #endif 877 #if ENABLE_HUSH_LOCAL 878 BLTIN("local" , builtin_local , "Set local variables"), 879 #endif 880 #if HUSH_DEBUG 881 BLTIN("memleak" , builtin_memleak , NULL), 882 #endif 883 BLTIN("read" , builtin_read , "Input into variable"), 884 #if ENABLE_HUSH_FUNCTIONS 885 BLTIN("return" , builtin_return , "Return from a function"), 886 #endif 887 BLTIN("set" , builtin_set , "Set/unset positional parameters"), 888 BLTIN("shift" , builtin_shift , "Shift positional parameters"), 889 #if ENABLE_HUSH_BASH_COMPAT 890 BLTIN("source" , builtin_source , "Run commands in a file"), 891 #endif 892 BLTIN("trap" , builtin_trap , "Trap signals"), 893 BLTIN("type" , builtin_type , "Show command type"), 894 BLTIN("ulimit" , shell_builtin_ulimit , "Control resource limits"), 895 BLTIN("umask" , builtin_umask , "Set file creation mask"), 896 BLTIN("unset" , builtin_unset , "Unset variables"), 897 BLTIN("wait" , builtin_wait , "Wait for process"), 600 898 }; 601 899 /* For now, echo and test are unconditionally enabled. 900 * Maybe make it configurable? */ 901 static const struct built_in_command bltins2[] = { 902 BLTIN("[" , builtin_test , NULL), 903 BLTIN("echo" , builtin_echo , NULL), 904 #if ENABLE_PRINTF 905 BLTIN("printf" , builtin_printf , NULL), 906 #endif 907 BLTIN("pwd" , builtin_pwd , NULL), 908 BLTIN("test" , builtin_test , NULL), 909 }; 910 911 912 /* Debug printouts. 913 */ 914 #if HUSH_DEBUG 915 /* prevent disasters with G.debug_indent < 0 */ 916 # define indent() fdprintf(2, "%*s", (G.debug_indent * 2) & 0xff, "") 917 # define debug_enter() (G.debug_indent++) 918 # define debug_leave() (G.debug_indent--) 919 #else 920 # define indent() ((void)0) 921 # define debug_enter() ((void)0) 922 # define debug_leave() ((void)0) 923 #endif 924 925 #ifndef debug_printf 926 # define debug_printf(...) (indent(), fdprintf(2, __VA_ARGS__)) 927 #endif 928 929 #ifndef debug_printf_parse 930 # define debug_printf_parse(...) (indent(), fdprintf(2, __VA_ARGS__)) 931 #endif 932 933 #ifndef debug_printf_exec 934 #define debug_printf_exec(...) (indent(), fdprintf(2, __VA_ARGS__)) 935 #endif 936 937 #ifndef debug_printf_env 938 # define debug_printf_env(...) (indent(), fdprintf(2, __VA_ARGS__)) 939 #endif 940 941 #ifndef debug_printf_jobs 942 # define debug_printf_jobs(...) (indent(), fdprintf(2, __VA_ARGS__)) 943 # define DEBUG_JOBS 1 944 #else 945 # define DEBUG_JOBS 0 946 #endif 947 948 #ifndef debug_printf_expand 949 # define debug_printf_expand(...) (indent(), fdprintf(2, __VA_ARGS__)) 950 # define DEBUG_EXPAND 1 951 #else 952 # define DEBUG_EXPAND 0 953 #endif 954 955 #ifndef debug_printf_varexp 956 # define debug_printf_varexp(...) (indent(), fdprintf(2, __VA_ARGS__)) 957 #endif 958 959 #ifndef debug_printf_glob 960 # define debug_printf_glob(...) (indent(), fdprintf(2, __VA_ARGS__)) 961 # define DEBUG_GLOB 1 962 #else 963 # define DEBUG_GLOB 0 964 #endif 965 966 #ifndef debug_printf_list 967 # define debug_printf_list(...) (indent(), fdprintf(2, __VA_ARGS__)) 968 #endif 969 970 #ifndef debug_printf_subst 971 # define debug_printf_subst(...) (indent(), fdprintf(2, __VA_ARGS__)) 972 #endif 973 974 #ifndef debug_printf_clean 975 # define debug_printf_clean(...) (indent(), fdprintf(2, __VA_ARGS__)) 976 # define DEBUG_CLEAN 1 977 #else 978 # define DEBUG_CLEAN 0 979 #endif 980 981 #if DEBUG_EXPAND 982 static void debug_print_strings(const char *prefix, char **vv) 983 { 984 indent(); 985 fdprintf(2, "%s:\n", prefix); 986 while (*vv) 987 fdprintf(2, " '%s'\n", *vv++); 988 } 989 #else 990 # define debug_print_strings(prefix, vv) ((void)0) 991 #endif 992 993 994 /* Leak hunting. Use hush_leaktool.sh for post-processing. 995 */ 996 #if LEAK_HUNTING 997 static void *xxmalloc(int lineno, size_t size) 998 { 999 void *ptr = xmalloc((size + 0xff) & ~0xff); 1000 fdprintf(2, "line %d: malloc %p\n", lineno, ptr); 1001 return ptr; 1002 } 1003 static void *xxrealloc(int lineno, void *ptr, size_t size) 1004 { 1005 ptr = xrealloc(ptr, (size + 0xff) & ~0xff); 1006 fdprintf(2, "line %d: realloc %p\n", lineno, ptr); 1007 return ptr; 1008 } 1009 static char *xxstrdup(int lineno, const char *str) 1010 { 1011 char *ptr = xstrdup(str); 1012 fdprintf(2, "line %d: strdup %p\n", lineno, ptr); 1013 return ptr; 1014 } 1015 static void xxfree(void *ptr) 1016 { 1017 fdprintf(2, "free %p\n", ptr); 1018 free(ptr); 1019 } 1020 # define xmalloc(s) xxmalloc(__LINE__, s) 1021 # define xrealloc(p, s) xxrealloc(__LINE__, p, s) 1022 # define xstrdup(s) xxstrdup(__LINE__, s) 1023 # define free(p) xxfree(p) 1024 #endif 1025 1026 1027 /* Syntax and runtime errors. They always abort scripts. 1028 * In interactive use they usually discard unparsed and/or unexecuted commands 1029 * and return to the prompt. 1030 * HUSH_DEBUG >= 2 prints line number in this file where it was detected. 1031 */ 1032 #if HUSH_DEBUG < 2 1033 # define die_if_script(lineno, ...) die_if_script(__VA_ARGS__) 1034 # define syntax_error(lineno, msg) syntax_error(msg) 1035 # define syntax_error_at(lineno, msg) syntax_error_at(msg) 1036 # define syntax_error_unterm_ch(lineno, ch) syntax_error_unterm_ch(ch) 1037 # define syntax_error_unterm_str(lineno, s) syntax_error_unterm_str(s) 1038 # define syntax_error_unexpected_ch(lineno, ch) syntax_error_unexpected_ch(ch) 1039 #endif 1040 1041 static void die_if_script(unsigned lineno, const char *fmt, ...) 1042 { 1043 va_list p; 1044 1045 #if HUSH_DEBUG >= 2 1046 bb_error_msg("hush.c:%u", lineno); 1047 #endif 1048 va_start(p, fmt); 1049 bb_verror_msg(fmt, p, NULL); 1050 va_end(p); 1051 if (!G_interactive_fd) 1052 xfunc_die(); 1053 } 1054 1055 static void syntax_error(unsigned lineno, const char *msg) 1056 { 1057 if (msg) 1058 die_if_script(lineno, "syntax error: %s", msg); 1059 else 1060 die_if_script(lineno, "syntax error", NULL); 1061 } 1062 1063 static void syntax_error_at(unsigned lineno, const char *msg) 1064 { 1065 die_if_script(lineno, "syntax error at '%s'", msg); 1066 } 1067 1068 static void syntax_error_unterm_str(unsigned lineno, const char *s) 1069 { 1070 die_if_script(lineno, "syntax error: unterminated %s", s); 1071 } 1072 1073 /* It so happens that all such cases are totally fatal 1074 * even if shell is interactive: EOF while looking for closing 1075 * delimiter. There is nowhere to read stuff from after that, 1076 * it's EOF! The only choice is to terminate. 1077 */ 1078 static void syntax_error_unterm_ch(unsigned lineno, char ch) NORETURN; 1079 static void syntax_error_unterm_ch(unsigned lineno, char ch) 1080 { 1081 char msg[2] = { ch, '\0' }; 1082 syntax_error_unterm_str(lineno, msg); 1083 xfunc_die(); 1084 } 1085 1086 static void syntax_error_unexpected_ch(unsigned lineno, int ch) 1087 { 1088 char msg[2]; 1089 msg[0] = ch; 1090 msg[1] = '\0'; 1091 die_if_script(lineno, "syntax error: unexpected %s", ch == EOF ? "EOF" : msg); 1092 } 1093 1094 #if HUSH_DEBUG < 2 1095 # undef die_if_script 1096 # undef syntax_error 1097 # undef syntax_error_at 1098 # undef syntax_error_unterm_ch 1099 # undef syntax_error_unterm_str 1100 # undef syntax_error_unexpected_ch 1101 #else 1102 # define die_if_script(...) die_if_script(__LINE__, __VA_ARGS__) 1103 # define syntax_error(msg) syntax_error(__LINE__, msg) 1104 # define syntax_error_at(msg) syntax_error_at(__LINE__, msg) 1105 # define syntax_error_unterm_ch(ch) syntax_error_unterm_ch(__LINE__, ch) 1106 # define syntax_error_unterm_str(s) syntax_error_unterm_str(__LINE__, s) 1107 # define syntax_error_unexpected_ch(ch) syntax_error_unexpected_ch(__LINE__, ch) 1108 #endif 1109 1110 1111 #if ENABLE_HUSH_INTERACTIVE 1112 static void cmdedit_update_prompt(void); 1113 #else 1114 # define cmdedit_update_prompt() ((void)0) 1115 #endif 1116 1117 1118 /* Utility functions 1119 */ 1120 /* Replace each \x with x in place, return ptr past NUL. */ 1121 static char *unbackslash(char *src) 1122 { 1123 char *dst = src = strchrnul(src, '\\'); 1124 while (1) { 1125 if (*src == '\\') 1126 src++; 1127 if ((*dst++ = *src++) == '\0') 1128 break; 1129 } 1130 return dst; 1131 } 1132 1133 static char **add_strings_to_strings(char **strings, char **add, int need_to_dup) 1134 { 1135 int i; 1136 unsigned count1; 1137 unsigned count2; 1138 char **v; 1139 1140 v = strings; 1141 count1 = 0; 1142 if (v) { 1143 while (*v) { 1144 count1++; 1145 v++; 1146 } 1147 } 1148 count2 = 0; 1149 v = add; 1150 while (*v) { 1151 count2++; 1152 v++; 1153 } 1154 v = xrealloc(strings, (count1 + count2 + 1) * sizeof(char*)); 1155 v[count1 + count2] = NULL; 1156 i = count2; 1157 while (--i >= 0) 1158 v[count1 + i] = (need_to_dup ? xstrdup(add[i]) : add[i]); 1159 return v; 1160 } 1161 #if LEAK_HUNTING 1162 static char **xx_add_strings_to_strings(int lineno, char **strings, char **add, int need_to_dup) 1163 { 1164 char **ptr = add_strings_to_strings(strings, add, need_to_dup); 1165 fdprintf(2, "line %d: add_strings_to_strings %p\n", lineno, ptr); 1166 return ptr; 1167 } 1168 #define add_strings_to_strings(strings, add, need_to_dup) \ 1169 xx_add_strings_to_strings(__LINE__, strings, add, need_to_dup) 1170 #endif 1171 1172 /* Note: takes ownership of "add" ptr (it is not strdup'ed) */ 1173 static char **add_string_to_strings(char **strings, char *add) 1174 { 1175 char *v[2]; 1176 v[0] = add; 1177 v[1] = NULL; 1178 return add_strings_to_strings(strings, v, /*dup:*/ 0); 1179 } 1180 #if LEAK_HUNTING 1181 static char **xx_add_string_to_strings(int lineno, char **strings, char *add) 1182 { 1183 char **ptr = add_string_to_strings(strings, add); 1184 fdprintf(2, "line %d: add_string_to_strings %p\n", lineno, ptr); 1185 return ptr; 1186 } 1187 #define add_string_to_strings(strings, add) \ 1188 xx_add_string_to_strings(__LINE__, strings, add) 1189 #endif 1190 1191 static void free_strings(char **strings) 1192 { 1193 char **v; 1194 1195 if (!strings) 1196 return; 1197 v = strings; 1198 while (*v) { 1199 free(*v); 1200 v++; 1201 } 1202 free(strings); 1203 } 1204 1205 1206 /* Helpers for setting new $n and restoring them back 1207 */ 1208 typedef struct save_arg_t { 1209 char *sv_argv0; 1210 char **sv_g_argv; 1211 int sv_g_argc; 1212 smallint sv_g_malloced; 1213 } save_arg_t; 1214 1215 static void save_and_replace_G_args(save_arg_t *sv, char **argv) 1216 { 1217 int n; 1218 1219 sv->sv_argv0 = argv[0]; 1220 sv->sv_g_argv = G.global_argv; 1221 sv->sv_g_argc = G.global_argc; 1222 sv->sv_g_malloced = G.global_args_malloced; 1223 1224 argv[0] = G.global_argv[0]; /* retain $0 */ 1225 G.global_argv = argv; 1226 G.global_args_malloced = 0; 1227 1228 n = 1; 1229 while (*++argv) 1230 n++; 1231 G.global_argc = n; 1232 } 1233 1234 static void restore_G_args(save_arg_t *sv, char **argv) 1235 { 1236 char **pp; 1237 1238 if (G.global_args_malloced) { 1239 /* someone ran "set -- arg1 arg2 ...", undo */ 1240 pp = G.global_argv; 1241 while (*++pp) /* note: does not free $0 */ 1242 free(*pp); 1243 free(G.global_argv); 1244 } 1245 argv[0] = sv->sv_argv0; 1246 G.global_argv = sv->sv_g_argv; 1247 G.global_argc = sv->sv_g_argc; 1248 G.global_args_malloced = sv->sv_g_malloced; 1249 } 1250 1251 1252 /* Basic theory of signal handling in shell 1253 * ======================================== 1254 * This does not describe what hush does, rather, it is current understanding 1255 * what it _should_ do. If it doesn't, it's a bug. 1256 * http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#trap 1257 * 1258 * Signals are handled only after each pipe ("cmd | cmd | cmd" thing) 1259 * is finished or backgrounded. It is the same in interactive and 1260 * non-interactive shells, and is the same regardless of whether 1261 * a user trap handler is installed or a shell special one is in effect. 1262 * ^C or ^Z from keyboard seems to execute "at once" because it usually 1263 * backgrounds (i.e. stops) or kills all members of currently running 1264 * pipe. 1265 * 1266 * Wait builtin in interruptible by signals for which user trap is set 1267 * or by SIGINT in interactive shell. 1268 * 1269 * Trap handlers will execute even within trap handlers. (right?) 1270 * 1271 * User trap handlers are forgotten when subshell ("(cmd)") is entered, 1272 * except for handlers set to '' (empty string). 1273 * 1274 * If job control is off, backgrounded commands ("cmd &") 1275 * have SIGINT, SIGQUIT set to SIG_IGN. 1276 * 1277 * Commands which are run in command substitution ("`cmd`") 1278 * have SIGTTIN, SIGTTOU, SIGTSTP set to SIG_IGN. 1279 * 1280 * Ordinary commands have signals set to SIG_IGN/DFL as inherited 1281 * by the shell from its parent. 1282 * 1283 * Signals which differ from SIG_DFL action 1284 * (note: child (i.e., [v]forked) shell is not an interactive shell): 1285 * 1286 * SIGQUIT: ignore 1287 * SIGTERM (interactive): ignore 1288 * SIGHUP (interactive): 1289 * send SIGCONT to stopped jobs, send SIGHUP to all jobs and exit 1290 * SIGTTIN, SIGTTOU, SIGTSTP (if job control is on): ignore 1291 * Note that ^Z is handled not by trapping SIGTSTP, but by seeing 1292 * that all pipe members are stopped. Try this in bash: 1293 * while :; do :; done - ^Z does not background it 1294 * (while :; do :; done) - ^Z backgrounds it 1295 * SIGINT (interactive): wait for last pipe, ignore the rest 1296 * of the command line, show prompt. NB: ^C does not send SIGINT 1297 * to interactive shell while shell is waiting for a pipe, 1298 * since shell is bg'ed (is not in foreground process group). 1299 * Example 1: this waits 5 sec, but does not execute ls: 1300 * "echo $$; sleep 5; ls -l" + "kill -INT <pid>" 1301 * Example 2: this does not wait and does not execute ls: 1302 * "echo $$; sleep 5 & wait; ls -l" + "kill -INT <pid>" 1303 * Example 3: this does not wait 5 sec, but executes ls: 1304 * "sleep 5; ls -l" + press ^C 1305 * 1306 * (What happens to signals which are IGN on shell start?) 1307 * (What happens with signal mask on shell start?) 1308 * 1309 * Implementation in hush 1310 * ====================== 1311 * We use in-kernel pending signal mask to determine which signals were sent. 1312 * We block all signals which we don't want to take action immediately, 1313 * i.e. we block all signals which need to have special handling as described 1314 * above, and all signals which have traps set. 1315 * After each pipe execution, we extract any pending signals via sigtimedwait() 1316 * and act on them. 1317 * 1318 * unsigned non_DFL_mask: a mask of such "special" signals 1319 * sigset_t blocked_set: current blocked signal set 1320 * 1321 * "trap - SIGxxx": 1322 * clear bit in blocked_set unless it is also in non_DFL_mask 1323 * "trap 'cmd' SIGxxx": 1324 * set bit in blocked_set (even if 'cmd' is '') 1325 * after [v]fork, if we plan to be a shell: 1326 * unblock signals with special interactive handling 1327 * (child shell is not interactive), 1328 * unset all traps except '' (note: regardless of child shell's type - {}, (), etc) 1329 * after [v]fork, if we plan to exec: 1330 * POSIX says fork clears pending signal mask in child - no need to clear it. 1331 * Restore blocked signal set to one inherited by shell just prior to exec. 1332 * 1333 * Note: as a result, we do not use signal handlers much. The only uses 1334 * are to count SIGCHLDs 1335 * and to restore tty pgrp on signal-induced exit. 1336 * 1337 * Note 2 (compat): 1338 * Standard says "When a subshell is entered, traps that are not being ignored 1339 * are set to the default actions". bash interprets it so that traps which 1340 * are set to '' (ignore) are NOT reset to defaults. We do the same. 1341 */ 1342 enum { 1343 SPECIAL_INTERACTIVE_SIGS = 0 1344 | (1 << SIGTERM) 1345 | (1 << SIGINT) 1346 | (1 << SIGHUP) 1347 , 1348 SPECIAL_JOB_SIGS = 0 602 1349 #if ENABLE_HUSH_JOB 603 604 /* move to libbb? */ 605 static void signal_SA_RESTART(int sig, void (*handler)(int)) 606 { 607 struct sigaction sa; 608 sa.sa_handler = handler; 609 sa.sa_flags = SA_RESTART; 610 sigemptyset(&sa.sa_mask); 611 sigaction(sig, &sa, NULL); 612 } 613 614 /* Signals are grouped, we handle them in batches */ 615 static void set_fatal_sighandler(void (*handler)(int)) 616 { 617 signal(SIGILL , handler); 618 signal(SIGTRAP, handler); 619 signal(SIGABRT, handler); 620 signal(SIGFPE , handler); 621 signal(SIGBUS , handler); 622 signal(SIGSEGV, handler); 623 /* bash 3.2 seems to handle these just like 'fatal' ones */ 624 signal(SIGHUP , handler); 625 signal(SIGPIPE, handler); 626 signal(SIGALRM, handler); 627 } 628 static void set_jobctrl_sighandler(void (*handler)(int)) 629 { 630 signal(SIGTSTP, handler); 631 signal(SIGTTIN, handler); 632 signal(SIGTTOU, handler); 633 } 634 static void set_misc_sighandler(void (*handler)(int)) 635 { 636 signal(SIGINT , handler); 637 signal(SIGQUIT, handler); 638 signal(SIGTERM, handler); 639 } 640 /* SIGCHLD is special and handled separately */ 641 642 static void set_every_sighandler(void (*handler)(int)) 643 { 644 set_fatal_sighandler(handler); 645 set_jobctrl_sighandler(handler); 646 set_misc_sighandler(handler); 647 signal(SIGCHLD, handler); 648 } 649 650 static void handler_ctrl_c(int sig) 651 { 652 debug_printf_jobs("got sig %d\n", sig); 653 // as usual we can have all kinds of nasty problems with leaked malloc data here 654 siglongjmp(toplevel_jb, 1); 655 } 656 657 static void handler_ctrl_z(int sig) 658 { 659 pid_t pid; 660 661 debug_printf_jobs("got tty sig %d in pid %d\n", sig, getpid()); 662 pid = fork(); 663 if (pid < 0) /* can't fork. Pretend there was no ctrl-Z */ 664 return; 665 ctrl_z_flag = 1; 666 if (!pid) { /* child */ 667 setpgrp(); 668 debug_printf_jobs("set pgrp for child %d ok\n", getpid()); 669 set_every_sighandler(SIG_DFL); 670 raise(SIGTSTP); /* resend TSTP so that child will be stopped */ 671 debug_printf_jobs("returning in child\n"); 672 /* return to nofork, it will eventually exit now, 673 * not return back to shell */ 674 return; 675 } 676 /* parent */ 677 /* finish filling up pipe info */ 678 toplevel_list->pgrp = pid; /* child is in its own pgrp */ 679 toplevel_list->progs[0].pid = pid; 680 /* parent needs to longjmp out of running nofork. 681 * we will "return" exitcode 0, with child put in background */ 682 // as usual we can have all kinds of nasty problems with leaked malloc data here 683 debug_printf_jobs("siglongjmp in parent\n"); 684 siglongjmp(toplevel_jb, 1); 685 } 1350 | (1 << SIGTTIN) 1351 | (1 << SIGTTOU) 1352 | (1 << SIGTSTP) 1353 #endif 1354 }; 1355 1356 #if ENABLE_HUSH_FAST 1357 static void SIGCHLD_handler(int sig UNUSED_PARAM) 1358 { 1359 G.count_SIGCHLD++; 1360 //bb_error_msg("[%d] SIGCHLD_handler: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD); 1361 } 1362 #endif 1363 1364 #if ENABLE_HUSH_JOB 1365 1366 /* After [v]fork, in child: do not restore tty pgrp on xfunc death */ 1367 # define disable_restore_tty_pgrp_on_exit() (die_sleep = 0) 1368 /* After [v]fork, in parent: restore tty pgrp on xfunc death */ 1369 # define enable_restore_tty_pgrp_on_exit() (die_sleep = -1) 686 1370 687 1371 /* Restores tty foreground process group, and exits. 688 1372 * May be called as signal handler for fatal signal 689 * (will faithfullyresend signal to itself, producing correct exit state)1373 * (will resend signal to itself, producing correct exit state) 690 1374 * or called directly with -EXITCODE. 691 1375 * We also call it if xfunc is exiting. */ 692 static void sigexit(int sig) ATTRIBUTE_NORETURN;1376 static void sigexit(int sig) NORETURN; 693 1377 static void sigexit(int sig) 694 1378 { 695 sigset_t block_all;696 697 1379 /* Disable all signals: job control, SIGPIPE, etc. */ 698 sigfillset(&block_all); 699 sigprocmask(SIG_SETMASK, &block_all, NULL); 700 701 if (interactive_fd) 702 tcsetpgrp(interactive_fd, saved_tty_pgrp); 1380 sigprocmask_allsigs(SIG_BLOCK); 1381 1382 /* Careful: we can end up here after [v]fork. Do not restore 1383 * tty pgrp then, only top-level shell process does that */ 1384 if (G_saved_tty_pgrp && getpid() == G.root_pid) 1385 tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp); 703 1386 704 1387 /* Not a signal, just exit */ … … 706 1389 _exit(- sig); 707 1390 708 /* Enable only this sig and kill ourself with it */ 709 signal(sig, SIG_DFL); 710 sigdelset(&block_all, sig); 711 sigprocmask(SIG_SETMASK, &block_all, NULL); 712 raise(sig); 713 _exit(1); /* Should not reach it */ 714 } 1391 kill_myself_with_sig(sig); /* does not return */ 1392 } 1393 #else 1394 1395 # define disable_restore_tty_pgrp_on_exit() ((void)0) 1396 # define enable_restore_tty_pgrp_on_exit() ((void)0) 1397 1398 #endif 715 1399 716 1400 /* Restores tty foreground process group, and exits. */ 717 static void hush_exit(int exitcode) ATTRIBUTE_NORETURN;1401 static void hush_exit(int exitcode) NORETURN; 718 1402 static void hush_exit(int exitcode) 719 1403 { 720 fflush(NULL); /* flush all streams */ 1404 if (G.exiting <= 0 && G.traps && G.traps[0] && G.traps[0][0]) { 1405 /* Prevent recursion: 1406 * trap "echo Hi; exit" EXIT; exit 1407 */ 1408 char *argv[3]; 1409 /* argv[0] is unused */ 1410 argv[1] = G.traps[0]; 1411 argv[2] = NULL; 1412 G.exiting = 1; /* prevent EXIT trap recursion */ 1413 /* Note: G.traps[0] is not cleared! 1414 * "trap" will still show it, if executed 1415 * in the handler */ 1416 builtin_eval(argv); 1417 } 1418 1419 #if ENABLE_FEATURE_CLEAN_UP 1420 { 1421 struct variable *cur_var; 1422 if (G.cwd != bb_msg_unknown) 1423 free((char*)G.cwd); 1424 cur_var = G.top_var; 1425 while (cur_var) { 1426 struct variable *tmp = cur_var; 1427 if (!cur_var->max_len) 1428 free(cur_var->varstr); 1429 cur_var = cur_var->next; 1430 free(tmp); 1431 } 1432 } 1433 #endif 1434 1435 #if ENABLE_HUSH_JOB 1436 fflush_all(); 721 1437 sigexit(- (exitcode & 0xff)); 722 } 723 724 #else /* !JOB */ 725 726 #define set_fatal_sighandler(handler) ((void)0) 727 #define set_jobctrl_sighandler(handler) ((void)0) 728 #define set_misc_sighandler(handler) ((void)0) 729 #define hush_exit(e) exit(e) 730 731 #endif /* JOB */ 732 733 734 static const char *set_cwd(void) 735 { 736 if (cwd == bb_msg_unknown) 737 cwd = NULL; /* xrealloc_getcwd_or_warn(arg) calls free(arg)! */ 738 cwd = xrealloc_getcwd_or_warn((char *)cwd); 739 if (!cwd) 740 cwd = bb_msg_unknown; 741 return cwd; 742 } 743 744 /* built-in 'eval' handler */ 745 static int builtin_eval(char **argv) 746 { 747 int rcode = EXIT_SUCCESS; 748 749 if (argv[1]) { 750 char *str = expand_strvec_to_string(argv + 1); 751 parse_and_run_string(str, PARSEFLAG_EXIT_FROM_LOOP | 752 PARSEFLAG_SEMICOLON); 1438 #else 1439 exit(exitcode); 1440 #endif 1441 } 1442 1443 1444 static int check_and_run_traps(int sig) 1445 { 1446 /* I want it in rodata, not in bss. 1447 * gcc 4.2.1 puts it in rodata only if it has { 0, 0 } 1448 * initializer. But other compilers may still use bss. 1449 * TODO: find more portable solution. 1450 */ 1451 static const struct timespec zero_timespec = { 0, 0 }; 1452 smalluint save_rcode; 1453 int last_sig = 0; 1454 1455 if (sig) 1456 goto jump_in; 1457 while (1) { 1458 sig = sigtimedwait(&G.blocked_set, NULL, &zero_timespec); 1459 if (sig <= 0) 1460 break; 1461 jump_in: 1462 last_sig = sig; 1463 if (G.traps && G.traps[sig]) { 1464 if (G.traps[sig][0]) { 1465 /* We have user-defined handler */ 1466 char *argv[3]; 1467 /* argv[0] is unused */ 1468 argv[1] = G.traps[sig]; 1469 argv[2] = NULL; 1470 save_rcode = G.last_exitcode; 1471 builtin_eval(argv); 1472 G.last_exitcode = save_rcode; 1473 } /* else: "" trap, ignoring signal */ 1474 continue; 1475 } 1476 /* not a trap: special action */ 1477 switch (sig) { 1478 #if ENABLE_HUSH_FAST 1479 case SIGCHLD: 1480 G.count_SIGCHLD++; 1481 //bb_error_msg("[%d] check_and_run_traps: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD); 1482 break; 1483 #endif 1484 case SIGINT: 1485 /* Builtin was ^C'ed, make it look prettier: */ 1486 bb_putchar('\n'); 1487 G.flag_SIGINT = 1; 1488 break; 1489 #if ENABLE_HUSH_JOB 1490 case SIGHUP: { 1491 struct pipe *job; 1492 /* bash is observed to signal whole process groups, 1493 * not individual processes */ 1494 for (job = G.job_list; job; job = job->next) { 1495 if (job->pgrp <= 0) 1496 continue; 1497 debug_printf_exec("HUPing pgrp %d\n", job->pgrp); 1498 if (kill(- job->pgrp, SIGHUP) == 0) 1499 kill(- job->pgrp, SIGCONT); 1500 } 1501 sigexit(SIGHUP); 1502 } 1503 #endif 1504 default: /* ignored: */ 1505 /* SIGTERM, SIGQUIT, SIGTTIN, SIGTTOU, SIGTSTP */ 1506 break; 1507 } 1508 } 1509 return last_sig; 1510 } 1511 1512 1513 static const char *get_cwd(int force) 1514 { 1515 if (force || G.cwd == NULL) { 1516 /* xrealloc_getcwd_or_warn(arg) calls free(arg), 1517 * we must not try to free(bb_msg_unknown) */ 1518 if (G.cwd == bb_msg_unknown) 1519 G.cwd = NULL; 1520 G.cwd = xrealloc_getcwd_or_warn((char *)G.cwd); 1521 if (!G.cwd) 1522 G.cwd = bb_msg_unknown; 1523 } 1524 return G.cwd; 1525 } 1526 1527 1528 /* 1529 * Shell and environment variable support 1530 */ 1531 static struct variable **get_ptr_to_local_var(const char *name, unsigned len) 1532 { 1533 struct variable **pp; 1534 struct variable *cur; 1535 1536 pp = &G.top_var; 1537 while ((cur = *pp) != NULL) { 1538 if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=') 1539 return pp; 1540 pp = &cur->next; 1541 } 1542 return NULL; 1543 } 1544 1545 static const char* FAST_FUNC get_local_var_value(const char *name) 1546 { 1547 struct variable **vpp; 1548 unsigned len = strlen(name); 1549 1550 if (G.expanded_assignments) { 1551 char **cpp = G.expanded_assignments; 1552 while (*cpp) { 1553 char *cp = *cpp; 1554 if (strncmp(cp, name, len) == 0 && cp[len] == '=') 1555 return cp + len + 1; 1556 cpp++; 1557 } 1558 } 1559 1560 vpp = get_ptr_to_local_var(name, len); 1561 if (vpp) 1562 return (*vpp)->varstr + len + 1; 1563 1564 if (strcmp(name, "PPID") == 0) 1565 return utoa(G.root_ppid); 1566 // bash compat: UID? EUID? 1567 #if ENABLE_HUSH_RANDOM_SUPPORT 1568 if (strcmp(name, "RANDOM") == 0) 1569 return utoa(next_random(&G.random_gen)); 1570 #endif 1571 return NULL; 1572 } 1573 1574 /* str holds "NAME=VAL" and is expected to be malloced. 1575 * We take ownership of it. 1576 * flg_export: 1577 * 0: do not change export flag 1578 * (if creating new variable, flag will be 0) 1579 * 1: set export flag and putenv the variable 1580 * -1: clear export flag and unsetenv the variable 1581 * flg_read_only is set only when we handle -R var=val 1582 */ 1583 #if !BB_MMU && ENABLE_HUSH_LOCAL 1584 /* all params are used */ 1585 #elif BB_MMU && ENABLE_HUSH_LOCAL 1586 #define set_local_var(str, flg_export, local_lvl, flg_read_only) \ 1587 set_local_var(str, flg_export, local_lvl) 1588 #elif BB_MMU && !ENABLE_HUSH_LOCAL 1589 #define set_local_var(str, flg_export, local_lvl, flg_read_only) \ 1590 set_local_var(str, flg_export) 1591 #elif !BB_MMU && !ENABLE_HUSH_LOCAL 1592 #define set_local_var(str, flg_export, local_lvl, flg_read_only) \ 1593 set_local_var(str, flg_export, flg_read_only) 1594 #endif 1595 static int set_local_var(char *str, int flg_export, int local_lvl, int flg_read_only) 1596 { 1597 struct variable **var_pp; 1598 struct variable *cur; 1599 char *eq_sign; 1600 int name_len; 1601 1602 eq_sign = strchr(str, '='); 1603 if (!eq_sign) { /* not expected to ever happen? */ 753 1604 free(str); 754 rcode = last_return_code; 755 } 756 return rcode; 757 } 758 759 /* built-in 'cd <path>' handler */ 760 static int builtin_cd(char **argv) 761 { 762 const char *newdir; 763 if (argv[1] == NULL) 764 newdir = getenv("HOME") ? : "/"; 765 else 766 newdir = argv[1]; 767 if (chdir(newdir)) { 768 printf("cd: %s: %s\n", newdir, strerror(errno)); 769 return EXIT_FAILURE; 770 } 771 set_cwd(); 1605 return -1; 1606 } 1607 1608 name_len = eq_sign - str + 1; /* including '=' */ 1609 var_pp = &G.top_var; 1610 while ((cur = *var_pp) != NULL) { 1611 if (strncmp(cur->varstr, str, name_len) != 0) { 1612 var_pp = &cur->next; 1613 continue; 1614 } 1615 /* We found an existing var with this name */ 1616 if (cur->flg_read_only) { 1617 #if !BB_MMU 1618 if (!flg_read_only) 1619 #endif 1620 bb_error_msg("%s: readonly variable", str); 1621 free(str); 1622 return -1; 1623 } 1624 if (flg_export == -1) { // "&& cur->flg_export" ? 1625 debug_printf_env("%s: unsetenv '%s'\n", __func__, str); 1626 *eq_sign = '\0'; 1627 unsetenv(str); 1628 *eq_sign = '='; 1629 } 1630 #if ENABLE_HUSH_LOCAL 1631 if (cur->func_nest_level < local_lvl) { 1632 /* New variable is declared as local, 1633 * and existing one is global, or local 1634 * from enclosing function. 1635 * Remove and save old one: */ 1636 *var_pp = cur->next; 1637 cur->next = *G.shadowed_vars_pp; 1638 *G.shadowed_vars_pp = cur; 1639 /* bash 3.2.33(1) and exported vars: 1640 * # export z=z 1641 * # f() { local z=a; env | grep ^z; } 1642 * # f 1643 * z=a 1644 * # env | grep ^z 1645 * z=z 1646 */ 1647 if (cur->flg_export) 1648 flg_export = 1; 1649 break; 1650 } 1651 #endif 1652 if (strcmp(cur->varstr + name_len, eq_sign + 1) == 0) { 1653 free_and_exp: 1654 free(str); 1655 goto exp; 1656 } 1657 if (cur->max_len != 0) { 1658 if (cur->max_len >= strlen(str)) { 1659 /* This one is from startup env, reuse space */ 1660 strcpy(cur->varstr, str); 1661 goto free_and_exp; 1662 } 1663 } else { 1664 /* max_len == 0 signifies "malloced" var, which we can 1665 * (and has to) free */ 1666 free(cur->varstr); 1667 } 1668 cur->max_len = 0; 1669 goto set_str_and_exp; 1670 } 1671 1672 /* Not found - create new variable struct */ 1673 cur = xzalloc(sizeof(*cur)); 1674 #if ENABLE_HUSH_LOCAL 1675 cur->func_nest_level = local_lvl; 1676 #endif 1677 cur->next = *var_pp; 1678 *var_pp = cur; 1679 1680 set_str_and_exp: 1681 cur->varstr = str; 1682 #if !BB_MMU 1683 cur->flg_read_only = flg_read_only; 1684 #endif 1685 exp: 1686 if (flg_export == 1) 1687 cur->flg_export = 1; 1688 if (name_len == 4 && cur->varstr[0] == 'P' && cur->varstr[1] == 'S') 1689 cmdedit_update_prompt(); 1690 if (cur->flg_export) { 1691 if (flg_export == -1) { 1692 cur->flg_export = 0; 1693 /* unsetenv was already done */ 1694 } else { 1695 debug_printf_env("%s: putenv '%s'\n", __func__, cur->varstr); 1696 return putenv(cur->varstr); 1697 } 1698 } 1699 return 0; 1700 } 1701 1702 /* Used at startup and after each cd */ 1703 static void set_pwd_var(int exp) 1704 { 1705 set_local_var(xasprintf("PWD=%s", get_cwd(/*force:*/ 1)), 1706 /*exp:*/ exp, /*lvl:*/ 0, /*ro:*/ 0); 1707 } 1708 1709 static int unset_local_var_len(const char *name, int name_len) 1710 { 1711 struct variable *cur; 1712 struct variable **var_pp; 1713 1714 if (!name) 1715 return EXIT_SUCCESS; 1716 var_pp = &G.top_var; 1717 while ((cur = *var_pp) != NULL) { 1718 if (strncmp(cur->varstr, name, name_len) == 0 && cur->varstr[name_len] == '=') { 1719 if (cur->flg_read_only) { 1720 bb_error_msg("%s: readonly variable", name); 1721 return EXIT_FAILURE; 1722 } 1723 *var_pp = cur->next; 1724 debug_printf_env("%s: unsetenv '%s'\n", __func__, cur->varstr); 1725 bb_unsetenv(cur->varstr); 1726 if (name_len == 3 && cur->varstr[0] == 'P' && cur->varstr[1] == 'S') 1727 cmdedit_update_prompt(); 1728 if (!cur->max_len) 1729 free(cur->varstr); 1730 free(cur); 1731 return EXIT_SUCCESS; 1732 } 1733 var_pp = &cur->next; 1734 } 772 1735 return EXIT_SUCCESS; 773 1736 } 774 1737 775 /* built-in 'exec' handler */ 776 static int builtin_exec(char **argv) 777 { 778 if (argv[1] == NULL) 779 return EXIT_SUCCESS; /* Really? */ 780 pseudo_exec_argv(argv + 1); 781 /* never returns */ 782 } 783 784 /* built-in 'exit' handler */ 785 static int builtin_exit(char **argv) 786 { 787 // TODO: bash does it ONLY on top-level sh exit (+interacive only?) 788 //puts("exit"); /* bash does it */ 789 // TODO: warn if we have background jobs: "There are stopped jobs" 790 // On second consecutive 'exit', exit anyway. 791 792 if (argv[1] == NULL) 793 hush_exit(last_return_code); 794 /* mimic bash: exit 123abc == exit 255 + error msg */ 795 xfunc_error_retval = 255; 796 /* bash: exit -2 == exit 254, no error msg */ 797 hush_exit(xatoi(argv[1]) & 0xff); 798 } 799 800 /* built-in 'export VAR=value' handler */ 801 static int builtin_export(char **argv) 802 { 803 const char *value; 804 char *name = argv[1]; 805 806 if (name == NULL) { 807 // TODO: 808 // ash emits: export VAR='VAL' 809 // bash: declare -x VAR="VAL" 810 // (both also escape as needed (quotes, $, etc)) 811 char **e = environ; 812 if (e) 813 while (*e) 814 puts(*e++); 815 return EXIT_SUCCESS; 816 } 817 818 value = strchr(name, '='); 819 if (!value) { 820 /* They are exporting something without a =VALUE */ 821 struct variable *var; 822 823 var = get_local_var(name); 824 if (var) { 825 var->flg_export = 1; 1738 static int unset_local_var(const char *name) 1739 { 1740 return unset_local_var_len(name, strlen(name)); 1741 } 1742 1743 static void unset_vars(char **strings) 1744 { 1745 char **v; 1746 1747 if (!strings) 1748 return; 1749 v = strings; 1750 while (*v) { 1751 const char *eq = strchrnul(*v, '='); 1752 unset_local_var_len(*v, (int)(eq - *v)); 1753 v++; 1754 } 1755 free(strings); 1756 } 1757 1758 static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val) 1759 { 1760 char *var = xasprintf("%s=%s", name, val); 1761 set_local_var(var, /*flags:*/ 0, /*lvl:*/ 0, /*ro:*/ 0); 1762 } 1763 1764 1765 /* 1766 * Helpers for "var1=val1 var2=val2 cmd" feature 1767 */ 1768 static void add_vars(struct variable *var) 1769 { 1770 struct variable *next; 1771 1772 while (var) { 1773 next = var->next; 1774 var->next = G.top_var; 1775 G.top_var = var; 1776 if (var->flg_export) { 1777 debug_printf_env("%s: restoring exported '%s'\n", __func__, var->varstr); 826 1778 putenv(var->varstr); 827 }828 /* bash does not return an error when trying to export829 * an undefined variable. Do likewise. */830 return EXIT_SUCCESS;831 }832 833 set_local_var(xstrdup(name), 1);834 return EXIT_SUCCESS;835 }836 837 #if ENABLE_HUSH_JOB838 /* built-in 'fg' and 'bg' handler */839 static int builtin_fg_bg(char **argv)840 {841 int i, jobnum;842 struct pipe *pi;843 844 if (!interactive_fd)845 return EXIT_FAILURE;846 /* If they gave us no args, assume they want the last backgrounded task */847 if (!argv[1]) {848 for (pi = job_list; pi; pi = pi->next) {849 if (pi->jobid == last_jobid) {850 goto found;851 }852 }853 bb_error_msg("%s: no current job", argv[0]);854 return EXIT_FAILURE;855 }856 if (sscanf(argv[1], "%%%d", &jobnum) != 1) {857 bb_error_msg("%s: bad argument '%s'", argv[0], argv[1]);858 return EXIT_FAILURE;859 }860 for (pi = job_list; pi; pi = pi->next) {861 if (pi->jobid == jobnum) {862 goto found;863 }864 }865 bb_error_msg("%s: %d: no such job", argv[0], jobnum);866 return EXIT_FAILURE;867 found:868 // TODO: bash prints a string representation869 // of job being foregrounded (like "sleep 1 | cat")870 if (*argv[0] == 'f') {871 /* Put the job into the foreground. */872 tcsetpgrp(interactive_fd, pi->pgrp);873 }874 875 /* Restart the processes in the job */876 debug_printf_jobs("reviving %d procs, pgrp %d\n", pi->num_progs, pi->pgrp);877 for (i = 0; i < pi->num_progs; i++) {878 debug_printf_jobs("reviving pid %d\n", pi->progs[i].pid);879 pi->progs[i].is_stopped = 0;880 }881 pi->stopped_progs = 0;882 883 i = kill(- pi->pgrp, SIGCONT);884 if (i < 0) {885 if (errno == ESRCH) {886 delete_finished_bg_job(pi);887 return EXIT_SUCCESS;888 1779 } else { 889 bb_perror_msg("kill (SIGCONT)"); 890 } 891 } 892 893 if (*argv[0] == 'f') { 894 remove_bg_job(pi); 895 return checkjobs_and_fg_shell(pi); 896 } 897 return EXIT_SUCCESS; 898 } 899 #endif 900 901 /* built-in 'help' handler */ 902 #if ENABLE_HUSH_HELP 903 static int builtin_help(char **argv ATTRIBUTE_UNUSED) 904 { 905 const struct built_in_command *x; 906 907 printf("\nBuilt-in commands:\n"); 908 printf("-------------------\n"); 909 for (x = bltins; x->cmd; x++) { 910 printf("%s\t%s\n", x->cmd, x->descr); 911 } 912 printf("\n\n"); 913 return EXIT_SUCCESS; 914 } 915 #endif 916 917 #if ENABLE_HUSH_JOB 918 /* built-in 'jobs' handler */ 919 static int builtin_jobs(char **argv ATTRIBUTE_UNUSED) 920 { 921 struct pipe *job; 922 const char *status_string; 923 924 for (job = job_list; job; job = job->next) { 925 if (job->running_progs == job->stopped_progs) 926 status_string = "Stopped"; 927 else 928 status_string = "Running"; 929 930 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->cmdtext); 931 } 932 return EXIT_SUCCESS; 933 } 934 #endif 935 936 /* built-in 'pwd' handler */ 937 static int builtin_pwd(char **argv ATTRIBUTE_UNUSED) 938 { 939 puts(set_cwd()); 940 return EXIT_SUCCESS; 941 } 942 943 /* built-in 'read VAR' handler */ 944 static int builtin_read(char **argv) 945 { 946 char *string; 947 const char *name = argv[1] ? argv[1] : "REPLY"; 948 949 string = xmalloc_reads(STDIN_FILENO, xasprintf("%s=", name)); 950 return set_local_var(string, 0); 951 } 952 953 /* built-in 'set [VAR=value]' handler */ 954 static int builtin_set(char **argv) 955 { 956 char *temp = argv[1]; 957 struct variable *e; 958 959 if (temp == NULL) 960 for (e = top_var; e; e = e->next) 961 puts(e->varstr); 962 else 963 set_local_var(xstrdup(temp), 0); 964 965 return EXIT_SUCCESS; 966 } 967 968 969 /* Built-in 'shift' handler */ 970 static int builtin_shift(char **argv) 971 { 972 int n = 1; 973 if (argv[1]) { 974 n = atoi(argv[1]); 975 } 976 if (n >= 0 && n < global_argc) { 977 global_argv[n] = global_argv[0]; 978 global_argc -= n; 979 global_argv += n; 980 return EXIT_SUCCESS; 981 } 982 return EXIT_FAILURE; 983 } 984 985 /* Built-in '.' handler (read-in and execute commands from file) */ 986 static int builtin_source(char **argv) 987 { 988 FILE *input; 989 int status; 990 991 if (argv[1] == NULL) 992 return EXIT_FAILURE; 993 994 /* XXX search through $PATH is missing */ 995 input = fopen(argv[1], "r"); 996 if (!input) { 997 bb_error_msg("cannot open '%s'", argv[1]); 998 return EXIT_FAILURE; 999 } 1000 1001 /* Now run the file */ 1002 /* XXX argv and argc are broken; need to save old global_argv 1003 * (pointer only is OK!) on this stack frame, 1004 * set global_argv=argv+1, recurse, and restore. */ 1005 mark_open(fileno(input)); 1006 status = parse_and_run_file(input); 1007 mark_closed(fileno(input)); 1008 fclose(input); 1009 return status; 1010 } 1011 1012 static int builtin_umask(char **argv) 1013 { 1014 mode_t new_umask; 1015 const char *arg = argv[1]; 1016 char *end; 1017 if (arg) { 1018 new_umask = strtoul(arg, &end, 8); 1019 if (*end != '\0' || end == arg) { 1020 return EXIT_FAILURE; 1021 } 1780 debug_printf_env("%s: restoring variable '%s'\n", __func__, var->varstr); 1781 } 1782 var = next; 1783 } 1784 } 1785 1786 static struct variable *set_vars_and_save_old(char **strings) 1787 { 1788 char **s; 1789 struct variable *old = NULL; 1790 1791 if (!strings) 1792 return old; 1793 s = strings; 1794 while (*s) { 1795 struct variable *var_p; 1796 struct variable **var_pp; 1797 char *eq; 1798 1799 eq = strchr(*s, '='); 1800 if (eq) { 1801 var_pp = get_ptr_to_local_var(*s, eq - *s); 1802 if (var_pp) { 1803 /* Remove variable from global linked list */ 1804 var_p = *var_pp; 1805 debug_printf_env("%s: removing '%s'\n", __func__, var_p->varstr); 1806 *var_pp = var_p->next; 1807 /* Add it to returned list */ 1808 var_p->next = old; 1809 old = var_p; 1810 } 1811 set_local_var(*s, /*exp:*/ 1, /*lvl:*/ 0, /*ro:*/ 0); 1812 } 1813 s++; 1814 } 1815 return old; 1816 } 1817 1818 1819 /* 1820 * in_str support 1821 */ 1822 static int FAST_FUNC static_get(struct in_str *i) 1823 { 1824 int ch = *i->p; 1825 if (ch != '\0') { 1826 i->p++; 1827 return ch; 1828 } 1829 return EOF; 1830 } 1831 1832 static int FAST_FUNC static_peek(struct in_str *i) 1833 { 1834 return *i->p; 1835 } 1836 1837 #if ENABLE_HUSH_INTERACTIVE 1838 1839 static void cmdedit_update_prompt(void) 1840 { 1841 if (ENABLE_FEATURE_EDITING_FANCY_PROMPT) { 1842 G.PS1 = get_local_var_value("PS1"); 1843 if (G.PS1 == NULL) 1844 G.PS1 = "\\w \\$ "; 1845 G.PS2 = get_local_var_value("PS2"); 1022 1846 } else { 1023 new_umask = umask(0); 1024 printf("%.3o\n", (unsigned) new_umask); 1025 } 1026 umask(new_umask); 1027 return EXIT_SUCCESS; 1028 } 1029 1030 /* built-in 'unset VAR' handler */ 1031 static int builtin_unset(char **argv) 1032 { 1033 /* bash always returns true */ 1034 unset_local_var(argv[1]); 1035 return EXIT_SUCCESS; 1036 } 1037 1038 //static int builtin_not_written(char **argv) 1039 //{ 1040 // printf("builtin_%s not written\n", argv[0]); 1041 // return EXIT_FAILURE; 1042 //} 1043 1044 static int b_check_space(o_string *o, int len) 1045 { 1046 /* It would be easy to drop a more restrictive policy 1047 * in here, such as setting a maximum string length */ 1048 if (o->length + len > o->maxlen) { 1049 /* assert(data == NULL || o->maxlen != 0); */ 1050 o->maxlen += (2*len > B_CHUNK ? 2*len : B_CHUNK); 1051 o->data = xrealloc(o->data, 1 + o->maxlen); 1052 } 1053 return o->data == NULL; 1054 } 1055 1056 static int b_addchr(o_string *o, int ch) 1057 { 1058 debug_printf("b_addchr: '%c' o->length=%d o=%p\n", ch, o->length, o); 1059 if (b_check_space(o, 1)) 1060 return B_NOSPAC; 1061 o->data[o->length] = ch; 1062 o->length++; 1063 o->data[o->length] = '\0'; 1064 return 0; 1065 } 1066 1067 static void b_reset(o_string *o) 1068 { 1069 o->length = 0; 1070 o->nonnull = 0; 1071 if (o->data != NULL) 1072 *o->data = '\0'; 1073 } 1074 1075 static void b_free(o_string *o) 1076 { 1077 b_reset(o); 1078 free(o->data); 1079 o->data = NULL; 1080 o->maxlen = 0; 1081 } 1082 1083 /* My analysis of quoting semantics tells me that state information 1084 * is associated with a destination, not a source. 1085 */ 1086 static int b_addqchr(o_string *o, int ch, int quote) 1087 { 1088 if (quote && strchr("*?[\\", ch)) { 1089 int rc; 1090 rc = b_addchr(o, '\\'); 1091 if (rc) 1092 return rc; 1093 } 1094 return b_addchr(o, ch); 1095 } 1096 1097 static int static_get(struct in_str *i) 1098 { 1099 int ch = *i->p++; 1100 if (ch == '\0') return EOF; 1101 return ch; 1102 } 1103 1104 static int static_peek(struct in_str *i) 1105 { 1106 return *i->p; 1107 } 1108 1109 #if ENABLE_HUSH_INTERACTIVE 1110 #if ENABLE_FEATURE_EDITING 1111 static void cmdedit_set_initial_prompt(void) 1112 { 1113 #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT 1114 PS1 = NULL; 1115 #else 1116 PS1 = getenv("PS1"); 1117 if (PS1 == NULL) 1118 PS1 = "\\w \\$ "; 1119 #endif 1120 } 1121 #endif /* EDITING */ 1122 1123 static const char* setup_prompt_string(int promptmode) 1847 G.PS1 = NULL; 1848 } 1849 if (G.PS2 == NULL) 1850 G.PS2 = "> "; 1851 } 1852 1853 static const char *setup_prompt_string(int promptmode) 1124 1854 { 1125 1855 const char *prompt_str; 1126 1856 debug_printf("setup_prompt_string %d ", promptmode); 1127 #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT 1128 /* Set up the prompt */ 1129 if (promptmode == 0) { /* PS1 */ 1130 free((char*)PS1); 1131 PS1 = xasprintf("%s %c ", cwd, (geteuid() != 0) ? '$' : '#'); 1132 prompt_str = PS1; 1133 } else { 1134 prompt_str = PS2; 1135 } 1136 #else 1137 prompt_str = (promptmode == 0) ? PS1 : PS2; 1138 #endif 1857 if (!ENABLE_FEATURE_EDITING_FANCY_PROMPT) { 1858 /* Set up the prompt */ 1859 if (promptmode == 0) { /* PS1 */ 1860 free((char*)G.PS1); 1861 /* bash uses $PWD value, even if it is set by user. 1862 * It uses current dir only if PWD is unset. 1863 * We always use current dir. */ 1864 G.PS1 = xasprintf("%s %c ", get_cwd(0), (geteuid() != 0) ? '$' : '#'); 1865 prompt_str = G.PS1; 1866 } else 1867 prompt_str = G.PS2; 1868 } else 1869 prompt_str = (promptmode == 0) ? G.PS1 : G.PS2; 1139 1870 debug_printf("result '%s'\n", prompt_str); 1140 1871 return prompt_str; … … 1147 1878 1148 1879 prompt_str = setup_prompt_string(i->promptmode); 1149 # if ENABLE_FEATURE_EDITING1880 # if ENABLE_FEATURE_EDITING 1150 1881 /* Enable command line editing only while a command line 1151 * is actually being read; otherwise, we'll end up bequeathing 1152 * atexit() handlers and other unwanted stuff to our 1153 * child processes (rob@sysgo.de) */ 1154 r = read_line_input(prompt_str, user_input_buf, BUFSIZ-1, line_input_state); 1882 * is actually being read */ 1883 do { 1884 G.flag_SIGINT = 0; 1885 /* buglet: SIGINT will not make new prompt to appear _at once_, 1886 * only after <Enter>. (^C will work) */ 1887 r = read_line_input(prompt_str, G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1, G.line_input_state); 1888 /* catch *SIGINT* etc (^C is handled by read_line_input) */ 1889 check_and_run_traps(0); 1890 } while (r == 0 || G.flag_SIGINT); /* repeat if ^C or SIGINT */ 1155 1891 i->eof_flag = (r < 0); 1156 1892 if (i->eof_flag) { /* EOF/error detected */ 1157 user_input_buf[0] = EOF; /* yes, it will be truncated, it's ok */ 1158 user_input_buf[1] = '\0'; 1159 } 1160 #else 1161 fputs(prompt_str, stdout); 1162 fflush(stdout); 1163 user_input_buf[0] = r = fgetc(i->file); 1164 /*user_input_buf[1] = '\0'; - already is and never changed */ 1893 G.user_input_buf[0] = EOF; /* yes, it will be truncated, it's ok */ 1894 G.user_input_buf[1] = '\0'; 1895 } 1896 # else 1897 do { 1898 G.flag_SIGINT = 0; 1899 fputs(prompt_str, stdout); 1900 fflush_all(); 1901 G.user_input_buf[0] = r = fgetc(i->file); 1902 /*G.user_input_buf[1] = '\0'; - already is and never changed */ 1903 //do we need check_and_run_traps(0)? (maybe only if stdin) 1904 } while (G.flag_SIGINT); 1165 1905 i->eof_flag = (r == EOF); 1166 #endif 1167 i->p = user_input_buf; 1168 } 1906 # endif 1907 i->p = G.user_input_buf; 1908 } 1909 1169 1910 #endif /* INTERACTIVE */ 1170 1911 1171 1912 /* This is the magic location that prints prompts 1172 1913 * and gets data back from the user */ 1173 static int file_get(struct in_str *i)1914 static int FAST_FUNC file_get(struct in_str *i) 1174 1915 { 1175 1916 int ch; … … 1183 1924 if (i->eof_flag && !*i->p) 1184 1925 ch = EOF; 1926 /* note: ch is never NUL */ 1185 1927 } else { 1186 1928 /* need to double check i->file because we might be doing something 1187 1929 * more complicated by now, like sourcing or substituting. */ 1188 1930 #if ENABLE_HUSH_INTERACTIVE 1189 if ( interactive_fd && i->promptme && i->file == stdin) {1931 if (G_interactive_fd && i->promptme && i->file == stdin) { 1190 1932 do { 1191 1933 get_user_input(i); … … 1196 1938 } 1197 1939 #endif 1198 ch = fgetc(i->file);1199 } 1200 debug_printf("file_get: got a'%c' %d\n", ch, ch);1940 do ch = fgetc(i->file); while (ch == '\0'); 1941 } 1942 debug_printf("file_get: got '%c' %d\n", ch, ch); 1201 1943 #if ENABLE_HUSH_INTERACTIVE 1202 1944 if (ch == '\n') … … 1206 1948 } 1207 1949 1208 /* All the callers guarantee this routine will never be1209 * used right after a newline, so prompting is not needed.1950 /* All callers guarantee this routine will never 1951 * be used right after a newline, so prompting is not needed. 1210 1952 */ 1211 static int file_peek(struct in_str *i)1953 static int FAST_FUNC file_peek(struct in_str *i) 1212 1954 { 1213 1955 int ch; … … 1216 1958 return EOF; 1217 1959 return *i->p; 1218 } 1219 ch = fgetc(i->file); 1960 /* note: ch is never NUL */ 1961 } 1962 do ch = fgetc(i->file); while (ch == '\0'); 1220 1963 i->eof_flag = (ch == EOF); 1221 1964 i->peek_buf[0] = ch; 1222 1965 i->peek_buf[1] = '\0'; 1223 1966 i->p = i->peek_buf; 1224 debug_printf("file_peek: got a '%c' %d\n", *i->p, *i->p);1967 debug_printf("file_peek: got '%c' %d\n", ch, ch); 1225 1968 return ch; 1226 1969 } … … 1250 1993 } 1251 1994 1252 static void mark_open(int fd) 1253 { 1254 struct close_me *new = xmalloc(sizeof(struct close_me)); 1255 new->fd = fd; 1256 new->next = close_me_head; 1257 close_me_head = new; 1258 } 1259 1260 static void mark_closed(int fd) 1261 { 1262 struct close_me *tmp; 1263 if (close_me_head == NULL || close_me_head->fd != fd) 1264 bb_error_msg_and_die("corrupt close_me"); 1265 tmp = close_me_head; 1266 close_me_head = close_me_head->next; 1267 free(tmp); 1268 } 1269 1270 static void close_all(void) 1271 { 1272 struct close_me *c; 1273 for (c = close_me_head; c; c = c->next) { 1274 close(c->fd); 1275 } 1276 close_me_head = NULL; 1995 1996 /* 1997 * o_string support 1998 */ 1999 #define B_CHUNK (32 * sizeof(char*)) 2000 2001 static void o_reset_to_empty_unquoted(o_string *o) 2002 { 2003 o->length = 0; 2004 o->has_quoted_part = 0; 2005 if (o->data) 2006 o->data[0] = '\0'; 2007 } 2008 2009 static void o_free(o_string *o) 2010 { 2011 free(o->data); 2012 memset(o, 0, sizeof(*o)); 2013 } 2014 2015 static ALWAYS_INLINE void o_free_unsafe(o_string *o) 2016 { 2017 free(o->data); 2018 } 2019 2020 static void o_grow_by(o_string *o, int len) 2021 { 2022 if (o->length + len > o->maxlen) { 2023 o->maxlen += (2*len > B_CHUNK ? 2*len : B_CHUNK); 2024 o->data = xrealloc(o->data, 1 + o->maxlen); 2025 } 2026 } 2027 2028 static void o_addchr(o_string *o, int ch) 2029 { 2030 debug_printf("o_addchr: '%c' o->length=%d o=%p\n", ch, o->length, o); 2031 o_grow_by(o, 1); 2032 o->data[o->length] = ch; 2033 o->length++; 2034 o->data[o->length] = '\0'; 2035 } 2036 2037 static void o_addblock(o_string *o, const char *str, int len) 2038 { 2039 o_grow_by(o, len); 2040 memcpy(&o->data[o->length], str, len); 2041 o->length += len; 2042 o->data[o->length] = '\0'; 2043 } 2044 2045 static void o_addstr(o_string *o, const char *str) 2046 { 2047 o_addblock(o, str, strlen(str)); 2048 } 2049 2050 #if !BB_MMU 2051 static void nommu_addchr(o_string *o, int ch) 2052 { 2053 if (o) 2054 o_addchr(o, ch); 2055 } 2056 #else 2057 # define nommu_addchr(o, str) ((void)0) 2058 #endif 2059 2060 static void o_addstr_with_NUL(o_string *o, const char *str) 2061 { 2062 o_addblock(o, str, strlen(str) + 1); 2063 } 2064 2065 /* 2066 * HUSH_BRACE_EXPANSION code needs corresponding quoting on variable expansion side. 2067 * Currently, "v='{q,w}'; echo $v" erroneously expands braces in $v. 2068 * Apparently, on unquoted $v bash still does globbing 2069 * ("v='*.txt'; echo $v" prints all .txt files), 2070 * but NOT brace expansion! Thus, there should be TWO independent 2071 * quoting mechanisms on $v expansion side: one protects 2072 * $v from brace expansion, and other additionally protects "$v" against globbing. 2073 * We have only second one. 2074 */ 2075 2076 #if ENABLE_HUSH_BRACE_EXPANSION 2077 # define MAYBE_BRACES "{}" 2078 #else 2079 # define MAYBE_BRACES "" 2080 #endif 2081 2082 /* My analysis of quoting semantics tells me that state information 2083 * is associated with a destination, not a source. 2084 */ 2085 static void o_addqchr(o_string *o, int ch) 2086 { 2087 int sz = 1; 2088 char *found = strchr("*?[\\" MAYBE_BRACES, ch); 2089 if (found) 2090 sz++; 2091 o_grow_by(o, sz); 2092 if (found) { 2093 o->data[o->length] = '\\'; 2094 o->length++; 2095 } 2096 o->data[o->length] = ch; 2097 o->length++; 2098 o->data[o->length] = '\0'; 2099 } 2100 2101 static void o_addQchr(o_string *o, int ch) 2102 { 2103 int sz = 1; 2104 if ((o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS) 2105 && strchr("*?[\\" MAYBE_BRACES, ch) 2106 ) { 2107 sz++; 2108 o->data[o->length] = '\\'; 2109 o->length++; 2110 } 2111 o_grow_by(o, sz); 2112 o->data[o->length] = ch; 2113 o->length++; 2114 o->data[o->length] = '\0'; 2115 } 2116 2117 static void o_addqblock(o_string *o, const char *str, int len) 2118 { 2119 while (len) { 2120 char ch; 2121 int sz; 2122 int ordinary_cnt = strcspn(str, "*?[\\" MAYBE_BRACES); 2123 if (ordinary_cnt > len) /* paranoia */ 2124 ordinary_cnt = len; 2125 o_addblock(o, str, ordinary_cnt); 2126 if (ordinary_cnt == len) 2127 return; 2128 str += ordinary_cnt; 2129 len -= ordinary_cnt + 1; /* we are processing + 1 char below */ 2130 2131 ch = *str++; 2132 sz = 1; 2133 if (ch) { /* it is necessarily one of "*?[\\" MAYBE_BRACES */ 2134 sz++; 2135 o->data[o->length] = '\\'; 2136 o->length++; 2137 } 2138 o_grow_by(o, sz); 2139 o->data[o->length] = ch; 2140 o->length++; 2141 o->data[o->length] = '\0'; 2142 } 2143 } 2144 2145 static void o_addQblock(o_string *o, const char *str, int len) 2146 { 2147 if (!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)) { 2148 o_addblock(o, str, len); 2149 return; 2150 } 2151 o_addqblock(o, str, len); 2152 } 2153 2154 static void o_addQstr(o_string *o, const char *str) 2155 { 2156 o_addQblock(o, str, strlen(str)); 2157 } 2158 2159 /* A special kind of o_string for $VAR and `cmd` expansion. 2160 * It contains char* list[] at the beginning, which is grown in 16 element 2161 * increments. Actual string data starts at the next multiple of 16 * (char*). 2162 * list[i] contains an INDEX (int!) into this string data. 2163 * It means that if list[] needs to grow, data needs to be moved higher up 2164 * but list[i]'s need not be modified. 2165 * NB: remembering how many list[i]'s you have there is crucial. 2166 * o_finalize_list() operation post-processes this structure - calculates 2167 * and stores actual char* ptrs in list[]. Oh, it NULL terminates it as well. 2168 */ 2169 #if DEBUG_EXPAND || DEBUG_GLOB 2170 static void debug_print_list(const char *prefix, o_string *o, int n) 2171 { 2172 char **list = (char**)o->data; 2173 int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]); 2174 int i = 0; 2175 2176 indent(); 2177 fdprintf(2, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d glob:%d quoted:%d escape:%d\n", 2178 prefix, list, n, string_start, o->length, o->maxlen, 2179 !!(o->o_expflags & EXP_FLAG_GLOB), 2180 o->has_quoted_part, 2181 !!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); 2182 while (i < n) { 2183 indent(); 2184 fdprintf(2, " list[%d]=%d '%s' %p\n", i, (int)(uintptr_t)list[i], 2185 o->data + (int)(uintptr_t)list[i] + string_start, 2186 o->data + (int)(uintptr_t)list[i] + string_start); 2187 i++; 2188 } 2189 if (n) { 2190 const char *p = o->data + (int)(uintptr_t)list[n - 1] + string_start; 2191 indent(); 2192 fdprintf(2, " total_sz:%ld\n", (long)((p + strlen(p) + 1) - o->data)); 2193 } 2194 } 2195 #else 2196 # define debug_print_list(prefix, o, n) ((void)0) 2197 #endif 2198 2199 /* n = o_save_ptr_helper(str, n) "starts new string" by storing an index value 2200 * in list[n] so that it points past last stored byte so far. 2201 * It returns n+1. */ 2202 static int o_save_ptr_helper(o_string *o, int n) 2203 { 2204 char **list = (char**)o->data; 2205 int string_start; 2206 int string_len; 2207 2208 if (!o->has_empty_slot) { 2209 string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]); 2210 string_len = o->length - string_start; 2211 if (!(n & 0xf)) { /* 0, 0x10, 0x20...? */ 2212 debug_printf_list("list[%d]=%d string_start=%d (growing)\n", n, string_len, string_start); 2213 /* list[n] points to string_start, make space for 16 more pointers */ 2214 o->maxlen += 0x10 * sizeof(list[0]); 2215 o->data = xrealloc(o->data, o->maxlen + 1); 2216 list = (char**)o->data; 2217 memmove(list + n + 0x10, list + n, string_len); 2218 o->length += 0x10 * sizeof(list[0]); 2219 } else { 2220 debug_printf_list("list[%d]=%d string_start=%d\n", 2221 n, string_len, string_start); 2222 } 2223 } else { 2224 /* We have empty slot at list[n], reuse without growth */ 2225 string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); /* NB: n+1! */ 2226 string_len = o->length - string_start; 2227 debug_printf_list("list[%d]=%d string_start=%d (empty slot)\n", 2228 n, string_len, string_start); 2229 o->has_empty_slot = 0; 2230 } 2231 list[n] = (char*)(uintptr_t)string_len; 2232 return n + 1; 2233 } 2234 2235 /* "What was our last o_save_ptr'ed position (byte offset relative o->data)?" */ 2236 static int o_get_last_ptr(o_string *o, int n) 2237 { 2238 char **list = (char**)o->data; 2239 int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]); 2240 2241 return ((int)(uintptr_t)list[n-1]) + string_start; 2242 } 2243 2244 #if ENABLE_HUSH_BRACE_EXPANSION 2245 /* There in a GNU extension, GLOB_BRACE, but it is not usable: 2246 * first, it processes even {a} (no commas), second, 2247 * I didn't manage to make it return strings when they don't match 2248 * existing files. Need to re-implement it. 2249 */ 2250 2251 /* Helper */ 2252 static int glob_needed(const char *s) 2253 { 2254 while (*s) { 2255 if (*s == '\\') { 2256 if (!s[1]) 2257 return 0; 2258 s += 2; 2259 continue; 2260 } 2261 if (*s == '*' || *s == '[' || *s == '?' || *s == '{') 2262 return 1; 2263 s++; 2264 } 2265 return 0; 2266 } 2267 /* Return pointer to next closing brace or to comma */ 2268 static const char *next_brace_sub(const char *cp) 2269 { 2270 unsigned depth = 0; 2271 cp++; 2272 while (*cp != '\0') { 2273 if (*cp == '\\') { 2274 if (*++cp == '\0') 2275 break; 2276 cp++; 2277 continue; 2278 } 2279 if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0)) 2280 break; 2281 if (*cp++ == '{') 2282 depth++; 2283 } 2284 2285 return *cp != '\0' ? cp : NULL; 2286 } 2287 /* Recursive brace globber. Note: may garble pattern[]. */ 2288 static int glob_brace(char *pattern, o_string *o, int n) 2289 { 2290 char *new_pattern_buf; 2291 const char *begin; 2292 const char *next; 2293 const char *rest; 2294 const char *p; 2295 size_t rest_len; 2296 2297 debug_printf_glob("glob_brace('%s')\n", pattern); 2298 2299 begin = pattern; 2300 while (1) { 2301 if (*begin == '\0') 2302 goto simple_glob; 2303 if (*begin == '{') { 2304 /* Find the first sub-pattern and at the same time 2305 * find the rest after the closing brace */ 2306 next = next_brace_sub(begin); 2307 if (next == NULL) { 2308 /* An illegal expression */ 2309 goto simple_glob; 2310 } 2311 if (*next == '}') { 2312 /* "{abc}" with no commas - illegal 2313 * brace expr, disregard and skip it */ 2314 begin = next + 1; 2315 continue; 2316 } 2317 break; 2318 } 2319 if (*begin == '\\' && begin[1] != '\0') 2320 begin++; 2321 begin++; 2322 } 2323 debug_printf_glob("begin:%s\n", begin); 2324 debug_printf_glob("next:%s\n", next); 2325 2326 /* Now find the end of the whole brace expression */ 2327 rest = next; 2328 while (*rest != '}') { 2329 rest = next_brace_sub(rest); 2330 if (rest == NULL) { 2331 /* An illegal expression */ 2332 goto simple_glob; 2333 } 2334 debug_printf_glob("rest:%s\n", rest); 2335 } 2336 rest_len = strlen(++rest) + 1; 2337 2338 /* We are sure the brace expression is well-formed */ 2339 2340 /* Allocate working buffer large enough for our work */ 2341 new_pattern_buf = xmalloc(strlen(pattern)); 2342 2343 /* We have a brace expression. BEGIN points to the opening {, 2344 * NEXT points past the terminator of the first element, and REST 2345 * points past the final }. We will accumulate result names from 2346 * recursive runs for each brace alternative in the buffer using 2347 * GLOB_APPEND. */ 2348 2349 p = begin + 1; 2350 while (1) { 2351 /* Construct the new glob expression */ 2352 memcpy( 2353 mempcpy( 2354 mempcpy(new_pattern_buf, 2355 /* We know the prefix for all sub-patterns */ 2356 pattern, begin - pattern), 2357 p, next - p), 2358 rest, rest_len); 2359 2360 /* Note: glob_brace() may garble new_pattern_buf[]. 2361 * That's why we re-copy prefix every time (1st memcpy above). 2362 */ 2363 n = glob_brace(new_pattern_buf, o, n); 2364 if (*next == '}') { 2365 /* We saw the last entry */ 2366 break; 2367 } 2368 p = next + 1; 2369 next = next_brace_sub(next); 2370 } 2371 free(new_pattern_buf); 2372 return n; 2373 2374 simple_glob: 2375 { 2376 int gr; 2377 glob_t globdata; 2378 2379 memset(&globdata, 0, sizeof(globdata)); 2380 gr = glob(pattern, 0, NULL, &globdata); 2381 debug_printf_glob("glob('%s'):%d\n", pattern, gr); 2382 if (gr != 0) { 2383 if (gr == GLOB_NOMATCH) { 2384 globfree(&globdata); 2385 /* NB: garbles parameter */ 2386 unbackslash(pattern); 2387 o_addstr_with_NUL(o, pattern); 2388 debug_printf_glob("glob pattern '%s' is literal\n", pattern); 2389 return o_save_ptr_helper(o, n); 2390 } 2391 if (gr == GLOB_NOSPACE) 2392 bb_error_msg_and_die(bb_msg_memory_exhausted); 2393 /* GLOB_ABORTED? Only happens with GLOB_ERR flag, 2394 * but we didn't specify it. Paranoia again. */ 2395 bb_error_msg_and_die("glob error %d on '%s'", gr, pattern); 2396 } 2397 if (globdata.gl_pathv && globdata.gl_pathv[0]) { 2398 char **argv = globdata.gl_pathv; 2399 while (1) { 2400 o_addstr_with_NUL(o, *argv); 2401 n = o_save_ptr_helper(o, n); 2402 argv++; 2403 if (!*argv) 2404 break; 2405 } 2406 } 2407 globfree(&globdata); 2408 } 2409 return n; 2410 } 2411 /* Performs globbing on last list[], 2412 * saving each result as a new list[]. 2413 */ 2414 static int perform_glob(o_string *o, int n) 2415 { 2416 char *pattern, *copy; 2417 2418 debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data); 2419 if (!o->data) 2420 return o_save_ptr_helper(o, n); 2421 pattern = o->data + o_get_last_ptr(o, n); 2422 debug_printf_glob("glob pattern '%s'\n", pattern); 2423 if (!glob_needed(pattern)) { 2424 /* unbackslash last string in o in place, fix length */ 2425 o->length = unbackslash(pattern) - o->data; 2426 debug_printf_glob("glob pattern '%s' is literal\n", pattern); 2427 return o_save_ptr_helper(o, n); 2428 } 2429 2430 copy = xstrdup(pattern); 2431 /* "forget" pattern in o */ 2432 o->length = pattern - o->data; 2433 n = glob_brace(copy, o, n); 2434 free(copy); 2435 if (DEBUG_GLOB) 2436 debug_print_list("perform_glob returning", o, n); 2437 return n; 2438 } 2439 2440 #else /* !HUSH_BRACE_EXPANSION */ 2441 2442 /* Helper */ 2443 static int glob_needed(const char *s) 2444 { 2445 while (*s) { 2446 if (*s == '\\') { 2447 if (!s[1]) 2448 return 0; 2449 s += 2; 2450 continue; 2451 } 2452 if (*s == '*' || *s == '[' || *s == '?') 2453 return 1; 2454 s++; 2455 } 2456 return 0; 2457 } 2458 /* Performs globbing on last list[], 2459 * saving each result as a new list[]. 2460 */ 2461 static int perform_glob(o_string *o, int n) 2462 { 2463 glob_t globdata; 2464 int gr; 2465 char *pattern; 2466 2467 debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data); 2468 if (!o->data) 2469 return o_save_ptr_helper(o, n); 2470 pattern = o->data + o_get_last_ptr(o, n); 2471 debug_printf_glob("glob pattern '%s'\n", pattern); 2472 if (!glob_needed(pattern)) { 2473 literal: 2474 /* unbackslash last string in o in place, fix length */ 2475 o->length = unbackslash(pattern) - o->data; 2476 debug_printf_glob("glob pattern '%s' is literal\n", pattern); 2477 return o_save_ptr_helper(o, n); 2478 } 2479 2480 memset(&globdata, 0, sizeof(globdata)); 2481 /* Can't use GLOB_NOCHECK: it does not unescape the string. 2482 * If we glob "*.\*" and don't find anything, we need 2483 * to fall back to using literal "*.*", but GLOB_NOCHECK 2484 * will return "*.\*"! 2485 */ 2486 gr = glob(pattern, 0, NULL, &globdata); 2487 debug_printf_glob("glob('%s'):%d\n", pattern, gr); 2488 if (gr != 0) { 2489 if (gr == GLOB_NOMATCH) { 2490 globfree(&globdata); 2491 goto literal; 2492 } 2493 if (gr == GLOB_NOSPACE) 2494 bb_error_msg_and_die(bb_msg_memory_exhausted); 2495 /* GLOB_ABORTED? Only happens with GLOB_ERR flag, 2496 * but we didn't specify it. Paranoia again. */ 2497 bb_error_msg_and_die("glob error %d on '%s'", gr, pattern); 2498 } 2499 if (globdata.gl_pathv && globdata.gl_pathv[0]) { 2500 char **argv = globdata.gl_pathv; 2501 /* "forget" pattern in o */ 2502 o->length = pattern - o->data; 2503 while (1) { 2504 o_addstr_with_NUL(o, *argv); 2505 n = o_save_ptr_helper(o, n); 2506 argv++; 2507 if (!*argv) 2508 break; 2509 } 2510 } 2511 globfree(&globdata); 2512 if (DEBUG_GLOB) 2513 debug_print_list("perform_glob returning", o, n); 2514 return n; 2515 } 2516 2517 #endif /* !HUSH_BRACE_EXPANSION */ 2518 2519 /* If o->o_expflags & EXP_FLAG_GLOB, glob the string so far remembered. 2520 * Otherwise, just finish current list[] and start new */ 2521 static int o_save_ptr(o_string *o, int n) 2522 { 2523 if (o->o_expflags & EXP_FLAG_GLOB) { 2524 /* If o->has_empty_slot, list[n] was already globbed 2525 * (if it was requested back then when it was filled) 2526 * so don't do that again! */ 2527 if (!o->has_empty_slot) 2528 return perform_glob(o, n); /* o_save_ptr_helper is inside */ 2529 } 2530 return o_save_ptr_helper(o, n); 2531 } 2532 2533 /* "Please convert list[n] to real char* ptrs, and NULL terminate it." */ 2534 static char **o_finalize_list(o_string *o, int n) 2535 { 2536 char **list; 2537 int string_start; 2538 2539 n = o_save_ptr(o, n); /* force growth for list[n] if necessary */ 2540 if (DEBUG_EXPAND) 2541 debug_print_list("finalized", o, n); 2542 debug_printf_expand("finalized n:%d\n", n); 2543 list = (char**)o->data; 2544 string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]); 2545 list[--n] = NULL; 2546 while (n) { 2547 n--; 2548 list[n] = o->data + (int)(uintptr_t)list[n] + string_start; 2549 } 2550 return list; 2551 } 2552 2553 static void free_pipe_list(struct pipe *pi); 2554 2555 /* Returns pi->next - next pipe in the list */ 2556 static struct pipe *free_pipe(struct pipe *pi) 2557 { 2558 struct pipe *next; 2559 int i; 2560 2561 debug_printf_clean("free_pipe (pid %d)\n", getpid()); 2562 for (i = 0; i < pi->num_cmds; i++) { 2563 struct command *command; 2564 struct redir_struct *r, *rnext; 2565 2566 command = &pi->cmds[i]; 2567 debug_printf_clean(" command %d:\n", i); 2568 if (command->argv) { 2569 if (DEBUG_CLEAN) { 2570 int a; 2571 char **p; 2572 for (a = 0, p = command->argv; *p; a++, p++) { 2573 debug_printf_clean(" argv[%d] = %s\n", a, *p); 2574 } 2575 } 2576 free_strings(command->argv); 2577 //command->argv = NULL; 2578 } 2579 /* not "else if": on syntax error, we may have both! */ 2580 if (command->group) { 2581 debug_printf_clean(" begin group (cmd_type:%d)\n", 2582 command->cmd_type); 2583 free_pipe_list(command->group); 2584 debug_printf_clean(" end group\n"); 2585 //command->group = NULL; 2586 } 2587 /* else is crucial here. 2588 * If group != NULL, child_func is meaningless */ 2589 #if ENABLE_HUSH_FUNCTIONS 2590 else if (command->child_func) { 2591 debug_printf_exec("cmd %p releases child func at %p\n", command, command->child_func); 2592 command->child_func->parent_cmd = NULL; 2593 } 2594 #endif 2595 #if !BB_MMU 2596 free(command->group_as_string); 2597 //command->group_as_string = NULL; 2598 #endif 2599 for (r = command->redirects; r; r = rnext) { 2600 debug_printf_clean(" redirect %d%s", 2601 r->rd_fd, redir_table[r->rd_type].descrip); 2602 /* guard against the case >$FOO, where foo is unset or blank */ 2603 if (r->rd_filename) { 2604 debug_printf_clean(" fname:'%s'\n", r->rd_filename); 2605 free(r->rd_filename); 2606 //r->rd_filename = NULL; 2607 } 2608 debug_printf_clean(" rd_dup:%d\n", r->rd_dup); 2609 rnext = r->next; 2610 free(r); 2611 } 2612 //command->redirects = NULL; 2613 } 2614 free(pi->cmds); /* children are an array, they get freed all at once */ 2615 //pi->cmds = NULL; 2616 #if ENABLE_HUSH_JOB 2617 free(pi->cmdtext); 2618 //pi->cmdtext = NULL; 2619 #endif 2620 2621 next = pi->next; 2622 free(pi); 2623 return next; 2624 } 2625 2626 static void free_pipe_list(struct pipe *pi) 2627 { 2628 while (pi) { 2629 #if HAS_KEYWORDS 2630 debug_printf_clean("pipe reserved word %d\n", pi->res_word); 2631 #endif 2632 debug_printf_clean("pipe followup code %d\n", pi->followup); 2633 pi = free_pipe(pi); 2634 } 2635 } 2636 2637 2638 /*** Parsing routines ***/ 2639 2640 #ifndef debug_print_tree 2641 static void debug_print_tree(struct pipe *pi, int lvl) 2642 { 2643 static const char *const PIPE[] = { 2644 [PIPE_SEQ] = "SEQ", 2645 [PIPE_AND] = "AND", 2646 [PIPE_OR ] = "OR" , 2647 [PIPE_BG ] = "BG" , 2648 }; 2649 static const char *RES[] = { 2650 [RES_NONE ] = "NONE" , 2651 # if ENABLE_HUSH_IF 2652 [RES_IF ] = "IF" , 2653 [RES_THEN ] = "THEN" , 2654 [RES_ELIF ] = "ELIF" , 2655 [RES_ELSE ] = "ELSE" , 2656 [RES_FI ] = "FI" , 2657 # endif 2658 # if ENABLE_HUSH_LOOPS 2659 [RES_FOR ] = "FOR" , 2660 [RES_WHILE] = "WHILE", 2661 [RES_UNTIL] = "UNTIL", 2662 [RES_DO ] = "DO" , 2663 [RES_DONE ] = "DONE" , 2664 # endif 2665 # if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE 2666 [RES_IN ] = "IN" , 2667 # endif 2668 # if ENABLE_HUSH_CASE 2669 [RES_CASE ] = "CASE" , 2670 [RES_CASE_IN ] = "CASE_IN" , 2671 [RES_MATCH] = "MATCH", 2672 [RES_CASE_BODY] = "CASE_BODY", 2673 [RES_ESAC ] = "ESAC" , 2674 # endif 2675 [RES_XXXX ] = "XXXX" , 2676 [RES_SNTX ] = "SNTX" , 2677 }; 2678 static const char *const CMDTYPE[] = { 2679 "{}", 2680 "()", 2681 "[noglob]", 2682 # if ENABLE_HUSH_FUNCTIONS 2683 "func()", 2684 # endif 2685 }; 2686 2687 int pin, prn; 2688 2689 pin = 0; 2690 while (pi) { 2691 fdprintf(2, "%*spipe %d res_word=%s followup=%d %s\n", lvl*2, "", 2692 pin, RES[pi->res_word], pi->followup, PIPE[pi->followup]); 2693 prn = 0; 2694 while (prn < pi->num_cmds) { 2695 struct command *command = &pi->cmds[prn]; 2696 char **argv = command->argv; 2697 2698 fdprintf(2, "%*s cmd %d assignment_cnt:%d", 2699 lvl*2, "", prn, 2700 command->assignment_cnt); 2701 if (command->group) { 2702 fdprintf(2, " group %s: (argv=%p)%s%s\n", 2703 CMDTYPE[command->cmd_type], 2704 argv 2705 # if !BB_MMU 2706 , " group_as_string:", command->group_as_string 2707 # else 2708 , "", "" 2709 # endif 2710 ); 2711 debug_print_tree(command->group, lvl+1); 2712 prn++; 2713 continue; 2714 } 2715 if (argv) while (*argv) { 2716 fdprintf(2, " '%s'", *argv); 2717 argv++; 2718 } 2719 fdprintf(2, "\n"); 2720 prn++; 2721 } 2722 pi = pi->next; 2723 pin++; 2724 } 2725 } 2726 #endif /* debug_print_tree */ 2727 2728 static struct pipe *new_pipe(void) 2729 { 2730 struct pipe *pi; 2731 pi = xzalloc(sizeof(struct pipe)); 2732 /*pi->followup = 0; - deliberately invalid value */ 2733 /*pi->res_word = RES_NONE; - RES_NONE is 0 anyway */ 2734 return pi; 2735 } 2736 2737 /* Command (member of a pipe) is complete, or we start a new pipe 2738 * if ctx->command is NULL. 2739 * No errors possible here. 2740 */ 2741 static int done_command(struct parse_context *ctx) 2742 { 2743 /* The command is really already in the pipe structure, so 2744 * advance the pipe counter and make a new, null command. */ 2745 struct pipe *pi = ctx->pipe; 2746 struct command *command = ctx->command; 2747 2748 if (command) { 2749 if (IS_NULL_CMD(command)) { 2750 debug_printf_parse("done_command: skipping null cmd, num_cmds=%d\n", pi->num_cmds); 2751 goto clear_and_ret; 2752 } 2753 pi->num_cmds++; 2754 debug_printf_parse("done_command: ++num_cmds=%d\n", pi->num_cmds); 2755 //debug_print_tree(ctx->list_head, 20); 2756 } else { 2757 debug_printf_parse("done_command: initializing, num_cmds=%d\n", pi->num_cmds); 2758 } 2759 2760 /* Only real trickiness here is that the uncommitted 2761 * command structure is not counted in pi->num_cmds. */ 2762 pi->cmds = xrealloc(pi->cmds, sizeof(*pi->cmds) * (pi->num_cmds+1)); 2763 ctx->command = command = &pi->cmds[pi->num_cmds]; 2764 clear_and_ret: 2765 memset(command, 0, sizeof(*command)); 2766 return pi->num_cmds; /* used only for 0/nonzero check */ 2767 } 2768 2769 static void done_pipe(struct parse_context *ctx, pipe_style type) 2770 { 2771 int not_null; 2772 2773 debug_printf_parse("done_pipe entered, followup %d\n", type); 2774 /* Close previous command */ 2775 not_null = done_command(ctx); 2776 ctx->pipe->followup = type; 2777 #if HAS_KEYWORDS 2778 ctx->pipe->pi_inverted = ctx->ctx_inverted; 2779 ctx->ctx_inverted = 0; 2780 ctx->pipe->res_word = ctx->ctx_res_w; 2781 #endif 2782 2783 /* Without this check, even just <enter> on command line generates 2784 * tree of three NOPs (!). Which is harmless but annoying. 2785 * IOW: it is safe to do it unconditionally. */ 2786 if (not_null 2787 #if ENABLE_HUSH_IF 2788 || ctx->ctx_res_w == RES_FI 2789 #endif 2790 #if ENABLE_HUSH_LOOPS 2791 || ctx->ctx_res_w == RES_DONE 2792 || ctx->ctx_res_w == RES_FOR 2793 || ctx->ctx_res_w == RES_IN 2794 #endif 2795 #if ENABLE_HUSH_CASE 2796 || ctx->ctx_res_w == RES_ESAC 2797 #endif 2798 ) { 2799 struct pipe *new_p; 2800 debug_printf_parse("done_pipe: adding new pipe: " 2801 "not_null:%d ctx->ctx_res_w:%d\n", 2802 not_null, ctx->ctx_res_w); 2803 new_p = new_pipe(); 2804 ctx->pipe->next = new_p; 2805 ctx->pipe = new_p; 2806 /* RES_THEN, RES_DO etc are "sticky" - 2807 * they remain set for pipes inside if/while. 2808 * This is used to control execution. 2809 * RES_FOR and RES_IN are NOT sticky (needed to support 2810 * cases where variable or value happens to match a keyword): 2811 */ 2812 #if ENABLE_HUSH_LOOPS 2813 if (ctx->ctx_res_w == RES_FOR 2814 || ctx->ctx_res_w == RES_IN) 2815 ctx->ctx_res_w = RES_NONE; 2816 #endif 2817 #if ENABLE_HUSH_CASE 2818 if (ctx->ctx_res_w == RES_MATCH) 2819 ctx->ctx_res_w = RES_CASE_BODY; 2820 if (ctx->ctx_res_w == RES_CASE) 2821 ctx->ctx_res_w = RES_CASE_IN; 2822 #endif 2823 ctx->command = NULL; /* trick done_command below */ 2824 /* Create the memory for command, roughly: 2825 * ctx->pipe->cmds = new struct command; 2826 * ctx->command = &ctx->pipe->cmds[0]; 2827 */ 2828 done_command(ctx); 2829 //debug_print_tree(ctx->list_head, 10); 2830 } 2831 debug_printf_parse("done_pipe return\n"); 2832 } 2833 2834 static void initialize_context(struct parse_context *ctx) 2835 { 2836 memset(ctx, 0, sizeof(*ctx)); 2837 ctx->pipe = ctx->list_head = new_pipe(); 2838 /* Create the memory for command, roughly: 2839 * ctx->pipe->cmds = new struct command; 2840 * ctx->command = &ctx->pipe->cmds[0]; 2841 */ 2842 done_command(ctx); 2843 } 2844 2845 /* If a reserved word is found and processed, parse context is modified 2846 * and 1 is returned. 2847 */ 2848 #if HAS_KEYWORDS 2849 struct reserved_combo { 2850 char literal[6]; 2851 unsigned char res; 2852 unsigned char assignment_flag; 2853 int flag; 2854 }; 2855 enum { 2856 FLAG_END = (1 << RES_NONE ), 2857 # if ENABLE_HUSH_IF 2858 FLAG_IF = (1 << RES_IF ), 2859 FLAG_THEN = (1 << RES_THEN ), 2860 FLAG_ELIF = (1 << RES_ELIF ), 2861 FLAG_ELSE = (1 << RES_ELSE ), 2862 FLAG_FI = (1 << RES_FI ), 2863 # endif 2864 # if ENABLE_HUSH_LOOPS 2865 FLAG_FOR = (1 << RES_FOR ), 2866 FLAG_WHILE = (1 << RES_WHILE), 2867 FLAG_UNTIL = (1 << RES_UNTIL), 2868 FLAG_DO = (1 << RES_DO ), 2869 FLAG_DONE = (1 << RES_DONE ), 2870 FLAG_IN = (1 << RES_IN ), 2871 # endif 2872 # if ENABLE_HUSH_CASE 2873 FLAG_MATCH = (1 << RES_MATCH), 2874 FLAG_ESAC = (1 << RES_ESAC ), 2875 # endif 2876 FLAG_START = (1 << RES_XXXX ), 2877 }; 2878 2879 static const struct reserved_combo* match_reserved_word(o_string *word) 2880 { 2881 /* Mostly a list of accepted follow-up reserved words. 2882 * FLAG_END means we are done with the sequence, and are ready 2883 * to turn the compound list into a command. 2884 * FLAG_START means the word must start a new compound list. 2885 */ 2886 static const struct reserved_combo reserved_list[] = { 2887 # if ENABLE_HUSH_IF 2888 { "!", RES_NONE, NOT_ASSIGNMENT , 0 }, 2889 { "if", RES_IF, WORD_IS_KEYWORD, FLAG_THEN | FLAG_START }, 2890 { "then", RES_THEN, WORD_IS_KEYWORD, FLAG_ELIF | FLAG_ELSE | FLAG_FI }, 2891 { "elif", RES_ELIF, WORD_IS_KEYWORD, FLAG_THEN }, 2892 { "else", RES_ELSE, WORD_IS_KEYWORD, FLAG_FI }, 2893 { "fi", RES_FI, NOT_ASSIGNMENT , FLAG_END }, 2894 # endif 2895 # if ENABLE_HUSH_LOOPS 2896 { "for", RES_FOR, NOT_ASSIGNMENT , FLAG_IN | FLAG_DO | FLAG_START }, 2897 { "while", RES_WHILE, WORD_IS_KEYWORD, FLAG_DO | FLAG_START }, 2898 { "until", RES_UNTIL, WORD_IS_KEYWORD, FLAG_DO | FLAG_START }, 2899 { "in", RES_IN, NOT_ASSIGNMENT , FLAG_DO }, 2900 { "do", RES_DO, WORD_IS_KEYWORD, FLAG_DONE }, 2901 { "done", RES_DONE, NOT_ASSIGNMENT , FLAG_END }, 2902 # endif 2903 # if ENABLE_HUSH_CASE 2904 { "case", RES_CASE, NOT_ASSIGNMENT , FLAG_MATCH | FLAG_START }, 2905 { "esac", RES_ESAC, NOT_ASSIGNMENT , FLAG_END }, 2906 # endif 2907 }; 2908 const struct reserved_combo *r; 2909 2910 for (r = reserved_list; r < reserved_list + ARRAY_SIZE(reserved_list); r++) { 2911 if (strcmp(word->data, r->literal) == 0) 2912 return r; 2913 } 2914 return NULL; 2915 } 2916 /* Return 0: not a keyword, 1: keyword 2917 */ 2918 static int reserved_word(o_string *word, struct parse_context *ctx) 2919 { 2920 # if ENABLE_HUSH_CASE 2921 static const struct reserved_combo reserved_match = { 2922 "", RES_MATCH, NOT_ASSIGNMENT , FLAG_MATCH | FLAG_ESAC 2923 }; 2924 # endif 2925 const struct reserved_combo *r; 2926 2927 if (word->has_quoted_part) 2928 return 0; 2929 r = match_reserved_word(word); 2930 if (!r) 2931 return 0; 2932 2933 debug_printf("found reserved word %s, res %d\n", r->literal, r->res); 2934 # if ENABLE_HUSH_CASE 2935 if (r->res == RES_IN && ctx->ctx_res_w == RES_CASE_IN) { 2936 /* "case word IN ..." - IN part starts first MATCH part */ 2937 r = &reserved_match; 2938 } else 2939 # endif 2940 if (r->flag == 0) { /* '!' */ 2941 if (ctx->ctx_inverted) { /* bash doesn't accept '! ! true' */ 2942 syntax_error("! ! command"); 2943 ctx->ctx_res_w = RES_SNTX; 2944 } 2945 ctx->ctx_inverted = 1; 2946 return 1; 2947 } 2948 if (r->flag & FLAG_START) { 2949 struct parse_context *old; 2950 2951 old = xmalloc(sizeof(*old)); 2952 debug_printf_parse("push stack %p\n", old); 2953 *old = *ctx; /* physical copy */ 2954 initialize_context(ctx); 2955 ctx->stack = old; 2956 } else if (/*ctx->ctx_res_w == RES_NONE ||*/ !(ctx->old_flag & (1 << r->res))) { 2957 syntax_error_at(word->data); 2958 ctx->ctx_res_w = RES_SNTX; 2959 return 1; 2960 } else { 2961 /* "{...} fi" is ok. "{...} if" is not 2962 * Example: 2963 * if { echo foo; } then { echo bar; } fi */ 2964 if (ctx->command->group) 2965 done_pipe(ctx, PIPE_SEQ); 2966 } 2967 2968 ctx->ctx_res_w = r->res; 2969 ctx->old_flag = r->flag; 2970 word->o_assignment = r->assignment_flag; 2971 2972 if (ctx->old_flag & FLAG_END) { 2973 struct parse_context *old; 2974 2975 done_pipe(ctx, PIPE_SEQ); 2976 debug_printf_parse("pop stack %p\n", ctx->stack); 2977 old = ctx->stack; 2978 old->command->group = ctx->list_head; 2979 old->command->cmd_type = CMD_NORMAL; 2980 # if !BB_MMU 2981 o_addstr(&old->as_string, ctx->as_string.data); 2982 o_free_unsafe(&ctx->as_string); 2983 old->command->group_as_string = xstrdup(old->as_string.data); 2984 debug_printf_parse("pop, remembering as:'%s'\n", 2985 old->command->group_as_string); 2986 # endif 2987 *ctx = *old; /* physical copy */ 2988 free(old); 2989 } 2990 return 1; 2991 } 2992 #endif /* HAS_KEYWORDS */ 2993 2994 /* Word is complete, look at it and update parsing context. 2995 * Normal return is 0. Syntax errors return 1. 2996 * Note: on return, word is reset, but not o_free'd! 2997 */ 2998 static int done_word(o_string *word, struct parse_context *ctx) 2999 { 3000 struct command *command = ctx->command; 3001 3002 debug_printf_parse("done_word entered: '%s' %p\n", word->data, command); 3003 if (word->length == 0 && !word->has_quoted_part) { 3004 debug_printf_parse("done_word return 0: true null, ignored\n"); 3005 return 0; 3006 } 3007 3008 if (ctx->pending_redirect) { 3009 /* We do not glob in e.g. >*.tmp case. bash seems to glob here 3010 * only if run as "bash", not "sh" */ 3011 /* http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html 3012 * "2.7 Redirection 3013 * ...the word that follows the redirection operator 3014 * shall be subjected to tilde expansion, parameter expansion, 3015 * command substitution, arithmetic expansion, and quote 3016 * removal. Pathname expansion shall not be performed 3017 * on the word by a non-interactive shell; an interactive 3018 * shell may perform it, but shall do so only when 3019 * the expansion would result in one word." 3020 */ 3021 ctx->pending_redirect->rd_filename = xstrdup(word->data); 3022 /* Cater for >\file case: 3023 * >\a creates file a; >\\a, >"\a", >"\\a" create file \a 3024 * Same with heredocs: 3025 * for <<\H delim is H; <<\\H, <<"\H", <<"\\H" - \H 3026 */ 3027 if (ctx->pending_redirect->rd_type == REDIRECT_HEREDOC) { 3028 unbackslash(ctx->pending_redirect->rd_filename); 3029 /* Is it <<"HEREDOC"? */ 3030 if (word->has_quoted_part) { 3031 ctx->pending_redirect->rd_dup |= HEREDOC_QUOTED; 3032 } 3033 } 3034 debug_printf_parse("word stored in rd_filename: '%s'\n", word->data); 3035 ctx->pending_redirect = NULL; 3036 } else { 3037 /* If this word wasn't an assignment, next ones definitely 3038 * can't be assignments. Even if they look like ones. */ 3039 if (word->o_assignment != DEFINITELY_ASSIGNMENT 3040 && word->o_assignment != WORD_IS_KEYWORD 3041 ) { 3042 word->o_assignment = NOT_ASSIGNMENT; 3043 } else { 3044 if (word->o_assignment == DEFINITELY_ASSIGNMENT) 3045 command->assignment_cnt++; 3046 word->o_assignment = MAYBE_ASSIGNMENT; 3047 } 3048 3049 #if HAS_KEYWORDS 3050 # if ENABLE_HUSH_CASE 3051 if (ctx->ctx_dsemicolon 3052 && strcmp(word->data, "esac") != 0 /* not "... pattern) cmd;; esac" */ 3053 ) { 3054 /* already done when ctx_dsemicolon was set to 1: */ 3055 /* ctx->ctx_res_w = RES_MATCH; */ 3056 ctx->ctx_dsemicolon = 0; 3057 } else 3058 # endif 3059 if (!command->argv /* if it's the first word... */ 3060 # if ENABLE_HUSH_LOOPS 3061 && ctx->ctx_res_w != RES_FOR /* ...not after FOR or IN */ 3062 && ctx->ctx_res_w != RES_IN 3063 # endif 3064 # if ENABLE_HUSH_CASE 3065 && ctx->ctx_res_w != RES_CASE 3066 # endif 3067 ) { 3068 debug_printf_parse("checking '%s' for reserved-ness\n", word->data); 3069 if (reserved_word(word, ctx)) { 3070 o_reset_to_empty_unquoted(word); 3071 debug_printf_parse("done_word return %d\n", 3072 (ctx->ctx_res_w == RES_SNTX)); 3073 return (ctx->ctx_res_w == RES_SNTX); 3074 } 3075 # if ENABLE_HUSH_BASH_COMPAT 3076 if (strcmp(word->data, "[[") == 0) { 3077 command->cmd_type = CMD_SINGLEWORD_NOGLOB; 3078 } 3079 /* fall through */ 3080 # endif 3081 } 3082 #endif 3083 if (command->group) { 3084 /* "{ echo foo; } echo bar" - bad */ 3085 syntax_error_at(word->data); 3086 debug_printf_parse("done_word return 1: syntax error, " 3087 "groups and arglists don't mix\n"); 3088 return 1; 3089 } 3090 if (word->has_quoted_part 3091 /* optimization: and if it's ("" or '') or ($v... or `cmd`...): */ 3092 && (word->data[0] == '\0' || word->data[0] == SPECIAL_VAR_SYMBOL) 3093 /* (otherwise it's known to be not empty and is already safe) */ 3094 ) { 3095 /* exclude "$@" - it can expand to no word despite "" */ 3096 char *p = word->data; 3097 while (p[0] == SPECIAL_VAR_SYMBOL 3098 && (p[1] & 0x7f) == '@' 3099 && p[2] == SPECIAL_VAR_SYMBOL 3100 ) { 3101 p += 3; 3102 } 3103 if (p == word->data || p[0] != '\0') { 3104 /* saw no "$@", or not only "$@" but some 3105 * real text is there too */ 3106 /* insert "empty variable" reference, this makes 3107 * e.g. "", $empty"" etc to not disappear */ 3108 o_addchr(word, SPECIAL_VAR_SYMBOL); 3109 o_addchr(word, SPECIAL_VAR_SYMBOL); 3110 } 3111 } 3112 command->argv = add_string_to_strings(command->argv, xstrdup(word->data)); 3113 debug_print_strings("word appended to argv", command->argv); 3114 } 3115 3116 #if ENABLE_HUSH_LOOPS 3117 if (ctx->ctx_res_w == RES_FOR) { 3118 if (word->has_quoted_part 3119 || !is_well_formed_var_name(command->argv[0], '\0') 3120 ) { 3121 /* bash says just "not a valid identifier" */ 3122 syntax_error("not a valid identifier in for"); 3123 return 1; 3124 } 3125 /* Force FOR to have just one word (variable name) */ 3126 /* NB: basically, this makes hush see "for v in ..." 3127 * syntax as if it is "for v; in ...". FOR and IN become 3128 * two pipe structs in parse tree. */ 3129 done_pipe(ctx, PIPE_SEQ); 3130 } 3131 #endif 3132 #if ENABLE_HUSH_CASE 3133 /* Force CASE to have just one word */ 3134 if (ctx->ctx_res_w == RES_CASE) { 3135 done_pipe(ctx, PIPE_SEQ); 3136 } 3137 #endif 3138 3139 o_reset_to_empty_unquoted(word); 3140 3141 debug_printf_parse("done_word return 0\n"); 3142 return 0; 3143 } 3144 3145 3146 /* Peek ahead in the input to find out if we have a "&n" construct, 3147 * as in "2>&1", that represents duplicating a file descriptor. 3148 * Return: 3149 * REDIRFD_CLOSE if >&- "close fd" construct is seen, 3150 * REDIRFD_SYNTAX_ERR if syntax error, 3151 * REDIRFD_TO_FILE if no & was seen, 3152 * or the number found. 3153 */ 3154 #if BB_MMU 3155 #define parse_redir_right_fd(as_string, input) \ 3156 parse_redir_right_fd(input) 3157 #endif 3158 static int parse_redir_right_fd(o_string *as_string, struct in_str *input) 3159 { 3160 int ch, d, ok; 3161 3162 ch = i_peek(input); 3163 if (ch != '&') 3164 return REDIRFD_TO_FILE; 3165 3166 ch = i_getch(input); /* get the & */ 3167 nommu_addchr(as_string, ch); 3168 ch = i_peek(input); 3169 if (ch == '-') { 3170 ch = i_getch(input); 3171 nommu_addchr(as_string, ch); 3172 return REDIRFD_CLOSE; 3173 } 3174 d = 0; 3175 ok = 0; 3176 while (ch != EOF && isdigit(ch)) { 3177 d = d*10 + (ch-'0'); 3178 ok = 1; 3179 ch = i_getch(input); 3180 nommu_addchr(as_string, ch); 3181 ch = i_peek(input); 3182 } 3183 if (ok) return d; 3184 3185 //TODO: this is the place to catch ">&file" bashism (redirect both fd 1 and 2) 3186 3187 bb_error_msg("ambiguous redirect"); 3188 return REDIRFD_SYNTAX_ERR; 3189 } 3190 3191 /* Return code is 0 normal, 1 if a syntax error is detected 3192 */ 3193 static int parse_redirect(struct parse_context *ctx, 3194 int fd, 3195 redir_type style, 3196 struct in_str *input) 3197 { 3198 struct command *command = ctx->command; 3199 struct redir_struct *redir; 3200 struct redir_struct **redirp; 3201 int dup_num; 3202 3203 dup_num = REDIRFD_TO_FILE; 3204 if (style != REDIRECT_HEREDOC) { 3205 /* Check for a '>&1' type redirect */ 3206 dup_num = parse_redir_right_fd(&ctx->as_string, input); 3207 if (dup_num == REDIRFD_SYNTAX_ERR) 3208 return 1; 3209 } else { 3210 int ch = i_peek(input); 3211 dup_num = (ch == '-'); /* HEREDOC_SKIPTABS bit is 1 */ 3212 if (dup_num) { /* <<-... */ 3213 ch = i_getch(input); 3214 nommu_addchr(&ctx->as_string, ch); 3215 ch = i_peek(input); 3216 } 3217 } 3218 3219 if (style == REDIRECT_OVERWRITE && dup_num == REDIRFD_TO_FILE) { 3220 int ch = i_peek(input); 3221 if (ch == '|') { 3222 /* >|FILE redirect ("clobbering" >). 3223 * Since we do not support "set -o noclobber" yet, 3224 * >| and > are the same for now. Just eat |. 3225 */ 3226 ch = i_getch(input); 3227 nommu_addchr(&ctx->as_string, ch); 3228 } 3229 } 3230 3231 /* Create a new redir_struct and append it to the linked list */ 3232 redirp = &command->redirects; 3233 while ((redir = *redirp) != NULL) { 3234 redirp = &(redir->next); 3235 } 3236 *redirp = redir = xzalloc(sizeof(*redir)); 3237 /* redir->next = NULL; */ 3238 /* redir->rd_filename = NULL; */ 3239 redir->rd_type = style; 3240 redir->rd_fd = (fd == -1) ? redir_table[style].default_fd : fd; 3241 3242 debug_printf_parse("redirect type %d %s\n", redir->rd_fd, 3243 redir_table[style].descrip); 3244 3245 redir->rd_dup = dup_num; 3246 if (style != REDIRECT_HEREDOC && dup_num != REDIRFD_TO_FILE) { 3247 /* Erik had a check here that the file descriptor in question 3248 * is legit; I postpone that to "run time" 3249 * A "-" representation of "close me" shows up as a -3 here */ 3250 debug_printf_parse("duplicating redirect '%d>&%d'\n", 3251 redir->rd_fd, redir->rd_dup); 3252 } else { 3253 /* Set ctx->pending_redirect, so we know what to do at the 3254 * end of the next parsed word. */ 3255 ctx->pending_redirect = redir; 3256 } 3257 return 0; 3258 } 3259 3260 /* If a redirect is immediately preceded by a number, that number is 3261 * supposed to tell which file descriptor to redirect. This routine 3262 * looks for such preceding numbers. In an ideal world this routine 3263 * needs to handle all the following classes of redirects... 3264 * echo 2>foo # redirects fd 2 to file "foo", nothing passed to echo 3265 * echo 49>foo # redirects fd 49 to file "foo", nothing passed to echo 3266 * echo -2>foo # redirects fd 1 to file "foo", "-2" passed to echo 3267 * echo 49x>foo # redirects fd 1 to file "foo", "49x" passed to echo 3268 * 3269 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html 3270 * "2.7 Redirection 3271 * ... If n is quoted, the number shall not be recognized as part of 3272 * the redirection expression. For example: 3273 * echo \2>a 3274 * writes the character 2 into file a" 3275 * We are getting it right by setting ->has_quoted_part on any \<char> 3276 * 3277 * A -1 return means no valid number was found, 3278 * the caller should use the appropriate default for this redirection. 3279 */ 3280 static int redirect_opt_num(o_string *o) 3281 { 3282 int num; 3283 3284 if (o->data == NULL) 3285 return -1; 3286 num = bb_strtou(o->data, NULL, 10); 3287 if (errno || num < 0) 3288 return -1; 3289 o_reset_to_empty_unquoted(o); 3290 return num; 3291 } 3292 3293 #if BB_MMU 3294 #define fetch_till_str(as_string, input, word, skip_tabs) \ 3295 fetch_till_str(input, word, skip_tabs) 3296 #endif 3297 static char *fetch_till_str(o_string *as_string, 3298 struct in_str *input, 3299 const char *word, 3300 int heredoc_flags) 3301 { 3302 o_string heredoc = NULL_O_STRING; 3303 unsigned past_EOL; 3304 int prev = 0; /* not \ */ 3305 int ch; 3306 3307 goto jump_in; 3308 while (1) { 3309 ch = i_getch(input); 3310 if (ch != EOF) 3311 nommu_addchr(as_string, ch); 3312 if ((ch == '\n' || ch == EOF) 3313 && ((heredoc_flags & HEREDOC_QUOTED) || prev != '\\') 3314 ) { 3315 if (strcmp(heredoc.data + past_EOL, word) == 0) { 3316 heredoc.data[past_EOL] = '\0'; 3317 debug_printf_parse("parsed heredoc '%s'\n", heredoc.data); 3318 return heredoc.data; 3319 } 3320 while (ch == '\n') { 3321 o_addchr(&heredoc, ch); 3322 prev = ch; 3323 jump_in: 3324 past_EOL = heredoc.length; 3325 do { 3326 ch = i_getch(input); 3327 if (ch != EOF) 3328 nommu_addchr(as_string, ch); 3329 } while ((heredoc_flags & HEREDOC_SKIPTABS) && ch == '\t'); 3330 } 3331 } 3332 if (ch == EOF) { 3333 o_free_unsafe(&heredoc); 3334 return NULL; 3335 } 3336 o_addchr(&heredoc, ch); 3337 nommu_addchr(as_string, ch); 3338 if (prev == '\\' && ch == '\\') 3339 /* Correctly handle foo\\<eol> (not a line cont.) */ 3340 prev = 0; /* not \ */ 3341 else 3342 prev = ch; 3343 } 3344 } 3345 3346 /* Look at entire parse tree for not-yet-loaded REDIRECT_HEREDOCs 3347 * and load them all. There should be exactly heredoc_cnt of them. 3348 */ 3349 static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_str *input) 3350 { 3351 struct pipe *pi = ctx->list_head; 3352 3353 while (pi && heredoc_cnt) { 3354 int i; 3355 struct command *cmd = pi->cmds; 3356 3357 debug_printf_parse("fetch_heredocs: num_cmds:%d cmd argv0:'%s'\n", 3358 pi->num_cmds, 3359 cmd->argv ? cmd->argv[0] : "NONE"); 3360 for (i = 0; i < pi->num_cmds; i++) { 3361 struct redir_struct *redir = cmd->redirects; 3362 3363 debug_printf_parse("fetch_heredocs: %d cmd argv0:'%s'\n", 3364 i, cmd->argv ? cmd->argv[0] : "NONE"); 3365 while (redir) { 3366 if (redir->rd_type == REDIRECT_HEREDOC) { 3367 char *p; 3368 3369 redir->rd_type = REDIRECT_HEREDOC2; 3370 /* redir->rd_dup is (ab)used to indicate <<- */ 3371 p = fetch_till_str(&ctx->as_string, input, 3372 redir->rd_filename, redir->rd_dup); 3373 if (!p) { 3374 syntax_error("unexpected EOF in here document"); 3375 return 1; 3376 } 3377 free(redir->rd_filename); 3378 redir->rd_filename = p; 3379 heredoc_cnt--; 3380 } 3381 redir = redir->next; 3382 } 3383 cmd++; 3384 } 3385 pi = pi->next; 3386 } 3387 #if 0 3388 /* Should be 0. If it isn't, it's a parse error */ 3389 if (heredoc_cnt) 3390 bb_error_msg_and_die("heredoc BUG 2"); 3391 #endif 3392 return 0; 3393 } 3394 3395 3396 static int run_list(struct pipe *pi); 3397 #if BB_MMU 3398 #define parse_stream(pstring, input, end_trigger) \ 3399 parse_stream(input, end_trigger) 3400 #endif 3401 static struct pipe *parse_stream(char **pstring, 3402 struct in_str *input, 3403 int end_trigger); 3404 3405 3406 #if !ENABLE_HUSH_FUNCTIONS 3407 #define parse_group(dest, ctx, input, ch) \ 3408 parse_group(ctx, input, ch) 3409 #endif 3410 static int parse_group(o_string *dest, struct parse_context *ctx, 3411 struct in_str *input, int ch) 3412 { 3413 /* dest contains characters seen prior to ( or {. 3414 * Typically it's empty, but for function defs, 3415 * it contains function name (without '()'). */ 3416 struct pipe *pipe_list; 3417 int endch; 3418 struct command *command = ctx->command; 3419 3420 debug_printf_parse("parse_group entered\n"); 3421 #if ENABLE_HUSH_FUNCTIONS 3422 if (ch == '(' && !dest->has_quoted_part) { 3423 if (dest->length) 3424 if (done_word(dest, ctx)) 3425 return 1; 3426 if (!command->argv) 3427 goto skip; /* (... */ 3428 if (command->argv[1]) { /* word word ... (... */ 3429 syntax_error_unexpected_ch('('); 3430 return 1; 3431 } 3432 /* it is "word(..." or "word (..." */ 3433 do 3434 ch = i_getch(input); 3435 while (ch == ' ' || ch == '\t'); 3436 if (ch != ')') { 3437 syntax_error_unexpected_ch(ch); 3438 return 1; 3439 } 3440 nommu_addchr(&ctx->as_string, ch); 3441 do 3442 ch = i_getch(input); 3443 while (ch == ' ' || ch == '\t' || ch == '\n'); 3444 if (ch != '{') { 3445 syntax_error_unexpected_ch(ch); 3446 return 1; 3447 } 3448 nommu_addchr(&ctx->as_string, ch); 3449 command->cmd_type = CMD_FUNCDEF; 3450 goto skip; 3451 } 3452 #endif 3453 3454 #if 0 /* Prevented by caller */ 3455 if (command->argv /* word [word]{... */ 3456 || dest->length /* word{... */ 3457 || dest->has_quoted_part /* ""{... */ 3458 ) { 3459 syntax_error(NULL); 3460 debug_printf_parse("parse_group return 1: " 3461 "syntax error, groups and arglists don't mix\n"); 3462 return 1; 3463 } 3464 #endif 3465 3466 #if ENABLE_HUSH_FUNCTIONS 3467 skip: 3468 #endif 3469 endch = '}'; 3470 if (ch == '(') { 3471 endch = ')'; 3472 command->cmd_type = CMD_SUBSHELL; 3473 } else { 3474 /* bash does not allow "{echo...", requires whitespace */ 3475 ch = i_getch(input); 3476 if (ch != ' ' && ch != '\t' && ch != '\n') { 3477 syntax_error_unexpected_ch(ch); 3478 return 1; 3479 } 3480 nommu_addchr(&ctx->as_string, ch); 3481 } 3482 3483 { 3484 #if BB_MMU 3485 # define as_string NULL 3486 #else 3487 char *as_string = NULL; 3488 #endif 3489 pipe_list = parse_stream(&as_string, input, endch); 3490 #if !BB_MMU 3491 if (as_string) 3492 o_addstr(&ctx->as_string, as_string); 3493 #endif 3494 /* empty ()/{} or parse error? */ 3495 if (!pipe_list || pipe_list == ERR_PTR) { 3496 /* parse_stream already emitted error msg */ 3497 if (!BB_MMU) 3498 free(as_string); 3499 debug_printf_parse("parse_group return 1: " 3500 "parse_stream returned %p\n", pipe_list); 3501 return 1; 3502 } 3503 command->group = pipe_list; 3504 #if !BB_MMU 3505 as_string[strlen(as_string) - 1] = '\0'; /* plink ')' or '}' */ 3506 command->group_as_string = as_string; 3507 debug_printf_parse("end of group, remembering as:'%s'\n", 3508 command->group_as_string); 3509 #endif 3510 #undef as_string 3511 } 3512 debug_printf_parse("parse_group return 0\n"); 3513 return 0; 3514 /* command remains "open", available for possible redirects */ 3515 } 3516 3517 #if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS 3518 /* Subroutines for copying $(...) and `...` things */ 3519 static void add_till_backquote(o_string *dest, struct in_str *input, int in_dquote); 3520 /* '...' */ 3521 static void add_till_single_quote(o_string *dest, struct in_str *input) 3522 { 3523 while (1) { 3524 int ch = i_getch(input); 3525 if (ch == EOF) { 3526 syntax_error_unterm_ch('\''); 3527 /*xfunc_die(); - redundant */ 3528 } 3529 if (ch == '\'') 3530 return; 3531 o_addchr(dest, ch); 3532 } 3533 } 3534 /* "...\"...`..`...." - do we need to handle "...$(..)..." too? */ 3535 static void add_till_double_quote(o_string *dest, struct in_str *input) 3536 { 3537 while (1) { 3538 int ch = i_getch(input); 3539 if (ch == EOF) { 3540 syntax_error_unterm_ch('"'); 3541 /*xfunc_die(); - redundant */ 3542 } 3543 if (ch == '"') 3544 return; 3545 if (ch == '\\') { /* \x. Copy both chars. */ 3546 o_addchr(dest, ch); 3547 ch = i_getch(input); 3548 } 3549 o_addchr(dest, ch); 3550 if (ch == '`') { 3551 add_till_backquote(dest, input, /*in_dquote:*/ 1); 3552 o_addchr(dest, ch); 3553 continue; 3554 } 3555 //if (ch == '$') ... 3556 } 3557 } 3558 /* Process `cmd` - copy contents until "`" is seen. Complicated by 3559 * \` quoting. 3560 * "Within the backquoted style of command substitution, backslash 3561 * shall retain its literal meaning, except when followed by: '$', '`', or '\'. 3562 * The search for the matching backquote shall be satisfied by the first 3563 * backquote found without a preceding backslash; during this search, 3564 * if a non-escaped backquote is encountered within a shell comment, 3565 * a here-document, an embedded command substitution of the $(command) 3566 * form, or a quoted string, undefined results occur. A single-quoted 3567 * or double-quoted string that begins, but does not end, within the 3568 * "`...`" sequence produces undefined results." 3569 * Example Output 3570 * echo `echo '\'TEST\`echo ZZ\`BEST` \TESTZZBEST 3571 */ 3572 static void add_till_backquote(o_string *dest, struct in_str *input, int in_dquote) 3573 { 3574 while (1) { 3575 int ch = i_getch(input); 3576 if (ch == '`') 3577 return; 3578 if (ch == '\\') { 3579 /* \x. Copy both unless it is \`, \$, \\ and maybe \" */ 3580 ch = i_getch(input); 3581 if (ch != '`' 3582 && ch != '$' 3583 && ch != '\\' 3584 && (!in_dquote || ch != '"') 3585 ) { 3586 o_addchr(dest, '\\'); 3587 } 3588 } 3589 if (ch == EOF) { 3590 syntax_error_unterm_ch('`'); 3591 /*xfunc_die(); - redundant */ 3592 } 3593 o_addchr(dest, ch); 3594 } 3595 } 3596 /* Process $(cmd) - copy contents until ")" is seen. Complicated by 3597 * quoting and nested ()s. 3598 * "With the $(command) style of command substitution, all characters 3599 * following the open parenthesis to the matching closing parenthesis 3600 * constitute the command. Any valid shell script can be used for command, 3601 * except a script consisting solely of redirections which produces 3602 * unspecified results." 3603 * Example Output 3604 * echo $(echo '(TEST)' BEST) (TEST) BEST 3605 * echo $(echo 'TEST)' BEST) TEST) BEST 3606 * echo $(echo \(\(TEST\) BEST) ((TEST) BEST 3607 * 3608 * Also adapted to eat ${var%...} and $((...)) constructs, since ... part 3609 * can contain arbitrary constructs, just like $(cmd). 3610 * In bash compat mode, it needs to also be able to stop on ':' or '/' 3611 * for ${var:N[:M]} and ${var/P[/R]} parsing. 3612 */ 3613 #define DOUBLE_CLOSE_CHAR_FLAG 0x80 3614 static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsigned end_ch) 3615 { 3616 int ch; 3617 char dbl = end_ch & DOUBLE_CLOSE_CHAR_FLAG; 3618 # if ENABLE_HUSH_BASH_COMPAT 3619 char end_char2 = end_ch >> 8; 3620 # endif 3621 end_ch &= (DOUBLE_CLOSE_CHAR_FLAG - 1); 3622 3623 while (1) { 3624 ch = i_getch(input); 3625 if (ch == EOF) { 3626 syntax_error_unterm_ch(end_ch); 3627 /*xfunc_die(); - redundant */ 3628 } 3629 if (ch == end_ch IF_HUSH_BASH_COMPAT( || ch == end_char2)) { 3630 if (!dbl) 3631 break; 3632 /* we look for closing )) of $((EXPR)) */ 3633 if (i_peek(input) == end_ch) { 3634 i_getch(input); /* eat second ')' */ 3635 break; 3636 } 3637 } 3638 o_addchr(dest, ch); 3639 if (ch == '(' || ch == '{') { 3640 ch = (ch == '(' ? ')' : '}'); 3641 add_till_closing_bracket(dest, input, ch); 3642 o_addchr(dest, ch); 3643 continue; 3644 } 3645 if (ch == '\'') { 3646 add_till_single_quote(dest, input); 3647 o_addchr(dest, ch); 3648 continue; 3649 } 3650 if (ch == '"') { 3651 add_till_double_quote(dest, input); 3652 o_addchr(dest, ch); 3653 continue; 3654 } 3655 if (ch == '`') { 3656 add_till_backquote(dest, input, /*in_dquote:*/ 0); 3657 o_addchr(dest, ch); 3658 continue; 3659 } 3660 if (ch == '\\') { 3661 /* \x. Copy verbatim. Important for \(, \) */ 3662 ch = i_getch(input); 3663 if (ch == EOF) { 3664 syntax_error_unterm_ch(')'); 3665 /*xfunc_die(); - redundant */ 3666 } 3667 o_addchr(dest, ch); 3668 continue; 3669 } 3670 } 3671 return ch; 3672 } 3673 #endif /* ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS */ 3674 3675 /* Return code: 0 for OK, 1 for syntax error */ 3676 #if BB_MMU 3677 #define parse_dollar(as_string, dest, input, quote_mask) \ 3678 parse_dollar(dest, input, quote_mask) 3679 #define as_string NULL 3680 #endif 3681 static int parse_dollar(o_string *as_string, 3682 o_string *dest, 3683 struct in_str *input, unsigned char quote_mask) 3684 { 3685 int ch = i_peek(input); /* first character after the $ */ 3686 3687 debug_printf_parse("parse_dollar entered: ch='%c'\n", ch); 3688 if (isalpha(ch)) { 3689 ch = i_getch(input); 3690 nommu_addchr(as_string, ch); 3691 make_var: 3692 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3693 while (1) { 3694 debug_printf_parse(": '%c'\n", ch); 3695 o_addchr(dest, ch | quote_mask); 3696 quote_mask = 0; 3697 ch = i_peek(input); 3698 if (!isalnum(ch) && ch != '_') 3699 break; 3700 ch = i_getch(input); 3701 nommu_addchr(as_string, ch); 3702 } 3703 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3704 } else if (isdigit(ch)) { 3705 make_one_char_var: 3706 ch = i_getch(input); 3707 nommu_addchr(as_string, ch); 3708 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3709 debug_printf_parse(": '%c'\n", ch); 3710 o_addchr(dest, ch | quote_mask); 3711 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3712 } else switch (ch) { 3713 case '$': /* pid */ 3714 case '!': /* last bg pid */ 3715 case '?': /* last exit code */ 3716 case '#': /* number of args */ 3717 case '*': /* args */ 3718 case '@': /* args */ 3719 goto make_one_char_var; 3720 case '{': { 3721 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3722 3723 ch = i_getch(input); /* eat '{' */ 3724 nommu_addchr(as_string, ch); 3725 3726 ch = i_getch(input); /* first char after '{' */ 3727 /* It should be ${?}, or ${#var}, 3728 * or even ${?+subst} - operator acting on a special variable, 3729 * or the beginning of variable name. 3730 */ 3731 if (ch == EOF 3732 || (!strchr(_SPECIAL_VARS_STR, ch) && !isalnum(ch)) /* not one of those */ 3733 ) { 3734 bad_dollar_syntax: 3735 syntax_error_unterm_str("${name}"); 3736 debug_printf_parse("parse_dollar return 1: unterminated ${name}\n"); 3737 return 1; 3738 } 3739 nommu_addchr(as_string, ch); 3740 ch |= quote_mask; 3741 3742 /* It's possible to just call add_till_closing_bracket() at this point. 3743 * However, this regresses some of our testsuite cases 3744 * which check invalid constructs like ${%}. 3745 * Oh well... let's check that the var name part is fine... */ 3746 3747 while (1) { 3748 unsigned pos; 3749 3750 o_addchr(dest, ch); 3751 debug_printf_parse(": '%c'\n", ch); 3752 3753 ch = i_getch(input); 3754 nommu_addchr(as_string, ch); 3755 if (ch == '}') 3756 break; 3757 3758 if (!isalnum(ch) && ch != '_') { 3759 unsigned end_ch; 3760 unsigned char last_ch; 3761 /* handle parameter expansions 3762 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02 3763 */ 3764 if (!strchr(VAR_SUBST_OPS, ch)) /* ${var<bad_char>... */ 3765 goto bad_dollar_syntax; 3766 3767 /* Eat everything until closing '}' (or ':') */ 3768 end_ch = '}'; 3769 if (ENABLE_HUSH_BASH_COMPAT 3770 && ch == ':' 3771 && !strchr(MINUS_PLUS_EQUAL_QUESTION, i_peek(input)) 3772 ) { 3773 /* It's ${var:N[:M]} thing */ 3774 end_ch = '}' * 0x100 + ':'; 3775 } 3776 if (ENABLE_HUSH_BASH_COMPAT 3777 && ch == '/' 3778 ) { 3779 /* It's ${var/[/]pattern[/repl]} thing */ 3780 if (i_peek(input) == '/') { /* ${var//pattern[/repl]}? */ 3781 i_getch(input); 3782 nommu_addchr(as_string, '/'); 3783 ch = '\\'; 3784 } 3785 end_ch = '}' * 0x100 + '/'; 3786 } 3787 o_addchr(dest, ch); 3788 again: 3789 if (!BB_MMU) 3790 pos = dest->length; 3791 #if ENABLE_HUSH_DOLLAR_OPS 3792 last_ch = add_till_closing_bracket(dest, input, end_ch); 3793 #else 3794 #error Simple code to only allow ${var} is not implemented 3795 #endif 3796 if (as_string) { 3797 o_addstr(as_string, dest->data + pos); 3798 o_addchr(as_string, last_ch); 3799 } 3800 3801 if (ENABLE_HUSH_BASH_COMPAT && (end_ch & 0xff00)) { 3802 /* close the first block: */ 3803 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3804 /* while parsing N from ${var:N[:M]} 3805 * or pattern from ${var/[/]pattern[/repl]} */ 3806 if ((end_ch & 0xff) == last_ch) { 3807 /* got ':' or '/'- parse the rest */ 3808 end_ch = '}'; 3809 goto again; 3810 } 3811 /* got '}' */ 3812 if (end_ch == '}' * 0x100 + ':') { 3813 /* it's ${var:N} - emulate :999999999 */ 3814 o_addstr(dest, "999999999"); 3815 } /* else: it's ${var/[/]pattern} */ 3816 } 3817 break; 3818 } 3819 } 3820 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3821 break; 3822 } 3823 #if ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_TICK 3824 case '(': { 3825 unsigned pos; 3826 3827 ch = i_getch(input); 3828 nommu_addchr(as_string, ch); 3829 # if ENABLE_SH_MATH_SUPPORT 3830 if (i_peek(input) == '(') { 3831 ch = i_getch(input); 3832 nommu_addchr(as_string, ch); 3833 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3834 o_addchr(dest, /*quote_mask |*/ '+'); 3835 if (!BB_MMU) 3836 pos = dest->length; 3837 add_till_closing_bracket(dest, input, ')' | DOUBLE_CLOSE_CHAR_FLAG); 3838 if (as_string) { 3839 o_addstr(as_string, dest->data + pos); 3840 o_addchr(as_string, ')'); 3841 o_addchr(as_string, ')'); 3842 } 3843 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3844 break; 3845 } 3846 # endif 3847 # if ENABLE_HUSH_TICK 3848 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3849 o_addchr(dest, quote_mask | '`'); 3850 if (!BB_MMU) 3851 pos = dest->length; 3852 add_till_closing_bracket(dest, input, ')'); 3853 if (as_string) { 3854 o_addstr(as_string, dest->data + pos); 3855 o_addchr(as_string, ')'); 3856 } 3857 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3858 # endif 3859 break; 3860 } 3861 #endif 3862 case '_': 3863 ch = i_getch(input); 3864 nommu_addchr(as_string, ch); 3865 ch = i_peek(input); 3866 if (isalnum(ch)) { /* it's $_name or $_123 */ 3867 ch = '_'; 3868 goto make_var; 3869 } 3870 /* else: it's $_ */ 3871 /* TODO: $_ and $-: */ 3872 /* $_ Shell or shell script name; or last argument of last command 3873 * (if last command wasn't a pipe; if it was, bash sets $_ to ""); 3874 * but in command's env, set to full pathname used to invoke it */ 3875 /* $- Option flags set by set builtin or shell options (-i etc) */ 3876 default: 3877 o_addQchr(dest, '$'); 3878 } 3879 debug_printf_parse("parse_dollar return 0\n"); 3880 return 0; 3881 #undef as_string 3882 } 3883 3884 #if BB_MMU 3885 # if ENABLE_HUSH_BASH_COMPAT 3886 #define encode_string(as_string, dest, input, dquote_end, process_bkslash) \ 3887 encode_string(dest, input, dquote_end, process_bkslash) 3888 # else 3889 /* only ${var/pattern/repl} (its pattern part) needs additional mode */ 3890 #define encode_string(as_string, dest, input, dquote_end, process_bkslash) \ 3891 encode_string(dest, input, dquote_end) 3892 # endif 3893 #define as_string NULL 3894 3895 #else /* !MMU */ 3896 3897 # if ENABLE_HUSH_BASH_COMPAT 3898 /* all parameters are needed, no macro tricks */ 3899 # else 3900 #define encode_string(as_string, dest, input, dquote_end, process_bkslash) \ 3901 encode_string(as_string, dest, input, dquote_end) 3902 # endif 3903 #endif 3904 static int encode_string(o_string *as_string, 3905 o_string *dest, 3906 struct in_str *input, 3907 int dquote_end, 3908 int process_bkslash) 3909 { 3910 #if !ENABLE_HUSH_BASH_COMPAT 3911 const int process_bkslash = 1; 3912 #endif 3913 int ch; 3914 int next; 3915 3916 again: 3917 ch = i_getch(input); 3918 if (ch != EOF) 3919 nommu_addchr(as_string, ch); 3920 if (ch == dquote_end) { /* may be only '"' or EOF */ 3921 debug_printf_parse("encode_string return 0\n"); 3922 return 0; 3923 } 3924 /* note: can't move it above ch == dquote_end check! */ 3925 if (ch == EOF) { 3926 syntax_error_unterm_ch('"'); 3927 /*xfunc_die(); - redundant */ 3928 } 3929 next = '\0'; 3930 if (ch != '\n') { 3931 next = i_peek(input); 3932 } 3933 debug_printf_parse("\" ch=%c (%d) escape=%d\n", 3934 ch, ch, !!(dest->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); 3935 if (process_bkslash && ch == '\\') { 3936 if (next == EOF) { 3937 syntax_error("\\<eof>"); 3938 xfunc_die(); 3939 } 3940 /* bash: 3941 * "The backslash retains its special meaning [in "..."] 3942 * only when followed by one of the following characters: 3943 * $, `, ", \, or <newline>. A double quote may be quoted 3944 * within double quotes by preceding it with a backslash." 3945 * NB: in (unquoted) heredoc, above does not apply to ", 3946 * therefore we check for it by "next == dquote_end" cond. 3947 */ 3948 if (next == dquote_end || strchr("$`\\\n", next)) { 3949 ch = i_getch(input); /* eat next */ 3950 if (ch == '\n') 3951 goto again; /* skip \<newline> */ 3952 } /* else: ch remains == '\\', and we double it below: */ 3953 o_addqchr(dest, ch); /* \c if c is a glob char, else just c */ 3954 nommu_addchr(as_string, ch); 3955 goto again; 3956 } 3957 if (ch == '$') { 3958 if (parse_dollar(as_string, dest, input, /*quote_mask:*/ 0x80) != 0) { 3959 debug_printf_parse("encode_string return 1: " 3960 "parse_dollar returned non-0\n"); 3961 return 1; 3962 } 3963 goto again; 3964 } 3965 #if ENABLE_HUSH_TICK 3966 if (ch == '`') { 3967 //unsigned pos = dest->length; 3968 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3969 o_addchr(dest, 0x80 | '`'); 3970 add_till_backquote(dest, input, /*in_dquote:*/ dquote_end == '"'); 3971 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3972 //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos); 3973 goto again; 3974 } 3975 #endif 3976 o_addQchr(dest, ch); 3977 goto again; 3978 #undef as_string 3979 } 3980 3981 /* 3982 * Scan input until EOF or end_trigger char. 3983 * Return a list of pipes to execute, or NULL on EOF 3984 * or if end_trigger character is met. 3985 * On syntax error, exit is shell is not interactive, 3986 * reset parsing machinery and start parsing anew, 3987 * or return ERR_PTR. 3988 */ 3989 static struct pipe *parse_stream(char **pstring, 3990 struct in_str *input, 3991 int end_trigger) 3992 { 3993 struct parse_context ctx; 3994 o_string dest = NULL_O_STRING; 3995 int heredoc_cnt; 3996 3997 /* Single-quote triggers a bypass of the main loop until its mate is 3998 * found. When recursing, quote state is passed in via dest->o_expflags. 3999 */ 4000 debug_printf_parse("parse_stream entered, end_trigger='%c'\n", 4001 end_trigger ? end_trigger : 'X'); 4002 debug_enter(); 4003 4004 /* If very first arg is "" or '', dest.data may end up NULL. 4005 * Preventing this: */ 4006 o_addchr(&dest, '\0'); 4007 dest.length = 0; 4008 4009 /* We used to separate words on $IFS here. This was wrong. 4010 * $IFS is used only for word splitting when $var is expanded, 4011 * here we should use blank chars as separators, not $IFS 4012 */ 4013 4014 reset: /* we come back here only on syntax errors in interactive shell */ 4015 4016 #if ENABLE_HUSH_INTERACTIVE 4017 input->promptmode = 0; /* PS1 */ 4018 #endif 4019 if (MAYBE_ASSIGNMENT != 0) 4020 dest.o_assignment = MAYBE_ASSIGNMENT; 4021 initialize_context(&ctx); 4022 heredoc_cnt = 0; 4023 while (1) { 4024 const char *is_blank; 4025 const char *is_special; 4026 int ch; 4027 int next; 4028 int redir_fd; 4029 redir_type redir_style; 4030 4031 ch = i_getch(input); 4032 debug_printf_parse(": ch=%c (%d) escape=%d\n", 4033 ch, ch, !!(dest.o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); 4034 if (ch == EOF) { 4035 struct pipe *pi; 4036 4037 if (heredoc_cnt) { 4038 syntax_error_unterm_str("here document"); 4039 goto parse_error; 4040 } 4041 /* end_trigger == '}' case errors out earlier, 4042 * checking only ')' */ 4043 if (end_trigger == ')') { 4044 syntax_error_unterm_ch('('); /* exits */ 4045 /* goto parse_error; */ 4046 } 4047 4048 if (done_word(&dest, &ctx)) { 4049 goto parse_error; 4050 } 4051 o_free(&dest); 4052 done_pipe(&ctx, PIPE_SEQ); 4053 pi = ctx.list_head; 4054 /* If we got nothing... */ 4055 /* (this makes bare "&" cmd a no-op. 4056 * bash says: "syntax error near unexpected token '&'") */ 4057 if (pi->num_cmds == 0 4058 IF_HAS_KEYWORDS( && pi->res_word == RES_NONE) 4059 ) { 4060 free_pipe_list(pi); 4061 pi = NULL; 4062 } 4063 #if !BB_MMU 4064 debug_printf_parse("as_string '%s'\n", ctx.as_string.data); 4065 if (pstring) 4066 *pstring = ctx.as_string.data; 4067 else 4068 o_free_unsafe(&ctx.as_string); 4069 #endif 4070 debug_leave(); 4071 debug_printf_parse("parse_stream return %p\n", pi); 4072 return pi; 4073 } 4074 nommu_addchr(&ctx.as_string, ch); 4075 4076 next = '\0'; 4077 if (ch != '\n') 4078 next = i_peek(input); 4079 4080 is_special = "{}<>;&|()#'" /* special outside of "str" */ 4081 "\\$\"" IF_HUSH_TICK("`"); /* always special */ 4082 /* Are { and } special here? */ 4083 if (ctx.command->argv /* word [word]{... - non-special */ 4084 || dest.length /* word{... - non-special */ 4085 || dest.has_quoted_part /* ""{... - non-special */ 4086 || (next != ';' /* }; - special */ 4087 && next != ')' /* }) - special */ 4088 && next != '&' /* }& and }&& ... - special */ 4089 && next != '|' /* }|| ... - special */ 4090 && !strchr(defifs, next) /* {word - non-special */ 4091 ) 4092 ) { 4093 /* They are not special, skip "{}" */ 4094 is_special += 2; 4095 } 4096 is_special = strchr(is_special, ch); 4097 is_blank = strchr(defifs, ch); 4098 4099 if (!is_special && !is_blank) { /* ordinary char */ 4100 ordinary_char: 4101 o_addQchr(&dest, ch); 4102 if ((dest.o_assignment == MAYBE_ASSIGNMENT 4103 || dest.o_assignment == WORD_IS_KEYWORD) 4104 && ch == '=' 4105 && is_well_formed_var_name(dest.data, '=') 4106 ) { 4107 dest.o_assignment = DEFINITELY_ASSIGNMENT; 4108 } 4109 continue; 4110 } 4111 4112 if (is_blank) { 4113 if (done_word(&dest, &ctx)) { 4114 goto parse_error; 4115 } 4116 if (ch == '\n') { 4117 /* Is this a case when newline is simply ignored? 4118 * Some examples: 4119 * "cmd | <newline> cmd ..." 4120 * "case ... in <newline> word) ..." 4121 */ 4122 if (IS_NULL_CMD(ctx.command) 4123 && dest.length == 0 && !dest.has_quoted_part 4124 ) { 4125 /* This newline can be ignored. But... 4126 * Without check #1, interactive shell 4127 * ignores even bare <newline>, 4128 * and shows the continuation prompt: 4129 * ps1_prompt$ <enter> 4130 * ps2> _ <=== wrong, should be ps1 4131 * Without check #2, "cmd & <newline>" 4132 * is similarly mistreated. 4133 * (BTW, this makes "cmd & cmd" 4134 * and "cmd && cmd" non-orthogonal. 4135 * Really, ask yourself, why 4136 * "cmd && <newline>" doesn't start 4137 * cmd but waits for more input? 4138 * No reason...) 4139 */ 4140 struct pipe *pi = ctx.list_head; 4141 if (pi->num_cmds != 0 /* check #1 */ 4142 && pi->followup != PIPE_BG /* check #2 */ 4143 ) { 4144 continue; 4145 } 4146 } 4147 /* Treat newline as a command separator. */ 4148 done_pipe(&ctx, PIPE_SEQ); 4149 debug_printf_parse("heredoc_cnt:%d\n", heredoc_cnt); 4150 if (heredoc_cnt) { 4151 if (fetch_heredocs(heredoc_cnt, &ctx, input)) { 4152 goto parse_error; 4153 } 4154 heredoc_cnt = 0; 4155 } 4156 dest.o_assignment = MAYBE_ASSIGNMENT; 4157 ch = ';'; 4158 /* note: if (is_blank) continue; 4159 * will still trigger for us */ 4160 } 4161 } 4162 4163 /* "cmd}" or "cmd }..." without semicolon or &: 4164 * } is an ordinary char in this case, even inside { cmd; } 4165 * Pathological example: { ""}; } should exec "}" cmd 4166 */ 4167 if (ch == '}') { 4168 if (!IS_NULL_CMD(ctx.command) /* cmd } */ 4169 || dest.length != 0 /* word} */ 4170 || dest.has_quoted_part /* ""} */ 4171 ) { 4172 goto ordinary_char; 4173 } 4174 if (!IS_NULL_PIPE(ctx.pipe)) /* cmd | } */ 4175 goto skip_end_trigger; 4176 /* else: } does terminate a group */ 4177 } 4178 4179 if (end_trigger && end_trigger == ch 4180 && (ch != ';' || heredoc_cnt == 0) 4181 #if ENABLE_HUSH_CASE 4182 && (ch != ')' 4183 || ctx.ctx_res_w != RES_MATCH 4184 || (!dest.has_quoted_part && strcmp(dest.data, "esac") == 0) 4185 ) 4186 #endif 4187 ) { 4188 if (heredoc_cnt) { 4189 /* This is technically valid: 4190 * { cat <<HERE; }; echo Ok 4191 * heredoc 4192 * heredoc 4193 * HERE 4194 * but we don't support this. 4195 * We require heredoc to be in enclosing {}/(), 4196 * if any. 4197 */ 4198 syntax_error_unterm_str("here document"); 4199 goto parse_error; 4200 } 4201 if (done_word(&dest, &ctx)) { 4202 goto parse_error; 4203 } 4204 done_pipe(&ctx, PIPE_SEQ); 4205 dest.o_assignment = MAYBE_ASSIGNMENT; 4206 /* Do we sit outside of any if's, loops or case's? */ 4207 if (!HAS_KEYWORDS 4208 IF_HAS_KEYWORDS(|| (ctx.ctx_res_w == RES_NONE && ctx.old_flag == 0)) 4209 ) { 4210 o_free(&dest); 4211 #if !BB_MMU 4212 debug_printf_parse("as_string '%s'\n", ctx.as_string.data); 4213 if (pstring) 4214 *pstring = ctx.as_string.data; 4215 else 4216 o_free_unsafe(&ctx.as_string); 4217 #endif 4218 debug_leave(); 4219 debug_printf_parse("parse_stream return %p: " 4220 "end_trigger char found\n", 4221 ctx.list_head); 4222 return ctx.list_head; 4223 } 4224 } 4225 skip_end_trigger: 4226 if (is_blank) 4227 continue; 4228 4229 /* Catch <, > before deciding whether this word is 4230 * an assignment. a=1 2>z b=2: b=2 is still assignment */ 4231 switch (ch) { 4232 case '>': 4233 redir_fd = redirect_opt_num(&dest); 4234 if (done_word(&dest, &ctx)) { 4235 goto parse_error; 4236 } 4237 redir_style = REDIRECT_OVERWRITE; 4238 if (next == '>') { 4239 redir_style = REDIRECT_APPEND; 4240 ch = i_getch(input); 4241 nommu_addchr(&ctx.as_string, ch); 4242 } 4243 #if 0 4244 else if (next == '(') { 4245 syntax_error(">(process) not supported"); 4246 goto parse_error; 4247 } 4248 #endif 4249 if (parse_redirect(&ctx, redir_fd, redir_style, input)) 4250 goto parse_error; 4251 continue; /* back to top of while (1) */ 4252 case '<': 4253 redir_fd = redirect_opt_num(&dest); 4254 if (done_word(&dest, &ctx)) { 4255 goto parse_error; 4256 } 4257 redir_style = REDIRECT_INPUT; 4258 if (next == '<') { 4259 redir_style = REDIRECT_HEREDOC; 4260 heredoc_cnt++; 4261 debug_printf_parse("++heredoc_cnt=%d\n", heredoc_cnt); 4262 ch = i_getch(input); 4263 nommu_addchr(&ctx.as_string, ch); 4264 } else if (next == '>') { 4265 redir_style = REDIRECT_IO; 4266 ch = i_getch(input); 4267 nommu_addchr(&ctx.as_string, ch); 4268 } 4269 #if 0 4270 else if (next == '(') { 4271 syntax_error("<(process) not supported"); 4272 goto parse_error; 4273 } 4274 #endif 4275 if (parse_redirect(&ctx, redir_fd, redir_style, input)) 4276 goto parse_error; 4277 continue; /* back to top of while (1) */ 4278 case '#': 4279 if (dest.length == 0 && !dest.has_quoted_part) { 4280 /* skip "#comment" */ 4281 while (1) { 4282 ch = i_peek(input); 4283 if (ch == EOF || ch == '\n') 4284 break; 4285 i_getch(input); 4286 /* note: we do not add it to &ctx.as_string */ 4287 } 4288 nommu_addchr(&ctx.as_string, '\n'); 4289 continue; /* back to top of while (1) */ 4290 } 4291 break; 4292 case '\\': 4293 if (next == '\n') { 4294 /* It's "\<newline>" */ 4295 #if !BB_MMU 4296 /* Remove trailing '\' from ctx.as_string */ 4297 ctx.as_string.data[--ctx.as_string.length] = '\0'; 4298 #endif 4299 ch = i_getch(input); /* eat it */ 4300 continue; /* back to top of while (1) */ 4301 } 4302 break; 4303 } 4304 4305 if (dest.o_assignment == MAYBE_ASSIGNMENT 4306 /* check that we are not in word in "a=1 2>word b=1": */ 4307 && !ctx.pending_redirect 4308 ) { 4309 /* ch is a special char and thus this word 4310 * cannot be an assignment */ 4311 dest.o_assignment = NOT_ASSIGNMENT; 4312 } 4313 4314 /* Note: nommu_addchr(&ctx.as_string, ch) is already done */ 4315 4316 switch (ch) { 4317 case '#': /* non-comment #: "echo a#b" etc */ 4318 o_addQchr(&dest, ch); 4319 break; 4320 case '\\': 4321 if (next == EOF) { 4322 syntax_error("\\<eof>"); 4323 xfunc_die(); 4324 } 4325 ch = i_getch(input); 4326 /* note: ch != '\n' (that case does not reach this place) */ 4327 o_addchr(&dest, '\\'); 4328 /*nommu_addchr(&ctx.as_string, '\\'); - already done */ 4329 o_addchr(&dest, ch); 4330 nommu_addchr(&ctx.as_string, ch); 4331 /* Example: echo Hello \2>file 4332 * we need to know that word 2 is quoted */ 4333 dest.has_quoted_part = 1; 4334 break; 4335 case '$': 4336 if (parse_dollar(&ctx.as_string, &dest, input, /*quote_mask:*/ 0) != 0) { 4337 debug_printf_parse("parse_stream parse error: " 4338 "parse_dollar returned non-0\n"); 4339 goto parse_error; 4340 } 4341 break; 4342 case '\'': 4343 dest.has_quoted_part = 1; 4344 while (1) { 4345 ch = i_getch(input); 4346 if (ch == EOF) { 4347 syntax_error_unterm_ch('\''); 4348 /*xfunc_die(); - redundant */ 4349 } 4350 nommu_addchr(&ctx.as_string, ch); 4351 if (ch == '\'') 4352 break; 4353 o_addqchr(&dest, ch); 4354 } 4355 break; 4356 case '"': 4357 dest.has_quoted_part = 1; 4358 if (dest.o_assignment == NOT_ASSIGNMENT) 4359 dest.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS; 4360 if (encode_string(&ctx.as_string, &dest, input, '"', /*process_bkslash:*/ 1)) 4361 goto parse_error; 4362 dest.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS; 4363 break; 4364 #if ENABLE_HUSH_TICK 4365 case '`': { 4366 unsigned pos; 4367 4368 o_addchr(&dest, SPECIAL_VAR_SYMBOL); 4369 o_addchr(&dest, '`'); 4370 pos = dest.length; 4371 add_till_backquote(&dest, input, /*in_dquote:*/ 0); 4372 # if !BB_MMU 4373 o_addstr(&ctx.as_string, dest.data + pos); 4374 o_addchr(&ctx.as_string, '`'); 4375 # endif 4376 o_addchr(&dest, SPECIAL_VAR_SYMBOL); 4377 //debug_printf_subst("SUBST RES3 '%s'\n", dest.data + pos); 4378 break; 4379 } 4380 #endif 4381 case ';': 4382 #if ENABLE_HUSH_CASE 4383 case_semi: 4384 #endif 4385 if (done_word(&dest, &ctx)) { 4386 goto parse_error; 4387 } 4388 done_pipe(&ctx, PIPE_SEQ); 4389 #if ENABLE_HUSH_CASE 4390 /* Eat multiple semicolons, detect 4391 * whether it means something special */ 4392 while (1) { 4393 ch = i_peek(input); 4394 if (ch != ';') 4395 break; 4396 ch = i_getch(input); 4397 nommu_addchr(&ctx.as_string, ch); 4398 if (ctx.ctx_res_w == RES_CASE_BODY) { 4399 ctx.ctx_dsemicolon = 1; 4400 ctx.ctx_res_w = RES_MATCH; 4401 break; 4402 } 4403 } 4404 #endif 4405 new_cmd: 4406 /* We just finished a cmd. New one may start 4407 * with an assignment */ 4408 dest.o_assignment = MAYBE_ASSIGNMENT; 4409 break; 4410 case '&': 4411 if (done_word(&dest, &ctx)) { 4412 goto parse_error; 4413 } 4414 if (next == '&') { 4415 ch = i_getch(input); 4416 nommu_addchr(&ctx.as_string, ch); 4417 done_pipe(&ctx, PIPE_AND); 4418 } else { 4419 done_pipe(&ctx, PIPE_BG); 4420 } 4421 goto new_cmd; 4422 case '|': 4423 if (done_word(&dest, &ctx)) { 4424 goto parse_error; 4425 } 4426 #if ENABLE_HUSH_CASE 4427 if (ctx.ctx_res_w == RES_MATCH) 4428 break; /* we are in case's "word | word)" */ 4429 #endif 4430 if (next == '|') { /* || */ 4431 ch = i_getch(input); 4432 nommu_addchr(&ctx.as_string, ch); 4433 done_pipe(&ctx, PIPE_OR); 4434 } else { 4435 /* we could pick up a file descriptor choice here 4436 * with redirect_opt_num(), but bash doesn't do it. 4437 * "echo foo 2| cat" yields "foo 2". */ 4438 done_command(&ctx); 4439 #if !BB_MMU 4440 o_reset_to_empty_unquoted(&ctx.as_string); 4441 #endif 4442 } 4443 goto new_cmd; 4444 case '(': 4445 #if ENABLE_HUSH_CASE 4446 /* "case... in [(]word)..." - skip '(' */ 4447 if (ctx.ctx_res_w == RES_MATCH 4448 && ctx.command->argv == NULL /* not (word|(... */ 4449 && dest.length == 0 /* not word(... */ 4450 && dest.has_quoted_part == 0 /* not ""(... */ 4451 ) { 4452 continue; 4453 } 4454 #endif 4455 case '{': 4456 if (parse_group(&dest, &ctx, input, ch) != 0) { 4457 goto parse_error; 4458 } 4459 goto new_cmd; 4460 case ')': 4461 #if ENABLE_HUSH_CASE 4462 if (ctx.ctx_res_w == RES_MATCH) 4463 goto case_semi; 4464 #endif 4465 case '}': 4466 /* proper use of this character is caught by end_trigger: 4467 * if we see {, we call parse_group(..., end_trigger='}') 4468 * and it will match } earlier (not here). */ 4469 syntax_error_unexpected_ch(ch); 4470 goto parse_error; 4471 default: 4472 if (HUSH_DEBUG) 4473 bb_error_msg_and_die("BUG: unexpected %c\n", ch); 4474 } 4475 } /* while (1) */ 4476 4477 parse_error: 4478 { 4479 struct parse_context *pctx; 4480 IF_HAS_KEYWORDS(struct parse_context *p2;) 4481 4482 /* Clean up allocated tree. 4483 * Sample for finding leaks on syntax error recovery path. 4484 * Run it from interactive shell, watch pmap `pidof hush`. 4485 * while if false; then false; fi; do break; fi 4486 * Samples to catch leaks at execution: 4487 * while if (true | {true;}); then echo ok; fi; do break; done 4488 * while if (true | {true;}); then echo ok; fi; do (if echo ok; break; then :; fi) | cat; break; done 4489 */ 4490 pctx = &ctx; 4491 do { 4492 /* Update pipe/command counts, 4493 * otherwise freeing may miss some */ 4494 done_pipe(pctx, PIPE_SEQ); 4495 debug_printf_clean("freeing list %p from ctx %p\n", 4496 pctx->list_head, pctx); 4497 debug_print_tree(pctx->list_head, 0); 4498 free_pipe_list(pctx->list_head); 4499 debug_printf_clean("freed list %p\n", pctx->list_head); 4500 #if !BB_MMU 4501 o_free_unsafe(&pctx->as_string); 4502 #endif 4503 IF_HAS_KEYWORDS(p2 = pctx->stack;) 4504 if (pctx != &ctx) { 4505 free(pctx); 4506 } 4507 IF_HAS_KEYWORDS(pctx = p2;) 4508 } while (HAS_KEYWORDS && pctx); 4509 /* Free text, clear all dest fields */ 4510 o_free(&dest); 4511 /* If we are not in top-level parse, we return, 4512 * our caller will propagate error. 4513 */ 4514 if (end_trigger != ';') { 4515 #if !BB_MMU 4516 if (pstring) 4517 *pstring = NULL; 4518 #endif 4519 debug_leave(); 4520 return ERR_PTR; 4521 } 4522 /* Discard cached input, force prompt */ 4523 input->p = NULL; 4524 IF_HUSH_INTERACTIVE(input->promptme = 1;) 4525 goto reset; 4526 } 4527 } 4528 4529 4530 /*** Execution routines ***/ 4531 4532 /* Expansion can recurse, need forward decls: */ 4533 #if !ENABLE_HUSH_BASH_COMPAT 4534 /* only ${var/pattern/repl} (its pattern part) needs additional mode */ 4535 #define expand_string_to_string(str, do_unbackslash) \ 4536 expand_string_to_string(str) 4537 #endif 4538 static char *expand_string_to_string(const char *str, int do_unbackslash); 4539 #if ENABLE_HUSH_TICK 4540 static int process_command_subs(o_string *dest, const char *s); 4541 #endif 4542 4543 /* expand_strvec_to_strvec() takes a list of strings, expands 4544 * all variable references within and returns a pointer to 4545 * a list of expanded strings, possibly with larger number 4546 * of strings. (Think VAR="a b"; echo $VAR). 4547 * This new list is allocated as a single malloc block. 4548 * NULL-terminated list of char* pointers is at the beginning of it, 4549 * followed by strings themselves. 4550 * Caller can deallocate entire list by single free(list). */ 4551 4552 /* A horde of its helpers come first: */ 4553 4554 static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len) 4555 { 4556 while (--len >= 0) { 4557 char c = *str++; 4558 4559 #if ENABLE_HUSH_BRACE_EXPANSION 4560 if (c == '{' || c == '}') { 4561 /* { -> \{, } -> \} */ 4562 o_addchr(o, '\\'); 4563 /* And now we want to add { or } and continue: 4564 * o_addchr(o, c); 4565 * continue; 4566 * luckily, just falling throught achieves this. 4567 */ 4568 } 4569 #endif 4570 o_addchr(o, c); 4571 if (c == '\\') { 4572 /* \z -> \\\z; \<eol> -> \\<eol> */ 4573 o_addchr(o, '\\'); 4574 if (len) { 4575 len--; 4576 o_addchr(o, '\\'); 4577 o_addchr(o, *str++); 4578 } 4579 } 4580 } 4581 } 4582 4583 /* Store given string, finalizing the word and starting new one whenever 4584 * we encounter IFS char(s). This is used for expanding variable values. 4585 * End-of-string does NOT finalize word: think about 'echo -$VAR-' */ 4586 static int expand_on_ifs(o_string *output, int n, const char *str) 4587 { 4588 while (1) { 4589 int word_len = strcspn(str, G.ifs); 4590 if (word_len) { 4591 if (!(output->o_expflags & EXP_FLAG_GLOB)) { 4592 o_addblock(output, str, word_len); 4593 } else { 4594 /* Protect backslashes against globbing up :) 4595 * Example: "v='\*'; echo b$v" prints "b\*" 4596 * (and does not try to glob on "*") 4597 */ 4598 o_addblock_duplicate_backslash(output, str, word_len); 4599 /*/ Why can't we do it easier? */ 4600 /*o_addblock(output, str, word_len); - WRONG: "v='\*'; echo Z$v" prints "Z*" instead of "Z\*" */ 4601 /*o_addqblock(output, str, word_len); - WRONG: "v='*'; echo Z$v" prints "Z*" instead of Z* files */ 4602 } 4603 str += word_len; 4604 } 4605 if (!*str) /* EOL - do not finalize word */ 4606 break; 4607 o_addchr(output, '\0'); 4608 debug_print_list("expand_on_ifs", output, n); 4609 n = o_save_ptr(output, n); 4610 str += strspn(str, G.ifs); /* skip ifs chars */ 4611 } 4612 debug_print_list("expand_on_ifs[1]", output, n); 4613 return n; 4614 } 4615 4616 /* Helper to expand $((...)) and heredoc body. These act as if 4617 * they are in double quotes, with the exception that they are not :). 4618 * Just the rules are similar: "expand only $var and `cmd`" 4619 * 4620 * Returns malloced string. 4621 * As an optimization, we return NULL if expansion is not needed. 4622 */ 4623 #if !ENABLE_HUSH_BASH_COMPAT 4624 /* only ${var/pattern/repl} (its pattern part) needs additional mode */ 4625 #define encode_then_expand_string(str, process_bkslash, do_unbackslash) \ 4626 encode_then_expand_string(str) 4627 #endif 4628 static char *encode_then_expand_string(const char *str, int process_bkslash, int do_unbackslash) 4629 { 4630 char *exp_str; 4631 struct in_str input; 4632 o_string dest = NULL_O_STRING; 4633 4634 if (!strchr(str, '$') 4635 && !strchr(str, '\\') 4636 #if ENABLE_HUSH_TICK 4637 && !strchr(str, '`') 4638 #endif 4639 ) { 4640 return NULL; 4641 } 4642 4643 /* We need to expand. Example: 4644 * echo $(($a + `echo 1`)) $((1 + $((2)) )) 4645 */ 4646 setup_string_in_str(&input, str); 4647 encode_string(NULL, &dest, &input, EOF, process_bkslash); 4648 //bb_error_msg("'%s' -> '%s'", str, dest.data); 4649 exp_str = expand_string_to_string(dest.data, /*unbackslash:*/ do_unbackslash); 4650 //bb_error_msg("'%s' -> '%s'", dest.data, exp_str); 4651 o_free_unsafe(&dest); 4652 return exp_str; 4653 } 4654 4655 #if ENABLE_SH_MATH_SUPPORT 4656 static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) 4657 { 4658 arith_state_t math_state; 4659 arith_t res; 4660 char *exp_str; 4661 4662 math_state.lookupvar = get_local_var_value; 4663 math_state.setvar = set_local_var_from_halves; 4664 //math_state.endofname = endofname; 4665 exp_str = encode_then_expand_string(arg, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); 4666 res = arith(&math_state, exp_str ? exp_str : arg); 4667 free(exp_str); 4668 if (errmsg_p) 4669 *errmsg_p = math_state.errmsg; 4670 if (math_state.errmsg) 4671 die_if_script(math_state.errmsg); 4672 return res; 4673 } 4674 #endif 4675 4676 #if ENABLE_HUSH_BASH_COMPAT 4677 /* ${var/[/]pattern[/repl]} helpers */ 4678 static char *strstr_pattern(char *val, const char *pattern, int *size) 4679 { 4680 while (1) { 4681 char *end = scan_and_match(val, pattern, SCAN_MOVE_FROM_RIGHT + SCAN_MATCH_LEFT_HALF); 4682 debug_printf_varexp("val:'%s' pattern:'%s' end:'%s'\n", val, pattern, end); 4683 if (end) { 4684 *size = end - val; 4685 return val; 4686 } 4687 if (*val == '\0') 4688 return NULL; 4689 /* Optimization: if "*pat" did not match the start of "string", 4690 * we know that "tring", "ring" etc will not match too: 4691 */ 4692 if (pattern[0] == '*') 4693 return NULL; 4694 val++; 4695 } 4696 } 4697 static char *replace_pattern(char *val, const char *pattern, const char *repl, char exp_op) 4698 { 4699 char *result = NULL; 4700 unsigned res_len = 0; 4701 unsigned repl_len = strlen(repl); 4702 4703 while (1) { 4704 int size; 4705 char *s = strstr_pattern(val, pattern, &size); 4706 if (!s) 4707 break; 4708 4709 result = xrealloc(result, res_len + (s - val) + repl_len + 1); 4710 memcpy(result + res_len, val, s - val); 4711 res_len += s - val; 4712 strcpy(result + res_len, repl); 4713 res_len += repl_len; 4714 debug_printf_varexp("val:'%s' s:'%s' result:'%s'\n", val, s, result); 4715 4716 val = s + size; 4717 if (exp_op == '/') 4718 break; 4719 } 4720 if (val[0] && result) { 4721 result = xrealloc(result, res_len + strlen(val) + 1); 4722 strcpy(result + res_len, val); 4723 debug_printf_varexp("val:'%s' result:'%s'\n", val, result); 4724 } 4725 debug_printf_varexp("result:'%s'\n", result); 4726 return result; 4727 } 4728 #endif 4729 4730 /* Helper: 4731 * Handles <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct. 4732 */ 4733 static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, char **pp) 4734 { 4735 const char *val = NULL; 4736 char *to_be_freed = NULL; 4737 char *p = *pp; 4738 char *var; 4739 char first_char; 4740 char exp_op; 4741 char exp_save = exp_save; /* for compiler */ 4742 char *exp_saveptr; /* points to expansion operator */ 4743 char *exp_word = exp_word; /* for compiler */ 4744 char arg0; 4745 4746 *p = '\0'; /* replace trailing SPECIAL_VAR_SYMBOL */ 4747 var = arg; 4748 exp_saveptr = arg[1] ? strchr(VAR_ENCODED_SUBST_OPS, arg[1]) : NULL; 4749 arg0 = arg[0]; 4750 first_char = arg[0] = arg0 & 0x7f; 4751 exp_op = 0; 4752 4753 if (first_char == '#' /* ${#... */ 4754 && arg[1] && !exp_saveptr /* not ${#} and not ${#<op_char>...} */ 4755 ) { 4756 /* It must be length operator: ${#var} */ 4757 var++; 4758 exp_op = 'L'; 4759 } else { 4760 /* Maybe handle parameter expansion */ 4761 if (exp_saveptr /* if 2nd char is one of expansion operators */ 4762 && strchr(NUMERIC_SPECVARS_STR, first_char) /* 1st char is special variable */ 4763 ) { 4764 /* ${?:0}, ${#[:]%0} etc */ 4765 exp_saveptr = var + 1; 4766 } else { 4767 /* ${?}, ${var}, ${var:0}, ${var[:]%0} etc */ 4768 exp_saveptr = var+1 + strcspn(var+1, VAR_ENCODED_SUBST_OPS); 4769 } 4770 exp_op = exp_save = *exp_saveptr; 4771 if (exp_op) { 4772 exp_word = exp_saveptr + 1; 4773 if (exp_op == ':') { 4774 exp_op = *exp_word++; 4775 //TODO: try ${var:} and ${var:bogus} in non-bash config 4776 if (ENABLE_HUSH_BASH_COMPAT 4777 && (!exp_op || !strchr(MINUS_PLUS_EQUAL_QUESTION, exp_op)) 4778 ) { 4779 /* oops... it's ${var:N[:M]}, not ${var:?xxx} or some such */ 4780 exp_op = ':'; 4781 exp_word--; 4782 } 4783 } 4784 *exp_saveptr = '\0'; 4785 } /* else: it's not an expansion op, but bare ${var} */ 4786 } 4787 4788 /* Look up the variable in question */ 4789 if (isdigit(var[0])) { 4790 /* parse_dollar should have vetted var for us */ 4791 int n = xatoi_positive(var); 4792 if (n < G.global_argc) 4793 val = G.global_argv[n]; 4794 /* else val remains NULL: $N with too big N */ 4795 } else { 4796 switch (var[0]) { 4797 case '$': /* pid */ 4798 val = utoa(G.root_pid); 4799 break; 4800 case '!': /* bg pid */ 4801 val = G.last_bg_pid ? utoa(G.last_bg_pid) : ""; 4802 break; 4803 case '?': /* exitcode */ 4804 val = utoa(G.last_exitcode); 4805 break; 4806 case '#': /* argc */ 4807 val = utoa(G.global_argc ? G.global_argc-1 : 0); 4808 break; 4809 default: 4810 val = get_local_var_value(var); 4811 } 4812 } 4813 4814 /* Handle any expansions */ 4815 if (exp_op == 'L') { 4816 debug_printf_expand("expand: length(%s)=", val); 4817 val = utoa(val ? strlen(val) : 0); 4818 debug_printf_expand("%s\n", val); 4819 } else if (exp_op) { 4820 if (exp_op == '%' || exp_op == '#') { 4821 /* Standard-mandated substring removal ops: 4822 * ${parameter%word} - remove smallest suffix pattern 4823 * ${parameter%%word} - remove largest suffix pattern 4824 * ${parameter#word} - remove smallest prefix pattern 4825 * ${parameter##word} - remove largest prefix pattern 4826 * 4827 * Word is expanded to produce a glob pattern. 4828 * Then var's value is matched to it and matching part removed. 4829 */ 4830 if (val && val[0]) { 4831 char *t; 4832 char *exp_exp_word; 4833 char *loc; 4834 unsigned scan_flags = pick_scan(exp_op, *exp_word); 4835 if (exp_op == *exp_word) /* ## or %% */ 4836 exp_word++; 4837 exp_exp_word = encode_then_expand_string(exp_word, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); 4838 if (exp_exp_word) 4839 exp_word = exp_exp_word; 4840 /* HACK ALERT. We depend here on the fact that 4841 * G.global_argv and results of utoa and get_local_var_value 4842 * are actually in writable memory: 4843 * scan_and_match momentarily stores NULs there. */ 4844 t = (char*)val; 4845 loc = scan_and_match(t, exp_word, scan_flags); 4846 //bb_error_msg("op:%c str:'%s' pat:'%s' res:'%s'", 4847 // exp_op, t, exp_word, loc); 4848 free(exp_exp_word); 4849 if (loc) { /* match was found */ 4850 if (scan_flags & SCAN_MATCH_LEFT_HALF) /* #[#] */ 4851 val = loc; /* take right part */ 4852 else /* %[%] */ 4853 val = to_be_freed = xstrndup(val, loc - val); /* left */ 4854 } 4855 } 4856 } 4857 #if ENABLE_HUSH_BASH_COMPAT 4858 else if (exp_op == '/' || exp_op == '\\') { 4859 /* It's ${var/[/]pattern[/repl]} thing. 4860 * Note that in encoded form it has TWO parts: 4861 * var/pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL> 4862 * and if // is used, it is encoded as \: 4863 * var\pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL> 4864 */ 4865 /* Empty variable always gives nothing: */ 4866 // "v=''; echo ${v/*/w}" prints "", not "w" 4867 if (val && val[0]) { 4868 /* pattern uses non-standard expansion. 4869 * repl should be unbackslashed and globbed 4870 * by the usual expansion rules: 4871 * >az; >bz; 4872 * v='a bz'; echo "${v/a*z/a*z}" prints "a*z" 4873 * v='a bz'; echo "${v/a*z/\z}" prints "\z" 4874 * v='a bz'; echo ${v/a*z/a*z} prints "az" 4875 * v='a bz'; echo ${v/a*z/\z} prints "z" 4876 * (note that a*z _pattern_ is never globbed!) 4877 */ 4878 char *pattern, *repl, *t; 4879 pattern = encode_then_expand_string(exp_word, /*process_bkslash:*/ 0, /*unbackslash:*/ 0); 4880 if (!pattern) 4881 pattern = xstrdup(exp_word); 4882 debug_printf_varexp("pattern:'%s'->'%s'\n", exp_word, pattern); 4883 *p++ = SPECIAL_VAR_SYMBOL; 4884 exp_word = p; 4885 p = strchr(p, SPECIAL_VAR_SYMBOL); 4886 *p = '\0'; 4887 repl = encode_then_expand_string(exp_word, /*process_bkslash:*/ arg0 & 0x80, /*unbackslash:*/ 1); 4888 debug_printf_varexp("repl:'%s'->'%s'\n", exp_word, repl); 4889 /* HACK ALERT. We depend here on the fact that 4890 * G.global_argv and results of utoa and get_local_var_value 4891 * are actually in writable memory: 4892 * replace_pattern momentarily stores NULs there. */ 4893 t = (char*)val; 4894 to_be_freed = replace_pattern(t, 4895 pattern, 4896 (repl ? repl : exp_word), 4897 exp_op); 4898 if (to_be_freed) /* at least one replace happened */ 4899 val = to_be_freed; 4900 free(pattern); 4901 free(repl); 4902 } 4903 } 4904 #endif 4905 else if (exp_op == ':') { 4906 #if ENABLE_HUSH_BASH_COMPAT && ENABLE_SH_MATH_SUPPORT 4907 /* It's ${var:N[:M]} bashism. 4908 * Note that in encoded form it has TWO parts: 4909 * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL> 4910 */ 4911 arith_t beg, len; 4912 const char *errmsg; 4913 4914 beg = expand_and_evaluate_arith(exp_word, &errmsg); 4915 if (errmsg) 4916 goto arith_err; 4917 debug_printf_varexp("beg:'%s'=%lld\n", exp_word, (long long)beg); 4918 *p++ = SPECIAL_VAR_SYMBOL; 4919 exp_word = p; 4920 p = strchr(p, SPECIAL_VAR_SYMBOL); 4921 *p = '\0'; 4922 len = expand_and_evaluate_arith(exp_word, &errmsg); 4923 if (errmsg) 4924 goto arith_err; 4925 debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len); 4926 if (len >= 0) { /* bash compat: len < 0 is illegal */ 4927 if (beg < 0) /* bash compat */ 4928 beg = 0; 4929 debug_printf_varexp("from val:'%s'\n", val); 4930 if (len == 0 || !val || beg >= strlen(val)) { 4931 arith_err: 4932 val = NULL; 4933 } else { 4934 /* Paranoia. What if user entered 9999999999999 4935 * which fits in arith_t but not int? */ 4936 if (len >= INT_MAX) 4937 len = INT_MAX; 4938 val = to_be_freed = xstrndup(val + beg, len); 4939 } 4940 debug_printf_varexp("val:'%s'\n", val); 4941 } else 4942 #endif 4943 { 4944 die_if_script("malformed ${%s:...}", var); 4945 val = NULL; 4946 } 4947 } else { /* one of "-=+?" */ 4948 /* Standard-mandated substitution ops: 4949 * ${var?word} - indicate error if unset 4950 * If var is unset, word (or a message indicating it is unset 4951 * if word is null) is written to standard error 4952 * and the shell exits with a non-zero exit status. 4953 * Otherwise, the value of var is substituted. 4954 * ${var-word} - use default value 4955 * If var is unset, word is substituted. 4956 * ${var=word} - assign and use default value 4957 * If var is unset, word is assigned to var. 4958 * In all cases, final value of var is substituted. 4959 * ${var+word} - use alternative value 4960 * If var is unset, null is substituted. 4961 * Otherwise, word is substituted. 4962 * 4963 * Word is subjected to tilde expansion, parameter expansion, 4964 * command substitution, and arithmetic expansion. 4965 * If word is not needed, it is not expanded. 4966 * 4967 * Colon forms (${var:-word}, ${var:=word} etc) do the same, 4968 * but also treat null var as if it is unset. 4969 */ 4970 int use_word = (!val || ((exp_save == ':') && !val[0])); 4971 if (exp_op == '+') 4972 use_word = !use_word; 4973 debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op, 4974 (exp_save == ':') ? "true" : "false", use_word); 4975 if (use_word) { 4976 to_be_freed = encode_then_expand_string(exp_word, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); 4977 if (to_be_freed) 4978 exp_word = to_be_freed; 4979 if (exp_op == '?') { 4980 /* mimic bash message */ 4981 die_if_script("%s: %s", 4982 var, 4983 exp_word[0] ? exp_word : "parameter null or not set" 4984 ); 4985 //TODO: how interactive bash aborts expansion mid-command? 4986 } else { 4987 val = exp_word; 4988 } 4989 4990 if (exp_op == '=') { 4991 /* ${var=[word]} or ${var:=[word]} */ 4992 if (isdigit(var[0]) || var[0] == '#') { 4993 /* mimic bash message */ 4994 die_if_script("$%s: cannot assign in this way", var); 4995 val = NULL; 4996 } else { 4997 char *new_var = xasprintf("%s=%s", var, val); 4998 set_local_var(new_var, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0); 4999 } 5000 } 5001 } 5002 } /* one of "-=+?" */ 5003 5004 *exp_saveptr = exp_save; 5005 } /* if (exp_op) */ 5006 5007 arg[0] = arg0; 5008 5009 *pp = p; 5010 *to_be_freed_pp = to_be_freed; 5011 return val; 5012 } 5013 5014 /* Expand all variable references in given string, adding words to list[] 5015 * at n, n+1,... positions. Return updated n (so that list[n] is next one 5016 * to be filled). This routine is extremely tricky: has to deal with 5017 * variables/parameters with whitespace, $* and $@, and constructs like 5018 * 'echo -$*-'. If you play here, you must run testsuite afterwards! */ 5019 static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) 5020 { 5021 /* output->o_expflags & EXP_FLAG_SINGLEWORD (0x80) if we are in 5022 * expansion of right-hand side of assignment == 1-element expand. 5023 */ 5024 char cant_be_null = 0; /* only bit 0x80 matters */ 5025 char *p; 5026 5027 debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg, 5028 !!(output->o_expflags & EXP_FLAG_SINGLEWORD)); 5029 debug_print_list("expand_vars_to_list", output, n); 5030 n = o_save_ptr(output, n); 5031 debug_print_list("expand_vars_to_list[0]", output, n); 5032 5033 while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) { 5034 char first_ch; 5035 char *to_be_freed = NULL; 5036 const char *val = NULL; 5037 #if ENABLE_HUSH_TICK 5038 o_string subst_result = NULL_O_STRING; 5039 #endif 5040 #if ENABLE_SH_MATH_SUPPORT 5041 char arith_buf[sizeof(arith_t)*3 + 2]; 5042 #endif 5043 o_addblock(output, arg, p - arg); 5044 debug_print_list("expand_vars_to_list[1]", output, n); 5045 arg = ++p; 5046 p = strchr(p, SPECIAL_VAR_SYMBOL); 5047 5048 /* Fetch special var name (if it is indeed one of them) 5049 * and quote bit, force the bit on if singleword expansion - 5050 * important for not getting v=$@ expand to many words. */ 5051 first_ch = arg[0] | (output->o_expflags & EXP_FLAG_SINGLEWORD); 5052 5053 /* Is this variable quoted and thus expansion can't be null? 5054 * "$@" is special. Even if quoted, it can still 5055 * expand to nothing (not even an empty string), 5056 * thus it is excluded. */ 5057 if ((first_ch & 0x7f) != '@') 5058 cant_be_null |= first_ch; 5059 5060 switch (first_ch & 0x7f) { 5061 /* Highest bit in first_ch indicates that var is double-quoted */ 5062 case '*': 5063 case '@': { 5064 int i; 5065 if (!G.global_argv[1]) 5066 break; 5067 i = 1; 5068 cant_be_null |= first_ch; /* do it for "$@" _now_, when we know it's not empty */ 5069 if (!(first_ch & 0x80)) { /* unquoted $* or $@ */ 5070 while (G.global_argv[i]) { 5071 n = expand_on_ifs(output, n, G.global_argv[i]); 5072 debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1); 5073 if (G.global_argv[i++][0] && G.global_argv[i]) { 5074 /* this argv[] is not empty and not last: 5075 * put terminating NUL, start new word */ 5076 o_addchr(output, '\0'); 5077 debug_print_list("expand_vars_to_list[2]", output, n); 5078 n = o_save_ptr(output, n); 5079 debug_print_list("expand_vars_to_list[3]", output, n); 5080 } 5081 } 5082 } else 5083 /* If EXP_FLAG_SINGLEWORD, we handle assignment 'a=....$@.....' 5084 * and in this case should treat it like '$*' - see 'else...' below */ 5085 if (first_ch == ('@'|0x80) /* quoted $@ */ 5086 && !(output->o_expflags & EXP_FLAG_SINGLEWORD) /* not v="$@" case */ 5087 ) { 5088 while (1) { 5089 o_addQstr(output, G.global_argv[i]); 5090 if (++i >= G.global_argc) 5091 break; 5092 o_addchr(output, '\0'); 5093 debug_print_list("expand_vars_to_list[4]", output, n); 5094 n = o_save_ptr(output, n); 5095 } 5096 } else { /* quoted $* (or v="$@" case): add as one word */ 5097 while (1) { 5098 o_addQstr(output, G.global_argv[i]); 5099 if (!G.global_argv[++i]) 5100 break; 5101 if (G.ifs[0]) 5102 o_addchr(output, G.ifs[0]); 5103 } 5104 } 5105 break; 5106 } 5107 case SPECIAL_VAR_SYMBOL: /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_SYMBOL> */ 5108 /* "Empty variable", used to make "" etc to not disappear */ 5109 arg++; 5110 cant_be_null = 0x80; 5111 break; 5112 #if ENABLE_HUSH_TICK 5113 case '`': /* <SPECIAL_VAR_SYMBOL>`cmd<SPECIAL_VAR_SYMBOL> */ 5114 *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */ 5115 arg++; 5116 /* Can't just stuff it into output o_string, 5117 * expanded result may need to be globbed 5118 * and $IFS-splitted */ 5119 debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch); 5120 G.last_exitcode = process_command_subs(&subst_result, arg); 5121 debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data); 5122 val = subst_result.data; 5123 goto store_val; 5124 #endif 5125 #if ENABLE_SH_MATH_SUPPORT 5126 case '+': { /* <SPECIAL_VAR_SYMBOL>+cmd<SPECIAL_VAR_SYMBOL> */ 5127 arith_t res; 5128 5129 arg++; /* skip '+' */ 5130 *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */ 5131 debug_printf_subst("ARITH '%s' first_ch %x\n", arg, first_ch); 5132 res = expand_and_evaluate_arith(arg, NULL); 5133 debug_printf_subst("ARITH RES '"ARITH_FMT"'\n", res); 5134 sprintf(arith_buf, ARITH_FMT, res); 5135 val = arith_buf; 5136 break; 5137 } 5138 #endif 5139 default: 5140 val = expand_one_var(&to_be_freed, arg, &p); 5141 IF_HUSH_TICK(store_val:) 5142 if (!(first_ch & 0x80)) { /* unquoted $VAR */ 5143 debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val, 5144 !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); 5145 if (val && val[0]) { 5146 n = expand_on_ifs(output, n, val); 5147 val = NULL; 5148 } 5149 } else { /* quoted $VAR, val will be appended below */ 5150 debug_printf_expand("quoted '%s', output->o_escape:%d\n", val, 5151 !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); 5152 } 5153 break; 5154 5155 } /* switch (char after <SPECIAL_VAR_SYMBOL>) */ 5156 5157 if (val && val[0]) { 5158 o_addQstr(output, val); 5159 } 5160 free(to_be_freed); 5161 5162 /* Restore NULL'ed SPECIAL_VAR_SYMBOL. 5163 * Do the check to avoid writing to a const string. */ 5164 if (*p != SPECIAL_VAR_SYMBOL) 5165 *p = SPECIAL_VAR_SYMBOL; 5166 5167 #if ENABLE_HUSH_TICK 5168 o_free(&subst_result); 5169 #endif 5170 arg = ++p; 5171 } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */ 5172 5173 if (arg[0]) { 5174 debug_print_list("expand_vars_to_list[a]", output, n); 5175 /* this part is literal, and it was already pre-quoted 5176 * if needed (much earlier), do not use o_addQstr here! */ 5177 o_addstr_with_NUL(output, arg); 5178 debug_print_list("expand_vars_to_list[b]", output, n); 5179 } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */ 5180 && !(cant_be_null & 0x80) /* and all vars were not quoted. */ 5181 ) { 5182 n--; 5183 /* allow to reuse list[n] later without re-growth */ 5184 output->has_empty_slot = 1; 5185 } else { 5186 o_addchr(output, '\0'); 5187 } 5188 5189 return n; 5190 } 5191 5192 static char **expand_variables(char **argv, unsigned expflags) 5193 { 5194 int n; 5195 char **list; 5196 o_string output = NULL_O_STRING; 5197 5198 output.o_expflags = expflags; 5199 5200 n = 0; 5201 while (*argv) { 5202 n = expand_vars_to_list(&output, n, *argv); 5203 argv++; 5204 } 5205 debug_print_list("expand_variables", &output, n); 5206 5207 /* output.data (malloced in one block) gets returned in "list" */ 5208 list = o_finalize_list(&output, n); 5209 debug_print_strings("expand_variables[1]", list); 5210 return list; 5211 } 5212 5213 static char **expand_strvec_to_strvec(char **argv) 5214 { 5215 return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS); 5216 } 5217 5218 #if ENABLE_HUSH_BASH_COMPAT 5219 static char **expand_strvec_to_strvec_singleword_noglob(char **argv) 5220 { 5221 return expand_variables(argv, EXP_FLAG_SINGLEWORD); 5222 } 5223 #endif 5224 5225 /* Used for expansion of right hand of assignments, 5226 * $((...)), heredocs, variable espansion parts. 5227 * 5228 * NB: should NOT do globbing! 5229 * "export v=/bin/c*; env | grep ^v=" outputs "v=/bin/c*" 5230 */ 5231 static char *expand_string_to_string(const char *str, int do_unbackslash) 5232 { 5233 #if !ENABLE_HUSH_BASH_COMPAT 5234 const int do_unbackslash = 1; 5235 #endif 5236 char *argv[2], **list; 5237 5238 debug_printf_expand("string_to_string<='%s'\n", str); 5239 /* This is generally an optimization, but it also 5240 * handles "", which otherwise trips over !list[0] check below. 5241 * (is this ever happens that we actually get str="" here?) 5242 */ 5243 if (!strchr(str, SPECIAL_VAR_SYMBOL) && !strchr(str, '\\')) { 5244 //TODO: Can use on strings with \ too, just unbackslash() them? 5245 debug_printf_expand("string_to_string(fast)=>'%s'\n", str); 5246 return xstrdup(str); 5247 } 5248 5249 argv[0] = (char*)str; 5250 argv[1] = NULL; 5251 list = expand_variables(argv, do_unbackslash 5252 ? EXP_FLAG_ESC_GLOB_CHARS | EXP_FLAG_SINGLEWORD 5253 : EXP_FLAG_SINGLEWORD 5254 ); 5255 if (HUSH_DEBUG) 5256 if (!list[0] || list[1]) 5257 bb_error_msg_and_die("BUG in varexp2"); 5258 /* actually, just move string 2*sizeof(char*) bytes back */ 5259 overlapping_strcpy((char*)list, list[0]); 5260 if (do_unbackslash) 5261 unbackslash((char*)list); 5262 debug_printf_expand("string_to_string=>'%s'\n", (char*)list); 5263 return (char*)list; 5264 } 5265 5266 /* Used for "eval" builtin */ 5267 static char* expand_strvec_to_string(char **argv) 5268 { 5269 char **list; 5270 5271 list = expand_variables(argv, EXP_FLAG_SINGLEWORD); 5272 /* Convert all NULs to spaces */ 5273 if (list[0]) { 5274 int n = 1; 5275 while (list[n]) { 5276 if (HUSH_DEBUG) 5277 if (list[n-1] + strlen(list[n-1]) + 1 != list[n]) 5278 bb_error_msg_and_die("BUG in varexp3"); 5279 /* bash uses ' ' regardless of $IFS contents */ 5280 list[n][-1] = ' '; 5281 n++; 5282 } 5283 } 5284 overlapping_strcpy((char*)list, list[0]); 5285 debug_printf_expand("strvec_to_string='%s'\n", (char*)list); 5286 return (char*)list; 5287 } 5288 5289 static char **expand_assignments(char **argv, int count) 5290 { 5291 int i; 5292 char **p; 5293 5294 G.expanded_assignments = p = NULL; 5295 /* Expand assignments into one string each */ 5296 for (i = 0; i < count; i++) { 5297 G.expanded_assignments = p = add_string_to_strings(p, expand_string_to_string(argv[i], /*unbackslash:*/ 1)); 5298 } 5299 G.expanded_assignments = NULL; 5300 return p; 5301 } 5302 5303 5304 #if BB_MMU 5305 /* never called */ 5306 void re_execute_shell(char ***to_free, const char *s, 5307 char *g_argv0, char **g_argv, 5308 char **builtin_argv) NORETURN; 5309 5310 static void reset_traps_to_defaults(void) 5311 { 5312 /* This function is always called in a child shell 5313 * after fork (not vfork, NOMMU doesn't use this function). 5314 */ 5315 unsigned sig; 5316 unsigned mask; 5317 5318 /* Child shells are not interactive. 5319 * SIGTTIN/SIGTTOU/SIGTSTP should not have special handling. 5320 * Testcase: (while :; do :; done) + ^Z should background. 5321 * Same goes for SIGTERM, SIGHUP, SIGINT. 5322 */ 5323 if (!G.traps && !(G.non_DFL_mask & SPECIAL_INTERACTIVE_SIGS)) 5324 return; /* already no traps and no SPECIAL_INTERACTIVE_SIGS */ 5325 5326 /* Switching off SPECIAL_INTERACTIVE_SIGS. 5327 * Stupid. It can be done with *single* &= op, but we can't use 5328 * the fact that G.blocked_set is implemented as a bitmask 5329 * in libc... */ 5330 mask = (SPECIAL_INTERACTIVE_SIGS >> 1); 5331 sig = 1; 5332 while (1) { 5333 if (mask & 1) { 5334 /* Careful. Only if no trap or trap is not "" */ 5335 if (!G.traps || !G.traps[sig] || G.traps[sig][0]) 5336 sigdelset(&G.blocked_set, sig); 5337 } 5338 mask >>= 1; 5339 if (!mask) 5340 break; 5341 sig++; 5342 } 5343 /* Our homegrown sig mask is saner to work with :) */ 5344 G.non_DFL_mask &= ~SPECIAL_INTERACTIVE_SIGS; 5345 5346 /* Resetting all traps to default except empty ones */ 5347 mask = G.non_DFL_mask; 5348 if (G.traps) for (sig = 0; sig < NSIG; sig++, mask >>= 1) { 5349 if (!G.traps[sig] || !G.traps[sig][0]) 5350 continue; 5351 free(G.traps[sig]); 5352 G.traps[sig] = NULL; 5353 /* There is no signal for 0 (EXIT) */ 5354 if (sig == 0) 5355 continue; 5356 /* There was a trap handler, we just removed it. 5357 * But if sig still has non-DFL handling, 5358 * we should not unblock the sig. */ 5359 if (mask & 1) 5360 continue; 5361 sigdelset(&G.blocked_set, sig); 5362 } 5363 sigprocmask(SIG_SETMASK, &G.blocked_set, NULL); 5364 } 5365 5366 #else /* !BB_MMU */ 5367 5368 static void re_execute_shell(char ***to_free, const char *s, 5369 char *g_argv0, char **g_argv, 5370 char **builtin_argv) NORETURN; 5371 static void re_execute_shell(char ***to_free, const char *s, 5372 char *g_argv0, char **g_argv, 5373 char **builtin_argv) 5374 { 5375 # define NOMMU_HACK_FMT ("-$%x:%x:%x:%x:%x:%llx" IF_HUSH_LOOPS(":%x")) 5376 /* delims + 2 * (number of bytes in printed hex numbers) */ 5377 char param_buf[sizeof(NOMMU_HACK_FMT) + 2 * (sizeof(int)*6 + sizeof(long long)*1)]; 5378 char *heredoc_argv[4]; 5379 struct variable *cur; 5380 # if ENABLE_HUSH_FUNCTIONS 5381 struct function *funcp; 5382 # endif 5383 char **argv, **pp; 5384 unsigned cnt; 5385 unsigned long long empty_trap_mask; 5386 5387 if (!g_argv0) { /* heredoc */ 5388 argv = heredoc_argv; 5389 argv[0] = (char *) G.argv0_for_re_execing; 5390 argv[1] = (char *) "-<"; 5391 argv[2] = (char *) s; 5392 argv[3] = NULL; 5393 pp = &argv[3]; /* used as pointer to empty environment */ 5394 goto do_exec; 5395 } 5396 5397 cnt = 0; 5398 pp = builtin_argv; 5399 if (pp) while (*pp++) 5400 cnt++; 5401 5402 empty_trap_mask = 0; 5403 if (G.traps) { 5404 int sig; 5405 for (sig = 1; sig < NSIG; sig++) { 5406 if (G.traps[sig] && !G.traps[sig][0]) 5407 empty_trap_mask |= 1LL << sig; 5408 } 5409 } 5410 5411 sprintf(param_buf, NOMMU_HACK_FMT 5412 , (unsigned) G.root_pid 5413 , (unsigned) G.root_ppid 5414 , (unsigned) G.last_bg_pid 5415 , (unsigned) G.last_exitcode 5416 , cnt 5417 , empty_trap_mask 5418 IF_HUSH_LOOPS(, G.depth_of_loop) 5419 ); 5420 # undef NOMMU_HACK_FMT 5421 /* 1:hush 2:-$<pid>:<pid>:<exitcode>:<etc...> <vars...> <funcs...> 5422 * 3:-c 4:<cmd> 5:<arg0> <argN...> 6:NULL 5423 */ 5424 cnt += 6; 5425 for (cur = G.top_var; cur; cur = cur->next) { 5426 if (!cur->flg_export || cur->flg_read_only) 5427 cnt += 2; 5428 } 5429 # if ENABLE_HUSH_FUNCTIONS 5430 for (funcp = G.top_func; funcp; funcp = funcp->next) 5431 cnt += 3; 5432 # endif 5433 pp = g_argv; 5434 while (*pp++) 5435 cnt++; 5436 *to_free = argv = pp = xzalloc(sizeof(argv[0]) * cnt); 5437 *pp++ = (char *) G.argv0_for_re_execing; 5438 *pp++ = param_buf; 5439 for (cur = G.top_var; cur; cur = cur->next) { 5440 if (strcmp(cur->varstr, hush_version_str) == 0) 5441 continue; 5442 if (cur->flg_read_only) { 5443 *pp++ = (char *) "-R"; 5444 *pp++ = cur->varstr; 5445 } else if (!cur->flg_export) { 5446 *pp++ = (char *) "-V"; 5447 *pp++ = cur->varstr; 5448 } 5449 } 5450 # if ENABLE_HUSH_FUNCTIONS 5451 for (funcp = G.top_func; funcp; funcp = funcp->next) { 5452 *pp++ = (char *) "-F"; 5453 *pp++ = funcp->name; 5454 *pp++ = funcp->body_as_string; 5455 } 5456 # endif 5457 /* We can pass activated traps here. Say, -Tnn:trap_string 5458 * 5459 * However, POSIX says that subshells reset signals with traps 5460 * to SIG_DFL. 5461 * I tested bash-3.2 and it not only does that with true subshells 5462 * of the form ( list ), but with any forked children shells. 5463 * I set trap "echo W" WINCH; and then tried: 5464 * 5465 * { echo 1; sleep 20; echo 2; } & 5466 * while true; do echo 1; sleep 20; echo 2; break; done & 5467 * true | { echo 1; sleep 20; echo 2; } | cat 5468 * 5469 * In all these cases sending SIGWINCH to the child shell 5470 * did not run the trap. If I add trap "echo V" WINCH; 5471 * _inside_ group (just before echo 1), it works. 5472 * 5473 * I conclude it means we don't need to pass active traps here. 5474 * Even if we would use signal handlers instead of signal masking 5475 * in order to implement trap handling, 5476 * exec syscall below resets signals to SIG_DFL for us. 5477 */ 5478 *pp++ = (char *) "-c"; 5479 *pp++ = (char *) s; 5480 if (builtin_argv) { 5481 while (*++builtin_argv) 5482 *pp++ = *builtin_argv; 5483 *pp++ = (char *) ""; 5484 } 5485 *pp++ = g_argv0; 5486 while (*g_argv) 5487 *pp++ = *g_argv++; 5488 /* *pp = NULL; - is already there */ 5489 pp = environ; 5490 5491 do_exec: 5492 debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s); 5493 sigprocmask(SIG_SETMASK, &G.inherited_set, NULL); 5494 execve(bb_busybox_exec_path, argv, pp); 5495 /* Fallback. Useful for init=/bin/hush usage etc */ 5496 if (argv[0][0] == '/') 5497 execve(argv[0], argv, pp); 5498 xfunc_error_retval = 127; 5499 bb_error_msg_and_die("can't re-execute the shell"); 5500 } 5501 #endif /* !BB_MMU */ 5502 5503 5504 static int run_and_free_list(struct pipe *pi); 5505 5506 /* Executing from string: eval, sh -c '...' 5507 * or from file: /etc/profile, . file, sh <script>, sh (intereactive) 5508 * end_trigger controls how often we stop parsing 5509 * NUL: parse all, execute, return 5510 * ';': parse till ';' or newline, execute, repeat till EOF 5511 */ 5512 static void parse_and_run_stream(struct in_str *inp, int end_trigger) 5513 { 5514 /* Why we need empty flag? 5515 * An obscure corner case "false; ``; echo $?": 5516 * empty command in `` should still set $? to 0. 5517 * But we can't just set $? to 0 at the start, 5518 * this breaks "false; echo `echo $?`" case. 5519 */ 5520 bool empty = 1; 5521 while (1) { 5522 struct pipe *pipe_list; 5523 5524 pipe_list = parse_stream(NULL, inp, end_trigger); 5525 if (!pipe_list) { /* EOF */ 5526 if (empty) 5527 G.last_exitcode = 0; 5528 break; 5529 } 5530 debug_print_tree(pipe_list, 0); 5531 debug_printf_exec("parse_and_run_stream: run_and_free_list\n"); 5532 run_and_free_list(pipe_list); 5533 empty = 0; 5534 } 5535 } 5536 5537 static void parse_and_run_string(const char *s) 5538 { 5539 struct in_str input; 5540 setup_string_in_str(&input, s); 5541 parse_and_run_stream(&input, '\0'); 5542 } 5543 5544 static void parse_and_run_file(FILE *f) 5545 { 5546 struct in_str input; 5547 setup_file_in_str(&input, f); 5548 parse_and_run_stream(&input, ';'); 5549 } 5550 5551 #if ENABLE_HUSH_TICK 5552 static FILE *generate_stream_from_string(const char *s, pid_t *pid_p) 5553 { 5554 pid_t pid; 5555 int channel[2]; 5556 # if !BB_MMU 5557 char **to_free = NULL; 5558 # endif 5559 5560 xpipe(channel); 5561 pid = BB_MMU ? xfork() : xvfork(); 5562 if (pid == 0) { /* child */ 5563 disable_restore_tty_pgrp_on_exit(); 5564 /* Process substitution is not considered to be usual 5565 * 'command execution'. 5566 * SUSv3 says ctrl-Z should be ignored, ctrl-C should not. 5567 */ 5568 bb_signals(0 5569 + (1 << SIGTSTP) 5570 + (1 << SIGTTIN) 5571 + (1 << SIGTTOU) 5572 , SIG_IGN); 5573 CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */ 5574 close(channel[0]); /* NB: close _first_, then move fd! */ 5575 xmove_fd(channel[1], 1); 5576 /* Prevent it from trying to handle ctrl-z etc */ 5577 IF_HUSH_JOB(G.run_list_level = 1;) 5578 /* Awful hack for `trap` or $(trap). 5579 * 5580 * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html 5581 * contains an example where "trap" is executed in a subshell: 5582 * 5583 * save_traps=$(trap) 5584 * ... 5585 * eval "$save_traps" 5586 * 5587 * Standard does not say that "trap" in subshell shall print 5588 * parent shell's traps. It only says that its output 5589 * must have suitable form, but then, in the above example 5590 * (which is not supposed to be normative), it implies that. 5591 * 5592 * bash (and probably other shell) does implement it 5593 * (traps are reset to defaults, but "trap" still shows them), 5594 * but as a result, "trap" logic is hopelessly messed up: 5595 * 5596 * # trap 5597 * trap -- 'echo Ho' SIGWINCH <--- we have a handler 5598 * # (trap) <--- trap is in subshell - no output (correct, traps are reset) 5599 * # true | trap <--- trap is in subshell - no output (ditto) 5600 * # echo `true | trap` <--- in subshell - output (but traps are reset!) 5601 * trap -- 'echo Ho' SIGWINCH 5602 * # echo `(trap)` <--- in subshell in subshell - output 5603 * trap -- 'echo Ho' SIGWINCH 5604 * # echo `true | (trap)` <--- in subshell in subshell in subshell - output! 5605 * trap -- 'echo Ho' SIGWINCH 5606 * 5607 * The rules when to forget and when to not forget traps 5608 * get really complex and nonsensical. 5609 * 5610 * Our solution: ONLY bare $(trap) or `trap` is special. 5611 */ 5612 s = skip_whitespace(s); 5613 if (strncmp(s, "trap", 4) == 0 5614 && skip_whitespace(s + 4)[0] == '\0' 5615 ) { 5616 static const char *const argv[] = { NULL, NULL }; 5617 builtin_trap((char**)argv); 5618 exit(0); /* not _exit() - we need to fflush */ 5619 } 5620 # if BB_MMU 5621 reset_traps_to_defaults(); 5622 parse_and_run_string(s); 5623 _exit(G.last_exitcode); 5624 # else 5625 /* We re-execute after vfork on NOMMU. This makes this script safe: 5626 * yes "0123456789012345678901234567890" | dd bs=32 count=64k >BIG 5627 * huge=`cat BIG` # was blocking here forever 5628 * echo OK 5629 */ 5630 re_execute_shell(&to_free, 5631 s, 5632 G.global_argv[0], 5633 G.global_argv + 1, 5634 NULL); 5635 # endif 5636 } 5637 5638 /* parent */ 5639 *pid_p = pid; 5640 # if ENABLE_HUSH_FAST 5641 G.count_SIGCHLD++; 5642 //bb_error_msg("[%d] fork in generate_stream_from_string:" 5643 // " G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", 5644 // getpid(), G.count_SIGCHLD, G.handled_SIGCHLD); 5645 # endif 5646 enable_restore_tty_pgrp_on_exit(); 5647 # if !BB_MMU 5648 free(to_free); 5649 # endif 5650 close(channel[1]); 5651 close_on_exec_on(channel[0]); 5652 return xfdopen_for_read(channel[0]); 5653 } 5654 5655 /* Return code is exit status of the process that is run. */ 5656 static int process_command_subs(o_string *dest, const char *s) 5657 { 5658 FILE *fp; 5659 struct in_str pipe_str; 5660 pid_t pid; 5661 int status, ch, eol_cnt; 5662 5663 fp = generate_stream_from_string(s, &pid); 5664 5665 /* Now send results of command back into original context */ 5666 setup_file_in_str(&pipe_str, fp); 5667 eol_cnt = 0; 5668 while ((ch = i_getch(&pipe_str)) != EOF) { 5669 if (ch == '\n') { 5670 eol_cnt++; 5671 continue; 5672 } 5673 while (eol_cnt) { 5674 o_addchr(dest, '\n'); 5675 eol_cnt--; 5676 } 5677 o_addQchr(dest, ch); 5678 } 5679 5680 debug_printf("done reading from `cmd` pipe, closing it\n"); 5681 fclose(fp); 5682 /* We need to extract exitcode. Test case 5683 * "true; echo `sleep 1; false` $?" 5684 * should print 1 */ 5685 safe_waitpid(pid, &status, 0); 5686 debug_printf("child exited. returning its exitcode:%d\n", WEXITSTATUS(status)); 5687 return WEXITSTATUS(status); 5688 } 5689 #endif /* ENABLE_HUSH_TICK */ 5690 5691 5692 static void setup_heredoc(struct redir_struct *redir) 5693 { 5694 struct fd_pair pair; 5695 pid_t pid; 5696 int len, written; 5697 /* the _body_ of heredoc (misleading field name) */ 5698 const char *heredoc = redir->rd_filename; 5699 char *expanded; 5700 #if !BB_MMU 5701 char **to_free; 5702 #endif 5703 5704 expanded = NULL; 5705 if (!(redir->rd_dup & HEREDOC_QUOTED)) { 5706 expanded = encode_then_expand_string(heredoc, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); 5707 if (expanded) 5708 heredoc = expanded; 5709 } 5710 len = strlen(heredoc); 5711 5712 close(redir->rd_fd); /* often saves dup2+close in xmove_fd */ 5713 xpiped_pair(pair); 5714 xmove_fd(pair.rd, redir->rd_fd); 5715 5716 /* Try writing without forking. Newer kernels have 5717 * dynamically growing pipes. Must use non-blocking write! */ 5718 ndelay_on(pair.wr); 5719 while (1) { 5720 written = write(pair.wr, heredoc, len); 5721 if (written <= 0) 5722 break; 5723 len -= written; 5724 if (len == 0) { 5725 close(pair.wr); 5726 free(expanded); 5727 return; 5728 } 5729 heredoc += written; 5730 } 5731 ndelay_off(pair.wr); 5732 5733 /* Okay, pipe buffer was not big enough */ 5734 /* Note: we must not create a stray child (bastard? :) 5735 * for the unsuspecting parent process. Child creates a grandchild 5736 * and exits before parent execs the process which consumes heredoc 5737 * (that exec happens after we return from this function) */ 5738 #if !BB_MMU 5739 to_free = NULL; 5740 #endif 5741 pid = xvfork(); 5742 if (pid == 0) { 5743 /* child */ 5744 disable_restore_tty_pgrp_on_exit(); 5745 pid = BB_MMU ? xfork() : xvfork(); 5746 if (pid != 0) 5747 _exit(0); 5748 /* grandchild */ 5749 close(redir->rd_fd); /* read side of the pipe */ 5750 #if BB_MMU 5751 full_write(pair.wr, heredoc, len); /* may loop or block */ 5752 _exit(0); 5753 #else 5754 /* Delegate blocking writes to another process */ 5755 xmove_fd(pair.wr, STDOUT_FILENO); 5756 re_execute_shell(&to_free, heredoc, NULL, NULL, NULL); 5757 #endif 5758 } 5759 /* parent */ 5760 #if ENABLE_HUSH_FAST 5761 G.count_SIGCHLD++; 5762 //bb_error_msg("[%d] fork in setup_heredoc: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD); 5763 #endif 5764 enable_restore_tty_pgrp_on_exit(); 5765 #if !BB_MMU 5766 free(to_free); 5767 #endif 5768 close(pair.wr); 5769 free(expanded); 5770 wait(NULL); /* wait till child has died */ 1277 5771 } 1278 5772 1279 5773 /* squirrel != NULL means we squirrel away copies of stdin, stdout, 1280 5774 * and stderr if they are redirected. */ 1281 static int setup_redirects(struct c hild_prog*prog, int squirrel[])5775 static int setup_redirects(struct command *prog, int squirrel[]) 1282 5776 { 1283 5777 int openfd, mode; … … 1285 5779 1286 5780 for (redir = prog->redirects; redir; redir = redir->next) { 1287 if (redir->dup == -1 && redir->word.gl_pathv == NULL) { 1288 /* something went wrong in the parse. Pretend it didn't happen */ 5781 if (redir->rd_type == REDIRECT_HEREDOC2) { 5782 /* rd_fd<<HERE case */ 5783 if (squirrel && redir->rd_fd < 3 5784 && squirrel[redir->rd_fd] < 0 5785 ) { 5786 squirrel[redir->rd_fd] = dup(redir->rd_fd); 5787 } 5788 /* for REDIRECT_HEREDOC2, rd_filename holds _contents_ 5789 * of the heredoc */ 5790 debug_printf_parse("set heredoc '%s'\n", 5791 redir->rd_filename); 5792 setup_heredoc(redir); 1289 5793 continue; 1290 5794 } 1291 if (redir->dup == -1) { 1292 mode = redir_table[redir->type].mode; 1293 openfd = open_or_warn(redir->word.gl_pathv[0], mode); 5795 5796 if (redir->rd_dup == REDIRFD_TO_FILE) { 5797 /* rd_fd<*>file case (<*> is <,>,>>,<>) */ 5798 char *p; 5799 if (redir->rd_filename == NULL) { 5800 /* Something went wrong in the parse. 5801 * Pretend it didn't happen */ 5802 bb_error_msg("bug in redirect parse"); 5803 continue; 5804 } 5805 mode = redir_table[redir->rd_type].mode; 5806 p = expand_string_to_string(redir->rd_filename, /*unbackslash:*/ 1); 5807 openfd = open_or_warn(p, mode); 5808 free(p); 1294 5809 if (openfd < 0) { 1295 5810 /* this could get lost if stderr has been redirected, but 1296 bash and ash both lose it as well (though zsh doesn't!) */ 5811 * bash and ash both lose it as well (though zsh doesn't!) */ 5812 //what the above comment tries to say? 1297 5813 return 1; 1298 5814 } 1299 5815 } else { 1300 openfd = redir->dup; 1301 } 1302 1303 if (openfd != redir->fd) { 1304 if (squirrel && redir->fd < 3) { 1305 squirrel[redir->fd] = dup(redir->fd); 1306 } 1307 if (openfd == -3) { 1308 close(openfd); 5816 /* rd_fd<*>rd_dup or rd_fd<*>- cases */ 5817 openfd = redir->rd_dup; 5818 } 5819 5820 if (openfd != redir->rd_fd) { 5821 if (squirrel && redir->rd_fd < 3 5822 && squirrel[redir->rd_fd] < 0 5823 ) { 5824 squirrel[redir->rd_fd] = dup(redir->rd_fd); 5825 } 5826 if (openfd == REDIRFD_CLOSE) { 5827 /* "n>-" means "close me" */ 5828 close(redir->rd_fd); 1309 5829 } else { 1310 dup2(openfd, redir->fd);1311 if (redir-> dup == -1)5830 xdup2(openfd, redir->rd_fd); 5831 if (redir->rd_dup == REDIRFD_TO_FILE) 1312 5832 close(openfd); 1313 5833 } … … 1329 5849 } 1330 5850 1331 /* never returns */ 1332 /* XXX no exit() here. If you don't exec, use _exit instead. 5851 static char *find_in_path(const char *arg) 5852 { 5853 char *ret = NULL; 5854 const char *PATH = get_local_var_value("PATH"); 5855 5856 if (!PATH) 5857 return NULL; 5858 5859 while (1) { 5860 const char *end = strchrnul(PATH, ':'); 5861 int sz = end - PATH; /* must be int! */ 5862 5863 free(ret); 5864 if (sz != 0) { 5865 ret = xasprintf("%.*s/%s", sz, PATH, arg); 5866 } else { 5867 /* We have xxx::yyyy in $PATH, 5868 * it means "use current dir" */ 5869 ret = xstrdup(arg); 5870 } 5871 if (access(ret, F_OK) == 0) 5872 break; 5873 5874 if (*end == '\0') { 5875 free(ret); 5876 return NULL; 5877 } 5878 PATH = end + 1; 5879 } 5880 5881 return ret; 5882 } 5883 5884 static const struct built_in_command *find_builtin_helper(const char *name, 5885 const struct built_in_command *x, 5886 const struct built_in_command *end) 5887 { 5888 while (x != end) { 5889 if (strcmp(name, x->b_cmd) != 0) { 5890 x++; 5891 continue; 5892 } 5893 debug_printf_exec("found builtin '%s'\n", name); 5894 return x; 5895 } 5896 return NULL; 5897 } 5898 static const struct built_in_command *find_builtin1(const char *name) 5899 { 5900 return find_builtin_helper(name, bltins1, &bltins1[ARRAY_SIZE(bltins1)]); 5901 } 5902 static const struct built_in_command *find_builtin(const char *name) 5903 { 5904 const struct built_in_command *x = find_builtin1(name); 5905 if (x) 5906 return x; 5907 return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]); 5908 } 5909 5910 #if ENABLE_HUSH_FUNCTIONS 5911 static struct function **find_function_slot(const char *name) 5912 { 5913 struct function **funcpp = &G.top_func; 5914 while (*funcpp) { 5915 if (strcmp(name, (*funcpp)->name) == 0) { 5916 break; 5917 } 5918 funcpp = &(*funcpp)->next; 5919 } 5920 return funcpp; 5921 } 5922 5923 static const struct function *find_function(const char *name) 5924 { 5925 const struct function *funcp = *find_function_slot(name); 5926 if (funcp) 5927 debug_printf_exec("found function '%s'\n", name); 5928 return funcp; 5929 } 5930 5931 /* Note: takes ownership on name ptr */ 5932 static struct function *new_function(char *name) 5933 { 5934 struct function **funcpp = find_function_slot(name); 5935 struct function *funcp = *funcpp; 5936 5937 if (funcp != NULL) { 5938 struct command *cmd = funcp->parent_cmd; 5939 debug_printf_exec("func %p parent_cmd %p\n", funcp, cmd); 5940 if (!cmd) { 5941 debug_printf_exec("freeing & replacing function '%s'\n", funcp->name); 5942 free(funcp->name); 5943 /* Note: if !funcp->body, do not free body_as_string! 5944 * This is a special case of "-F name body" function: 5945 * body_as_string was not malloced! */ 5946 if (funcp->body) { 5947 free_pipe_list(funcp->body); 5948 # if !BB_MMU 5949 free(funcp->body_as_string); 5950 # endif 5951 } 5952 } else { 5953 debug_printf_exec("reinserting in tree & replacing function '%s'\n", funcp->name); 5954 cmd->argv[0] = funcp->name; 5955 cmd->group = funcp->body; 5956 # if !BB_MMU 5957 cmd->group_as_string = funcp->body_as_string; 5958 # endif 5959 } 5960 } else { 5961 debug_printf_exec("remembering new function '%s'\n", name); 5962 funcp = *funcpp = xzalloc(sizeof(*funcp)); 5963 /*funcp->next = NULL;*/ 5964 } 5965 5966 funcp->name = name; 5967 return funcp; 5968 } 5969 5970 static void unset_func(const char *name) 5971 { 5972 struct function **funcpp = find_function_slot(name); 5973 struct function *funcp = *funcpp; 5974 5975 if (funcp != NULL) { 5976 debug_printf_exec("freeing function '%s'\n", funcp->name); 5977 *funcpp = funcp->next; 5978 /* funcp is unlinked now, deleting it. 5979 * Note: if !funcp->body, the function was created by 5980 * "-F name body", do not free ->body_as_string 5981 * and ->name as they were not malloced. */ 5982 if (funcp->body) { 5983 free_pipe_list(funcp->body); 5984 free(funcp->name); 5985 # if !BB_MMU 5986 free(funcp->body_as_string); 5987 # endif 5988 } 5989 free(funcp); 5990 } 5991 } 5992 5993 # if BB_MMU 5994 #define exec_function(to_free, funcp, argv) \ 5995 exec_function(funcp, argv) 5996 # endif 5997 static void exec_function(char ***to_free, 5998 const struct function *funcp, 5999 char **argv) NORETURN; 6000 static void exec_function(char ***to_free, 6001 const struct function *funcp, 6002 char **argv) 6003 { 6004 # if BB_MMU 6005 int n = 1; 6006 6007 argv[0] = G.global_argv[0]; 6008 G.global_argv = argv; 6009 while (*++argv) 6010 n++; 6011 G.global_argc = n; 6012 /* On MMU, funcp->body is always non-NULL */ 6013 n = run_list(funcp->body); 6014 fflush_all(); 6015 _exit(n); 6016 # else 6017 re_execute_shell(to_free, 6018 funcp->body_as_string, 6019 G.global_argv[0], 6020 argv + 1, 6021 NULL); 6022 # endif 6023 } 6024 6025 static int run_function(const struct function *funcp, char **argv) 6026 { 6027 int rc; 6028 save_arg_t sv; 6029 smallint sv_flg; 6030 6031 save_and_replace_G_args(&sv, argv); 6032 6033 /* "we are in function, ok to use return" */ 6034 sv_flg = G.flag_return_in_progress; 6035 G.flag_return_in_progress = -1; 6036 # if ENABLE_HUSH_LOCAL 6037 G.func_nest_level++; 6038 # endif 6039 6040 /* On MMU, funcp->body is always non-NULL */ 6041 # if !BB_MMU 6042 if (!funcp->body) { 6043 /* Function defined by -F */ 6044 parse_and_run_string(funcp->body_as_string); 6045 rc = G.last_exitcode; 6046 } else 6047 # endif 6048 { 6049 rc = run_list(funcp->body); 6050 } 6051 6052 # if ENABLE_HUSH_LOCAL 6053 { 6054 struct variable *var; 6055 struct variable **var_pp; 6056 6057 var_pp = &G.top_var; 6058 while ((var = *var_pp) != NULL) { 6059 if (var->func_nest_level < G.func_nest_level) { 6060 var_pp = &var->next; 6061 continue; 6062 } 6063 /* Unexport */ 6064 if (var->flg_export) 6065 bb_unsetenv(var->varstr); 6066 /* Remove from global list */ 6067 *var_pp = var->next; 6068 /* Free */ 6069 if (!var->max_len) 6070 free(var->varstr); 6071 free(var); 6072 } 6073 G.func_nest_level--; 6074 } 6075 # endif 6076 G.flag_return_in_progress = sv_flg; 6077 6078 restore_G_args(&sv, argv); 6079 6080 return rc; 6081 } 6082 #endif /* ENABLE_HUSH_FUNCTIONS */ 6083 6084 6085 #if BB_MMU 6086 #define exec_builtin(to_free, x, argv) \ 6087 exec_builtin(x, argv) 6088 #else 6089 #define exec_builtin(to_free, x, argv) \ 6090 exec_builtin(to_free, argv) 6091 #endif 6092 static void exec_builtin(char ***to_free, 6093 const struct built_in_command *x, 6094 char **argv) NORETURN; 6095 static void exec_builtin(char ***to_free, 6096 const struct built_in_command *x, 6097 char **argv) 6098 { 6099 #if BB_MMU 6100 int rcode = x->b_function(argv); 6101 fflush_all(); 6102 _exit(rcode); 6103 #else 6104 /* On NOMMU, we must never block! 6105 * Example: { sleep 99 | read line; } & echo Ok 6106 */ 6107 re_execute_shell(to_free, 6108 argv[0], 6109 G.global_argv[0], 6110 G.global_argv + 1, 6111 argv); 6112 #endif 6113 } 6114 6115 6116 static void execvp_or_die(char **argv) NORETURN; 6117 static void execvp_or_die(char **argv) 6118 { 6119 debug_printf_exec("execing '%s'\n", argv[0]); 6120 sigprocmask(SIG_SETMASK, &G.inherited_set, NULL); 6121 execvp(argv[0], argv); 6122 bb_perror_msg("can't execute '%s'", argv[0]); 6123 _exit(127); /* bash compat */ 6124 } 6125 6126 #if ENABLE_HUSH_MODE_X 6127 static void dump_cmd_in_x_mode(char **argv) 6128 { 6129 if (G_x_mode && argv) { 6130 /* We want to output the line in one write op */ 6131 char *buf, *p; 6132 int len; 6133 int n; 6134 6135 len = 3; 6136 n = 0; 6137 while (argv[n]) 6138 len += strlen(argv[n++]) + 1; 6139 buf = xmalloc(len); 6140 buf[0] = '+'; 6141 p = buf + 1; 6142 n = 0; 6143 while (argv[n]) 6144 p += sprintf(p, " %s", argv[n++]); 6145 *p++ = '\n'; 6146 *p = '\0'; 6147 fputs(buf, stderr); 6148 free(buf); 6149 } 6150 } 6151 #else 6152 # define dump_cmd_in_x_mode(argv) ((void)0) 6153 #endif 6154 6155 #if BB_MMU 6156 #define pseudo_exec_argv(nommu_save, argv, assignment_cnt, argv_expanded) \ 6157 pseudo_exec_argv(argv, assignment_cnt, argv_expanded) 6158 #define pseudo_exec(nommu_save, command, argv_expanded) \ 6159 pseudo_exec(command, argv_expanded) 6160 #endif 6161 6162 /* Called after [v]fork() in run_pipe, or from builtin_exec. 6163 * Never returns. 6164 * Don't exit() here. If you don't exec, use _exit instead. 1333 6165 * The at_exit handlers apparently confuse the calling process, 1334 6166 * in particular stdin handling. Not sure why? -- because of vfork! (vda) */ 1335 static void pseudo_exec_argv( char **argv)1336 { 1337 int i, rcode;1338 char *p; 1339 const struct built_in_command *x;1340 1341 for (i = 0; is_assignment(argv[i]); i++){1342 debug_printf_exec("pid %d environment modification: %s\n",1343 getpid(), argv[i]); 1344 // FIXME: vfork case?? 1345 p = expand_string_to_string(argv[i]);1346 putenv(p); 1347 }1348 argv += i;1349 /* If a variable is assigned in a forest, and nobody listens,1350 * was it ever really set?1351 */1352 if (argv[0] == NULL) {6167 static void pseudo_exec_argv(nommu_save_t *nommu_save, 6168 char **argv, int assignment_cnt, 6169 char **argv_expanded) NORETURN; 6170 static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save, 6171 char **argv, int assignment_cnt, 6172 char **argv_expanded) 6173 { 6174 char **new_env; 6175 6176 new_env = expand_assignments(argv, assignment_cnt); 6177 dump_cmd_in_x_mode(new_env); 6178 6179 if (!argv[assignment_cnt]) { 6180 /* Case when we are here: ... | var=val | ... 6181 * (note that we do not exit early, i.e., do not optimize out 6182 * expand_assignments(): think about ... | var=`sleep 1` | ... 6183 */ 6184 free_strings(new_env); 1353 6185 _exit(EXIT_SUCCESS); 1354 6186 } 1355 6187 1356 argv = expand_strvec_to_strvec(argv); 1357 1358 /* 1359 * Check if the command matches any of the builtins. 6188 #if BB_MMU 6189 set_vars_and_save_old(new_env); 6190 free(new_env); /* optional */ 6191 /* we can also destroy set_vars_and_save_old's return value, 6192 * to save memory */ 6193 #else 6194 nommu_save->new_env = new_env; 6195 nommu_save->old_vars = set_vars_and_save_old(new_env); 6196 #endif 6197 6198 if (argv_expanded) { 6199 argv = argv_expanded; 6200 } else { 6201 argv = expand_strvec_to_strvec(argv + assignment_cnt); 6202 #if !BB_MMU 6203 nommu_save->argv = argv; 6204 #endif 6205 } 6206 dump_cmd_in_x_mode(argv); 6207 6208 #if ENABLE_FEATURE_SH_STANDALONE || BB_MMU 6209 if (strchr(argv[0], '/') != NULL) 6210 goto skip; 6211 #endif 6212 6213 /* Check if the command matches any of the builtins. 1360 6214 * Depending on context, this might be redundant. But it's 1361 6215 * easier to waste a few CPU cycles than it is to figure out 1362 6216 * if this is one of those cases. 1363 6217 */ 1364 for (x = bltins; x->cmd; x++) { 1365 if (strcmp(argv[0], x->cmd) == 0) { 1366 debug_printf_exec("running builtin '%s'\n", argv[0]); 1367 rcode = x->function(argv); 1368 fflush(stdout); 1369 _exit(rcode); 1370 } 1371 } 1372 6218 { 6219 /* On NOMMU, it is more expensive to re-execute shell 6220 * just in order to run echo or test builtin. 6221 * It's better to skip it here and run corresponding 6222 * non-builtin later. */ 6223 const struct built_in_command *x; 6224 x = BB_MMU ? find_builtin(argv[0]) : find_builtin1(argv[0]); 6225 if (x) { 6226 exec_builtin(&nommu_save->argv_from_re_execing, x, argv); 6227 } 6228 } 6229 #if ENABLE_HUSH_FUNCTIONS 6230 /* Check if the command matches any functions */ 6231 { 6232 const struct function *funcp = find_function(argv[0]); 6233 if (funcp) { 6234 exec_function(&nommu_save->argv_from_re_execing, funcp, argv); 6235 } 6236 } 6237 #endif 6238 6239 #if ENABLE_FEATURE_SH_STANDALONE 1373 6240 /* Check if the command matches any busybox applets */ 1374 #if ENABLE_FEATURE_SH_STANDALONE 1375 if (strchr(argv[0], '/') == NULL) { 1376 const struct bb_applet *a = find_applet_by_name(argv[0]); 1377 if (a) { 1378 if (a->noexec) { 1379 current_applet = a; 6241 { 6242 int a = find_applet_by_name(argv[0]); 6243 if (a >= 0) { 6244 # if BB_MMU /* see above why on NOMMU it is not allowed */ 6245 if (APPLET_IS_NOEXEC(a)) { 1380 6246 debug_printf_exec("running applet '%s'\n", argv[0]); 1381 // is it ok that run_current_applet_and_exit() does exit(), not _exit()? 1382 run_current_applet_and_exit(argv);1383 } 1384 /* re-exec ourselves with the new arguments */6247 run_applet_no_and_exit(a, argv); 6248 } 6249 # endif 6250 /* Re-exec ourselves */ 1385 6251 debug_printf_exec("re-execing applet '%s'\n", argv[0]); 1386 execvp(bb_busybox_exec_path, argv); 6252 sigprocmask(SIG_SETMASK, &G.inherited_set, NULL); 6253 execv(bb_busybox_exec_path, argv); 1387 6254 /* If they called chroot or otherwise made the binary no longer 1388 6255 * executable, fall through */ … … 1391 6258 #endif 1392 6259 1393 debug_printf_exec("execing '%s'\n", argv[0]); 1394 execvp(argv[0], argv); 1395 bb_perror_msg("cannot exec '%s'", argv[0]); 1396 _exit(1); 1397 } 1398 1399 static void pseudo_exec(struct child_prog *child) 1400 { 1401 // FIXME: buggy wrt NOMMU! Must not modify any global data 1402 // until it does exec/_exit, but currently it does. 1403 int rcode; 1404 1405 if (child->argv) { 1406 pseudo_exec_argv(child->argv); 1407 } 1408 1409 if (child->group) { 1410 // FIXME: do not modify globals! Think vfork! 1411 #if ENABLE_HUSH_INTERACTIVE 1412 debug_printf_exec("pseudo_exec: setting interactive_fd=0\n"); 1413 interactive_fd = 0; /* crucial!!!! */ 1414 #endif 1415 debug_printf_exec("pseudo_exec: run_list_real\n"); 1416 rcode = run_list_real(child->group); 6260 #if ENABLE_FEATURE_SH_STANDALONE || BB_MMU 6261 skip: 6262 #endif 6263 execvp_or_die(argv); 6264 } 6265 6266 /* Called after [v]fork() in run_pipe 6267 */ 6268 static void pseudo_exec(nommu_save_t *nommu_save, 6269 struct command *command, 6270 char **argv_expanded) NORETURN; 6271 static void pseudo_exec(nommu_save_t *nommu_save, 6272 struct command *command, 6273 char **argv_expanded) 6274 { 6275 if (command->argv) { 6276 pseudo_exec_argv(nommu_save, command->argv, 6277 command->assignment_cnt, argv_expanded); 6278 } 6279 6280 if (command->group) { 6281 /* Cases when we are here: 6282 * ( list ) 6283 * { list } & 6284 * ... | ( list ) | ... 6285 * ... | { list } | ... 6286 */ 6287 #if BB_MMU 6288 int rcode; 6289 debug_printf_exec("pseudo_exec: run_list\n"); 6290 reset_traps_to_defaults(); 6291 rcode = run_list(command->group); 1417 6292 /* OK to leak memory by not calling free_pipe_list, 1418 6293 * since this process is about to exit */ 1419 6294 _exit(rcode); 1420 } 1421 1422 /* Can happen. See what bash does with ">foo" by itself. */ 1423 debug_printf("trying to pseudo_exec null command\n"); 6295 #else 6296 re_execute_shell(&nommu_save->argv_from_re_execing, 6297 command->group_as_string, 6298 G.global_argv[0], 6299 G.global_argv + 1, 6300 NULL); 6301 #endif 6302 } 6303 6304 /* Case when we are here: ... | >file */ 6305 debug_printf_exec("pseudo_exec'ed null command\n"); 1424 6306 _exit(EXIT_SUCCESS); 1425 6307 } … … 1437 6319 if (pi->cmdtext) 1438 6320 return pi->cmdtext; 1439 argv = pi->progs[0].argv; 1440 if (!argv || !argv[0]) 1441 return (pi->cmdtext = xzalloc(1)); 6321 argv = pi->cmds[0].argv; 6322 if (!argv || !argv[0]) { 6323 pi->cmdtext = xzalloc(1); 6324 return pi->cmdtext; 6325 } 1442 6326 1443 6327 len = 0; 1444 do len += strlen(*argv) + 1; while (*++argv); 1445 pi->cmdtext = p = xmalloc(len); 1446 argv = pi->progs[0].argv; 6328 do { 6329 len += strlen(*argv) + 1; 6330 } while (*++argv); 6331 p = xmalloc(len); 6332 pi->cmdtext = p; 6333 argv = pi->cmds[0].argv; 1447 6334 do { 1448 6335 len = strlen(*argv); … … 1457 6344 static void insert_bg_job(struct pipe *pi) 1458 6345 { 1459 struct pipe * thejob;6346 struct pipe *job, **jobp; 1460 6347 int i; 1461 6348 1462 6349 /* Linear search for the ID of the job to use */ 1463 6350 pi->jobid = 1; 1464 for (thejob = job_list; thejob; thejob = thejob->next) 1465 if (thejob->jobid >= pi->jobid) 1466 pi->jobid = thejob->jobid + 1; 1467 1468 /* Add thejob to the list of running jobs */ 1469 if (!job_list) { 1470 thejob = job_list = xmalloc(sizeof(*thejob)); 6351 for (job = G.job_list; job; job = job->next) 6352 if (job->jobid >= pi->jobid) 6353 pi->jobid = job->jobid + 1; 6354 6355 /* Add job to the list of running jobs */ 6356 jobp = &G.job_list; 6357 while ((job = *jobp) != NULL) 6358 jobp = &job->next; 6359 job = *jobp = xmalloc(sizeof(*job)); 6360 6361 *job = *pi; /* physical copy */ 6362 job->next = NULL; 6363 job->cmds = xzalloc(sizeof(pi->cmds[0]) * pi->num_cmds); 6364 /* Cannot copy entire pi->cmds[] vector! This causes double frees */ 6365 for (i = 0; i < pi->num_cmds; i++) { 6366 job->cmds[i].pid = pi->cmds[i].pid; 6367 /* all other fields are not used and stay zero */ 6368 } 6369 job->cmdtext = xstrdup(get_cmdtext(pi)); 6370 6371 if (G_interactive_fd) 6372 printf("[%d] %d %s\n", job->jobid, job->cmds[0].pid, job->cmdtext); 6373 G.last_jobid = job->jobid; 6374 } 6375 6376 static void remove_bg_job(struct pipe *pi) 6377 { 6378 struct pipe *prev_pipe; 6379 6380 if (pi == G.job_list) { 6381 G.job_list = pi->next; 1471 6382 } else { 1472 for (thejob = job_list; thejob->next; thejob = thejob->next) 1473 continue; 1474 thejob->next = xmalloc(sizeof(*thejob)); 1475 thejob = thejob->next; 1476 } 1477 1478 /* Physically copy the struct job */ 1479 memcpy(thejob, pi, sizeof(struct pipe)); 1480 thejob->progs = xzalloc(sizeof(pi->progs[0]) * pi->num_progs); 1481 /* We cannot copy entire pi->progs[] vector! Double free()s will happen */ 1482 for (i = 0; i < pi->num_progs; i++) { 1483 // TODO: do we really need to have so many fields which are just dead weight 1484 // at execution stage? 1485 thejob->progs[i].pid = pi->progs[i].pid; 1486 /* all other fields are not used and stay zero */ 1487 } 1488 thejob->next = NULL; 1489 thejob->cmdtext = xstrdup(get_cmdtext(pi)); 1490 1491 /* We don't wait for background thejobs to return -- append it 1492 to the list of backgrounded thejobs and leave it alone */ 1493 printf("[%d] %d %s\n", thejob->jobid, thejob->progs[0].pid, thejob->cmdtext); 1494 last_bg_pid = thejob->progs[0].pid; 1495 last_jobid = thejob->jobid; 1496 } 1497 1498 static void remove_bg_job(struct pipe *pi) 1499 { 1500 struct pipe *prev_pipe; 1501 1502 if (pi == job_list) { 1503 job_list = pi->next; 1504 } else { 1505 prev_pipe = job_list; 6383 prev_pipe = G.job_list; 1506 6384 while (prev_pipe->next != pi) 1507 6385 prev_pipe = prev_pipe->next; 1508 6386 prev_pipe->next = pi->next; 1509 6387 } 1510 if ( job_list)1511 last_jobid =job_list->jobid;6388 if (G.job_list) 6389 G.last_jobid = G.job_list->jobid; 1512 6390 else 1513 last_jobid = 0;1514 } 1515 1516 /* remove a backgrounded job */6391 G.last_jobid = 0; 6392 } 6393 6394 /* Remove a backgrounded job */ 1517 6395 static void delete_finished_bg_job(struct pipe *pi) 1518 6396 { 1519 6397 remove_bg_job(pi); 1520 pi->stopped_progs = 0; 1521 free_pipe(pi, 0); 1522 free(pi); 6398 free_pipe(pi); 1523 6399 } 1524 6400 #endif /* JOB */ 1525 6401 1526 /* Check sto see if any processes have exited -- if they1527 1528 static int checkjobs(struct pipe *fg_pipe)6402 /* Check to see if any processes have exited -- if they 6403 * have, figure out why and see if a job has completed */ 6404 static int checkjobs(struct pipe *fg_pipe) 1529 6405 { 1530 6406 int attributes; 1531 6407 int status; 1532 6408 #if ENABLE_HUSH_JOB 1533 int prognum = 0;1534 6409 struct pipe *pi; 1535 6410 #endif … … 1537 6412 int rcode = 0; 1538 6413 6414 debug_printf_jobs("checkjobs %p\n", fg_pipe); 6415 1539 6416 attributes = WUNTRACED; 1540 if (fg_pipe == NULL) {6417 if (fg_pipe == NULL) 1541 6418 attributes |= WNOHANG; 1542 } 6419 6420 errno = 0; 6421 #if ENABLE_HUSH_FAST 6422 if (G.handled_SIGCHLD == G.count_SIGCHLD) { 6423 //bb_error_msg("[%d] checkjobs: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d children?:%d fg_pipe:%p", 6424 //getpid(), G.count_SIGCHLD, G.handled_SIGCHLD, G.we_have_children, fg_pipe); 6425 /* There was neither fork nor SIGCHLD since last waitpid */ 6426 /* Avoid doing waitpid syscall if possible */ 6427 if (!G.we_have_children) { 6428 errno = ECHILD; 6429 return -1; 6430 } 6431 if (fg_pipe == NULL) { /* is WNOHANG set? */ 6432 /* We have children, but they did not exit 6433 * or stop yet (we saw no SIGCHLD) */ 6434 return 0; 6435 } 6436 /* else: !WNOHANG, waitpid will block, can't short-circuit */ 6437 } 6438 #endif 1543 6439 1544 6440 /* Do we do this right? … … 1548 6444 * bash-3.00# echo $? 1549 6445 * 1 <========== bg pipe is not fully done, but exitcode is already known! 6446 * [hush 1.14.0: yes we do it right] 1550 6447 */ 1551 1552 //FIXME: non-interactive bash does not continue even if all processes in fg pipe1553 //are stopped. Testcase: "cat | cat" in a script (not on command line)1554 // + killall -STOP cat1555 1556 6448 wait_more: 1557 while ((childpid = waitpid(-1, &status, attributes)) > 0) { 1558 const int dead = WIFEXITED(status) || WIFSIGNALED(status); 1559 1560 #ifdef DEBUG_SHELL_JOBS 6449 while (1) { 6450 int i; 6451 int dead; 6452 6453 #if ENABLE_HUSH_FAST 6454 i = G.count_SIGCHLD; 6455 #endif 6456 childpid = waitpid(-1, &status, attributes); 6457 if (childpid <= 0) { 6458 if (childpid && errno != ECHILD) 6459 bb_perror_msg("waitpid"); 6460 #if ENABLE_HUSH_FAST 6461 else { /* Until next SIGCHLD, waitpid's are useless */ 6462 G.we_have_children = (childpid == 0); 6463 G.handled_SIGCHLD = i; 6464 //bb_error_msg("[%d] checkjobs: waitpid returned <= 0, G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD); 6465 } 6466 #endif 6467 break; 6468 } 6469 dead = WIFEXITED(status) || WIFSIGNALED(status); 6470 6471 #if DEBUG_JOBS 1561 6472 if (WIFSTOPPED(status)) 1562 6473 debug_printf_jobs("pid %d stopped by sig %d (exitcode %d)\n", … … 1571 6482 /* Were we asked to wait for fg pipe? */ 1572 6483 if (fg_pipe) { 1573 int i; 1574 for (i = 0; i < fg_pipe->num_progs; i++) { 1575 debug_printf_jobs("check pid %d\n", fg_pipe->progs[i].pid); 1576 if (fg_pipe->progs[i].pid == childpid) { 1577 /* printf("process %d exit %d\n", i, WEXITSTATUS(status)); */ 1578 if (dead) { 1579 fg_pipe->progs[i].pid = 0; 1580 fg_pipe->running_progs--; 1581 if (i == fg_pipe->num_progs-1) 1582 /* last process gives overall exitstatus */ 1583 rcode = WEXITSTATUS(status); 1584 } else { 1585 fg_pipe->progs[i].is_stopped = 1; 1586 fg_pipe->stopped_progs++; 6484 i = fg_pipe->num_cmds; 6485 while (--i >= 0) { 6486 debug_printf_jobs("check pid %d\n", fg_pipe->cmds[i].pid); 6487 if (fg_pipe->cmds[i].pid != childpid) 6488 continue; 6489 if (dead) { 6490 int ex; 6491 fg_pipe->cmds[i].pid = 0; 6492 fg_pipe->alive_cmds--; 6493 ex = WEXITSTATUS(status); 6494 /* bash prints killer signal's name for *last* 6495 * process in pipe (prints just newline for SIGINT). 6496 * Mimic this. Example: "sleep 5" + (^\ or kill -QUIT) 6497 */ 6498 if (WIFSIGNALED(status)) { 6499 int sig = WTERMSIG(status); 6500 if (i == fg_pipe->num_cmds-1) 6501 printf("%s\n", sig == SIGINT ? "" : get_signame(sig)); 6502 /* TODO: MIPS has 128 sigs (1..128), what if sig==128 here? 6503 * Maybe we need to use sig | 128? */ 6504 ex = sig + 128; 1587 6505 } 1588 debug_printf_jobs("fg_pipe: running_progs %d stopped_progs %d\n", 1589 fg_pipe->running_progs, fg_pipe->stopped_progs); 1590 if (fg_pipe->running_progs - fg_pipe->stopped_progs <= 0) { 1591 /* All processes in fg pipe have exited/stopped */ 6506 fg_pipe->cmds[i].cmd_exitcode = ex; 6507 } else { 6508 fg_pipe->cmds[i].is_stopped = 1; 6509 fg_pipe->stopped_cmds++; 6510 } 6511 debug_printf_jobs("fg_pipe: alive_cmds %d stopped_cmds %d\n", 6512 fg_pipe->alive_cmds, fg_pipe->stopped_cmds); 6513 if (fg_pipe->alive_cmds == fg_pipe->stopped_cmds) { 6514 /* All processes in fg pipe have exited or stopped */ 6515 i = fg_pipe->num_cmds; 6516 while (--i >= 0) { 6517 rcode = fg_pipe->cmds[i].cmd_exitcode; 6518 /* usually last process gives overall exitstatus, 6519 * but with "set -o pipefail", last *failed* process does */ 6520 if (G.o_opt[OPT_O_PIPEFAIL] == 0 || rcode != 0) 6521 break; 6522 } 6523 IF_HAS_KEYWORDS(if (fg_pipe->pi_inverted) rcode = !rcode;) 6524 /* Note: *non-interactive* bash does not continue if all processes in fg pipe 6525 * are stopped. Testcase: "cat | cat" in a script (not on command line!) 6526 * and "killall -STOP cat" */ 6527 if (G_interactive_fd) { 1592 6528 #if ENABLE_HUSH_JOB 1593 if (fg_pipe-> running_progs)6529 if (fg_pipe->alive_cmds != 0) 1594 6530 insert_bg_job(fg_pipe); 1595 6531 #endif 1596 6532 return rcode; 1597 6533 } 1598 /* There are still running processes in the fg pipe */1599 goto wait_more;6534 if (fg_pipe->alive_cmds == 0) 6535 return rcode; 1600 6536 } 1601 } 1602 /* fall through to searching process in bg pipes */ 6537 /* There are still running processes in the fg pipe */ 6538 goto wait_more; /* do waitpid again */ 6539 } 6540 /* it wasnt fg_pipe, look for process in bg pipes */ 1603 6541 } 1604 6542 … … 1606 6544 /* We asked to wait for bg or orphaned children */ 1607 6545 /* No need to remember exitcode in this case */ 1608 for (pi = job_list; pi; pi = pi->next) { 1609 prognum = 0; 1610 while (prognum < pi->num_progs) { 1611 if (pi->progs[prognum].pid == childpid) 6546 for (pi = G.job_list; pi; pi = pi->next) { 6547 for (i = 0; i < pi->num_cmds; i++) { 6548 if (pi->cmds[i].pid == childpid) 1612 6549 goto found_pi_and_prognum; 1613 prognum++; 1614 } 1615 } 1616 #endif 1617 6550 } 6551 } 1618 6552 /* Happens when shell is used as init process (init=/bin/sh) */ 1619 6553 debug_printf("checkjobs: pid %d was not in our list!\n", childpid); 1620 goto wait_more; 1621 1622 #if ENABLE_HUSH_JOB 6554 continue; /* do waitpid again */ 6555 1623 6556 found_pi_and_prognum: 1624 6557 if (dead) { 1625 6558 /* child exited */ 1626 pi->progs[prognum].pid = 0; 1627 pi->running_progs--; 1628 if (!pi->running_progs) { 1629 printf(JOB_STATUS_FORMAT, pi->jobid, 6559 pi->cmds[i].pid = 0; 6560 pi->alive_cmds--; 6561 if (!pi->alive_cmds) { 6562 if (G_interactive_fd) 6563 printf(JOB_STATUS_FORMAT, pi->jobid, 1630 6564 "Done", pi->cmdtext); 1631 6565 delete_finished_bg_job(pi); … … 1633 6567 } else { 1634 6568 /* child stopped */ 1635 pi->stopped_progs++; 1636 pi->progs[prognum].is_stopped = 1; 1637 } 1638 #endif 1639 } 1640 1641 /* wait found no children or failed */ 1642 1643 if (childpid && errno != ECHILD) 1644 bb_perror_msg("waitpid"); 6569 pi->cmds[i].is_stopped = 1; 6570 pi->stopped_cmds++; 6571 } 6572 #endif 6573 } /* while (waitpid succeeds)... */ 6574 1645 6575 return rcode; 1646 6576 } 1647 6577 1648 6578 #if ENABLE_HUSH_JOB 1649 static int checkjobs_and_fg_shell(struct pipe *fg_pipe)6579 static int checkjobs_and_fg_shell(struct pipe *fg_pipe) 1650 6580 { 1651 6581 pid_t p; 1652 6582 int rcode = checkjobs(fg_pipe); 1653 /* Job finished, move the shell to the foreground */ 1654 p = getpgid(0); /* pgid of our process */ 1655 debug_printf_jobs("fg'ing ourself: getpgid(0)=%d\n", (int)p); 1656 if (tcsetpgrp(interactive_fd, p) && errno != ENOTTY) 1657 bb_perror_msg("tcsetpgrp-4a"); 6583 if (G_saved_tty_pgrp) { 6584 /* Job finished, move the shell to the foreground */ 6585 p = getpgrp(); /* our process group id */ 6586 debug_printf_jobs("fg'ing ourself: getpgrp()=%d\n", (int)p); 6587 tcsetpgrp(G_interactive_fd, p); 6588 } 1658 6589 return rcode; 1659 6590 } 1660 6591 #endif 1661 6592 1662 /* run_pipe_real() starts all the jobs, but doesn't wait for anything1663 * to finish.See checkjobs().6593 /* Start all the jobs, but don't wait for anything to finish. 6594 * See checkjobs(). 1664 6595 * 1665 * return code is normally -1, when the caller has to wait for children6596 * Return code is normally -1, when the caller has to wait for children 1666 6597 * to finish to determine the exit status of the pipe. If the pipe 1667 6598 * is a simple builtin command, however, the action is done by the 1668 * time run_pipe _realreturns, and the exit code is provided as the6599 * time run_pipe returns, and the exit code is provided as the 1669 6600 * return value. 1670 *1671 * The input of the pipe is always stdin, the output is always1672 * stdout. The outpipe[] mechanism in BusyBox-0.48 lash is bogus,1673 * because it tries to avoid running the command substitution in1674 * subshell, when that is in fact necessary. The subshell process1675 * now has its stdout directed to the input of the appropriate pipe,1676 * so this routine is noticeably simpler.1677 6601 * 1678 6602 * Returns -1 only if started some children. IOW: we have to 1679 6603 * mask out retvals of builtins etc with 0xff! 6604 * 6605 * The only case when we do not need to [v]fork is when the pipe 6606 * is single, non-backgrounded, non-subshell command. Examples: 6607 * cmd ; ... { list } ; ... 6608 * cmd && ... { list } && ... 6609 * cmd || ... { list } || ... 6610 * If it is, then we can run cmd as a builtin, NOFORK [do we do this?], 6611 * or (if SH_STANDALONE) an applet, and we can run the { list } 6612 * with run_list. If it isn't one of these, we fork and exec cmd. 6613 * 6614 * Cases when we must fork: 6615 * non-single: cmd | cmd 6616 * backgrounded: cmd & { list } & 6617 * subshell: ( list ) [&] 1680 6618 */ 1681 static int run_pipe_real(struct pipe *pi) 1682 { 1683 int i; 1684 int nextin, nextout; 1685 int pipefds[2]; /* pipefds[0] is for reading */ 1686 struct child_prog *child; 1687 const struct built_in_command *x; 1688 char *p; 6619 #if !ENABLE_HUSH_MODE_X 6620 #define redirect_and_varexp_helper(new_env_p, old_vars_p, command, squirrel, argv_expanded) \ 6621 redirect_and_varexp_helper(new_env_p, old_vars_p, command, squirrel) 6622 #endif 6623 static int redirect_and_varexp_helper(char ***new_env_p, 6624 struct variable **old_vars_p, 6625 struct command *command, 6626 int squirrel[3], 6627 char **argv_expanded) 6628 { 6629 /* setup_redirects acts on file descriptors, not FILEs. 6630 * This is perfect for work that comes after exec(). 6631 * Is it really safe for inline use? Experimentally, 6632 * things seem to work. */ 6633 int rcode = setup_redirects(command, squirrel); 6634 if (rcode == 0) { 6635 char **new_env = expand_assignments(command->argv, command->assignment_cnt); 6636 *new_env_p = new_env; 6637 dump_cmd_in_x_mode(new_env); 6638 dump_cmd_in_x_mode(argv_expanded); 6639 if (old_vars_p) 6640 *old_vars_p = set_vars_and_save_old(new_env); 6641 } 6642 return rcode; 6643 } 6644 static NOINLINE int run_pipe(struct pipe *pi) 6645 { 6646 static const char *const null_ptr = NULL; 6647 6648 int cmd_no; 6649 int next_infd; 6650 struct command *command; 6651 char **argv_expanded; 6652 char **argv; 1689 6653 /* it is not always needed, but we aim to smaller code */ 1690 6654 int squirrel[] = { -1, -1, -1 }; 1691 6655 int rcode; 1692 const int single_fg = (pi->num_progs == 1 && pi->followup != PIPE_BG); 1693 1694 debug_printf_exec("run_pipe_real start: single_fg=%d\n", single_fg); 1695 1696 nextin = 0; 6656 6657 debug_printf_exec("run_pipe start: members:%d\n", pi->num_cmds); 6658 debug_enter(); 6659 6660 /* Testcase: set -- q w e; (IFS='' echo "$*"; IFS=''; echo "$*"); echo "$*" 6661 * Result should be 3 lines: q w e, qwe, q w e 6662 */ 6663 G.ifs = get_local_var_value("IFS"); 6664 if (!G.ifs) 6665 G.ifs = defifs; 6666 6667 IF_HUSH_JOB(pi->pgrp = -1;) 6668 pi->stopped_cmds = 0; 6669 command = &pi->cmds[0]; 6670 argv_expanded = NULL; 6671 6672 if (pi->num_cmds != 1 6673 || pi->followup == PIPE_BG 6674 || command->cmd_type == CMD_SUBSHELL 6675 ) { 6676 goto must_fork; 6677 } 6678 6679 pi->alive_cmds = 1; 6680 6681 debug_printf_exec(": group:%p argv:'%s'\n", 6682 command->group, command->argv ? command->argv[0] : "NONE"); 6683 6684 if (command->group) { 6685 #if ENABLE_HUSH_FUNCTIONS 6686 if (command->cmd_type == CMD_FUNCDEF) { 6687 /* "executing" func () { list } */ 6688 struct function *funcp; 6689 6690 funcp = new_function(command->argv[0]); 6691 /* funcp->name is already set to argv[0] */ 6692 funcp->body = command->group; 6693 # if !BB_MMU 6694 funcp->body_as_string = command->group_as_string; 6695 command->group_as_string = NULL; 6696 # endif 6697 command->group = NULL; 6698 command->argv[0] = NULL; 6699 debug_printf_exec("cmd %p has child func at %p\n", command, funcp); 6700 funcp->parent_cmd = command; 6701 command->child_func = funcp; 6702 6703 debug_printf_exec("run_pipe: return EXIT_SUCCESS\n"); 6704 debug_leave(); 6705 return EXIT_SUCCESS; 6706 } 6707 #endif 6708 /* { list } */ 6709 debug_printf("non-subshell group\n"); 6710 rcode = 1; /* exitcode if redir failed */ 6711 if (setup_redirects(command, squirrel) == 0) { 6712 debug_printf_exec(": run_list\n"); 6713 rcode = run_list(command->group) & 0xff; 6714 } 6715 restore_redirects(squirrel); 6716 IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;) 6717 debug_leave(); 6718 debug_printf_exec("run_pipe: return %d\n", rcode); 6719 return rcode; 6720 } 6721 6722 argv = command->argv ? command->argv : (char **) &null_ptr; 6723 { 6724 const struct built_in_command *x; 6725 #if ENABLE_HUSH_FUNCTIONS 6726 const struct function *funcp; 6727 #else 6728 enum { funcp = 0 }; 6729 #endif 6730 char **new_env = NULL; 6731 struct variable *old_vars = NULL; 6732 6733 if (argv[command->assignment_cnt] == NULL) { 6734 /* Assignments, but no command */ 6735 /* Ensure redirects take effect (that is, create files). 6736 * Try "a=t >file" */ 6737 #if 0 /* A few cases in testsuite fail with this code. FIXME */ 6738 rcode = redirect_and_varexp_helper(&new_env, /*old_vars:*/ NULL, command, squirrel, /*argv_expanded:*/ NULL); 6739 /* Set shell variables */ 6740 if (new_env) { 6741 argv = new_env; 6742 while (*argv) { 6743 set_local_var(*argv, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0); 6744 /* Do we need to flag set_local_var() errors? 6745 * "assignment to readonly var" and "putenv error" 6746 */ 6747 argv++; 6748 } 6749 } 6750 /* Redirect error sets $? to 1. Otherwise, 6751 * if evaluating assignment value set $?, retain it. 6752 * Try "false; q=`exit 2`; echo $?" - should print 2: */ 6753 if (rcode == 0) 6754 rcode = G.last_exitcode; 6755 /* Exit, _skipping_ variable restoring code: */ 6756 goto clean_up_and_ret0; 6757 6758 #else /* Older, bigger, but more correct code */ 6759 6760 rcode = setup_redirects(command, squirrel); 6761 restore_redirects(squirrel); 6762 /* Set shell variables */ 6763 if (G_x_mode) 6764 bb_putchar_stderr('+'); 6765 while (*argv) { 6766 char *p = expand_string_to_string(*argv, /*unbackslash:*/ 1); 6767 if (G_x_mode) 6768 fprintf(stderr, " %s", p); 6769 debug_printf_exec("set shell var:'%s'->'%s'\n", 6770 *argv, p); 6771 set_local_var(p, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0); 6772 /* Do we need to flag set_local_var() errors? 6773 * "assignment to readonly var" and "putenv error" 6774 */ 6775 argv++; 6776 } 6777 if (G_x_mode) 6778 bb_putchar_stderr('\n'); 6779 /* Redirect error sets $? to 1. Otherwise, 6780 * if evaluating assignment value set $?, retain it. 6781 * Try "false; q=`exit 2`; echo $?" - should print 2: */ 6782 if (rcode == 0) 6783 rcode = G.last_exitcode; 6784 IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;) 6785 debug_leave(); 6786 debug_printf_exec("run_pipe: return %d\n", rcode); 6787 return rcode; 6788 #endif 6789 } 6790 6791 /* Expand the rest into (possibly) many strings each */ 6792 if (0) {} 6793 #if ENABLE_HUSH_BASH_COMPAT 6794 else if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) { 6795 argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt); 6796 } 6797 #endif 6798 else { 6799 argv_expanded = expand_strvec_to_strvec(argv + command->assignment_cnt); 6800 } 6801 6802 /* if someone gives us an empty string: `cmd with empty output` */ 6803 if (!argv_expanded[0]) { 6804 free(argv_expanded); 6805 debug_leave(); 6806 return G.last_exitcode; 6807 } 6808 6809 x = find_builtin(argv_expanded[0]); 6810 #if ENABLE_HUSH_FUNCTIONS 6811 funcp = NULL; 6812 if (!x) 6813 funcp = find_function(argv_expanded[0]); 6814 #endif 6815 if (x || funcp) { 6816 if (!funcp) { 6817 if (x->b_function == builtin_exec && argv_expanded[1] == NULL) { 6818 debug_printf("exec with redirects only\n"); 6819 rcode = setup_redirects(command, NULL); 6820 goto clean_up_and_ret1; 6821 } 6822 } 6823 rcode = redirect_and_varexp_helper(&new_env, &old_vars, command, squirrel, argv_expanded); 6824 if (rcode == 0) { 6825 if (!funcp) { 6826 debug_printf_exec(": builtin '%s' '%s'...\n", 6827 x->b_cmd, argv_expanded[1]); 6828 rcode = x->b_function(argv_expanded) & 0xff; 6829 fflush_all(); 6830 } 6831 #if ENABLE_HUSH_FUNCTIONS 6832 else { 6833 # if ENABLE_HUSH_LOCAL 6834 struct variable **sv; 6835 sv = G.shadowed_vars_pp; 6836 G.shadowed_vars_pp = &old_vars; 6837 # endif 6838 debug_printf_exec(": function '%s' '%s'...\n", 6839 funcp->name, argv_expanded[1]); 6840 rcode = run_function(funcp, argv_expanded) & 0xff; 6841 # if ENABLE_HUSH_LOCAL 6842 G.shadowed_vars_pp = sv; 6843 # endif 6844 } 6845 #endif 6846 } 6847 clean_up_and_ret: 6848 unset_vars(new_env); 6849 add_vars(old_vars); 6850 /* clean_up_and_ret0: */ 6851 restore_redirects(squirrel); 6852 clean_up_and_ret1: 6853 free(argv_expanded); 6854 IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;) 6855 debug_leave(); 6856 debug_printf_exec("run_pipe return %d\n", rcode); 6857 return rcode; 6858 } 6859 6860 if (ENABLE_FEATURE_SH_STANDALONE) { 6861 int n = find_applet_by_name(argv_expanded[0]); 6862 if (n >= 0 && APPLET_IS_NOFORK(n)) { 6863 rcode = redirect_and_varexp_helper(&new_env, &old_vars, command, squirrel, argv_expanded); 6864 if (rcode == 0) { 6865 debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", 6866 argv_expanded[0], argv_expanded[1]); 6867 rcode = run_nofork_applet(n, argv_expanded); 6868 } 6869 goto clean_up_and_ret; 6870 } 6871 } 6872 /* It is neither builtin nor applet. We must fork. */ 6873 } 6874 6875 must_fork: 6876 /* NB: argv_expanded may already be created, and that 6877 * might include `cmd` runs! Do not rerun it! We *must* 6878 * use argv_expanded if it's non-NULL */ 6879 6880 /* Going to fork a child per each pipe member */ 6881 pi->alive_cmds = 0; 6882 next_infd = 0; 6883 6884 cmd_no = 0; 6885 while (cmd_no < pi->num_cmds) { 6886 struct fd_pair pipefds; 6887 #if !BB_MMU 6888 volatile nommu_save_t nommu_save; 6889 nommu_save.new_env = NULL; 6890 nommu_save.old_vars = NULL; 6891 nommu_save.argv = NULL; 6892 nommu_save.argv_from_re_execing = NULL; 6893 #endif 6894 command = &pi->cmds[cmd_no]; 6895 cmd_no++; 6896 if (command->argv) { 6897 debug_printf_exec(": pipe member '%s' '%s'...\n", 6898 command->argv[0], command->argv[1]); 6899 } else { 6900 debug_printf_exec(": pipe member with no argv\n"); 6901 } 6902 6903 /* pipes are inserted between pairs of commands */ 6904 pipefds.rd = 0; 6905 pipefds.wr = 1; 6906 if (cmd_no < pi->num_cmds) 6907 xpiped_pair(pipefds); 6908 6909 command->pid = BB_MMU ? fork() : vfork(); 6910 if (!command->pid) { /* child */ 1697 6911 #if ENABLE_HUSH_JOB 1698 pi->pgrp = -1; 1699 #endif 1700 pi->running_progs = 1; 1701 pi->stopped_progs = 0; 1702 1703 /* Check if this is a simple builtin (not part of a pipe). 1704 * Builtins within pipes have to fork anyway, and are handled in 1705 * pseudo_exec. "echo foo | read bar" doesn't work on bash, either. 1706 */ 1707 child = &(pi->progs[0]); 1708 if (single_fg && child->group && child->subshell == 0) { 1709 debug_printf("non-subshell grouping\n"); 1710 setup_redirects(child, squirrel); 1711 debug_printf_exec(": run_list_real\n"); 1712 rcode = run_list_real(child->group); 1713 restore_redirects(squirrel); 1714 debug_printf_exec("run_pipe_real return %d\n", rcode); 1715 return rcode; // do we need to add '... & 0xff' ? 1716 } 1717 1718 if (single_fg && child->argv != NULL) { 1719 char **argv_expanded; 1720 char **argv = child->argv; 1721 1722 for (i = 0; is_assignment(argv[i]); i++) 1723 continue; 1724 if (i != 0 && argv[i] == NULL) { 1725 /* assignments, but no command: set the local environment */ 1726 for (i = 0; argv[i] != NULL; i++) { 1727 debug_printf("local environment set: %s\n", argv[i]); 1728 p = expand_string_to_string(argv[i]); 1729 set_local_var(p, 0); 1730 } 1731 return EXIT_SUCCESS; /* don't worry about errors in set_local_var() yet */ 1732 } 1733 for (i = 0; is_assignment(argv[i]); i++) { 1734 p = expand_string_to_string(argv[i]); 1735 //sp: child->sp--; 1736 putenv(p); 1737 } 1738 for (x = bltins; x->cmd; x++) { 1739 if (strcmp(argv[i], x->cmd) == 0) { 1740 if (x->function == builtin_exec && argv[i+1] == NULL) { 1741 debug_printf("magic exec\n"); 1742 setup_redirects(child, NULL); 1743 return EXIT_SUCCESS; 1744 } 1745 debug_printf("builtin inline %s\n", argv[0]); 1746 /* XXX setup_redirects acts on file descriptors, not FILEs. 1747 * This is perfect for work that comes after exec(). 1748 * Is it really safe for inline use? Experimentally, 1749 * things seem to work with glibc. */ 1750 setup_redirects(child, squirrel); 1751 debug_printf_exec(": builtin '%s' '%s'...\n", x->cmd, argv[i+1]); 1752 //sp: if (child->sp) /* btw we can do it unconditionally... */ 1753 argv_expanded = expand_strvec_to_strvec(argv + i); 1754 rcode = x->function(argv_expanded) & 0xff; 1755 free(argv_expanded); 1756 restore_redirects(squirrel); 1757 debug_printf_exec("run_pipe_real return %d\n", rcode); 1758 return rcode; 1759 } 1760 } 1761 #if ENABLE_FEATURE_SH_STANDALONE 1762 { 1763 const struct bb_applet *a = find_applet_by_name(argv[i]); 1764 if (a && a->nofork) { 1765 setup_redirects(child, squirrel); 1766 save_nofork_data(&nofork_save); 1767 argv_expanded = argv + i; 1768 //sp: if (child->sp) 1769 argv_expanded = expand_strvec_to_strvec(argv + i); 1770 debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", argv_expanded[0], argv_expanded[1]); 1771 rcode = run_nofork_applet_prime(&nofork_save, a, argv_expanded) & 0xff; 1772 free(argv_expanded); 1773 restore_redirects(squirrel); 1774 debug_printf_exec("run_pipe_real return %d\n", rcode); 1775 return rcode; 1776 } 1777 } 1778 #endif 1779 } 1780 1781 /* Going to fork a child per each pipe member */ 1782 pi->running_progs = 0; 1783 1784 /* Disable job control signals for shell (parent) and 1785 * for initial child code after fork */ 1786 set_jobctrl_sighandler(SIG_IGN); 1787 1788 for (i = 0; i < pi->num_progs; i++) { 1789 child = &(pi->progs[i]); 1790 if (child->argv) 1791 debug_printf_exec(": pipe member '%s' '%s'...\n", child->argv[0], child->argv[1]); 1792 else 1793 debug_printf_exec(": pipe member with no argv\n"); 1794 1795 /* pipes are inserted between pairs of commands */ 1796 if ((i + 1) < pi->num_progs) { 1797 pipe(pipefds); 1798 nextout = pipefds[1]; 1799 } else { 1800 nextout = 1; 1801 pipefds[0] = -1; 1802 } 1803 1804 /* XXX test for failed fork()? */ 1805 #if BB_MMU 1806 child->pid = fork(); 1807 #else 1808 child->pid = vfork(); 1809 #endif 1810 if (!child->pid) { /* child */ 6912 disable_restore_tty_pgrp_on_exit(); 6913 CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */ 6914 1811 6915 /* Every child adds itself to new process group 1812 * with pgid == pid of first child in pipe */ 1813 #if ENABLE_HUSH_JOB 1814 if (run_list_level == 1 && interactive_fd) { 1815 /* Don't do pgrp restore anymore on fatal signals */ 1816 set_fatal_sighandler(SIG_DFL); 1817 if (pi->pgrp < 0) /* true for 1st process only */ 1818 pi->pgrp = getpid(); 1819 if (setpgid(0, pi->pgrp) == 0 && pi->followup != PIPE_BG) { 6916 * with pgid == pid_of_first_child_in_pipe */ 6917 if (G.run_list_level == 1 && G_interactive_fd) { 6918 pid_t pgrp; 6919 pgrp = pi->pgrp; 6920 if (pgrp < 0) /* true for 1st process only */ 6921 pgrp = getpid(); 6922 if (setpgid(0, pgrp) == 0 6923 && pi->followup != PIPE_BG 6924 && G_saved_tty_pgrp /* we have ctty */ 6925 ) { 1820 6926 /* We do it in *every* child, not just first, 1821 6927 * to avoid races */ 1822 tcsetpgrp( interactive_fd, pi->pgrp);6928 tcsetpgrp(G_interactive_fd, pgrp); 1823 6929 } 1824 6930 } 1825 6931 #endif 1826 /* in non-interactive case fatal sigs are already SIG_DFL */ 1827 close_all(); 1828 if (nextin != 0) { 1829 dup2(nextin, 0); 1830 close(nextin); 1831 } 1832 if (nextout != 1) { 1833 dup2(nextout, 1); 1834 close(nextout); 1835 } 1836 if (pipefds[0] != -1) { 1837 close(pipefds[0]); /* opposite end of our output pipe */ 1838 } 6932 if (pi->alive_cmds == 0 && pi->followup == PIPE_BG) { 6933 /* 1st cmd in backgrounded pipe 6934 * should have its stdin /dev/null'ed */ 6935 close(0); 6936 if (open(bb_dev_null, O_RDONLY)) 6937 xopen("/", O_RDONLY); 6938 } else { 6939 xmove_fd(next_infd, 0); 6940 } 6941 xmove_fd(pipefds.wr, 1); 6942 if (pipefds.rd > 1) 6943 close(pipefds.rd); 1839 6944 /* Like bash, explicit redirects override pipes, 1840 6945 * and the pipe fd is available for dup'ing. */ 1841 setup_redirects(child, NULL); 6946 if (setup_redirects(command, NULL)) 6947 _exit(1); 1842 6948 1843 6949 /* Restore default handlers just prior to exec */ 1844 set_jobctrl_sighandler(SIG_DFL); 1845 set_misc_sighandler(SIG_DFL); 1846 signal(SIGCHLD, SIG_DFL); 1847 pseudo_exec(child); 1848 } 1849 1850 pi->running_progs++; 1851 6950 /*signal(SIGCHLD, SIG_DFL); - so far we don't have any handlers */ 6951 6952 /* Stores to nommu_save list of env vars putenv'ed 6953 * (NOMMU, on MMU we don't need that) */ 6954 /* cast away volatility... */ 6955 pseudo_exec((nommu_save_t*) &nommu_save, command, argv_expanded); 6956 /* pseudo_exec() does not return */ 6957 } 6958 6959 /* parent or error */ 6960 #if ENABLE_HUSH_FAST 6961 G.count_SIGCHLD++; 6962 //bb_error_msg("[%d] fork in run_pipe: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD); 6963 #endif 6964 enable_restore_tty_pgrp_on_exit(); 6965 #if !BB_MMU 6966 /* Clean up after vforked child */ 6967 free(nommu_save.argv); 6968 free(nommu_save.argv_from_re_execing); 6969 unset_vars(nommu_save.new_env); 6970 add_vars(nommu_save.old_vars); 6971 #endif 6972 free(argv_expanded); 6973 argv_expanded = NULL; 6974 if (command->pid < 0) { /* [v]fork failed */ 6975 /* Clearly indicate, was it fork or vfork */ 6976 bb_perror_msg(BB_MMU ? "vfork"+1 : "vfork"); 6977 } else { 6978 pi->alive_cmds++; 1852 6979 #if ENABLE_HUSH_JOB 1853 /* Second and next children need to know pid of first one */ 1854 if (pi->pgrp < 0) 1855 pi->pgrp = child->pid; 1856 #endif 1857 if (nextin != 0) 1858 close(nextin); 1859 if (nextout != 1) 1860 close(nextout); 1861 1862 /* If there isn't another process, nextin is garbage 1863 but it doesn't matter */ 1864 nextin = pipefds[0]; 1865 } 1866 debug_printf_exec("run_pipe_real return -1\n"); 6980 /* Second and next children need to know pid of first one */ 6981 if (pi->pgrp < 0) 6982 pi->pgrp = command->pid; 6983 #endif 6984 } 6985 6986 if (cmd_no > 1) 6987 close(next_infd); 6988 if (cmd_no < pi->num_cmds) 6989 close(pipefds.wr); 6990 /* Pass read (output) pipe end to next iteration */ 6991 next_infd = pipefds.rd; 6992 } 6993 6994 if (!pi->alive_cmds) { 6995 debug_leave(); 6996 debug_printf_exec("run_pipe return 1 (all forks failed, no children)\n"); 6997 return 1; 6998 } 6999 7000 debug_leave(); 7001 debug_printf_exec("run_pipe return -1 (%u children started)\n", pi->alive_cmds); 1867 7002 return -1; 1868 7003 } 1869 1870 #ifndef debug_print_tree1871 static void debug_print_tree(struct pipe *pi, int lvl)1872 {1873 static const char *PIPE[] = {1874 [PIPE_SEQ] = "SEQ",1875 [PIPE_AND] = "AND",1876 [PIPE_OR ] = "OR" ,1877 [PIPE_BG ] = "BG" ,1878 };1879 static const char *RES[] = {1880 [RES_NONE ] = "NONE" ,1881 #if ENABLE_HUSH_IF1882 [RES_IF ] = "IF" ,1883 [RES_THEN ] = "THEN" ,1884 [RES_ELIF ] = "ELIF" ,1885 [RES_ELSE ] = "ELSE" ,1886 [RES_FI ] = "FI" ,1887 #endif1888 #if ENABLE_HUSH_LOOPS1889 [RES_FOR ] = "FOR" ,1890 [RES_WHILE] = "WHILE",1891 [RES_UNTIL] = "UNTIL",1892 [RES_DO ] = "DO" ,1893 [RES_DONE ] = "DONE" ,1894 [RES_IN ] = "IN" ,1895 #endif1896 [RES_XXXX ] = "XXXX" ,1897 [RES_SNTX ] = "SNTX" ,1898 };1899 1900 int pin, prn;1901 1902 pin = 0;1903 while (pi) {1904 fprintf(stderr, "%*spipe %d res_word=%s followup=%d %s\n", lvl*2, "",1905 pin, RES[pi->res_word], pi->followup, PIPE[pi->followup]);1906 prn = 0;1907 while (prn < pi->num_progs) {1908 struct child_prog *child = &pi->progs[prn];1909 char **argv = child->argv;1910 1911 fprintf(stderr, "%*s prog %d", lvl*2, "", prn);1912 if (child->group) {1913 fprintf(stderr, " group %s: (argv=%p)\n",1914 (child->subshell ? "()" : "{}"),1915 argv);1916 debug_print_tree(child->group, lvl+1);1917 prn++;1918 continue;1919 }1920 if (argv) while (*argv) {1921 fprintf(stderr, " '%s'", *argv);1922 argv++;1923 }1924 fprintf(stderr, "\n");1925 prn++;1926 }1927 pi = pi->next;1928 pin++;1929 }1930 }1931 #endif1932 7004 1933 7005 /* NB: called by pseudo_exec, and therefore must not modify any 1934 7006 * global data until exec/_exit (we can be a child after vfork!) */ 1935 static int run_list_real(struct pipe *pi) 1936 { 1937 struct pipe *rpipe; 7007 static int run_list(struct pipe *pi) 7008 { 7009 #if ENABLE_HUSH_CASE 7010 char *case_word = NULL; 7011 #endif 1938 7012 #if ENABLE_HUSH_LOOPS 1939 char *for_varname= NULL;7013 struct pipe *loop_top = NULL; 1940 7014 char **for_lcur = NULL; 1941 7015 char **for_list = NULL; 1942 int flag_rep = 0; 1943 #endif 1944 int save_num_progs; 1945 int flag_skip = 1; 1946 int rcode = 0; /* probably for gcc only */ 1947 int flag_restore = 0; 7016 #endif 7017 smallint last_followup; 7018 smalluint rcode; 7019 #if ENABLE_HUSH_IF || ENABLE_HUSH_CASE 7020 smalluint cond_code = 0; 7021 #else 7022 enum { cond_code = 0 }; 7023 #endif 7024 #if HAS_KEYWORDS 7025 smallint rword; /* RES_foo */ 7026 smallint last_rword; /* ditto */ 7027 #endif 7028 7029 debug_printf_exec("run_list start lvl %d\n", G.run_list_level); 7030 debug_enter(); 7031 7032 #if ENABLE_HUSH_LOOPS 7033 /* Check syntax for "for" */ 7034 { 7035 struct pipe *cpipe; 7036 for (cpipe = pi; cpipe; cpipe = cpipe->next) { 7037 if (cpipe->res_word != RES_FOR && cpipe->res_word != RES_IN) 7038 continue; 7039 /* current word is FOR or IN (BOLD in comments below) */ 7040 if (cpipe->next == NULL) { 7041 syntax_error("malformed for"); 7042 debug_leave(); 7043 debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level); 7044 return 1; 7045 } 7046 /* "FOR v; do ..." and "for v IN a b; do..." are ok */ 7047 if (cpipe->next->res_word == RES_DO) 7048 continue; 7049 /* next word is not "do". It must be "in" then ("FOR v in ...") */ 7050 if (cpipe->res_word == RES_IN /* "for v IN a b; not_do..."? */ 7051 || cpipe->next->res_word != RES_IN /* FOR v not_do_and_not_in..."? */ 7052 ) { 7053 syntax_error("malformed for"); 7054 debug_leave(); 7055 debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level); 7056 return 1; 7057 } 7058 } 7059 } 7060 #endif 7061 7062 /* Past this point, all code paths should jump to ret: label 7063 * in order to return, no direct "return" statements please. 7064 * This helps to ensure that no memory is leaked. */ 7065 7066 #if ENABLE_HUSH_JOB 7067 G.run_list_level++; 7068 #endif 7069 7070 #if HAS_KEYWORDS 7071 rword = RES_NONE; 7072 last_rword = RES_XXXX; 7073 #endif 7074 last_followup = PIPE_SEQ; 7075 rcode = G.last_exitcode; 7076 7077 /* Go through list of pipes, (maybe) executing them. */ 7078 for (; pi; pi = IF_HUSH_LOOPS(rword == RES_DONE ? loop_top : ) pi->next) { 7079 if (G.flag_SIGINT) 7080 break; 7081 7082 IF_HAS_KEYWORDS(rword = pi->res_word;) 7083 debug_printf_exec(": rword=%d cond_code=%d last_rword=%d\n", 7084 rword, cond_code, last_rword); 7085 #if ENABLE_HUSH_LOOPS 7086 if ((rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR) 7087 && loop_top == NULL /* avoid bumping G.depth_of_loop twice */ 7088 ) { 7089 /* start of a loop: remember where loop starts */ 7090 loop_top = pi; 7091 G.depth_of_loop++; 7092 } 7093 #endif 7094 /* Still in the same "if...", "then..." or "do..." branch? */ 7095 if (IF_HAS_KEYWORDS(rword == last_rword &&) 1) { 7096 if ((rcode == 0 && last_followup == PIPE_OR) 7097 || (rcode != 0 && last_followup == PIPE_AND) 7098 ) { 7099 /* It is "<true> || CMD" or "<false> && CMD" 7100 * and we should not execute CMD */ 7101 debug_printf_exec("skipped cmd because of || or &&\n"); 7102 last_followup = pi->followup; 7103 continue; 7104 } 7105 } 7106 last_followup = pi->followup; 7107 IF_HAS_KEYWORDS(last_rword = rword;) 1948 7108 #if ENABLE_HUSH_IF 1949 int if_code = 0, next_if_code = 0; /* need double-buffer to handle elif */ 1950 #else 1951 enum { if_code = 0, next_if_code = 0 }; 1952 #endif 1953 reserved_style rword; 1954 reserved_style skip_more_for_this_rword = RES_XXXX; 1955 1956 debug_printf_exec("run_list_real start lvl %d\n", run_list_level + 1); 1957 7109 if (cond_code) { 7110 if (rword == RES_THEN) { 7111 /* if false; then ... fi has exitcode 0! */ 7112 G.last_exitcode = rcode = EXIT_SUCCESS; 7113 /* "if <false> THEN cmd": skip cmd */ 7114 continue; 7115 } 7116 } else { 7117 if (rword == RES_ELSE || rword == RES_ELIF) { 7118 /* "if <true> then ... ELSE/ELIF cmd": 7119 * skip cmd and all following ones */ 7120 break; 7121 } 7122 } 7123 #endif 1958 7124 #if ENABLE_HUSH_LOOPS 1959 /* check syntax for "for" */ 1960 for (rpipe = pi; rpipe; rpipe = rpipe->next) { 1961 if ((rpipe->res_word == RES_IN || rpipe->res_word == RES_FOR) 1962 && (rpipe->next == NULL) 1963 ) { 1964 syntax("malformed for"); /* no IN or no commands after IN */ 1965 debug_printf_exec("run_list_real lvl %d return 1\n", run_list_level); 1966 return 1; 1967 } 1968 if ((rpipe->res_word == RES_IN && rpipe->next->res_word == RES_IN && rpipe->next->progs[0].argv != NULL) 1969 || (rpipe->res_word == RES_FOR && rpipe->next->res_word != RES_IN) 1970 ) { 1971 /* TODO: what is tested in the first condition? */ 1972 syntax("malformed for"); /* 2nd condition: not followed by IN */ 1973 debug_printf_exec("run_list_real lvl %d return 1\n", run_list_level); 1974 return 1; 1975 } 1976 } 1977 #else 1978 rpipe = NULL; 1979 #endif 1980 7125 if (rword == RES_FOR) { /* && pi->num_cmds - always == 1 */ 7126 if (!for_lcur) { 7127 /* first loop through for */ 7128 7129 static const char encoded_dollar_at[] ALIGN1 = { 7130 SPECIAL_VAR_SYMBOL, '@' | 0x80, SPECIAL_VAR_SYMBOL, '\0' 7131 }; /* encoded representation of "$@" */ 7132 static const char *const encoded_dollar_at_argv[] = { 7133 encoded_dollar_at, NULL 7134 }; /* argv list with one element: "$@" */ 7135 char **vals; 7136 7137 vals = (char**)encoded_dollar_at_argv; 7138 if (pi->next->res_word == RES_IN) { 7139 /* if no variable values after "in" we skip "for" */ 7140 if (!pi->next->cmds[0].argv) { 7141 G.last_exitcode = rcode = EXIT_SUCCESS; 7142 debug_printf_exec(": null FOR: exitcode EXIT_SUCCESS\n"); 7143 break; 7144 } 7145 vals = pi->next->cmds[0].argv; 7146 } /* else: "for var; do..." -> assume "$@" list */ 7147 /* create list of variable values */ 7148 debug_print_strings("for_list made from", vals); 7149 for_list = expand_strvec_to_strvec(vals); 7150 for_lcur = for_list; 7151 debug_print_strings("for_list", for_list); 7152 } 7153 if (!*for_lcur) { 7154 /* "for" loop is over, clean up */ 7155 free(for_list); 7156 for_list = NULL; 7157 for_lcur = NULL; 7158 break; 7159 } 7160 /* Insert next value from for_lcur */ 7161 /* note: *for_lcur already has quotes removed, $var expanded, etc */ 7162 set_local_var(xasprintf("%s=%s", pi->cmds[0].argv[0], *for_lcur++), /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0); 7163 continue; 7164 } 7165 if (rword == RES_IN) { 7166 continue; /* "for v IN list;..." - "in" has no cmds anyway */ 7167 } 7168 if (rword == RES_DONE) { 7169 continue; /* "done" has no cmds too */ 7170 } 7171 #endif 7172 #if ENABLE_HUSH_CASE 7173 if (rword == RES_CASE) { 7174 case_word = expand_strvec_to_string(pi->cmds->argv); 7175 continue; 7176 } 7177 if (rword == RES_MATCH) { 7178 char **argv; 7179 7180 if (!case_word) /* "case ... matched_word) ... WORD)": we executed selected branch, stop */ 7181 break; 7182 /* all prev words didn't match, does this one match? */ 7183 argv = pi->cmds->argv; 7184 while (*argv) { 7185 char *pattern = expand_string_to_string(*argv, /*unbackslash:*/ 1); 7186 /* TODO: which FNM_xxx flags to use? */ 7187 cond_code = (fnmatch(pattern, case_word, /*flags:*/ 0) != 0); 7188 free(pattern); 7189 if (cond_code == 0) { /* match! we will execute this branch */ 7190 free(case_word); /* make future "word)" stop */ 7191 case_word = NULL; 7192 break; 7193 } 7194 argv++; 7195 } 7196 continue; 7197 } 7198 if (rword == RES_CASE_BODY) { /* inside of a case branch */ 7199 if (cond_code != 0) 7200 continue; /* not matched yet, skip this pipe */ 7201 } 7202 #endif 7203 /* Just pressing <enter> in shell should check for jobs. 7204 * OTOH, in non-interactive shell this is useless 7205 * and only leads to extra job checks */ 7206 if (pi->num_cmds == 0) { 7207 if (G_interactive_fd) 7208 goto check_jobs_and_continue; 7209 continue; 7210 } 7211 7212 /* After analyzing all keywords and conditions, we decided 7213 * to execute this pipe. NB: have to do checkjobs(NULL) 7214 * after run_pipe to collect any background children, 7215 * even if list execution is to be stopped. */ 7216 debug_printf_exec(": run_pipe with %d members\n", pi->num_cmds); 7217 { 7218 int r; 7219 #if ENABLE_HUSH_LOOPS 7220 G.flag_break_continue = 0; 7221 #endif 7222 rcode = r = run_pipe(pi); /* NB: rcode is a smallint */ 7223 if (r != -1) { 7224 /* We ran a builtin, function, or group. 7225 * rcode is already known 7226 * and we don't need to wait for anything. */ 7227 G.last_exitcode = rcode; 7228 debug_printf_exec(": builtin/func exitcode %d\n", rcode); 7229 check_and_run_traps(0); 7230 #if ENABLE_HUSH_LOOPS 7231 /* Was it "break" or "continue"? */ 7232 if (G.flag_break_continue) { 7233 smallint fbc = G.flag_break_continue; 7234 /* We might fall into outer *loop*, 7235 * don't want to break it too */ 7236 if (loop_top) { 7237 G.depth_break_continue--; 7238 if (G.depth_break_continue == 0) 7239 G.flag_break_continue = 0; 7240 /* else: e.g. "continue 2" should *break* once, *then* continue */ 7241 } /* else: "while... do... { we are here (innermost list is not a loop!) };...done" */ 7242 if (G.depth_break_continue != 0 || fbc == BC_BREAK) 7243 goto check_jobs_and_break; 7244 /* "continue": simulate end of loop */ 7245 rword = RES_DONE; 7246 continue; 7247 } 7248 #endif 7249 #if ENABLE_HUSH_FUNCTIONS 7250 if (G.flag_return_in_progress == 1) { 7251 /* same as "goto check_jobs_and_break" */ 7252 checkjobs(NULL); 7253 break; 7254 } 7255 #endif 7256 } else if (pi->followup == PIPE_BG) { 7257 /* What does bash do with attempts to background builtins? */ 7258 /* even bash 3.2 doesn't do that well with nested bg: 7259 * try "{ { sleep 10; echo DEEP; } & echo HERE; } &". 7260 * I'm NOT treating inner &'s as jobs */ 7261 check_and_run_traps(0); 1981 7262 #if ENABLE_HUSH_JOB 1982 /* Example of nested list: "while true; do { sleep 1 | exit 2; } done". 1983 * We are saving state before entering outermost list ("while...done") 1984 * so that ctrl-Z will correctly background _entire_ outermost list, 1985 * not just a part of it (like "sleep 1 | exit 2") */ 1986 if (++run_list_level == 1 && interactive_fd) { 1987 if (sigsetjmp(toplevel_jb, 1)) { 1988 /* ctrl-Z forked and we are parent; or ctrl-C. 1989 * Sighandler has longjmped us here */ 1990 signal(SIGINT, SIG_IGN); 1991 signal(SIGTSTP, SIG_IGN); 1992 /* Restore level (we can be coming from deep inside 1993 * nested levels) */ 1994 run_list_level = 1; 1995 #if ENABLE_FEATURE_SH_STANDALONE 1996 if (nofork_save.saved) { /* if save area is valid */ 1997 debug_printf_jobs("exiting nofork early\n"); 1998 restore_nofork_data(&nofork_save); 1999 } 2000 #endif 2001 if (ctrl_z_flag) { 2002 /* ctrl-Z has forked and stored pid of the child in pi->pid. 2003 * Remember this child as background job */ 2004 insert_bg_job(pi); 7263 if (G.run_list_level == 1) 7264 insert_bg_job(pi); 7265 #endif 7266 /* Last command's pid goes to $! */ 7267 G.last_bg_pid = pi->cmds[pi->num_cmds - 1].pid; 7268 G.last_exitcode = rcode = EXIT_SUCCESS; 7269 debug_printf_exec(": cmd&: exitcode EXIT_SUCCESS\n"); 2005 7270 } else { 2006 /* ctrl-C. We just stop doing whatever we were doing */2007 putchar('\n');2008 }2009 rcode = 0;2010 goto ret;2011 }2012 /* ctrl-Z handler will store pid etc in pi */2013 toplevel_list = pi;2014 ctrl_z_flag = 0;2015 #if ENABLE_FEATURE_SH_STANDALONE2016 nofork_save.saved = 0; /* in case we will run a nofork later */2017 #endif2018 signal_SA_RESTART(SIGTSTP, handler_ctrl_z);2019 signal(SIGINT, handler_ctrl_c);2020 }2021 #endif2022 2023 for (; pi; pi = flag_restore ? rpipe : pi->next) {2024 rword = pi->res_word;2025 #if ENABLE_HUSH_LOOPS2026 if (rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR) {2027 flag_restore = 0;2028 if (!rpipe) {2029 flag_rep = 0;2030 rpipe = pi;2031 }2032 }2033 #endif2034 debug_printf_exec(": rword=%d if_code=%d next_if_code=%d skip_more=%d\n",2035 rword, if_code, next_if_code, skip_more_for_this_rword);2036 if (rword == skip_more_for_this_rword && flag_skip) {2037 if (pi->followup == PIPE_SEQ)2038 flag_skip = 0;2039 continue;2040 }2041 flag_skip = 1;2042 skip_more_for_this_rword = RES_XXXX;2043 #if ENABLE_HUSH_IF2044 if (rword == RES_THEN || rword == RES_ELSE)2045 if_code = next_if_code;2046 if (rword == RES_THEN && if_code)2047 continue;2048 if (rword == RES_ELSE && !if_code)2049 continue;2050 if (rword == RES_ELIF && !if_code)2051 break;2052 #endif2053 #if ENABLE_HUSH_LOOPS2054 if (rword == RES_FOR && pi->num_progs) {2055 if (!for_lcur) {2056 /* if no variable values after "in" we skip "for" */2057 if (!pi->next->progs->argv)2058 continue;2059 /* create list of variable values */2060 for_list = expand_strvec_to_strvec(pi->next->progs->argv);2061 for_lcur = for_list;2062 for_varname = pi->progs->argv[0];2063 pi->progs->argv[0] = NULL;2064 flag_rep = 1;2065 }2066 free(pi->progs->argv[0]);2067 if (!*for_lcur) {2068 free(for_list);2069 for_lcur = NULL;2070 flag_rep = 0;2071 pi->progs->argv[0] = for_varname;2072 pi->progs->glob_result.gl_pathv[0] = pi->progs->argv[0];2073 continue;2074 }2075 /* insert next value from for_lcur */2076 /* vda: does it need escaping? */2077 pi->progs->argv[0] = xasprintf("%s=%s", for_varname, *for_lcur++);2078 pi->progs->glob_result.gl_pathv[0] = pi->progs->argv[0];2079 }2080 if (rword == RES_IN)2081 continue;2082 if (rword == RES_DO) {2083 if (!flag_rep)2084 continue;2085 }2086 if (rword == RES_DONE) {2087 if (flag_rep) {2088 flag_restore = 1;2089 } else {2090 rpipe = NULL;2091 }2092 }2093 #endif2094 if (pi->num_progs == 0)2095 continue;2096 save_num_progs = pi->num_progs; /* save number of programs */2097 debug_printf_exec(": run_pipe_real with %d members\n", pi->num_progs);2098 rcode = run_pipe_real(pi);2099 if (rcode != -1) {2100 /* We only ran a builtin: rcode was set by the return value2101 * of run_pipe_real(), and we don't need to wait for anything. */2102 } else if (pi->followup == PIPE_BG) {2103 /* What does bash do with attempts to background builtins? */2104 /* Even bash 3.2 doesn't do that well with nested bg:2105 * try "{ { sleep 10; echo DEEP; } & echo HERE; } &".2106 * I'm NOT treating inner &'s as jobs */2107 7271 #if ENABLE_HUSH_JOB 2108 if (run_list_level == 1) 2109 insert_bg_job(pi); 2110 #endif 2111 rcode = EXIT_SUCCESS; 2112 } else { 2113 #if ENABLE_HUSH_JOB 2114 /* Paranoia, just "interactive_fd" should be enough? */ 2115 if (run_list_level == 1 && interactive_fd) { 2116 /* waits for completion, then fg's main shell */ 2117 rcode = checkjobs_and_fg_shell(pi); 2118 } else 2119 #endif 2120 { 2121 /* this one just waits for completion */ 2122 rcode = checkjobs(pi); 2123 } 2124 debug_printf_exec(": checkjobs returned %d\n", rcode); 2125 } 2126 debug_printf_exec(": setting last_return_code=%d\n", rcode); 2127 last_return_code = rcode; 2128 pi->num_progs = save_num_progs; /* restore number of programs */ 7272 if (G.run_list_level == 1 && G_interactive_fd) { 7273 /* Waits for completion, then fg's main shell */ 7274 rcode = checkjobs_and_fg_shell(pi); 7275 debug_printf_exec(": checkjobs_and_fg_shell exitcode %d\n", rcode); 7276 check_and_run_traps(0); 7277 } else 7278 #endif 7279 { /* This one just waits for completion */ 7280 rcode = checkjobs(pi); 7281 debug_printf_exec(": checkjobs exitcode %d\n", rcode); 7282 check_and_run_traps(0); 7283 } 7284 G.last_exitcode = rcode; 7285 } 7286 } 7287 7288 /* Analyze how result affects subsequent commands */ 2129 7289 #if ENABLE_HUSH_IF 2130 7290 if (rword == RES_IF || rword == RES_ELIF) 2131 next_if_code = rcode; /* can be overwritten a number of times */7291 cond_code = rcode; 2132 7292 #endif 2133 7293 #if ENABLE_HUSH_LOOPS 2134 if (rword == RES_WHILE) 2135 flag_rep = !last_return_code; 2136 if (rword == RES_UNTIL) 2137 flag_rep = last_return_code; 2138 #endif 2139 if ((rcode == EXIT_SUCCESS && pi->followup == PIPE_OR) 2140 || (rcode != EXIT_SUCCESS && pi->followup == PIPE_AND) 2141 ) { 2142 skip_more_for_this_rword = rword; 2143 } 7294 /* Beware of "while false; true; do ..."! */ 7295 if (pi->next && pi->next->res_word == RES_DO) { 7296 if (rword == RES_WHILE) { 7297 if (rcode) { 7298 /* "while false; do...done" - exitcode 0 */ 7299 G.last_exitcode = rcode = EXIT_SUCCESS; 7300 debug_printf_exec(": while expr is false: breaking (exitcode:EXIT_SUCCESS)\n"); 7301 goto check_jobs_and_break; 7302 } 7303 } 7304 if (rword == RES_UNTIL) { 7305 if (!rcode) { 7306 debug_printf_exec(": until expr is true: breaking\n"); 7307 check_jobs_and_break: 7308 checkjobs(NULL); 7309 break; 7310 } 7311 } 7312 } 7313 #endif 7314 7315 check_jobs_and_continue: 2144 7316 checkjobs(NULL); 2145 } 7317 } /* for (pi) */ 2146 7318 2147 7319 #if ENABLE_HUSH_JOB 2148 if (ctrl_z_flag) {2149 /* ctrl-Z forked somewhere in the past, we are the child, 2150 * and now we completed running the list. Exit. */ 2151 exit(rcode);2152 }2153 ret: 2154 if (!--run_list_level && interactive_fd) { 2155 signal(SIGTSTP, SIG_IGN); 2156 signal(SIGINT, SIG_IGN);2157 } 2158 #endif 2159 debug_printf_exec("run_list _real lvl %d return %d\n",run_list_level + 1, rcode);7320 G.run_list_level--; 7321 #endif 7322 #if ENABLE_HUSH_LOOPS 7323 if (loop_top) 7324 G.depth_of_loop--; 7325 free(for_list); 7326 #endif 7327 #if ENABLE_HUSH_CASE 7328 free(case_word); 7329 #endif 7330 debug_leave(); 7331 debug_printf_exec("run_list lvl %d return %d\n", G.run_list_level + 1, rcode); 2160 7332 return rcode; 2161 7333 } 2162 7334 2163 /* return code is the exit status of the pipe */ 2164 static int free_pipe(struct pipe *pi, int indent) 2165 { 2166 char **p; 2167 struct child_prog *child; 2168 struct redir_struct *r, *rnext; 2169 int a, i, ret_code = 0; 2170 2171 if (pi->stopped_progs > 0) 2172 return ret_code; 2173 debug_printf_clean("%s run pipe: (pid %d)\n", indenter(indent), getpid()); 2174 for (i = 0; i < pi->num_progs; i++) { 2175 child = &pi->progs[i]; 2176 debug_printf_clean("%s command %d:\n", indenter(indent), i); 2177 if (child->argv) { 2178 for (a = 0, p = child->argv; *p; a++, p++) { 2179 debug_printf_clean("%s argv[%d] = %s\n", indenter(indent), a, *p); 2180 } 2181 globfree(&child->glob_result); 2182 child->argv = NULL; 2183 } else if (child->group) { 2184 debug_printf_clean("%s begin group (subshell:%d)\n", indenter(indent), child->subshell); 2185 ret_code = free_pipe_list(child->group, indent+3); 2186 debug_printf_clean("%s end group\n", indenter(indent)); 2187 } else { 2188 debug_printf_clean("%s (nil)\n", indenter(indent)); 2189 } 2190 for (r = child->redirects; r; r = rnext) { 2191 debug_printf_clean("%s redirect %d%s", indenter(indent), r->fd, redir_table[r->type].descrip); 2192 if (r->dup == -1) { 2193 /* guard against the case >$FOO, where foo is unset or blank */ 2194 if (r->word.gl_pathv) { 2195 debug_printf_clean(" %s\n", *r->word.gl_pathv); 2196 globfree(&r->word); 2197 } 2198 } else { 2199 debug_printf_clean("&%d\n", r->dup); 2200 } 2201 rnext = r->next; 2202 free(r); 2203 } 2204 child->redirects = NULL; 2205 } 2206 free(pi->progs); /* children are an array, they get freed all at once */ 2207 pi->progs = NULL; 7335 /* Select which version we will use */ 7336 static int run_and_free_list(struct pipe *pi) 7337 { 7338 int rcode = 0; 7339 debug_printf_exec("run_and_free_list entered\n"); 7340 if (!G.n_mode) { 7341 debug_printf_exec(": run_list: 1st pipe with %d cmds\n", pi->num_cmds); 7342 rcode = run_list(pi); 7343 } 7344 /* free_pipe_list has the side effect of clearing memory. 7345 * In the long run that function can be merged with run_list, 7346 * but doing that now would hobble the debugging effort. */ 7347 free_pipe_list(pi); 7348 debug_printf_exec("run_and_free_list return %d\n", rcode); 7349 return rcode; 7350 } 7351 7352 7353 /* Called a few times only (or even once if "sh -c") */ 7354 static void init_sigmasks(void) 7355 { 7356 unsigned sig; 7357 unsigned mask; 7358 sigset_t old_blocked_set; 7359 7360 if (!G.inherited_set_is_saved) { 7361 sigprocmask(SIG_SETMASK, NULL, &G.blocked_set); 7362 G.inherited_set = G.blocked_set; 7363 } 7364 old_blocked_set = G.blocked_set; 7365 7366 mask = (1 << SIGQUIT); 7367 if (G_interactive_fd) { 7368 mask = (1 << SIGQUIT) | SPECIAL_INTERACTIVE_SIGS; 7369 if (G_saved_tty_pgrp) /* we have ctty, job control sigs work */ 7370 mask |= SPECIAL_JOB_SIGS; 7371 } 7372 G.non_DFL_mask = mask; 7373 7374 sig = 0; 7375 while (mask) { 7376 if (mask & 1) 7377 sigaddset(&G.blocked_set, sig); 7378 mask >>= 1; 7379 sig++; 7380 } 7381 sigdelset(&G.blocked_set, SIGCHLD); 7382 7383 if (memcmp(&old_blocked_set, &G.blocked_set, sizeof(old_blocked_set)) != 0) 7384 sigprocmask(SIG_SETMASK, &G.blocked_set, NULL); 7385 7386 /* POSIX allows shell to re-enable SIGCHLD 7387 * even if it was SIG_IGN on entry */ 7388 #if ENABLE_HUSH_FAST 7389 G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */ 7390 if (!G.inherited_set_is_saved) 7391 signal(SIGCHLD, SIGCHLD_handler); 7392 #else 7393 if (!G.inherited_set_is_saved) 7394 signal(SIGCHLD, SIG_DFL); 7395 #endif 7396 7397 G.inherited_set_is_saved = 1; 7398 } 7399 2208 7400 #if ENABLE_HUSH_JOB 2209 free(pi->cmdtext); 2210 pi->cmdtext = NULL; 2211 #endif 2212 return ret_code; 2213 } 2214 2215 static int free_pipe_list(struct pipe *head, int indent) 2216 { 2217 int rcode = 0; /* if list has no members */ 2218 struct pipe *pi, *next; 2219 2220 for (pi = head; pi; pi = next) { 2221 debug_printf_clean("%s pipe reserved mode %d\n", indenter(indent), pi->res_word); 2222 rcode = free_pipe(pi, indent); 2223 debug_printf_clean("%s pipe followup code %d\n", indenter(indent), pi->followup); 2224 next = pi->next; 2225 /*pi->next = NULL;*/ 2226 free(pi); 2227 } 2228 return rcode; 2229 } 2230 2231 /* Select which version we will use */ 2232 static int run_list(struct pipe *pi) 2233 { 2234 int rcode = 0; 2235 debug_printf_exec("run_list entered\n"); 2236 if (fake_mode == 0) { 2237 debug_printf_exec(": run_list_real with %d members\n", pi->num_progs); 2238 rcode = run_list_real(pi); 2239 } 2240 /* free_pipe_list has the side effect of clearing memory. 2241 * In the long run that function can be merged with run_list_real, 2242 * but doing that now would hobble the debugging effort. */ 2243 free_pipe_list(pi, 0); 2244 debug_printf_exec("run_list return %d\n", rcode); 2245 return rcode; 2246 } 2247 2248 /* The API for glob is arguably broken. This routine pushes a non-matching 2249 * string into the output structure, removing non-backslashed backslashes. 2250 * If someone can prove me wrong, by performing this function within the 2251 * original glob(3) api, feel free to rewrite this routine into oblivion. 2252 * Return code (0 vs. GLOB_NOSPACE) matches glob(3). 2253 * XXX broken if the last character is '\\', check that before calling. 2254 */ 2255 static int globhack(const char *src, int flags, glob_t *pglob) 2256 { 2257 int cnt = 0, pathc; 2258 const char *s; 2259 char *dest; 2260 for (cnt = 1, s = src; s && *s; s++) { 2261 if (*s == '\\') s++; 2262 cnt++; 2263 } 2264 dest = xmalloc(cnt); 2265 if (!(flags & GLOB_APPEND)) { 2266 pglob->gl_pathv = NULL; 2267 pglob->gl_pathc = 0; 2268 pglob->gl_offs = 0; 2269 pglob->gl_offs = 0; 2270 } 2271 pathc = ++pglob->gl_pathc; 2272 pglob->gl_pathv = xrealloc(pglob->gl_pathv, (pathc+1) * sizeof(*pglob->gl_pathv)); 2273 pglob->gl_pathv[pathc-1] = dest; 2274 pglob->gl_pathv[pathc] = NULL; 2275 for (s = src; s && *s; s++, dest++) { 2276 if (*s == '\\') s++; 2277 *dest = *s; 2278 } 2279 *dest = '\0'; 2280 return 0; 2281 } 2282 2283 /* XXX broken if the last character is '\\', check that before calling */ 2284 static int glob_needed(const char *s) 2285 { 2286 for (; *s; s++) { 2287 if (*s == '\\') s++; 2288 if (strchr("*[?", *s)) return 1; 2289 } 2290 return 0; 2291 } 2292 2293 static int xglob(o_string *dest, int flags, glob_t *pglob) 2294 { 2295 int gr; 2296 2297 /* short-circuit for null word */ 2298 /* we can code this better when the debug_printf's are gone */ 2299 if (dest->length == 0) { 2300 if (dest->nonnull) { 2301 /* bash man page calls this an "explicit" null */ 2302 gr = globhack(dest->data, flags, pglob); 2303 debug_printf("globhack returned %d\n", gr); 2304 } else { 2305 return 0; 2306 } 2307 } else if (glob_needed(dest->data)) { 2308 gr = glob(dest->data, flags, NULL, pglob); 2309 debug_printf("glob returned %d\n", gr); 2310 if (gr == GLOB_NOMATCH) { 2311 /* quote removal, or more accurately, backslash removal */ 2312 gr = globhack(dest->data, flags, pglob); 2313 debug_printf("globhack returned %d\n", gr); 2314 } 2315 } else { 2316 gr = globhack(dest->data, flags, pglob); 2317 debug_printf("globhack returned %d\n", gr); 2318 } 2319 if (gr == GLOB_NOSPACE) 2320 bb_error_msg_and_die("out of memory during glob"); 2321 if (gr != 0) { /* GLOB_ABORTED ? */ 2322 bb_error_msg("glob(3) error %d", gr); 2323 } 2324 /* globprint(glob_target); */ 2325 return gr; 2326 } 2327 2328 /* expand_strvec_to_strvec() takes a list of strings, expands 2329 * all variable references within and returns a pointer to 2330 * a list of expanded strings, possibly with larger number 2331 * of strings. (Think VAR="a b"; echo $VAR). 2332 * This new list is allocated as a single malloc block. 2333 * NULL-terminated list of char* pointers is at the beginning of it, 2334 * followed by strings themself. 2335 * Caller can deallocate entire list by single free(list). */ 2336 2337 /* Helpers first: 2338 * count_XXX estimates size of the block we need. It's okay 2339 * to over-estimate sizes a bit, if it makes code simpler */ 2340 static int count_ifs(const char *str) 2341 { 2342 int cnt = 0; 2343 debug_printf_expand("count_ifs('%s') ifs='%s'", str, ifs); 2344 while (1) { 2345 str += strcspn(str, ifs); 2346 if (!*str) break; 2347 str++; /* str += strspn(str, ifs); */ 2348 cnt++; /* cnt += strspn(str, ifs); - but this code is larger */ 2349 } 2350 debug_printf_expand(" return %d\n", cnt); 2351 return cnt; 2352 } 2353 2354 static void count_var_expansion_space(int *countp, int *lenp, char *arg) 2355 { 2356 char first_ch; 2357 int i; 2358 int len = *lenp; 2359 int count = *countp; 2360 const char *val; 2361 char *p; 2362 2363 while ((p = strchr(arg, SPECIAL_VAR_SYMBOL))) { 2364 len += p - arg; 2365 arg = ++p; 2366 p = strchr(p, SPECIAL_VAR_SYMBOL); 2367 first_ch = arg[0]; 2368 2369 switch (first_ch & 0x7f) { 2370 /* high bit in 1st_ch indicates that var is double-quoted */ 2371 case '$': /* pid */ 2372 case '!': /* bg pid */ 2373 case '?': /* exitcode */ 2374 case '#': /* argc */ 2375 len += sizeof(int)*3 + 1; /* enough for int */ 7401 /* helper */ 7402 static void maybe_set_to_sigexit(int sig) 7403 { 7404 void (*handler)(int); 7405 /* non_DFL_mask'ed signals are, well, masked, 7406 * no need to set handler for them. 7407 */ 7408 if (!((G.non_DFL_mask >> sig) & 1)) { 7409 handler = signal(sig, sigexit); 7410 if (handler == SIG_IGN) /* oops... restore back to IGN! */ 7411 signal(sig, handler); 7412 } 7413 } 7414 /* Set handlers to restore tty pgrp and exit */ 7415 static void set_fatal_handlers(void) 7416 { 7417 /* We _must_ restore tty pgrp on fatal signals */ 7418 if (HUSH_DEBUG) { 7419 maybe_set_to_sigexit(SIGILL ); 7420 maybe_set_to_sigexit(SIGFPE ); 7421 maybe_set_to_sigexit(SIGBUS ); 7422 maybe_set_to_sigexit(SIGSEGV); 7423 maybe_set_to_sigexit(SIGTRAP); 7424 } /* else: hush is perfect. what SEGV? */ 7425 maybe_set_to_sigexit(SIGABRT); 7426 /* bash 3.2 seems to handle these just like 'fatal' ones */ 7427 maybe_set_to_sigexit(SIGPIPE); 7428 maybe_set_to_sigexit(SIGALRM); 7429 /* if we are interactive, SIGHUP, SIGTERM and SIGINT are masked. 7430 * if we aren't interactive... but in this case 7431 * we never want to restore pgrp on exit, and this fn is not called */ 7432 /*maybe_set_to_sigexit(SIGHUP );*/ 7433 /*maybe_set_to_sigexit(SIGTERM);*/ 7434 /*maybe_set_to_sigexit(SIGINT );*/ 7435 } 7436 #endif 7437 7438 static int set_mode(int state, char mode, const char *o_opt) 7439 { 7440 int idx; 7441 switch (mode) { 7442 case 'n': 7443 G.n_mode = state; 7444 break; 7445 case 'x': 7446 IF_HUSH_MODE_X(G_x_mode = state;) 7447 break; 7448 case 'o': 7449 if (!o_opt) { 7450 /* "set -+o" without parameter. 7451 * in bash, set -o produces this output: 7452 * pipefail off 7453 * and set +o: 7454 * set +o pipefail 7455 * We always use the second form. 7456 */ 7457 const char *p = o_opt_strings; 7458 idx = 0; 7459 while (*p) { 7460 printf("set %co %s\n", (G.o_opt[idx] ? '-' : '+'), p); 7461 idx++; 7462 p += strlen(p) + 1; 7463 } 2376 7464 break; 2377 case '*': 2378 case '@': 2379 for (i = 1; i < global_argc; i++) { 2380 len += strlen(global_argv[i]) + 1; 2381 count++; 2382 if (!(first_ch & 0x80)) 2383 count += count_ifs(global_argv[i]); 2384 } 7465 } 7466 idx = index_in_strings(o_opt_strings, o_opt); 7467 if (idx >= 0) { 7468 G.o_opt[idx] = state; 2385 7469 break; 2386 default: 2387 *p = '\0'; 2388 arg[0] = first_ch & 0x7f; 2389 if (isdigit(arg[0])) { 2390 i = xatoi_u(arg); 2391 val = NULL; 2392 if (i < global_argc) 2393 val = global_argv[i]; 2394 } else 2395 val = lookup_param(arg); 2396 arg[0] = first_ch; 2397 *p = SPECIAL_VAR_SYMBOL; 2398 2399 if (val) { 2400 len += strlen(val) + 1; 2401 if (!(first_ch & 0x80)) 2402 count += count_ifs(val); 2403 } 2404 } 2405 arg = ++p; 2406 } 2407 2408 len += strlen(arg) + 1; 2409 count++; 2410 *lenp = len; 2411 *countp = count; 2412 } 2413 2414 /* Store given string, finalizing the word and starting new one whenever 2415 * we encounter ifs char(s). This is used for expanding variable values. 2416 * End-of-string does NOT finalize word: think about 'echo -$VAR-' */ 2417 static int expand_on_ifs(char **list, int n, char **posp, const char *str) 2418 { 2419 char *pos = *posp; 2420 while (1) { 2421 int word_len = strcspn(str, ifs); 2422 if (word_len) { 2423 memcpy(pos, str, word_len); /* store non-ifs chars */ 2424 pos += word_len; 2425 str += word_len; 2426 } 2427 if (!*str) /* EOL - do not finalize word */ 2428 break; 2429 *pos++ = '\0'; 2430 if (n) debug_printf_expand("expand_on_ifs finalized list[%d]=%p '%s' " 2431 "strlen=%d next=%p pos=%p\n", n-1, list[n-1], list[n-1], 2432 strlen(list[n-1]), list[n-1] + strlen(list[n-1]) + 1, pos); 2433 list[n++] = pos; 2434 str += strspn(str, ifs); /* skip ifs chars */ 2435 } 2436 *posp = pos; 2437 return n; 2438 } 2439 2440 /* Expand all variable references in given string, adding words to list[] 2441 * at n, n+1,... positions. Return updated n (so that list[n] is next one 2442 * to be filled). This routine is extremely tricky: has to deal with 2443 * variables/parameters with whitespace, $* and $@, and constructs like 2444 * 'echo -$*-'. If you play here, you must run testsuite afterwards! */ 2445 /* NB: another bug is that we cannot detect empty strings yet: 2446 * "" or $empty"" expands to zero words, has to expand to empty word */ 2447 static int expand_vars_to_list(char **list, int n, char **posp, char *arg, char or_mask) 2448 { 2449 /* or_mask is either 0 (normal case) or 0x80 2450 * (expansion of right-hand side of assignment == 1-element expand) */ 2451 2452 char first_ch, ored_ch; 2453 int i; 2454 const char *val; 2455 char *p; 2456 char *pos = *posp; 2457 2458 ored_ch = 0; 2459 2460 if (n) debug_printf_expand("expand_vars_to_list finalized list[%d]=%p '%s' " 2461 "strlen=%d next=%p pos=%p\n", n-1, list[n-1], list[n-1], 2462 strlen(list[n-1]), list[n-1] + strlen(list[n-1]) + 1, pos); 2463 list[n++] = pos; 2464 2465 while ((p = strchr(arg, SPECIAL_VAR_SYMBOL))) { 2466 memcpy(pos, arg, p - arg); 2467 pos += (p - arg); 2468 arg = ++p; 2469 p = strchr(p, SPECIAL_VAR_SYMBOL); 2470 2471 first_ch = arg[0] | or_mask; /* forced to "quoted" if or_mask = 0x80 */ 2472 ored_ch |= first_ch; 2473 val = NULL; 2474 switch (first_ch & 0x7f) { 2475 /* Highest bit in first_ch indicates that var is double-quoted */ 2476 case '$': /* pid */ 2477 /* FIXME: (echo $$) should still print pid of main shell */ 2478 val = utoa(getpid()); 2479 break; 2480 case '!': /* bg pid */ 2481 val = last_bg_pid ? utoa(last_bg_pid) : (char*)""; 2482 break; 2483 case '?': /* exitcode */ 2484 val = utoa(last_return_code); 2485 break; 2486 case '#': /* argc */ 2487 val = utoa(global_argc ? global_argc-1 : 0); 2488 break; 2489 case '*': 2490 case '@': 2491 i = 1; 2492 if (!(first_ch & 0x80)) { /* unquoted $* or $@ */ 2493 while (i < global_argc) { 2494 n = expand_on_ifs(list, n, &pos, global_argv[i]); 2495 debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, global_argc-1); 2496 if (global_argv[i++][0] && i < global_argc) { 2497 /* this argv[] is not empty and not last: 2498 * put terminating NUL, start new word */ 2499 *pos++ = '\0'; 2500 if (n) debug_printf_expand("expand_vars_to_list 2 finalized list[%d]=%p '%s' " 2501 "strlen=%d next=%p pos=%p\n", n-1, list[n-1], list[n-1], 2502 strlen(list[n-1]), list[n-1] + strlen(list[n-1]) + 1, pos); 2503 list[n++] = pos; 2504 } 2505 } 2506 } else 2507 /* If or_mask is nonzero, we handle assignment 'a=....$@.....' 2508 * and in this case should theat it like '$*' */ 2509 if (first_ch == ('@'|0x80) && !or_mask) { /* quoted $@ */ 2510 while (1) { 2511 strcpy(pos, global_argv[i]); 2512 pos += strlen(global_argv[i]); 2513 if (++i >= global_argc) 2514 break; 2515 *pos++ = '\0'; 2516 if (n) debug_printf_expand("expand_vars_to_list 3 finalized list[%d]=%p '%s' " 2517 "strlen=%d next=%p pos=%p\n", n-1, list[n-1], list[n-1], 2518 strlen(list[n-1]), list[n-1] + strlen(list[n-1]) + 1, pos); 2519 list[n++] = pos; 2520 } 2521 } else { /* quoted $*: add as one word */ 2522 while (1) { 2523 strcpy(pos, global_argv[i]); 2524 pos += strlen(global_argv[i]); 2525 if (++i >= global_argc) 2526 break; 2527 if (ifs[0]) 2528 *pos++ = ifs[0]; 2529 } 2530 } 2531 break; 2532 default: 2533 *p = '\0'; 2534 arg[0] = first_ch & 0x7f; 2535 if (isdigit(arg[0])) { 2536 i = xatoi_u(arg); 2537 val = NULL; 2538 if (i < global_argc) 2539 val = global_argv[i]; 2540 } else 2541 val = lookup_param(arg); 2542 arg[0] = first_ch; 2543 *p = SPECIAL_VAR_SYMBOL; 2544 if (!(first_ch & 0x80)) { /* unquoted $VAR */ 2545 if (val) { 2546 n = expand_on_ifs(list, n, &pos, val); 2547 val = NULL; 2548 } 2549 } /* else: quoted $VAR, val will be appended at pos */ 2550 } 2551 if (val) { 2552 strcpy(pos, val); 2553 pos += strlen(val); 2554 } 2555 arg = ++p; 2556 } 2557 debug_printf_expand("expand_vars_to_list adding tail '%s' at %p\n", arg, pos); 2558 strcpy(pos, arg); 2559 pos += strlen(arg) + 1; 2560 if (pos == list[n-1] + 1) { /* expansion is empty */ 2561 if (!(ored_ch & 0x80)) { /* all vars were not quoted... */ 2562 debug_printf_expand("expand_vars_to_list list[%d] empty, going back\n", n); 2563 pos--; 2564 n--; 2565 } 2566 } 2567 2568 *posp = pos; 2569 return n; 2570 } 2571 2572 static char **expand_variables(char **argv, char or_mask) 2573 { 2574 int n; 2575 int count = 1; 2576 int len = 0; 2577 char *pos, **v, **list; 2578 2579 v = argv; 2580 if (!*v) debug_printf_expand("count_var_expansion_space: " 2581 "argv[0]=NULL count=%d len=%d alloc_space=%d\n", 2582 count, len, sizeof(char*) * count + len); 2583 while (*v) { 2584 count_var_expansion_space(&count, &len, *v); 2585 debug_printf_expand("count_var_expansion_space: " 2586 "'%s' count=%d len=%d alloc_space=%d\n", 2587 *v, count, len, sizeof(char*) * count + len); 2588 v++; 2589 } 2590 len += sizeof(char*) * count; /* total to alloc */ 2591 list = xmalloc(len); 2592 pos = (char*)(list + count); 2593 debug_printf_expand("list=%p, list[0] should be %p\n", list, pos); 2594 n = 0; 2595 v = argv; 2596 while (*v) 2597 n = expand_vars_to_list(list, n, &pos, *v++, or_mask); 2598 2599 if (n) debug_printf_expand("finalized list[%d]=%p '%s' " 2600 "strlen=%d next=%p pos=%p\n", n-1, list[n-1], list[n-1], 2601 strlen(list[n-1]), list[n-1] + strlen(list[n-1]) + 1, pos); 2602 list[n] = NULL; 2603 2604 #ifdef DEBUG_EXPAND 2605 { 2606 int m = 0; 2607 while (m <= n) { 2608 debug_printf_expand("list[%d]=%p '%s'\n", m, list[m], list[m]); 2609 m++; 2610 } 2611 debug_printf_expand("used_space=%d\n", pos - (char*)list); 2612 } 2613 #endif 2614 if (ENABLE_HUSH_DEBUG) 2615 if (pos - (char*)list > len) 2616 bb_error_msg_and_die("BUG in varexp"); 2617 return list; 2618 } 2619 2620 static char **expand_strvec_to_strvec(char **argv) 2621 { 2622 return expand_variables(argv, 0); 2623 } 2624 2625 static char *expand_string_to_string(const char *str) 2626 { 2627 char *argv[2], **list; 2628 2629 argv[0] = (char*)str; 2630 argv[1] = NULL; 2631 list = expand_variables(argv, 0x80); /* 0x80: make one-element expansion */ 2632 if (ENABLE_HUSH_DEBUG) 2633 if (!list[0] || list[1]) 2634 bb_error_msg_and_die("BUG in varexp2"); 2635 /* actually, just move string 2*sizeof(char*) bytes back */ 2636 strcpy((char*)list, list[0]); 2637 debug_printf_expand("string_to_string='%s'\n", (char*)list); 2638 return (char*)list; 2639 } 2640 2641 static char* expand_strvec_to_string(char **argv) 2642 { 2643 char **list; 2644 2645 list = expand_variables(argv, 0x80); 2646 /* Convert all NULs to spaces */ 2647 if (list[0]) { 2648 int n = 1; 2649 while (list[n]) { 2650 if (ENABLE_HUSH_DEBUG) 2651 if (list[n-1] + strlen(list[n-1]) + 1 != list[n]) 2652 bb_error_msg_and_die("BUG in varexp3"); 2653 list[n][-1] = ' '; /* TODO: or to ifs[0]? */ 2654 n++; 2655 } 2656 } 2657 strcpy((char*)list, list[0]); 2658 debug_printf_expand("strvec_to_string='%s'\n", (char*)list); 2659 return (char*)list; 2660 } 2661 2662 /* This is used to get/check local shell variables */ 2663 static struct variable *get_local_var(const char *name) 2664 { 2665 struct variable *cur; 2666 int len; 2667 2668 if (!name) 2669 return NULL; 2670 len = strlen(name); 2671 for (cur = top_var; cur; cur = cur->next) { 2672 if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=') 2673 return cur; 2674 } 2675 return NULL; 2676 } 2677 2678 /* str holds "NAME=VAL" and is expected to be malloced. 2679 * We take ownership of it. */ 2680 static int set_local_var(char *str, int flg_export) 2681 { 2682 struct variable *cur; 2683 char *value; 2684 int name_len; 2685 2686 value = strchr(str, '='); 2687 if (!value) { /* not expected to ever happen? */ 2688 free(str); 2689 return -1; 2690 } 2691 2692 name_len = value - str + 1; /* including '=' */ 2693 cur = top_var; /* cannot be NULL (we have HUSH_VERSION and it's RO) */ 2694 while (1) { 2695 if (strncmp(cur->varstr, str, name_len) != 0) { 2696 if (!cur->next) { 2697 /* Bail out. Note that now cur points 2698 * to last var in linked list */ 2699 break; 2700 } 2701 cur = cur->next; 2702 continue; 2703 } 2704 /* We found an existing var with this name */ 2705 *value = '\0'; 2706 if (cur->flg_read_only) { 2707 bb_error_msg("%s: readonly variable", str); 2708 free(str); 2709 return -1; 2710 } 2711 unsetenv(str); /* just in case */ 2712 *value = '='; 2713 if (strcmp(cur->varstr, str) == 0) { 2714 free_and_exp: 2715 free(str); 2716 goto exp; 2717 } 2718 if (cur->max_len >= strlen(str)) { 2719 /* This one is from startup env, reuse space */ 2720 strcpy(cur->varstr, str); 2721 goto free_and_exp; 2722 } 2723 /* max_len == 0 signifies "malloced" var, which we can 2724 * (and has to) free */ 2725 if (!cur->max_len) 2726 free(cur->varstr); 2727 cur->max_len = 0; 2728 goto set_str_and_exp; 2729 } 2730 2731 /* Not found - create next variable struct */ 2732 cur->next = xzalloc(sizeof(*cur)); 2733 cur = cur->next; 2734 2735 set_str_and_exp: 2736 cur->varstr = str; 2737 exp: 2738 if (flg_export) 2739 cur->flg_export = 1; 2740 if (cur->flg_export) 2741 return putenv(cur->varstr); 2742 return 0; 2743 } 2744 2745 static void unset_local_var(const char *name) 2746 { 2747 struct variable *cur; 2748 struct variable *prev = prev; /* for gcc */ 2749 int name_len; 2750 2751 if (!name) 2752 return; 2753 name_len = strlen(name); 2754 cur = top_var; 2755 while (cur) { 2756 if (strncmp(cur->varstr, name, name_len) == 0 && cur->varstr[name_len] == '=') { 2757 if (cur->flg_read_only) { 2758 bb_error_msg("%s: readonly variable", name); 2759 return; 2760 } 2761 /* prev is ok to use here because 1st variable, HUSH_VERSION, 2762 * is ro, and we cannot reach this code on the 1st pass */ 2763 prev->next = cur->next; 2764 unsetenv(cur->varstr); 2765 if (!cur->max_len) 2766 free(cur->varstr); 2767 free(cur); 2768 return; 2769 } 2770 prev = cur; 2771 cur = cur->next; 2772 } 2773 } 2774 2775 static int is_assignment(const char *s) 2776 { 2777 if (!s || !isalpha(*s)) 2778 return 0; 2779 s++; 2780 while (isalnum(*s) || *s == '_') 2781 s++; 2782 return *s == '='; 2783 } 2784 2785 /* the src parameter allows us to peek forward to a possible &n syntax 2786 * for file descriptor duplication, e.g., "2>&1". 2787 * Return code is 0 normally, 1 if a syntax error is detected in src. 2788 * Resource errors (in xmalloc) cause the process to exit */ 2789 static int setup_redirect(struct p_context *ctx, int fd, redir_type style, 2790 struct in_str *input) 2791 { 2792 struct child_prog *child = ctx->child; 2793 struct redir_struct *redir = child->redirects; 2794 struct redir_struct *last_redir = NULL; 2795 2796 /* Create a new redir_struct and drop it onto the end of the linked list */ 2797 while (redir) { 2798 last_redir = redir; 2799 redir = redir->next; 2800 } 2801 redir = xmalloc(sizeof(struct redir_struct)); 2802 redir->next = NULL; 2803 redir->word.gl_pathv = NULL; 2804 if (last_redir) { 2805 last_redir->next = redir; 2806 } else { 2807 child->redirects = redir; 2808 } 2809 2810 redir->type = style; 2811 redir->fd = (fd == -1) ? redir_table[style].default_fd : fd; 2812 2813 debug_printf("Redirect type %d%s\n", redir->fd, redir_table[style].descrip); 2814 2815 /* Check for a '2>&1' type redirect */ 2816 redir->dup = redirect_dup_num(input); 2817 if (redir->dup == -2) return 1; /* syntax error */ 2818 if (redir->dup != -1) { 2819 /* Erik had a check here that the file descriptor in question 2820 * is legit; I postpone that to "run time" 2821 * A "-" representation of "close me" shows up as a -3 here */ 2822 debug_printf("Duplicating redirect '%d>&%d'\n", redir->fd, redir->dup); 2823 } else { 2824 /* We do _not_ try to open the file that src points to, 2825 * since we need to return and let src be expanded first. 2826 * Set ctx->pending_redirect, so we know what to do at the 2827 * end of the next parsed word. */ 2828 ctx->pending_redirect = redir; 2829 } 2830 return 0; 2831 } 2832 2833 static struct pipe *new_pipe(void) 2834 { 2835 struct pipe *pi; 2836 pi = xzalloc(sizeof(struct pipe)); 2837 /*pi->num_progs = 0;*/ 2838 /*pi->progs = NULL;*/ 2839 /*pi->next = NULL;*/ 2840 /*pi->followup = 0; invalid */ 2841 if (RES_NONE) 2842 pi->res_word = RES_NONE; 2843 return pi; 2844 } 2845 2846 static void initialize_context(struct p_context *ctx) 2847 { 2848 ctx->child = NULL; 2849 ctx->pipe = ctx->list_head = new_pipe(); 2850 ctx->pending_redirect = NULL; 2851 ctx->res_w = RES_NONE; 2852 //only ctx->parse_type is not touched... is this intentional? 2853 ctx->old_flag = 0; 2854 ctx->stack = NULL; 2855 done_command(ctx); /* creates the memory for working child */ 2856 } 2857 2858 /* normal return is 0 2859 * if a reserved word is found, and processed, return 1 2860 * should handle if, then, elif, else, fi, for, while, until, do, done. 2861 * case, function, and select are obnoxious, save those for later. 2862 */ 2863 #if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS 2864 static int reserved_word(o_string *dest, struct p_context *ctx) 2865 { 2866 struct reserved_combo { 2867 char literal[7]; 2868 unsigned char code; 2869 int flag; 2870 }; 2871 /* Mostly a list of accepted follow-up reserved words. 2872 * FLAG_END means we are done with the sequence, and are ready 2873 * to turn the compound list into a command. 2874 * FLAG_START means the word must start a new compound list. 2875 */ 2876 static const struct reserved_combo reserved_list[] = { 2877 #if ENABLE_HUSH_IF 2878 { "if", RES_IF, FLAG_THEN | FLAG_START }, 2879 { "then", RES_THEN, FLAG_ELIF | FLAG_ELSE | FLAG_FI }, 2880 { "elif", RES_ELIF, FLAG_THEN }, 2881 { "else", RES_ELSE, FLAG_FI }, 2882 { "fi", RES_FI, FLAG_END }, 2883 #endif 2884 #if ENABLE_HUSH_LOOPS 2885 { "for", RES_FOR, FLAG_IN | FLAG_START }, 2886 { "while", RES_WHILE, FLAG_DO | FLAG_START }, 2887 { "until", RES_UNTIL, FLAG_DO | FLAG_START }, 2888 { "in", RES_IN, FLAG_DO }, 2889 { "do", RES_DO, FLAG_DONE }, 2890 { "done", RES_DONE, FLAG_END } 2891 #endif 2892 }; 2893 2894 const struct reserved_combo *r; 2895 2896 for (r = reserved_list; r < reserved_list + ARRAY_SIZE(reserved_list); r++) { 2897 if (strcmp(dest->data, r->literal) != 0) 2898 continue; 2899 debug_printf("found reserved word %s, code %d\n", r->literal, r->code); 2900 if (r->flag & FLAG_START) { 2901 struct p_context *new; 2902 debug_printf("push stack\n"); 2903 #if ENABLE_HUSH_LOOPS 2904 if (ctx->res_w == RES_IN || ctx->res_w == RES_FOR) { 2905 syntax("malformed for"); /* example: 'for if' */ 2906 ctx->res_w = RES_SNTX; 2907 b_reset(dest); 2908 return 1; 2909 } 2910 #endif 2911 new = xmalloc(sizeof(*new)); 2912 *new = *ctx; /* physical copy */ 2913 initialize_context(ctx); 2914 ctx->stack = new; 2915 } else if (ctx->res_w == RES_NONE || !(ctx->old_flag & (1 << r->code))) { 2916 syntax(NULL); 2917 ctx->res_w = RES_SNTX; 2918 b_reset(dest); 2919 return 1; 2920 } 2921 ctx->res_w = r->code; 2922 ctx->old_flag = r->flag; 2923 if (ctx->old_flag & FLAG_END) { 2924 struct p_context *old; 2925 debug_printf("pop stack\n"); 2926 done_pipe(ctx, PIPE_SEQ); 2927 old = ctx->stack; 2928 old->child->group = ctx->list_head; 2929 old->child->subshell = 0; 2930 *ctx = *old; /* physical copy */ 2931 free(old); 2932 } 2933 b_reset(dest); 2934 return 1; 2935 } 2936 return 0; 2937 } 2938 #else 2939 #define reserved_word(dest, ctx) ((int)0) 2940 #endif 2941 2942 /* Normal return is 0. 2943 * Syntax or xglob errors return 1. */ 2944 static int done_word(o_string *dest, struct p_context *ctx) 2945 { 2946 struct child_prog *child = ctx->child; 2947 glob_t *glob_target; 2948 int gr, flags = 0; 2949 2950 debug_printf_parse("done_word entered: '%s' %p\n", dest->data, child); 2951 if (dest->length == 0 && !dest->nonnull) { 2952 debug_printf_parse("done_word return 0: true null, ignored\n"); 2953 return 0; 2954 } 2955 if (ctx->pending_redirect) { 2956 glob_target = &ctx->pending_redirect->word; 2957 } else { 2958 if (child->group) { 2959 syntax(NULL); 2960 debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n"); 2961 return 1; 2962 } 2963 if (!child->argv && (ctx->parse_type & PARSEFLAG_SEMICOLON)) { 2964 debug_printf_parse(": checking '%s' for reserved-ness\n", dest->data); 2965 if (reserved_word(dest, ctx)) { 2966 debug_printf_parse("done_word return %d\n", (ctx->res_w == RES_SNTX)); 2967 return (ctx->res_w == RES_SNTX); 2968 } 2969 } 2970 glob_target = &child->glob_result; 2971 if (child->argv) 2972 flags |= GLOB_APPEND; 2973 } 2974 gr = xglob(dest, flags, glob_target); 2975 if (gr != 0) { 2976 debug_printf_parse("done_word return 1: xglob returned %d\n", gr); 2977 return 1; 2978 } 2979 2980 b_reset(dest); 2981 if (ctx->pending_redirect) { 2982 ctx->pending_redirect = NULL; 2983 if (glob_target->gl_pathc != 1) { 2984 bb_error_msg("ambiguous redirect"); 2985 debug_printf_parse("done_word return 1: ambiguous redirect\n"); 2986 return 1; 2987 } 2988 } else { 2989 child->argv = glob_target->gl_pathv; 2990 } 2991 #if ENABLE_HUSH_LOOPS 2992 if (ctx->res_w == RES_FOR) { 2993 done_word(dest, ctx); 2994 done_pipe(ctx, PIPE_SEQ); 2995 } 2996 #endif 2997 debug_printf_parse("done_word return 0\n"); 2998 return 0; 2999 } 3000 3001 /* The only possible error here is out of memory, in which case 3002 * xmalloc exits. */ 3003 static int done_command(struct p_context *ctx) 3004 { 3005 /* The child is really already in the pipe structure, so 3006 * advance the pipe counter and make a new, null child. */ 3007 struct pipe *pi = ctx->pipe; 3008 struct child_prog *child = ctx->child; 3009 3010 if (child) { 3011 if (child->group == NULL 3012 && child->argv == NULL 3013 && child->redirects == NULL 3014 ) { 3015 debug_printf_parse("done_command: skipping null cmd, num_progs=%d\n", pi->num_progs); 3016 return pi->num_progs; 3017 } 3018 pi->num_progs++; 3019 debug_printf_parse("done_command: ++num_progs=%d\n", pi->num_progs); 3020 } else { 3021 debug_printf_parse("done_command: initializing, num_progs=%d\n", pi->num_progs); 3022 } 3023 3024 /* Only real trickiness here is that the uncommitted 3025 * child structure is not counted in pi->num_progs. */ 3026 pi->progs = xrealloc(pi->progs, sizeof(*pi->progs) * (pi->num_progs+1)); 3027 child = &pi->progs[pi->num_progs]; 3028 3029 memset(child, 0, sizeof(*child)); 3030 /*child->redirects = NULL;*/ 3031 /*child->argv = NULL;*/ 3032 /*child->is_stopped = 0;*/ 3033 /*child->group = NULL;*/ 3034 /*child->glob_result.gl_pathv = NULL;*/ 3035 child->family = pi; 3036 //sp: /*child->sp = 0;*/ 3037 //pt: child->parse_type = ctx->parse_type; 3038 3039 ctx->child = child; 3040 /* but ctx->pipe and ctx->list_head remain unchanged */ 3041 3042 return pi->num_progs; /* used only for 0/nonzero check */ 3043 } 3044 3045 static int done_pipe(struct p_context *ctx, pipe_style type) 3046 { 3047 struct pipe *new_p; 3048 int not_null; 3049 3050 debug_printf_parse("done_pipe entered, followup %d\n", type); 3051 not_null = done_command(ctx); /* implicit closure of previous command */ 3052 ctx->pipe->followup = type; 3053 ctx->pipe->res_word = ctx->res_w; 3054 /* Without this check, even just <enter> on command line generates 3055 * tree of three NOPs (!). Which is harmless but annoying. 3056 * IOW: it is safe to do it unconditionally. */ 3057 if (not_null) { 3058 new_p = new_pipe(); 3059 ctx->pipe->next = new_p; 3060 ctx->pipe = new_p; 3061 ctx->child = NULL; 3062 done_command(ctx); /* set up new pipe to accept commands */ 3063 } 3064 debug_printf_parse("done_pipe return 0\n"); 3065 return 0; 3066 } 3067 3068 /* peek ahead in the in_str to find out if we have a "&n" construct, 3069 * as in "2>&1", that represents duplicating a file descriptor. 3070 * returns either -2 (syntax error), -1 (no &), or the number found. 3071 */ 3072 static int redirect_dup_num(struct in_str *input) 3073 { 3074 int ch, d = 0, ok = 0; 3075 ch = b_peek(input); 3076 if (ch != '&') return -1; 3077 3078 b_getch(input); /* get the & */ 3079 ch = b_peek(input); 3080 if (ch == '-') { 3081 b_getch(input); 3082 return -3; /* "-" represents "close me" */ 3083 } 3084 while (isdigit(ch)) { 3085 d = d*10 + (ch-'0'); 3086 ok = 1; 3087 b_getch(input); 3088 ch = b_peek(input); 3089 } 3090 if (ok) return d; 3091 3092 bb_error_msg("ambiguous redirect"); 3093 return -2; 3094 } 3095 3096 /* If a redirect is immediately preceded by a number, that number is 3097 * supposed to tell which file descriptor to redirect. This routine 3098 * looks for such preceding numbers. In an ideal world this routine 3099 * needs to handle all the following classes of redirects... 3100 * echo 2>foo # redirects fd 2 to file "foo", nothing passed to echo 3101 * echo 49>foo # redirects fd 49 to file "foo", nothing passed to echo 3102 * echo -2>foo # redirects fd 1 to file "foo", "-2" passed to echo 3103 * echo 49x>foo # redirects fd 1 to file "foo", "49x" passed to echo 3104 * A -1 output from this program means no valid number was found, so the 3105 * caller should use the appropriate default for this redirection. 3106 */ 3107 static int redirect_opt_num(o_string *o) 3108 { 3109 int num; 3110 3111 if (o->length == 0) 3112 return -1; 3113 for (num = 0; num < o->length; num++) { 3114 if (!isdigit(*(o->data + num))) { 3115 return -1; 3116 } 3117 } 3118 /* reuse num (and save an int) */ 3119 num = atoi(o->data); 3120 b_reset(o); 3121 return num; 3122 } 3123 3124 #if ENABLE_HUSH_TICK 3125 static FILE *generate_stream_from_list(struct pipe *head) 3126 { 3127 FILE *pf; 3128 int pid, channel[2]; 3129 3130 xpipe(channel); 3131 #if BB_MMU 3132 pid = fork(); 3133 #else 3134 pid = vfork(); 3135 #endif 3136 if (pid < 0) { 3137 bb_perror_msg_and_die("fork"); 3138 } else if (pid == 0) { 3139 close(channel[0]); 3140 if (channel[1] != 1) { 3141 dup2(channel[1], 1); 3142 close(channel[1]); 3143 } 3144 /* Prevent it from trying to handle ctrl-z etc */ 3145 #if ENABLE_HUSH_JOB 3146 run_list_level = 1; 3147 #endif 3148 /* Process substitution is not considered to be usual 3149 * 'command execution'. 3150 * SUSv3 says ctrl-Z should be ignored, ctrl-C should not. */ 3151 /* Not needed, we are relying on it being disabled 3152 * everywhere outside actual command execution. */ 3153 /*set_jobctrl_sighandler(SIG_IGN);*/ 3154 set_misc_sighandler(SIG_DFL); 3155 _exit(run_list_real(head)); /* leaks memory */ 3156 } 3157 close(channel[1]); 3158 pf = fdopen(channel[0], "r"); 3159 return pf; 3160 } 3161 3162 /* Return code is exit status of the process that is run. */ 3163 static int process_command_subs(o_string *dest, struct p_context *ctx, 3164 struct in_str *input, const char *subst_end) 3165 { 3166 int retcode, ch, eol_cnt; 3167 o_string result = NULL_O_STRING; 3168 struct p_context inner; 3169 FILE *p; 3170 struct in_str pipe_str; 3171 3172 initialize_context(&inner); 3173 3174 /* recursion to generate command */ 3175 retcode = parse_stream(&result, &inner, input, subst_end); 3176 if (retcode != 0) 3177 return retcode; /* syntax error or EOF */ 3178 done_word(&result, &inner); 3179 done_pipe(&inner, PIPE_SEQ); 3180 b_free(&result); 3181 3182 p = generate_stream_from_list(inner.list_head); 3183 if (p == NULL) return 1; 3184 mark_open(fileno(p)); 3185 setup_file_in_str(&pipe_str, p); 3186 3187 /* now send results of command back into original context */ 3188 eol_cnt = 0; 3189 while ((ch = b_getch(&pipe_str)) != EOF) { 3190 if (ch == '\n') { 3191 eol_cnt++; 3192 continue; 3193 } 3194 while (eol_cnt) { 3195 b_addqchr(dest, '\n', dest->quote); 3196 eol_cnt--; 3197 } 3198 b_addqchr(dest, ch, dest->quote); 3199 } 3200 3201 debug_printf("done reading from pipe, pclose()ing\n"); 3202 /* This is the step that wait()s for the child. Should be pretty 3203 * safe, since we just read an EOF from its stdout. We could try 3204 * to do better, by using wait(), and keeping track of background jobs 3205 * at the same time. That would be a lot of work, and contrary 3206 * to the KISS philosophy of this program. */ 3207 mark_closed(fileno(p)); 3208 retcode = fclose(p); 3209 free_pipe_list(inner.list_head, 0); 3210 debug_printf("closed FILE from child, retcode=%d\n", retcode); 3211 return retcode; 3212 } 3213 #endif 3214 3215 static int parse_group(o_string *dest, struct p_context *ctx, 3216 struct in_str *input, int ch) 3217 { 3218 int rcode; 3219 const char *endch = NULL; 3220 struct p_context sub; 3221 struct child_prog *child = ctx->child; 3222 3223 debug_printf_parse("parse_group entered\n"); 3224 if (child->argv) { 3225 syntax(NULL); 3226 debug_printf_parse("parse_group return 1: syntax error, groups and arglists don't mix\n"); 3227 return 1; 3228 } 3229 initialize_context(&sub); 3230 endch = "}"; 3231 if (ch == '(') { 3232 endch = ")"; 3233 child->subshell = 1; 3234 } 3235 rcode = parse_stream(dest, &sub, input, endch); 3236 //vda: err chk? 3237 done_word(dest, &sub); /* finish off the final word in the subcontext */ 3238 done_pipe(&sub, PIPE_SEQ); /* and the final command there, too */ 3239 child->group = sub.list_head; 3240 3241 debug_printf_parse("parse_group return %d\n", rcode); 3242 return rcode; 3243 /* child remains "open", available for possible redirects */ 3244 } 3245 3246 /* Basically useful version until someone wants to get fancier, 3247 * see the bash man page under "Parameter Expansion" */ 3248 static const char *lookup_param(const char *src) 3249 { 3250 struct variable *var = get_local_var(src); 3251 if (var) 3252 return strchr(var->varstr, '=') + 1; 3253 return NULL; 3254 } 3255 3256 /* return code: 0 for OK, 1 for syntax error */ 3257 static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input) 3258 { 3259 int ch = b_peek(input); /* first character after the $ */ 3260 unsigned char quote_mask = dest->quote ? 0x80 : 0; 3261 3262 debug_printf_parse("handle_dollar entered: ch='%c'\n", ch); 3263 if (isalpha(ch)) { 3264 b_addchr(dest, SPECIAL_VAR_SYMBOL); 3265 //sp: ctx->child->sp++; 3266 while (1) { 3267 debug_printf_parse(": '%c'\n", ch); 3268 b_getch(input); 3269 b_addchr(dest, ch | quote_mask); 3270 quote_mask = 0; 3271 ch = b_peek(input); 3272 if (!isalnum(ch) && ch != '_') 3273 break; 3274 } 3275 b_addchr(dest, SPECIAL_VAR_SYMBOL); 3276 } else if (isdigit(ch)) { 3277 make_one_char_var: 3278 b_addchr(dest, SPECIAL_VAR_SYMBOL); 3279 //sp: ctx->child->sp++; 3280 debug_printf_parse(": '%c'\n", ch); 3281 b_getch(input); 3282 b_addchr(dest, ch | quote_mask); 3283 b_addchr(dest, SPECIAL_VAR_SYMBOL); 3284 } else switch (ch) { 3285 case '$': /* pid */ 3286 case '!': /* last bg pid */ 3287 case '?': /* last exit code */ 3288 case '#': /* number of args */ 3289 case '*': /* args */ 3290 case '@': /* args */ 3291 goto make_one_char_var; 3292 case '{': 3293 b_addchr(dest, SPECIAL_VAR_SYMBOL); 3294 //sp: ctx->child->sp++; 3295 b_getch(input); 3296 /* XXX maybe someone will try to escape the '}' */ 3297 while (1) { 3298 ch = b_getch(input); 3299 if (ch == '}') 3300 break; 3301 if (!isalnum(ch) && ch != '_') { 3302 syntax("unterminated ${name}"); 3303 debug_printf_parse("handle_dollar return 1: unterminated ${name}\n"); 3304 return 1; 3305 } 3306 debug_printf_parse(": '%c'\n", ch); 3307 b_addchr(dest, ch | quote_mask); 3308 quote_mask = 0; 3309 } 3310 b_addchr(dest, SPECIAL_VAR_SYMBOL); 3311 break; 3312 #if ENABLE_HUSH_TICK 3313 case '(': 3314 b_getch(input); 3315 process_command_subs(dest, ctx, input, ")"); 3316 break; 3317 #endif 3318 case '-': 3319 case '_': 3320 /* still unhandled, but should be eventually */ 3321 bb_error_msg("unhandled syntax: $%c", ch); 3322 return 1; 3323 break; 3324 default: 3325 b_addqchr(dest, '$', dest->quote); 3326 } 3327 debug_printf_parse("handle_dollar return 0\n"); 3328 return 0; 3329 } 3330 3331 /* return code is 0 for normal exit, 1 for syntax error */ 3332 static int parse_stream(o_string *dest, struct p_context *ctx, 3333 struct in_str *input, const char *end_trigger) 3334 { 3335 int ch, m; 3336 int redir_fd; 3337 redir_type redir_style; 3338 int next; 3339 3340 /* Only double-quote state is handled in the state variable dest->quote. 3341 * A single-quote triggers a bypass of the main loop until its mate is 3342 * found. When recursing, quote state is passed in via dest->quote. */ 3343 3344 debug_printf_parse("parse_stream entered, end_trigger='%s'\n", end_trigger); 3345 3346 while (1) { 3347 m = CHAR_IFS; 3348 next = '\0'; 3349 ch = b_getch(input); 3350 if (ch != EOF) { 3351 m = charmap[ch]; 3352 if (ch != '\n') 3353 next = b_peek(input); 3354 } 3355 debug_printf_parse(": ch=%c (%d) m=%d quote=%d\n", 3356 ch, ch, m, dest->quote); 3357 if (m == CHAR_ORDINARY 3358 || (m != CHAR_SPECIAL && dest->quote) 3359 ) { 3360 if (ch == EOF) { 3361 syntax("unterminated \""); 3362 debug_printf_parse("parse_stream return 1: unterminated \"\n"); 3363 return 1; 3364 } 3365 b_addqchr(dest, ch, dest->quote); 3366 continue; 3367 } 3368 if (m == CHAR_IFS) { 3369 if (done_word(dest, ctx)) { 3370 debug_printf_parse("parse_stream return 1: done_word!=0\n"); 3371 return 1; 3372 } 3373 if (ch == EOF) 3374 break; 3375 /* If we aren't performing a substitution, treat 3376 * a newline as a command separator. 3377 * [why we don't handle it exactly like ';'? --vda] */ 3378 if (end_trigger && ch == '\n') { 3379 done_pipe(ctx, PIPE_SEQ); 3380 } 3381 } 3382 if ((end_trigger && strchr(end_trigger, ch)) 3383 && !dest->quote && ctx->res_w == RES_NONE 3384 ) { 3385 debug_printf_parse("parse_stream return 0: end_trigger char found\n"); 3386 return 0; 3387 } 3388 if (m == CHAR_IFS) 3389 continue; 3390 switch (ch) { 3391 case '#': 3392 if (dest->length == 0 && !dest->quote) { 3393 while (1) { 3394 ch = b_peek(input); 3395 if (ch == EOF || ch == '\n') 3396 break; 3397 b_getch(input); 3398 } 3399 } else { 3400 b_addqchr(dest, ch, dest->quote); 3401 } 3402 break; 3403 case '\\': 3404 if (next == EOF) { 3405 syntax("\\<eof>"); 3406 debug_printf_parse("parse_stream return 1: \\<eof>\n"); 3407 return 1; 3408 } 3409 b_addqchr(dest, '\\', dest->quote); 3410 b_addqchr(dest, b_getch(input), dest->quote); 3411 break; 3412 case '$': 3413 if (handle_dollar(dest, ctx, input) != 0) { 3414 debug_printf_parse("parse_stream return 1: handle_dollar returned non-0\n"); 3415 return 1; 3416 } 3417 break; 3418 case '\'': 3419 dest->nonnull = 1; 3420 while (1) { 3421 ch = b_getch(input); 3422 if (ch == EOF || ch == '\'') 3423 break; 3424 b_addchr(dest, ch); 3425 } 3426 if (ch == EOF) { 3427 syntax("unterminated '"); 3428 debug_printf_parse("parse_stream return 1: unterminated '\n"); 3429 return 1; 3430 } 3431 break; 3432 case '"': 3433 dest->nonnull = 1; 3434 dest->quote = !dest->quote; 3435 break; 3436 #if ENABLE_HUSH_TICK 3437 case '`': 3438 process_command_subs(dest, ctx, input, "`"); 3439 break; 3440 #endif 3441 case '>': 3442 redir_fd = redirect_opt_num(dest); 3443 done_word(dest, ctx); 3444 redir_style = REDIRECT_OVERWRITE; 3445 if (next == '>') { 3446 redir_style = REDIRECT_APPEND; 3447 b_getch(input); 3448 } 3449 #if 0 3450 else if (next == '(') { 3451 syntax(">(process) not supported"); 3452 debug_printf_parse("parse_stream return 1: >(process) not supported\n"); 3453 return 1; 3454 } 3455 #endif 3456 setup_redirect(ctx, redir_fd, redir_style, input); 3457 break; 3458 case '<': 3459 redir_fd = redirect_opt_num(dest); 3460 done_word(dest, ctx); 3461 redir_style = REDIRECT_INPUT; 3462 if (next == '<') { 3463 redir_style = REDIRECT_HEREIS; 3464 b_getch(input); 3465 } else if (next == '>') { 3466 redir_style = REDIRECT_IO; 3467 b_getch(input); 3468 } 3469 #if 0 3470 else if (next == '(') { 3471 syntax("<(process) not supported"); 3472 debug_printf_parse("parse_stream return 1: <(process) not supported\n"); 3473 return 1; 3474 } 3475 #endif 3476 setup_redirect(ctx, redir_fd, redir_style, input); 3477 break; 3478 case ';': 3479 done_word(dest, ctx); 3480 done_pipe(ctx, PIPE_SEQ); 3481 break; 3482 case '&': 3483 done_word(dest, ctx); 3484 if (next == '&') { 3485 b_getch(input); 3486 done_pipe(ctx, PIPE_AND); 3487 } else { 3488 done_pipe(ctx, PIPE_BG); 3489 } 3490 break; 3491 case '|': 3492 done_word(dest, ctx); 3493 if (next == '|') { 3494 b_getch(input); 3495 done_pipe(ctx, PIPE_OR); 3496 } else { 3497 /* we could pick up a file descriptor choice here 3498 * with redirect_opt_num(), but bash doesn't do it. 3499 * "echo foo 2| cat" yields "foo 2". */ 3500 done_command(ctx); 3501 } 3502 break; 3503 case '(': 3504 case '{': 3505 if (parse_group(dest, ctx, input, ch) != 0) { 3506 debug_printf_parse("parse_stream return 1: parse_group returned non-0\n"); 3507 return 1; 3508 } 3509 break; 3510 case ')': 3511 case '}': 3512 syntax("unexpected }"); /* Proper use of this character is caught by end_trigger */ 3513 debug_printf_parse("parse_stream return 1: unexpected '}'\n"); 3514 return 1; 3515 default: 3516 if (ENABLE_HUSH_DEBUG) 3517 bb_error_msg_and_die("BUG: unexpected %c\n", ch); 3518 } 3519 } 3520 /* Complain if quote? No, maybe we just finished a command substitution 3521 * that was quoted. Example: 3522 * $ echo "`cat foo` plus more" 3523 * and we just got the EOF generated by the subshell that ran "cat foo" 3524 * The only real complaint is if we got an EOF when end_trigger != NULL, 3525 * that is, we were really supposed to get end_trigger, and never got 3526 * one before the EOF. Can't use the standard "syntax error" return code, 3527 * so that parse_stream_outer can distinguish the EOF and exit smoothly. */ 3528 debug_printf_parse("parse_stream return %d\n", -(end_trigger != NULL)); 3529 if (end_trigger) 3530 return -1; 3531 return 0; 3532 } 3533 3534 static void set_in_charmap(const char *set, int code) 3535 { 3536 while (*set) 3537 charmap[(unsigned char)*set++] = code; 3538 } 3539 3540 static void update_charmap(void) 3541 { 3542 /* char *ifs and char charmap[256] are both globals. */ 3543 ifs = getenv("IFS"); 3544 if (ifs == NULL) 3545 ifs = " \t\n"; 3546 /* Precompute a list of 'flow through' behavior so it can be treated 3547 * quickly up front. Computation is necessary because of IFS. 3548 * Special case handling of IFS == " \t\n" is not implemented. 3549 * The charmap[] array only really needs two bits each, 3550 * and on most machines that would be faster (reduced L1 cache use). 3551 */ 3552 memset(charmap, CHAR_ORDINARY, sizeof(charmap)); 3553 #if ENABLE_HUSH_TICK 3554 set_in_charmap("\\$\"`", CHAR_SPECIAL); 3555 #else 3556 set_in_charmap("\\$\"", CHAR_SPECIAL); 3557 #endif 3558 set_in_charmap("<>;&|(){}#'", CHAR_ORDINARY_IF_QUOTED); 3559 set_in_charmap(ifs, CHAR_IFS); /* are ordinary if quoted */ 3560 } 3561 3562 /* most recursion does not come through here, the exception is 3563 * from builtin_source() and builtin_eval() */ 3564 static int parse_and_run_stream(struct in_str *inp, int parse_flag) 3565 { 3566 struct p_context ctx; 3567 o_string temp = NULL_O_STRING; 3568 int rcode; 3569 do { 3570 ctx.parse_type = parse_flag; 3571 initialize_context(&ctx); 3572 update_charmap(); 3573 if (!(parse_flag & PARSEFLAG_SEMICOLON) || (parse_flag & PARSEFLAG_REPARSING)) 3574 set_in_charmap(";$&|", CHAR_ORDINARY); 3575 #if ENABLE_HUSH_INTERACTIVE 3576 inp->promptmode = 0; /* PS1 */ 3577 #endif 3578 /* We will stop & execute after each ';' or '\n'. 3579 * Example: "sleep 9999; echo TEST" + ctrl-C: 3580 * TEST should be printed */ 3581 rcode = parse_stream(&temp, &ctx, inp, ";\n"); 3582 if (rcode != 1 && ctx.old_flag != 0) { 3583 syntax(NULL); 3584 } 3585 if (rcode != 1 && ctx.old_flag == 0) { 3586 done_word(&temp, &ctx); 3587 done_pipe(&ctx, PIPE_SEQ); 3588 debug_print_tree(ctx.list_head, 0); 3589 debug_printf_exec("parse_stream_outer: run_list\n"); 3590 run_list(ctx.list_head); 3591 } else { 3592 if (ctx.old_flag != 0) { 3593 free(ctx.stack); 3594 b_reset(&temp); 3595 } 3596 temp.nonnull = 0; 3597 temp.quote = 0; 3598 inp->p = NULL; 3599 free_pipe_list(ctx.list_head, 0); 3600 } 3601 b_free(&temp); 3602 } while (rcode != -1 && !(parse_flag & PARSEFLAG_EXIT_FROM_LOOP)); /* loop on syntax errors, return on EOF */ 3603 return 0; 3604 } 3605 3606 static int parse_and_run_string(const char *s, int parse_flag) 3607 { 3608 struct in_str input; 3609 setup_string_in_str(&input, s); 3610 return parse_and_run_stream(&input, parse_flag); 3611 } 3612 3613 static int parse_and_run_file(FILE *f) 3614 { 3615 int rcode; 3616 struct in_str input; 3617 setup_file_in_str(&input, f); 3618 rcode = parse_and_run_stream(&input, PARSEFLAG_SEMICOLON); 3619 return rcode; 3620 } 3621 3622 #if ENABLE_HUSH_JOB 3623 /* Make sure we have a controlling tty. If we get started under a job 3624 * aware app (like bash for example), make sure we are now in charge so 3625 * we don't fight over who gets the foreground */ 3626 static void setup_job_control(void) 3627 { 3628 pid_t shell_pgrp; 3629 3630 saved_task_pgrp = shell_pgrp = getpgrp(); 3631 debug_printf_jobs("saved_task_pgrp=%d\n", saved_task_pgrp); 3632 fcntl(interactive_fd, F_SETFD, FD_CLOEXEC); 3633 3634 /* If we were ran as 'hush &', 3635 * sleep until we are in the foreground. */ 3636 while (tcgetpgrp(interactive_fd) != shell_pgrp) { 3637 /* Send TTIN to ourself (should stop us) */ 3638 kill(- shell_pgrp, SIGTTIN); 3639 shell_pgrp = getpgrp(); 3640 } 3641 3642 /* Ignore job-control and misc signals. */ 3643 set_jobctrl_sighandler(SIG_IGN); 3644 set_misc_sighandler(SIG_IGN); 3645 //huh? signal(SIGCHLD, SIG_IGN); 3646 3647 /* We _must_ restore tty pgrp on fatal signals */ 3648 set_fatal_sighandler(sigexit); 3649 3650 /* Put ourselves in our own process group. */ 3651 setpgrp(); /* is the same as setpgid(our_pid, our_pid); */ 3652 /* Grab control of the terminal. */ 3653 tcsetpgrp(interactive_fd, getpid()); 3654 } 3655 #endif 3656 3657 int hush_main(int argc, char **argv); 7470 } 7471 default: 7472 return EXIT_FAILURE; 7473 } 7474 return EXIT_SUCCESS; 7475 } 7476 7477 int hush_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 3658 7478 int hush_main(int argc, char **argv) 3659 7479 { 3660 static const char version_str[] ALIGN1 = "HUSH_VERSION="HUSH_VER_STR;3661 static const struct variable const_shell_ver = {3662 .next = NULL,3663 .varstr = (char*)version_str,3664 .max_len = 1, /* 0 can provoke free(name) */3665 .flg_export = 1,3666 .flg_read_only = 1,3667 };3668 3669 7480 int opt; 3670 FILE *input;7481 unsigned builtin_argc; 3671 7482 char **e; 3672 7483 struct variable *cur_var; 3673 3674 PTR_TO_GLOBALS = xzalloc(sizeof(G)); 3675 7484 struct variable *shell_ver; 7485 7486 INIT_G(); 7487 if (EXIT_SUCCESS) /* if EXIT_SUCCESS == 0, it is already done */ 7488 G.last_exitcode = EXIT_SUCCESS; 7489 #if !BB_MMU 7490 G.argv0_for_re_execing = argv[0]; 7491 #endif 3676 7492 /* Deal with HUSH_VERSION */ 3677 shell_ver = const_shell_ver; /* copying struct here */ 3678 top_var = &shell_ver; 7493 shell_ver = xzalloc(sizeof(*shell_ver)); 7494 shell_ver->flg_export = 1; 7495 shell_ver->flg_read_only = 1; 7496 /* Code which handles ${var<op>...} needs writable values for all variables, 7497 * therefore we xstrdup: */ 7498 shell_ver->varstr = xstrdup(hush_version_str); 7499 /* Create shell local variables from the values 7500 * currently living in the environment */ 7501 debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); 3679 7502 unsetenv("HUSH_VERSION"); /* in case it exists in initial env */ 3680 /* Initialize our shell local variables with the values 3681 * currently living in the environment */ 3682 cur_var = top_var; 7503 G.top_var = shell_ver; 7504 cur_var = G.top_var; 3683 7505 e = environ; 3684 7506 if (e) while (*e) { … … 3693 7515 e++; 3694 7516 } 3695 putenv((char *)version_str); /* reinstate HUSH_VERSION */ 7517 /* (Re)insert HUSH_VERSION into env (AFTER we scanned the env!) */ 7518 debug_printf_env("putenv '%s'\n", shell_ver->varstr); 7519 putenv(shell_ver->varstr); 7520 7521 /* Export PWD */ 7522 set_pwd_var(/*exp:*/ 1); 7523 /* bash also exports SHLVL and _, 7524 * and sets (but doesn't export) the following variables: 7525 * BASH=/bin/bash 7526 * BASH_VERSINFO=([0]="3" [1]="2" [2]="0" [3]="1" [4]="release" [5]="i386-pc-linux-gnu") 7527 * BASH_VERSION='3.2.0(1)-release' 7528 * HOSTTYPE=i386 7529 * MACHTYPE=i386-pc-linux-gnu 7530 * OSTYPE=linux-gnu 7531 * HOSTNAME=<xxxxxxxxxx> 7532 * PPID=<NNNNN> - we also do it elsewhere 7533 * EUID=<NNNNN> 7534 * UID=<NNNNN> 7535 * GROUPS=() 7536 * LINES=<NNN> 7537 * COLUMNS=<NNN> 7538 * BASH_ARGC=() 7539 * BASH_ARGV=() 7540 * BASH_LINENO=() 7541 * BASH_SOURCE=() 7542 * DIRSTACK=() 7543 * PIPESTATUS=([0]="0") 7544 * HISTFILE=/<xxx>/.bash_history 7545 * HISTFILESIZE=500 7546 * HISTSIZE=500 7547 * MAILCHECK=60 7548 * PATH=/usr/gnu/bin:/usr/local/bin:/bin:/usr/bin:. 7549 * SHELL=/bin/bash 7550 * SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor 7551 * TERM=dumb 7552 * OPTERR=1 7553 * OPTIND=1 7554 * IFS=$' \t\n' 7555 * PS1='\s-\v\$ ' 7556 * PS2='> ' 7557 * PS4='+ ' 7558 */ 3696 7559 3697 7560 #if ENABLE_FEATURE_EDITING 3698 line_input_state = new_line_input_t(FOR_SHELL); 3699 #endif 3700 /* XXX what should these be while sourcing /etc/profile? */ 3701 global_argc = argc; 3702 global_argv = argv; 7561 G.line_input_state = new_line_input_t(FOR_SHELL); 7562 # if defined MAX_HISTORY && MAX_HISTORY > 0 && ENABLE_HUSH_SAVEHISTORY 7563 { 7564 const char *hp = get_local_var_value("HISTFILE"); 7565 if (!hp) { 7566 hp = get_local_var_value("HOME"); 7567 if (hp) { 7568 G.line_input_state->hist_file = concat_path_file(hp, ".hush_history"); 7569 //set_local_var(xasprintf("HISTFILE=%s", ...)); 7570 } 7571 } 7572 } 7573 # endif 7574 #endif 7575 7576 G.global_argc = argc; 7577 G.global_argv = argv; 3703 7578 /* Initialize some more globals to non-zero values */ 3704 set_cwd(); 3705 #if ENABLE_HUSH_INTERACTIVE 3706 #if ENABLE_FEATURE_EDITING 3707 cmdedit_set_initial_prompt(); 3708 #endif 3709 PS2 = "> "; 3710 #endif 3711 3712 if (EXIT_SUCCESS) /* otherwise is already done */ 3713 last_return_code = EXIT_SUCCESS; 3714 3715 if (argv[0] && argv[0][0] == '-') { 3716 debug_printf("sourcing /etc/profile\n"); 3717 input = fopen("/etc/profile", "r"); 3718 if (input != NULL) { 3719 mark_open(fileno(input)); 3720 parse_and_run_file(input); 3721 mark_closed(fileno(input)); 3722 fclose(input); 3723 } 3724 } 3725 input = stdin; 3726 3727 while ((opt = getopt(argc, argv, "c:xif")) > 0) { 7579 cmdedit_update_prompt(); 7580 7581 if (setjmp(die_jmp)) { 7582 /* xfunc has failed! die die die */ 7583 /* no EXIT traps, this is an escape hatch! */ 7584 G.exiting = 1; 7585 hush_exit(xfunc_error_retval); 7586 } 7587 7588 /* Shell is non-interactive at first. We need to call 7589 * init_sigmasks() if we are going to execute "sh <script>", 7590 * "sh -c <cmds>" or login shell's /etc/profile and friends. 7591 * If we later decide that we are interactive, we run init_sigmasks() 7592 * in order to intercept (more) signals. 7593 */ 7594 7595 /* Parse options */ 7596 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */ 7597 builtin_argc = 0; 7598 while (1) { 7599 opt = getopt(argc, argv, "+c:xins" 7600 #if !BB_MMU 7601 "<:$:R:V:" 7602 # if ENABLE_HUSH_FUNCTIONS 7603 "F:" 7604 # endif 7605 #endif 7606 ); 7607 if (opt <= 0) 7608 break; 3728 7609 switch (opt) { 3729 7610 case 'c': 3730 global_argv = argv + optind; 3731 global_argc = argc - optind; 3732 opt = parse_and_run_string(optarg, PARSEFLAG_SEMICOLON); 7611 /* Possibilities: 7612 * sh ... -c 'script' 7613 * sh ... -c 'script' ARG0 [ARG1...] 7614 * On NOMMU, if builtin_argc != 0, 7615 * sh ... -c 'builtin' BARGV... "" ARG0 [ARG1...] 7616 * "" needs to be replaced with NULL 7617 * and BARGV vector fed to builtin function. 7618 * Note: the form without ARG0 never happens: 7619 * sh ... -c 'builtin' BARGV... "" 7620 */ 7621 if (!G.root_pid) { 7622 G.root_pid = getpid(); 7623 G.root_ppid = getppid(); 7624 } 7625 G.global_argv = argv + optind; 7626 G.global_argc = argc - optind; 7627 if (builtin_argc) { 7628 /* -c 'builtin' [BARGV...] "" ARG0 [ARG1...] */ 7629 const struct built_in_command *x; 7630 7631 init_sigmasks(); 7632 x = find_builtin(optarg); 7633 if (x) { /* paranoia */ 7634 G.global_argc -= builtin_argc; /* skip [BARGV...] "" */ 7635 G.global_argv += builtin_argc; 7636 G.global_argv[-1] = NULL; /* replace "" */ 7637 G.last_exitcode = x->b_function(argv + optind - 1); 7638 } 7639 goto final_return; 7640 } 7641 if (!G.global_argv[0]) { 7642 /* -c 'script' (no params): prevent empty $0 */ 7643 G.global_argv--; /* points to argv[i] of 'script' */ 7644 G.global_argv[0] = argv[0]; 7645 G.global_argc++; 7646 } /* else -c 'script' ARG0 [ARG1...]: $0 is ARG0 */ 7647 init_sigmasks(); 7648 parse_and_run_string(optarg); 3733 7649 goto final_return; 3734 7650 case 'i': 3735 7651 /* Well, we cannot just declare interactiveness, 3736 7652 * we have to have some stuff (ctty, etc) */ 3737 /* interactive_fd++; */7653 /* G_interactive_fd++; */ 3738 7654 break; 3739 case 'f': 3740 fake_mode = 1; 7655 case 's': 7656 /* "-s" means "read from stdin", but this is how we always 7657 * operate, so simply do nothing here. */ 3741 7658 break; 7659 #if !BB_MMU 7660 case '<': /* "big heredoc" support */ 7661 full_write1_str(optarg); 7662 _exit(0); 7663 case '$': { 7664 unsigned long long empty_trap_mask; 7665 7666 G.root_pid = bb_strtou(optarg, &optarg, 16); 7667 optarg++; 7668 G.root_ppid = bb_strtou(optarg, &optarg, 16); 7669 optarg++; 7670 G.last_bg_pid = bb_strtou(optarg, &optarg, 16); 7671 optarg++; 7672 G.last_exitcode = bb_strtou(optarg, &optarg, 16); 7673 optarg++; 7674 builtin_argc = bb_strtou(optarg, &optarg, 16); 7675 optarg++; 7676 empty_trap_mask = bb_strtoull(optarg, &optarg, 16); 7677 if (empty_trap_mask != 0) { 7678 int sig; 7679 init_sigmasks(); 7680 G.traps = xzalloc(sizeof(G.traps[0]) * NSIG); 7681 for (sig = 1; sig < NSIG; sig++) { 7682 if (empty_trap_mask & (1LL << sig)) { 7683 G.traps[sig] = xzalloc(1); /* == xstrdup(""); */ 7684 sigaddset(&G.blocked_set, sig); 7685 } 7686 } 7687 sigprocmask(SIG_SETMASK, &G.blocked_set, NULL); 7688 } 7689 # if ENABLE_HUSH_LOOPS 7690 optarg++; 7691 G.depth_of_loop = bb_strtou(optarg, &optarg, 16); 7692 # endif 7693 break; 7694 } 7695 case 'R': 7696 case 'V': 7697 set_local_var(xstrdup(optarg), /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ opt == 'R'); 7698 break; 7699 # if ENABLE_HUSH_FUNCTIONS 7700 case 'F': { 7701 struct function *funcp = new_function(optarg); 7702 /* funcp->name is already set to optarg */ 7703 /* funcp->body is set to NULL. It's a special case. */ 7704 funcp->body_as_string = argv[optind]; 7705 optind++; 7706 break; 7707 } 7708 # endif 7709 #endif 7710 case 'n': 7711 case 'x': 7712 if (set_mode(1, opt, NULL) == 0) /* no error */ 7713 break; 3742 7714 default: 3743 7715 #ifndef BB_VER … … 3749 7721 #endif 3750 7722 } 3751 } 3752 #if ENABLE_HUSH_JOB 3753 /* A shell is interactive if the '-i' flag was given, or if all of 3754 * the following conditions are met: 7723 } /* option parsing loop */ 7724 7725 if (!G.root_pid) { 7726 G.root_pid = getpid(); 7727 G.root_ppid = getppid(); 7728 } 7729 7730 /* If we are login shell... */ 7731 if (argv[0] && argv[0][0] == '-') { 7732 FILE *input; 7733 debug_printf("sourcing /etc/profile\n"); 7734 input = fopen_for_read("/etc/profile"); 7735 if (input != NULL) { 7736 close_on_exec_on(fileno(input)); 7737 init_sigmasks(); 7738 parse_and_run_file(input); 7739 fclose(input); 7740 } 7741 /* bash: after sourcing /etc/profile, 7742 * tries to source (in the given order): 7743 * ~/.bash_profile, ~/.bash_login, ~/.profile, 7744 * stopping on first found. --noprofile turns this off. 7745 * bash also sources ~/.bash_logout on exit. 7746 * If called as sh, skips .bash_XXX files. 7747 */ 7748 } 7749 7750 if (argv[optind]) { 7751 FILE *input; 7752 /* 7753 * "bash <script>" (which is never interactive (unless -i?)) 7754 * sources $BASH_ENV here (without scanning $PATH). 7755 * If called as sh, does the same but with $ENV. 7756 */ 7757 debug_printf("running script '%s'\n", argv[optind]); 7758 G.global_argv = argv + optind; 7759 G.global_argc = argc - optind; 7760 input = xfopen_for_read(argv[optind]); 7761 close_on_exec_on(fileno(input)); 7762 init_sigmasks(); 7763 parse_and_run_file(input); 7764 #if ENABLE_FEATURE_CLEAN_UP 7765 fclose(input); 7766 #endif 7767 goto final_return; 7768 } 7769 7770 /* Up to here, shell was non-interactive. Now it may become one. 7771 * NB: don't forget to (re)run init_sigmasks() as needed. 7772 */ 7773 7774 /* A shell is interactive if the '-i' flag was given, 7775 * or if all of the following conditions are met: 3755 7776 * no -c command 3756 7777 * no arguments remaining or the -s flag given 3757 7778 * standard input is a terminal 3758 7779 * standard output is a terminal 3759 * Refer to Posix.2, the description of the 'sh' utility. */ 3760 if (argv[optind] == NULL && input == stdin 3761 && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) 3762 ) { 3763 saved_tty_pgrp = tcgetpgrp(STDIN_FILENO); 3764 debug_printf("saved_tty_pgrp=%d\n", saved_tty_pgrp); 3765 if (saved_tty_pgrp >= 0) { 3766 /* try to dup to high fd#, >= 255 */ 3767 interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255); 3768 if (interactive_fd < 0) { 3769 /* try to dup to any fd */ 3770 interactive_fd = dup(STDIN_FILENO); 3771 if (interactive_fd < 0) 3772 /* give up */ 3773 interactive_fd = 0; 3774 } 3775 // TODO: track & disallow any attempts of user 3776 // to (inadvertently) close/redirect it 3777 } 3778 } 3779 debug_printf("interactive_fd=%d\n", interactive_fd); 3780 if (interactive_fd) { 3781 /* Looks like they want an interactive shell */ 3782 setup_job_control(); 3783 /* Make xfuncs do cleanup on exit */ 3784 die_sleep = -1; /* flag */ 3785 // FIXME: should we reset die_sleep = 0 whereever we fork? 3786 if (setjmp(die_jmp)) { 3787 /* xfunc has failed! die die die */ 3788 hush_exit(xfunc_error_retval); 3789 } 3790 #if !ENABLE_FEATURE_SH_EXTRA_QUIET 3791 printf("\n\n%s hush - the humble shell v"HUSH_VER_STR"\n", bb_banner); 3792 printf("Enter 'help' for a list of built-in commands.\n\n"); 3793 #endif 7780 * Refer to Posix.2, the description of the 'sh' utility. 7781 */ 7782 #if ENABLE_HUSH_JOB 7783 if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) { 7784 G_saved_tty_pgrp = tcgetpgrp(STDIN_FILENO); 7785 debug_printf("saved_tty_pgrp:%d\n", G_saved_tty_pgrp); 7786 if (G_saved_tty_pgrp < 0) 7787 G_saved_tty_pgrp = 0; 7788 7789 /* try to dup stdin to high fd#, >= 255 */ 7790 G_interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255); 7791 if (G_interactive_fd < 0) { 7792 /* try to dup to any fd */ 7793 G_interactive_fd = dup(STDIN_FILENO); 7794 if (G_interactive_fd < 0) { 7795 /* give up */ 7796 G_interactive_fd = 0; 7797 G_saved_tty_pgrp = 0; 7798 } 7799 } 7800 // TODO: track & disallow any attempts of user 7801 // to (inadvertently) close/redirect G_interactive_fd 7802 } 7803 debug_printf("interactive_fd:%d\n", G_interactive_fd); 7804 if (G_interactive_fd) { 7805 close_on_exec_on(G_interactive_fd); 7806 7807 if (G_saved_tty_pgrp) { 7808 /* If we were run as 'hush &', sleep until we are 7809 * in the foreground (tty pgrp == our pgrp). 7810 * If we get started under a job aware app (like bash), 7811 * make sure we are now in charge so we don't fight over 7812 * who gets the foreground */ 7813 while (1) { 7814 pid_t shell_pgrp = getpgrp(); 7815 G_saved_tty_pgrp = tcgetpgrp(G_interactive_fd); 7816 if (G_saved_tty_pgrp == shell_pgrp) 7817 break; 7818 /* send TTIN to ourself (should stop us) */ 7819 kill(- shell_pgrp, SIGTTIN); 7820 } 7821 } 7822 7823 /* Block some signals */ 7824 init_sigmasks(); 7825 7826 if (G_saved_tty_pgrp) { 7827 /* Set other signals to restore saved_tty_pgrp */ 7828 set_fatal_handlers(); 7829 /* Put ourselves in our own process group 7830 * (bash, too, does this only if ctty is available) */ 7831 bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */ 7832 /* Grab control of the terminal */ 7833 tcsetpgrp(G_interactive_fd, getpid()); 7834 } 7835 /* -1 is special - makes xfuncs longjmp, not exit 7836 * (we reset die_sleep = 0 whereever we [v]fork) */ 7837 enable_restore_tty_pgrp_on_exit(); /* sets die_sleep = -1 */ 7838 } else { 7839 init_sigmasks(); 3794 7840 } 3795 7841 #elif ENABLE_HUSH_INTERACTIVE 3796 /* no job control compiled, only prompt/line editing */ 3797 if (argv[optind] == NULL && input == stdin 3798 && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) 3799 ) { 3800 interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255); 3801 if (interactive_fd < 0) { 7842 /* No job control compiled in, only prompt/line editing */ 7843 if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) { 7844 G_interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255); 7845 if (G_interactive_fd < 0) { 3802 7846 /* try to dup to any fd */ 3803 interactive_fd = dup(STDIN_FILENO);3804 if ( interactive_fd < 0)7847 G_interactive_fd = dup(STDIN_FILENO); 7848 if (G_interactive_fd < 0) 3805 7849 /* give up */ 3806 interactive_fd = 0; 3807 } 3808 } 3809 3810 #endif 3811 3812 if (argv[optind] == NULL) { 3813 opt = parse_and_run_file(stdin); 3814 goto final_return; 3815 } 3816 3817 debug_printf("\nrunning script '%s'\n", argv[optind]); 3818 global_argv = argv + optind; 3819 global_argc = argc - optind; 3820 input = xfopen(argv[optind], "r"); 3821 opt = parse_and_run_file(input); 7850 G_interactive_fd = 0; 7851 } 7852 } 7853 if (G_interactive_fd) { 7854 close_on_exec_on(G_interactive_fd); 7855 } 7856 init_sigmasks(); 7857 #else 7858 /* We have interactiveness code disabled */ 7859 init_sigmasks(); 7860 #endif 7861 /* bash: 7862 * if interactive but not a login shell, sources ~/.bashrc 7863 * (--norc turns this off, --rcfile <file> overrides) 7864 */ 7865 7866 if (!ENABLE_FEATURE_SH_EXTRA_QUIET && G_interactive_fd) { 7867 /* note: ash and hush share this string */ 7868 printf("\n\n%s %s\n" 7869 IF_HUSH_HELP("Enter 'help' for a list of built-in commands.\n") 7870 "\n", 7871 bb_banner, 7872 "hush - the humble shell" 7873 ); 7874 } 7875 7876 parse_and_run_file(stdin); 3822 7877 3823 7878 final_return: 3824 3825 #if ENABLE_FEATURE_CLEAN_UP 7879 hush_exit(G.last_exitcode); 7880 } 7881 7882 7883 #if ENABLE_MSH 7884 int msh_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 7885 int msh_main(int argc, char **argv) 7886 { 7887 //bb_error_msg("msh is deprecated, please use hush instead"); 7888 return hush_main(argc, argv); 7889 } 7890 #endif 7891 7892 7893 /* 7894 * Built-ins 7895 */ 7896 static int FAST_FUNC builtin_true(char **argv UNUSED_PARAM) 7897 { 7898 return 0; 7899 } 7900 7901 static int run_applet_main(char **argv, int (*applet_main_func)(int argc, char **argv)) 7902 { 7903 int argc = 0; 7904 while (*argv) { 7905 argc++; 7906 argv++; 7907 } 7908 return applet_main_func(argc, argv - argc); 7909 } 7910 7911 static int FAST_FUNC builtin_test(char **argv) 7912 { 7913 return run_applet_main(argv, test_main); 7914 } 7915 7916 static int FAST_FUNC builtin_echo(char **argv) 7917 { 7918 return run_applet_main(argv, echo_main); 7919 } 7920 7921 #if ENABLE_PRINTF 7922 static int FAST_FUNC builtin_printf(char **argv) 7923 { 7924 return run_applet_main(argv, printf_main); 7925 } 7926 #endif 7927 7928 static char **skip_dash_dash(char **argv) 7929 { 7930 argv++; 7931 if (argv[0] && argv[0][0] == '-' && argv[0][1] == '-' && argv[0][2] == '\0') 7932 argv++; 7933 return argv; 7934 } 7935 7936 static int FAST_FUNC builtin_eval(char **argv) 7937 { 7938 int rcode = EXIT_SUCCESS; 7939 7940 argv = skip_dash_dash(argv); 7941 if (*argv) { 7942 char *str = expand_strvec_to_string(argv); 7943 /* bash: 7944 * eval "echo Hi; done" ("done" is syntax error): 7945 * "echo Hi" will not execute too. 7946 */ 7947 parse_and_run_string(str); 7948 free(str); 7949 rcode = G.last_exitcode; 7950 } 7951 return rcode; 7952 } 7953 7954 static int FAST_FUNC builtin_cd(char **argv) 7955 { 7956 const char *newdir; 7957 7958 argv = skip_dash_dash(argv); 7959 newdir = argv[0]; 7960 if (newdir == NULL) { 7961 /* bash does nothing (exitcode 0) if HOME is ""; if it's unset, 7962 * bash says "bash: cd: HOME not set" and does nothing 7963 * (exitcode 1) 7964 */ 7965 const char *home = get_local_var_value("HOME"); 7966 newdir = home ? home : "/"; 7967 } 7968 if (chdir(newdir)) { 7969 /* Mimic bash message exactly */ 7970 bb_perror_msg("cd: %s", newdir); 7971 return EXIT_FAILURE; 7972 } 7973 /* Read current dir (get_cwd(1) is inside) and set PWD. 7974 * Note: do not enforce exporting. If PWD was unset or unexported, 7975 * set it again, but do not export. bash does the same. 7976 */ 7977 set_pwd_var(/*exp:*/ 0); 7978 return EXIT_SUCCESS; 7979 } 7980 7981 static int FAST_FUNC builtin_exec(char **argv) 7982 { 7983 argv = skip_dash_dash(argv); 7984 if (argv[0] == NULL) 7985 return EXIT_SUCCESS; /* bash does this */ 7986 7987 /* Careful: we can end up here after [v]fork. Do not restore 7988 * tty pgrp then, only top-level shell process does that */ 7989 if (G_saved_tty_pgrp && getpid() == G.root_pid) 7990 tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp); 7991 7992 /* TODO: if exec fails, bash does NOT exit! We do. 7993 * We'll need to undo sigprocmask (it's inside execvp_or_die) 7994 * and tcsetpgrp, and this is inherently racy. 7995 */ 7996 execvp_or_die(argv); 7997 } 7998 7999 static int FAST_FUNC builtin_exit(char **argv) 8000 { 8001 debug_printf_exec("%s()\n", __func__); 8002 8003 /* interactive bash: 8004 * # trap "echo EEE" EXIT 8005 * # exit 8006 * exit 8007 * There are stopped jobs. 8008 * (if there are _stopped_ jobs, running ones don't count) 8009 * # exit 8010 * exit 8011 # EEE (then bash exits) 8012 * 8013 * TODO: we can use G.exiting = -1 as indicator "last cmd was exit" 8014 */ 8015 8016 /* note: EXIT trap is run by hush_exit */ 8017 argv = skip_dash_dash(argv); 8018 if (argv[0] == NULL) 8019 hush_exit(G.last_exitcode); 8020 /* mimic bash: exit 123abc == exit 255 + error msg */ 8021 xfunc_error_retval = 255; 8022 /* bash: exit -2 == exit 254, no error msg */ 8023 hush_exit(xatoi(argv[0]) & 0xff); 8024 } 8025 8026 static void print_escaped(const char *s) 8027 { 8028 if (*s == '\'') 8029 goto squote; 8030 do { 8031 const char *p = strchrnul(s, '\''); 8032 /* print 'xxxx', possibly just '' */ 8033 printf("'%.*s'", (int)(p - s), s); 8034 if (*p == '\0') 8035 break; 8036 s = p; 8037 squote: 8038 /* s points to '; print "'''...'''" */ 8039 putchar('"'); 8040 do putchar('\''); while (*++s == '\''); 8041 putchar('"'); 8042 } while (*s); 8043 } 8044 8045 #if !ENABLE_HUSH_LOCAL 8046 #define helper_export_local(argv, exp, lvl) \ 8047 helper_export_local(argv, exp) 8048 #endif 8049 static void helper_export_local(char **argv, int exp, int lvl) 8050 { 8051 do { 8052 char *name = *argv; 8053 char *name_end = strchrnul(name, '='); 8054 8055 /* So far we do not check that name is valid (TODO?) */ 8056 8057 if (*name_end == '\0') { 8058 struct variable *var, **vpp; 8059 8060 vpp = get_ptr_to_local_var(name, name_end - name); 8061 var = vpp ? *vpp : NULL; 8062 8063 if (exp == -1) { /* unexporting? */ 8064 /* export -n NAME (without =VALUE) */ 8065 if (var) { 8066 var->flg_export = 0; 8067 debug_printf_env("%s: unsetenv '%s'\n", __func__, name); 8068 unsetenv(name); 8069 } /* else: export -n NOT_EXISTING_VAR: no-op */ 8070 continue; 8071 } 8072 if (exp == 1) { /* exporting? */ 8073 /* export NAME (without =VALUE) */ 8074 if (var) { 8075 var->flg_export = 1; 8076 debug_printf_env("%s: putenv '%s'\n", __func__, var->varstr); 8077 putenv(var->varstr); 8078 continue; 8079 } 8080 } 8081 /* Exporting non-existing variable. 8082 * bash does not put it in environment, 8083 * but remembers that it is exported, 8084 * and does put it in env when it is set later. 8085 * We just set it to "" and export. */ 8086 /* Or, it's "local NAME" (without =VALUE). 8087 * bash sets the value to "". */ 8088 name = xasprintf("%s=", name); 8089 } else { 8090 /* (Un)exporting/making local NAME=VALUE */ 8091 name = xstrdup(name); 8092 } 8093 set_local_var(name, /*exp:*/ exp, /*lvl:*/ lvl, /*ro:*/ 0); 8094 } while (*++argv); 8095 } 8096 8097 static int FAST_FUNC builtin_export(char **argv) 8098 { 8099 unsigned opt_unexport; 8100 8101 #if ENABLE_HUSH_EXPORT_N 8102 /* "!": do not abort on errors */ 8103 opt_unexport = getopt32(argv, "!n"); 8104 if (opt_unexport == (uint32_t)-1) 8105 return EXIT_FAILURE; 8106 argv += optind; 8107 #else 8108 opt_unexport = 0; 8109 argv++; 8110 #endif 8111 8112 if (argv[0] == NULL) { 8113 char **e = environ; 8114 if (e) { 8115 while (*e) { 8116 #if 0 8117 puts(*e++); 8118 #else 8119 /* ash emits: export VAR='VAL' 8120 * bash: declare -x VAR="VAL" 8121 * we follow ash example */ 8122 const char *s = *e++; 8123 const char *p = strchr(s, '='); 8124 8125 if (!p) /* wtf? take next variable */ 8126 continue; 8127 /* export var= */ 8128 printf("export %.*s", (int)(p - s) + 1, s); 8129 print_escaped(p + 1); 8130 putchar('\n'); 8131 #endif 8132 } 8133 /*fflush_all(); - done after each builtin anyway */ 8134 } 8135 return EXIT_SUCCESS; 8136 } 8137 8138 helper_export_local(argv, (opt_unexport ? -1 : 1), 0); 8139 8140 return EXIT_SUCCESS; 8141 } 8142 8143 #if ENABLE_HUSH_LOCAL 8144 static int FAST_FUNC builtin_local(char **argv) 8145 { 8146 if (G.func_nest_level == 0) { 8147 bb_error_msg("%s: not in a function", argv[0]); 8148 return EXIT_FAILURE; /* bash compat */ 8149 } 8150 helper_export_local(argv, 0, G.func_nest_level); 8151 return EXIT_SUCCESS; 8152 } 8153 #endif 8154 8155 static int FAST_FUNC builtin_trap(char **argv) 8156 { 8157 int sig; 8158 char *new_cmd; 8159 8160 if (!G.traps) 8161 G.traps = xzalloc(sizeof(G.traps[0]) * NSIG); 8162 8163 argv++; 8164 if (!*argv) { 8165 int i; 8166 /* No args: print all trapped */ 8167 for (i = 0; i < NSIG; ++i) { 8168 if (G.traps[i]) { 8169 printf("trap -- "); 8170 print_escaped(G.traps[i]); 8171 /* note: bash adds "SIG", but only if invoked 8172 * as "bash". If called as "sh", or if set -o posix, 8173 * then it prints short signal names. 8174 * We are printing short names: */ 8175 printf(" %s\n", get_signame(i)); 8176 } 8177 } 8178 /*fflush_all(); - done after each builtin anyway */ 8179 return EXIT_SUCCESS; 8180 } 8181 8182 new_cmd = NULL; 8183 /* If first arg is a number: reset all specified signals */ 8184 sig = bb_strtou(*argv, NULL, 10); 8185 if (errno == 0) { 8186 int ret; 8187 process_sig_list: 8188 ret = EXIT_SUCCESS; 8189 while (*argv) { 8190 sig = get_signum(*argv++); 8191 if (sig < 0 || sig >= NSIG) { 8192 ret = EXIT_FAILURE; 8193 /* Mimic bash message exactly */ 8194 bb_perror_msg("trap: %s: invalid signal specification", argv[-1]); 8195 continue; 8196 } 8197 8198 free(G.traps[sig]); 8199 G.traps[sig] = xstrdup(new_cmd); 8200 8201 debug_printf("trap: setting SIG%s (%i) to '%s'\n", 8202 get_signame(sig), sig, G.traps[sig]); 8203 8204 /* There is no signal for 0 (EXIT) */ 8205 if (sig == 0) 8206 continue; 8207 8208 if (new_cmd) { 8209 sigaddset(&G.blocked_set, sig); 8210 } else { 8211 /* There was a trap handler, we are removing it 8212 * (if sig has non-DFL handling, 8213 * we don't need to do anything) */ 8214 if (sig < 32 && (G.non_DFL_mask & (1 << sig))) 8215 continue; 8216 sigdelset(&G.blocked_set, sig); 8217 } 8218 } 8219 sigprocmask(SIG_SETMASK, &G.blocked_set, NULL); 8220 return ret; 8221 } 8222 8223 if (!argv[1]) { /* no second arg */ 8224 bb_error_msg("trap: invalid arguments"); 8225 return EXIT_FAILURE; 8226 } 8227 8228 /* First arg is "-": reset all specified to default */ 8229 /* First arg is "--": skip it, the rest is "handler SIGs..." */ 8230 /* Everything else: set arg as signal handler 8231 * (includes "" case, which ignores signal) */ 8232 if (argv[0][0] == '-') { 8233 if (argv[0][1] == '\0') { /* "-" */ 8234 /* new_cmd remains NULL: "reset these sigs" */ 8235 goto reset_traps; 8236 } 8237 if (argv[0][1] == '-' && argv[0][2] == '\0') { /* "--" */ 8238 argv++; 8239 } 8240 /* else: "-something", no special meaning */ 8241 } 8242 new_cmd = *argv; 8243 reset_traps: 8244 argv++; 8245 goto process_sig_list; 8246 } 8247 8248 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */ 8249 static int FAST_FUNC builtin_type(char **argv) 8250 { 8251 int ret = EXIT_SUCCESS; 8252 8253 while (*++argv) { 8254 const char *type; 8255 char *path = NULL; 8256 8257 if (0) {} /* make conditional compile easier below */ 8258 /*else if (find_alias(*argv)) 8259 type = "an alias";*/ 8260 #if ENABLE_HUSH_FUNCTIONS 8261 else if (find_function(*argv)) 8262 type = "a function"; 8263 #endif 8264 else if (find_builtin(*argv)) 8265 type = "a shell builtin"; 8266 else if ((path = find_in_path(*argv)) != NULL) 8267 type = path; 8268 else { 8269 bb_error_msg("type: %s: not found", *argv); 8270 ret = EXIT_FAILURE; 8271 continue; 8272 } 8273 8274 printf("%s is %s\n", *argv, type); 8275 free(path); 8276 } 8277 8278 return ret; 8279 } 8280 8281 #if ENABLE_HUSH_JOB 8282 /* built-in 'fg' and 'bg' handler */ 8283 static int FAST_FUNC builtin_fg_bg(char **argv) 8284 { 8285 int i, jobnum; 8286 struct pipe *pi; 8287 8288 if (!G_interactive_fd) 8289 return EXIT_FAILURE; 8290 8291 /* If they gave us no args, assume they want the last backgrounded task */ 8292 if (!argv[1]) { 8293 for (pi = G.job_list; pi; pi = pi->next) { 8294 if (pi->jobid == G.last_jobid) { 8295 goto found; 8296 } 8297 } 8298 bb_error_msg("%s: no current job", argv[0]); 8299 return EXIT_FAILURE; 8300 } 8301 if (sscanf(argv[1], "%%%d", &jobnum) != 1) { 8302 bb_error_msg("%s: bad argument '%s'", argv[0], argv[1]); 8303 return EXIT_FAILURE; 8304 } 8305 for (pi = G.job_list; pi; pi = pi->next) { 8306 if (pi->jobid == jobnum) { 8307 goto found; 8308 } 8309 } 8310 bb_error_msg("%s: %d: no such job", argv[0], jobnum); 8311 return EXIT_FAILURE; 8312 found: 8313 /* TODO: bash prints a string representation 8314 * of job being foregrounded (like "sleep 1 | cat") */ 8315 if (argv[0][0] == 'f' && G_saved_tty_pgrp) { 8316 /* Put the job into the foreground. */ 8317 tcsetpgrp(G_interactive_fd, pi->pgrp); 8318 } 8319 8320 /* Restart the processes in the job */ 8321 debug_printf_jobs("reviving %d procs, pgrp %d\n", pi->num_cmds, pi->pgrp); 8322 for (i = 0; i < pi->num_cmds; i++) { 8323 debug_printf_jobs("reviving pid %d\n", pi->cmds[i].pid); 8324 pi->cmds[i].is_stopped = 0; 8325 } 8326 pi->stopped_cmds = 0; 8327 8328 i = kill(- pi->pgrp, SIGCONT); 8329 if (i < 0) { 8330 if (errno == ESRCH) { 8331 delete_finished_bg_job(pi); 8332 return EXIT_SUCCESS; 8333 } 8334 bb_perror_msg("kill (SIGCONT)"); 8335 } 8336 8337 if (argv[0][0] == 'f') { 8338 remove_bg_job(pi); 8339 return checkjobs_and_fg_shell(pi); 8340 } 8341 return EXIT_SUCCESS; 8342 } 8343 #endif 8344 8345 #if ENABLE_HUSH_HELP 8346 static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM) 8347 { 8348 const struct built_in_command *x; 8349 8350 printf( 8351 "Built-in commands:\n" 8352 "------------------\n"); 8353 for (x = bltins1; x != &bltins1[ARRAY_SIZE(bltins1)]; x++) { 8354 if (x->b_descr) 8355 printf("%-10s%s\n", x->b_cmd, x->b_descr); 8356 } 8357 bb_putchar('\n'); 8358 return EXIT_SUCCESS; 8359 } 8360 #endif 8361 8362 #if ENABLE_HUSH_JOB 8363 static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM) 8364 { 8365 struct pipe *job; 8366 const char *status_string; 8367 8368 for (job = G.job_list; job; job = job->next) { 8369 if (job->alive_cmds == job->stopped_cmds) 8370 status_string = "Stopped"; 8371 else 8372 status_string = "Running"; 8373 8374 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->cmdtext); 8375 } 8376 return EXIT_SUCCESS; 8377 } 8378 #endif 8379 8380 #if HUSH_DEBUG 8381 static int FAST_FUNC builtin_memleak(char **argv UNUSED_PARAM) 8382 { 8383 void *p; 8384 unsigned long l; 8385 8386 # ifdef M_TRIM_THRESHOLD 8387 /* Optional. Reduces probability of false positives */ 8388 malloc_trim(0); 8389 # endif 8390 /* Crude attempt to find where "free memory" starts, 8391 * sans fragmentation. */ 8392 p = malloc(240); 8393 l = (unsigned long)p; 8394 free(p); 8395 p = malloc(3400); 8396 if (l < (unsigned long)p) l = (unsigned long)p; 8397 free(p); 8398 8399 if (!G.memleak_value) 8400 G.memleak_value = l; 8401 8402 l -= G.memleak_value; 8403 if ((long)l < 0) 8404 l = 0; 8405 l /= 1024; 8406 if (l > 127) 8407 l = 127; 8408 8409 /* Exitcode is "how many kilobytes we leaked since 1st call" */ 8410 return l; 8411 } 8412 #endif 8413 8414 static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM) 8415 { 8416 puts(get_cwd(0)); 8417 return EXIT_SUCCESS; 8418 } 8419 8420 static int FAST_FUNC builtin_read(char **argv) 8421 { 8422 const char *r; 8423 char *opt_n = NULL; 8424 char *opt_p = NULL; 8425 char *opt_t = NULL; 8426 char *opt_u = NULL; 8427 int read_flags; 8428 8429 /* "!": do not abort on errors. 8430 * Option string must start with "sr" to match BUILTIN_READ_xxx 8431 */ 8432 read_flags = getopt32(argv, "!srn:p:t:u:", &opt_n, &opt_p, &opt_t, &opt_u); 8433 if (read_flags == (uint32_t)-1) 8434 return EXIT_FAILURE; 8435 argv += optind; 8436 8437 r = shell_builtin_read(set_local_var_from_halves, 8438 argv, 8439 get_local_var_value("IFS"), /* can be NULL */ 8440 read_flags, 8441 opt_n, 8442 opt_p, 8443 opt_t, 8444 opt_u 8445 ); 8446 8447 if ((uintptr_t)r > 1) { 8448 bb_error_msg("%s", r); 8449 r = (char*)(uintptr_t)1; 8450 } 8451 8452 return (uintptr_t)r; 8453 } 8454 8455 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set 8456 * built-in 'set' handler 8457 * SUSv3 says: 8458 * set [-abCefhmnuvx] [-o option] [argument...] 8459 * set [+abCefhmnuvx] [+o option] [argument...] 8460 * set -- [argument...] 8461 * set -o 8462 * set +o 8463 * Implementations shall support the options in both their hyphen and 8464 * plus-sign forms. These options can also be specified as options to sh. 8465 * Examples: 8466 * Write out all variables and their values: set 8467 * Set $1, $2, and $3 and set "$#" to 3: set c a b 8468 * Turn on the -x and -v options: set -xv 8469 * Unset all positional parameters: set -- 8470 * Set $1 to the value of x, even if it begins with '-' or '+': set -- "$x" 8471 * Set the positional parameters to the expansion of x, even if x expands 8472 * with a leading '-' or '+': set -- $x 8473 * 8474 * So far, we only support "set -- [argument...]" and some of the short names. 8475 */ 8476 static int FAST_FUNC builtin_set(char **argv) 8477 { 8478 int n; 8479 char **pp, **g_argv; 8480 char *arg = *++argv; 8481 8482 if (arg == NULL) { 8483 struct variable *e; 8484 for (e = G.top_var; e; e = e->next) 8485 puts(e->varstr); 8486 return EXIT_SUCCESS; 8487 } 8488 8489 do { 8490 if (strcmp(arg, "--") == 0) { 8491 ++argv; 8492 goto set_argv; 8493 } 8494 if (arg[0] != '+' && arg[0] != '-') 8495 break; 8496 for (n = 1; arg[n]; ++n) { 8497 if (set_mode((arg[0] == '-'), arg[n], argv[1])) 8498 goto error; 8499 if (arg[n] == 'o' && argv[1]) 8500 argv++; 8501 } 8502 } while ((arg = *++argv) != NULL); 8503 /* Now argv[0] is 1st argument */ 8504 8505 if (arg == NULL) 8506 return EXIT_SUCCESS; 8507 set_argv: 8508 8509 /* NB: G.global_argv[0] ($0) is never freed/changed */ 8510 g_argv = G.global_argv; 8511 if (G.global_args_malloced) { 8512 pp = g_argv; 8513 while (*++pp) 8514 free(*pp); 8515 g_argv[1] = NULL; 8516 } else { 8517 G.global_args_malloced = 1; 8518 pp = xzalloc(sizeof(pp[0]) * 2); 8519 pp[0] = g_argv[0]; /* retain $0 */ 8520 g_argv = pp; 8521 } 8522 /* This realloc's G.global_argv */ 8523 G.global_argv = pp = add_strings_to_strings(g_argv, argv, /*dup:*/ 1); 8524 8525 n = 1; 8526 while (*++pp) 8527 n++; 8528 G.global_argc = n; 8529 8530 return EXIT_SUCCESS; 8531 8532 /* Nothing known, so abort */ 8533 error: 8534 bb_error_msg("set: %s: invalid option", arg); 8535 return EXIT_FAILURE; 8536 } 8537 8538 static int FAST_FUNC builtin_shift(char **argv) 8539 { 8540 int n = 1; 8541 argv = skip_dash_dash(argv); 8542 if (argv[0]) { 8543 n = atoi(argv[0]); 8544 } 8545 if (n >= 0 && n < G.global_argc) { 8546 if (G.global_args_malloced) { 8547 int m = 1; 8548 while (m <= n) 8549 free(G.global_argv[m++]); 8550 } 8551 G.global_argc -= n; 8552 memmove(&G.global_argv[1], &G.global_argv[n+1], 8553 G.global_argc * sizeof(G.global_argv[0])); 8554 return EXIT_SUCCESS; 8555 } 8556 return EXIT_FAILURE; 8557 } 8558 8559 static int FAST_FUNC builtin_source(char **argv) 8560 { 8561 char *arg_path, *filename; 8562 FILE *input; 8563 save_arg_t sv; 8564 #if ENABLE_HUSH_FUNCTIONS 8565 smallint sv_flg; 8566 #endif 8567 8568 argv = skip_dash_dash(argv); 8569 filename = argv[0]; 8570 if (!filename) { 8571 /* bash says: "bash: .: filename argument required" */ 8572 return 2; /* bash compat */ 8573 } 8574 arg_path = NULL; 8575 if (!strchr(filename, '/')) { 8576 arg_path = find_in_path(filename); 8577 if (arg_path) 8578 filename = arg_path; 8579 } 8580 input = fopen_or_warn(filename, "r"); 8581 free(arg_path); 8582 if (!input) { 8583 /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */ 8584 return EXIT_FAILURE; 8585 } 8586 close_on_exec_on(fileno(input)); 8587 8588 #if ENABLE_HUSH_FUNCTIONS 8589 sv_flg = G.flag_return_in_progress; 8590 /* "we are inside sourced file, ok to use return" */ 8591 G.flag_return_in_progress = -1; 8592 #endif 8593 save_and_replace_G_args(&sv, argv); 8594 8595 parse_and_run_file(input); 3826 8596 fclose(input); 3827 if (cwd != bb_msg_unknown) 3828 free((char*)cwd); 3829 cur_var = top_var->next; 3830 while (cur_var) { 3831 struct variable *tmp = cur_var; 3832 if (!cur_var->max_len) 3833 free(cur_var->varstr); 3834 cur_var = cur_var->next; 3835 free(tmp); 3836 } 3837 #endif 3838 hush_exit(opt ? opt : last_return_code); 3839 } 8597 8598 restore_G_args(&sv, argv); 8599 #if ENABLE_HUSH_FUNCTIONS 8600 G.flag_return_in_progress = sv_flg; 8601 #endif 8602 8603 return G.last_exitcode; 8604 } 8605 8606 static int FAST_FUNC builtin_umask(char **argv) 8607 { 8608 int rc; 8609 mode_t mask; 8610 8611 mask = umask(0); 8612 argv = skip_dash_dash(argv); 8613 if (argv[0]) { 8614 mode_t old_mask = mask; 8615 8616 mask ^= 0777; 8617 rc = bb_parse_mode(argv[0], &mask); 8618 mask ^= 0777; 8619 if (rc == 0) { 8620 mask = old_mask; 8621 /* bash messages: 8622 * bash: umask: 'q': invalid symbolic mode operator 8623 * bash: umask: 999: octal number out of range 8624 */ 8625 bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]); 8626 } 8627 } else { 8628 rc = 1; 8629 /* Mimic bash */ 8630 printf("%04o\n", (unsigned) mask); 8631 /* fall through and restore mask which we set to 0 */ 8632 } 8633 umask(mask); 8634 8635 return !rc; /* rc != 0 - success */ 8636 } 8637 8638 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#unset */ 8639 static int FAST_FUNC builtin_unset(char **argv) 8640 { 8641 int ret; 8642 unsigned opts; 8643 8644 /* "!": do not abort on errors */ 8645 /* "+": stop at 1st non-option */ 8646 opts = getopt32(argv, "!+vf"); 8647 if (opts == (unsigned)-1) 8648 return EXIT_FAILURE; 8649 if (opts == 3) { 8650 bb_error_msg("unset: -v and -f are exclusive"); 8651 return EXIT_FAILURE; 8652 } 8653 argv += optind; 8654 8655 ret = EXIT_SUCCESS; 8656 while (*argv) { 8657 if (!(opts & 2)) { /* not -f */ 8658 if (unset_local_var(*argv)) { 8659 /* unset <nonexistent_var> doesn't fail. 8660 * Error is when one tries to unset RO var. 8661 * Message was printed by unset_local_var. */ 8662 ret = EXIT_FAILURE; 8663 } 8664 } 8665 #if ENABLE_HUSH_FUNCTIONS 8666 else { 8667 unset_func(*argv); 8668 } 8669 #endif 8670 argv++; 8671 } 8672 return ret; 8673 } 8674 8675 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/wait.html */ 8676 static int FAST_FUNC builtin_wait(char **argv) 8677 { 8678 int ret = EXIT_SUCCESS; 8679 int status, sig; 8680 8681 argv = skip_dash_dash(argv); 8682 if (argv[0] == NULL) { 8683 /* Don't care about wait results */ 8684 /* Note 1: must wait until there are no more children */ 8685 /* Note 2: must be interruptible */ 8686 /* Examples: 8687 * $ sleep 3 & sleep 6 & wait 8688 * [1] 30934 sleep 3 8689 * [2] 30935 sleep 6 8690 * [1] Done sleep 3 8691 * [2] Done sleep 6 8692 * $ sleep 3 & sleep 6 & wait 8693 * [1] 30936 sleep 3 8694 * [2] 30937 sleep 6 8695 * [1] Done sleep 3 8696 * ^C <-- after ~4 sec from keyboard 8697 * $ 8698 */ 8699 sigaddset(&G.blocked_set, SIGCHLD); 8700 sigprocmask(SIG_SETMASK, &G.blocked_set, NULL); 8701 while (1) { 8702 checkjobs(NULL); 8703 if (errno == ECHILD) 8704 break; 8705 /* Wait for SIGCHLD or any other signal of interest */ 8706 /* sigtimedwait with infinite timeout: */ 8707 sig = sigwaitinfo(&G.blocked_set, NULL); 8708 if (sig > 0) { 8709 sig = check_and_run_traps(sig); 8710 if (sig && sig != SIGCHLD) { /* see note 2 */ 8711 ret = 128 + sig; 8712 break; 8713 } 8714 } 8715 } 8716 sigdelset(&G.blocked_set, SIGCHLD); 8717 sigprocmask(SIG_SETMASK, &G.blocked_set, NULL); 8718 return ret; 8719 } 8720 8721 /* This is probably buggy wrt interruptible-ness */ 8722 while (*argv) { 8723 pid_t pid = bb_strtou(*argv, NULL, 10); 8724 if (errno) { 8725 /* mimic bash message */ 8726 bb_error_msg("wait: '%s': not a pid or valid job spec", *argv); 8727 return EXIT_FAILURE; 8728 } 8729 if (waitpid(pid, &status, 0) == pid) { 8730 if (WIFSIGNALED(status)) 8731 ret = 128 + WTERMSIG(status); 8732 else if (WIFEXITED(status)) 8733 ret = WEXITSTATUS(status); 8734 else /* wtf? */ 8735 ret = EXIT_FAILURE; 8736 } else { 8737 bb_perror_msg("wait %s", *argv); 8738 ret = 127; 8739 } 8740 argv++; 8741 } 8742 8743 return ret; 8744 } 8745 8746 #if ENABLE_HUSH_LOOPS || ENABLE_HUSH_FUNCTIONS 8747 static unsigned parse_numeric_argv1(char **argv, unsigned def, unsigned def_min) 8748 { 8749 if (argv[1]) { 8750 def = bb_strtou(argv[1], NULL, 10); 8751 if (errno || def < def_min || argv[2]) { 8752 bb_error_msg("%s: bad arguments", argv[0]); 8753 def = UINT_MAX; 8754 } 8755 } 8756 return def; 8757 } 8758 #endif 8759 8760 #if ENABLE_HUSH_LOOPS 8761 static int FAST_FUNC builtin_break(char **argv) 8762 { 8763 unsigned depth; 8764 if (G.depth_of_loop == 0) { 8765 bb_error_msg("%s: only meaningful in a loop", argv[0]); 8766 return EXIT_SUCCESS; /* bash compat */ 8767 } 8768 G.flag_break_continue++; /* BC_BREAK = 1 */ 8769 8770 G.depth_break_continue = depth = parse_numeric_argv1(argv, 1, 1); 8771 if (depth == UINT_MAX) 8772 G.flag_break_continue = BC_BREAK; 8773 if (G.depth_of_loop < depth) 8774 G.depth_break_continue = G.depth_of_loop; 8775 8776 return EXIT_SUCCESS; 8777 } 8778 8779 static int FAST_FUNC builtin_continue(char **argv) 8780 { 8781 G.flag_break_continue = 1; /* BC_CONTINUE = 2 = 1+1 */ 8782 return builtin_break(argv); 8783 } 8784 #endif 8785 8786 #if ENABLE_HUSH_FUNCTIONS 8787 static int FAST_FUNC builtin_return(char **argv) 8788 { 8789 int rc; 8790 8791 if (G.flag_return_in_progress != -1) { 8792 bb_error_msg("%s: not in a function or sourced script", argv[0]); 8793 return EXIT_FAILURE; /* bash compat */ 8794 } 8795 8796 G.flag_return_in_progress = 1; 8797 8798 /* bash: 8799 * out of range: wraps around at 256, does not error out 8800 * non-numeric param: 8801 * f() { false; return qwe; }; f; echo $? 8802 * bash: return: qwe: numeric argument required <== we do this 8803 * 255 <== we also do this 8804 */ 8805 rc = parse_numeric_argv1(argv, G.last_exitcode, 0); 8806 return rc; 8807 } 8808 #endif
Note:
See TracChangeset
for help on using the changeset viewer.