aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2020-07-17 01:21:20 -0400
committerJesse Luehrs <doy@tozt.net>2020-07-17 01:21:20 -0400
commit6985d5dd288ebc665fa5b342d013fba656276a61 (patch)
treee422c2fca52c1ca26c4e8f3ea0b8af25f0785e85
parent1996a03987a5a8c7e50a16a7a63b6dbdcd0424ad (diff)
downloadpty-process-6985d5dd288ebc665fa5b342d013fba656276a61.tar.gz
pty-process-6985d5dd288ebc665fa5b342d013fba656276a61.zip
make the pty the controlling terminal for the child spawned into it
this is necessary to propagate SIGWINCH signals, among other things
-rw-r--r--src/command.rs18
1 files changed, 16 insertions, 2 deletions
diff --git a/src/command.rs b/src/command.rs
index cf1925d..7377881 100644
--- a/src/command.rs
+++ b/src/command.rs
@@ -35,10 +35,17 @@ impl Command for std::process::Command {
.stdout(unsafe { std::process::Stdio::from_raw_fd(stdout) })
.stderr(unsafe { std::process::Stdio::from_raw_fd(stderr) });
- // safe because the only thing this function does is call close(),
- // which is an async-signal-safe function
+ // XXX not entirely safe - setsid() and close() are async-signal-safe
+ // functions, but ioctl() is not, and only async-signal-safe functions
+ // are allowed to be called between fork() and exec(). other things
+ // seem to be able to get away with this though, so i'm not sure what
+ // the right answer here is?
unsafe {
self.pre_exec(move || {
+ nix::unistd::setsid().map_err(|e| e.as_errno().unwrap())?;
+ set_controlling_terminal(pts_fd, std::ptr::null())
+ .map_err(|e| e.as_errno().unwrap())?;
+
// in the parent, destructors will handle closing these file
// descriptors (other than pt, used by the parent to
// communicate with the child) when the function ends, but in
@@ -59,6 +66,7 @@ impl Command for std::process::Command {
.map_err(|e| e.as_errno().unwrap())?;
nix::unistd::close(stderr)
.map_err(|e| e.as_errno().unwrap())?;
+
Ok(())
});
}
@@ -97,3 +105,9 @@ impl std::ops::DerefMut for Child {
&mut self.child
}
}
+
+nix::ioctl_write_ptr_bad!(
+ set_controlling_terminal,
+ libc::TIOCSCTTY,
+ libc::c_int
+);