3
3
use crate :: error:: Error ;
4
4
use nix;
5
5
use nix:: fcntl:: { open, OFlag } ;
6
+ use nix:: libc:: { ioctl, TIOCSCTTY } ;
6
7
use nix:: libc:: { STDERR_FILENO , STDIN_FILENO , STDOUT_FILENO } ;
7
8
use nix:: pty:: { grantpt, posix_openpt, unlockpt, PtyMaster } ;
8
9
pub use nix:: sys:: { signal, wait} ;
@@ -86,7 +87,7 @@ impl PtyProcess {
86
87
/// Start a process in a forked pty
87
88
pub fn new ( mut command : Command ) -> Result < Self , Error > {
88
89
// Open a new PTY master
89
- let master_fd = posix_openpt ( OFlag :: O_RDWR ) ?;
90
+ let master_fd = posix_openpt ( OFlag :: O_RDWR | OFlag :: O_NOCTTY ) ?;
90
91
91
92
// Allow a slave to be generated for it
92
93
grantpt ( & master_fd) ?;
@@ -112,16 +113,31 @@ impl PtyProcess {
112
113
dup2 ( slave_fd, STDOUT_FILENO ) ?;
113
114
dup2 ( slave_fd, STDERR_FILENO ) ?;
114
115
116
+ unsafe {
117
+ match ioctl ( master_fd. as_raw_fd ( ) , TIOCSCTTY ) {
118
+ 0 => Ok ( ( ) ) ,
119
+ _ => Err ( nix:: Error :: last ( ) ) ,
120
+ } ?;
121
+ }
122
+
115
123
// Avoid leaking slave fd
116
124
if slave_fd > STDERR_FILENO {
117
125
close ( slave_fd) ?;
118
126
}
119
127
120
128
// set echo off
121
129
let mut flags = termios:: tcgetattr ( STDIN_FILENO ) ?;
122
- flags. local_flags &= ! termios:: LocalFlags :: ECHO ;
130
+ flags. local_flags . remove ( termios:: LocalFlags :: ECHO ) ;
123
131
termios:: tcsetattr ( STDIN_FILENO , termios:: SetArg :: TCSANOW , & flags) ?;
124
132
133
+ loop {
134
+ flags = termios:: tcgetattr ( STDIN_FILENO ) ?;
135
+ if !flags. local_flags . contains ( termios:: LocalFlags :: ECHO ) {
136
+ break ;
137
+ }
138
+ std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 100 ) ) ;
139
+ }
140
+
125
141
command. exec ( ) ;
126
142
Err ( Error :: Nix ( nix:: Error :: last ( ) ) )
127
143
}
0 commit comments