PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Pipes in C



Pug
29-06-2001, 14:23
Hi,

wie kann ich aus einem C Programm raus ein anderes Programm aufrufen und Ihm Daten per Pipe übergeben????.

CU Pug

o.bildesheim
29-06-2001, 17:02
Hallo, Pug!

Du kannst den Systemcall pipe() verwenden, um eine Pipe anzulegen. Als einzigen Parameter erwartet dieser Systemcall ein Array mit zwei Integer, den Filedeskriptoren, die die beiden Enden der Pipe bilden sollen.

Ich vermute, dass aufgerufen Programm soll ueber die Standardeingabe Daten erhalten. Dann verwendest Du am einfachsten die Standardausgabe im aufrufenden Programme. Das ganze geht mit fork(), execlp() zum Steuern der Prozesse und Aufruf des Programms, sowie durch Verwendung von pipe() zum Bereitstellen der Pipe.

Hier ein Beispiel:

<pre>
#include <unistd.h>
#include <stdio.h>

int main( int argc, char** argv)
{
char meinText[] = "Hallo Programm.\n";
int fds[2];
pipe(fds);
if (0 == fork()) {
/*
Kindprozess
*/
dup2( fds[0], 0);
close( fds[1]); /* brauch ich nicht */
/*
fuehre Programm testfilter aus;
es werden keine Parameter ueber-
geben.
*/
execlp(
"/usr/local/bin/testfilter",
"testfilter", 0);
/*
wenn execlp() zurueckkehrt,
muss ein Fehler passiert sein
*/
fprintf( stderr,
"Fehler bei execlp\n");
exit(1);
}
/*
Vaterprozess
*/
close( fds[0]);
write( fds[1],
meinText, strlen(meinText));
close( fds[1]);
wait(0); /* auf Kindprozess warten */
}
</pre>

Beste Gruesse,
Oliver Bildesheim

[ 29. Juni 2001: Beitrag editiert von: o.bildesheim ]

[ 29. Juni 2001: Beitrag editiert von: o.bildesheim ]

[ 29. Juni 2001: Beitrag editiert von: o.bildesheim ]

jgbauman
29-06-2001, 17:13
Unter http://www.linuxforen.de/cgibin/ubb/ultimatebb.cgi?ubb=get_topic&f=18&t=000328 gibts die Python Versions. Must Du nur noch in C uebersetzten. Hilfe gibts unter:
man pipe
man open
man execv
man close

Pug
29-06-2001, 17:26
Habe schon etwas zusammen gestückelt



#include &ltunistd.h&gt
#include &ltstdlib.h&gt
#include &ltstdio.h&gt

int main( int argc, char** argv)
{

char addr[] = "root@localhost";
char subject[] = "Murphy's Gesetz";
char text[] = "Ausnahmen sind grundsätzlich zahlreicher als Regeln.\n";

int fds[2],status;


pipe(fds);

if (0 == fork()) {

/* child */
dup2( fds[0], 0);
close( fds[1]);

execlp("mail", "mail", "-s", subject, addr, 0);
fprintf( stderr, "execlp mail failed\n");
exit(1);
}

/* parent */
close( fds[0]);

write( fds[1], text, strlen(text));

close( fds[1]);
wait(0);
}


bekomme aber immer folgende Ausgabe:

ni-tux01:~ # gcc testmal.cc
testmal.cc: In function `int main(int, char **)':
testmal.cc:36: implicit declaration of function `int wait(...)'
ni-tux01:~ #

Hat jemand einen Lösungsvorschlag für mich ??

[ 29. Juni 2001: Beitrag editiert von: Pug ]

Pug
29-06-2001, 19:32
Ok,

Wenn ich die Datei in von *.cc in *.c umbennene dann funktioniert es komischerweise.

Kann der c++ nix mit den Headerfiles anfangen oder was ist da los ???

CU
PUG

o.bildesheim
29-06-2001, 23:11
Hallo, Pug!

Falls Du bei explizitem Aufruf des g++ (also g++ statt gcc) noch die gleiche Fehlermeldung bekommst, dann kann es sein, das der C++ Compiler die Sache etwas anders angeht als der C Compiler.

Den einen oder anderen Unterschied gibt es natuerlich, wenn die Datei auf cc endet, da dann der gcc i.d.R. annimmt, er muesse den C++ Compiler anwerfen - allerdings sollten die Standard (C) Headerfiles trotzdem verwendet werden koennen (zumindest weitestgehend).

Die bekannten Unterschiede zwischen C++/C werden im allgemeinen durch entsprechende Preprocessoranweisungen in den Headerfiles abgefangen.

Beste Gruesse,
Oliver Bildesheim

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,Geneva">Zitat:</font><HR>Original erstellt von Pug:
<STRONG>Ok,

Wenn ich die Datei in von *.cc in *.c umbennene dann funktioniert es komischerweise.

Kann der c++ nix mit den Headerfiles anfangen oder was ist da los ???

CU
PUG</STRONG>[/quote]

Pug
02-07-2001, 14:52
Hallo,

Danke erstrmal für die Hilfe und die Informationen. Das Proggi läuft jetzt. Allerdings habe ich noch eine Frage.

Ich möchte aus einem Daemon heraus eine Pipe in ein anderes Programm bzw. Perlscript öffnen. Wie könnte mann das realisieren?

Es handelt sich um den Scanlogd Daemon von Solar Designer.

Hier mal ein Auszug aus dem Code




/*
* scanlogd v2.2 by Solar Designer <solar@false.com>.
*
* You're allowed to do whatever you like with this software (including
* re-distribution in any form, with or without modification), provided
* that credit is given where it is due and any modified versions are
* marked as such.
*
* There's absolutely no warranty.
*/

int main(void)
{
#ifndef SCANLOGD_USER
/* We probably can't disable promiscuous mode if we aren't running as root */
signal(SIGTERM, cleanup);
signal(SIGINT, cleanup);
signal(SIGHUP, cleanup);
#endif

/* Initialize the packet capture interface */
if (in_init()) return 1;

chdir("/");
setsid();

#ifdef USE_RLOG
errno = 0;
if (openrlog(RLOG_ID)) {
fprintf(stderr,
"openrlog(\"" RLOG_ID "\"): %s\n",
errno ? strerror(errno) : "Failed");
return 1;
}
#endif

/* We can drop root now */
#ifdef SCANLOGD_USER
drop_root();
#endif

/* Become a daemon */
switch (fork()) {
case -1:
pexit("fork");

case 0:
break;

default:
/* in_init() could have registered an atexit(3) function to restore the
* interface, but this is not a real exit, yet (in fact, we're starting
* up), so we use _exit(2) rather than exit(3) here */
_exit(0);
}

setsid();

/* Initialize the state. All source IP addresses are set to 0.0.0.0, which
* means the list entries aren't in use yet. */
memset(&state, 0, sizeof(state));


Wie kann ich hier das mit der Pipe regeln ich habe probiert die Pipe vor dem Fork() bei "// Become a Daemon " zu erstellen und falls Fork dir PID 0 zurück liefert in meine Routinen zu springen aber das scheint sich nicht mit dem Daemon zu vertragen.

Hat jemand einen Vorschlag?

CU PUG