rm-lisa 0.3.2

A logging library for rem-verse, with support for inputs, tasks, and more.
Documentation
//! Unsafe FFI Bindings.

use crate::termios::os::target::{
	speed_t as raw_speed_t, termios as raw_termios, winsize as raw_winsize,
};
use libc::{TIOCGWINSZ, c_int, ioctl, pid_t};

unsafe extern "C" {
	pub fn tcgetattr(fd: c_int, termios_p: *mut raw_termios) -> c_int;
	pub fn tcsetattr(fd: c_int, optional_actions: c_int, termios_p: *const raw_termios) -> c_int;
	pub fn tcsendbreak(fd: c_int, duration: c_int) -> c_int;
	pub fn tcdrain(fd: c_int) -> c_int;
	pub fn tcflush(fd: c_int, queue_selector: c_int) -> c_int;
	pub fn tcflow(fd: c_int, action: c_int) -> c_int;
	#[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
	pub fn cfmakeraw(termios_p: *mut raw_termios);
	pub fn cfgetispeed(termios_p: *const raw_termios) -> raw_speed_t;
	pub fn cfgetospeed(termios_p: *const raw_termios) -> raw_speed_t;
	pub fn cfsetispeed(termios_p: *mut raw_termios, speed: raw_speed_t) -> c_int;
	pub fn cfsetospeed(termios_p: *mut raw_termios, speed: raw_speed_t) -> c_int;
	#[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "haiku")))]
	pub fn cfsetspeed(termios_p: *mut raw_termios, speed: raw_speed_t) -> c_int;
	pub fn tcgetsid(fd: c_int) -> pid_t;
}

/// Our version of libc is old enough that tcgetwinsize is not default implemented..
///
/// Implement this 'fake' version that can then later on be swapped with the
/// implementation in newer libc's.
///
/// ## Safety
///
/// Exported as unsafe, as when we actually link with libc it's an extern
/// function that is unsafe because it is C.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn tcgetwinsize(fd: c_int, winsize: *mut raw_winsize) -> c_int {
	unsafe { ioctl(fd, TIOCGWINSZ, winsize) }
}

/// A version of `makeraw` for OS's that do not have this.
///
/// ## Safety
///
/// Exported as unsafe, as when we actually link with libc it's an extern
/// function that is unsafe because it is C.
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn cfmakeraw(termios: *mut raw_termios) {
	use crate::termios::os::target::{
		BRKINT, ICRNL, IGNBRK, IGNCR, IMAXBEL, INLCR, ISTRIP, IXON, PARMRK,
	};
	use crate::termios::os::target::{
		CS8, CSIZE, ECHO, ECHONL, ICANON, IEXTEN, ISIG, OPOST, PARENB,
	};
	use crate::termios::os::target::{VMIN, VTIME};

	// Equivalent of cfmakeraw() in glibc
	(*termios).c_iflag &=
		!(IMAXBEL | IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
	(*termios).c_oflag &= !OPOST;
	(*termios).c_lflag &= !(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
	(*termios).c_cflag &= !(CSIZE | PARENB);
	(*termios).c_cflag |= CS8;
	(*termios).c_cc[VMIN] = 1;
	(*termios).c_cc[VTIME] = 0;
}

/// An implementation of `cfsetspeed` for OS's that don't have it.
///
/// ## Safety
///
/// Exported as unsafe, as when we actually link with libc it's an extern
/// function that is unsafe because it is C.
#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "haiku"))]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn cfsetspeed(termios_p: *mut raw_termios, speed: raw_speed_t) -> c_int {
	match unsafe { cfsetispeed(termios_p, speed) } {
		0 => unsafe { cfsetospeed(termios_p, speed) },
		err => err,
	}
}