Реализация оболочки Unix в C: проверьте, является ли файл исполняемым - PullRequest
4 голосов
/ 07 января 2011

Я работаю над реализацией оболочки Unix на C, и в настоящее время я занимаюсь проблемой относительных путей.Особенно при вводе команд.А пока мне приходится каждый раз вводить полный путь к исполняемому файлу, когда я бы просто поставил «ls» или «cat».

Мне удалось получить переменную $ PATH env.Моя идея состоит в том, чтобы разделить переменную на символ «:», затем добавить каждую новую строку к имени команды и проверить, существует ли файл и является ли он исполняемым.

Например, если мой PATH: "/ bin: / usr / bin" и я ввожу "ls", я бы хотел, чтобы программа сначала проверила, существует ли "/ bin / ls" и является ли она исполняемой, еслине переходить к "/usr/bin/".

Два вопроса:

1) Это хороший способ сделать это?(Разве это не обязательно должно быть лучшим. Я просто хочу убедиться, что это будет работать.

2) Что более важно, Как я могу проверить в C, если файл существует и являетсяисполняемый файл?

Надеюсь, я достаточно ясен, и ... хорошо, спасибо:)

Ответы [ 6 ]

10 голосов
/ 07 января 2011

Не.Выполнение этой проверки неверно;это по своей сути зависит от состояния гонки.Вместо этого попытайтесь выполнить его с соответствующим exec семейным вызовом.Если это не исполняемый файл, вы получите ошибку.

Также обратите внимание, что вам не нужно искать PATH самостоятельно;execvp может сделать это за вас.

5 голосов
/ 07 января 2011

stat?Psh.Намного больше, чем нужно.

Проверьте системный вызов access().

if (access(filename, F_OK|X_OK) == 0)
{
    /* You can execute this file. */
}

Обратите внимание, что любая проверка на доступ к файлу или наличие файла имеет врожденное состояние расы в нем.Вы не можете гарантировать при вызове execve, что кто-то не удалил исполняемый бит, не изменил владельца файла, не удалил файл и т. Д. За время, прошедшее с момента проверки.Помните об этом, когда будете писать код и решать, как обрабатывать ошибки.

4 голосов
/ 07 января 2011

Вызовите stat по полному пути, и если он вернет 0 (успех), цель существует. В этом В этом случае вы можете использовать поле st_mode в возвращаемой структуре, чтобы проверить, target - это каталог, устройство, именованный канал или обычный файл. Если это файл, st_mode также будет содержать биты прав доступа. (Если это каталог, некоторые «исполняемые» биты могут быть установленным, но это будет означать «доступный для поиска», а не «исполняемый».)

Редактировать: Как уже отмечали другие, это зависит от расы, и есть лучшие способы выполнить то, что вы хотите сделать в этой конкретной ситуации.

4 голосов
/ 07 января 2011

Используйте функцию stat: http://linux.die.net/man/2/stat

например:.

struct stat sb;
if(!stat(path, &sb))
{
  if(IS_REG(sb.st_mode) && sb.st_mode & 0111)
    printf("%s is executable\n", path);
}
0 голосов
/ 08 апреля 2012

Ответ access() является единственным разумным.Если вы используете stat, вам придется проанализировать / etc / group, чтобы найти все группы, в которых вы находитесь BESIDE getgid(), и проверить их вместе с исполняемым битом группы.

0 голосов
/ 10 января 2011

Как вы создаете процесс ??

Использовать execlp или execvp.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...