Написание собственной оболочки Unix на C. Проблемы с PATH и execv

StackOverflow https://stackoverflow.com//questions/12650092

  •  11-12-2019
  •  | 
  •  

Вопрос

Я пишу свою собственную оболочку на C.Он должен иметь возможность отображать текущий каталог пользователя, выполнять команды на основе полного пути (должен использовать execv) и разрешить пользователю менять каталог с помощью cd.

Это домашнее задание.Учитель дал нам только базовый курс по C и очень краткое описание того, как должна работать программа.Поскольку я не из тех, кто легко сдается, я три дня размышлял, как это сделать, но теперь я в тупике.

Это то, что у меня есть до сих пор:

  • Отображает имя пользователя, имя компьютера и текущий каталог (по умолчанию домашний каталог).
  • Запрашивает у пользователя ввод и получает ввод
  • Разделяет ввод пользователя по " " на массив аргументов.
  • Разделяет переменную среды PATH по ":" на массив токенов.

Я не уверен, как действовать дальше.Я знаю, что мне нужно использовать команду execv, но в своих исследованиях в Google я не нашел примера, который мне был бы понятен.Например, если используется команда bin/ls, как execv узнает, что нужно отобразить все файлы/папки из домашнего каталога?Как сообщить системе, что я изменил каталог?

Я часто пользуюсь этим сайтом, который мне очень помог: http://linuxgazette.net/111/ramankutty.html но я опять в тупике.

Спасибо за вашу помощь.Дайте мне знать, следует ли мне опубликовать часть моего существующего кода, хотя я не был уверен, было ли это необходимо.

Это было полезно?

Решение

Для реализации команды cd вам просто нужен системный вызов chdir.

#include <unistd.h>

int chdir(
    const char *path /* the path name */
);

Итак, вы можете просто позвонить что-то вроде:

int ret1 = chdir("../foo/bar");

Возвращаемое значение chdir равно 0, если можно было перейти в этот каталог, и -1, если произошла ошибка.Для ошибки вам следует объединить справочную страницу.

Текущий каталог может быть проверен любой программой, поэтому, если вы выполните ls без каких-либо аргументов, затем ls проверяет, в каком каталоге он работает, и использует этот каталог в качестве единственного аргумента.Это особенность ls, а не execv вызов.

Для второй части.

#include <unistd.h>
int execv(
     const char *path, /* programm path*/
     char *const argv[]/* argument vector*/
);

execv выполняет исполняемый файл в заданном месте path и с аргументами, приведенными в argv.Итак, если вы хотите выполнить /bin/ls ../foo /bar, вам нужно что-то похожее на

char *cmd_str = "/bin/ls";
char *argv[] = {cmd_str, "../foo", "/bar", NULL };
if (execv(cmd_str, argv) == -1 ){
    /* an error occurred */
}

Ошибка, возвращенная execv это -1.Если вы хотите узнать, почему команда не была выполнена, обратитесь к страницам руководства.

А NULL в char *argv[] = {cmd_str, "../foo", "/bar", NULL }; указывает на отсутствие других аргументов после NULL.

Третья часть.Система на базе Unix обычно рассматривает команды с / в ней как команды, которые можно выполнить напрямую.Это означает, что вы сначала проверяете, есть ли косая черта в данной командной строке.

int ret_value;
if (strchr(cmd_str, '/')
    if (execv(cmd_str, argv) == -1 ){
        /* an error occurred */
    }

Если слэша нет, то нужно пройтись по всем каталогам в PATH и проверьте, можете ли вы выполнить команду.Итак, данная команда ls ../foo /bar и давайте предположим значение PATH является ".:/sbin:/bin:/usr/bin".Затем мы попытаемся сначала выполнить ./ls ../foo /bar затем /usr/bin/ls ../foo /bar и наконец /bin/ls ../foo /bar.

Надеюсь это поможет.

Другие советы

Например, если команда bin/ls, как execv знаете, как отображать все файлы/папки из домашнего каталога?Как сообщить системе, что я изменил каталог?

Каждый процесс имеет текущий рабочий каталог, который можно изменить с помощью chdir.Дочерние процессы унаследуют рабочий каталог от своего родителя.Таким образом, ваша оболочка будет управлять своим текущим рабочим каталогом в ответ на cd команды, вводимые пользователем.Когда вводится команда, которая не является встроенной, вы fork создать дочерний процесс, а затем вызвать execv там для выполнения двоичного файла.

Если вы хотите взять PATH Учитывая имена программ, которые не содержат части каталога, вам следует попробовать все возможные комбинации PATH элемент и имя программы.Вы можете либо проверить, существует ли указанный файл, либо просто попытаться выполнить его и продолжить работу со следующим, если это не удастся.Я упал execv звонок не удался, вам придется позвонить _exit чтобы завершить дочерний процесс.

Обратите внимание, что большинство оболочек обрабатывают любую команду, содержащую / как путь, который передается execv напрямую.Если путь не начинать с /, то это относительный путь, и операционная система разрешит его относительно текущего рабочего каталога.Другими словами, bin/ls из вашего примера будет относиться к ls двоичный файл в bin каталог, который является подкаталогом текущего рабочего каталога.Только команды, которые не содержат никаких / вообще либо интерпретируются как встроенная команда (например, cd) или имя какого-либо двоичного файла, расположенного на PATH.

Первый аргумент для execv это путь, который вы вычислили.Первый элемент argv список традиционно соответствует имени в том виде, в каком оно было введено, т.е.без добавления PATH каталог.После этого первого аргумента передаются любые дополнительные параметры командной строки, за которыми следует NULL чтобы завершить список.

Я думаю, что вопрос заключается в том, что вы считаете, что оболочка несет ответственность за выполнение работы ls.Генеракодицетагкод на самом деле не является «частью» оболочки (в этом случае по меньшей мере).Оболочка выполняет программу под названием ls.Большинство комментариев, по-видимому, объясняют, как найти ls, но я не верю, что это то, о чем вы путаете.

Вы должны внимательно рассмотреть вопрос о том, какая точка оболочки, прежде чем писать его.Комментарии косвенно отмечали тот факт, что оболочка «просто» должна «вызывать» программы, такие как ls и ls, не выполняют их задачи.

ls само по себе знает, что, если не указаны никакие аргументы, предполагается, что в текущем рабочем каталоге будут перечислены файлы, возвращаемые функцией getcwd

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top