Skip to main content

ree/
reset.rs

1use rustix::{process, termios};
2
3use crate::{Error, display, tty};
4
5/// Repair the kernel TTY state and reset the attached terminal emulator.
6///
7/// # Errors
8///
9/// Returns [`Error`] when no terminal is available, the process is a background
10/// job, terminal state cannot be changed, or the terminfo entry cannot be read.
11///
12/// # Examples
13///
14/// ```no_run
15/// ree::reset()?;
16/// # Ok::<(), ree::Error>(())
17/// ```
18pub fn reset() -> Result<(), Error> {
19    let terminal = tty::find().ok_or(Error::NoTerminal)?;
20    let foreground = tty::retry_on_interrupt(|| termios::tcgetpgrp(&terminal))
21        .map_err(Error::GetForegroundProcess)?;
22    if foreground != process::getpgrp() {
23        return Err(Error::NotForegroundProcess);
24    }
25
26    tty::retry_on_interrupt(|| termios::tcflow(&terminal, termios::Action::OOn))
27        .map_err(Error::ResumeOutput)?;
28
29    let mut mode = tty::retry_on_interrupt(|| termios::tcgetattr(&terminal))
30        .map_err(Error::GetTerminalState)?;
31    tty::repair_terminal_mode(&mut mode);
32    tty::retry_on_interrupt(|| {
33        termios::tcsetattr(&terminal, termios::OptionalActions::Flush, &mode)
34    })
35    .map_err(Error::SetTerminalState)?;
36
37    display::reset(&terminal)
38}