I / O重定向,打印到错误的文件描述符

时间:2015-02-25 19:44:30

标签: c++ linux unix io-redirection

我正在使用滚边和其他文件描述符,我遇到了泡菜。

一些上下文

对于某些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;
}

非常感谢!

0 个答案:

没有答案