Module termios

An interface for controlling asynchronous communication ports

This interface provides a safe wrapper around the termios subsystem defined by POSIX. The underlying types are all implemented in libc for most platforms and either wrapped in safer types here or exported directly.

If you are unfamiliar with the termios API, you should first read the API documentation and then come back to understand how nix safely wraps it.

It should be noted that this API incurs some runtime overhead above the base libc definitions. As this interface is not used with high-bandwidth information, this should be fine in most cases. The primary cost when using this API is that the Termios datatype here duplicates the standard fields of the underlying termios struct and uses safe type wrappers for those fields. This means that when crossing the FFI interface to the underlying C library, data is first copied into the underlying termios struct, then the operation is done, and the data is copied back (with additional sanity checking) into the safe wrapper types. The termios struct is relatively small across all platforms (on the order of 32-64 bytes).

The following examples highlight some of the API use cases such that users coming from using C or reading the standard documentation will understand how to use the safe API exposed here.

Example disabling processing of the end-of-file control character:

# use self::nix::sys::termios::SpecialCharacterIndices::VEOF;
# use self::nix::sys::termios::{_POSIX_VDISABLE, Termios};
# let mut termios: Termios = unsafe { std::mem::zeroed() };
termios.control_chars[VEOF as usize] = _POSIX_VDISABLE;

The flags within Termios are defined as bitfields using the bitflags crate. This provides an interface for working with bitfields that is similar to working with the raw unsigned integer types but offers type safety because of the internal checking that values will always be a valid combination of the defined flags.

An example showing some of the basic operations for interacting with the control flags:

# use self::nix::sys::termios::{ControlFlags, Termios};
# let mut termios: Termios = unsafe { std::mem::zeroed() };
termios.control_flags & ControlFlags::CSIZE == ControlFlags::CS5;
termios.control_flags |= ControlFlags::CS5;

Baud rates

This API is not consistent across platforms when it comes to BaudRate: Android and Linux both only support the rates specified by the BaudRate enum through their termios API while the BSDs support arbitrary baud rates as the values of the BaudRate enum constants are the same integer value of the constant (B9600 == 9600). Therefore the nix::termios API uses the following conventions:

The most common use case of specifying a baud rate using the enum will work the same across platforms:

# use nix::sys::termios::{BaudRate, cfsetispeed, cfsetospeed, cfsetspeed, Termios};
# fn main() {
# let mut t: Termios = unsafe { std::mem::zeroed() };
cfsetispeed(&mut t, BaudRate::B9600).unwrap();
cfsetospeed(&mut t, BaudRate::B9600).unwrap();
cfsetspeed(&mut t, BaudRate::B9600).unwrap();
# }

Additionally round-tripping baud rates is consistent across platforms:

# use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetispeed, cfsetspeed, Termios};
# fn main() {
# let mut t: Termios = unsafe { std::mem::zeroed() };
# cfsetspeed(&mut t, BaudRate::B9600).unwrap();
let speed = cfgetispeed(&t);
assert_eq!(speed, cfgetospeed(&t));
cfsetispeed(&mut t, speed).unwrap();
# }

On non-BSDs, cfgetispeed() and cfgetospeed() both return a BaudRate:

# use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios};
# fn main() {
# let mut t: Termios = unsafe { std::mem::zeroed() };
# cfsetspeed(&mut t, BaudRate::B9600);
assert_eq!(cfgetispeed(&t), BaudRate::B9600);
assert_eq!(cfgetospeed(&t), BaudRate::B9600);
# }

But on the BSDs, cfgetispeed() and cfgetospeed() both return u32s:

# use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios};
# fn main() {
# let mut t: Termios = unsafe { std::mem::zeroed() };
# cfsetspeed(&mut t, 9600u32);
assert_eq!(cfgetispeed(&t), 9600u32);
assert_eq!(cfgetospeed(&t), 9600u32);
# }

It's trivial to convert from a BaudRate to a u32 on BSDs:

# use nix::sys::termios::{BaudRate, cfgetispeed, cfsetspeed, Termios};
# fn main() {
# let mut t: Termios = unsafe { std::mem::zeroed() };
# cfsetspeed(&mut t, 9600u32);
assert_eq!(cfgetispeed(&t), BaudRate::B9600.into());
assert_eq!(u32::from(BaudRate::B9600), 9600u32);
# }

And on BSDs you can specify arbitrary baud rates (note this depends on hardware support) by specifying baud rates directly using u32s:

# use nix::sys::termios::{cfsetispeed, cfsetospeed, cfsetspeed, Termios};
# fn main() {
# let mut t: Termios = unsafe { std::mem::zeroed() };
cfsetispeed(&mut t, 9600u32);
cfsetospeed(&mut t, 9600u32);
cfsetspeed(&mut t, 9600u32);
# }

Structs

Enums

Functions

Constants