En C, ¿cómo redirige stdin/stdout/stderr a los archivos al hacer una llamada execvp() o similar?
linux unix (3)
Eche un vistazo a la función freopen
.
Tuve que hacer algo similar con stdout
y escribí dos funciones que hacen el trabajo por mí:
static int fd;
static fpos_t pos;
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);
}
Tengo el siguiente código:
pid_t pid = fork();
if (pid == -1)
{
// ...
}
else if (pid == 0)
{
stdin = someopenfile;
stdout = someotherfile;
stderr = somethirdopenfile;
execvp(args[0], args);
// handle error ...
}
else
{
// ...
}
El problema es que la entrada / salida de la llamada execvp()
sigue siendo la consola, en lugar de los archivos. Claramente estoy haciendo algo mal, ¿cuál es la forma correcta de hacer esto?
La forma correcta de hacerlo es reemplazar los descriptores de archivo STDIN_FILENO
, STDOUT_FILENO
y STDERR_FILENO
con los archivos abiertos usando dup2()
. También debe cerrar los archivos originales en el proceso hijo:
else if (pid == 0)
{
dup2(fileno(someopenfile), STDIN_FILENO);
dup2(fileno(someotherfile), STDOUT_FILENO);
dup2(fileno(somethirdopenfile), STDERR_FILENO);
fclose(someopenfile);
fclose(someotheropenfile);
fclose(somethirdopenfile);
execvp(args[0], args);
// handle error ...
}
Puede usar esto cuando stdin, stdout, stderr son terminales-
//change stdin,stdout,stderr
freopen("new_stdin","r",stdin);
freopen("new_stdout","r",stdout);
freopen("new_stderr","r",stderr);
//----do something;
//reset stdin,stdout,stderr
freopen("/dev/tty","r",stdin);
freopen("/dev/tty","r",stdout);
freopen("/dev/tty","r",stderr);