Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/base/src/sys/windows/terminal.rs
5394 views
1
// Copyright 2023 The ChromiumOS Authors
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
use std::io::Stdin;
6
7
use winapi::shared::minwindef::DWORD;
8
use winapi::um::consoleapi::GetConsoleMode;
9
use winapi::um::consoleapi::SetConsoleMode;
10
use winapi::um::wincon::ENABLE_ECHO_INPUT;
11
use winapi::um::wincon::ENABLE_LINE_INPUT;
12
use winapi::um::wincon::ENABLE_PROCESSED_INPUT;
13
use winapi::um::wincon::ENABLE_VIRTUAL_TERMINAL_INPUT;
14
15
use crate::AsRawDescriptor;
16
use crate::Error;
17
use crate::RawDescriptor;
18
use crate::Result;
19
20
/// Trait for file descriptors that are terminals.
21
///
22
/// # Safety
23
/// This is marked unsafe because the implementation must promise that the returned RawDescriptor is
24
/// a valid descriptor and that the lifetime of the returned descriptor is at least that of the
25
/// trait object.
26
pub unsafe trait Terminal {
27
/// Gets the file descriptor of the terminal.
28
fn terminal_descriptor(&self) -> RawDescriptor;
29
30
/// Set this terminal's mode to raw mode.
31
///
32
/// Returns the original mode, which can be passed to `restore_mode()` to reset the terminal to
33
/// its previous state.
34
fn set_raw_mode(&self) -> Result<DWORD> {
35
let descriptor = self.terminal_descriptor();
36
let mut orig_mode = 0;
37
38
// SAFETY:
39
// Safe because we provide a valid descriptor and pointer and we check the return result.
40
if unsafe { GetConsoleMode(descriptor, &mut orig_mode) } == 0 {
41
return Err(Error::last());
42
}
43
44
let new_mode = (orig_mode | ENABLE_VIRTUAL_TERMINAL_INPUT)
45
& !(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
46
47
// SAFETY:
48
// Safe because the syscall will only read the extent of mode and we check the return
49
// result.
50
if unsafe { SetConsoleMode(descriptor, new_mode) } == 0 {
51
return Err(Error::last());
52
}
53
54
Ok(orig_mode)
55
}
56
57
/// Set this terminal's mode to a previous state returned by `set_raw_mode()`.
58
fn restore_mode(&self, mode: DWORD) -> Result<()> {
59
// SAFETY:
60
// Safe because the syscall will only read the extent of mode and we check the return
61
// result.
62
if unsafe { SetConsoleMode(self.terminal_descriptor(), mode) } == 0 {
63
Err(Error::last())
64
} else {
65
Ok(())
66
}
67
}
68
}
69
70
// SAFETY:
71
// Safe because we return a genuine terminal descriptor that never changes and shares our lifetime.
72
unsafe impl Terminal for Stdin {
73
fn terminal_descriptor(&self) -> RawDescriptor {
74
self.as_raw_descriptor()
75
}
76
}
77
78