Я хочу достоверно знать размер терминала, даже когда приложение работает в подоболочке. Кажется, что единственный работающий способ - использовать stdin fd, но я хотел бы знать, почему есть ссылки на документацию, подтверждающую это. Есть много вопросов, например, зачем использовать stdout (или, в этом случае, stdin) fd, чтобы узнать размер терминала?
fn main() {
let mut size = winsize {
ws_row: 0,
ws_col: 0,
ws_xpixel: 0,
ws_ypixel: 0,
};
let fd = std::fs::OpenOptions::new()
.read(true)
.write(true)
.open("/dev/tty")
.map(|file| file.as_raw_fd())
.unwrap()
;
unsafe { ioctl(fd, TIOCGWINSZ.into(), &mut size) };
println!("/dev/tty cols: {}, lines: {}", size.ws_row, size.ws_col);
unsafe { ioctl(STDOUT_FILENO, TIOCGWINSZ.into(), &mut size) };
println!("stdout cols: {}, lines: {}", size.ws_row, size.ws_col);
unsafe { ioctl(STDERR_FILENO, TIOCGWINSZ.into(), &mut size) };
println!("stderr cols: {}, lines: {}", size.ws_row, size.ws_col);
unsafe { ioctl(STDIN_FILENO, TIOCGWINSZ.into(), &mut size) };
println!("stdin cols: {}, lines: {}", size.ws_row, size.ws_col);
}
Я запустил echo (cargo run 2>&1)
в оболочке fi sh и получил это:
Compiling test_term_size v0.1.0 (/home/m/code/test_term_size) warning: unused import: `File` --> src/main.rs:2:15 | 2 | use std::fs::{File}; | ^^^^ | = note: `#[warn(unused_imports)]` on by default warning: unused imports: `O_RDWR`, `open` --> src/main.rs:4:5 | 4 | O_RDWR, | ^^^^^^ 5 | open, ioctl, winsize, STDIN_FILENO, | ^^^^ Finished dev [unoptimized + debuginfo] target(s) in 0.21s Running `target/debug/test_term_size` /dev/tty cols: 0, lines: 0 stdout cols: 0, lines: 0 stderr cols: 0, lines: 0 stdin cols: 52, lines: 106
strace -e trace=ioctl,open target/debug/test_term_size
ioctl(3, TIOCGWINSZ, 0x7ffdb9805578) = -1 EBADF (Bad file descriptor)
/dev/tty cols: 0, lines: 0
ioctl(1, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
stdout cols: 52, lines: 213
ioctl(2, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
stderr cols: 52, lines: 213
ioctl(0, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
stdin cols: 52, lines: 213
+++ exited with 0 +++
strace -e trace=ioctl,open cargo run
ioctl(2, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(2, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(2, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(2, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(2, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
ioctl(2, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
ioctl(2, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/test_term_size`
ioctl(3, TIOCGWINSZ, 0x7ffea819b008) = -1 EBADF (Bad file descriptor)
/dev/tty cols: 0, lines: 0
ioctl(1, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
stdout cols: 52, lines: 213
ioctl(2, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
stderr cols: 52, lines: 213
ioctl(0, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
stdin cols: 52, lines: 213
+++ exited with 0 +++
echo (strace -e trace=ioctl,open cargo run 2>&1)
ioctl(2, TCGETS, 0x7ffdae149cb0) = -1 ENOTTY (Inappropriate ioctl for device) ioctl(2, TCGETS, 0x7ffdae149a30) = -1 ENOTTY (Inappropriate ioctl for device) ioctl(2, TCGETS, 0x7ffdae149a30) = -1 ENOTTY (Inappropriate ioctl for device) ioctl(2, TCGETS, 0x7ffdae149540) = -1 ENOTTY (Inappropriate ioctl for device) warning: unused import: `File` --> src/main.rs:2:15 | 2 | use std::fs::{File}; | ^^^^ | = note: `#[warn(unused_imports)]` on by default warning: unused imports: `O_RDWR`, `open` --> src/main.rs:4:5 | 4 | O_RDWR, | ^^^^^^ 5 | open, ioctl, winsize, STDIN_FILENO, | ^^^^ Finished dev [unoptimized + debuginfo] target(s) in 0.02s Running `target/debug/test_term_size` ioctl(3, TIOCGWINSZ, 0x7ffd8c3ae728) = -1 EBADF (Bad file descriptor) /dev/tty cols: 0, lines: 0 ioctl(1, TIOCGWINSZ, 0x7ffd8c3ae728) = -1 ENOTTY (Inappropriate ioctl for device) stdout cols: 0, lines: 0 ioctl(2, TIOCGWINSZ, 0x7ffd8c3ae728) = -1 ENOTTY (Inappropriate ioctl for device) stderr cols: 0, lines: 0 ioctl(0, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0 stdin cols: 52, lines: 213 +++ exited with 0 +++
echo (strace -e trace=ioctl,open target/debug/test_term_size 2>&1)
ioctl(3, TIOCGWINSZ, 0x7fffdc82e938) = -1 EBADF (Bad file descriptor) /dev/tty cols: 0, lines: 0 ioctl(1, TIOCGWINSZ, 0x7fffdc82e938) = -1 ENOTTY (Inappropriate ioctl for device) stdout cols: 0, lines: 0 ioctl(2, TIOCGWINSZ, 0x7fffdc82e938) = -1 ENOTTY (Inappropriate ioctl for device) stderr cols: 0, lines: 0 ioctl(0, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0 stdin cols: 52, lines: 213 +++ exited with 0 +++
echo (strace -e trace=ioctl,open target/debug/test_term_size 2>&1)
ioctl(3, TIOCGWINSZ, 0x7fffdc82e938) = -1 EBADF (Bad file descriptor) /dev/tty cols: 0, lines: 0 ioctl(1, TIOCGWINSZ, 0x7fffdc82e938) = -1 ENOTTY (Inappropriate ioctl for device) stdout cols: 0, lines: 0 ioctl(2, TIOCGWINSZ, 0x7fffdc82e938) = -1 ENOTTY (Inappropriate ioctl for device) stderr cols: 0, lines: 0 ioctl(0, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0 stdin cols: 52, lines: 213 +++ exited with 0 +++