diff --git a/src/builtin.cpp b/src/builtin.cpp index faf4af24d..39c77ff78 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -486,7 +486,7 @@ static const wcstring_list_t help_builtins({L"for", L"while", L"function", L"if" static bool cmd_needs_help(const wchar_t *cmd) { return contains(help_builtins, cmd); } /// Execute a builtin command -int builtin_run(parser_t &parser, wchar_t **argv, io_streams_t &streams) { +int builtin_run(parser_t &parser, int job_pgid, wchar_t **argv, io_streams_t &streams) { UNUSED(parser); UNUSED(streams); if (argv == NULL || argv[0] == NULL) return STATUS_INVALID_ARGS; @@ -503,7 +503,7 @@ int builtin_run(parser_t &parser, wchar_t **argv, io_streams_t &streams) { // If we are interactive, save the foreground pgroup and restore it after in case the // builtin needs to read from the terminal. See #4540. bool grab_tty = is_interactive_session && isatty(streams.stdin_fd); - pid_t pgroup_to_restore = grab_tty ? terminal_acquire_before_builtin() : -1; + pid_t pgroup_to_restore = grab_tty ? terminal_acquire_before_builtin(job_pgid) : -1; int ret = data->func(parser, streams, argv); if (pgroup_to_restore >= 0) { tcsetpgrp(STDIN_FILENO, pgroup_to_restore); diff --git a/src/builtin.h b/src/builtin.h index ef9dc2000..ac64f2dc7 100644 --- a/src/builtin.h +++ b/src/builtin.h @@ -88,7 +88,7 @@ enum { COMMAND_NOT_BUILTIN, BUILTIN_REGULAR, BUILTIN_FUNCTION }; void builtin_init(); bool builtin_exists(const wcstring &cmd); -int builtin_run(parser_t &parser, wchar_t **argv, io_streams_t &streams); +int builtin_run(parser_t &parser, int job_pgrp, wchar_t **argv, io_streams_t &streams); wcstring_list_t builtin_get_names(); void builtin_get_names(std::vector *list); diff --git a/src/exec.cpp b/src/exec.cpp index 25dc0f7fa..dc9337cc7 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -484,7 +484,7 @@ static bool exec_internal_builtin_proc(parser_t &parser, job_t *j, process_t *p, j->set_flag(JOB_FOREGROUND, false); // Note this call may block for a long time, while the builtin performs I/O. - p->status = builtin_run(parser, p->get_argv(), streams); + p->status = builtin_run(parser, j->pgid, p->get_argv(), streams); // Restore the fg flag, which is temporarily set to false during builtin // execution so as not to confuse some job-handling builtins. diff --git a/src/proc.cpp b/src/proc.cpp index e23e389a0..da627a540 100644 --- a/src/proc.cpp +++ b/src/proc.cpp @@ -870,10 +870,10 @@ bool terminal_give_to_job(const job_t *j, bool cont) { return true; } -pid_t terminal_acquire_before_builtin() { +pid_t terminal_acquire_before_builtin(int job_pgid) { pid_t selfpid = getpid(); pid_t current_owner = tcgetpgrp(STDIN_FILENO); - if (current_owner >= 0 && current_owner != selfpid) { + if (current_owner >= 0 && current_owner != selfpid && current_owner == job_pgid) { if (tcsetpgrp(STDIN_FILENO, selfpid) == 0) { return current_owner; } diff --git a/src/proc.h b/src/proc.h index 57b2e8526..c85bc3712 100644 --- a/src/proc.h +++ b/src/proc.h @@ -374,6 +374,6 @@ pid_t proc_wait_any(); bool terminal_give_to_job(const job_t *j, bool cont); -/// Given that we are about to run a builtin, acquire the terminal if we do not own it. Returns the -/// pid to restore after running the builtin, or -1 if there is no pid to restore. -pid_t terminal_acquire_before_builtin(); +/// Given that we are about to run a builtin, acquire the terminal if it is owned by the given job. +/// Returns the pid to restore after running the builtin, or -1 if there is no pid to restore. +pid_t terminal_acquire_before_builtin(int job_pgid);