agapanthus: (C) - ext Programm rufen, stdout auswerten

Moin.

Heute komme ich mal mit einem Problem, weit weg von HTML & Co.:

Ich starte auf einer Linux-Kiste aus einem C-Programm ssh (mittels execve in einem Kind-Prozess, Parent wartet mittels wait() auf das Ende des Childs), was wiederum auf einer anderen Linux-Kiste ein Kommando ausführt. Das per ssh gerufene Programm gibt per stdout etwas zurück, die Ausgabe landet auf der Konsole des 1. Rechners. Soweit geht es. Ich brauche diese Ausgabe aber in einer Variable in meinem C-Programm...

Kann mir einer auf die Sprünge helfen?

In Perl ist's so schön einfach ;-)
$output = $command;

Danke für Eure Antworten,
Gruß Frank

  1. Tag,
    Meine C-Tage sind zwar schon ein weilchen her, aber könnts damit gehen:

    popen, pclose - initiate a pipe to or from a process

    Viele Grüße,
    Jörg

    1. Moin.

      popen, pclose - initiate a pipe to or from a process

      Ja, so einfach ist's, fast wie in Perl ;-)

      Danke!

      Gruß Frank

  2. 你好 agapanthus,

    [… Ausgabe umleiten …]
    Kann mir einer auf die Sprünge helfen?

    Eigentlich sehr einfach: vor dem fork() einen pipe()-Aufruf machen. Dann
    im Kind _vor_ dem execve() per dup2() den stdout-Deskriptor in die Pipe
    umleiten:

      
    int main(void) {  
      int fds[2],status;  
      pid_t p;  
      
      if(pipe(fds) == -1) {  
        perror("pipe");  
        return EXIT_FAILURE;  
      }  
      
      if((p = fork()) == -1) {  
        close(fds[0]);  
        close(fds[1]);  
        perror("fork");  
        return EXIT_FAILURE;  
      }  
      
      if(p == 0) {  
        if(dup2(fileno(stdout),fds[1]) == -1) {  
          perror("dup2");  
          close(fds[0]);  
          close(fds[1]);  
          return EXIT_FAILURE;  
        }  
      
        execve(...);  
        close(fds[0]);  
        close(fds[1]);  
        perror("execve"); /* only reached if an error occures */  
        return EXIT_FAILURE;  
      }  
      
      /* hier von fds[0] die Ausgabe des Programms lesen */  
      
      waitpid(p,&status,0);  
      if(WEXITSTATUS(status) != EXIT_SUCCESS) {  
        close(fds[0]);  
        close(fds[1]);  
        return EXIT_FAILURE;  
      }  
      
      /* mach was mit der Ausgabe */  
      
      close(fds[0]);  
      close(fds[1]);  
      
      return EXIT_SUCCESS;  
    }  
    
    

    So müsste es passen. Typos kannst du behalten ;)

    再见,
     克里斯蒂安

    --
    Meine Schultüte | Nein, es ist nicht das Fenster…
    On the day *I* go to work for Microsoft, faint oinking sounds will be heard from far overhead, the moon will not merely turn blue but develop polkadots, and hell will freeze over so solid the brimstone will go superconductive. (Eric Raymond als Antwort auf ein Job-Angebot von MS)
    http://wwwtech.de/
    1. Moin.

      Eigentlich sehr einfach: vor dem fork() einen pipe()-Aufruf machen. Dann
      im Kind _vor_ dem execve() per dup2() den stdout-Deskriptor in die Pipe
      umleiten:

      Ah, verstehe. Auch wenn Jörgs Lösung einfacher aussieht, ich werde Deine jetzt auch noch probieren. Bin beim Suchen eben auch auf dub gestoßen, die man page von Linux ist allerdings nicht soooo ergiebig.

      Danke.

      Gruß Frank

      1. 你好 agapanthus,

        Eigentlich sehr einfach: vor dem fork() einen pipe()-Aufruf machen. Dann
        im Kind _vor_ dem execve() per dup2() den stdout-Deskriptor in die Pipe
        umleiten:

        Ah, verstehe. Auch wenn Jörgs Lösung einfacher aussieht, ich werde Deine
        jetzt auch noch probieren.

        Ja, in der Praxis reicht popen() meistens aus, aber nicht immer ;) Egal,
        es ging hier eher ums Verständnis, wie das funktioniert ;)

        Bin beim Suchen eben auch auf dub gestoßen, die man page von Linux ist
        allerdings nicht soooo ergiebig.

        Find ich nicht, ich find sie völlig ausreichend ;)

        再见,
         克里斯蒂安

        --
        Neuer alter Plasma-Bildschirm | Meine Schultüte
        Fatal! Ich kann kein Reserve-Offizier mehr sein!
        http://wwwtech.de/
    2. Hi,

      if(dup2(fileno(stdout),fds[1]) == -1) {

      IEEE Std 1003.1, 2004 Edition:

      RETURN VALUE
      Upon successful completion, fileno() shall return the integer value of the file descriptor associated with stream. Otherwise, the value -1 shall be returned and errno set to indicate the error.

      ERRORS
      The fileno() function may fail if:
      [EBADF] The stream argument is not a valid stream.

      Das ist bei "stdout" kaum anzunehmen, ist aber technisch durchaus moeglich (ich hab' da schon Dinger gesehn, ich kann Dir sagen! ;-). Man sollte aber den OP zumindest darauf hinweisen finde ich.

      waitpid(p,&status,0);

      Auch waitpid() gibt etwas zurueck, ist jedoch in diesem Beispiel nicht wirklich relevant. Dem OP sei aber auch hier die relevante Manpage zur Lektuere empfohlen.

      if(WEXITSTATUS(status) != EXIT_SUCCESS) {

      Davor fehlt etwas. Was? Nun, ein Blick in die Manpage:

      WIFEXITED(status)
        is non-zero if the child exited normally.

      WEXITSTATUS(status)
        evaluates to the least significant  eight  bits  of
        the  return  code  of  the  child which terminated,
        which may have been set as the argument to  a  call
        to exit() or as the argument for a return statement
        in the main program.  This macro can only be evalu­
        ated if WIFEXITED returned non-zero.

      Entspricht damit POSIX:

      IEEE Std 1003.1, 2004 Edition:
      WIFEXITED(stat_val)
      Evaluates to a non-zero value if status was returned for a child process that terminated normally.

      WEXITSTATUS(stat_val)
      If the value of WIFEXITED(stat_val) is non-zero, this macro evaluates to the low-order 8 bits of the status argument that the child process passed to _exit() or exit(), or the value the child process returned from main().

      return EXIT_SUCCESS;

      Eigentlich gehoeren die beiden Macros EXIT_SUCCESS und EXIT_FAILURE zu exit() und sollten nicht ausserhalb diesen Zusammenhanges benutzt werden.
      Aber wie gesagt: "eigentlich", denn es macht ja doch jeder, auch ich.

      Entschuldige bitte, das ich mal wieder voellig uebertrieben pingelig bin, mir war einfach danach, denn <http://www.niscc.gov.uk/niscc/docs/br-20051114-01013.html@das hier> trifft fuer meine zwei Netze, die das nutzen aufgrund meiner Paranoia^WPingeligkeit nicht zu ;-)

      so short

      Christoph Zurnieden

      1. 你好 Christoph,

        Entschuldige bitte, das ich mal wieder voellig uebertrieben pingelig bin,
        mir war einfach danach, denn das hier trifft fuer meine zwei Netze, die das
        nutzen aufgrund meiner Paranoia^WPingeligkeit nicht zu ;-)

        Hehe, ich habe mich schon gefragt, was dich aufgehalten hat ;)

        再见,
         克里斯蒂安

        --
        Neuer alter Plasma-Bildschirm | Meine Schultüte
        Q: God, root, what's the difference?
        A: God is merciful.
        http://wwwtech.de/