我无法获得使用 execvp
调用的程序的完整输出。在这里,我基本上是在尝试用一个可以过滤输入和输出的程序来包装任何程序:
#define BUF_SIZ 8192
int main(int argc, char **argv) {
int outp[2]; // r, w
int inp[2];
pid_t pid;
char buf[BUF_SIZ];
fd_set fds;
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 300000;
if (pipe(outp) < 0 || pipe(inp) < 0) return 1;
if ((pid = fork()) < 0) return 2;
else if (pid) {
close(outp[1]);
close(inp[0]);
dup2(outp[0], STDIN_FILENO);
dup2(inp[1], STDOUT_FILENO);
execvp(*(argv + 1), argv + 1);
} else {
while (1) {
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
FD_SET(inp[0], &fds);
if (select(inp[0] + 1, &fds, NULL, NULL, &tv) < 0) exit(3);
if (FD_ISSET(STDIN_FILENO, &fds))
write(outp[1], buf, read(STDIN_FILENO, buf, BUF_SIZ));
if (FD_ISSET(inp[0], &fds))
write(STDOUT_FILENO, buf, read(inp[0], buf, BUF_SIZ));
}
}
return 0;
}
如果我使用该程序调用 shell sh
,我会得到以下输出(我没有收到提示):
$ ./shell sh
echo "test"
test
^C
如果我尝试运行 Python;我没有收到任何输出:
$ ./shell python
print "test"
^C
为什么我没有收到(大部分)输出?
最佳答案
问题是,您的 shell 和 python 解释器的标准输入不是终端。在这种情况下,这两个程序的行为有点不同:
- shell 不发出提示
- Python 想要首先从标准输入(直到 EOF)读取它的完整脚本
例如,要使 python 脚本正常工作,您必须从您的 stdin 捕获 EOF(读取返回 0),在这种情况下关闭 python 进程的 stdin。然后,您可以通过在终端上按 CTRL+D 来调用 EOF。
if (select(inp[0] + 1, &fds, NULL, NULL, &tv) < 0) exit(3);
if (FD_ISSET(STDIN_FILENO, &fds)) {
int st = read(STDIN_FILENO, buf, BUF_SIZ));
if (st > 0)
write(outp[1], buf, st);
else {
close(outp[1]);
...
如果您想要一个交互式终端,您必须打开一个新的伪终端,forkpty(3)
将为您完成大部分工作。
关于关于如何结束 Execvp 调用的困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35564681/