У меня есть проект для написания оболочки в C++ в операционной системе Linux, которая может запускать подмножество команд, которые терминал может запускать как cd
, ls
и т.д.
Мой вопрос: если я использую что-то вроде execl("bin/ls","ls")
как он знает, где выполнить ls
. Будет ли он по умолчанию просто запускать ls
из каталога, из которого запускается программа. И если да, то как мне изменить, где он работает от, если я запустил cd foo
а затем снова запустил ls. Да, я делаю довольно ограниченную версию bash.
Вот что я до сих пор запустил ls.
int quash :: ls (строка)
{
pid_t child = 0;
child = fork();
if (child < 0)
{
fprintf( stderr, "process failed to fork\n" );
return 1;
}
if (child == 0)
{
wait(NULL);
}
else
{
execlp("/bin/ls", "ls");
}
return 0;
}
Будет ли execlp() "/bin/ls", "ls"); распечатать что-нибудь или мне нужно добавить что-то еще?
Резюме
Если вы вызываете execl("bin/ls", "ls")
система попытается найти файл с именем ls
в каталоге с именем bin
внутри текущего рабочего каталога. Это почти наверняка не то, что вы хотите сделать. Вы, вероятно, хотите:
execlp("ls", "ls);
или
execl("/bin/ls", "ls");
Хотя также возможно, что ни то, ни другое не требуется.
Подробнее
Существует множество различных функций, которые могут быть использованы для замены текущего процесса новым изображением процесса; они включают, по меньшей мере, следующее:
execl, execv
execle, execve
execlp, execvp
Варианты, которые включают l, являются вариабельными; они берут NULL-конец списка аргументов const char*
которые определяют вектор argv
который должен быть передан новому исполняемому файлу. Версии, которые включают в себя v вместо этого, принимают один аргумент char*const[]
, который представляет собой массив строк с нулевым завершением, которые используются для построения вектора argv
.
Версии, которые заканчиваются на e
принимают один дополнительный аргумент, который является char *const[]
используемым для создания новых переменных исполняемой среды. В других версиях используется существующая коллекция переменных среды.
Версии, которые заканчиваются на p
обрабатывают первый аргумент по-разному двумя способами:
Если первый аргумент не содержит /, тогда (текущая) PATH
среды PATH
используется для поиска правильной директории. Ожидается, что PATH
будет списком путей к каталогам, разделенных :, и имя файла (то есть первый аргумент execlp
или execvp
) будет искать в каждом каталоге по очереди. Если первый аргумент содержит /, то он обрабатывается так же, как и другие варианты exec
: первый аргумент должен быть фактическим путем к исполняемому файлу, который обычно является абсолютным путем (то есть, который начинается с /), хотя допускается относительный путь, и в этом случае он будет относиться к текущему рабочему каталогу.
Кроме того, если файл найден, но он не распознается как исполняемый двоичный файл, он будет рассматриваться как сценарий оболочки, будучи переданным оболочке по умолчанию (обычно /bin/sh
). Версия non- p
exec
возвращает ошибку в этом случае. (Это не то же самое, что исполнение "shebang", которое не указано Posix, но которое обычно будет выполняться загрузчиком системного образа, чтобы оно работало с любым вариантом exec
.)
Для интерпретаторов оболочки версии v намного удобнее. Это прискорбно, что нет версии, которая предлагает как e и p опции (хотя библиотека GNU C glibc
действительно обеспечивает один, execvpe
), потому что без этой возможности, нет никакого способа, чтобы получить автоматический поиск пути с текущей PATH
переменной; только с новой PATH
.
Рекомендации:
Определение Posix: http://pubs.opengroup.org/onlinepubs/9699919799/functions/execl.html
Linux manpage для execve
(в glibc
, все остальные варианты exec
конечном итоге вызывают execve
): http://linux.die.net/man/2/execve
Linux manpage для остальных вариантов exec
: http://linux.die.net/man/3/exec
PATH
может сыграть свою роль ...