aboutsummaryrefslogtreecommitdiff
path: root/shell/hush.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/hush.c')
-rw-r--r--shell/hush.c82
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
1482static 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
1591static void xfunc_has_died(void) NORETURN;
1592static 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?
1592static int check_and_run_traps(void) 1602static 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;