ИМЯ¶
execve - выполнить
программу
ОБЗОР¶
#include <unistd.h>
int execve(const char *filename, char *const argv
[], char *const envp[]);
ОПИСАНИЕ¶
execve() выполняет
программу,
заданную
параметром
filename.
Программа
должна быть
или двоичным
исполняемым
файлом, или
скриптом,
начинающимся
со строки
вида "
#!
интерпретатор
[аргументы]".
В последнем
случае
интерпретатор
-- это
правильный
путь к
исполняемому
файлу,
который не
является
скриптом;
этот файл
будет
выполнен как
интерпретатор
[arg]
filename.
argv -- это массив
строк,
аргументов
новой
программы.
envp
-- это массив
строк в
формате
key=value,
которые
передаются
новой
программе в
качестве
окружения (environment).
Как
argv, так и
envp
завершаются
нулевым
указателем.
К массиву
аргументов и
к окружению
можно
обратиться
из функции
main(), которая
объявлена
как
int main(int argc, char *argv[], char *envp[]).
execve() не
возвращает
управление
при успешном
выполнении,
а код, данные, bss
и стек
вызвавшего
процесса
перезаписываются
кодом,
данными и
стеком
загруженной
программы.
Новая
программа
также
наследует от
вызвавшего
процесса его
идентификатор
и открытые
файловые
дескрипторы,
на которых
не было
флага
закрыть-при-exec
(close-on-exec, COE). Сигналы,
ожидающие
обработки,
удаляются.
Переопределённые
обработчики
сигналов
возвращаются
в значение
по
умолчанию.
Обработчик
сигнала SIGCHLD
(когда
установлен в
SIG_IGN) может быть
сброшен или
не сброшен в
SIG_DFL.
Если текущая
программа
выполнялась
под
управлением
ptrace, то после
успешного
execve() ей
посылается
сигнал
SIGTRAP.
Если на файле
программы
filename
установлен
setuid-бит, то
фактический
идентификатор
пользователя
вызывавшего
процесса
меняется на
идентификатор
владельца
файла
программы.
Точно так же,
если на
файле
программы
установлен
setgid-бит, то
фактический
идентификатор
группы
устанавливается
в группу
файла
программы.
Если
исполняемый
файл
является
динамически-скомпонованным
файлом в
формате a.out,
содержащим
заглушки для
вызова
разделяемых
библиотек,
то в начале
выполнения
этого файла
вызывается
динамический
компоновщик
ld.so(8), который
загружает
библиотеки и
компонует их
с
исполняемым
файлом.
Если
исполняемый
файл
является
динамически-скомпонованным
файлом в
формате ELF, то
для загрузки
разделяемых
библиотек
используется
интерпретатор,
указанные в
сегменте PT_INTERP.
Обычно это
/lib/ld-linux.so.1 для
программ,
скомпилированных
под Linux libc версии 5,
или же
/lib/ld-linux.so.2
для
программ,
скомпилированных
под GNU libc версии 2.
ВОЗВРАЩАЕМОЕ
ЗНАЧЕНИЕ¶
При успешном
завершении
execve() не
возвращает
управление,
при ошибке
возвращается
-1, а значение
errno
устанавливается
должным
образом.
КОДЫ
ОШИБОК¶
- EACCES
- Интерпретатор
файла или
скрипта не
является
обычным
файлом.
- EACCES
- Нет прав
на
выполнение
файла,
скрипта или
ELF-интерпретатора.
- EACCES
- Файловая
система
смонтирована
с флагом noexec.
- EPERM
- Файловая
система
смонтирована
с флагом nosuid,
пользователь
не является
суперпользователем,
а на файле
установлен
бит setuid или setgid.
- EPERM
- Процесс
работает
под
отладчиком,
пользователь
не является
суперпользователем,
а на файле
установлен
бит setuid или setgid.
- E2BIG
- Список
аргументов
слишком
велик.
- ENOEXEC
- Исполняемый
файл в
неизвестном
формате, для
другой
архитектуры,
или же
встречены
какие-то
ошибки,
препятствующие
его
выполнению.
- EFAULT
- filename
указывает
за пределы
доступного
адресного
пространства.
- ENAMETOOLONG
- filename
слишком
длинное.
- ENOENT
- Файл filename,
или
интерпретатор
скрипта или
ELF-файла не
существует,
или же не
найдена
разделяемая
библиотека,
требуемая
файлу или
интерпретатору.
- ENOMEM
- Недостаточно
памяти в
ядре.
- ENOTDIR
- Компонент
пути filename, или
интерпретатору
скрипта или
ELF-интерпретатору
не является
каталогом.
- EACCES
- Нет прав
на поиск в
одном из
каталогов
по пути к filename,
или имени
интерпретатора
скрипта или
ELF-интерпретатора.
- ELOOP
- Слишком
много
символьных
ссылок
встречено
при поиске
filename, или
интерпретатора
скрипта или
ELF-интерпретатора.
- ETXTBSY
- Исполняемый
файл открыт
для записи
одним или
более
процессами.
- EIO
- Произошла
ошибка
ввода-вывода.
- ENFILE
- Достигнут
системный
лимит на
общее
количество
открытых
файлов.
- EMFILE
- Процесс
уже открыл
максимально
доступное
количество
открытых
файлов.
- EINVAL
- Исполняемый
файл в
формате ELF
содержит
более
одного
сегмента PT_INTERP
(то есть, в
нем указано
более
одного
интерпретатора).
- EISDIR
- ELF-интерпретатор
является
каталогом.
- ELIBBAD
- ELF-интерпретатор
имеет
неизвестный
формат.
СООТВЕТСТВИЕ
СТАНДАРТАМ¶
SVr4, SVID, X/OPEN, BSD 4.3. POSIX не
документирует
поведение,
связанное с #!,
но в
остальном
совершенно
совместимо. SVr4
документирует
дополнительные
коды ошибок
EAGAIN, EINTR, ELIBACC, ENOLINK, EMULTIHOP; POSIX не
документирует
коды ошибок
ETXTBSY, EPERM, EFAULT, ELOOP, EIO, ENFILE, EMFILE, EINVAL, EISDIR и
ELIBBAD.
ЗАМЕЧАНИЯ¶
SUID и SGID процессы
не могут
быть
оттрассированы
ptrace()d.
Linux игнорирует
SUID и SGID биты на
скриптах.
Результат
монтирования
файловой
системы с
опцией
nosuid
различается
в
зависимости
от версий
ядра Linux:
некоторые
ядра будут
отвергать
выполнение
SUID/SGID программ,
когда это
должно дать
пользователю
те
возможности,
которыми он
уже не
обладается
(и
возвращать EPERM),
некоторые
ядра будут
просто
игнорировать
SUID/SGID биты, но
успешно
производить
запуск
программы.
Первая
строка
(строка с #!)
исполняемого
скрипта не
может быть
длиннее 127
символов.
СМОТРИ
ТАКЖЕ¶
chmod(2),
fork(2),
execl(3),
environ(5),
ld.so(8)
ПЕРЕВОД¶
Дополнения к
первоначальному
переводу:
Виктор
Вислобоков
<corochoone@perm.ru> 2003