子进程无法从创建的伪终端读取

发布于 2024-08-19 21:02:30 字数 847 浏览 11 评论 0原文

我正在尝试编写一个可以使用伪终端使用密码登录 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()。这是怎么回事?

I'm trying to write an app that can login to SSH with a password, by using pseudo terminals. But if I write() to the master device then the data somehow does not appear in the slave device. Here's a simple test case:

#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;
    }
}

The app will first output "Press Enter to send a byte". After pressing Enter, I expect the child process's read() to return. But the read() there seems to block indefinitely even though the master's write() succeeds, so the master waits forever on the waitpid(). What's going on?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绮筵 2024-08-26 21:02:30

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

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

这似乎对我有用。

The problem is that you didn't modify the line discipline of the PTY. The default line discipline is line oriented, so no input will be sent to the slave process until a newline character is read. (You can see this by sending a "\n" to the slave, instead of just "1".) You can run the PTY in RAW mode by, in the child process, calling tcgetattr, cfmakeraw and tcsetattr, like follows:

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

This seems to work for me.

﹏半生如梦愿梦如真 2024-08-26 21:02:30

这篇博文中的示例代码可能会有帮助。作者对其原始问题(与您的问题非常相似)进行了更新,并提供了可用的 spawn (char *argv[]); 函数。

The example code at this blog post should probably be of help. The author has an update to his original problem (very similar to yours) with a usable spawn (char *argv[]); function given.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文