我正在尝试构建一个小型终端模拟器,并且遇到了一些有趣的与 libc 的类型冲突。 当我尝试设置 pty 连接的从属部分时,我需要通过对 ptsname() 的系统调用来创建从属,以便获取 pts 的名称以便我可以访问它。 但是,我收到一个类型错误,说 libc::ptsname() 需要 i32 作为输入。 这与说它应该传递文件描述符的手册页直接冲突。 我只是想知道是否可以将文件描述符的 libc::c_int 转换为 i32 以传递给 ptsname。

代码如下:

use libc::{self, c_int, grantpt, posix_openpt, ptsname, unlockpt, O_RDWR};
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 master: c_int;
    unsafe {
        // create master/slave pair of fd
        master = posix_openpt(O_RDWR);
        if master == -1 {
            panic!("Failed to posix_openpt");
        }

        // set slave ownership and mode as master
        let mut result = grantpt(master);
        if result == -1 {
            panic!("Failed to grantpt");
        }
        // unlock slave
        result = unlockpt(master);
        if result == -1 {
            panic!("Failed to unlockpt");
        }
    }
    let slave: c_int = ptsname(master as i32);
    slave = libc::open(slave);

    let mut builder = Command::new(process);

    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/bish";

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

和控制台输出(现在可以忽略第二个错误):

error[E0308]: mismatched types
  --> src/main.rs:42:24
   |
42 |     let slave: c_int = ptsname(master as i32);
   |                        ^^^^^^^^^^^^^^^^^^^^^^ expected i32, found *-ptr
   |
   = note: expected type `i32`
              found type `*mut i8`

error[E0060]: this function takes at least 2 parameters but 1 parameter was supplied
  --> src/main.rs:43:13
   |
43 |     slave = libc::open(slave);
   |             ^^^^^^^^^^^^^^^^^ expected at least 2 parameters

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0060, E0308.
For more information about an error, try `rustc --explain E0060`.
error: could not compile `experiment`.

#1楼 票数:1 已采纳

这并不是说它需要i32输入,而是您要问的是ptsname(master as i32); 具有类型i32 这可能是一个有点混乱,因为c_int是一个别名i32 ,所以它听起来像它的要求无关的类型。

问题是当ptsname返回*mut c_charc_char也是别名,这次是i8 )时,你给slavec_int类型。

  ask by LeeAsh translate from so

未解决问题?本站智能推荐:

1回复

你如何写信给 Pty 大师 Rust

我创建了一个简单的 pty 设置,但是我不确定如何在创建后实际写入主端或从端。 我也不确定我的设置是否正确,因为经过检查,pty 的子进程的 Stdin、Stdout 和 Stderr 都是 None 而不是设置为从文件描述符。 任何人都可以澄清这是否正确,如果不正确,您对如何解决它有任何建议吗?
3回复

如何在不阻塞Rust的情况下读取子进程的输出?

我正在Rust中制作一个小的ncurses应用程序,该应用程序需要与子进程进行通信。 我已经有一个用Common Lisp编写的原型。 我试图重写它,因为CL为这么小的工具使用了大量的内存。 我在弄清楚如何与子流程进行交互时遇到了一些麻烦。 我目前正在做的大致是这样的: 创建过程: 将
1回复

如何与另一个进程的STDIO“远程登录”?

通常,CouchDB通过简单的基于行的协议通过STDIO与视图服务器进行通信。 我想要做的是,让它读取和写入某种管道或伪终端(而不是视图服务器),然后与之连接并播放视图服务器。 我认为一种解决方法是大量使用cat和FIFO。 但是我发现在Mac上echo "hi" > /
5回复

您可以傻傻地呆着并分别记录stdout和stderr吗?

问题 因此,您想(分别)记录一个进程或子进程的stdout和stderr,如果您未记录任何内容,则输出不会与在终端中看到的输出不同。 似乎很简单,不是吗? 不幸的是,似乎不可能为这个问题写一个通用的解决方案,该解决方案适用于任何给定的流程... 背景 管道重定向是一种分
1回复

PTY/TTY - 仅使用 Slave FD 不能做什么

问题: 如果我有一个 pty 或 tty 主/从对,如果我只有从节点的文件描述符,我不能用它做什么? 或者,换句话说:只有当我拥有主节点的文件描述符时,我能做什么? 我目前的理解: 我理解了终端/控制台/SSH 的“典型”关系,该终端/控制台/SSH 具有用于与人交互的主端,并且一个或多个程序
1回复

你怎么知道fd是指伪终端的内部还是外部?

至少在Linux和NetBSD上, isatty在内部( /dev/pts/0 , /dev/ttyp0等)或外部( /dev/ptmx , /dev/ptyp0等)上打开fds时返回true伪tcgetxxx ,以及我可以方便地测试的所有tcgetxxx操作也无法区分。 原则上,您可以通过调
2回复

为什么我不能从另一个终端写入终端设备的标准输入

我在Gnome桌面管理器Ubuntu中打开了两个pts终端。 我想做的是使用终端/ dev / pts / 1通过重定向将一些内容写入终端/ dev / pts / 0: 但是在pts / 0中,仅打印日期,而按Enter则不执行它。 所以我猜想该命令不会进入pts / 0的标准
1回复

我如何使stdin成为tty?

有些程序会根据其stdout是否为tty来更改其输出。 因此,如果将它们放在管道中或重定向它们,则输出将与外壳中的输出不同。 这是一个例子: 因此,如果我想向某人展示这样的命令应该是什么样子(例如,我正在编写教程),则必须突出显示并复制终端的输出,然后将其保存到文件中。 看来我