system - выполняет команду оболочки (shell)
system(3)
выполняет команду оболочки (shell)
ОБЗОР
#include <stdlib.h>
int system(const char *command);
ОПИСАНИЕ
В библиотечной функции
system() используется
fork(2) для создания
процесса-потомка, в котором посредством
execl(3) запускается команда
оболочки, указанная в
command:
execl("/bin/sh", "sh", "-c", command, (char *) 0);
Функция system() возвращает результат после завершения работы команды.
На время выполнения команды SIGCHLD блокируется, а SIGINT и SIGQUIT
игнорируются в процессе, который вызвал system() (эти сигналы будут
обработаны их действиями по умолчанию внутри процесса-потомка, который
выполняет command).
Если значение command равно NULL, то system() возвращает состояние,
показывающее доступна ли оболочка в системе.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Возвращаемым значением
system() может быть одно из:
Если значение command равно NULL, то возвращается ненулевое значение,
если оболочка присутствует в системе, или 0, если оболочка недоступна.
Если процесс-потомок не может быть создан или его состояние невозможно
вернуть, то возвращается значение -1.
Если оболочка не может выполниться в процессе-потомке, то возвращается
значение будет таким же как если бы оболочка-потомок завершилась вызовом
_exit(2) с состоянием 127.
Если все системные вызовы выполнены без ошибок, то возвращается значение
состояния завершения процесса-потомка, использовавшегося для выполнения
command (состояние завершения оболочки — это состояние завершения
последней выполнявшейся команды).
В последних двух случаях возвращаемое значение — это «состояние ожидания»,
которое можно определить с помощью макроса описанного в waitpid(2)
(т. е., WIFEXITED(), WEXITSTATUS() и т. п.).
Функция system() не отражает состояние ожидание других потомков.
АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).
Интерфейс Атрибут Значение
system()
безвредность в потоках: безвредно (MT-Safe)
СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008, C89, C99.
ЗАМЕЧАНИЯ
Функция system() проста и удобна: она позаботится обо всём для вызовов
fork(2), execl(3) и waitpid(2), а также необходимых действиях с
сигналами; также оболочка выполнит обычные подстановки и перенаправления
ввода-вывода command. Но system() не эффективна: для создания процесса
требуются дополнительные системные вызовы, которые запускают оболочку и
выполняют команду.
Если определён макрос тестирования свойств _XOPEN_SOURCE (до включения
всех заголовочных файлов), то при включении <stdlib.h>
становятся доступны макросы, описанные в waitpid(2) (WEXITSTATUS() и
т. п.).
Как уже упоминалось, функция system() игнорирует SIGINT и
SIGQUIT. Это может привести к тому, что программы вызывающие её из цикла
станут не прерываемыми, пока сами не проверят условия выхода для своих
дочерних процессов. Пример:
while (что-то) {
int ret = system("foo");
if (WIFSIGNALED(ret) &&
(WTERMSIG(ret) == SIGINT || WTERMSIG(ret) == SIGQUIT))
break;
}
Не используйте system() в программах с привилегиями set-user-ID или
set-group-ID, потому что некоторые странные значения переменных окружения
могут нарушить целостность системы. Вместо неё рекомендуется использование
семейства функций exec(3), кроме execlp(3) или
execvp(3). Фактически, функция system() неправильно работает из
программ с привилегиями set-user-ID или set-group-ID в системах, где
/bin/sh — это bash версии 2, так как bash 2 сбрасывает права при запуске
(в Debian используется изменённый bash, который этого не делает, если
оболочка вызывается как sh).
В версиях glibc до 2.1.3 проверка доступности /bin/sh в действительности
не выполнялась, если значение command равно NULL; вместо этого всегда
предполагалось наличие, и в этом случае system() всегда возвращала
1. Начиная с glibc 2.1.3, эта проверка выполняется, так как несмотря на
требование POSIX.1-2001 a conforming implementation to provide a shell,
that shell may not be available or executable if the calling program has
previously called chroot(2) (which is not specified by POSIX.1-2001).
Существует вероятность, что команда оболочки возвратит значение 127, которое
также является и возвращаемым значением самой system(); в этом случае
нельзя понять, что невозможно выполнить оболочку в процессе-потомке.