C направляет стандартный вывод в файл, а затем сбрасывает

Я хотел бы изменить дескриптор файла, чтобы мои команды execvp отправлялись в файл. После этого я хотел бы сбросить stdout обратно в консоль.

Это то, что у меня есть до сих пор:

int main() {
    printf("to console\n");
    int stdoutfd = dup(STDOUT_FILENO);
    FILE* file = fopen("./test.txt","ab+");
    int filefd = fileno(file);
    dup2(filefd,STDOUT_FILENO);
    char *args[] = {"ls","-la",NULL};
    execvp(args[0],args);
    dup2(stdoutfd,STDOUT_FILENO);
    close(stdoutfd);
    printf("to console\n");
}

Первый printf печатает в консоль, затем execvp по командам «ls -la» печатается в файл test.txt, но моя проблема в том, что второй printf нигде не печатает.

Я понимаю, что на аналогичный вопрос был дан ответ в C восстановить стандартный вывод на терминал, но это решение не работает.


person dinamix    schedule 30.09.2016    source источник
comment
execvp не возвращается в случае успеха. execvp заменяет текущий образ процесса новым образом процесса. То есть, если нет ошибки с вызовом execvp, ни один код после execvp никогда не будет выполняться. Вы, вероятно, захотите сначала fork перед вызовом execvp.   -  person kaylum    schedule 30.09.2016
comment
Вы выяснили, почему этот другой ответ не работает? Он дает твердые советы (и мой ответ не является общепринятым). Это будет работать, если ваша программа в порядке — в примере в вопросе нет fork(), поэтому после успешного execvp() ничего не выполняется. Последние три строки никогда не выполняются, если работает execvp(). Вы можете изменить строку "ls" на "not-the-ls" (конечно, при условии, что у вас нет команды с именем not-the-ls) и перезапустить; тогда вы увидите сообщение to console.   -  person Jonathan Leffler    schedule 30.09.2016
comment
Правильный; единственный раз, когда любая из функций семейства exec*() возвращает значение, это когда она не смогла выполнить то, что ее попросили выполнить.   -  person Jonathan Leffler    schedule 30.09.2016


Ответы (2)


После нет. Вызов функции execvp заменяет ваш процесс. Если это удается, остальная часть вашего кода не выполняется.

person David Schwartz    schedule 30.09.2016

относительно переназначения stdout для перехода в другое место

Это от: http://stackoverflow.com/questions/584868/rerouting-stdin-and-stdout-from-c

Зачем использовать freopen()? В спецификации C89 есть ответ в одном из примечаний к разделу:

116. The primary use of the freopen function is to change the file associated with a standard text stream (stderr, stdin, or stdout), as those identifiers need not be modifiable lvalues to which the value returned by the fopen function may be assigned.

freopen обычно используется не по назначению, т.е. stdin = freopen("newin", "r", stdin);. Это не более переносимо, чем fclose(stdin); stdin = fopen("newin", "r");. Оба выражения пытаются присвоить значение стандартному вводу, который не гарантируется присваиваемостью.

Правильный способ использования freopen — опустить присваивание: freopen("newin", "r", stdin);

person user3629249    schedule 02.10.2016