Функции execlp(), execvp(), execl() и execv() не позволяют программисту явно указывать список переменных среды; вместо этого новая программа наследует их от вызывающего процесса (см. раздел 6.7). В одних случаях это нам подходит, а в других — нет. Из соображений безопасности иногда лучше снабжать программу заранее известным списком переменных среды. Более детально об этом рассказывается в разделе 38.8.

Процедура наследования новой программой среды вызывающего процесса во время вызова execl() продемонстрирована в листинге 27.5. Сначала эта программа использует функцию putenv(), чтобы изменить переменные среды, которые она наследует от командной оболочки в результате вызова fork(). Затем запущенная программа printenv выводит значения переменных среды USER и SHELL. Запустив этот код, мы увидим следующее:

$ echo $USER $SHELL Выводим некоторые из переменных среды командной оболочки

blv /bin/bash

$ ./t_execl

Initial value of USER: blv Копия среды была унаследована от командной оболочки

Britta Эти две строки выводятся запущенной программой printenv

/bin/bash

Листинг 27.5. Передача среды вызывающего процесса новой программе с помощью execl()

procexec/t_execl.c

#include

#include "tlpi_hdr.h"

int

main(int argc, char *argv[])

{

printf("Initial value of USER: %s\n", getenv("USER"));

if (putenv("USER=britta")!= 0)

errExit("putenv");

execl("/usr/bin/printenv", "printenv", "USER", "SHELL", (char *) NULL);

errExit("execl"); /* Если мы добрались сюда, то что-то пошло не так */

}

procexec/t_execl.c

27.2.4. Выполнение файла через ссылку на его дескриптор: fexecve()

С версии 2.3.2 библиотека glibc предоставляет функцию fexecve(), которая похожа на execve(), но позволяет указать исполняемый файл в виде дескриптора fd, а не с помощью пути к файлу. Использование fexecve() подходит для приложений, которые перед выполнением файла хотят его открыть и проверить его контрольную сумму.

#define _GNU_SOURCE

#include

int fexecve(int fd, char *const argv[], char *const envp[]);

Не возвращает значение при успешном завершении; при ошибке возвращает –1

Мы можем открыть и прочитать/проверить содержимое файла без функции fexecve() (используя вызов open()). Однако это сделало бы возможным подмену файла между его открытием и выполнением, потому что удержание дескриптора открытого файла не мешает создать новый файл с тем же именем. Таким образом, проверенное содержимое могло бы отличаться от того, что непосредственно запускается.

27.3. Интерпретируемые скрипты

Интерпретатор — это программа, которая считывает и выполняет текстовые команды (в отличие от компилятора, транслирующего исходный код в машинный, который затем может быть выполнен процессором или виртуальной машиной). В качестве примеров интерпретатора можно привести различные командные оболочки UNIX, а также такие программы, как awk, sed, perl, python и ruby. Обычно интерпретаторы позволяют считывать и выполнять команды не только в интерактивном режиме, но и путем загрузки их из текстового файла, который называют скриптом (или сценарием).

Ядра в системах UNIX позволяют запускать интерпретируемые скрипты тем же способом, что и скомпилированные программы. Для этого должно выполняться два условия: во-первых, файл скрипта должен быть исполняемым и, во-вторых, в начале файла должна находиться строка, в которой указан путь к подходящему интерпретатору. Эта строка имеет следующий вид.

#! путь-к-интерпретатору [опциональные-аргументы]

Символы #! («шебанг») должны находиться в начале строки; при желании между ними и путем к интерпретатору можно указать пробел. Переменная окружения PATH не используется при анализе этого пути, поэтому обычно путь должен быть абсолютным. Относительные пути тоже допускаются, хотя их принято избегать; они вычисляются относительно текущего каталога процесса, который запускает интерпретатор. Путь к интерпретатору отделяется от опциональных аргументов (назначение которых мы объясним чуть ниже) с помощью пробельного символа. Сами аргументы не должны содержать пробельных символов.

Скрипты командной строки в UNIX (или просто shell-скрипты) обычно начинаются со следующей строчки, в которой указана командная оболочка для их выполнения:

#!/bin/sh

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

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