Reimplementacja pipe znanego z terminala.

0

Cześć, za zadanie mam zrobić program myPipe, taki że myPipe arg1 arg2 arg3 ... wykona efektywnie arg1 | arg2 | arg3 | ... (w np. bashu).

To jest to co mam:

#include <unistd.h>
#include <sys/types.h>

#include "err.h" // Zawiera funkcję syserr, która wypisuje konkretny błąd, a następnie kończy proces.

int main(int argc, char* argv[])
{
    argc--;
    argv++;

    if (argc == 0) {
        return 0;
    }
    if (argc == 1) {
        execl(argv[0], argv[0], NULL);
    }

    pid_t pid;
    int pipefd[argc - 1][2];
    for (int i = 0; i < argc - 1; ++i) {
        if (pipe(pipefd[i]) == -1) syserr("Ceci n'est pas une pipe.");
    }
    for (int i = 0; i < argc; ++i) {
        switch (pid = fork()) {
            case 0:
                if (i > 0) {
                    if (close(0) == -1) syserr("close(0)");
                    if (dup2(pipefd[i-1][0], 0) == -1) syserr("dup2(pipefd[i-1][0], 0)");
                }
                if (i < argc - 1) {
                    if (close(1) == -1) syserr("close(1)");
                    if (dup2(pipefd[i][1], 1) == -1) syserr("dup2(pipefd[i][1], 1)");
                }
                if (execl(argv[i], argv[i], NULL) == -1) syserr("execl");
                break;
            case -1:
                syserr("fork");
        }
    }
}

Problem polega na tym, że jak zrobię echo some_input | ./myPipe ./example ./example, to program działa, natomiast jeśli wejście nie będzie przekierowane, to pierwszy z programów informuje, że nie podołał zadaniu czytania danych z stdin. Co robię źle?

Dodam jeszcze, że jeśli używam strace do uruchomienia programu, błąd nie występuje.

1

Taki kod zdaje się działać dobrze:

    for (int i = 0; i < argc; ++i) {
        pid = fork();
        if(pid > 0) {
                if (i > 0) {
                    if (close(0) == -1) syserr("close(0)");
                    if (dup2(pipefd[i-1][0], 0) == -1) syserr("dup2(pipefd[i-1][0], 0)");
                }
                if (i < argc - 1) {
                    if (close(1) == -1) syserr("close(1)");
                    if (dup2(pipefd[i][1], 1) == -1) syserr("dup2(pipefd[i][1], 1)");
                }
                if (execl(argv[i], argv[i], NULL) == -1) syserr("execl");
        } else if (pid < 0) {
                syserr("fork");
        }
    }

Temat jest dość złożony. Przypuszczam, że różnica polega na tym, że jak nie czytasz ze strumienia (strace pewnie też używa przekierowania) to czytasz z urządzenia znakowego (/dev/tty czy coś w tym guście). Z doświadczenia wiem, że pliki, strumienie, strumienie nazwane i urządzenia specjalne zachowują się czasami inaczej i inaczej niż byśmy się spodzewali. :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1