Как ты пишешь в pty мастер Rust - PullRequest
       105

Как ты пишешь в pty мастер Rust

3 голосов
/ 24 февраля 2020

Я создал простую установку pty, однако я не уверен в том, как на самом деле писать на ведущую или подчиненную стороны после ее создания. Я также не уверен, что мои настройки правильны, потому что при проверке Stdin, Stdout и Stderr дочернего процесса для pty все None вместо того, чтобы быть установленным в дескриптор подчиненного файла. Кто-нибудь сможет уточнить, если это правильно, и если нет, то есть ли у вас какие-либо предложения о том, как это исправить?

use libc::{self};
use nix::pty::openpty;
use std::os::unix::io::FromRawFd;
use std::process::{Child, Command, Stdio};

#[derive(Debug)]
pub struct Pty {
    process: Child,
    fd: i32,
}

fn create_pty(process: &str) -> Pty {
    let ends = openpty(None, None).expect("openpty failed");
    let master = ends.master;
    let slave = ends.slave;

    let mut builder = Command::new(process);
    builder.stdin(unsafe { Stdio::from_raw_fd(slave) });
    builder.stdout(unsafe { Stdio::from_raw_fd(slave) });
    builder.stderr(unsafe { Stdio::from_raw_fd(slave) });

    match builder.spawn() {
        Ok(process) => {
            let pty = Pty {
                process,
                fd: master,
            };

            pty
        }
        Err(e) => {
            panic!("Failed to create pty: {}", e);
        }
    }
}

fn main() {
    let shell = "/bin/bash";

    let pty = create_pty(shell);
    println!("{:?}", pty);

    println!("{}", pty.process.id());
}

1 Ответ

3 голосов
/ 24 февраля 2020

Это ожидается. std::process::Child::stdin и друзья не установлены для необработанных файловых дескрипторов (поскольку Rust не знает, что они есть, у разработчика нет конца master вашего pty).

Вы можете создать свой ржавый дескриптор файла для мастера самостоятельно:

fn main() {
    let shell = "/bin/bash";

    let pty = create_pty(shell);
    println!("{:?}", pty);

    let mut output = unsafe { File::from_raw_fd(pty.fd) };
    write!(output, "touch /tmp/itworks\n");
    output.flush();

    std::thread::sleep_ms(1000);

    println!("{}", pty.process.id());
}

Вы увидите, что это действительно создает файл "/tmp/itworks".

(Постоянная ссылка на игровую площадку)

...