Ausgabe eines Aufgerufenen Programms in C verwenden
-
Hallo zusammen.
Ich habe ein hoffentlich kleines Problem.
Und zwar muss ich ein Tool in C schreiben,
welches ein weiteres Linux Tool aufruft
und dessen Ausgabe auf der Shell, bzw Teile davon,
in zB Variablen meines selbst erstellten Tools abspeichert
damit ich anschließend Abfragen kann ob die Ausgabe bestimmte Kriterien erfüllt.zB: Hat das Tool ausgegeben, dass diese und diese Information so und so ist.
Tipp: Es geht hier um das Tool Nmap. Wer es kennt, kennt auch die Ausgaben, die es macht.
Ich muss nun die teilweise sehr sehr lange Ausgabe eines Netzwerkscans auf bestimmte Kriterien von meinem C-Tool analysieren lassen.Ich hoffe, dass mir jemand weiterhelfen kann.
Liebe Grüße,
Felix
-
Ich mach zwar nix unter Linux, aber ich glaube, dafür gibt es eine Funktion namens popen - einfach mal danach googeln.
-
Belli schrieb:
Ich mach zwar nix unter Linux, aber ich glaube, dafür gibt es eine Funktion namens popen - einfach mal danach googeln.
Nein, den Aufruf des Programms Nmap mache ich innerhalb meines C-Tools mit
char cmd_out[255]; sprintf(cmd_out, "nmap ... befehle"); System("cmd_out");
Jetzt muss ich nur die Ausgabe, die auf der Shell erscheint weiterverarbeiten bzw brauche einzelne werte und zahlen, die das Programm Nmap auf der Shell ausgibt.
Wie bekomme ich diese Werte eingelesen in Variablen..?
LG Felix
-
Indem du das so machst, wie hingewiesen.
Du hast keine Ahnung von C aber weißt ganz genau, wie was geht und nicht geht?
Erkläre mal, wie du Probleme löst.
-
Ich kenn nur
system
als Funktion der Standardlibrary.Der Prottyp von
system
sieht so aus:int system (const char* command);
Der Rückgabe wert ist ein
int
und wird folgendermassen beschrieben:system schrieb:
Return Value
If command is a null pointer, the function returns a non-zero value in case a command processor is available and a zero value if it is not.If command is not a null pointer, the value returned depends on the system and library implementations, but it is generally expected to be the status code returned by the called command, if supported.
Da ist also nichts mit der Ausgabe von dem aufgerufenen Programm.
Wie ist dein System deklariert?
-
Wutz schrieb:
Indem du das so machst, wie hingewiesen.
Du hast keine Ahnung von C aber weißt ganz genau, wie was geht und nicht geht?
Erkläre mal, wie du Probleme löst.Ich habe mir kurz ne Übersicht zu popen() angeguckt und habe gesehen dass man so eine komplett neue Shellsitzung öffnet und das brauchte ich doch gar nicht oder?
Ich dachte man kann einfach entweder die Ausgabe in eine Datei schreiben lassen, aus der ich dann die sachen auslese oder dass ich direkt die Terminalausgabe aus demselben lesen kann. Ka. zB mit sscanf() ... aber ich weis ja nicht wie..Oder geht das ausschließlich so mit diesem popen?
Ich habe C nur zwei Jahre in der Schule gehabt und da auch nur eins indem wir ausschließlich Windows Console Applications gemacht haben und das zweite ausschließlich Microprozessoren angesteuert.
Und da das nur eins von vielen Fächern war habe ich jetzt nicht soo die Kenntnisse
Habe aber im Praktikum jetzt doofer weise Aufgaben die ausschließlich mit Linux zu tun haben, da das OS der hergestellten Geräte Linux ist.Tut mir leid, wenn meine Antworten manchmal so komisch rüberkommen. Ich weis auch nicht warum. Eigentlich will ich ja neues lernen ..
LG Felix
-
Das einfachste wäre, wenn du über die Shell die Pipe (|) benutzt:
nmap ... | YourProgramm
(wobei dann ... für die Argumente von nmap steht)
In deinem Programm kannst du dann über die Standardeingabe (stdin) die Ausgabe von nmap einlesen und interpretieren.
-
Th69 schrieb:
Das einfachste wäre, wenn du über die Shell die Pipe (|) benutzt:
nmap ... | YourProgramm
(wobei dann ... für die Argumente von nmap steht)
In deinem Programm kannst du dann über die Standardeingabe (stdin) die Ausgabe von nmap einlesen und interpretieren.
Danke das hört sich doch echt gut an!
Und das einlesen, wie geht das genau? Also den sscanf() Befehl habe ich bisher nur so als direkten User-Eingaben Scan verstanden ..
Liebe Grüße,
Felix
-
sscanf
ist zum lesen aus Strings.Da mit der Pipe die Standardausgabe von dem linken Programm zur Standardeingabe vom rechten Programm wird, kannst mit den ganz normalen Ein-/Ausgabefunktionen arbeiten:
scanf
(nur ein s)Da bedeutet aber auch, dass dein Programm nmap nicht mehr mit system aufruft.
mekick schrieb:
Ich dachte man kann einfach entweder die Ausgabe in eine Datei schreiben lassen, aus der ich dann die sachen auslese oder
Klar, geht auch.
Wenn du dein Programm richtig anfängst, gibt es keinen großen unterschied zu der Pipe-Version.mekick schrieb:
... oder dass ich direkt die Terminalausgabe aus demselben lesen kann. Ka. zB mit sscanf() ... aber ich weis ja nicht wie..
was ist an "Nutze
popen
" so schwer zu verstehen.
Wenn du nicht weiß wie dupopen
einsetzen kannst, ist das was anderes.
(Was der Bauer nicht kennt, frisst er nicht)das p bei popen steht übrigens für Pipe.
Und: http://de.wikipedia.org/wiki/Filter_(Unix)
-
DirkB schrieb:
sscanf
ist zum lesen aus Strings.Da mit der Pipe die Standardausgabe von dem linken Programm zur Standardeingabe vom rechten Programm wird, kannst mit den ganz normalen Ein-/Ausgabefunktionen arbeiten:
scanf
(nur ein s)Da bedeutet aber auch, dass dein Programm nmap nicht mehr mit system aufruft.
mekick schrieb:
Ich dachte man kann einfach entweder die Ausgabe in eine Datei schreiben lassen, aus der ich dann die sachen auslese oder
Klar, geht auch.
Wenn du dein Programm richtig anfängst, gibt es keinen großen unterschied zu der Pipe-Version.mekick schrieb:
... oder dass ich direkt die Terminalausgabe aus demselben lesen kann. Ka. zB mit sscanf() ... aber ich weis ja nicht wie..
was ist an "Nutze
popen
" so schwer zu verstehen.
Wenn du nicht weiß wie dupopen
einsetzen kannst, ist das was anderes.
(Was der Bauer nicht kennt, frisst er nicht)das p bei popen steht übrigens für Pipe.
Und: http://de.wikipedia.org/wiki/Filter_(Unix)Korrekt. Ich kenne popen nicht ! ^^
Ok. Gehen wir davon aus ich möchte das mit dem Ausgabe in Datei umlenken machen und danach die Datei durchgehen und daraus die sachen einlesen ...
how to() ?
ist das einfach ne while-schleife, die runterläuft bis es keine nächste zeile mehr gibt und von oben alles in einen string schreibt oder wie hab ich mir das vorzustellen?
LG und DANKE!
Felix
-
So sieht das ganz realistisch aus, was ich einlesen muss:
Starting Nmap 6.46 ( http://nmap.org ) at 2014-06-20 16:09 CEST Stats: 0:00:05 elapsed; 0 hosts completed (0 up), 256 undergoing Ping Scan Ping Scan Timing: About 41.99% done; ETC: 16:09 (0:00:07 remaining) Stats: 0:00:05 elapsed; 0 hosts completed (0 up), 256 undergoing Ping Scan Ping Scan Timing: About 84.96% done; ETC: 16:09 (0:00:01 remaining) Stats: 0:00:07 elapsed; 233 hosts completed (23 up), 23 undergoing Connect Scan Connect Scan Timing: About 90.29% done; ETC: 16:09 (0:00:00 remaining) Nmap scan report for MarkusB_I5-760.domain.de (192.168.4.85) Host is up (0.00086s latency). Not shown: 44 filtered ports PORT STATE SERVICE 80/tcp open http 443/tcp open https 445/tcp open microsoft-ds Nmap scan report for linux-dp.domain.de (192.168.4.121) Host is up (0.00012s latency). All 47 scanned ports on linux-dp.domain.de (192.168.4.121) are closed Nmap scan report for linux-jl2.domain.de (192.168.4.126) Host is up (0.000089s latency). All 47 scanned ports on linux-jl2.domain.de (192.168.4.126) are closed Nmap scan report for 192.168.4.140 Host is up (0.00024s latency). Not shown: 46 closed ports PORT STATE SERVICE 80/tcp open http Nmap scan report for 192.168.4.154 Host is up (0.00018s latency). Not shown: 46 closed ports PORT STATE SERVICE 445/tcp open microsoft-ds Nmap scan report for 192.168.4.161 Host is up (0.0100s latency). Not shown: 46 closed ports PORT STATE SERVICE 21/tcp open ftp Nmap scan report for linux-testserver3.domain.de (192.168.4.164) Host is up (0.00033s latency). Not shown: 45 closed ports PORT STATE SERVICE 21/tcp open ftp 80/tcp open http Nmap scan report for linux-testserver4.domain.de (192.168.4.165) Host is up (0.00029s latency). Not shown: 44 closed ports PORT STATE SERVICE 21/tcp open ftp 53/tcp open domain 80/tcp open http Nmap scan report for 192.168.4.166 Host is up (0.00026s latency). All 47 scanned ports on 192.168.4.166 are closed Nmap scan report for 192.168.4.168 Host is up (0.00026s latency). All 47 scanned ports on 192.168.4.168 are closed Nmap scan report for 192.168.4.207 Host is up (0.00022s latency). Not shown: 40 closed ports PORT STATE SERVICE 21/tcp open ftp 25/tcp open smtp 80/tcp open http 443/tcp open https 445/tcp open microsoft-ds 515/tcp open printer 631/tcp open ipp Nmap scan report for 192.168.4.208 Host is up (0.00020s latency). Not shown: 45 closed ports PORT STATE SERVICE 80/tcp open http 515/tcp open printer Nmap scan report for asterisk.domain.de (192.168.4.236) Host is up (0.00017s latency). Not shown: 44 closed ports PORT STATE SERVICE 21/tcp open ftp 80/tcp open http 443/tcp open https Nmap scan report for Server.domain.de (192.168.4.240) Host is up (0.00020s latency). Not shown: 45 closed ports PORT STATE SERVICE 445/tcp open microsoft-ds 631/tcp open ipp Nmap scan report for 192.168.4.243 Host is up (0.00039s latency). Not shown: 44 closed ports PORT STATE SERVICE 80/tcp open http 443/tcp open https 445/tcp open microsoft-ds Nmap scan report for 192.168.4.245 Host is up (0.00017s latency). Not shown: 43 closed ports PORT STATE SERVICE 80/tcp open http 443/tcp open https 445/tcp open microsoft-ds 631/tcp open ipp Nmap scan report for 192.168.4.246 Host is up (0.00018s latency). Not shown: 44 closed ports PORT STATE SERVICE 443/tcp open https 445/tcp open microsoft-ds 631/tcp open ipp Nmap scan report for mail-test.domain.de (192.168.4.247) Host is up (0.00058s latency). Not shown: 40 filtered ports PORT STATE SERVICE 25/tcp open smtp 80/tcp open http 110/tcp open pop3 143/tcp open imap 465/tcp closed smtps 993/tcp open imaps 995/tcp open pop3s Nmap scan report for dav.mail (192.168.4.248) Host is up (0.00072s latency). Not shown: 42 filtered ports PORT STATE SERVICE 80/tcp open http 443/tcp open https 465/tcp open smtps 993/tcp open imaps 995/tcp open pop3s Nmap scan report for 192.168.4.249 Host is up (0.00033s latency). Not shown: 46 closed ports PORT STATE SERVICE 80/tcp open http Nmap scan report for 192.168.4.251 Host is up (0.0011s latency). Not shown: 46 closed ports PORT STATE SERVICE 80/tcp open http Nmap scan report for INTEC_EM.domain.de (192.168.4.252) Host is up (0.00079s latency). Not shown: 43 closed ports PORT STATE SERVICE 25/tcp open smtp 110/tcp open pop3 143/tcp open imap 445/tcp open microsoft-ds Nmap scan report for Lancom_1611.domain.de (192.168.4.253) Host is up (0.00045s latency). Not shown: 45 closed ports PORT STATE SERVICE 80/tcp open http 443/tcp open https Nmap done: 256 IP addresses (23 hosts up) scanned in 7.75 seconds
-
DirkB schrieb:
was ist an "Nutze
popen
" so schwer zu verstehen.Mit popen ersparst du dir den Umweg über eine extra Datei; das kann bei deinem überschaubaren C-Wissen nur von Vorteil für Lösung deines Problems sein.
-
mekick schrieb:
how to() ?
ist das einfach ne while-schleife, die runterläuft bis es keine nächste zeile mehr gibt und von oben alles in einen string schreibt oder wie hab ich mir das vorzustellen?
Ja, möglicherweise. Du kannst aber gleich beim lesen auswerten.
mekick schrieb:
So sieht das ganz realistisch aus, was ich einlesen muss: ...
Und was möchtest du davon haben?
Die Anzahl der Wörter oder die IP-Adressen oder .... ?
DAvon hängt es dann ab, wie du weiter machst.
-
Ist das ein Rumgeeiere hier! Ich habe hier einmal ein Beispiel für drei mögliche Ansätze:
- Ausgabe umleiten in eine Datei.
- Ausgabe per popen zeilenweise einlesen
- Ausgabe per popen im Block einlesen
Das Beispiel kann optimiert werden und auf persönliche Anforderungen angepasst werden
(und es gibt auch noch andere Möglichkeiten), aber es zeigt, wie es gehen kann:#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <string.h> void to_file (char* cmd) { char redirect[256] = ">tmp.txt "; strcat (redirect, cmd); system (redirect); } void popen_line_by_line (char* cmd) { char psBuffer[128] = {0}; FILE *pPipe; pPipe = popen( "ls -l", "r" ); if( !pPipe ) exit( 1 ); while(fgets(psBuffer, 128, pPipe)) { printf ("%s",psBuffer); fflush (stdout); } pclose (pPipe); } void popen_to_buffer (char* cmd) { char psBuffer[128] = {0}; char msgBuffer[4096] = {0}; FILE *pPipe; pPipe = popen(cmd , "r" ); if( !pPipe ) exit( 1 ); while(fgets(psBuffer, 128, pPipe)) { printf ("%s",psBuffer); fflush (stdout); strcat(msgBuffer,psBuffer); } pclose (pPipe); printf ("%s",msgBuffer); } int main ( void ) { char* cmd = "ls -l"; // Nach Bedarf auskommentieren to_file(cmd); popen_line_by_line (cmd); popen_to_buffer(cmd); return 0; }
Ich persönlich hätte für die Aufgabe eine modernere Skriptsprache (z.B. PHP) gewählt,
da diese die gewünschte Funktionalität fest und relativ idiotensicher eingebaut haben.viele grüße
ralph
-
Die wohl in den meisten Fällen "richtigste" Möglichkeit ist aber immer noch das, was Th69 vorgeschlagen hat. Alles deutet da drauf hin, dass dies auch hier die richtige Wahl wäre.
Man muss nicht immer die genaue Frage des Threaderstellers beantworten, wenn doch offensichtlich ein X-Y Problem vorliegt.
-
rkhb schrieb:
... void to_file (char* cmd) { char redirect[256] = ">tmp.txt "; strcat (redirect, cmd); system (redirect); ... int main ( void ) { char* cmd = "ls -l"; // Nach Bedarf auskommentieren to_file(cmd); ... }
Was macht denn der Befehl
>tmp.txt ls -l
?
-
Das ist ein Deppenbeispiel, und genau so macht man es eben nicht.
Das Deppenbeispiel setzt voraus, dass im aktuellen Verzeichnis Schreibrechte und ausreichend Platz vorliegen, und wer räumt den Müll da hinterher wieder weg?
Genau, der Deppenprogrammierer sicherlich nicht.
All das entfällt, wie oben erwähnt, wenn man die POSIX konforme Funktion popen/pclose verwendet.
-
DirkB schrieb:
Was macht denn der Befehl
>tmp.txt ls -l
?Das Gleiche wie in einer Windows-Konsole ">tmp.txt dir". Der Trick: Man kann die Umleitung auch nach vorne bringen.
viele grüße
ralph
-
Nur als Hinweis... nmap unterstützt verschiedene Ausgaben. Es gibt so zB grepable- und auch xml-Ausgaben.
-
Nur zur info .. ich habe jetzt folgende Lösung gewählt:
1. gesamten Output in output.txt schreiben
2. mit getline() aus dem gcc GNU Compiler Zeilenweise einlesen
3. mit den strXXX()-Funktionen die Inhalte der einzelnen Zeilen auf Muster vergleichenDas schien mir anhand meiner bisherigen Kenntnisse die geeignetste Lösung und da ich mir nochmals die Anwendung des Programms vor Augen geführt habe ist mir klar geworden, dass es gar nicht schlecht ist, dass ich nun eine Ausgabedatei erhalte, da ich im Laufe des Programms mehrere Aufrufe machen müsste oder aber unübersichtliche Variablendefinitionen zwischenschieben müsste, so aber jetzt einfach immer wieder die output.txt als bestehenden Ausgangsstream nutzen kann.
Ich meine diese Lösung nennt sich jetzt Ausgabe in Datei umlenken und anschließendes Pathen ..?
Danke für eure Hilfe!!
Liebe Grüße,
FelixHier nochmal der Code:
// Pointer auf Datei = ptoutput FILE *ptoutput; // Prototyp von getline(): ssize_t getline(char** ReservierterSpeicherFürInputLine, size_t* ByteGrößeDesReserviertenSpeichers, FILE* InputStream) // Speicher für Buffer/InputLine festlegen char * ptline_in; ptline_in = (char *) malloc(70); // Variable für die Größe der Textzeile in Bytes size_t istorage = 70; // Wenn die Datei output.txt nicht geöffnet werden kann // Gebe Error aus if ( (ptoutput = fopen("output.txt","r")) == NULL) { fprintf(stderr, "\nKonnte Datei 'output.txt' nicht öffnen!"); return EXIT_FAILURE; } // Zeilenweises Einlesen von output.txt und Ausgeben der Gelesenen Zeilen und der Größe der Zeilen while(getline(&ptline_in, &istorage, ptoutput) > 0) { printf("Line: %s \nBytes: %u \n", ptline_in, istorage); } return EXIT_SUCCESS;