2015-11-27 3 views
-1

Я пытаюсь обрабатывать команды с такими трубами, как ls | wc или ls /tmp | wc -l, но я получаю сообщение «wc: standard input: Bad file descriptor». Я впервые работаю над чем-то подобным. Любые предложения будут полезны.wc: standard input: Bad file descriptor

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

Обратите внимание, что освобождение после вызовов 'execvp()' является проблематичным, а не из-за того, что они 'free()', а потому, что единственный раз, когда они выполняются, это когда 'execvp()' fail, но когда что происходит, ребенок должен, вероятно, сообщить об ошибке на стандартную ошибку и выйти, а не вернуться в основной цикл и запросить дополнительные данные. Обратите внимание, что ваш основной код ввода не учитывает возможность того, что 'getline()' может возвращать '-1', чтобы указать больше данных; когда это происходит, вы ходите вокруг памяти до начала ваших массивов и других сомнительных практик. Вам нужно использовать функции! –

+0

Мой компилятор говорит мне, что строка 'for (i = 0; i

+0

Ваш код использует псевдо-массивы типа 'pi0',' pi1', 'pi2' и' pip0', 'pip1',' pip2' , и 'pr0',' pr1', 'pr2'. Они делают жизнь тяжелой; используйте реальные массивы. Они также делают код хрупким. И длинный. –

ответ

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.

Есть много других проблем, которые должны быть решены, но это поможет вам.

Смежные вопросы