Linux shell simulation: stuck on multiple pipes

I know similar questions have already been asked but none of the replies helped me. I am trying to implement a miniature Linux shell and am stuck on multiple pipes. Commands with a single pipe (e.g. ls | wc) work, but if I add a second pipe, nothing is shown on the console. Here is my code.

void ExecuteCommand(NODE *cHead,NODE *oHead)
{
    int fd[10][2];  // file descriptors' array
    int nfdCnt = 0 ;    // file descriptors counter
    string strCmd;      // command
    string strOp = "";  // operator
    int nOpCnt = 0 ;    // operator count

    while(1)
    {
        if (cHead != NULL)  // cHead is head pointer to the linked list of commands.
        {
            strCmd =  GetCmdOROperator(&cHead); // get command
        }
        if (oHead == NULL)  // oHead is head pointer to the linked list of operators.
        {
            strOp = "";
        }
        else
        {
            strOp = GetCmdOROperator(&oHead);   // get operator
        }

        if (strOp.empty())  // no operator exists. single or last command in the chain.
        {
            // Fork the child process
            pid_t child_id = fork();

            if(child_id == 0)
            {
                // Execute the command

                if (nOpCnt) // if we previously encountered any operator
                {
                    close(fd[nfdCnt-1][FD_WRITE]);
                    dup2(fd[nfdCnt-1][FD_READ], FD_READ);   // read from pipe updated by previous command
                }

                // call execvp()

                exit(-1);
            }
            else
            {
                for (int i = 0 ; i < nfdCnt; i++)
                {
                    close(fd[nfdCnt][0]);
                    close(fd[nfdCnt][1]);
                }
                wait(NULL);
                break;
            }
        }

        if (strOp == "|")
        {
            nOpCnt++ ;

            if (pipe (fd[nfdCnt]) < 0)
            {
                printf("\npipe error");
                return ;
            }

            pid_t child_id = fork();
            if (child_id == 0)
            {
                close(fd[nfdCnt][FD_READ]); // we dont need this
                dup2(fd[nfdCnt][FD_WRITE], FD_WRITE);

                if(nOpCnt > 1) // if we have already encountered a pipe before
                {
                    dup2(fd[nfdCnt-1][FD_READ],FD_READ);
                    close(fd[nfdCnt-1][FD_WRITE]);
                }

                // call execvp()
                exit (-1);
            }
            else
            {
                nfdCnt++;
            }

        }

    }
}

Answers


I haven't looked too closely at your code, but it looks like you are leaving file descriptors open, in which case processes will block on a read since someone has the write side open even though you think you've closed it. Try adding a close after each dup2:

 dup2( fd[ nfdCnt - 1 ][ FD_READ ], FD_READ );
 close( fd[ nfdCnt - 1 ][ FD_READ ])

(Also, add some error checking. dup2, fork, close, etc. can all fail. It is sometimes convenient to skip error checking when posting questions to a forum, but make sure that you don't omit it in actual code.)


Need Your Help

How can I programmatically get the default behavior of sigterm inside a custom signal handler?

c++ c unix signals

Based on man -S 7 signal, when a program which has not defined a signal handler receives SIGTERM, the default action is to Term.

Cannot change class objects properties when it is stored in an array, why not?

iphone arrays class properties sprite

Basically I create an array and add instances of my custom class to it. But when i try to access properties of the instances stored in the array, I get no response from the class. Btw, it works with

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.