Вызов функции
popen
должен задавать
"r"
или
"w"
; никакого другого значения стандартной реализацией popen не поддерживается. Это означает, что вы не можете вызвать другую программу и одновременно читать из нее и писать в нее. В случае сбоя
popen
возвращает пустой указатель. Если вы хотите создать двунаправленную связь с помощью каналов, стандартное решение — применить два канала: по одному для потока данных каждого направления.
pclose
Когда процесс, стартовавший с помощью
popen
, закончится, вы можете закрыть файловый поток, связанный с ним, с помощью функции
pclose
. Вызов
pclose
вернет управление, только когда процесс, запущенный с помощью
popen
, завершится. Если он все еще выполняется во время вызова
pclose
, вызов
pclose
будет ждать окончания процесса.
Функция
pclose
обычно возвращает код завершения процесса, чей файловый поток она закрывает. Если вызывающий процесс уже выполнил оператор
wait
перед вызовом
pclose
, статус завершения будет потерян, поскольку вызванный процесс закончен, и функция
pclose
вернет -1 с переменной
errno
, получившей значение
ECHILD
.
Выполните упражнение 13.1.
Упражнение 13.1. Чтение вывода внешней программы
Давайте опробуем простой пример popen1.c с функциями
popen
и
pclose
. Вы будете применять в программе
popen
для доступа к информации из
uname
.
uname
— это команда, выводящая системную информацию, включая тип компьютера, имя ОС, версию и выпуск, а также сетевое имя машины.
Запустив программу, вы откроете канал к
uname
; сделаете его читаемым и зададите
read_fp
, как указатель на вывод. В конце канал, на который указывает
read_fp
, закрывается.
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main() {
FILE *read_fp;
char buffer[BUFSIZ +1];
int chars_read;
memset(buffer, '\0', sizeof(buffer));
read_fp = popen("uname -a", "r");
if (read_fp ! = NULL) {
chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp);
if (chars_read > 0) {
printf("Output was:-\n%s\n", buffer);
}
pclose(read_fp);
exit(EXIT_SUCCESS);
}
exit(EXIT_FAILURE);
}
Когда вы выполните программу, то должны получить вывод, похожий на следующий (полученный на одной из машин авторов):
$ ./popen1
Output was:-
Linux suse103 2.6.20.2-2-default #1 SMP Fri Mar 9 21:54:10 UTC 2001 i686 i686 i386 GNU/Linux
Как это работает
Программа применяет функцию
popen
для вызова команды
uname
с параметром
-а
. Затем она использует возвращенный файловый поток для чтения данных, до
BUFSIZ
символов (как задано в директиве
#define
из файла stdio.h), и затем выводит их на экран. Поскольку вы перехватываете вывод команды uname внутри программы, его можно обрабатывать.
Отправка вывода в popen
Теперь, когда вы рассмотрели пример захвата вывода из внешней программы, давайте познакомимся с отправкой вывода во внешнюю программу. В упражнении 13.2 показана программа popen2.c, передающая по каналу данные другой программе. В этом примере будет использована команда od (от англ. octal dump — восьмеричный дамп).
Упражнение 13.2. Пересылка вывода в другую программу
Взглянув на следующий программный код, вы увидите, что он очень похож на предыдущий пример, за исключением того, что вы пишете данные в канал вместо чтения данных из него. Далее приведена программа popen2.c.
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main() {
FILE *write_fp;
char buffer[BUFSIZ + 1];
sprintf(buffer, "Once upon a time, there was...\n");
write_fp = popen("od -c", "w");
if (write_fp != NULL) {
fwrite(buffer, sizeof(char), strlen(buffer), write_fp);
pclose(write_fp);
exit(EXIT_SUCCESS);
}
exit(EXIT_FAILURE);
}
После выполнения этой программы вы должны получить следующий вывод:
$ <b>./popen2</b>
0000000 O n c e u p o n a t i m e
0000020 , t h e r e w a s . . . \n
0000037
Как это работает
Программа применяет
popen
с параметром "w" для запуска команды
od -с
таким образом, что может отправить данные этой команде. Затем она отправляет строку, которую команда
od -с
получает и обрабатывает; далее команда
od -с
выводит результат обработки в своем стандартном выводе.