PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : read() nach popen() schreibt "GNU" in den Puffer



nasontyphalt
24-06-2008, 18:31
Ahoi!

Ich würde gern popen() einsetzen, nach dem darauf folgenden read() steht aber nur "GNU" im Puffer.
So sieht mein Programm aus:


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


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

FILE *fd;
char buffer[1024];

fd = popen("ls", "r");

read( (int) fd, buffer, sizeof(buffer) );


printf("%s", buffer ); /* gibt "GNU" aus */

exit(0);

}

Warum tut es das?

jeebee
24-06-2008, 19:15
Dir ist bewusst, dass ein FILE* nicht ein Filedeskriptor ist, sondern ein File-Handle den du z.B. für fread() und co. brauchst. Wogegen read() einen FD haben will (dies ist einfach eine Zahl die beim Öffnen einer Datei vom Kernel vergeben wird...)


#include <stdio.h>
/* unistd.h brauchst du gar nicht ... */
#include <stdlib.h>


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

FILE *fd;
/* Buffer mit 0 initialisieren, dann kommt nicht am Schluss noch Müll
* wenn der Buffer zu gross ist.
*/
char buffer[1024] = {0};

fd = popen("ls", "r");

/* fread anstatt read
* Argument 1: Zielbuffer
* Argument 2: Blockgrösse zum Lesen
* Argument 3: Anzahl Blöcke zum Lesen
* Argument 4: FILE* Struktur von welcher gelesen wird
*/
fread(buffer, 512, sizeof(buffer)/512, fd );


printf("%s", buffer ); /* gibt "GNU" aus */

/* wenn schon exit() -- return 0 würde auch reichen --
* dann doch auch gerade mit den Standard-Exit-Werten EXIT_SUCCESS
* und EXIT_FAILURE, dann funktionierts nämlich auch auf
* einem System das nicht 0 als OK beim Rückgabewert hat wie
* erwartet
*/
exit(EXIT_SUCCESS);

}

Ist ganz kurz getestet. Wenn allerdings die Ausgabe von ls länger als dein Buffer ist wird einfach abgeschnitten.

peschmae
24-06-2008, 19:28
Einiges wurde schon gesagt, noch zwei Sachen:

Ich würde z.B. bei ls jetzt eher ein


fgets(buffer, sizeof(buffer), fd);

verwenden, das liest dir genau eine Zeile aufs Mal aus der Datei.

Ausserdem würde ich, sobald ich das Zeugs nicht mehr benötige, die Pipe wie sichs gehört schliessen:


pclose(fd);


MfG Peschmä

nasontyphalt
25-06-2008, 08:02
Das leuchtet ein. Ich danke euch beiden!

jeebee
25-06-2008, 08:06
@peschmae:
1) stimmt, dann hast du immer alles was ls ausgibt.
2) das pclose wollte ich eigentlich noch hinzufügen, ging dann aber vergessen.

jay-t
29-06-2008, 14:04
Einiges wurde schon gesagt, noch zwei Sachen:

Ich würde z.B. bei ls jetzt eher ein


fgets(buffer, sizeof(buffer), fd);

verwenden, das liest dir genau eine Zeile aufs Mal aus der Datei.



Bei meinen Projekten die auf mehreren Plattformen (Linux, Windows, Amiga) laufen, gab es mit "fgets" Probleme beim Linefeed.

Bei der Windowsversion wurde nur "CR LF" als Linefeed erkannt.
Dateien die z. B. unter Linux erstellt wurden und nur LF am Ende hatten
wurden nicht richtig gelesen.

Spätestens bei Projekten die auf mehreren OS laufen sollen, geht mit
fgets nichts mehr!

peschmae
29-06-2008, 19:35
Naja, es geht um den Output von einem ls, das hat natürlich einen Linefeed wie alles andere auf der Plattform auch - und gets erkennt den auch gleich ;)

Wenn man Plattformen mixerlt wirds natürlich übel. :D

MfG Peschmä