wc:标准输入:错误的文件描述符

时间:2015-11-27 15:34:43

标签: c pipe

我正在尝试使用ls | wcls /tmp | wc -l这样的管道处理命令,但我得到的是“wc:标准输入:错误的文件描述符”消息。这是我第一次做这样的事情。任何建议都会有所帮助。

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

int main()
{
    for(;;)
    {
        char *cmd, *splitcmd, *splinput, *splipip;
        int i, j, nargc = 0, characters;
        char **cmdArray;
        char **splArray;
        char **pipArray;
        size_t bufsize = 1024;
        int *pipefd;
        int pipeArrCount;
        pid_t pid, wpid;
        int status = 0;
        int count = 0;
        int metro = 0;
        char pr1[40],  pr2[40],  pr0[40];
        char pi0[40],  pi1[40],  pi2[40];
        char pip0[40],  pip1[40],  pip2[40];
        int savestdoutfd = dup(fileno(stdout));
        int savestdinfd = dup(fileno(stdin));

        char *path;
        path = getenv("PATH");

        cmd = (char *)malloc(bufsize * sizeof(char));
        characters = getline(&cmd, &bufsize, stdin);
        printf("cmd == => %s  characters == =>  %d \n", cmd, characters);
        if (cmd[characters-1] == '\n')
        {
            cmd[characters-1]='\0';
            characters--;
        }
        printf("cmd == => %s  characters == =>  %d \n", cmd, characters);

        cmdArray = (char**)malloc(bufsize * sizeof(char *) );
        for (i = 0; i < bufsize; i++ )
        {
            cmdArray[i]=(char*)malloc(bufsize * sizeof(char ) );
        }

        splitcmd = strtok(cmd, "|");
        printf(" cmd ==  ==   %s\n", cmd);
        while((splitcmd))
        {
            strcpy(cmdArray[nargc], splitcmd);
            if (cmdArray[nargc][(strlen(cmdArray[nargc]))-1] == ' ')
                cmdArray[nargc][(strlen(cmdArray[nargc]))-1]='\0';
            printf(" nargc ==  == %d  cmdArray == =[  %s  ] \n", nargc, cmdArray[nargc]);
            nargc++;
            splitcmd = strtok(NULL, "|");
        }

        strcpy(pr0, cmdArray[0]);
        strcpy(pr1, cmdArray[1]);
        strcpy(pr2, cmdArray[2]);
        printf(" pr0  %s   \n", pr0);
        printf(" pr1  %s   \n", pr1);
        printf(" pr2  %s   \n", pr2);

        splArray = (char**)malloc(bufsize * sizeof(char *) );
        for (i = 0; i < bufsize; i++ )
        {
            splArray[i]=(char*)malloc(bufsize * sizeof(char ) );
        }

        splinput = strtok(pr0, " ");
        while((splinput))
        {
            strcpy(splArray[count], splinput);
            if (splArray[count][(strlen(splArray[count]))-1] == ' ')
                splArray[count][(strlen(splArray[count]))-1]='\0';
            printf(" count ==  == %d  splArray == =[  %s  ] \n", count, splArray[count]);
            count++;
            splinput = strtok(NULL, " ");
        }


        strcpy(pi0, splArray[0]);
        strcpy(pi1, splArray[1]);
        strcpy(pi2, splArray[2]);
        printf(" pi0  %s   \n", pi0);
        printf(" pi1  %s   \n", pi1);
        printf(" pi2  %s   \n", pi2);

        pipArray= (char**)malloc(bufsize * sizeof(char *) );
        for (i = 0; i < bufsize; i++ )
        {
            pipArray[i]=(char*)malloc(bufsize * sizeof(char ) );
        }

        splipip = strtok(pr1, " ");
        while((splipip))
        {
            strcpy(pipArray[metro], splipip);
            if (pipArray[metro][(strlen(pipArray[metro]))-1] == ' ')
                pipArray[metro][(strlen(pipArray[metro]))-1]='\0';
            printf(" metro ==  == %d  pipArray == =[  %s  ]    \n", metro, pipArray[metro]);

            metro++;
            splipip = strtok(NULL, " ");
        }


        strcpy(pip0, pipArray[0]);
        strcpy(pip1, pipArray[1]);
        strcpy(pip2, pipArray[2]);
        printf(" pip0  %s   \n", pip0);
        printf(" pip1  %s   \n", pip1);
        printf(" pip2  %s   \n", pip2);

        pipefd=(int*)malloc(2 * nargc*sizeof(int));
        printf(" nargc == =   %d\n", nargc);
        pipeArrCount = 2*(nargc-1);
        printf("pipeArrCount == = %d\n", pipeArrCount);
        //exit(0);
        for(i = 0; i < pipeArrCount; i)
        {
            pipe(pipefd + i);
            i = i + 2;
        }
        for(i = 0; i < nargc; i++)
        {
            if (i == 0)
            {
                if ((pid = fork())  ==  0)
                {
                    dup2(pipefd[2 * i+1], fileno(stdout));

                    for(j = 0; j < pipeArrCount; j++)
                    {
                        close(pipefd[j]);
                    }

                    if (count  == 1 )
                    {

                        char *argv[] = {path, NULL};
                        execvp(pi0, argv);
                        for (i = 0; i < 100; i++)
                        {
                            free(cmdArray[i]);
                        }
                        free(cmdArray);
                    }

                    else if (count == 2)
                    {
                        char *argv[] = {pi0, pi1, NULL};
                        execvp(pi0, argv);
                        for (i = 0; i < 100; i++)
                        {
                            free(cmdArray[i]);
                        }
                        free(cmdArray);
                    }
                    else
                    {
                        char *argv[] = {pi0, pi1, pi2, NULL};

                        execvp(argv[0], argv);
                        for (i = 0; i < bufsize; i++)
                        {
                            free(cmdArray[i]);
                        }
                        free(cmdArray);

                    }
                    exit(0);

                }
                wait(&status);

                dup2(savestdoutfd, fileno(stdout));

            }

            else
            {
                if (fork()  ==  0)
                {
                    dup2(pipefd[2 * i-1], fileno(stdin));

                    for(j = 0; j < pipeArrCount; j++)
                    {
                        close(pipefd[j]);
                    }
                    dup2(savestdoutfd, fileno(stdout));
                    close(savestdoutfd);
                    if (metro  == 1 )
                    {

                        char *argv[] = {pip0, NULL};
                        execvp(pip0, argv);
                        for (i = 0; i < 100; i++)
                        {
                            free(cmdArray[i]);
                        }
                        free(cmdArray);

                    }

                    else if (metro == 2)
                    {
                        char *argv[] = {pip0, pip1, NULL};
                        execvp(argv[0], argv);
                        for (i = 0; i < 100; i++)
                        {
                            free(cmdArray[i]);
                        }
                        free(cmdArray);
                    }

                    else
                    {

                        char *argv[] = {pip0, pip1, pip2, NULL};
                        execvp(argv[0], argv);
                        for (i = 0; i < 100; i++)
                        {
                            free(cmdArray[i]);
                        }
                        free(cmdArray);
                    }
                    dup2(savestdinfd, fileno(stdin));
                    close(savestdinfd);
                    exit(0);

                }
            }
        }
        for (j = 0; j < pipeArrCount; j++)
        {
            close(pipefd[j]);
        }
        while ((wpid = wait(&status)) > 0);
    }
}

1 个答案:

答案 0 :(得分:1)

您的问题可能是运营商优先级。在运行管道中命令的else循环的for子句中,您有:

dup2(pipefd[2 * i-1], fileno(stdin));

下标计算的间距是奇数;代码相当于:

dup2(pipefd[2*i - 1], fileno(stdin));

但是,该描述符是管道的写描述符,而不是读描述符,因此wc在尝试从只写文件描述符中读取时会获得EBADF

有效的是:

dup2(pipefd[2 *(i-1)], fileno(stdin));

您应该使用STDIN_FILENO代替fileno(stdin),类似STDOUT_FILENO

还有许多其他问题需要解决,但这会让你顺利。