【发布时间】:2016-06-03 14:00:51
【问题描述】:
我正在尝试创建一个最小的代码来使用 pipe/fork/execlp。 到目前为止一切顺利,我正在使用带有 bash -c 的 execlp,所以如果我这样做的话。
echo asd |./a.out cat
> asd
所以它按预期工作。 但是,如果我尝试使用任何需要 TTY 的东西,它就不起作用。 像 ./a.out vim 一样,我得到“Vim:警告:输入不是来自终端” 并且打开的 vim 没有按预期工作。
我试图在互联网上找到一个关于如何打开 TTY 的示例,我找到的唯一一个是: http://www.danlj.org/lad/src/minopen.c
到目前为止,我的代码是:
#include <iostream>
#include <cstdio>
#include <string.h>
#include <cstdlib>
#include <unistd.h>
#include <sys/wait.h>
typedef struct pCon{
int fout[2];
int fin[2];
int fd[2];
int pid1, pid2;
} connectionManager;
std::string command = "";
/*
* Implementation
*/
void childFork(connectionManager *cm);
int main(int argc, char *argv[]) {
int size;
if(argc < 2) exit(1);
else command = argv[1];
connectionManager *cm = new connectionManager;
pipe(cm->fd);
if((cm->pid1 = fork()) == -1)exit(1);
if (cm->pid1 == 0)
{
const unsigned int RCVBUFSIZE = 2000;
char echoString[RCVBUFSIZE];
while((size = read(fileno(stdin),echoString,RCVBUFSIZE)) > 0)
write(cm->fd[1], echoString, size);
close(cm->fd[1]);
}
else
childFork(cm);
return 0;
}
void childFork(connectionManager *cm){
char *buffer = new char[2000];
int size;
close(cm->fd[1]);
dup2(cm->fd[0], 0);
close(cm->fd[0]);
pipe(cm->fout);
if((cm->pid2 = fork()) == -1)exit(1);
if (cm->pid2 == 0)
{
close(cm->fout[0]);
int returnCode = execlp("bash", "bash", "-c", command.c_str(), NULL);
if(returnCode!=0)
std::cerr << "Error starting the bash program" << std::endl;
}
else
{
close(cm->fout[1]);
while((size = read(cm->fout[0], buffer, 2000 )) > 0 )
write(fileno(stdout), buffer, size);
}
}
我尝试保留最少的必要代码以使其正常工作。 有没有办法在这段代码上实现 TTY,我知道这似乎不是那么简单的任务。 有人可以帮我吗?
我也尝试打开 tty 并复制它,但到目前为止没有运气。
【问题讨论】:
-
你打算将分叉进程的哪个 i/o 通道连接到 TTY 屏幕和 TTY 键盘(通常是 std::cout 和 std::cin)?
-
@DOUGLASO.MOEN 我想我两者都需要,在那个代码中,我希望最终能够毫无问题地打开类似 VIM 的东西。
-
检查这个问题:superuser.com/questions/336016/…,所以你可以参考xargs的源代码来检查它是如何使用
-o选项来操作stdin的。 -
因为您的 tty 的标准输入和标准输出会转到终端进行用户交互,所以可以考虑使用选项 --command=STRING 启动 gnome-terminal(或替代品)。 STRING 标识您选择的编辑器和任何参数(文件名)。在 gnome-terminal 命令中,您还可以指定几何图形、窗口标题和工作目录。您的代码 sn-p 显示 fork,这很好,或者您可以使用 exec 系列之一,我喜欢 popen。
-
嗯,我的问题可以用 ssh localhost "bash" 重现,它不分配 TTY,但 ssh localhost dows 工作。这个程序到底是一个“ssh”,我去掉了很多代码。 SSH 如何实现 TTY,是否需要另一个程序来实现。关于popen,我不能使用,因为你只能重定向标准输入或标准输出。上面的这个场景只是一个例子,我希望能够使用像 tar -zcvf - Folder | 这样的东西。 ./a.out "tar -xvf -"。到目前为止效果很好,但如果我需要一个终端,一切都会停止工作