summaryrefslogtreecommitdiff
path: root/src/sys/termios.rs
diff options
context:
space:
mode:
authorSteve Lau <stevelauc@outlook.com>2022-12-08 14:04:22 +0800
committerSteve Lau <stevelauc@outlook.com>2022-12-08 14:04:22 +0800
commit8f52bc97c96922f61140948eacabf966712d105e (patch)
tree5271be5f4aed5ec73304796b002bbfd2edbed76d /src/sys/termios.rs
parent67f7d46c6e9d2089f03b2322d31dcb4b388eb730 (diff)
downloadnix-8f52bc97c96922f61140948eacabf966712d105e.zip
feat: I/O safety for 'sys/termios' & 'pty'
Diffstat (limited to 'src/sys/termios.rs')
-rw-r--r--src/sys/termios.rs49
1 files changed, 34 insertions, 15 deletions
diff --git a/src/sys/termios.rs b/src/sys/termios.rs
index fba2cd82..4cc635bc 100644
--- a/src/sys/termios.rs
+++ b/src/sys/termios.rs
@@ -222,7 +222,7 @@ use libc::{self, c_int, tcflag_t};
use std::cell::{Ref, RefCell};
use std::convert::From;
use std::mem;
-use std::os::unix::io::RawFd;
+use std::os::unix::io::{AsFd, AsRawFd};
#[cfg(feature = "process")]
use crate::unistd::Pid;
@@ -1143,10 +1143,12 @@ pub fn cfmakesane(termios: &mut Termios) {
/// `tcgetattr()` returns a `Termios` structure with the current configuration for a port. Modifying
/// this structure *will not* reconfigure the port, instead the modifications should be done to
/// the `Termios` structure and then the port should be reconfigured using `tcsetattr()`.
-pub fn tcgetattr(fd: RawFd) -> Result<Termios> {
+pub fn tcgetattr<Fd: AsFd>(fd: &Fd) -> Result<Termios> {
let mut termios = mem::MaybeUninit::uninit();
- let res = unsafe { libc::tcgetattr(fd, termios.as_mut_ptr()) };
+ let res = unsafe {
+ libc::tcgetattr(fd.as_fd().as_raw_fd(), termios.as_mut_ptr())
+ };
Errno::result(res)?;
@@ -1159,18 +1161,26 @@ pub fn tcgetattr(fd: RawFd) -> Result<Termios> {
/// `tcsetattr()` reconfigures the given port based on a given `Termios` structure. This change
/// takes affect at a time specified by `actions`. Note that this function may return success if
/// *any* of the parameters were successfully set, not only if all were set successfully.
-pub fn tcsetattr(fd: RawFd, actions: SetArg, termios: &Termios) -> Result<()> {
+pub fn tcsetattr<Fd: AsFd>(
+ fd: &Fd,
+ actions: SetArg,
+ termios: &Termios,
+) -> Result<()> {
let inner_termios = termios.get_libc_termios();
Errno::result(unsafe {
- libc::tcsetattr(fd, actions as c_int, &*inner_termios)
+ libc::tcsetattr(
+ fd.as_fd().as_raw_fd(),
+ actions as c_int,
+ &*inner_termios,
+ )
})
.map(drop)
}
/// Block until all output data is written (see
/// [tcdrain(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcdrain.html)).
-pub fn tcdrain(fd: RawFd) -> Result<()> {
- Errno::result(unsafe { libc::tcdrain(fd) }).map(drop)
+pub fn tcdrain<Fd: AsFd>(fd: &Fd) -> Result<()> {
+ Errno::result(unsafe { libc::tcdrain(fd.as_fd().as_raw_fd()) }).map(drop)
}
/// Suspend or resume the transmission or reception of data (see
@@ -1178,8 +1188,11 @@ pub fn tcdrain(fd: RawFd) -> Result<()> {
///
/// `tcflow()` suspends of resumes the transmission or reception of data for the given port
/// depending on the value of `action`.
-pub fn tcflow(fd: RawFd, action: FlowArg) -> Result<()> {
- Errno::result(unsafe { libc::tcflow(fd, action as c_int) }).map(drop)
+pub fn tcflow<Fd: AsFd>(fd: &Fd, action: FlowArg) -> Result<()> {
+ Errno::result(unsafe {
+ libc::tcflow(fd.as_fd().as_raw_fd(), action as c_int)
+ })
+ .map(drop)
}
/// Discard data in the output or input queue (see
@@ -1187,8 +1200,11 @@ pub fn tcflow(fd: RawFd, action: FlowArg) -> Result<()> {
///
/// `tcflush()` will discard data for a terminal port in the input queue, output queue, or both
/// depending on the value of `action`.
-pub fn tcflush(fd: RawFd, action: FlushArg) -> Result<()> {
- Errno::result(unsafe { libc::tcflush(fd, action as c_int) }).map(drop)
+pub fn tcflush<Fd: AsFd>(fd: &Fd, action: FlushArg) -> Result<()> {
+ Errno::result(unsafe {
+ libc::tcflush(fd.as_fd().as_raw_fd(), action as c_int)
+ })
+ .map(drop)
}
/// Send a break for a specific duration (see
@@ -1196,16 +1212,19 @@ pub fn tcflush(fd: RawFd, action: FlushArg) -> Result<()> {
///
/// When using asynchronous data transmission `tcsendbreak()` will transmit a continuous stream
/// of zero-valued bits for an implementation-defined duration.
-pub fn tcsendbreak(fd: RawFd, duration: c_int) -> Result<()> {
- Errno::result(unsafe { libc::tcsendbreak(fd, duration) }).map(drop)
+pub fn tcsendbreak<Fd: AsFd>(fd: &Fd, duration: c_int) -> Result<()> {
+ Errno::result(unsafe {
+ libc::tcsendbreak(fd.as_fd().as_raw_fd(), duration)
+ })
+ .map(drop)
}
feature! {
#![feature = "process"]
/// Get the session controlled by the given terminal (see
/// [tcgetsid(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetsid.html)).
-pub fn tcgetsid(fd: RawFd) -> Result<Pid> {
- let res = unsafe { libc::tcgetsid(fd) };
+pub fn tcgetsid<Fd: AsFd>(fd: &Fd) -> Result<Pid> {
+ let res = unsafe { libc::tcgetsid(fd.as_fd().as_raw_fd()) };
Errno::result(res).map(Pid::from_raw)
}