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
//! Terminal raw-mode guard.
//!
//! `tio` and `picocom` both leave the terminal wrecked if they crash
//! mid-session — every embedded engineer has typed `reset` blindly at
//! least once. [`RawModeGuard`] makes a best-effort promise to restore
//! `termios` on every exit path:
//!
//! - normal `Drop` (main returns, `?` early return, scope exit, ...);
//! - unwinding panic (a panic hook is chained in front of the existing one).
//!
//! External signals (`SIGINT`, `SIGTERM`, `SIGHUP`) are *not* handled
//! here — see [`crate::signal::SignalListener`], which trips the
//! session's [`CancellationToken`](tokio_util::sync::CancellationToken)
//! so `main` returns normally and `Drop` fires through the same code
//! path as a clean shutdown.
//!
//! In raw mode the kernel no longer translates `Ctrl-C` to `SIGINT` —
//! that key arrives as a regular byte (`0x03`) the application must
//! handle.
//!
//! Calling [`RawModeGuard::install`] more than once per process is
//! supported: only the first call wires up the panic hook; subsequent
//! calls just toggle raw mode.
use PhantomData;
use panic;
use ;
use Once;
use ;
/// `true` when raw mode is currently active *because of us*.
///
/// Written by the guard's `Drop` and by the panic hook.
static RAW_MODE_ACTIVE: AtomicBool = new;
/// Ensures the panic hook is installed exactly once per process.
static HOOKS: Once = new;
/// RAII handle that holds the terminal in raw mode for its lifetime.
///
/// The guard is `!Send` and `!Sync` on purpose — keeping it bound to
/// the thread that owns `main` makes the cleanup story easier to reason
/// about and rules out a class of multi-thread mistakes.
///
/// # Example
///
/// ```ignore
/// let _guard = RawModeGuard::install()?;
/// // ... raw-mode session ...
/// // Drop fires here; termios is restored even if we early-returned.
/// ```
/// Disables raw mode if it is currently active (idempotent).
///
/// Errors from [`disable_raw_mode`] are deliberately swallowed: the
/// guard is a best-effort cleanup, and there is nothing useful to do if
/// the OS refuses to restore termios at process exit.
/// Chains a panic hook in front of the existing one so termios is
/// restored before the panic message lands.