Почему chdir(«~/dev/») возвращает -1?

#c #c #unix

#c #c #unix

Вопрос:

В моем приложении на c я хочу изменить рабочий каталог на указанный. Но когда я указываю "~/dev/" как рабочий каталог chdir() , происходит сбой и возвращается -1. Вместо этого это работает, когда я указываю "/home/myusername/dev" . Почему это происходит? Как я могу решить эту проблему (кроме проверки, является ли строка первым символом ~ и замены его на /home/myusername )?

Комментарии:

1. chdir("$HOME/dev/") тоже сбой, и по той же причине.

Ответ №1:

Расширение tilde (~) в переменную среды HOME выполняется с помощью bash. Это расширение выполняется до того, как оно передается команде chdir. Суть в том, что ~ обрабатывается bash, а не командой chdir. Таким образом, вы не можете использовать его при вызове функции chdir().

Чтобы найти другие расширения (и подробности ~ expansion), выполненные bash, проверьте эту ссылку.

Ответ №2:

Вы могли бы использовать следующее, чтобы получить то, до чего ~ , вероятно, будет расширено (используя getpwuid ):

 #include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <pwd.h>

// @prefer_env should be TRUE if you prefer the value of the $HOME
//  environment variable over what is stored in the user's passwd
char* get_homedir(int prefer_env)
{
    char *found = getenv("HOME");
    char *homedir = NULL;

    if (!prefer_env || !found)
    {
        struct passwd *pw = getpwuid(geteuid());
        if (pw amp;amp; pw->pw_dir) found = pw->pw_dir;
    }

    if (found)
    {
        // I would add error checking
        homedir = (char*)malloc(strlen(found)   1);
        strcpy(homedir, found);
    }

    return homedir;
}
  

Комментарии:

1. Этот код не проверяет переменную среды HOME, которая может переопределить путь, указанный при вводе пароля, другим значением.

2. @Al Riddoch: Я всегда с подозрением отношусь к этой переменной окружения, но это просто основано на опыте. Я обновлю свой код, чтобы использовать либо то, либо другое.

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

Ответ №3:

Разрешение ~ , как и любой переменной окружения, зависит от командной строки. Я не думаю, что вы можете использовать это в функциях C api.

Ответ №4:

Ну, в вашем домашнем каталоге ~ обычно заменяется вашей оболочкой, когда вы вводите его перед тем, как оболочка вызовет какой-либо программный вызов (даже если cd не является программным вызовом, а реализован в самой оболочке).

В любом случае: в C нет способа автоматически заменить ~ на ваш homedir

Ответ №5:

Как указано в предыдущих ответах, библиотека C не заменяет ~ для вас. Это делается командной оболочкой. Не следует предполагать, что домашним каталогом пользователя является /home/myusername, поскольку этого нельзя предположить.

Правильный способ определить домашний каталог — это проверить наличие переменной среды HOME и прочитать ее содержимое. Обычно это будет определено, но в случае, если это не так, вам следует вернуться к использованию getpwuid() или аналогичного вызова, чтобы получить ввод пароля для текущего пользователя, который будет включать его домашний каталог.

Ответ №6:

Попробуйте вместо этого использовать $HOME, ~ — это просто ярлык для $HOME.

Комментарии:

1. На самом деле оболочка все равно расширит ~ до вашего домашнего каталога, если $HOME не задан, так что это не так просто, как ярлык для $HOME.