1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/*
* Mitts Build — Rust-first build and package tooling with shared artifact cache
* Copyright (c) 2026 Alexander Panasenko
*
* Contact: alex@prod.codes
* Author: https://prod.codes/about/
* Project: https://github.com/alex09x/mitts
* SPDX-License-Identifier: MIT OR Apache-2.0
*/
#[cfg(unix)]
use std::cell::UnsafeCell;
#[cfg(unix)]
use std::mem::MaybeUninit;
#[cfg(unix)]
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
#[cfg(unix)]
struct TermiosStorage(UnsafeCell<MaybeUninit<libc::termios>>);
#[cfg(unix)]
unsafe impl Sync for TermiosStorage {}
#[cfg(unix)]
static HAS_ORIGINAL: AtomicBool = AtomicBool::new(false);
#[cfg(unix)]
static ORIGINAL_TERMIOS: TermiosStorage = TermiosStorage(UnsafeCell::new(MaybeUninit::uninit()));
#[cfg(unix)]
static PREV_SIGINT: AtomicUsize = AtomicUsize::new(0);
#[cfg(unix)]
static PREV_SIGTERM: AtomicUsize = AtomicUsize::new(0);
#[cfg(unix)]
extern "C" fn handle_signal(sig: libc::c_int) {
restore_terminal();
unsafe {
libc::signal(sig, libc::SIG_DFL);
libc::raise(sig);
}
}
#[cfg(unix)]
fn restore_terminal() {
if HAS_ORIGINAL.swap(false, Ordering::SeqCst) {
unsafe {
let fd = libc::STDIN_FILENO;
// Discard any keystrokes (such as pressed Enter keys) accumulated during the build
libc::tcflush(fd, libc::TCIFLUSH);
// Restore original terminal attributes
let orig_ptr = (*ORIGINAL_TERMIOS.0.get()).as_ptr();
libc::tcsetattr(fd, libc::TCSANOW, orig_ptr);
// Restore cursor visibility
let _ = libc::write(libc::STDERR_FILENO, b"\x1b[?25h".as_ptr() as *const _, 6);
// Restore previous signal handlers
let prev_int = PREV_SIGINT.swap(0, Ordering::SeqCst);
if prev_int != 0 {
libc::signal(libc::SIGINT, prev_int as _);
}
let prev_term = PREV_SIGTERM.swap(0, Ordering::SeqCst);
if prev_term != 0 {
libc::signal(libc::SIGTERM, prev_term as _);
}
}
}
}
/// RAII guard that disables terminal echoing and line buffering effects (preventing duplicate
/// progress bars when pressing Enter) and hides cursor during long-running compilation.
///
/// Restores original terminal modes, flushes unread input, and restores the cursor on drop
/// or on premature termination (SIGINT / SIGTERM).
pub struct TerminalGuard {
active: bool,
}
impl TerminalGuard {
/// Attempts to acquire control over the interactive terminal.
/// If stdin is not a TTY, this is a safe no-op.
pub fn acquire() -> Self {
#[cfg(unix)]
{
let fd = libc::STDIN_FILENO;
unsafe {
if libc::isatty(fd) != 1 {
return Self { active: false };
}
if HAS_ORIGINAL
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
.is_ok()
{
let mut termios = MaybeUninit::uninit();
if libc::tcgetattr(fd, termios.as_mut_ptr()) == 0 {
*ORIGINAL_TERMIOS.0.get() = termios;
// Save and set signal handlers
let sig_handler: extern "C" fn(libc::c_int) = handle_signal;
let prev_int = libc::signal(libc::SIGINT, sig_handler as _);
if prev_int != libc::SIG_ERR {
PREV_SIGINT.store(prev_int as usize, Ordering::SeqCst);
}
let prev_term = libc::signal(libc::SIGTERM, sig_handler as _);
if prev_term != libc::SIG_ERR {
PREV_SIGTERM.store(prev_term as usize, Ordering::SeqCst);
}
// Disable ECHO and ECHONL so pressing Enter or typing doesn't emit newlines
// or characters that clobber or duplicate the progress bar
let mut modified = (*ORIGINAL_TERMIOS.0.get()).assume_init();
modified.c_lflag &= !(libc::ECHO | libc::ECHONL);
libc::tcsetattr(fd, libc::TCSANOW, &modified);
// Hide cursor during progress bar rendering
let _ =
libc::write(libc::STDERR_FILENO, b"\x1b[?25l".as_ptr() as *const _, 6);
return Self { active: true };
} else {
HAS_ORIGINAL.store(false, Ordering::SeqCst);
}
}
}
}
Self { active: false }
}
}
impl Drop for TerminalGuard {
fn drop(&mut self) {
if self.active {
#[cfg(unix)]
restore_terminal();
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_terminal_guard_acquire_and_drop() {
let guard = TerminalGuard::acquire();
drop(guard);
}
#[test]
#[cfg(unix)]
fn test_terminal_guard_pty_and_restore() {
unsafe {
let master = libc::posix_openpt(libc::O_RDWR | libc::O_NOCTTY);
if master >= 0 {
if libc::grantpt(master) == 0 && libc::unlockpt(master) == 0 {
let slave_name = libc::ptsname(master);
if !slave_name.is_null() {
let slave = libc::open(slave_name, libc::O_RDWR | libc::O_NOCTTY);
if slave >= 0 {
let old_stdin = libc::dup(libc::STDIN_FILENO);
if libc::dup2(slave, libc::STDIN_FILENO) >= 0 {
let guard = TerminalGuard::acquire();
assert!(guard.active);
// Second concurrent acquire fails because HAS_ORIGINAL is already true
let second = TerminalGuard::acquire();
assert!(!second.active);
drop(second);
drop(guard);
assert!(!HAS_ORIGINAL.load(Ordering::SeqCst));
}
if old_stdin >= 0 {
libc::dup2(old_stdin, libc::STDIN_FILENO);
libc::close(old_stdin);
}
libc::close(slave);
}
}
}
libc::close(master);
}
}
}
#[test]
#[cfg(unix)]
fn test_restore_terminal_when_not_active() {
assert!(!HAS_ORIGINAL.load(Ordering::SeqCst));
restore_terminal();
assert!(!HAS_ORIGINAL.load(Ordering::SeqCst));
}
}