Читаем UNIX полностью

Упражнение 7.15

Напишите программу random.

$ random filename

должна выдавать одну строку, произвольно выбранную из файла. Если есть файл people, содержащий имена, random можно использовать в программе scapegoat ("козел отпущения"), полезной при случайном определении виновных:

$ cat scapegoat

echo "В этом виноват `random people`!"

$ scapegoat

В этом виноват Кен!

$

Убедитесь в том, что random хороша независимо от распределения длины строк.

Упражнение 7.16

Помимо прочего в индексном дескрипторе указаны адреса размещения блоков файла на диске. Рассмотрите файл , а затем напишите программу icat, которая должна читать файлы, описываемые номером записи каталога и устройством диска. (Она, конечно, будет работать только в том случае, если требуемый диск открыт на чтение.) При каких обстоятельствах icat полезна?

<p>7.4 Процессы</p>

В этом разделе мы покажем вам, как выполнить одну программу, вызвав ее из другой. Самый легкий путь — привлечь стандартную библиотечную программу system, упомянутую, но забракованную в гл. 6. Программа system использует один аргумент — командную строку в том виде, в каком она вводится с терминала (за исключением символа перевода строки), и выполняет ее порожденным shell. Если командная строка должна быть создана из кусочков, можно прибегнуть к форматированию памяти программой sprintf. В конце раздела мы рассмотрим более безопасную версию system для работы с диалоговыми программами, но прежде чем изучать программу в целом, обсудим структуры, из которых она составляется.

Создание процесса низкого уровня: execlp и execvp

Самая важная операция - выполнение другой программы без возврата с помощью системного вызова execlp. Например, чтобы напечатать дату и выполнить тем самым последнее действие запущенной программы, используют

execlp("date", "date", (char*)0);

Первый аргумент execlp есть имя файла команды; execlp выбирает путь поиска (т.е. $PATH) из вашего окружения и выполняет такой же поиск, как shell. Второй и последующие аргументы — это имена и аргументы команд; для новой программы они становятся массивом argv. Конец списка отмечен аргументом 0. (См. справочное руководство по exec(2), и вы поймете конструкцию execlp.)

Вызов execlp перекрывает существующую программу новой, запускает ее и затем завершается. Первоначальная программа получает управление обратно только при возникновении ошибки, например, когда файл не удается найти или он является невыполнимым:

execlp("date", "date", (char*)0);

fprintf(stderr, "Не удалось выполнить 'date'\n");

exit(1);

Если число аргументов вам заранее не известно, полезно применить execvp (вариант execlp). Вызов выглядит так:

execvp(filename, argp);

где argp означает массив указателей к аргументам (таким, как argv). Последним в массиве должен быть указатель NULL, так что execvp может отметить конец списка. Как и для execlp, filename — это файл, в котором находится программа, argp — массив argv для новой программы, a argp[0] — имя программы.

Ни одна из перечисленных выше программ не обеспечивает расширения в списке аргументов метасимволов типа <, >, *, кавычки и т.п. Если они вам нужны, воспользуйтесь execlp и вызовите /bin/sh из shell, которая выполнит эту работу. Сконструируйте строку commandline, содержащую полную команду, как если бы она была напечатана на терминале, например:

execlp("/bin/sh/", "sh", "-с", commandline, (char*)0);

Аргумент предписывает трактовать следующий аргумент как целую командную строку.

В качестве иллюстрации exec рассмотрим программу waitfile. Команда

$ waitfile filename [command]

периодически проверяет поименованный файл. Если он не менялся после последней проверки, выполняется command. В том случае, когда команда не указана, файл копируется в стандартный выходной поток. С помощью waitfile мы контролируем работу troff, как в

$ waitfile troff .out echo troff done &

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

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