pty-shell 0.1.3

Spawn a shell and control it through pty
Documentation
use libc;
use pty;
use std::os::unix::io::AsRawFd;
use std::io::Result;
use winsize;
use termios::*;

static mut termios_to_restore: Option<Termios> = None;
pub extern "C" fn restore_termios() {
    match unsafe { termios_to_restore } {
        Some(termios) => { let _ = tcsetattr(libc::STDIN_FILENO, TCSANOW, &termios); }
        None => ()
    }
}

pub fn setup_terminal(pty: pty::ChildPTY) -> Result<()> {
    let termios = try!(Termios::from_fd(libc::STDIN_FILENO));

    unsafe {
        termios_to_restore = Some(termios);
        libc::atexit(restore_termios);
    };

    try!(enter_raw_mode(libc::STDIN_FILENO));

    let winsize = try!(winsize::from_fd(libc::STDIN_FILENO));
    winsize::set(pty.as_raw_fd(), &winsize);

    Ok(())
}

fn enter_raw_mode(fd: libc::c_int) -> Result<()> {
    let mut new_termios = try!(Termios::from_fd(fd));

    new_termios.c_lflag &= !(ECHO | ICANON | IEXTEN | ISIG);
    new_termios.c_iflag &= !(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
    new_termios.c_cflag &= !(CSIZE | PARENB);
    new_termios.c_cflag |= CS8;
    new_termios.c_oflag &= !(OPOST);
    new_termios.c_cc[VMIN] = 1;
    new_termios.c_cc[VTIME] = 0;

    try!(tcsetattr(libc::STDIN_FILENO, TCSANOW, &new_termios));

    Ok(())
}