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

C++ I/O重定向,打印到错误的文件描述符,c++,linux,unix,io-redirection,C++,Linux,Unix,Io Redirection,我正在处理管道和其他文件描述符,结果遇到了麻烦 一些背景 对于某些人来说,下面的函数使用基于上下文的文件描述符重复执行execvp调用。这样(理想情况下)调用就可以很容易地串在一起进行i/o重定向 例如,一个可能的输入可能如下所示: cat < input.txt | tr a-z A-Z cat

我正在处理管道和其他文件描述符,结果遇到了麻烦

一些背景 对于某些人来说,下面的函数使用基于上下文的文件描述符重复执行execvp调用。这样(理想情况下)调用就可以很容易地串在一起进行i/o重定向

例如,一个可能的输入可能如下所示:

cat < input.txt | tr a-z A-Z
cat
此函数之外的解析器将转换为:

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 |
argvv.at(0).first=“cat”,NULL

argvv.at(0).second.at(0)=“1”//这让我们很容易看到这个“块”在使用什么。在我的代码中,1代表“这是维姆的结果,但你是对的。我会把它编辑掉,我看不出有什么问题,也不知道这和C作为编程语言有什么关系。请修改你的标签并提出你的问题的更简洁的描述。“J.S.GugSistt我认为从我使用系统调用以来就包含C是明智的,但是你是对的,代码是用C++编写的,所以我想标签不是完全相关的。”JensGustedt,我也认为我把这个问题弄得非常清楚。但我现在用粗体字写了。
(cat < input.txt) (| tr a-z A-Z)
  argvv[0] ^         argvv[1] ^
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;
}