web-dev-qa-db-fra.com

En C, comment rediriger stdin/stdout/stderr vers des fichiers lors d’un appel execvp () ou similaire?

J'ai le code suivant:

pid_t pid = fork();
if (pid == -1)
{
    // ...
}
else if (pid == 0)
{
    stdin = someopenfile;
    stdout = someotherfile;
    stderr = somethirdopenfile;
    execvp(args[0], args);
    // handle error ...
}
else
{
    // ...
}

Le problème est que l'entrée/sortie de l'appel execvp() est toujours la console, plutôt que les fichiers. Clairement, je fais quelque chose de mal, quelle est la bonne façon de faire cela?

20
Matt

La bonne façon de procéder consiste à remplacer les descripteurs de fichier STDIN_FILENO, STDOUT_FILENO et STDERR_FILENO par les fichiers ouverts à l'aide de dup2(). Vous devez également fermer les fichiers d'origine dans le processus enfant:

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 ...
}
42
caf

Jetez un coup d’œil à freopen function.

J'ai dû faire quelque chose de similaire avec stdout et écrit deux fonctions qui font le travail pour moi:

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);
}
7
Jack

Vous pouvez l’utiliser lorsque stdin, stdout, stderr sont 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);
0
alhelal