diff --git a/src/descriptor/err.rs b/src/descriptor.rs similarity index 61% rename from src/descriptor/err.rs rename to src/descriptor.rs index c18665e..0781b1d 100644 --- a/src/descriptor/err.rs +++ b/src/descriptor.rs @@ -1,5 +1,9 @@ -use std::error::Error; -use std::fmt; +use std::{ + error::Error, + ffi::CStr, + fmt, + os::fd::{FromRawFd, OwnedFd}, +}; /// The enum `DescriptorError` defines the possible errors /// from constructor Descriptor. @@ -33,3 +37,19 @@ impl Error for DescriptorError { None } } + +/// Open the given file as a file descriptor. +pub fn open( + path: &CStr, + flag: libc::c_int, + mode: Option, +) -> Result { + // Safety: we've just ensured that path is non-null and the + // other params are valid by construction. + unsafe { + match libc::open(path.as_ptr().cast(), flag, mode.unwrap_or_default()) { + -1 => Err(DescriptorError::OpenFail), + fd => Ok(OwnedFd::from_raw_fd(fd)), + } + } +} diff --git a/src/descriptor/mod.rs b/src/descriptor/mod.rs deleted file mode 100644 index ed59e85..0000000 --- a/src/descriptor/mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -mod err; - -pub use self::err::DescriptorError; -use std::{ - ffi::CStr, - os::fd::{FromRawFd, OwnedFd}, -}; - -/// Open the given file as a file descriptor. -pub fn open( - path: &CStr, - flag: libc::c_int, - mode: Option, -) -> Result { - // Safety: we've just ensured that path is non-null and the - // other params are valid by construction. - unsafe { - match libc::open(path.as_ptr().cast(), flag, mode.unwrap_or_default()) { - -1 => Err(DescriptorError::OpenFail), - fd => Ok(OwnedFd::from_raw_fd(fd)), - } - } -} diff --git a/src/fork/mod.rs b/src/fork.rs similarity index 67% rename from src/fork/mod.rs rename to src/fork.rs index a5163df..c0ea26f 100644 --- a/src/fork/mod.rs +++ b/src/fork.rs @@ -1,11 +1,79 @@ -mod err; mod pty; -pub use self::err::{ForkError, Result}; pub use self::pty::{Master, MasterError}; pub use self::pty::{Slave, SlaveError}; +use crate::descriptor::DescriptorError; +use std::error::Error; use std::ffi::CStr; use std::ffi::CString; +use std::fmt; + +/// The alias `Result` learns `ForkError` possibility. +pub type Result = ::std::result::Result; + +/// The enum `ForkError` defines the possible errors from constructor Fork. +#[derive(Clone, Copy, Debug)] +pub enum ForkError { + /// Can't creates the child. + Failure, + /// Can't set the id group. + SetsidFail, + /// Can't suspending the calling process. + WaitpidFail, + /// Is child and not parent. + IsChild, + /// Is parent and not child. + IsParent, + /// The Master occured a error. + BadMaster(MasterError), + /// The Slave occured a error. + BadSlave(SlaveError), + /// The Master's Descriptor occured a error. + BadDescriptorMaster(DescriptorError), + /// The Slave's Descriptor occured a error. + BadDescriptorSlave(DescriptorError), +} + +impl fmt::Display for ForkError { + /// The function `fmt` formats the value using the given formatter. + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", ::errno::errno()) + } +} + +impl Error for ForkError { + /// The function `description` returns a short description of the error. + fn description(&self) -> &str { + match *self { + ForkError::Failure => { + "On failure, -1 is returned in the parent,no child process is created, and errno \ + isset appropriately." + } + ForkError::SetsidFail => { + "fails if the calling process is alreadya process group leader." + } + ForkError::WaitpidFail => "Can't suspending the calling process.", + ForkError::IsChild => "is child and not parent", + ForkError::IsParent => "is parent and not child", + ForkError::BadMaster(_) => "the master as occured an error", + ForkError::BadSlave(_) => "the slave as occured an error", + ForkError::BadDescriptorMaster(_) => "the master's descriptor as occured an error", + ForkError::BadDescriptorSlave(_) => "the slave's descriptor as occured an error", + } + } + + /// The function `cause` returns the lower-level cause of this error, if + /// any. + fn cause(&self) -> Option<&dyn Error> { + match *self { + ForkError::BadMaster(ref err) => Some(err), + ForkError::BadSlave(ref err) => Some(err), + ForkError::BadDescriptorMaster(ref err) => Some(err), + ForkError::BadDescriptorSlave(ref err) => Some(err), + _ => None, + } + } +} const MAX_PTS_NAME: usize = 1024; diff --git a/src/fork/err.rs b/src/fork/err.rs deleted file mode 100644 index f5b3f5d..0000000 --- a/src/fork/err.rs +++ /dev/null @@ -1,72 +0,0 @@ -use descriptor::DescriptorError; -use std::error::Error; -use std::fmt; - -use super::pty::{MasterError, SlaveError}; - -/// The alias `Result` learns `ForkError` possibility. -pub type Result = ::std::result::Result; - -/// The enum `ForkError` defines the possible errors from constructor Fork. -#[derive(Clone, Copy, Debug)] -pub enum ForkError { - /// Can't creates the child. - Failure, - /// Can't set the id group. - SetsidFail, - /// Can't suspending the calling process. - WaitpidFail, - /// Is child and not parent. - IsChild, - /// Is parent and not child. - IsParent, - /// The Master occured a error. - BadMaster(MasterError), - /// The Slave occured a error. - BadSlave(SlaveError), - /// The Master's Descriptor occured a error. - BadDescriptorMaster(DescriptorError), - /// The Slave's Descriptor occured a error. - BadDescriptorSlave(DescriptorError), -} - -impl fmt::Display for ForkError { - /// The function `fmt` formats the value using the given formatter. - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", ::errno::errno()) - } -} - -impl Error for ForkError { - /// The function `description` returns a short description of the error. - fn description(&self) -> &str { - match *self { - ForkError::Failure => { - "On failure, -1 is returned in the parent,no child process is created, and errno \ - isset appropriately." - } - ForkError::SetsidFail => { - "fails if the calling process is alreadya process group leader." - } - ForkError::WaitpidFail => "Can't suspending the calling process.", - ForkError::IsChild => "is child and not parent", - ForkError::IsParent => "is parent and not child", - ForkError::BadMaster(_) => "the master as occured an error", - ForkError::BadSlave(_) => "the slave as occured an error", - ForkError::BadDescriptorMaster(_) => "the master's descriptor as occured an error", - ForkError::BadDescriptorSlave(_) => "the slave's descriptor as occured an error", - } - } - - /// The function `cause` returns the lower-level cause of this error, if - /// any. - fn cause(&self) -> Option<&dyn Error> { - match *self { - ForkError::BadMaster(ref err) => Some(err), - ForkError::BadSlave(ref err) => Some(err), - ForkError::BadDescriptorMaster(ref err) => Some(err), - ForkError::BadDescriptorSlave(ref err) => Some(err), - _ => None, - } - } -} diff --git a/src/fork/pty/mod.rs b/src/fork/pty.rs similarity index 100% rename from src/fork/pty/mod.rs rename to src/fork/pty.rs diff --git a/src/fork/pty/master/mod.rs b/src/fork/pty/master.rs similarity index 66% rename from src/fork/pty/master/mod.rs rename to src/fork/pty/master.rs index 653640c..e8391b8 100644 --- a/src/fork/pty/master/mod.rs +++ b/src/fork/pty/master.rs @@ -1,14 +1,11 @@ -mod err; - #[cfg(target_os = "macos")] mod ptsname_r_macos; -use crate::descriptor; - -pub use self::err::{MasterError, Result}; +use crate::descriptor::{self, DescriptorError}; use std::{ + error::Error, ffi::CStr, - io, + fmt, io, os::{ fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd}, unix::io::RawFd, @@ -16,6 +13,46 @@ use std::{ sync::Arc, }; +/// The alias `Result` learns `MasterError` possibility. +pub type Result = ::std::result::Result; + +/// The enum `MasterError` defines the possible errors from constructor Master. +#[derive(Clone, Copy, Debug)] +pub enum MasterError { + BadDescriptor(DescriptorError), + GrantptError, + UnlockptError, + PtsnameError, +} + +impl fmt::Display for MasterError { + /// The function `fmt` formats the value using the given formatter. + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", ::errno::errno()) + } +} + +impl Error for MasterError { + /// The function `description` returns a short description of the error. + fn description(&self) -> &str { + match *self { + MasterError::BadDescriptor(_) => "the descriptor as occured an error", + MasterError::GrantptError => "the `grantpt` has a error, errnois set appropriately.", + MasterError::UnlockptError => "the `grantpt` has a error, errnois set appropriately.", + MasterError::PtsnameError => "the `ptsname` has a error", + } + } + + /// The function `cause` returns the lower-level cause of this error, if + /// any. + fn cause(&self) -> Option<&dyn Error> { + match *self { + MasterError::BadDescriptor(ref err) => Some(err), + _ => None, + } + } +} + #[derive(Debug, Clone)] pub struct Master { pty: Arc, @@ -76,7 +113,8 @@ impl Master { let result = libc::ptsname_r(self.raw_fd(), data as *mut libc::c_char, buf.len()); #[cfg(target_os = "macos")] - let result = ptsname_r_macos::ptsname_r(fd, data as *mut libc::c_char, buf.len()); + let result = + ptsname_r_macos::ptsname_r(self.raw_fd(), data as *mut libc::c_char, buf.len()); match result { 0 => Ok(()), diff --git a/src/fork/pty/master/err.rs b/src/fork/pty/master/err.rs deleted file mode 100644 index 532c64b..0000000 --- a/src/fork/pty/master/err.rs +++ /dev/null @@ -1,43 +0,0 @@ -use descriptor::DescriptorError; -use std::error::Error; -use std::fmt; - -/// The alias `Result` learns `MasterError` possibility. -pub type Result = ::std::result::Result; - -/// The enum `MasterError` defines the possible errors from constructor Master. -#[derive(Clone, Copy, Debug)] -pub enum MasterError { - BadDescriptor(DescriptorError), - GrantptError, - UnlockptError, - PtsnameError, -} - -impl fmt::Display for MasterError { - /// The function `fmt` formats the value using the given formatter. - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", ::errno::errno()) - } -} - -impl Error for MasterError { - /// The function `description` returns a short description of the error. - fn description(&self) -> &str { - match *self { - MasterError::BadDescriptor(_) => "the descriptor as occured an error", - MasterError::GrantptError => "the `grantpt` has a error, errnois set appropriately.", - MasterError::UnlockptError => "the `grantpt` has a error, errnois set appropriately.", - MasterError::PtsnameError => "the `ptsname` has a error", - } - } - - /// The function `cause` returns the lower-level cause of this error, if - /// any. - fn cause(&self) -> Option<&dyn Error> { - match *self { - MasterError::BadDescriptor(ref err) => Some(err), - _ => None, - } - } -} diff --git a/src/fork/pty/slave.rs b/src/fork/pty/slave.rs new file mode 100644 index 0000000..b1e27a7 --- /dev/null +++ b/src/fork/pty/slave.rs @@ -0,0 +1,83 @@ +use crate::descriptor::{self, DescriptorError}; +use std::{ + error::Error, + ffi::CStr, + fmt, + os::{ + fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd}, + unix::io::RawFd, + }, + sync::Arc, +}; + +/// The alias `Result` learns `SlaveError` possibility. +pub type Result = ::std::result::Result; + +/// The enum `SlaveError` defines the possible errors from constructor Slave. +#[derive(Clone, Copy, Debug)] +pub enum SlaveError { + BadDescriptor(DescriptorError), + Dup2Error, +} + +impl fmt::Display for SlaveError { + /// The function `fmt` formats the value using the given formatter. + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", ::errno::errno()) + } +} + +impl Error for SlaveError { + /// The function `description` returns a short description of the error. + fn description(&self) -> &str { + match *self { + SlaveError::BadDescriptor(_) => "the descriptor as occured an error", + SlaveError::Dup2Error => "the `dup2` has a error, errno isset appropriately.", + } + } + + /// The function `cause` returns the lower-level cause of this error, if + /// any. + fn cause(&self) -> Option<&dyn Error> { + match *self { + SlaveError::BadDescriptor(ref err) => Some(err), + _ => None, + } + } +} + +#[derive(Debug, Clone)] +pub struct Slave { + pty: Arc, +} + +impl Slave { + /// The constructor function `new` returns the Slave interface. + pub fn new(path: &CStr) -> Result { + match descriptor::open(path, libc::O_RDWR, None) { + Err(cause) => Err(SlaveError::BadDescriptor(cause)), + Ok(fd) => Ok(Slave { pty: Arc::new(fd) }), + } + } + + /// Extract the raw fd from the underlying object + pub fn raw_fd(&self) -> RawFd { + self.pty.as_raw_fd() + } + + /// Borrow the raw fd + pub fn borrow_fd(&self) -> BorrowedFd<'_> { + self.pty.as_fd() + } + + pub fn dup2(&self, std: libc::c_int) -> Result { + // Safety: pty is live across the lifetime of this call, + // so the fd is valid. + unsafe { + match libc::dup2(self.raw_fd(), std) { + -1 => Err(SlaveError::Dup2Error), + d => Ok(d), + } + } + } +} diff --git a/src/fork/pty/slave/err.rs b/src/fork/pty/slave/err.rs deleted file mode 100644 index 816c7ad..0000000 --- a/src/fork/pty/slave/err.rs +++ /dev/null @@ -1,39 +0,0 @@ -use descriptor::DescriptorError; -use std::error::Error; -use std::fmt; - -/// The alias `Result` learns `SlaveError` possibility. -pub type Result = ::std::result::Result; - -/// The enum `SlaveError` defines the possible errors from constructor Slave. -#[derive(Clone, Copy, Debug)] -pub enum SlaveError { - BadDescriptor(DescriptorError), - Dup2Error, -} - -impl fmt::Display for SlaveError { - /// The function `fmt` formats the value using the given formatter. - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", ::errno::errno()) - } -} - -impl Error for SlaveError { - /// The function `description` returns a short description of the error. - fn description(&self) -> &str { - match *self { - SlaveError::BadDescriptor(_) => "the descriptor as occured an error", - SlaveError::Dup2Error => "the `dup2` has a error, errno isset appropriately.", - } - } - - /// The function `cause` returns the lower-level cause of this error, if - /// any. - fn cause(&self) -> Option<&dyn Error> { - match *self { - SlaveError::BadDescriptor(ref err) => Some(err), - _ => None, - } - } -} diff --git a/src/fork/pty/slave/mod.rs b/src/fork/pty/slave/mod.rs deleted file mode 100644 index 3f8a574..0000000 --- a/src/fork/pty/slave/mod.rs +++ /dev/null @@ -1,50 +0,0 @@ -mod err; - -use crate::descriptor; - -pub use self::err::{Result, SlaveError}; - -use std::{ - ffi::CStr, - os::{ - fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd}, - unix::io::RawFd, - }, - sync::Arc, -}; - -#[derive(Debug, Clone)] -pub struct Slave { - pty: Arc, -} - -impl Slave { - /// The constructor function `new` returns the Slave interface. - pub fn new(path: &CStr) -> Result { - match descriptor::open(path, libc::O_RDWR, None) { - Err(cause) => Err(SlaveError::BadDescriptor(cause)), - Ok(fd) => Ok(Slave { pty: Arc::new(fd) }), - } - } - - /// Extract the raw fd from the underlying object - pub fn raw_fd(&self) -> RawFd { - self.pty.as_raw_fd() - } - - /// Borrow the raw fd - pub fn borrow_fd(&self) -> BorrowedFd<'_> { - self.pty.as_fd() - } - - pub fn dup2(&self, std: libc::c_int) -> Result { - // Safety: pty is live across the lifetime of this call, - // so the fd is valid. - unsafe { - match libc::dup2(self.raw_fd(), std) { - -1 => Err(SlaveError::Dup2Error), - d => Ok(d), - } - } - } -}