使用C在shell中实现无限制的管道

时间:2015-04-28 21:44:29

标签: c linux bash shell pipe

我试图实现一个C shell,允许使用字符'>'

的无限制单向管道

所以它可以处理ls -A>尾巴> grep' .zip'

我知道管道应该在进程之间进行通信,但我认为我提出了一个可以使用一个管道和多个子进程的想法。

这是我到目前为止所拥有的

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

char *args[1000][1000];//array of arguments

int args_count = 0;//count of the arguments in the array

int runCommand(char **arguments, int *fd, int pipeHasSomeData, int baseCase) {

  pid_t pid;

  int x = 0;

  int status;

  pid = fork();

  if(pid != 0) {

      waitpid(pid, &status, 0);

      if(baseCase) {

          if(WIFEXITED(status))
            {

                if(WEXITSTATUS(status) == 0)
                {
                    /*it worked*/

                } else if(WEXITSTATUS(status) == 255) {

                    printf("The program %s does not exist \n", arguments[0]);

                } else {

                    printf("ERROR: Error code: %d", WEXITSTATUS(status));

                }
            }
            else
            {
                printf("There was a problem that is not normal");
            }

          printf("\n \n");

      }

      return 1;

    } else {

      if(pipeHasSomeData == 1) {//  read from the pipe

          dup2(fd[0], 0);//read from pipe

      }

      if(baseCase == 0) {// not the base case

          dup2(fd[1], 1);//write to pipe

      } else {

          close(fd[1]);//close write

      }

          exit(execvp(arguments[0], arguments));

        return 0;

    }

}

int execute_commands(char *arguments[1000][1000], int pd[2] = NULL) {

    int current_count = args_count;

    int iterator = 0;

    int fd[2];

    int useAPipeInCommand = 0;

    pipe(fd);

while(iterator <= args_count) {//go through and execute all the commands

        if(current_count == 0) {//base case

            return runCommand(arguments[iterator], fd, useAPipeInCommand, 1);

        } else {

            runCommand(arguments[iterator], fd, useAPipeInCommand, 0);

            useAPipeInCommand = 1;

        }

    iterator++;

    current_count--;

    }//end while

    return 1;

}

int main () {

    int i = 0;

    char  text[1024];             /* the input line                 */
    char *tok2;

     while (1) {                   /* repeat until done ....         */

      fflush(stdin);
      fflush(stdout);

      printf("Shell -> ");     /*   display a prompt             */

         *text = 0;

          fgets(text, sizeof text, stdin);             /*   read in the command line     */
          fflush(stdout);
          printf("\n");

          char * tok = strtok(text, " \n\t");

          if (strcmp(tok, "exit") == 0) {  /* is it an "exit"?     */
               return 0;         /*   exit if it is                */

          }

         if (strcmp(tok, " ") == 0) {  /* is it an "exit"?     */
               continue;         /*   exit if it is                */

          }

         tok2 = tok;

      memset(args, 0, sizeof(args[0][0]) * 1000 * 1000);//clear the arguments array

      args_count = 0;

          int count = 0;

          while(tok2 != NULL) {

             if(strcmp(tok2, ">") != 0) {

                 args[args_count][count] = tok2;

                 count++;

                 tok2 = strtok(NULL, " \n\t");

             } else {//pipe was found, up the argument counter and set count to 0

         args[args_count][count] = NULL;

         args_count++;

                 count = 0;

                 tok2 = strtok(NULL, " \n\t");

             }

         }

         args[args_count][count] = NULL;

     execute_commands(args);

    }//end while

    return 0;

}

运行单个基本情况没问题但是当我做管道时shell冻结了。关于这个问题的任何想法?

1 个答案:

答案 0 :(得分:0)

来自@beau-bouchard@rici的评论的正确答案:

管道有一个(小)有限缓冲区;除非正在读取管道的另一端,否则你不能不加阻塞地写入管道。

要获得正确的实施,请查看“C中的多个管道”Coding multiple pipe in C

- 更新:

以下是我遇到类似问题的最终工作代码:

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

int READ = 0;

int WRITE = 1;

char *args[1000][1000];//array of arguments

int args_count = 0;//count of the arguments in the array

int execute_commands(char *arguments[1000][1000]) {

    int pd[2];

    int iterator = 0;

    int fd[2];

    int f_in = 0;

while(iterator <= args_count) {//go through and execute all the commands

      pid_t pid;

      int status;

      pipe(fd);

      pid = fork();

      if(pid != 0) {

          waitpid(pid, &status, 0);//wait for child to exit
          close(fd[WRITE]);//close the writing end

              if(WIFEXITED(status))
                {

                    if(WEXITSTATUS(status) == 0)
                    {
                        /*it worked*/

                    } else if(WEXITSTATUS(status) == 255) {

                        printf("The program %s does not exist \n", arguments[iterator][0]);

                    } else {

                        printf("ERROR: Error code: %d", WEXITSTATUS(status));

                    }
                }
                else
                {
                    printf("There was a problem that is not normal %d", status);
                }

                f_in = fd[READ];//set the pipe to the in

          if(iterator == args_count) {

              printf("\n \n");

          }

          //return 1;

        } else {

          dup2(f_in, 0);

          if(iterator != args_count) {//its not the main value

              dup2(fd[WRITE], 1);//write to pipe

          }

          close(fd[READ]);

              exit(execvp(arguments[iterator][0], arguments[iterator]));

            return 0;

        }

    iterator++;

    }//end while

    return 1;

}

int main () {

    int i = 0;

    char  text[1024];             /* the input line                 */
    char *tok2;

     while (1) {                   /* repeat until done ....         */

      fflush(stdin);
      fflush(stdout);

      printf("Shell -> ");     /*   display a prompt             */

         *text = 0;

          fgets(text, sizeof text, stdin);             /*   read in the command line     */
          fflush(stdout);
          printf("\n");

          char * tok = strtok(text, " \n\t");

          if (strcmp(tok, "exit") == 0) {  /* is it an "exit"?     */
               return 0;         /*   exit if it is                */

          }

         if (strcmp(tok, " ") == 0) {  /* is it an "exit"?     */
               continue;         /*   exit if it is                */

          }

         tok2 = tok;

      memset(args, 0, sizeof(args[0][0]) * 1000 * 1000);//clear the arguments array

      args_count = 0;

          int count = 0;

          while(tok2 != NULL) {

             if(strcmp(tok2, ">") != 0) {

                 args[args_count][count] = tok2;

                 count++;

                 tok2 = strtok(NULL, " \n\t");

             } else {//pipe was found, up the argument counter and set count to 0

         args[args_count][count] = NULL;

         args_count++;

                 count = 0;

                 tok2 = strtok(NULL, " \n\t");

             }

         }

         args[args_count][count] = NULL;

     execute_commands(args);

    }//end while

    return 0;

}