diff options
Diffstat (limited to 'shell/hush.c')
-rw-r--r-- | shell/hush.c | 48 |
1 files changed, 38 insertions, 10 deletions
diff --git a/shell/hush.c b/shell/hush.c index 6d472337f..6a27b1634 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -339,7 +339,7 @@ | |||
339 | * therefore we don't show them either. | 339 | * therefore we don't show them either. |
340 | */ | 340 | */ |
341 | //usage:#define hush_trivial_usage | 341 | //usage:#define hush_trivial_usage |
342 | //usage: "[-enxl] [-c 'SCRIPT' [ARG0 ARGS] | FILE [ARGS] | -s [ARGS]]" | 342 | //usage: "[-enxl] [-c 'SCRIPT' [ARG0 ARGS] | FILE ARGS | -s ARGS]" |
343 | //usage:#define hush_full_usage "\n\n" | 343 | //usage:#define hush_full_usage "\n\n" |
344 | //usage: "Unix shell interpreter" | 344 | //usage: "Unix shell interpreter" |
345 | 345 | ||
@@ -373,7 +373,7 @@ | |||
373 | # define F_DUPFD_CLOEXEC F_DUPFD | 373 | # define F_DUPFD_CLOEXEC F_DUPFD |
374 | #endif | 374 | #endif |
375 | 375 | ||
376 | #if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !(ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH) | 376 | #if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !ENABLE_SHELL_ASH |
377 | # include "embedded_scripts.h" | 377 | # include "embedded_scripts.h" |
378 | #else | 378 | #else |
379 | # define NUM_SCRIPTS 0 | 379 | # define NUM_SCRIPTS 0 |
@@ -3360,7 +3360,7 @@ static int glob_brace(char *pattern, o_string *o, int n) | |||
3360 | * NEXT points past the terminator of the first element, and REST | 3360 | * NEXT points past the terminator of the first element, and REST |
3361 | * points past the final }. We will accumulate result names from | 3361 | * points past the final }. We will accumulate result names from |
3362 | * recursive runs for each brace alternative in the buffer using | 3362 | * recursive runs for each brace alternative in the buffer using |
3363 | * GLOB_APPEND. */ | 3363 | * GLOB_APPEND. */ |
3364 | 3364 | ||
3365 | p = begin + 1; | 3365 | p = begin + 1; |
3366 | while (1) { | 3366 | while (1) { |
@@ -6311,7 +6311,7 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int | |||
6311 | 6311 | ||
6312 | /* Expanding ARG in ${var+ARG}, ${var-ARG} | 6312 | /* Expanding ARG in ${var+ARG}, ${var-ARG} |
6313 | */ | 6313 | */ |
6314 | static int encode_then_append_var_plusminus(o_string *output, int n, | 6314 | static NOINLINE int encode_then_append_var_plusminus(o_string *output, int n, |
6315 | char *str, int dquoted) | 6315 | char *str, int dquoted) |
6316 | { | 6316 | { |
6317 | struct in_str input; | 6317 | struct in_str input; |
@@ -6472,16 +6472,21 @@ static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) | |||
6472 | /* ${var/[/]pattern[/repl]} helpers */ | 6472 | /* ${var/[/]pattern[/repl]} helpers */ |
6473 | static char *strstr_pattern(char *val, const char *pattern, int *size) | 6473 | static char *strstr_pattern(char *val, const char *pattern, int *size) |
6474 | { | 6474 | { |
6475 | int sz = strcspn(pattern, "*?[\\"); | 6475 | int first_escaped = (pattern[0] == '\\' && pattern[1]); |
6476 | if (pattern[sz] == '\0') { | 6476 | /* "first_escaped" trick allows to treat e.g. "\*no_glob_chars" |
6477 | * as literal too (as it is semi-common, and easy to accomodate | ||
6478 | * by just using str + 1). | ||
6479 | */ | ||
6480 | int sz = strcspn(pattern + first_escaped * 2, "*?[\\"); | ||
6481 | if ((pattern + first_escaped * 2)[sz] == '\0') { | ||
6477 | /* Optimization for trivial patterns. | 6482 | /* Optimization for trivial patterns. |
6478 | * Testcase for very slow replace (performs about 22k replaces): | 6483 | * Testcase for very slow replace (performs about 22k replaces): |
6479 | * x=:::::::::::::::::::::: | 6484 | * x=:::::::::::::::::::::: |
6480 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} | 6485 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} |
6481 | * echo "${x//:/|}" | 6486 | * echo "${x//:/|}" |
6482 | */ | 6487 | */ |
6483 | *size = sz; | 6488 | *size = sz + first_escaped; |
6484 | return strstr(val, pattern); | 6489 | return strstr(val, pattern + first_escaped); |
6485 | } | 6490 | } |
6486 | 6491 | ||
6487 | while (1) { | 6492 | while (1) { |
@@ -10220,7 +10225,7 @@ int hush_main(int argc, char **argv) | |||
10220 | 10225 | ||
10221 | cached_getpid = getpid(); /* for tcsetpgrp() during init */ | 10226 | cached_getpid = getpid(); /* for tcsetpgrp() during init */ |
10222 | G.root_pid = cached_getpid; /* for $PID (NOMMU can override via -$HEXPID:HEXPPID:...) */ | 10227 | G.root_pid = cached_getpid; /* for $PID (NOMMU can override via -$HEXPID:HEXPPID:...) */ |
10223 | G.root_ppid = getppid(); /* for $PPID (NOMMU can override) */ | 10228 | G.root_ppid = getppid(); /* for $PPID (NOMMU can override) */ |
10224 | 10229 | ||
10225 | /* Deal with HUSH_VERSION */ | 10230 | /* Deal with HUSH_VERSION */ |
10226 | debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); | 10231 | debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); |
@@ -10351,6 +10356,29 @@ int hush_main(int argc, char **argv) | |||
10351 | /* Well, we cannot just declare interactiveness, | 10356 | /* Well, we cannot just declare interactiveness, |
10352 | * we have to have some stuff (ctty, etc) */ | 10357 | * we have to have some stuff (ctty, etc) */ |
10353 | /* G_interactive_fd++; */ | 10358 | /* G_interactive_fd++; */ |
10359 | //There are a few cases where bash -i -c 'SCRIPT' | ||
10360 | //has visible effect (differs from bash -c 'SCRIPT'): | ||
10361 | //it ignores TERM: | ||
10362 | // bash -i -c 'kill $$; echo ALIVE' | ||
10363 | // ALIVE | ||
10364 | //it resets SIG_INGed HUP to SIG_DFL: | ||
10365 | // trap '' hup; bash -i -c 'kill -hup $$; echo ALIVE' | ||
10366 | // Hangup [the message is not printed by bash, it's the shell which started it] | ||
10367 | //is talkative about jobs and exiting: | ||
10368 | // bash -i -c 'sleep 1 & exit' | ||
10369 | // [1] 16170 | ||
10370 | // exit | ||
10371 | //includes $ENV file (only if run as "sh"): | ||
10372 | // echo last >/tmp/ENV; ENV=/tmp/ENV sh -i -c 'echo HERE' | ||
10373 | // last: cannot open /var/log/wtmp: No such file or directory | ||
10374 | // HERE | ||
10375 | //(under "bash", it's the opposite: it runs $BASH_ENV file only *without* -i). | ||
10376 | // | ||
10377 | //ash -i -c 'sleep 3; sleep 3', on ^C, drops into a prompt instead of exiting | ||
10378 | //(this may be a bug, bash does not do this). | ||
10379 | //(ash -i -c 'sleep 3' won't show this, the last command gets auto-"exec"ed) | ||
10380 | // | ||
10381 | //None of the above feel like useful features people would rely on. | ||
10354 | break; | 10382 | break; |
10355 | case 's': | 10383 | case 's': |
10356 | G.opt_s = 1; | 10384 | G.opt_s = 1; |
@@ -11727,7 +11755,7 @@ static int FAST_FUNC builtin_fg_bg(char **argv) | |||
11727 | /* TODO: bash prints a string representation | 11755 | /* TODO: bash prints a string representation |
11728 | * of job being foregrounded (like "sleep 1 | cat") */ | 11756 | * of job being foregrounded (like "sleep 1 | cat") */ |
11729 | if (argv[0][0] == 'f' && G_saved_tty_pgrp) { | 11757 | if (argv[0][0] == 'f' && G_saved_tty_pgrp) { |
11730 | /* Put the job into the foreground. */ | 11758 | /* Put the job into the foreground. */ |
11731 | tcsetpgrp(G_interactive_fd, pi->pgrp); | 11759 | tcsetpgrp(G_interactive_fd, pi->pgrp); |
11732 | } | 11760 | } |
11733 | 11761 | ||