子进程无法从创建的伪终端读取
我正在尝试编写一个可以使用伪终端使用密码登录 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题是您没有修改 PTY 的线路规则。默认的行规则是面向行的,因此在读取换行符之前不会将任何输入发送到从属进程。 (您可以通过向从站发送“\n”而不是“1”来看到这一点。)您可以通过在子进程中调用 tcgetattr,以 RAW 模式运行 PTY,< code>cfmakeraw 和
tcsetattr
,如下所示:这似乎对我有用。
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
andtcsetattr
, like follows:This seems to work for me.
这篇博文中的示例代码可能会有帮助。作者对其原始问题(与您的问题非常相似)进行了更新,并提供了可用的
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.