我正在使用滚边和其他文件描述符,我遇到了泡菜。
对于某些clairty,下面的函数使用基于上下文的文件描述符进行重复的execvp调用。这是(理想情况下)调用可以很容易地连接在一起进行i / o重定向。
例如,一个可能的输入可能如下所示:
cat < input.txt | tr a-z A-Z
此函数之外的解析器变为:
argvv.at(0).first = "cat", NULL
argvv.at(0).second.at(0) = "1" //this lets us easily see what fd this 'chunk' is using. In my code, 1 stands for "<"
argvv.at(0).second.at(1) = "input.txt" // the file to be read from
argvv.at(1).first = "tr", "a-z", "A-Z", NULL;
argvv.at(1).second.at(0) = "4" // in my code, 4 stands for |
在某种程度上,它有点像这样:
(cat < input.txt) (| tr a-z A-Z)
argvv[0] ^ argvv[1] ^
这一切都被送到fcall()来执行。
解析器的工作方式并非一成不变。这可能不是最好的做事方式,但我现在更愿意解决手头的问题。
对于调用打印到标准输出的结果,调用打印到标准输入。对于不涉及管道的情况,这仍然适用。 情况应该不是这样,有些事情一定是错的,但我无法弄清楚是什么。
我还不熟悉i / o,而且我没有看到我错过的文件描述符。
或者也许不是这样,而且存在更大的误解。真的,我只是希望它不会成为一个错字,所以我可以学到新东西。
为了按预期运行,需要对代码进行哪些更改?为什么?
int fcall(std::vector < std::pair<char**, std::vector <std::string> > > argvv ){
const int pipew = 1;
const int piper = 0;
//gotta say, fully understanding pipe I really appriciate how much sense this saves me.
int status;
if (strlen(argvv.at(0).first[0]) == 0){
return -1;
}
if (!strcmp(argvv.at(0).first[0], "exit")){
return 1;
}
//counter of weights
unsigned int waitcount = 0;
int n = 0;
std::vector<int*> fdv;
for (unsigned int k = 0; k < argvv.size(); k++){
if (!argvv.at(k).second.at(0).compare("4") ){ //figures out how many pipes we'll need
int fd[2];
if(pipe(fd) == -1)
perror("pipe");
fdv.push_back(fd);
}
else
{
fdv.push_back(NULL);
}
if(argvv.at(k).second.at(0).compare("2") && argvv.at(k).second.at(0).compare("3")){ //determines how long we should be waiting
waitcount++;
}
}
int stdins;
int stdouts;
if (-1 == (stdins = dup(0)))
perror("dup");
if (-1 == (stdouts = dup(1)))
perror("dup");
for (unsigned int i = 0; i < argvv.size(); i++ ){
int pid = fork();
if(pid == -1)//fork’s return value for an error is -1
{
//perror("There was an error with fork(). ");
perror("fork"); //although you certainly can use the above, it is good
//practice not to write more information than necessary
exit(1);//there was an error with fork so exit the program and go back and fix it
}
else if(pid == 0)//when pid is 0 you are in the child process
{
int fdx;
int fdy;
//(I) ==============
int y = ((int)argvv.at(i).second.at(0).at(0)-48);
std::cerr << y << std::endl;
switch (y){
case 0:
break;
case 1:
if (-1 == (fdy = open(argvv.at(i).second.at(1).c_str(), O_RDONLY))){
perror("open");
}
if (-1 == dup2(fdy, 0)){
perror("dup");
}
break;
case 2:
break;
case 3:
break;
case 4:
if(-1 == dup2(fdv.at(i)[piper],0 ))
perror("dup");
break;
}
//(I +1) ==============
if (i+1 < argvv.size()){
int z = ((int)argvv.at(i+1).second.at(0).at(0)-48);
std::cerr << std::endl;
switch (z){
case 0:
break;
case 1:
break;
case 2:
if (-1 == (fdx = open(argvv.at(i+1).second.at(1).c_str(), O_RDWR | O_CREAT,S_IRWXU ))){
perror("open");
}
if (-1 == dup2(fdx,1 ))
perror("dup");
break;
case 3:
if (-1 == (fdx = open(argvv.at(i+1).second.at(1).c_str(), (O_RDWR | O_APPEND) | O_CREAT,S_IRWXU ))){
perror("open");
}
if (-1 == dup2(fdx,1 ))
perror("dup");
break;
case 4:
if(-1 == dup2(fdv.at(i+1)[pipew],1 ))
perror("dup");
break;
}
}
for(unsigned int kg; kg < fdv.size(); kg++){
if (fdv.at(kg) != NULL){
if (-1 == close(fdv.at(kg)[0]))
perror("close");
if (-1 == close(fdv.at(kg)[1]))
perror("close");
}
}
if (y != 2 && y!= 3){
if (0 < execvp(argvv.at(i).first[0],argvv.at(i).first )){
n = -1;
perror("execvp");
}
}
exit(1); //when the child process finishes doing what we want it to, cout,
//we want to kill the child process so it doesn’t go on in the program so we exit
}
}
for (unsigned int f = 0; f < waitcount; f++){
if (-1 == wait(&status))
perror("wait");
}
if (-1 == dup2(stdins, 0))
perror("dup");
if (-1 == dup2(stdouts, 1))
perror("dup");
if (-1 == close(stdins))
perror("close");
if (-1 == close(stdouts))
perror("close");
return n;
}
非常感谢!