Skip to content

Add a method to set the controlling tty of child processes (unix). #28982

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions src/libstd/sys/unix/ext/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,18 @@ pub trait CommandExt {
/// that the child is the leader of a new process group. The parent process
/// remains the child reaper of the new process.
///
/// If the tty argument is not `None`, this file will be the controlling
/// terminal for the new session (cf. `login_tty(3)` and tty_ioctl(4),
/// specifically the section on `TIOCSCTTY`). Note that this does not set
/// that file to be the stdio handles for the child process, to do that you
/// must set them directly with the `stdin()` et al methods.
///
/// This is not enough to create a daemon process. The *init* process should
/// be the child reaper of a daemon. This can be achieved if the parent
/// process exit. Moreover, a daemon should not have a controlling terminal.
/// To achieve this, a session leader (the child) must spawn another process
/// (the daemon) in the same session.
#[unstable(feature = "process_session_leader", reason = "recently added",
issue = "27811")]
fn session_leader(&mut self, on: bool) -> &mut process::Command;
fn session_leader<T: AsRawFd>(&mut self, tty: Option<&T>) -> &mut process::Command;
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand All @@ -58,8 +62,12 @@ impl CommandExt for process::Command {
self
}

fn session_leader(&mut self, on: bool) -> &mut process::Command {
self.as_inner_mut().session_leader = on;
fn session_leader<T: AsRawFd>(&mut self, tty: Option<&T>) -> &mut process::Command {
{
let inner = self.as_inner_mut();
inner.session_leader = true;
inner.tty = tty.map(T::as_raw_fd);
}
self
}
}
Expand Down
18 changes: 18 additions & 0 deletions src/libstd/sys/unix/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub struct Command {
pub uid: Option<uid_t>,
pub gid: Option<gid_t>,
pub session_leader: bool,
pub tty: Option<RawFd>,
}

impl Command {
Expand All @@ -49,6 +50,7 @@ impl Command {
uid: None,
gid: None,
session_leader: false,
tty: None,
}
}

Expand Down Expand Up @@ -307,7 +309,23 @@ impl Process {
// process leader already. We just forked so it shouldn't return
// error, but ignore it anyway.
let _ = libc::setsid();

// Associate the tty file descriptor with the controlling terminal,
// then close it unless it is an stdio handle. Errors returned by
// close are ignored.
if let Some(tty) = cfg.tty {

const TIOCSCTTY: u64 = 0x540E;

if cvt_r(|| libc::funcs::bsd44::ioctl(tty, TIOCSCTTY)).is_err() {
fail(&mut output);
} else if tty > 2 {
let _ = libc::close(tty);
}

}
}

if !dirp.is_null() && libc::chdir(dirp) == -1 {
fail(&mut output);
}
Expand Down