Стандартная ошибка и popen (): как это сделать? - PullRequest
0 голосов
/ 14 октября 2010

Я хочу открыть процесс из кода C и быть в состоянии прочитать его стандартный вывод и стандартную ошибку, в то же время имея возможность записи на его стандартный ввод.popen(), но это не позволяет читать стандартный поток ошибок.Вы можете добавить «2>&1» к команде, но это не позволит различить стандартный вывод и данные об ошибках.Для моего приложения требуется возможность разделить оба потока.

В Python есть popen3, а в Ruby Open3, чтобы делать подобные вещи, но я не могу найти способ сделать этоC. Любая помощь?

Ответы [ 3 ]

4 голосов
/ 14 октября 2010
#include <unistd.h>
#include <stdio.h>

...


int pipe_err[2], pipe_out[2], pipe_in[2];

if (pipe(pipe_err) || pipe(pipe_out) || pipe(pipe_in)) { // abbreviated error detection
     perror("pipe");
     scream_and_run_around_frantically();
     exit(BAD);
}
pid_t pid = fork();
if (!pid) { // in child
    dup2(pipe_err[1], 2);
    dup2(pipe_out[1], 1);
    dup2(pipe_in[0], 0);
    close(pipe_err[0]);
    close(pipe_err[1]);
    close(pipe_out[0]);
    close(pipe_out[1]);
    close(pipe_in[0]);
    close(pipe_in[1]);

    // close any other files that you don't want the new program
    // to get access to here unless you know that they have the
    // O_CLOEXE bit set

    execl(program_path, program_name, arg1, arg2, arg3);
    /* only gets here if there is an error executing the program */
 } else { // in the parent
     if (pid < 0) {
           perror("fork");
           error_death_plague_stubbed_toe();
           exit(BAD);
     }
     child_err = pipe_err[0];
     close(pipe_err[1]);
     child_out = pipe_out[0];
     close(pipe_out[1]);
     child_in = pipe_in[1];
     close(pipe_in[0]);

     ...

Возможно, вы захотите взглянуть на

man 3 exec

. Здесь есть множество функций, которые превращают текущую программу в новую.Все они имеют разные интерфейсы, но используют execve под капотом.

man 2 execve

Также:

man 2 fork

и

man 2 pipe
2 голосов
/ 14 октября 2010

Вы можете рассмотреть возможность использования execl().Это то, что используется внутри popen().

1 голос
/ 14 октября 2010

Если вы разветвляете дочерний процесс, вы можете продублировать дескриптор stderr и использовать его в дочернем процессе.

...