Thread: problems with multiple pipes.

  1. #1
    Registered User
    Join Date
    Sep 2005
    Posts
    41

    problems with multiple pipes.

    This problem works with 2 piped commands (ie ls | grep main) but when I try to do more than 2 commands the program freezes.The int main() basically does the i/o and the execute command function is pretty much where im having all the problems. Thanks for any help. PS ParsedTokens is a class that parses completely the input. It puts the tokens in a vector of strings.


    Code:
    // Program asks user for input and tries to execute linux commands based on that input
    // User can use multiple input piped commands ie ls | grep main | grep o.
    
    #define _GNU_SOURCE 1
    
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <unistd.h>
    #include <getopt.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/wait.h>
    #include <errno.h>
    #include <fcntl.h>
    #include "parsedTokens.h"
    #include <string>
    #include <iostream>
    #include <deque>
    
    using namespace std;
    
    void execute_command(string left_command, string right_command);
    
    int main()
    {
    	char input[256];
    	string temp;
    	string temp2;
    	string temp3;
    	ParsedTokens Tokens;
    	unsigned int num_tokens;
    	vector<string> commands;
        int len, len2;
    
    	// get input
    	cout << "enter text: ";
                    cin.getline(input, 256, '\n');
    	Tokens.Clear();
    	Tokens.ParseAndAddTokens(input);
    	cout << "you typed: " << input << endl;
    	cout << "Parsed: " << endl;
    
    	// lists parsed input
    	for(unsigned int i = 0; i < Tokens.GetNumTokens(); i++)
    	{
    	   cout << Tokens[i] << endl;
    	}
    
    	// puts the tokens (not including the "|") into a vector 
    	for(unsigned int i = 0; i < Tokens.GetNumTokens(); i++)
    	{
    	   if(Tokens[i] != "|")
    	   {
    		   if(temp3.empty())
    		   {
    			   temp3 = Tokens[i];
    			   cout << "temp3: " << temp3 << endl;
    			   //if not at last token dont push but add the next token that isn't a pipe to temp3
    			   if(i == Tokens.GetNumTokens() - 1)
    			   {
    				   commands.push_back(temp3);
                       temp3.erase(0, temp3.length());
    			   }
    			   else if(Tokens[i+1] == "|")    // if the next token is a | then push token in temp3
    			   {
    				   commands.push_back(temp3);
    				   temp3.erase(0, temp3.length());
    			   }
    
    		   }
    		   else   // if temp3 isn't empty then add space to temp3 and add next token to temp3
    		   {
    		      temp3.insert(temp3.length()," ");
    		      temp3.insert(temp3.length(), Tokens[i]);
    			  cout << "temp3: " << temp3 << " after getting put together" << endl;
    			  if(i == Tokens.GetNumTokens() - 1)   // if you're at last token then push
    			   {
    				   commands.push_back(temp3);
                       temp3.erase(0, temp3.length());
    			   }
    			   else if(Tokens[i+1] == "|")    // if the next token is a | then push token in temp3
    			   {
    				   commands.push_back(temp3);
    				   temp3.erase(0, temp3.length());
    			   }
    
    		   }
    	   }
    	   /*else
    	   {
    		   commands.push_back(temp3);
    		   temp3.erase(0, temp3.length());
    	   }*/
        }
    		  
        cout << "all the commands to be executed" << endl;
    
    	for(int i = 0; i < commands.size(); i++)
    	   cout << commands[i] << endl;
    
    	//execute_command(commands[0], commands[1]);
    	for(int i = 0; i < commands.size() - 1; i++)
    	{
    		cout << "left command: " << commands[i] << endl;
    		cout << "right command: " << commands[i+1] << endl;
    		execute_command(commands[i], commands[i+1]);
    	}
    	   
        return 0;
    }
    
    void execute_command(string left_command, string right_command)
    {
       //char *argv[] = {"ls", "ls", 0};
       //char *left_arg[] = {"ls", 0};
       //char *right_arg[] = {"grep", "main", 0};
       int p[2];
       int pid;
       int len, len2;
       ParsedTokens left_comm_toks;
       ParsedTokens right_comm_toks;
          
       // int pipe(int filedes[2]);
       // filedes[0] is for reading, filedes[1] is for writing
       if(pipe(p) < 0)
       {
          cerr << strerror(errno) << endl;
          exit(EXIT_FAILURE);
       }
    
       pid = fork();
       if(pid < 0)
       {
          cerr << strerror(errno) << endl;
          exit(EXIT_FAILURE);
       }
       if(pid == 0)
       {
          cout << "exec left command" << endl;
    	  char * tempstring;
    	  tempstring = new char[left_command.length() + 1];
    	  strcpy(tempstring, left_command.c_str());
    	  left_comm_toks.ParseAndAddTokens(tempstring);
    	  len = left_comm_toks[0].length();
    	  const char * arg0 = left_comm_toks[0].c_str();
    	  // converts left_command into left_argv[] which execvp uses
    	  /*len = left_command.length();
    	  char * const myArr = new char[len + 1];
    	  for(int x = 0; x < len; x++)
    	     myArr[x] = left_command[x];
    	  myArr[len] = '\0';
    	  char * const left_argv[] = {myArr,0};*/
          
    	  delete [] tempstring;
    
    	  vector<string> left_args;
    
          for(int i = 0; i < left_comm_toks.GetNumTokens(); i++)
          {
             left_args.push_back(left_comm_toks[i]);
          }
    
          vector<char *> left_argv;
    
          for(int i = 0; i < left_args.size(); i ++)
             left_argv.push_back(const_cast<char *>(left_args[i].c_str()));
    
    	  left_argv.push_back('\0');
    
    	  close(p[0]);
    	  dup2(p[1], 1);
          close(p[1]);
          //argv[2] = 0;
          //
    	  execvp(arg0, &left_argv[0]); 
          cerr << "Error on exec of " << arg0 << ": " << strerror(errno) << endl;
          _exit(errno == ENOENT ? 127 : 126);
    
       }
    
       pid = fork();
       if(pid < 0)
       {
          cerr << strerror(errno) << endl;
          exit(EXIT_FAILURE);
       }
       if(pid == 0)
       {
          cout << "executing right command" << endl;
          // converts left_command into left_argv[] which execvp uses
    	  /*len2 = right_command.length();
    	  char * const myArr2 = new char[len +1];
    	  for(int x = 0; x < len2; x++)
    	     myArr2[x] = right_command[x];
    	   myArr2[len2] = '\0';
    
    	  char *const right_argv[] = {myArr2, 0};*/
    
          char * tempstring2;
    	  tempstring2 = new char[right_command.length() + 1];
    	  strcpy(tempstring2, right_command.c_str());
    	  right_comm_toks.ParseAndAddTokens(tempstring2);
    	  len = right_comm_toks[0].length();
    	  const char * arg02 = right_comm_toks[0].c_str();
    
    	  delete [] tempstring2;
    
    	  vector<string> right_args;
    
          for(int i = 0; i < right_comm_toks.GetNumTokens(); i++)
          {
             right_args.push_back(right_comm_toks[i]);
          }
    
          vector<char *> right_argv;
    
          for(int i = 0; i < right_args.size(); i ++)
             right_argv.push_back(const_cast<char *>(right_args[i].c_str()));
    
    	  right_argv.push_back('\0');
    	  close(p[1]);
    	  dup2(p[0], 0);
          close(p[0]);
          //execvp(right_argv[0], right_argv);
          execvp(arg02, &right_argv[0]);
    	  cerr << "Error on exec of " << right_argv[0] << ": " << strerror(errno) << endl;
          _exit(errno == ENOENT ? 127 : 126);
       }
       close(p[0]);
       close(p[1]);
    
       wait(0);
       wait(0);
       
    }

  2. #2
    Registered User
    Join Date
    Aug 2002
    Posts
    351
    Find out where it's freezing by using gdb or strace and attaching to the running process using the '-p' option.

  3. #3
    Registered User
    Join Date
    Nov 2005
    Posts
    52
    After a (very cursory) glance, I'd say that your problem lies in the fact that your execute_command function is set up strictly to handle the case of 2 commands, due to the way you're using your pipes. I don't see how (without digging deeper, which I'll do in a moment) you've got it arranged to chain the pipes correctly.

  4. #4
    Registered User
    Join Date
    Dec 2010
    Posts
    1

    Thumbs up Actually i have implemented two pipes in c that i m posting

    Quote Originally Posted by Stuka View Post
    After a (very cursory) glance, I'd say that your problem lies in the fact that your execute_command function is set up strictly to handle the case of 2 commands, due to the way you're using your pipes. I don't see how (without digging deeper, which I'll do in a moment) you've got it arranged to chain the pipes correctly.
    Code:
    Actually I have implemented two pipes in c program......
    
    It will get you the value for :-
    
    ls -l | tee f1 | wc -l
    
    Here goes the program..........
    
    #include <stdio.h>
    #include <string.h>
    #include <fcntl.h>
    #include<malloc.h>
    #include<ctype.h>
    #include <unistd.h>
    
     
    int main()
    {
    
    
    int fd[2], fd1[2];
    
      int pid, pid2, pid3;
    
      if (pipe(fd) == -1) {
        printf("Error: Pipe failed.\n");
        return 1;
      }
      if (pipe(fd1) == -1) {
        printf("Error: Pipe failed.\n");
        return 1;
      }
    
      if ((pid = fork()) < 0) {
        printf("Error: Fork failed.\n");
        return 1;
      }
      
      if (pid == 0) {
    
        // child process
        close(fd1[1]);
    close(fd[1]);
        dup2(fd1[0], 0);
        close(fd1[0]);
       char *argv1[2];
    
                            argv1[0]="wc";
                            argv1[1]="-l";
    			argv1[2]=NULL;
           execvp(argv1[0],argv1);
    
    }
    else {
    if ((pid2 = fork()) < 0) {
          printf("Error: Fork failed.\n");
          return 1;
        }
        if (pid2 == 0) {
          // child process
    
        close(fd[1]);
    	close(fd1[0]);
        dup2(fd[0], 0);
        close(fd[0]);
    
          dup2(fd1[1], 1);
          close(fd1[1]);
    
          
     
    	  char *argv2[2];
        	        argv2[0]="tee";
                        argv2[1]="f1";
    			argv2[2]=NULL;
    
    
           execvp(argv2[0],argv2);
    
    
        }
    else 
    {
      if ((pid3 = fork()) < 0) 
    	{
          printf("Error: Fork failed.\n");
          return 1;}
      if (pid3 == 0) {
          // child process
          close(fd[0]);
    	close(fd1[1]);
    	dup2(fd[1],1);
    	close(fd[1]);      
    	char *argv3[2];
                            argv3[0]="ls";
                            argv3[1]="-l";
    			argv3[2]=NULL;
    
       execvp(argv3[0], argv3);
          printf("Error: execv failed.\n");
        return 1;
        }
    
    else
    { 
         // parent process (the shell)
          
     wait(NULL);
        }
    
     } 
     
    }
     return 0; 
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. why Multiple define error ...
    By nilathinesh in forum C Programming
    Replies: 2
    Last Post: 10-19-2006, 06:31 AM
  2. Multiple Definition problems
    By shiver in forum C++ Programming
    Replies: 12
    Last Post: 08-30-2006, 02:33 PM
  3. Multiple problems with my program
    By Seirei in forum C Programming
    Replies: 4
    Last Post: 02-17-2006, 10:15 PM
  4. Replies: 1
    Last Post: 05-01-2003, 02:52 PM
  5. Multiple toolboxes in an app.
    By Anonymous Cowar in forum Windows Programming
    Replies: 2
    Last Post: 12-03-2002, 03:17 AM