Читаем Linux API. Исчерпывающее руководство полностью

• Между выполнением функций popen() и pclose() вызывающий процесс может создать других потомков, поэтому стандарт SUSv3 требует, чтобы вызов popen() не блокировал сигнал SIGCHLD. То есть процесс, который вызывает wait() перед функцией pclose(), может получить статус потомка, созданного с помощью popen(). В таком случае последующий вызов pclose() возвратит -1 и присвоит errno ошибку ECHILD, сигнализируя о невозможности извлечения статуса потомка.

Пример программы

В листинге 44.5 показан пример использования функций popen() и pclose(). Программа многократно считывает шаблон имени файла и задействует popen(), чтобы получить результат передачи этого шаблона команде ls (до появления библиотечной функции glob() похожий подход использовался в старых версиях UNIX для генерирования имен файлов).

Листинг 44.5. Поиск файлов по шаблону с помощью функции popen()

pipes/popen_glob.c

#include

#include

#include "print_wait_status.h" /* Для printWaitStatus() */

#include "tlpi_hdr.h"

#define POPEN_FMT "/bin/ls — d %s 2> /dev/null"

#define PAT_SIZE 50

#define PCMD_BUF_SIZE (sizeof(POPEN_FMT) + PAT_SIZE)

int

main(int argc, char *argv[])

{

char pat[PAT_SIZE]; /* Поиск по шаблону */

char popenCmd[PCMD_BUF_SIZE];

FILE *fp; /* Файловый поток, возвращенный вызовом popen() */

Boolean badPattern; /* Некорректные символы в 'pat'? */

int len, status, fileCnt, j;

char pathname[PATH_MAX];

for (;;) { /* Считываем шаблон, выводим результаты поиска */

printf("pattern: ");

fflush(stdout);

 if (fgets(pat, PAT_SIZE, stdin) == NULL)

break; /* Конец файла */

len = strlen(pat);

if (len <= 1) /* Пустая строка */

continue;

if (pat[len — 1] == '\n') /* Убираем завершающий символ новой строки */

pat[len — 1] = '\0';

/* Следим за тем, чтобы шаблон содержал только допустимые символы, то есть

буквы, цифры, подчеркивания, точки и символы поиска по шаблону,

поддерживаемые командной оболочкой (мы используем более строгое

определение допустимого, чем командная оболочка, которая позволяет

добавлять любые символы, если они находятся внутри кавычек). */

 for (j = 0, badPattern = FALSE; j < len &&!badPattern; j++)

if (!isalnum((unsigned char) pat[j]) &&

strchr("_*?[^-].", pat[j]) == NULL)

badPattern = TRUE;

if (badPattern) {

printf("Bad pattern character: %c\n", pat[j — 1]);

continue;

}

/* Создаем и выполняем команду glob 'pat' */

 snprintf(popenCmd, PCMD_BUF_SIZE, POPEN_FMT, pat);

popenCmd[PCMD_BUF_SIZE — 1] = '\0'; /* Добавляем в конце строки

нулевой символ */

 fp = popen(popenCmd, "r");

if (fp == NULL) {

printf("popen() failed\n");

continue;

}

/* Перебираем итоговый список путей, пока не доходим до конца файла */

fileCnt = 0;

while (fgets(pathname, PATH_MAX, fp)!= NULL) {

printf("%s", pathname);

fileCnt++;

}

/* Закрываем канал, извлекаем и выводим код завершения */

status = pclose(fp);

printf(" %d matching file%s\n", fileCnt,

(fileCnt!= 1)? "s": "");

printf(" pclose() status = %#x\n", (unsigned int) status);

if (status!= -1)

printWaitStatus("\t", status);

}

exit(EXIT_SUCCESS);

}

pipes/popen_glob.c

Использование программы из листинга 44.5 показано на примере следующей сессии командной строки. Здесь мы указываем два шаблона: первому соответствуют два файла, а для второго не находится ни одного совпадения:

$ ./popen_glob

pattern: popen_glob* Соответствует двум файлам

popen_glob

popen_glob.c

2 matching files

pclose() status = 0

child exited, status=0

pattern: x* Не соответствует ни одному файлу

0 matching files

pclose() status = 0x100 ls(1) завершается со статусом 1

child exited, status=1

pattern: ^DНажмите Ctrl+D, чтобы выйти

Построение команды поиска по шаблону в листинге 44.5 требует некоторого объяснения. Сам поиск выполняется командной оболочкой. Команда ls используется всего лишь для построчного вывода совпавших файлов. Вместо этого можно было бы воспользоваться командой echo, но это повлекло бы нежелательные результаты: если не обнаружено ни одного совпадения, то командная оболочка оставляет шаблон без изменений и просто выводит его с помощью команды echo. Команда ls в данной ситуации, прежде чем завершиться со статусом 1, возвращает в вывод stderr (который мы перенаправили в /dev/null) сообщение об ошибке, а стандартный вывод оставляет пустым.

Стоит также обратить внимание на проверку ввода, производимую в листинге 44.5 . Она делается для того, чтобы не дать popen() выполнить произвольную консольную команду в случае некорректного ввода. Представьте, что эта проверка не проводится и пользователь ввел такую строку:

pattern: ; rm *

В этом случае программа передала бы в функцию popen() следующую команду, что привело бы к катастрофическим результатам:

/bin/ls — d; rm * 2> /dev/null

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных