Функции 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
/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
Не возвращает значение при успешном завершении; при ошибке возвращает –1
Мы можем открыть и прочитать/проверить содержимое файла без функции fexecve() (используя вызов open()). Однако это сделало бы возможным подмену файла между его открытием и выполнением, потому что удержание дескриптора открытого файла не мешает создать новый файл с тем же именем. Таким образом, проверенное содержимое могло бы отличаться от того, что непосредственно запускается.
Ядра в системах UNIX позволяют запускать интерпретируемые скрипты тем же способом, что и скомпилированные программы. Для этого должно выполняться два условия: во-первых, файл скрипта должен быть исполняемым и, во-вторых, в начале файла должна находиться строка, в которой указан путь к подходящему интерпретатору. Эта строка имеет следующий вид.
#!
Символы #! («шебанг») должны находиться в начале строки; при желании между ними и путем к интерпретатору можно указать пробел. Переменная окружения PATH
Скрипты командной строки в UNIX (или просто shell-скрипты) обычно начинаются со следующей строчки, в которой указана командная оболочка для их выполнения:
#!/bin/sh