为什么我的管道grep没有工作?

时间:2014-03-17 21:18:08

标签: c shell pipe stdin

我在C中编写了自己的shell,当我运行ls | grep .c时,我什么都没得到。尽管unpiped命令工作正常,例如ls。这是我的代码:

#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);  
}

我想当我使用烟斗时,我可能会陷入儿童过程中,但我还没有能够看到哪里。感谢。

2 个答案:

答案 0 :(得分:3)

您几乎肯定无法关闭所有文件描述符。这种错误的一个原因是您的dup2来电。

后:

dup2(fdr[1], STDOUT_FILENO);

你应该致电

close(fdr[1]);

答案 1 :(得分:1)

为什么wait(0)之后fork()?在孩子中,这将立即返回错误,但在父母中,它将阻止直到孩子退出。我很难跟踪管道是如何建立的,因为每个孩子都在分配管道中的下一个孩子。我猜测wait(0)正在制造一个鸡蛋问题;在孩子退出之前,父母不能开始,但孩子不能退出,因为它需要来自父母的输入。如果shell进程只是循环管道组件并自己分叉,然后等待它们全部完成,那会不会更简单?