• Если в аргументе command передали нулевой указатель, system() возвращает ненулевое значение (если доступна командная оболочка) или 0 (если доступа к оболочке нет). Этот случай является следствием того факта, что стандарты языка С не привязаны ни к какой конкретной операционной системе, поэтому system() может запускаться в среде, несовместимой с UNIX, в которой отсутствует командная строка. Более того, командная оболочка может оказаться недоступной даже в UNIX-системе, если перед выполнением system() программа вызвала chroot(). Если в аргументе command не нулевой указатель, вывод функции system() обусловливается оставшимися пунктами данного списка.

• Если дочерний процесс не может быть создан или его код завершения нельзя получить, system() возвращает –1.

• Если командная оболочка не может быть запущена в дочернем процессе, system() возвращает значение, которое мы бы получили при завершении дочерней командной оболочки, вызывав _exit(127).

• Если все системные вызовы выполнились успешно, system() возвращает код завершения дочерней командной оболочки, с помощью которого запускалась внешняя команда. (Код завершения командной оболочки совпадает с кодом заверешния последней выполненной команды. Если эта команда была завершена с помощью сигнала, то большинство оболочек завершаются с кодом, равным 128+n, где n — номер сигнала. Код завершения потомка, завершенного с помощью сигнала, рассматривается в разделе 26.1.3).

Имея лишь значение, возвращенное system(), невозможно точно сказать, когда ей не удается запустить командную оболочку, а когда командная оболочка просто завершается со статусом 127 (последний вариант возможен, если оболочка не может найти и запустить программу с заданным именем).

В последних двух случаях значение, возвращаемое функцией system(), является статусом ожидания того же формата, который возвращается вызовом waitpid(). Это означает, что для анализа данного значения следует использовать функции, описанные в подразделе 26.1.3; кроме того, мы можем вывести его с помощью нашей функции printWaitStatus() (см. листинг 26.2).

Пример программы

Использование функции system() демонстрируется в листинге 27.7. Эта программа запускает цикл, который считывает строку с командой, выполняет ее с помощью system(), и затем анализирует и выводит полученный результат. Пример ее выполнения показан ниже:

$ ./t_system

Command: whoami

mtk

system() returned: status=0x0000 (0,0)

child exited, status=0

Command: ls | grep XYZ Код завершения оболочки совпадает с кодом…

system() returned: status=0x0100 (1,0) …выхода ее последней команды (grep), которая…

child exited, status=1 …не нашла совпадений, что привело к вызову exit(1)

Command: exit 127

system() returned: status=0x7f00 (127,0)

(Probably) could not invoke shell Но в данном случае это не так

Command: sleep 100

Нажимаем Ctrl-Z, чтобы приостановить активную группу процессов

[1]+ Stopped./t_system

$ ps | grep sleep Находим PID команды sleep

29361 pts/6 00:00:00 sleep

$ kill 29361 И отправляем сигнал, чтобы ее завершить

$ fg Опять делаем программу t_system активной

./t_system

system() returned: status=0x000f (0,15)

child killed by signal 15 (Terminated)

Command: ^DНажимаем Ctrl+D для завершения программы

Листинг 27.7. Выполнение консольной команды с помощью функции system()

procexec/t_system.c

#include

#include "print_wait_status.h"

#include "tlpi_hdr.h"

#define MAX_CMD_LEN 200

int

main(int argc, char *argv[])

{

char str[MAX_CMD_LEN]; /* Команда, которую нужно выполнить посредством system() */

int status; /* Статус, возвращаемый из system() */

for (;;) { /* Считываем и выполняем консольную команду */

printf("Command: ");

fflush(stdout);

if (fgets(str, MAX_CMD_LEN, stdin) == NULL)

break; /* Конец файла */

status = system(str);

printf("system() returned: status=0x%04x (%d,%d)\n",

(unsigned int) status, status >> 8, status & 0xff);

if (status == –1) {

errExit("system");

} else {

if (WIFEXITED(status) && WEXITSTATUS(status) == 127)

printf("(Probably) could not invoke shell\n");

else /* Оболочка успешно выполнила команду */

printWaitStatus(NULL, status);

}

}

exit(EXIT_SUCCESS);

}

procexec/t_system.c

Избегайте функции system() в программах с установленным ID пользователя или группы

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

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