【问题标题】:Child process unable to read from created pseudo terminal子进程无法从创建的伪终端读取
【发布时间】:2010-02-02 18:45:45
【问题描述】:

我正在尝试使用伪终端编写一个可以使用密码登录 SSH 的应用程序。但是如果我 write() 到主设备,那么数据就不会出现在从设备中。这是一个简单的测试用例:

#include <sys/wait.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#ifdef __linux__
    #include <pty.h>
#else
    #include <util.h>
#endif

int
main() {
    int master;
    pid_t pid = forkpty(&master, NULL, NULL, NULL);
    if (pid == 0) {
        int ch;
        read(0, &ch, 1);
        _exit(1);
    } else {
        printf("Press Enter to send a byte.\n");
        getchar();
        write(master, "1", 1);
        printf("Done. Waiting for process to exit...\n");
        waitpid(pid, NULL, 0);
        return 0;
    }
}

应用程序将首先输出“Press Enter to send a byte”。按 Enter 后,我希望子进程的 read() 返回。但是即使 master 的 write() 成功,那里的 read() 似乎也无限期地阻塞,所以 master 永远在 waitpid() 上等待。怎么回事?

【问题讨论】:

  • 我不确定你在用这个做什么,但我会用expect来做这样的事情。它适用于大多数发行版。 expect.nist.gov
  • 我正在编写的应用程序将分发给可能没有“期望”或可能不想安装它的用户。此外,我还想知道如何正确使用伪终端,以防我将来需要它们。
  • 试试这个:write(master, "1\n", 2);

标签: c posix pty


【解决方案1】:

问题是您没有修改 PTY 的线路规程。默认的行规则是面向行的,因此在读取换行符之前不会将任何输入发送到从属进程。 (您可以通过向从属设备发送“\n”而不是“1”来查看这一点。)您可以在 RAW 模式下运行 PTY,方法是在子进程中调用 tcgetattrcfmakeraw 和 @987654323 @,如下:

    if (pid == 0) {
        int ch;
        struct termios t;
        tcgetattr(0, &t);
        cfmakeraw(&t);
        tcsetattr(0, TCSANOW, &t);
        read(0, &ch, 1);
        _exit(1);
    } else {

这似乎对我有用。

【讨论】:

    【解决方案2】:

    this blog post 的示例代码可能会有所帮助。作者对他的原始问题(与您的问题非常相似)进行了更新,并给出了可用的spawn (char *argv[]); 函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-22
      相关资源
      最近更新 更多