Skip to content

Commit cd64884

Browse files
committed
Implement os.get_terminal_size
1 parent 1bc0f2b commit cd64884

File tree

3 files changed

+62
-5
lines changed

3 files changed

+62
-5
lines changed

vm/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ schannel = "0.1"
125125
version = "0.3"
126126
features = [
127127
"winsock2", "handleapi", "ws2def", "std", "winbase", "wincrypt", "fileapi", "processenv",
128-
"namedpipeapi", "winnt", "processthreadsapi", "errhandlingapi", "winuser", "synchapi",
128+
"namedpipeapi", "winnt", "processthreadsapi", "errhandlingapi", "winuser", "synchapi", "wincon",
129+
"impl-default",
129130
]
130131

131132
[target.'cfg(target_arch = "wasm32")'.dependencies]

vm/src/stdlib/os.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1867,6 +1867,60 @@ fn os_strerror(e: i32) -> String {
18671867
.into_owned()
18681868
}
18691869

1870+
#[pystruct_sequence(name = "os.terminal_size")]
1871+
#[allow(dead_code)]
1872+
struct PyTerminalSize {
1873+
columns: usize,
1874+
lines: usize,
1875+
}
1876+
1877+
fn os_get_terminal_size(fd: OptionalArg<i32>, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
1878+
let (columns, lines) = {
1879+
#[cfg(unix)]
1880+
{
1881+
nix::ioctl_read_bad!(winsz, libc::TIOCGWINSZ, libc::winsize);
1882+
let mut w = libc::winsize {
1883+
ws_row: 0,
1884+
ws_col: 0,
1885+
ws_xpixel: 0,
1886+
ws_ypixel: 0,
1887+
};
1888+
unsafe { winsz(fd.unwrap_or(libc::STDOUT_FILENO), &mut w) }
1889+
.map_err(|e| convert_nix_error(vm, e))?;
1890+
(w.ws_col.into(), w.ws_row.into())
1891+
}
1892+
#[cfg(windows)]
1893+
{
1894+
use winapi::um::{handleapi, processenv, winbase, wincon};
1895+
let stdhandle = match fd {
1896+
OptionalArg::Present(0) => winbase::STD_INPUT_HANDLE,
1897+
OptionalArg::Present(1) | OptionalArg::Missing => winbase::STD_OUTPUT_HANDLE,
1898+
OptionalArg::Present(2) => winbase::STD_ERROR_HANDLE,
1899+
_ => return Err(vm.new_value_error("bad file descriptor".to_owned())),
1900+
};
1901+
let h = unsafe { processenv::GetStdHandle(stdhandle) };
1902+
if h.is_null() {
1903+
return Err(vm.new_os_error("handle cannot be retrieved".to_owned()));
1904+
}
1905+
if h == handleapi::INVALID_HANDLE_VALUE {
1906+
return Err(errno_err(vm));
1907+
}
1908+
let mut csbi = wincon::CONSOLE_SCREEN_BUFFER_INFO::default();
1909+
let ret = unsafe { wincon::GetConsoleScreenBufferInfo(h, &mut csbi) };
1910+
if ret == 0 {
1911+
return Err(errno_err(vm));
1912+
}
1913+
let w = csbi.srWindow;
1914+
(
1915+
(w.Right - w.Left + 1) as usize,
1916+
(w.Bottom - w.Top + 1) as usize,
1917+
)
1918+
}
1919+
};
1920+
PyTerminalSize { columns, lines }
1921+
.into_struct_sequence(vm, vm.try_class(MODULE_NAME, "terminal_size")?)
1922+
}
1923+
18701924
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
18711925
let ctx = &vm.ctx;
18721926

@@ -1885,6 +1939,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
18851939
});
18861940

18871941
let stat_result = StatResult::make_class(ctx);
1942+
let terminal_size = PyTerminalSize::make_class(ctx);
18881943

18891944
struct SupportFunc<'a> {
18901945
name: &'a str,
@@ -1964,6 +2019,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
19642019
"ScandirIter" => scandir_iter,
19652020
"DirEntry" => dir_entry,
19662021
"stat_result" => stat_result,
2022+
"terminal_size" => terminal_size,
19672023
"lstat" => ctx.new_function(os_lstat),
19682024
"getcwd" => ctx.new_function(os_getcwd),
19692025
"chdir" => ctx.new_function(os_chdir),
@@ -1978,6 +2034,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
19782034
"link" => ctx.new_function(os_link),
19792035
"kill" => ctx.new_function(os_kill),
19802036
"strerror" => ctx.new_function(os_strerror),
2037+
"get_terminal_size" => ctx.new_function(os_get_terminal_size),
19812038

19822039
"O_RDONLY" => ctx.new_int(libc::O_RDONLY),
19832040
"O_WRONLY" => ctx.new_int(libc::O_WRONLY),

vm/src/stdlib/winapi.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,8 @@ fn _winapi_CreateProcess(
130130
args: CreateProcessArgs,
131131
vm: &VirtualMachine,
132132
) -> PyResult<(usize, usize, u32, u32)> {
133-
use winbase::STARTUPINFOEXW;
134-
let mut si: STARTUPINFOEXW = unsafe { std::mem::zeroed() };
135-
si.StartupInfo.cb = std::mem::size_of::<STARTUPINFOEXW>() as _;
133+
let mut si = winbase::STARTUPINFOEXW::default();
134+
si.StartupInfo.cb = std::mem::size_of_val(&si) as _;
136135

137136
macro_rules! si_attr {
138137
($attr:ident, $t:ty) => {{
@@ -207,7 +206,7 @@ fn _winapi_CreateProcess(
207206
| winbase::CREATE_UNICODE_ENVIRONMENT,
208207
env as _,
209208
current_dir,
210-
&mut si as *mut STARTUPINFOEXW as _,
209+
&mut si as *mut winbase::STARTUPINFOEXW as _,
211210
&mut procinfo,
212211
)
213212
};

0 commit comments

Comments
 (0)