From: Chet Ramey Date: Fri, 29 Aug 2014 13:15:21 +0000 (-0400) Subject: commit bash-20140815 snapshot X-Git-Tag: bash-4.4-alpha~60 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=581fe5894cf309bbd703b2d2a16cb855c0093070;p=thirdparty%2Fbash.git commit bash-20140815 snapshot --- diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 4748c6331..a419df988 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -6515,3 +6515,40 @@ parse.y token. This lets the higher layers deal with quoted newlines after the command substitution. Fixes bug reported by EmanueL Czirai + + 8/11 + ---- +execute_cmd.c + - execute_pipeline: check whether lastpipe_jid corresponds to a valid + job before calling append_process, for the same reason as fix from + 6/19. Fixes bug reported by + + 8/12 + ---- +lib/sh/unicode.c + - stub_charset: use strncpy instead of strcpy because we are copying + into a local fixed-length buffer. Fixes vulnerability reported by + + +execute_cmd.c + - execute_pipeline: if we don't call append_process, call + wait_for_single_pid to get the status of `lastpid', since that will + check the status of already-reaped processes. Fixes spurious error + message about non-existent process from fix of 8/11 + + 8/15 + ---- +jobs.c + - running_in_background: new variable, keeps track of whether or not we + are running in the background (not perfect yet) + - initialize_job_control: even if we are not turning on job control, + get the terminal pgrp so we can use it later + - {set_job_control,initialize_job_control}: set running_in_background + to 1 if terminal pgrp != shell pgrp + - {stop_pipeline,make_child,wait_for}: if we are running in the + background, don't mess with the terminal's process group; assume that + the parent shell will do that. Fixes bug reprted by Greg Wooledge + + +shell.c + - shell_reinitialize: reset running_in_background back to 0 diff --git a/execute_cmd.c b/execute_cmd.c index f0f115b85..1f5c9e2e0 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -1469,7 +1469,7 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close) login_shell = interactive = 0; if (user_subshell) - subshell_environment = SUBSHELL_PAREN; + subshell_environment = SUBSHELL_PAREN; /* XXX */ else { subshell_environment = 0; /* XXX */ @@ -2432,9 +2432,17 @@ execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close) if (lastpipe_flag) { #if defined (JOB_CONTROL) - append_process (savestring (the_printed_command), dollar_dollar_pid, exec_result, lastpipe_jid); -#endif + if (INVALID_JOB (lastpipe_jid) == 0) + { + append_process (savestring (the_printed_command_except_trap), dollar_dollar_pid, exec_result, lastpipe_jid); + lstdin = wait_for (lastpid); + } + else + lstdin = wait_for_single_pid (lastpid); /* checks bgpids list */ +#else lstdin = wait_for (lastpid); +#endif + #if defined (JOB_CONTROL) /* If wait_for removes the job from the jobs table, use result of last command as pipeline's exit status as usual. The jobs list can get @@ -3973,7 +3981,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close) already_forked = 1; simple_command->flags |= CMD_NO_FORK; - subshell_environment = SUBSHELL_FORK; + subshell_environment = SUBSHELL_FORK; /* XXX */ if (pipe_in != NO_PIPE || pipe_out != NO_PIPE) subshell_environment |= SUBSHELL_PIPE; if (async) @@ -5000,7 +5008,7 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, if (async) interactive = 0; - subshell_environment = SUBSHELL_FORK; + subshell_environment = SUBSHELL_FORK; /* XXX */ if (redirects && (do_redirections (redirects, RX_ACTIVE) != 0)) { diff --git a/jobs.c b/jobs.c index c45f43c06..5ab779bba 100644 --- a/jobs.c +++ b/jobs.c @@ -223,6 +223,9 @@ PROCESS *the_pipeline = (PROCESS *)NULL; /* If this is non-zero, do job control. */ int job_control = 1; +/* Are we running in background? (terminal_pgrp != shell_pgrp) */ +int running_in_background = 0; + /* Call this when you start making children. */ int already_making_children = 0; @@ -640,10 +643,11 @@ stop_pipeline (async, deferred) * the parent gives it away. * * Don't give the terminal away if this shell is an asynchronous - * subshell. + * subshell or if we're a (presumably non-interactive) shell running + * in the background. * */ - if (job_control && newjob->pgrp && (subshell_environment&SUBSHELL_ASYNC) == 0) + if (job_control && newjob->pgrp && (subshell_environment&SUBSHELL_ASYNC) == 0 && running_in_background == 0) maybe_give_terminal_to (shell_pgrp, newjob->pgrp, 0); } } @@ -1824,7 +1828,7 @@ make_child (command, async_p) In this case, we don't want to give the terminal to the shell's process group (we could be in the middle of a pipeline, for example). */ - if (async_p == 0 && pipeline_pgrp != shell_pgrp && ((subshell_environment&SUBSHELL_ASYNC) == 0)) + if (async_p == 0 && pipeline_pgrp != shell_pgrp && ((subshell_environment&SUBSHELL_ASYNC) == 0) && running_in_background == 0) give_terminal_to (pipeline_pgrp, 0); #if defined (PGRP_PIPE) @@ -2580,7 +2584,9 @@ itrace("wait_for: blocking wait for %d returns %d child = %p", (int)pid, r, chil if (job == NO_JOB) itrace("wait_for: job == NO_JOB, giving the terminal to shell_pgrp (%ld)", (long)shell_pgrp); #endif - give_terminal_to (shell_pgrp, 0); + /* Don't modify terminal pgrp if we are running in the background */ + if (running_in_background == 0) + give_terminal_to (shell_pgrp, 0); } /* If the command did not exit cleanly, or the job is just @@ -3790,6 +3796,7 @@ initialize_job_control (force) job_control = 0; original_pgrp = NO_PID; shell_tty = fileno (stderr); + terminal_pgrp = tcgetpgrp (shell_tty); /* for checking later */ } else { @@ -3890,6 +3897,8 @@ initialize_job_control (force) internal_error (_("no job control in this shell")); } + running_in_background = terminal_pgrp != shell_pgrp; + if (shell_tty != fileno (stderr)) SET_CLOSE_ON_EXEC (shell_tty); @@ -4088,7 +4097,7 @@ maybe_give_terminal_to (opgrp, npgrp, flags) else if (tpgrp != opgrp) { #if defined (DEBUG) - internal_warning ("maybe_give_terminal_to: terminal pgrp == %d shell pgrp = %d new pgrp = %d", tpgrp, opgrp, npgrp); + internal_warning ("%d: maybe_give_terminal_to: terminal pgrp == %d shell pgrp = %d new pgrp = %d in_background = %d", (int)getpid(), tpgrp, opgrp, npgrp, running_in_background); #endif return -1; } @@ -4352,6 +4361,21 @@ set_job_control (arg) old = job_control; job_control = arg; + if (terminal_pgrp == NO_PID) + terminal_pgrp = tcgetpgrp (shell_tty); + + running_in_background = (terminal_pgrp != shell_pgrp); + +#if 0 + if (interactive_shell == 0 && running_in_background == 0 && job_control != old) + { + if (job_control) + initialize_job_signals (); + else + default_tty_job_signals (); + } +#endif + /* If we're turning on job control, reset pipeline_pgrp so make_child will put new child processes into the right pgrp */ if (job_control != old && job_control) diff --git a/lib/sh/unicode.c b/lib/sh/unicode.c index 9ee7147d7..798260ecd 100644 --- a/lib/sh/unicode.c +++ b/lib/sh/unicode.c @@ -78,13 +78,15 @@ stub_charset () s = strrchr (locale, '.'); if (s) { - strcpy (charsetbuf, s+1); + strncpy (charsetbuf, s+1, sizeof (charsetbuf) - 1); + charsetbuf[sizeof (charsetbuf) - 1] = '\0'; t = strchr (charsetbuf, '@'); if (t) *t = 0; return charsetbuf; } - strcpy (charsetbuf, locale); + strncpy (charsetbuf, locale, sizeof (charsetbuf) - 1); + charsetbuf[sizeof (charsetbuf) - 1] = '\0'; return charsetbuf; } #endif diff --git a/nojobs.c b/nojobs.c index 0c9bd751b..28519c5db 100644 --- a/nojobs.c +++ b/nojobs.c @@ -99,6 +99,8 @@ int check_window_size = CHECKWINSIZE_DEFAULT; /* We don't have job control. */ int job_control = 0; +int running_in_background = 0; /* can't tell without job control */ + /* STATUS and FLAGS are only valid if pid != NO_PID STATUS is only valid if (flags & PROC_RUNNING) == 0 */ struct proc_status { diff --git a/patchlevel.h b/patchlevel.h index c8605ba6f..9f74b87bb 100644 --- a/patchlevel.h +++ b/patchlevel.h @@ -25,6 +25,6 @@ regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh looks for to find the patch level (for the sccs version string). */ -#define PATCHLEVEL 22 +#define PATCHLEVEL 24 #endif /* _PATCHLEVEL_H_ */ diff --git a/shell.c b/shell.c index cf929dc5e..b743d149b 100644 --- a/shell.c +++ b/shell.c @@ -100,6 +100,7 @@ extern char *dist_version, *release_status; extern int patch_level, build_version; extern int shell_level; extern int subshell_environment; +extern int running_in_background; extern int last_command_exit_value; extern int line_number; extern int expand_aliases; @@ -1804,7 +1805,8 @@ shell_reinitialize () /* Things that get 0. */ login_shell = make_login_shell = interactive = executing = 0; debugging = do_version = line_number = last_command_exit_value = 0; - forced_interactive = interactive_shell = subshell_environment = 0; + forced_interactive = interactive_shell = 0; + subshell_environment = running_in_background = 0; expand_aliases = 0; /* XXX - should we set jobs_m_flag to 0 here? */