我无法获得使用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
为什么我没有收到(大多数)输出?
答案 0 :(得分:3)
问题是,shell和python解释器的stdin不是终端。在这种情况下,两个程序的行为都有所不同:
例如,要使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)
将为您完成大部分工作。