(C) - ext Programm rufen, stdout auswerten
agapanthus
- programmiertechnik
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
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
Moin.
Ja, so einfach ist's, fast wie in Perl ;-)
Danke!
Gruß Frank
你好 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 ;)
再见,
克里斯蒂安
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
你好 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 ;)
再见,
克里斯蒂安
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
你好 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 ;)
再见,
克里斯蒂安