Я пытаюсь выполнить другую программу из своей собственной, но я не понимаю нескольких вещей. Итак, я написал этот код:
void run() {
cout << "##Run" << endl;
pid_t process_id = fork();
if (process_id == 0) {
char* args[] = { "sudo", "ls", "-l" };
auto i = execvp("sudo", args);
cout << "#Result: " << i << endl;
return;
} else if (process_id < 0) {
throw std::runtime_error("fork() failed");
} else if (process_id > 0) {
wait(&process_id);
}
return;
}
void run_decorator() {
cout << "###Run decorator: " << endl;
run();
}
int main() {
run();
run_decorator();
return 0;
}
И вывод
##Run
total 88
-rwxr-xr-x 1 bezik bezik 77560 Nov 29 19:53 colors
-rwxr-xr-x 1 bezik bezik 63 Nov 26 21:45 compile
drwxr-xr-x 2 bezik bezik 4096 Nov 26 20:46 headers
drwxr-xr-x 2 bezik bezik 4096 Nov 23 00:48 sources
###Run decorator:
##Run
#Result: -1
Может кто-нибудь объяснить мне, почему execvp не удалось при вызове из функции run_decorator ()?
Читать внимательно документация execvp (3). Это говорит о execl
так далее…:
Первый аргумент, по соглашению, должен указывать на
имя файла, связанное с исполняемым файлом. Список
аргументы должен заканчиваться нулевым указателем, и, так как это
переменные функции, этот указатель должен быть приведен(char *) NULL
,
и относительно execvp
:
Массив указателей должен заканчиваться нулевым указателем.
Так что вы должны код:
char* args[] = { "sudo", "ls", "-l", NULL };
execvp("sudo", args);
КСТАТИ, execvp
вообще не возвращайся, Кроме на провал. Не нужно сохранять свой результат после звонка.
Но вам нужно, когда execvp
возвращает (и это происходит только при ошибке), чтобы показать какое-то сообщение об ошибке. Я предлагаю:
perror("execvp");
exit(EXIT_FAILURE);
и вы могли бы найти действительные аргументы для вызова, в этом конкретном случае, _exit (2) вместо выход (3). Я все еще предпочитаю exit
(потому что это очистит буферы stdio и запустит atexit (3)-зарегистрированные обработчики).
Может кто-нибудь, пожалуйста, объясните мне, почему
execvp
не удалось
Да, ERRNO (3). Который используется PError (3).
Не забывай читать внимательно документация каждой используемой функции. Для системных вызовов (перечисленных в Системные вызовы (2)) и стандартные функции библиотеки C (см. интро (3)), как правило, вы должны обрабатывать случай сбоя (часто используя errno
по крайней мере через perror
затем exit
)
Я не понимаю зачем тебе sudo
с ls
, Есть несколько случаев, когда это может быть полезно, так как большую часть времени ваш рабочий каталог в списке (тогда sudo
бесполезно), и в этом случае вы могли бы даже использовать opendir (3), READDIR (3) с стат (2) (так что не надо fork
затем execvp
/bin/ls
программа).
Читайте также о УИП методы в execve (2) а также Учетные данные (7) (а также setreuid (2)). Увидеть этот (вы могли бы избежать sudo
с вашей собственной программой setuid).
Кстати, вы должны скомпилировать с все предупреждения и отладочная информация (g++ -Wall -Wextra -g
с НКУ) а также использовать отладчик gdb
(и, возможно Трассирование (1) а также Valgrind (1)).
Других решений пока нет …