Chris Phillips
Chris Phillips

Reputation: 2124

Why isn't my piped grep working?

I've written my own shell in C, and when I run ls | grep .c, I get nothing. Although unpiped commands are working fine, like ls. Here's my code:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

#include "shell.h"
#include "builtins.h"
#include "makeargv.h"



void shell() 
{
    pid_t   shell_pid;
    int     i;
    int     flag = 1;
    int     argc0;
    int     argc1;
    int     fdl[2];
    int     fdr[2];
    size_t  input_size;
    char    cwd[128];   //this is being toggled
    char    *delim0;
    char    *delim1;
    char    *lastarg;
    char    *input;
    char    *debugdescriptor;
    char    **argvp;
    char    **firstargs;

    shell_pid = getpid();
    do
    {
        // Retrieve PID & CWD of the parent process. 
        getcwd(cwd, (128 * sizeof(char)));  
        printf("{%i}%s$ ", shell_pid, cwd);         

        // Retrieve input from stdin.
        input = NULL;
        input_size = 0;
        getline(&input, &input_size, stdin);

        //seperates the input into pipe-delimited arguments("tokens")
        delim1 = "|\n";
        argc1 = makeargv(input, delim1, &argvp);

        //got some debugging tools here
        //debugdescriptor = "PIPE-SEPERATED";
        //debug_args(&argvp, &argc1, debugdescriptor);


        //check for quit and cd first
        delim0 = " ";
        argc0 = makeargv(argvp[0], delim0, &firstargs);
        //more debugging tools here
        //debugdescriptor = "FIRST ARGS";
        //debug_args(&firstargs, &argc0, debugdescriptor);
        //exit
        if((i = strcmp(firstargs[0],"exit")) == 0 || (i = strcmp(firstargs[0],"quit")) == 0)
        {
            printf("===========SHELL TERMINATED==============\n\n");
            flag = 0;
        }
        //cd
        else if((i = strcmp(firstargs[0],"cd")) == 0)
        {
            chdir(firstargs[1]);
        }

        else // Create a child process to handle user input.
        {
            char **thisarg;
            int childlayer = 0;
            pid_t pid = fork();
            wait(0);
            if(pid == 0)
                childlayer++;               
            int tokens = argc1 - 1;
            if(argc1 == 1 && pid == 0)
            {
                makeargv(argvp[tokens], delim0, &thisarg);
                execvp(thisarg[0], thisarg);
            }
            else //more than 1 arguement, (has pipes)
            {
                while(pid == 0 && childlayer < argc1){
                    if(childlayer == 1){ //rightmost
                        pipe(fdl);
                        pid = fork();
                        wait(0);
                        if(pid == 0)
                            childlayer++;
                        if(pid > 0){
                            close(fdl[1]);
                            dup2(fdl[0], STDIN_FILENO); //sets the final output to write to STDIN
                            execute(childlayer, argc1, &argvp);
                        }
                    }
                    else if(childlayer > 1 && childlayer < argc1-1){ //middle args
                        pipe(fdr);
                        fdr[1] = fdl[1];
                        fdr[0] = fdl[0];

                        dup2(fdr[1], STDOUT_FILENO);

                        pipe(fdl);
                        pid = fork();
                        wait(0);
                        if(pid == 0)
                            childlayer++;
                        if(pid > 0){
                            close(fdl[1]);
                            dup2(fdl[0], STDIN_FILENO);
                            execute(childlayer, argc1, &argvp);
                        }
                    }
                    else{ //leftmost
                        pipe(fdr);
                        fdr[0] = fdl[0];
                        fdr[1] = fdl[1];
                        close(fdr[0]);
                        dup2(fdr[1], STDOUT_FILENO);
                        execute(childlayer, argc1, &argvp);
                    }
                }       
            }
        }
    }while(flag == 1);  
}

I think I may be getting stuck in a child process when I use the pipes, but I haven't been able to see where. Thanks.

Upvotes: 0

Views: 402

Answers (2)

pat
pat

Reputation: 12749

Why do you wait(0) immediately after fork()? In the child, this will return immediately with an error, but in the parent, it will block until the child exits. I'm having a hard time following how the pipeline is established because each child is forking off the next child in the pipeline. I'm guessing the wait(0) is creating a chicken-and-egg problem; the parent can't start until the child exits, but the child can't exit because it needs input from the parent. Wouldn't it be simpler if the shell process just looped over the pipeline components and forked each one itself, and then waited for them all to finish?

Upvotes: 1

William Pursell
William Pursell

Reputation: 212198

You are almost certainly failing to close all your file descriptors. One source of such an error is your dup2 calls.

After:

dup2(fdr[1], STDOUT_FILENO);

you should call

close(fdr[1]);

Upvotes: 3

Related Questions