diff options
Diffstat (limited to 'shell/hush.c')
-rw-r--r-- | shell/hush.c | 82 |
1 files changed, 51 insertions, 31 deletions
diff --git a/shell/hush.c b/shell/hush.c index 3ca04494c..eabe83ac6 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -1479,10 +1479,11 @@ static sighandler_t install_sighandler(int sig, sighandler_t handler) | |||
1479 | 1479 | ||
1480 | #if ENABLE_HUSH_JOB | 1480 | #if ENABLE_HUSH_JOB |
1481 | 1481 | ||
1482 | static void xfunc_has_died(void); | ||
1482 | /* After [v]fork, in child: do not restore tty pgrp on xfunc death */ | 1483 | /* After [v]fork, in child: do not restore tty pgrp on xfunc death */ |
1483 | # define disable_restore_tty_pgrp_on_exit() (die_sleep = 0) | 1484 | # define disable_restore_tty_pgrp_on_exit() (die_func = NULL) |
1484 | /* After [v]fork, in parent: restore tty pgrp on xfunc death */ | 1485 | /* After [v]fork, in parent: restore tty pgrp on xfunc death */ |
1485 | # define enable_restore_tty_pgrp_on_exit() (die_sleep = -1) | 1486 | # define enable_restore_tty_pgrp_on_exit() (die_func = xfunc_has_died) |
1486 | 1487 | ||
1487 | /* Restores tty foreground process group, and exits. | 1488 | /* Restores tty foreground process group, and exits. |
1488 | * May be called as signal handler for fatal signal | 1489 | * May be called as signal handler for fatal signal |
@@ -1587,6 +1588,15 @@ static void hush_exit(int exitcode) | |||
1587 | #endif | 1588 | #endif |
1588 | } | 1589 | } |
1589 | 1590 | ||
1591 | static void xfunc_has_died(void) NORETURN; | ||
1592 | static void xfunc_has_died(void) | ||
1593 | { | ||
1594 | /* xfunc has failed! die die die */ | ||
1595 | /* no EXIT traps, this is an escape hatch! */ | ||
1596 | G.exiting = 1; | ||
1597 | hush_exit(xfunc_error_retval); | ||
1598 | } | ||
1599 | |||
1590 | 1600 | ||
1591 | //TODO: return a mask of ALL handled sigs? | 1601 | //TODO: return a mask of ALL handled sigs? |
1592 | static int check_and_run_traps(void) | 1602 | static int check_and_run_traps(void) |
@@ -3161,11 +3171,29 @@ static int reserved_word(o_string *word, struct parse_context *ctx) | |||
3161 | old->command->group = ctx->list_head; | 3171 | old->command->group = ctx->list_head; |
3162 | old->command->cmd_type = CMD_NORMAL; | 3172 | old->command->cmd_type = CMD_NORMAL; |
3163 | # if !BB_MMU | 3173 | # if !BB_MMU |
3164 | o_addstr(&old->as_string, ctx->as_string.data); | 3174 | /* At this point, the compound command's string is in |
3165 | o_free_unsafe(&ctx->as_string); | 3175 | * ctx->as_string... except for the leading keyword! |
3166 | old->command->group_as_string = xstrdup(old->as_string.data); | 3176 | * Consider this example: "echo a | if true; then echo a; fi" |
3167 | debug_printf_parse("pop, remembering as:'%s'\n", | 3177 | * ctx->as_string will contain "true; then echo a; fi", |
3168 | old->command->group_as_string); | 3178 | * with "if " remaining in old->as_string! |
3179 | */ | ||
3180 | { | ||
3181 | char *str; | ||
3182 | int len = old->as_string.length; | ||
3183 | /* Concatenate halves */ | ||
3184 | o_addstr(&old->as_string, ctx->as_string.data); | ||
3185 | o_free_unsafe(&ctx->as_string); | ||
3186 | /* Find where leading keyword starts in first half */ | ||
3187 | str = old->as_string.data + len; | ||
3188 | if (str > old->as_string.data) | ||
3189 | str--; /* skip whitespace after keyword */ | ||
3190 | while (str > old->as_string.data && isalpha(str[-1])) | ||
3191 | str--; | ||
3192 | /* Ugh, we're done with this horrid hack */ | ||
3193 | old->command->group_as_string = xstrdup(str); | ||
3194 | debug_printf_parse("pop, remembering as:'%s'\n", | ||
3195 | old->command->group_as_string); | ||
3196 | } | ||
3169 | # endif | 3197 | # endif |
3170 | *ctx = *old; /* physical copy */ | 3198 | *ctx = *old; /* physical copy */ |
3171 | free(old); | 3199 | free(old); |
@@ -4248,7 +4276,7 @@ static struct pipe *parse_stream(char **pstring, | |||
4248 | pi = NULL; | 4276 | pi = NULL; |
4249 | } | 4277 | } |
4250 | #if !BB_MMU | 4278 | #if !BB_MMU |
4251 | debug_printf_parse("as_string '%s'\n", ctx.as_string.data); | 4279 | debug_printf_parse("as_string1 '%s'\n", ctx.as_string.data); |
4252 | if (pstring) | 4280 | if (pstring) |
4253 | *pstring = ctx.as_string.data; | 4281 | *pstring = ctx.as_string.data; |
4254 | else | 4282 | else |
@@ -4399,7 +4427,7 @@ static struct pipe *parse_stream(char **pstring, | |||
4399 | ) { | 4427 | ) { |
4400 | o_free(&dest); | 4428 | o_free(&dest); |
4401 | #if !BB_MMU | 4429 | #if !BB_MMU |
4402 | debug_printf_parse("as_string '%s'\n", ctx.as_string.data); | 4430 | debug_printf_parse("as_string2 '%s'\n", ctx.as_string.data); |
4403 | if (pstring) | 4431 | if (pstring) |
4404 | *pstring = ctx.as_string.data; | 4432 | *pstring = ctx.as_string.data; |
4405 | else | 4433 | else |
@@ -4639,9 +4667,6 @@ static struct pipe *parse_stream(char **pstring, | |||
4639 | * with redirect_opt_num(), but bash doesn't do it. | 4667 | * with redirect_opt_num(), but bash doesn't do it. |
4640 | * "echo foo 2| cat" yields "foo 2". */ | 4668 | * "echo foo 2| cat" yields "foo 2". */ |
4641 | done_command(&ctx); | 4669 | done_command(&ctx); |
4642 | #if !BB_MMU | ||
4643 | o_reset_to_empty_unquoted(&ctx.as_string); | ||
4644 | #endif | ||
4645 | } | 4670 | } |
4646 | goto new_cmd; | 4671 | goto new_cmd; |
4647 | case '(': | 4672 | case '(': |
@@ -6779,7 +6804,7 @@ static int checkjobs(struct pipe *fg_pipe) | |||
6779 | int sig = WTERMSIG(status); | 6804 | int sig = WTERMSIG(status); |
6780 | if (i == fg_pipe->num_cmds-1) | 6805 | if (i == fg_pipe->num_cmds-1) |
6781 | /* TODO: use strsignal() instead for bash compat? but that's bloat... */ | 6806 | /* TODO: use strsignal() instead for bash compat? but that's bloat... */ |
6782 | printf("%s\n", sig == SIGINT || sig == SIGPIPE ? "" : get_signame(sig)); | 6807 | puts(sig == SIGINT || sig == SIGPIPE ? "" : get_signame(sig)); |
6783 | /* TODO: if (WCOREDUMP(status)) + " (core dumped)"; */ | 6808 | /* TODO: if (WCOREDUMP(status)) + " (core dumped)"; */ |
6784 | /* TODO: MIPS has 128 sigs (1..128), what if sig==128 here? | 6809 | /* TODO: MIPS has 128 sigs (1..128), what if sig==128 here? |
6785 | * Maybe we need to use sig | 128? */ | 6810 | * Maybe we need to use sig | 128? */ |
@@ -7851,12 +7876,7 @@ int hush_main(int argc, char **argv) | |||
7851 | /* Initialize some more globals to non-zero values */ | 7876 | /* Initialize some more globals to non-zero values */ |
7852 | cmdedit_update_prompt(); | 7877 | cmdedit_update_prompt(); |
7853 | 7878 | ||
7854 | if (setjmp(die_jmp)) { | 7879 | die_func = xfunc_has_died; |
7855 | /* xfunc has failed! die die die */ | ||
7856 | /* no EXIT traps, this is an escape hatch! */ | ||
7857 | G.exiting = 1; | ||
7858 | hush_exit(xfunc_error_retval); | ||
7859 | } | ||
7860 | 7880 | ||
7861 | /* Shell is non-interactive at first. We need to call | 7881 | /* Shell is non-interactive at first. We need to call |
7862 | * install_special_sighandlers() if we are going to execute "sh <script>", | 7882 | * install_special_sighandlers() if we are going to execute "sh <script>", |
@@ -8114,9 +8134,7 @@ int hush_main(int argc, char **argv) | |||
8114 | /* Grab control of the terminal */ | 8134 | /* Grab control of the terminal */ |
8115 | tcsetpgrp(G_interactive_fd, getpid()); | 8135 | tcsetpgrp(G_interactive_fd, getpid()); |
8116 | } | 8136 | } |
8117 | /* -1 is special - makes xfuncs longjmp, not exit | 8137 | enable_restore_tty_pgrp_on_exit(); |
8118 | * (we reset die_sleep = 0 whereever we [v]fork) */ | ||
8119 | enable_restore_tty_pgrp_on_exit(); /* sets die_sleep = -1 */ | ||
8120 | 8138 | ||
8121 | # if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0 | 8139 | # if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0 |
8122 | { | 8140 | { |
@@ -8950,24 +8968,29 @@ static int FAST_FUNC builtin_umask(char **argv) | |||
8950 | int rc; | 8968 | int rc; |
8951 | mode_t mask; | 8969 | mode_t mask; |
8952 | 8970 | ||
8971 | rc = 1; | ||
8953 | mask = umask(0); | 8972 | mask = umask(0); |
8954 | argv = skip_dash_dash(argv); | 8973 | argv = skip_dash_dash(argv); |
8955 | if (argv[0]) { | 8974 | if (argv[0]) { |
8956 | mode_t old_mask = mask; | 8975 | mode_t old_mask = mask; |
8957 | 8976 | ||
8958 | mask ^= 0777; | 8977 | /* numeric umasks are taken as-is */ |
8959 | rc = bb_parse_mode(argv[0], &mask); | 8978 | /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */ |
8960 | mask ^= 0777; | 8979 | if (!isdigit(argv[0][0])) |
8961 | if (rc == 0) { | 8980 | mask ^= 0777; |
8981 | mask = bb_parse_mode(argv[0], mask); | ||
8982 | if (!isdigit(argv[0][0])) | ||
8983 | mask ^= 0777; | ||
8984 | if ((unsigned)mask > 0777) { | ||
8962 | mask = old_mask; | 8985 | mask = old_mask; |
8963 | /* bash messages: | 8986 | /* bash messages: |
8964 | * bash: umask: 'q': invalid symbolic mode operator | 8987 | * bash: umask: 'q': invalid symbolic mode operator |
8965 | * bash: umask: 999: octal number out of range | 8988 | * bash: umask: 999: octal number out of range |
8966 | */ | 8989 | */ |
8967 | bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]); | 8990 | bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]); |
8991 | rc = 0; | ||
8968 | } | 8992 | } |
8969 | } else { | 8993 | } else { |
8970 | rc = 1; | ||
8971 | /* Mimic bash */ | 8994 | /* Mimic bash */ |
8972 | printf("%04o\n", (unsigned) mask); | 8995 | printf("%04o\n", (unsigned) mask); |
8973 | /* fall through and restore mask which we set to 0 */ | 8996 | /* fall through and restore mask which we set to 0 */ |
@@ -9097,12 +9120,9 @@ static int FAST_FUNC builtin_wait(char **argv) | |||
9097 | return EXIT_FAILURE; | 9120 | return EXIT_FAILURE; |
9098 | } | 9121 | } |
9099 | if (waitpid(pid, &status, 0) == pid) { | 9122 | if (waitpid(pid, &status, 0) == pid) { |
9123 | ret = WEXITSTATUS(status); | ||
9100 | if (WIFSIGNALED(status)) | 9124 | if (WIFSIGNALED(status)) |
9101 | ret = 128 + WTERMSIG(status); | 9125 | ret = 128 + WTERMSIG(status); |
9102 | else if (WIFEXITED(status)) | ||
9103 | ret = WEXITSTATUS(status); | ||
9104 | else /* wtf? */ | ||
9105 | ret = EXIT_FAILURE; | ||
9106 | } else { | 9126 | } else { |
9107 | bb_perror_msg("wait %s", *argv); | 9127 | bb_perror_msg("wait %s", *argv); |
9108 | ret = 127; | 9128 | ret = 127; |