supercode-cli 0.5.84

Volter Harness — a lightweight, fully-customizable AI coding agent CLI in Rust. Any model via OpenRouter; natively continues Claude Code and Codex sessions.
//! Exact host-terminal state capture around stock frontend processes.

use std::io;

/// Snapshot of terminal flags inherited by a child frontend. Dropping the
/// snapshot is idempotent best-effort restoration; callers can restore
/// eagerly to surface failures before returning.
pub(crate) struct TerminalSnapshot {
    #[cfg(unix)]
    states: Vec<(libc::c_int, libc::termios)>,
    #[cfg(windows)]
    states: Vec<(windows_sys::Win32::Foundation::HANDLE, u32)>,
    restored: bool,
}

impl TerminalSnapshot {
    pub(crate) fn capture() -> io::Result<Self> {
        #[cfg(unix)]
        {
            Self::capture_unix(&[libc::STDIN_FILENO, libc::STDOUT_FILENO, libc::STDERR_FILENO])
        }
        #[cfg(windows)]
        {
            use windows_sys::Win32::System::Console::{GetConsoleMode, GetStdHandle};
            use windows_sys::Win32::System::Console::{
                STD_ERROR_HANDLE, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE,
            };
            let mut states = Vec::new();
            for id in [STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE] {
                let handle = unsafe { GetStdHandle(id) };
                let mut mode = 0;
                if !handle.is_null() && unsafe { GetConsoleMode(handle, &mut mode) } != 0 {
                    states.push((handle, mode));
                }
            }
            Ok(Self {
                states,
                restored: false,
            })
        }
        #[cfg(not(any(unix, windows)))]
        {
            Ok(Self { restored: false })
        }
    }

    #[cfg(unix)]
    fn capture_unix(fds: &[libc::c_int]) -> io::Result<Self> {
        let mut states = Vec::new();
        for &fd in fds {
            if unsafe { libc::isatty(fd) } != 1 {
                continue;
            }
            let mut state = unsafe { std::mem::zeroed::<libc::termios>() };
            if unsafe { libc::tcgetattr(fd, &mut state) } != 0 {
                return Err(io::Error::last_os_error());
            }
            states.push((fd, state));
        }
        Ok(Self {
            states,
            restored: false,
        })
    }

    /// Restore the byte-for-byte terminal flags captured before launch.
    pub(crate) fn restore(&mut self) -> io::Result<()> {
        if self.restored {
            return Ok(());
        }
        #[cfg(unix)]
        for (fd, state) in &self.states {
            if unsafe { libc::tcsetattr(*fd, libc::TCSANOW, state) } != 0 {
                return Err(io::Error::last_os_error());
            }
        }
        #[cfg(windows)]
        for (handle, mode) in &self.states {
            if unsafe { windows_sys::Win32::System::Console::SetConsoleMode(*handle, *mode) } == 0 {
                return Err(io::Error::last_os_error());
            }
        }
        self.restored = true;
        Ok(())
    }

    /// A crashed or killed client cannot emit its normal screen-mode cleanup.
    /// Reset only modes that stock fullscreen clients enable, then restore the
    /// exact kernel terminal flags captured by this host.
    pub(crate) fn restore_after_abnormal_exit(&mut self) -> io::Result<()> {
        use std::io::Write;
        if !self.restored {
            let mut output = std::io::stdout().lock();
            output.write_all(b"\x1b[?25h\x1b[?1049l\x1b[?2004l\x1b[?1004l")?;
            output.flush()?;
        }
        self.restore()
    }
}

impl Drop for TerminalSnapshot {
    fn drop(&mut self) {
        let _ = self.restore();
    }
}

/// Give an isolated stock-client process group foreground access to the
/// inherited terminal, then return foreground ownership to the invoking host
/// before it restores modes or prints diagnostics.
pub(crate) struct ForegroundProcessGroup {
    #[cfg(unix)]
    fd: libc::c_int,
    #[cfg(unix)]
    original_group: libc::pid_t,
    #[cfg(unix)]
    original_sigttou: libc::sighandler_t,
    active: bool,
}

impl ForegroundProcessGroup {
    pub(crate) fn transfer_to(child_pid: Option<u32>) -> io::Result<Self> {
        #[cfg(unix)]
        {
            let fd = libc::STDIN_FILENO;
            let Some(child_pid) = child_pid else {
                return Ok(Self {
                    fd,
                    original_group: 0,
                    original_sigttou: libc::SIG_DFL,
                    active: false,
                });
            };
            if unsafe { libc::isatty(fd) } != 1 {
                return Ok(Self {
                    fd,
                    original_group: 0,
                    original_sigttou: libc::SIG_DFL,
                    active: false,
                });
            }
            let original_group = unsafe { libc::tcgetpgrp(fd) };
            if original_group < 0 {
                return Err(io::Error::last_os_error());
            }
            // A background process that restores itself would otherwise be
            // stopped by SIGTTOU. This host owns no concurrent terminal job.
            let original_sigttou = unsafe { libc::signal(libc::SIGTTOU, libc::SIG_IGN) };
            if unsafe { libc::tcsetpgrp(fd, child_pid as libc::pid_t) } != 0 {
                unsafe { libc::signal(libc::SIGTTOU, original_sigttou) };
                return Err(io::Error::last_os_error());
            }
            Ok(Self {
                fd,
                original_group,
                original_sigttou,
                active: true,
            })
        }
        #[cfg(not(unix))]
        {
            let _ = child_pid;
            Ok(Self { active: false })
        }
    }

    pub(crate) fn restore(&mut self) -> io::Result<()> {
        if !self.active {
            return Ok(());
        }
        #[cfg(unix)]
        {
            if unsafe { libc::tcsetpgrp(self.fd, self.original_group) } != 0 {
                return Err(io::Error::last_os_error());
            }
            unsafe { libc::signal(libc::SIGTTOU, self.original_sigttou) };
        }
        self.active = false;
        Ok(())
    }
}

impl Drop for ForegroundProcessGroup {
    fn drop(&mut self) {
        let _ = self.restore();
    }
}