mxsh 0.2.0

Embeddable POSIX-style shell parser and runtime
Documentation
pub(crate) struct SignalDispositionGuard {
    saved: Vec<(i32, libc::sighandler_t)>,
}

impl SignalDispositionGuard {
    pub(crate) fn new() -> Self {
        Self { saved: Vec::new() }
    }

    #[cfg(feature = "unix-runtime")]
    pub(crate) fn set(&mut self, sig: i32, disposition: libc::sighandler_t) -> bool {
        if !configurable_signal(sig) {
            return false;
        }
        let previous = unsafe { libc::signal(sig, disposition) };
        if previous == libc::SIG_ERR {
            return false;
        }
        self.saved.push((sig, previous));
        true
    }

    #[cfg(any(
        feature = "frontend",
        all(
            test,
            feature = "embed",
            feature = "test-support",
            feature = "unix-runtime"
        )
    ))]
    pub(crate) fn set_preserving_ignore(
        &mut self,
        sig: i32,
        disposition: libc::sighandler_t,
    ) -> bool {
        if !configurable_signal(sig) {
            return false;
        }
        let previous = unsafe { libc::signal(sig, disposition) };
        if previous == libc::SIG_ERR {
            return false;
        }
        if previous == libc::SIG_IGN {
            unsafe {
                let _ = libc::signal(sig, libc::SIG_IGN);
            }
            return false;
        }
        self.saved.push((sig, previous));
        true
    }
}

impl Drop for SignalDispositionGuard {
    fn drop(&mut self) {
        for (sig, handler) in self.saved.drain(..).rev() {
            unsafe {
                let _ = libc::signal(sig, handler);
            }
        }
    }
}

fn configurable_signal(sig: i32) -> bool {
    sig > 0 && sig != libc::SIGKILL && sig != libc::SIGSTOP
}