
6.2.3. Каналы - легкий путь!
Если все изложенные выше изыскания кажутся слишком размытым способом создания и использования каналов, то вот альтернатива этому.
LIBRARY FUNCTION: popen();
PROTOTYPE: FILE *popen ( char *command, char *type );
RETURNS: новый файловый поток в случае успеха
NULL при неудачном fork() или pipe()
NOTES: создает канал, и выполняет fork/exec, используя command
Эта стандартная библиотечная функция создает полудуплексный канал посредством вызывания pipe() внутренне. Затем она порождает дочерний процесс, запускает Bourne shell и исполняет аргумент command внутри shell-а. Управление потоком данных определяется вторым аргументом, type. Он может быть "r" или "w" - для чтения или записи, но не может быть и то, и другое! Под Linux-ом канал будет открыт в виде, определенном первой литерой аргумента "type". Поэтому, если вы попытаетесь ввести "rw", канал будет открыт только в виде "read".
Каналы, созданные popen(), должны быть закрыты pclose(). К этому моменту вы, вероятно, уже использовали [реализовали] popen/pclose share, удивительно похожий на стандартный файловый поток I/O функций fopen() и fclose().LIBRARY FUNCTION: pclose();
PROTOTYPE: int pclose( FILE *stream )
RETURNS: выход из статуса системного вызова wait4()
-1, если "stream" некорректен или облом с wait4()
NOTES: ожидает окончания связанного каналом процесса, затем закрывает поток.
Функция pclose() выполняет wait4() над процессом, порожденным popen()-ом. Когда она возвращается, то уничтожает канал и файловый поток. Повторим еще раз, что этот эффект аналогичен эффекту, вызываемому функцией fclose() для нормального, основанного на потоке файлового ввода/вывода.
Рассмотрим пример, который открывает канал для команды сортировки и начинает сортировать массив строк:
(C)opyright 1994-1995, Scott Burket
#include
#define MAXSTRS 5
int main(void)
{
int cntr;
FILE *pipe_fp;
char *strings[MAXSTRS] = {"echo", "bravo", "alpha", "charlie", "delta"};
/* Создаем односторонний канал вызовом popen() */
if (( pipe_fp = popen("sort", "w")) == NULL)
{
perror("popen");
exit(1);
}
/* Цикл */
for(cntr=0;
cntr /tmp/foo", "w") popen("sort | uniq | more", "w");
В качестве другого примера popen()-а, рассмотрим маленькую программу, открывающую два канала (один - для команды ls, другой - для сортировки):
(C)opyright 1994-1995, Scott Burkett
#include
int main(void)
{
FILE *pipein_fp, *pipeout_fp;
char readbuf[80];
/* Создаем односторонний канал вызовом popen() */
if (( pipein_fp = popen("ls", "r")) == NULL)
{
perror("popen");
exit(1);
}
/* Создаем односторонний канал вызовом popen() */
if (( pipeout_fp = popen("sort", "w")) == NULL)
{
perror("popen");
exit(1);
}
/* Цикл */
while(fgets(readbuf, 80, pipein_fp)) fputs(readbuf, pipeout_fp);
/* Закрываем каналы */
pclose(pipein_fp);
pclose(pipeout_fp);
return(0);
}
В качестве последней демонстрации popen(), давайте создадим программу, характерную для открытия канала между отданной командой и именем файла:
(C)opyright 1994-1995, Scott Burkett
#include
int main(int argc, char *argv[])
{
FILE *pipe_fp, *infile;
char readbuf[80];
if( argc != 3 )
{
fpintf(stderr, "USAGE"