Implementierung mehrerer Pipes mit dem Systemaufruf fork () execvp () wait () pipe () - es funktioniert einfach nicht

Ich muss meine Shell implementieren, die mehrere Pipe-Befehle verarbeitet. Zum Beispiel muss ich in der Lage sein, damit umzugehen:ls | grep -i cs340 | sort | uniq | cut -c 5. Ich gehe davon aus, dass das Problem darin besteht, dass ich die Ausgabe des vorherigen Befehls nicht an die Eingabe des nächsten Befehls übergebe. Wenn ich meinen Code ausführe, erhalte ich keine Ausgabe. Ich benutze diesen Pseudocode:

for cmd in cmds
    if there is a next cmd
        pipe(new_fds)
    fork
    if child
        if there is a previous cmd
            dup2(old_fds[0], 0)
            close(old_fds[0])
            close(old_fds[1])
        if there is a next cmd
            close(new_fds[0])
            dup2(new_fds[1], 1)
            close(new_fds[1])
        exec cmd || die
    else
        if there is a previous cmd
            close(old_fds[0])
            close(old_fds[1])
        if there is a next cmd
            old_fds = new_fds
if there are multiple cmds
    close(old_fds[0])
    close(old_fds[1])

Hier ist der Quellcode der Funktion, die mehrere Pipes verarbeitet.

void execute_multiple_commands(struct command ** commands_to_exec,
        int num_commands_p)
{
    pid_t status;
    int i, err;
    int new_fd[2], old_fd[2];
    pid_t pid, cpid;

    // creating child process
    if ( (cpid = fork()) == -1)
    {
        fprintf(stderr, "Could not create child process, exiting...");
        exit(1);
    }

    if (cpid == 0) // in the child process we run multiple pipe handling
    {
        for (i = 0; i < num_commands_p; i++) // for each cmd in cmds
        {
            if (i+1 < num_commands_p) // if there is next cmd
                pipe(new_fd);

            if ( (pid = fork()) == -1)
            {
                fprintf(stderr, "Could not create child process, exiting...");
                exit(1);
            }

            if (pid == 0) // if child
            {
                if (i != 0) // if there is a previous command
                {
                    dup2(old_fd[0], 0); // setting up old_pipe to input into the child
                    close(old_fd[0]);
                    close(old_fd[1]);

                }
                if (i+1 < num_commands_p) // if there is a next cmd
                {
                    close(new_fd[0]); // setting up new_pipe to get output from child
                    dup2(new_fd[1], 1);
                    close(new_fd[1]);

                    err = execvp(commands_to_exec[i]->args[0], commands_to_exec[i]->args);
                    status = err;
                    exit(err);
                }
            }
            else
            {
                waitpid(pid, &status, 0);
                if (status == -1)
                    exit(1);

                if (i != 0) // if there a previous command
                {
                    close(old_fd[0]);
                    close(old_fd[1]);
                }
                if (i+1 < num_commands_p) // if there a next cmd
                {
                    old_fd[0] = new_fd[0];
                    old_fd[1] = new_fd[1];
                }
                exit(0);
            } // end if
        } // end for

        if (i) // if there a multiple commands
        {
            close(old_fd[0]);
            close(old_fd[1]);
        }
    }
    else // in the parent process we are waiting for child to handle multiple pipes
        waitpid(cpid, &status, 0);
}

Funktionexecvp() nimmt Array von Strukturen. Ich habe mein gesamtes Analyseteil überprüft und es funktioniert einwandfrei. Es ist derexecute_multiple_commands() Funktion, mit der ich Probleme habe.

Hier ist der Code für struct:

// name: command
// desc: holds one command (meaning that it can be
//        more than one token in that command)
//        "ls -la" will be an example of one command
//       holds num of tokens in command array
struct command
{
    char ** args;
    int num_args;
};

Antworten auf die Frage(1)

Ihre Antwort auf die Frage