2016-03-30 14 views
0

Ich habe die vorherigen Fragen, die gefragt wurden, angeschaut. Und ich habe diesen Code entwickelt, um den aktuellen Wert von stderr zu erhalten, ihn an einen buf umzuleiten und stderr neu zuzuweisen. Das ist Code.umleiten stderr zu einem Puffer in c

Die Umleitung des stderr zum Buff findet nicht statt. Ich habe dies auf dem Bildschirm sehen kann, wenn ich versuche, den Code auszuführen:

 ls: cannot access system: No such file or directory 
    hellow world 
    error from buffer 

Der Quellcode sieht wie folgt aus:

#include<stdio.h> 
static int fd; 
static fpos_t pos; 
char *buf; 

void closeerr() 
{ 
    fflush(stderr); 
    fgetpos(stderr, &pos); 
    fd = dup(fileno(stderr)); 
    buf =(char *)calloc(sizeof(char *),1024); 
    stderr = fmemopen(buf, sizeof(buf), "w"); 
} 

void reverterr() 
{ 
    fflush(stderr); 
    dup2(fd, fileno(stderr)); 
    close(fd); 
    clearerr(stderr); 
    fsetpos(stderr, &pos); 
} 

void main() 
{ 
    closeerr(); 
    printf("hellow world"); 
    system(" ls -l system"); // this is where I see the error msg 
    printf("error from buffer %s",buf); 
    reverterr(); 
} 

Dieser Code erneut anweist stdout (die Logik wäre gleich Re-direct stderr) in eine temporäre Datei (Ansatz 1 wie unten vorgeschlagen, obwohl ich nicht gegabelt haben, und ein Kind-Prozess erstellt, um in die Datei zu schreiben)

void switchStdout(const char *newStream) 
{ 
    fflush(stdout); 
    fgetpos(stdout, &pos); 
    fd = dup(fileno(stdout)); 
    freopen(newStream, "w", stdout); 

}

void revertStdout() 
{ 
    fflush(stdout); 
    dup2(fd, fileno(stdout)); 
    close(fd); 
    clearerr(stdout); 
    fsetpos(stdout, &pos); 
} 

void main(){ 
    switchStdout("/tmp/err.txt"); 
    printf("Hello world"); 
    revertStdout(); 
} 
+0

Gegeben 'char * buf;' was, was denkst du 'sizeof (buf);' ist? –

Antwort

1

Die fmemopen() Funktion tatsächlich keinen Dateideskriptor öffnen, so dass auf einem fileno()FILE von fmemopen() kehrt ein undefinierter Wert erhalten. fmemopen() wird implementiert, indem direkt in den Puffer geschrieben wird, ohne dass die Daten jemals über das Betriebssystem gesendet werden. Es ist nicht möglich, die mit fmemopen() geöffnete Datei durch eine fork() zu erhalten.

Ein weiteres Problem ist, dass Sie nie Speicher für Ihren Puffer reservieren, lesen Sie über die fmemopen() API und wie Sie es verwenden, um das Problem zu verstehen.

Hier sind zwei Ansätze, die funktionieren:

  • eine temporäre Datei öffnen, dann fork(). Im gegabelten Prozess dupieren Sie den Dateideskriptor über den Dateideskriptor 2 (STDERR_FILENO) und führen Sie dann Ihren Befehl aus. In der Eltern, wait() für das Kind, dann lesen Sie, was es in die temporäre Datei geschrieben hat. Beachten Sie, dass Sie eine lseek() vor dem Lesen tun müssen, da das Kind den Dateizeiger ändert.
  • öffnen Sie einen Fifo mit pipe(), dann fork(). Im Kind, duple das Schreibende über den Dateideskriptor 2, schließe das Leseende und führe dann deinen Befehl aus. Schließen Sie im übergeordneten Element das Schreibende und lesen Sie, was das Kind während des Lesevorgangs vom Leseende geschrieben hat. Vergiss nicht wait() für das Kind danach.
+0

Ich betrachtete den Ansatz, die Ausgabe in eine temporäre Datei zu schreiben (aus der temporären Datei und dann in den Puffer einzulesen), anstatt sie in einen Puffer umzulenken. Es wäre eine leichte Überlastung und ich würde es gerne vermeiden. Dies ist eine Handversion eines größeren Problems und es kann viele Instanzen des Systemaufrufs geben. – bhavs

+1

@bhavs können Sie dies nicht vermeiden, da, wenn Sie die STDERR-Dateinummer korrekt umleiten, alle Aufrufe von 'fprintf (" stderr ") trotzdem in Ihren mem-Puffer gehen, aber wenn Sie stderr neu definieren, passiert nichts . – ikrabbe

+0

@ikrabbe Ja, aber im Kind wird nur der Dateideskriptor beibehalten. 'Fmemopen()' erstellt keinen Dateideskriptor, daher ist jeder Ansatz, der auf 'fmemopen()' angewiesen ist, von Anfang an verloren. – fuz