Externes Programm mit Rückgabewert



  • Hi,
    Ich wollte mal fragen, wie ich ein Externes Programm (zB cat,ls, find, file, ...) aus C heraus ausführen kann und die Ausgabe dann bekomme?

    Also das was die sonst auf die Konsole schreiben.

    Mit fork den Prozess spalten und im child über exec das gewünschte Programm starten (also es wird das child ersetzt).
    Nur wie komme ich dann an die Ausgabe?
    Mit Pipes könnte ich zwischen zwei selbst geschrieben kommunizieren, aber so?
    Öder kann ich eine Pipe auch an das per Exec gestartet mit geben um das Ergebnis zu erhalten?



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C (C89 und C99) in das Forum Linux/Unix verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • http://lmgtfy.com/?q=fork+exec+stdin+pipe

    Je nach dem, was genau du machen möchtest, gibt es evtl auch elegantere Alternativen.



  • Der Trick ist, dass der neue Prozess die Handles des alten übernimmt. Du kannst also mit pipe(2) vorher eine pipe öffnen und dann STDOUT_FILENO mit der pipe verbinden (siehe dup(2)).



  • Schau dir mal popen an - das kann sowas. Verwende ich eigntlich sehr oft.
    Hab mir sogar ne Pfeiffe-Routine für Open Cobol gebastelt. Man brauchts halt immer wieder mal.



  • Man kann vor exec* stdout in die Pipe umleiten.

    Zum Beispiel:

    #define _GNU_SOURCE
    
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
    
    #include <stddef.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main() {
      pid_t pid;
      int status;
      int pipes[2];
    
      pipe(pipes);
      pid = fork();
    
      if(pid == -1) {
        perror("fork");
      } else if(pid == 0) {
        /* Kindprozess.
         *
         * Leseende der Pipe schließen, stdout in Schreibende umleiten.
         */
        close(pipes[0]);
        dup2 (pipes[1], STDOUT_FILENO);
    
        execlp("ls", "ls", "-l", "-a", NULL);
      } else {
        /* Vaterprozess.
         *
         * Der kann dann aus dem Leseende der Pipe das lesen, was der Kindprozess
         * nach stdout schreibt.
         */
        char *s = NULL;
        FILE *fd_pipe;
        size_t n = 0;
    
        close(pipes[1]);
    
        printf("child pid: %u\n", pid);
    
        fd_pipe = fdopen(pipes[0], "r");
        while(getline(&s, &n, fd_pipe) != -1) {
          printf("Vom Kindprozess: %s", s);
        }
    
        free(s);
    
        waitpid(pid, &status, 0);
    
        if(WIFEXITED(status)) {
          printf("Return value: %d\n", WEXITSTATUS(status));
        }
      }
    
      return 0;
    }
    

    Dabei ist _GNU_SOURCE nur für getline notwendig. Falls gewollt, kann man mit stderr und einer weiteren Pipe auf die gleiche Weise verfahren.



  • Hi danke mal!

    Dann noch 3 Fragen:
    1)
    Wieso wurde das in Linux/Unix verschoben?
    Sind alles Konstrukte, die doch auf Windows genau so laufen?
    Oder gings um die Beispielbefehle?

    Wie lese ich am besten aus der pipe heraus?
    Also jetzt am Beispiel "ls" zB.
    da hätte ich dann gerne jedes Element in einem Array.
    Sprich ich müsste ein Dynamisches Array anlegen und dieses würde auch aus dynamischen einträgen (strings) bestehen.

    Wie Handhabt ihr sowas?
    Welche "read" (als Überbegriff) Funktion wäre da geeigent?
    Würde weil jedes Zeichen einzeln ... an einen String anhängen, warten bis space kommt/ bzw \n bzw \r und dann in array hinzufügen ...?

    Was würdet ihr da vorschlagen?

    1. sollte man nicht vor dem lesen wait haben? sonst ließt man die pipe aus bevor es zu ende ist? Und wozu ist free(s)?

Anmelden zum Antworten