aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-03 19:14:32 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-03 19:14:32 +0000
commit60b392fd5bd49af2813b3970940e75516bf1e5dd (patch)
treed442fa5a4ae3b192727466dd951b89837decaef6
parentb6e6556b31e76afdbe956886e45b1168d4a49de6 (diff)
downloadbusybox-w32-60b392fd5bd49af2813b3970940e75516bf1e5dd.tar.gz
busybox-w32-60b392fd5bd49af2813b3970940e75516bf1e5dd.tar.bz2
busybox-w32-60b392fd5bd49af2813b3970940e75516bf1e5dd.zip
hush: randomconfig fixes
-rw-r--r--shell/hush.c94
1 files changed, 48 insertions, 46 deletions
diff --git a/shell/hush.c b/shell/hush.c
index e0c1fde6b..64c1d3dd6 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -462,6 +462,9 @@ struct globals {
462 int interactive_fd; 462 int interactive_fd;
463 const char *PS1; 463 const char *PS1;
464 const char *PS2; 464 const char *PS2;
465#define G_interactive_fd (G.interactive_fd)
466#else
467#define G_interactive_fd 0
465#endif 468#endif
466#if ENABLE_FEATURE_EDITING 469#if ENABLE_FEATURE_EDITING
467 line_input_t *line_input_state; 470 line_input_t *line_input_state;
@@ -616,11 +619,11 @@ static const struct built_in_command bltins[] = {
616static void maybe_die(const char *notice, const char *msg) 619static void maybe_die(const char *notice, const char *msg)
617{ 620{
618 /* Was using fancy stuff: 621 /* Was using fancy stuff:
619 * (G.interactive_fd ? bb_error_msg : bb_error_msg_and_die)(...params...) 622 * (G_interactive_fd ? bb_error_msg : bb_error_msg_and_die)(...params...)
620 * but it SEGVs. ?! Oh well... explicit temp ptr works around that */ 623 * but it SEGVs. ?! Oh well... explicit temp ptr works around that */
621 void FAST_FUNC (*fp)(const char *s, ...) = bb_error_msg_and_die; 624 void FAST_FUNC (*fp)(const char *s, ...) = bb_error_msg_and_die;
622#if ENABLE_HUSH_INTERACTIVE 625#if ENABLE_HUSH_INTERACTIVE
623 fp = (G.interactive_fd ? bb_error_msg : bb_error_msg_and_die); 626 fp = (G_interactive_fd ? bb_error_msg : bb_error_msg_and_die);
624#endif 627#endif
625 fp(msg ? "%s: %s" : notice, notice, msg); 628 fp(msg ? "%s: %s" : notice, notice, msg);
626} 629}
@@ -861,8 +864,7 @@ static void init_signal_mask(void)
861{ 864{
862 unsigned sig; 865 unsigned sig;
863 unsigned mask = (1 << SIGQUIT); 866 unsigned mask = (1 << SIGQUIT);
864#if ENABLE_HUSH_INTERACTIVE 867 if (G_interactive_fd) {
865 if (G.interactive_fd) {
866 mask = 0 868 mask = 0
867 | (1 << SIGQUIT) 869 | (1 << SIGQUIT)
868 | (1 << SIGTERM) 870 | (1 << SIGTERM)
@@ -873,7 +875,6 @@ static void init_signal_mask(void)
873 | (1 << SIGINT) 875 | (1 << SIGINT)
874 ; 876 ;
875 } 877 }
876#endif
877 G.non_DFL_mask = mask; 878 G.non_DFL_mask = mask;
878 879
879 sigprocmask(SIG_SETMASK, NULL, &G.blocked_set); 880 sigprocmask(SIG_SETMASK, NULL, &G.blocked_set);
@@ -945,12 +946,10 @@ static void sigexit(int sig)
945 /* Disable all signals: job control, SIGPIPE, etc. */ 946 /* Disable all signals: job control, SIGPIPE, etc. */
946 sigprocmask_allsigs(SIG_BLOCK); 947 sigprocmask_allsigs(SIG_BLOCK);
947 948
948#if ENABLE_HUSH_INTERACTIVE
949 /* Careful: we can end up here after [v]fork. Do not restore 949 /* Careful: we can end up here after [v]fork. Do not restore
950 * tty pgrp then, only top-level shell process does that */ 950 * tty pgrp then, only top-level shell process does that */
951 if (G.interactive_fd && getpid() == G.root_pid) 951 if (G_interactive_fd && getpid() == G.root_pid)
952 tcsetpgrp(G.interactive_fd, G.saved_tty_pgrp); 952 tcsetpgrp(G_interactive_fd, G.saved_tty_pgrp);
953#endif
954 953
955 /* Not a signal, just exit */ 954 /* Not a signal, just exit */
956 if (sig <= 0) 955 if (sig <= 0)
@@ -1307,7 +1306,7 @@ static int file_get(struct in_str *i)
1307 /* need to double check i->file because we might be doing something 1306 /* need to double check i->file because we might be doing something
1308 * more complicated by now, like sourcing or substituting. */ 1307 * more complicated by now, like sourcing or substituting. */
1309#if ENABLE_HUSH_INTERACTIVE 1308#if ENABLE_HUSH_INTERACTIVE
1310 if (G.interactive_fd && i->promptme && i->file == stdin) { 1309 if (G_interactive_fd && i->promptme && i->file == stdin) {
1311 do { 1310 do {
1312 get_user_input(i); 1311 get_user_input(i);
1313 } while (!*i->p); /* need non-empty line */ 1312 } while (!*i->p); /* need non-empty line */
@@ -2408,7 +2407,7 @@ static void insert_bg_job(struct pipe *pi)
2408 2407
2409 /* We don't wait for background thejobs to return -- append it 2408 /* We don't wait for background thejobs to return -- append it
2410 to the list of backgrounded thejobs and leave it alone */ 2409 to the list of backgrounded thejobs and leave it alone */
2411 if (G.interactive_fd) 2410 if (G_interactive_fd)
2412 printf("[%d] %d %s\n", thejob->jobid, thejob->cmds[0].pid, thejob->cmdtext); 2411 printf("[%d] %d %s\n", thejob->jobid, thejob->cmds[0].pid, thejob->cmdtext);
2413 G.last_bg_pid = thejob->cmds[0].pid; 2412 G.last_bg_pid = thejob->cmds[0].pid;
2414 G.last_jobid = thejob->jobid; 2413 G.last_jobid = thejob->jobid;
@@ -2558,7 +2557,7 @@ static int checkjobs(struct pipe* fg_pipe)
2558 pi->cmds[i].pid = 0; 2557 pi->cmds[i].pid = 0;
2559 pi->alive_cmds--; 2558 pi->alive_cmds--;
2560 if (!pi->alive_cmds) { 2559 if (!pi->alive_cmds) {
2561 if (G.interactive_fd) 2560 if (G_interactive_fd)
2562 printf(JOB_STATUS_FORMAT, pi->jobid, 2561 printf(JOB_STATUS_FORMAT, pi->jobid,
2563 "Done", pi->cmdtext); 2562 "Done", pi->cmdtext);
2564 delete_finished_bg_job(pi); 2563 delete_finished_bg_job(pi);
@@ -2582,7 +2581,7 @@ static int checkjobs_and_fg_shell(struct pipe* fg_pipe)
2582 /* Job finished, move the shell to the foreground */ 2581 /* Job finished, move the shell to the foreground */
2583 p = getpgid(0); /* pgid of our process */ 2582 p = getpgid(0); /* pgid of our process */
2584 debug_printf_jobs("fg'ing ourself: getpgid(0)=%d\n", (int)p); 2583 debug_printf_jobs("fg'ing ourself: getpgid(0)=%d\n", (int)p);
2585 tcsetpgrp(G.interactive_fd, p); 2584 tcsetpgrp(G_interactive_fd, p);
2586 return rcode; 2585 return rcode;
2587} 2586}
2588#endif 2587#endif
@@ -2755,7 +2754,7 @@ static int run_pipe(struct pipe *pi)
2755 2754
2756 /* Every child adds itself to new process group 2755 /* Every child adds itself to new process group
2757 * with pgid == pid_of_first_child_in_pipe */ 2756 * with pgid == pid_of_first_child_in_pipe */
2758 if (G.run_list_level == 1 && G.interactive_fd) { 2757 if (G.run_list_level == 1 && G_interactive_fd) {
2759 pid_t pgrp; 2758 pid_t pgrp;
2760 pgrp = pi->pgrp; 2759 pgrp = pi->pgrp;
2761 if (pgrp < 0) /* true for 1st process only */ 2760 if (pgrp < 0) /* true for 1st process only */
@@ -2763,7 +2762,7 @@ static int run_pipe(struct pipe *pi)
2763 if (setpgid(0, pgrp) == 0 && pi->followup != PIPE_BG) { 2762 if (setpgid(0, pgrp) == 0 && pi->followup != PIPE_BG) {
2764 /* We do it in *every* child, not just first, 2763 /* We do it in *every* child, not just first,
2765 * to avoid races */ 2764 * to avoid races */
2766 tcsetpgrp(G.interactive_fd, pgrp); 2765 tcsetpgrp(G_interactive_fd, pgrp);
2767 } 2766 }
2768 } 2767 }
2769#endif 2768#endif
@@ -2961,7 +2960,7 @@ static int run_list(struct pipe *pi)
2961 * We are saving state before entering outermost list ("while...done") 2960 * We are saving state before entering outermost list ("while...done")
2962 * so that ctrl-Z will correctly background _entire_ outermost list, 2961 * so that ctrl-Z will correctly background _entire_ outermost list,
2963 * not just a part of it (like "sleep 1 | exit 2") */ 2962 * not just a part of it (like "sleep 1 | exit 2") */
2964 if (++G.run_list_level == 1 && G.interactive_fd) { 2963 if (++G.run_list_level == 1 && G_interactive_fd) {
2965 if (sigsetjmp(G.toplevel_jb, 1)) { 2964 if (sigsetjmp(G.toplevel_jb, 1)) {
2966 /* ctrl-Z forked and we are parent; or ctrl-C. 2965 /* ctrl-Z forked and we are parent; or ctrl-C.
2967 * Sighandler has longjmped us here */ 2966 * Sighandler has longjmped us here */
@@ -3124,7 +3123,7 @@ static int run_list(struct pipe *pi)
3124 * OTOH, in non-interactive shell this is useless 3123 * OTOH, in non-interactive shell this is useless
3125 * and only leads to extra job checks */ 3124 * and only leads to extra job checks */
3126 if (pi->num_cmds == 0) { 3125 if (pi->num_cmds == 0) {
3127 if (G.interactive_fd) 3126 if (G_interactive_fd)
3128 goto check_jobs_and_continue; 3127 goto check_jobs_and_continue;
3129 continue; 3128 continue;
3130 } 3129 }
@@ -3176,7 +3175,7 @@ static int run_list(struct pipe *pi)
3176 rcode = 0; /* EXIT_SUCCESS */ 3175 rcode = 0; /* EXIT_SUCCESS */
3177 } else { 3176 } else {
3178#if ENABLE_HUSH_JOB 3177#if ENABLE_HUSH_JOB
3179 if (G.run_list_level == 1 && G.interactive_fd) { 3178 if (G.run_list_level == 1 && G_interactive_fd) {
3180 /* waits for completion, then fg's main shell */ 3179 /* waits for completion, then fg's main shell */
3181 rcode = checkjobs_and_fg_shell(pi); 3180 rcode = checkjobs_and_fg_shell(pi);
3182 check_and_run_traps(0); 3181 check_and_run_traps(0);
@@ -3232,7 +3231,7 @@ static int run_list(struct pipe *pi)
3232//// } 3231//// }
3233 ret: 3232 ret:
3234 G.run_list_level--; 3233 G.run_list_level--;
3235//// if (!G.run_list_level && G.interactive_fd) { 3234//// if (!G.run_list_level && G_interactive_fd) {
3236//// signal(SIGTSTP, SIG_IGN); 3235//// signal(SIGTSTP, SIG_IGN);
3237//// signal(SIGINT, SIG_IGN); 3236//// signal(SIGINT, SIG_IGN);
3238//// } 3237//// }
@@ -4294,7 +4293,7 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger)
4294 /* If we got nothing... */ 4293 /* If we got nothing... */
4295 pi = ctx.list_head; 4294 pi = ctx.list_head;
4296 if (pi->num_cmds == 0 4295 if (pi->num_cmds == 0
4297 && pi->res_word == RES_NONE 4296 IF_HAS_KEYWORDS( && pi->res_word == RES_NONE)
4298 ) { 4297 ) {
4299 free_pipe_list(pi, 0); 4298 free_pipe_list(pi, 0);
4300 pi = NULL; 4299 pi = NULL;
@@ -4564,7 +4563,8 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger)
4564 4563
4565 parse_error: 4564 parse_error:
4566 { 4565 {
4567 struct parse_context *pctx, *p2; 4566 struct parse_context *pctx;
4567 IF_HAS_KEYWORDS(struct parse_context *p2;)
4568 4568
4569 /* Clean up allocated tree. 4569 /* Clean up allocated tree.
4570 * Samples for finding leaks on syntax error recovery path. 4570 * Samples for finding leaks on syntax error recovery path.
@@ -4582,12 +4582,12 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger)
4582 debug_print_tree(pctx->list_head, 0); 4582 debug_print_tree(pctx->list_head, 0);
4583 free_pipe_list(pctx->list_head, 0); 4583 free_pipe_list(pctx->list_head, 0);
4584 debug_printf_clean("freed list %p\n", pctx->list_head); 4584 debug_printf_clean("freed list %p\n", pctx->list_head);
4585 p2 = pctx->stack; 4585 IF_HAS_KEYWORDS(p2 = pctx->stack;)
4586 if (pctx != &ctx) { 4586 if (pctx != &ctx) {
4587 free(pctx); 4587 free(pctx);
4588 } 4588 }
4589 pctx = p2; 4589 IF_HAS_KEYWORDS(pctx = p2;)
4590 } while (pctx); 4590 } while (HAS_KEYWORDS && pctx);
4591 /* Free text, clear all dest fields */ 4591 /* Free text, clear all dest fields */
4592 o_free(&dest); 4592 o_free(&dest);
4593 /* If we are not in top-level parse, we return, 4593 /* If we are not in top-level parse, we return,
@@ -4597,7 +4597,7 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger)
4597 return ERR_PTR; 4597 return ERR_PTR;
4598 /* Discard cached input, force prompt */ 4598 /* Discard cached input, force prompt */
4599 input->p = NULL; 4599 input->p = NULL;
4600 input->promptme = 1; 4600 USE_HUSH_INTERACTIVE(input->promptme = 1;)
4601 goto reset; 4601 goto reset;
4602 } 4602 }
4603} 4603}
@@ -4678,7 +4678,7 @@ static void setup_job_control(void)
4678 4678
4679 /* If we were ran as 'hush &', 4679 /* If we were ran as 'hush &',
4680 * sleep until we are in the foreground. */ 4680 * sleep until we are in the foreground. */
4681 while (tcgetpgrp(G.interactive_fd) != shell_pgrp) { 4681 while (tcgetpgrp(G_interactive_fd) != shell_pgrp) {
4682 /* Send TTIN to ourself (should stop us) */ 4682 /* Send TTIN to ourself (should stop us) */
4683 kill(- shell_pgrp, SIGTTIN); 4683 kill(- shell_pgrp, SIGTTIN);
4684 shell_pgrp = getpgrp(); 4684 shell_pgrp = getpgrp();
@@ -4690,7 +4690,7 @@ static void setup_job_control(void)
4690 /* Put ourselves in our own process group. */ 4690 /* Put ourselves in our own process group. */
4691 bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */ 4691 bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */
4692 /* Grab control of the terminal. */ 4692 /* Grab control of the terminal. */
4693 tcsetpgrp(G.interactive_fd, getpid()); 4693 tcsetpgrp(G_interactive_fd, getpid());
4694} 4694}
4695#endif 4695#endif
4696 4696
@@ -4792,7 +4792,7 @@ int hush_main(int argc, char **argv)
4792 case 'i': 4792 case 'i':
4793 /* Well, we cannot just declare interactiveness, 4793 /* Well, we cannot just declare interactiveness,
4794 * we have to have some stuff (ctty, etc) */ 4794 * we have to have some stuff (ctty, etc) */
4795 /* G.interactive_fd++; */ 4795 /* G_interactive_fd++; */
4796 break; 4796 break;
4797 case 's': 4797 case 's':
4798 /* "-s" means "read from stdin", but this is how we always 4798 /* "-s" means "read from stdin", but this is how we always
@@ -4827,22 +4827,22 @@ int hush_main(int argc, char **argv)
4827 debug_printf("saved_tty_pgrp=%d\n", G.saved_tty_pgrp); 4827 debug_printf("saved_tty_pgrp=%d\n", G.saved_tty_pgrp);
4828 if (G.saved_tty_pgrp >= 0) { 4828 if (G.saved_tty_pgrp >= 0) {
4829 /* try to dup to high fd#, >= 255 */ 4829 /* try to dup to high fd#, >= 255 */
4830 G.interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255); 4830 G_interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255);
4831 if (G.interactive_fd < 0) { 4831 if (G_interactive_fd < 0) {
4832 /* try to dup to any fd */ 4832 /* try to dup to any fd */
4833 G.interactive_fd = dup(STDIN_FILENO); 4833 G_interactive_fd = dup(STDIN_FILENO);
4834 if (G.interactive_fd < 0) 4834 if (G_interactive_fd < 0)
4835 /* give up */ 4835 /* give up */
4836 G.interactive_fd = 0; 4836 G_interactive_fd = 0;
4837 } 4837 }
4838 // TODO: track & disallow any attempts of user 4838 // TODO: track & disallow any attempts of user
4839 // to (inadvertently) close/redirect it 4839 // to (inadvertently) close/redirect it
4840 } 4840 }
4841 } 4841 }
4842 init_signal_mask(); /* note: ensures SIGCHLD is not masked */ 4842 init_signal_mask(); /* note: ensures SIGCHLD is not masked */
4843 debug_printf("G.interactive_fd=%d\n", G.interactive_fd); 4843 debug_printf("interactive_fd=%d\n", G_interactive_fd);
4844 if (G.interactive_fd) { 4844 if (G_interactive_fd) {
4845 fcntl(G.interactive_fd, F_SETFD, FD_CLOEXEC); 4845 fcntl(G_interactive_fd, F_SETFD, FD_CLOEXEC);
4846 /* Looks like they want an interactive shell */ 4846 /* Looks like they want an interactive shell */
4847 setup_job_control(); 4847 setup_job_control();
4848 /* -1 is special - makes xfuncs longjmp, not exit 4848 /* -1 is special - makes xfuncs longjmp, not exit
@@ -4858,19 +4858,21 @@ int hush_main(int argc, char **argv)
4858 if (argv[optind] == NULL && input == stdin 4858 if (argv[optind] == NULL && input == stdin
4859 && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) 4859 && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)
4860 ) { 4860 ) {
4861 G.interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255); 4861 G_interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255);
4862 if (G.interactive_fd < 0) { 4862 if (G_interactive_fd < 0) {
4863 /* try to dup to any fd */ 4863 /* try to dup to any fd */
4864 G.interactive_fd = dup(STDIN_FILENO); 4864 G_interactive_fd = dup(STDIN_FILENO);
4865 if (G.interactive_fd < 0) 4865 if (G_interactive_fd < 0)
4866 /* give up */ 4866 /* give up */
4867 G.interactive_fd = 0; 4867 G_interactive_fd = 0;
4868 } 4868 }
4869 if (G.interactive_fd) { 4869 if (G_interactive_fd) {
4870 fcntl(G.interactive_fd, F_SETFD, FD_CLOEXEC); 4870 fcntl(G_interactive_fd, F_SETFD, FD_CLOEXEC);
4871 } 4871 }
4872 } 4872 }
4873 init_signal_mask(); /* note: ensures SIGCHLD is not masked */ 4873 init_signal_mask(); /* note: ensures SIGCHLD is not masked */
4874#else
4875 init_signal_mask();
4874#endif 4876#endif
4875 /* POSIX allows shell to re-enable SIGCHLD 4877 /* POSIX allows shell to re-enable SIGCHLD
4876 * even if it was SIG_IGN on entry */ 4878 * even if it was SIG_IGN on entry */
@@ -4878,7 +4880,7 @@ int hush_main(int argc, char **argv)
4878 signal(SIGCHLD, SIG_DFL); // SIGCHLD_handler); 4880 signal(SIGCHLD, SIG_DFL); // SIGCHLD_handler);
4879 4881
4880#if ENABLE_HUSH_INTERACTIVE && !ENABLE_FEATURE_SH_EXTRA_QUIET 4882#if ENABLE_HUSH_INTERACTIVE && !ENABLE_FEATURE_SH_EXTRA_QUIET
4881 if (G.interactive_fd) { 4883 if (G_interactive_fd) {
4882 printf("\n\n%s hush - the humble shell v"HUSH_VER_STR"\n", bb_banner); 4884 printf("\n\n%s hush - the humble shell v"HUSH_VER_STR"\n", bb_banner);
4883 printf("Enter 'help' for a list of built-in commands.\n\n"); 4885 printf("Enter 'help' for a list of built-in commands.\n\n");
4884 } 4886 }
@@ -5135,7 +5137,7 @@ static int builtin_fg_bg(char **argv)
5135 int i, jobnum; 5137 int i, jobnum;
5136 struct pipe *pi; 5138 struct pipe *pi;
5137 5139
5138 if (!G.interactive_fd) 5140 if (!G_interactive_fd)
5139 return EXIT_FAILURE; 5141 return EXIT_FAILURE;
5140 /* If they gave us no args, assume they want the last backgrounded task */ 5142 /* If they gave us no args, assume they want the last backgrounded task */
5141 if (!argv[1]) { 5143 if (!argv[1]) {
@@ -5163,7 +5165,7 @@ static int builtin_fg_bg(char **argv)
5163 // of job being foregrounded (like "sleep 1 | cat") 5165 // of job being foregrounded (like "sleep 1 | cat")
5164 if (*argv[0] == 'f') { 5166 if (*argv[0] == 'f') {
5165 /* Put the job into the foreground. */ 5167 /* Put the job into the foreground. */
5166 tcsetpgrp(G.interactive_fd, pi->pgrp); 5168 tcsetpgrp(G_interactive_fd, pi->pgrp);
5167 } 5169 }
5168 5170
5169 /* Restart the processes in the job */ 5171 /* Restart the processes in the job */