popen

Dieses Thema im Forum "C/C++" wurde erstellt von genius0815, 03.09.2009.

  1. #1 genius0815, 03.09.2009
    genius0815

    genius0815 Grünschnabel

    Dabei seit:
    01.09.2009
    Beiträge:
    7
    Zustimmungen:
    0
    Hallo ich versuche/suche eine Funktion, die ein bashcommando ausführt und dann den Wert zurückgibt. Mit system erhalte ich nur den Fehlerwert zurück. Da hab ich popen gefunden, aber ich krieg es nicht hin:

    cmd ist ein beliebiges Kommande der shell, der Rückgabewert soll ein Zeiger auf einen Char sein. Man weiss vorher nicht wie gross die Ausgabe des Kommandos ist. Den Rückgabewert will ich dann mit printf ausdrucken lassen beim Aufruf der Funktion.
    Ich glaub das was ich hier zusammmen gebaut hab, ist völlig falsch, aber ich weiss es gerade nicht besser und hab die anderen Varianten schon gelöscht.

    Code:
    char read_cmd(char *cmd)
    {
    		const size_t s = 1024;
            size_t bytes=8;
            char buffer[s];
    		char *output;
     		FILE* fp = NULL;
    		int nRet;
    		size_t *t = malloc(0);
    
    		char **gptr = (char **)malloc(sizeof(char*));
    		*gptr = NULL;
    
    		if((fp = popen(cmd,"r")) == NULL){
                          printf ("Failure during read command output\n");
                    }
    		else {
    			fread( buffer, bytes, s, fp);
    			gptr = (char *)buffer;
    			**gptr = realloc(gptr, s);
    			return gptr;
    		}
    }
    Danke für Hilfe
     
  2. Anzeige

    Schau dir mal diese Kategorie an. Dort findest du bestimmt etwas.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  3. #2 brainfuck, 03.09.2009
    brainfuck

    brainfuck Mitglied

    Dabei seit:
    17.06.2007
    Beiträge:
    48
    Zustimmungen:
    0
    Ort:
    Eppstein/Taunus
    Ohne genau dabei durchgestiegen zu sein was Du da gecodet hast erklär Ich dir mal wie man sowas prinzipiell macht (Ich mach das so selten in C, daher weiß ich nicht immer die genauen parameter etc):

    Du öffnest mit popen eine pipe zu deinem Programm, das hast Du ja schon richtig gemacht.
    Dann würde Ich einen Puffer anlegen der, weiß Ich, 100 byte groß ist. Dann solltest Du so lange bis zu 100B lesen bis der Stream geschlossen wird. Nach jedem lesevorgang solltest Du den Puffer mit realloc neu belegen, das geht mit realloc recht gut. Du musst nur aufpassen dass jedesmal ein neuer pointer an fread übergeben wird, weil Du ja nicht jedesmal den Puffer von vorne wieder zuschreiben willst. Achte auch darauf wie viel wirklich gelesen wurd, wobei das vermutlich nicht relevant ist, da Streams standardmäßig blockieren. Dies ist glaube Ich nur bei TCP problematisch. Du musst also jedesmal bisher_gelesene_bytes + letztes_mal_gelesene_bytes + 100B Speicher anfordern. Am Ende jagst Du den string am besten durch strdup, der macht eine Kopie was den vorteil hat dass Du nicht den überschüssigen speicher selbst freigeben musst. Du machst am Ende folgendes:

    /* buffer_all ist der puffer in dem alles am ende drinsteht, plus eventuell überschüssiger Speicher */
    char *ret_buffer = strdup(buffer_all);
    free(buffer_all);
    return ret_buffer;

    Damit sollte es dann erledigt sein.

    PS: die äußerst umständliche Speicherverwaltung ist der Grund dafür warum Ich lieber Objektorientiert Programmiere.

    PPS: vielleicht gibt es in C auch eine Funktion die 2 strings aneinander hängt. Dann könntest Du auch einfach vor jedem lesevorgang aus der pipe einen 100B puffer anlegen, 99B lesen (NULL am ende nicht vergessen), und den an das bisher gelesene Anhängen. Das würde Dir eine Menge Arbeit abnehmen.

    Ich hoffe Ich hab Dir mehr geholfen als dass Ich Dich verwirrt habe.
     
  4. Tblue

    Tblue Tripel-As

    Dabei seit:
    27.11.2007
    Beiträge:
    188
    Zustimmungen:
    0
    Gibt es, strcat() bzw. strncat().
     
  5. #4 brainfuck, 03.09.2009
    brainfuck

    brainfuck Mitglied

    Dabei seit:
    17.06.2007
    Beiträge:
    48
    Zustimmungen:
    0
    Ort:
    Eppstein/Taunus
    wobei strcat() afaik den speicher nicht selbst reserviert, wobei das ja dank strlen() kein großes Problem darstellt.
     
  6. #5 genius0815, 03.09.2009
    genius0815

    genius0815 Grünschnabel

    Dabei seit:
    01.09.2009
    Beiträge:
    7
    Zustimmungen:
    0
    Genau diesen Vorgang krieg ich nicht hin. Kann jemand mir etwas Quelltext als Anhaltspunkt geben?

    gruss
     
  7. #6 brainfuck, 03.09.2009
    brainfuck

    brainfuck Mitglied

    Dabei seit:
    17.06.2007
    Beiträge:
    48
    Zustimmungen:
    0
    Ort:
    Eppstein/Taunus
    Schon mal als Warnung: Ich habe diesen code nicht getestet, Ich hab ihn einfach mal so wie Ich denke dass es laufen _könnte_ runtergeschrieben:

    Code:
    char *read_cmd(char *cmd) {
    #define BUFSIZE 100
       char *tmp_buf = (char *)malloc(BUFSIZE + 1);
       /* vielleicht ist das +1 nicht nötig, aber es kann nicht schaden */
       char *ret_buf = (char *)malloc(1); /* für realloc nötig */
       int bytes_read = 0;
       int bytes_saved = 0;
       *tmp_buf = *ret_buf = '\0'; /* als string markieren */
       FILE *pipefd = popen(cmd, "r"); /* programm starten */
       if (!pipefd) {
          fprintf(stderr, "Failure starting command\n")
          exit(1);
       }
       while(!feof(pipefd)) { 
          /* dies nur so lange machen wie es etwas zu lesen gibt */
          bytes_read = fread(tmp_buf, sizeof(char), BUFSIZE, pipefd);
          ret_buf = realloc(ret_buf, bytes_saved + bytes_read + 1); 
          /* die adresse kann sich ändern */
          strncpy(ret_buf, tmp_buf, bytes_read);
          bytes_saved += bytes_read;
       }
       free(tmp_buf);
       return ret_buf;
    }
    
    Also wie gesagt, das Ganze ohne Gewähr!
     
  8. #7 genius0815, 04.09.2009
    Zuletzt bearbeitet: 04.09.2009
    genius0815

    genius0815 Grünschnabel

    Dabei seit:
    01.09.2009
    Beiträge:
    7
    Zustimmungen:
    0
    Hallo,

    es funktioniert leider nicht ganz so wie gewünscht. Das Problem ist, dass mehr zeilige Ausgaben des Commandos abgeschnitten werden. Muss ich irgendwo noch ein Linefeed einbauen? Oder das ganze mit getline machen?

    Hab jetzt rausgefunden, dass die Länge des zurückgegebenen Strings von BUFSIZE abhängt. Wird das doch nicht aneinander kopiert? Wenn ich das richtig verstehe ist doch ret_buf der Rückgabewert?

    gruss

    Jetzt hab ichs: statt strncpy muss man strncat nehmen zum aneinanderreihen der Strings sonst überschreibt er das alte.
     
  9. Anzeige

    Vielleicht findest du HIER Antworten.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  10. #8 brainfuck, 04.09.2009
    brainfuck

    brainfuck Mitglied

    Dabei seit:
    17.06.2007
    Beiträge:
    48
    Zustimmungen:
    0
    Ort:
    Eppstein/Taunus
    Oh, das wollte Ich eigentlich auch benutzen, muss mich wohl vertan haben.
    Aber dann gehts?
     
  11. #9 genius0815, 04.09.2009
    genius0815

    genius0815 Grünschnabel

    Dabei seit:
    01.09.2009
    Beiträge:
    7
    Zustimmungen:
    0
    Ja jetzt funktionert es danke.
    Wollte es erst noch umbauen auf eine verkettete Liste, weilich mit den strings hinterher was anfangen wollte, aber krieg ich net hin,muss ich wohl dann auf der shellebene machen.

    gruss
     
Thema:

popen

Die Seite wird geladen...

popen - Ähnliche Themen

  1. subprocess.Popen() - Stream Stout

    subprocess.Popen() - Stream Stout: subprocess.Popen() - Stream Stdout Hallo liebe leute, ich mal wieder :-) Ich habe ja in meinen vorherigen Threads beschrieben was ich machen...
  2. streams von der Standardausgabe abfangen mit popen()

    streams von der Standardausgabe abfangen mit popen(): Mahlzeit, ich will eine API für das CGI entwickeln um z.Bsp.: start/stop-Scripte anstoßen zu können, Dateien zu erzeugen usw.... Hilfreich, wenn...