1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
#[cfg(unix)]
use std::os::fd::RawFd;
#[cfg(unix)]
pub(crate) fn duplicate_fd(fd: RawFd) -> std::io::Result<RawFd> {
let duplicated = unsafe { libc::dup(fd) };
if duplicated < 0 {
return Err(std::io::Error::last_os_error());
}
Ok(duplicated)
}
#[cfg(unix)]
pub(crate) fn set_cloexec(fd: RawFd) -> std::io::Result<()> {
let flags = unsafe { libc::fcntl(fd, libc::F_GETFD) };
if flags < 0 {
return Err(std::io::Error::last_os_error());
}
if unsafe { libc::fcntl(fd, libc::F_SETFD, flags | libc::FD_CLOEXEC) } < 0 {
return Err(std::io::Error::last_os_error());
}
Ok(())
}
#[cfg(unix)]
pub(crate) fn set_nonblocking(fd: RawFd) -> std::io::Result<()> {
let flags = unsafe { libc::fcntl(fd, libc::F_GETFL) };
if flags < 0 {
return Err(std::io::Error::last_os_error());
}
if unsafe { libc::fcntl(fd, libc::F_SETFL, flags | libc::O_NONBLOCK) } < 0 {
return Err(std::io::Error::last_os_error());
}
Ok(())
}
#[cfg(unix)]
pub(crate) fn duplicate_cloexec_fd(fd: RawFd) -> std::io::Result<RawFd> {
let duplicated = duplicate_fd(fd)?;
if let Err(err) = set_cloexec(duplicated) {
let _ = unsafe { libc::close(duplicated) };
return Err(err);
}
Ok(duplicated)
}
#[cfg(unix)]
pub(crate) fn poll_read_ready(fd: RawFd, timeout_ms: i32) -> std::io::Result<bool> {
let mut poll_fd = libc::pollfd {
fd,
events: libc::POLLIN,
revents: 0,
};
loop {
let result = unsafe { libc::poll(&mut poll_fd, 1, timeout_ms) };
if result < 0 {
let err = std::io::Error::last_os_error();
if err.kind() == std::io::ErrorKind::Interrupted {
continue;
}
return Err(err);
}
return Ok(result > 0 && (poll_fd.revents & (libc::POLLIN | libc::POLLHUP)) != 0);
}
}
#[cfg(unix)]
pub(crate) fn poll_write_ready(fd: RawFd, timeout_ms: i32) -> std::io::Result<bool> {
let mut poll_fd = libc::pollfd {
fd,
events: libc::POLLOUT,
revents: 0,
};
loop {
let result = unsafe { libc::poll(&mut poll_fd, 1, timeout_ms) };
if result < 0 {
let err = std::io::Error::last_os_error();
if err.kind() == std::io::ErrorKind::Interrupted {
continue;
}
return Err(err);
}
return Ok(result > 0 && (poll_fd.revents & (libc::POLLOUT | libc::POLLHUP)) != 0);
}
}
#[cfg(unix)]
pub(crate) fn resize_pty_fd(
fd: RawFd,
rows: u16,
cols: u16,
cell_width_px: u32,
cell_height_px: u32,
) -> std::io::Result<()> {
let size = libc::winsize {
ws_row: rows,
ws_col: cols,
ws_xpixel: (cols as u32)
.saturating_mul(cell_width_px)
.min(u16::MAX as u32) as u16,
ws_ypixel: (rows as u32)
.saturating_mul(cell_height_px)
.min(u16::MAX as u32) as u16,
};
if unsafe { libc::ioctl(fd, libc::TIOCSWINSZ, &size) } < 0 {
return Err(std::io::Error::last_os_error());
}
Ok(())
}
|