execve - функция, осуществляющая выполнение программы
НАЗВАНИЕexecve - функция, осуществляющая выполнение программы
СИНТАКСИС
#include
int execve(const char *filename, char *const argv [], char
*const envp[]);
ОПИСАНИЕ
Функция execve() отвечает за выполнение программы,
заданной параметром filename. Программа должна быть либо
двоичным исполняемым файлом, либо скриптом, который
начинается со строки вида "#! интерпретатор [аргументы]".
В последнем случае интерпретатор - это правильный путь к
исполняемому файлу, который не является скриптом; он будет
вызван как интерпретатор [arg] filename. argv - массив
аргументов (строк), передаваемый запускаемой программе.
envp - массив строк в формате параметр=значение,
передаваемый в качестве окружения запускаемой программе.
Оба параметра: argv и envp,- должны завершаться нулевым
указателем. К массиву аргументов и к окружению можно
обратиться из вызываемой программы с помощью функции main,
когда она определена как int main (int argc, char *argv[],
char *envp[]). Значение execve() не возвращается при
успешном выполнении программы, а код, данные,
инициализированные данные и стек вызвавшего процесса
записываются как код, данные и стек загруженной программы.
Новая программа наследует от вызвавшего процесса его
идентификатор и открытые файловые описатели, на которых не
было флага "close-on-exec". Сигналы, ожидающие обработки,
удаляются. Новое значение обработчиков сигналов становится
их значением по умолчанию. Сигнал SIGCHLD, в зависимости
от установки его в SIG_IGN, может быть сброшен в SIG_DFL.
Если текущая программа выполнялась под управлением ptrace,
то после успешного выполнения execve() ей посылается
сигнал SIGTRAP. Если в файле программы filename
установлен set-uid бит, то идентификатор эффективного
пользователя вызывающего процесса меняется на
идентификатор владельца файла программы. Точно так же,
если на файле программы установлен set-gid бит, то
идентификатор эффективной группы устанавливается в группе
файла программы. Если исполняемый файл является
динамически скомпонованным файлом в формате 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,
пользователь не является суперпользователем, а в
файле установлен бит SUID или SGID);
EPERM (процесс отлаживается, пользователь не является
суперпользователем, а в файле установлен бит SUID
или SGID);
E2BIG (слишком длинный список аргументов);
ENOEXEC
(формат исполняемого файла неизвестен, файл
предназначен для другой архитектуры или содержит
какие-то ошибки, препятствующие его выполнению);
EFAULT (Файл filename указывает на файл за пределами
доступного адресного пространства);
ENAMETOOLONG
(Файл filename является слишком длинным);
ENOENT (1. Файла filename, скрипта или ELF-интерпретатора
не существует. 2. Библиотека, которая используется
файлом, или интерпретатор не найдены.);
ENOMEM (недостаточно памяти в системе);
ENOTDIR
(компонент имени filename, скрипта или
ELF-интерпретатора не является каталогом);
EACCES (нет прав на поиск одного из каталогов, являющегося
компонентом filename, имени скрипта или
ELF-интерпретатора);
ELOOP (слишком много символьных ссылок составляют file-
name, имя скрипта или 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().
Linux игнорирует биты SUID и SGID в скриптах.
Результат подключения файловой системы nosuid будет
отличаться в разных версиях ядер Linux: некоторые будут
отменять выполнение SUID/SGID исполняемых, если это даст
пользователю возможности, недопустимых для него (возвращая
EPERM), некоторые будут просто игнорировать биты SUID/SGID
и нормально выполняться.
Первая строка (строка с #!) исполняемого скрипта не может
быть длиннее 127-и символов.