stevenkhan commited on
Commit
cd206cc
·
verified ·
1 Parent(s): 8b1fe8d

Upload spectral-pty/src/unix.rs

Browse files
Files changed (1) hide show
  1. spectral-pty/src/unix.rs +89 -0
spectral-pty/src/unix.rs ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ use libc;
2
+ use std::fs::File;
3
+ use std::io::{self, Read, Write};
4
+ use std::os::fd::{AsRawFd, FromRawFd, RawFd};
5
+
6
+ use crate::PtyTrait;
7
+
8
+ pub struct Pty {
9
+ pub master: File,
10
+ pub child_pid: libc::pid_t,
11
+ pub shell_path: String,
12
+ }
13
+
14
+ impl Pty {
15
+ pub fn new(cols: u16, rows: u16, shell: Option<&str>) -> io::Result<Self> {
16
+ let shell_path = shell.map(|s| s.to_string()).unwrap_or_else(|| {
17
+ std::env::var("SHELL").unwrap_or_else(|_| "/bin/sh".to_string())
18
+ });
19
+ let shell = shell_path.as_str();
20
+
21
+ let mut winsize = libc::winsize {
22
+ ws_row: rows, ws_col: cols, ws_xpixel: 0, ws_ypixel: 0,
23
+ };
24
+
25
+ let mut master_fd: RawFd = -1;
26
+ let mut slave_fd: RawFd = -1;
27
+
28
+ unsafe {
29
+ if libc::openpty(
30
+ &mut master_fd, &mut slave_fd,
31
+ std::ptr::null_mut(), std::ptr::null(), &mut winsize,
32
+ ) != 0 { return Err(io::Error::last_os_error()); }
33
+ }
34
+
35
+ let child_pid = unsafe { libc::fork() };
36
+ if child_pid < 0 { return Err(io::Error::last_os_error()); }
37
+
38
+ if child_pid == 0 {
39
+ unsafe {
40
+ libc::close(master_fd);
41
+ libc::setsid();
42
+ libc::ioctl(slave_fd, libc::TIOCSCTTY, 0);
43
+ libc::dup2(slave_fd, 0);
44
+ libc::dup2(slave_fd, 1);
45
+ libc::dup2(slave_fd, 2);
46
+ if slave_fd > 2 { libc::close(slave_fd); }
47
+ let shell_c = std::ffi::CString::new(shell).unwrap();
48
+ let arg0_c = std::ffi::CString::new("-").unwrap();
49
+ libc::execvp(shell_c.as_ptr(), [arg0_c.as_ptr(), std::ptr::null()].as_ptr());
50
+ libc::_exit(1);
51
+ }
52
+ }
53
+
54
+ unsafe { libc::close(slave_fd); }
55
+ let master = unsafe { File::from_raw_fd(master_fd) };
56
+
57
+ Ok(Self { master, child_pid, shell_path })
58
+ }
59
+ }
60
+
61
+ impl PtyTrait for Pty {
62
+ fn resize(&mut self, cols: u16, rows: u16) -> io::Result<()> {
63
+ let winsize = libc::winsize {
64
+ ws_row: rows, ws_col: cols, ws_xpixel: 0, ws_ypixel: 0,
65
+ };
66
+ let fd = self.master.as_raw_fd();
67
+ unsafe {
68
+ if libc::ioctl(fd, libc::TIOCSWINSZ, &winsize) != 0 {
69
+ return Err(io::Error::last_os_error());
70
+ }
71
+ }
72
+ Ok(())
73
+ }
74
+
75
+ fn pid(&self) -> Option<u32> { Some(self.child_pid as u32) }
76
+ }
77
+
78
+ impl Read for Pty {
79
+ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.master.read(buf) }
80
+ }
81
+
82
+ impl Write for Pty {
83
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.master.write(buf) }
84
+ fn flush(&mut self) -> io::Result<()> { self.master.flush() }
85
+ }
86
+
87
+ impl Drop for Pty {
88
+ fn drop(&mut self) { unsafe { libc::kill(self.child_pid, libc::SIGHUP); } }
89
+ }