C中的多管道bash风格

r3d*_*ice 1 c unix shell pipe

我知道有很多线程都在谈论这个问题,但我真的不明白它的实现方式.

我正在尝试创建一个可以执行linux命令的shell,因为ps | grep | less 我已经通过将每个命令及其args放在一个简单的链接列表中来进行解析.

这是我的实现不起作用.希望足够清楚.

if ((son = fork()) < 0)
  return printerr_sys("Unable to fork", 0);
if (son == 0)
  {
    if (first > 1 && data->format[first - 1] &&
    is_directing_elt(data->format[first - 1]) == DIRECT_TPIPE)
       dup2(tube_p[0], STDIN_FILENO);
       first = make_argv(data, first, &argv);
    if (next)
     {
      dup2(tube_v[1], STDOUT_FILENO);
      close(tube_v[0]);
     }
    if (execvp(argv[0], argv) < 0)
      return printerr_cmd(argv[0], 1);
  }
else
  {
    if (next)
        {
           close(tube_v[1]);
           cmdline_executer(data, next, tube_v);
        }
    waitpid(son, &(data->lastcmd), WUNTRACED);
    data->lastcmd = WEXITSTATUS(data->lastcmd);
  }
return TRUE;
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  • 什么是正确的实施?
  • 是否有可能通过递归来做到这一点?
  • 我需要从右到左或从左到右分叉(从逻辑上讲,它会得到相同的结果)?

Osc*_*ros 5

这是我在计算机科学职业生涯中必须在C for Operating System主题中实现的UNIX Shell的一部分.

/* Executes the command 'buffer' assuming that doesn't contain redirections */
void execute_only_pipes(char* buffer)
{
    char *temp = NULL, *pipeCommands[MAX_PIPES], *cmdArgs[MAX_ARGUMENTS];
    int newPipe[2], oldPipe[2], pipesCount, aCount, i, status;
    pid_t pid;

    pipesCount = -1; /* This variable will contain how many pipes the command contains */

    /* Counting the number of pipes and splitting them into pipeCommands */
    do 
    {
        temp = strsep(&buffer, "|");

        if(temp != NULL) 
        {
            if(strlen(temp) > 0) 
            {
                pipeCommands[++pipesCount] = temp;
            }
        }
    } while(temp);

    cmdArgs[++pipesCount] = NULL;

    for(i = 0; i < pipesCount; i++) /* For each command */
    {
        aCount = -1;

        /* Parsing command & arguments */
        do 
        {
            temp = strsep(&pipeCommands[i], " ");
            if(temp != NULL) 
            {
                if(strlen(temp) > 0) 
                {
                    /* If a parameter is ~, then replace it by /home/user */
                    if (!strcmp(temp, "~"))
                        strcpy(temp, home);
                    cmdArgs[++aCount] = temp;
                }
            }
        } while(temp);

        cmdArgs[++aCount] = NULL;

        /* If there still are commands to be executed */
        if(i < pipesCount-1) 
        {
            pipe(newPipe); /* just create a pipe */
        }

        pid = fork();

        if(pid == 0)  /* Child */
        {
            /* If there is a previous command */
            if(i > 0)
            {
                close(oldPipe[1]);
                dup2(oldPipe[0], 0);
                close(oldPipe[0]);
            }

            /* If there still are commands to be executed */
            if(i < pipesCount-1) 
            {
                close(newPipe[0]);
                dup2(newPipe[1], 1);
                close(newPipe[1]);
            }

            /* Execute it */
            int res = execvp(cmdArgs[0], cmdArgs);

            if (res == -1)
            {
                printf("Error. Command not found: %s\n", cmdArgs[0]);
            }
            exit(1);
        } 
        else /* Father */
        {
            /* If there is a previous command */
            if(i > 0) 
            {
                close(oldPipe[0]);
                close(oldPipe[1]);
            }

            /* do we have a next command? */
            if(i < pipesCount-1) 
            {
                oldPipe[0] = newPipe[0];
                oldPipe[1] = newPipe[1];
            }

            /* wait for last command process? */
            if(i == pipesCount-1) 
            {
                waitpid(pid, &status, 0);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它可能是一个小马车(我不检查是否fork() < 0等),但主要想法是正确的.

>是否可以通过递归来实现?

大多数时候我试图避免递归,如果我可以编写类似可理解的代码而不使用它.