char *pw_name; /* Имя для входа в систему (имя пользователя) */
char *pw_passwd; /* Зашифрованный пароль */
uid_t pw_uid; /* Идентификатор пользователя */
gid_t pw_gid; /* Идентификатор группы */
char *pw_gecos; /* Комментарий (информация о пользователе) */
char *pw_dir; /* Исходный рабочий (домашний) каталог */
char *pw_shell; /* Оболочка входа в систему */
};
Поля pw_gecos и pw_passwd структуры passwd в SUSv3 не определены, но доступны во всех реализациях UNIX. Поле pw_passwd содержит актуальную информацию только при выключенном режиме использования теневых паролей. (С точки зрения программирования наипростейший способ выявить включение режима использования теневых паролей состоит в вызове функции getspnam() (вскоре рассмотрим) сразу же после успешного выполнения функции getpwnam(), чтобы увидеть, сможет ли она возвратить запись теневого пароля для того же имени пользователя.) В некоторых других реализациях в этой структуре предоставляются дополнительные нестандартные поля.
Поле pw_gecos происходит из ранних реализаций UNIX, где в нем содержалась информация для связи с машиной, на которой запущена операционная система General Electric Comprehensive Operating System (GECOS). Хотя эта цель его применения давно устарела, имя поля осталось прежним, а само оно предназначено для записи информации о пользователе.
Функция getpwuid() возвращает точно такую же информацию, что и функция getpwnam(), но ведет поиск по числовому идентификатору пользователя, предоставленному в аргументе uid. Обе функции возвращают указатель на статически выделенную структуру. Эта структура перезаписывается при каждом вызове любой из этих функций (или рассматриваемой далее функции getpwent()).
Поскольку функции getpwnam() и getpwuid() возвращают указатель на статически выделенную структуру, они являются нереентерабельными. На самом деле ситуация складывается еще сложнее, поскольку возвращаемая структура passwd содержит указатели на другую информацию (например, поле pw_name), которая также является статически выделенной. (Реентерабельность объясняется в подразделе 21.1.2.) Такие же утверждения справедливы для функций getgrnam() и getgrgid(), которые мы вскоре рассмотрим.
В SUSv3 указывается эквивалентный набор реентерабельных функций — getpwnam_r(), getpwuid_r(), getgrnam_r() и getgrgid_r(), включающих в качестве аргументов как структуру passwd (или group), так и область буфера для хранения других структур, на которые указывают поля структуры passwd (group). Количество байтов, требуемое для этого дополнительного буфера, может быть получено с помощью вызова sysconf(_SC_GETPW_R_SIZE_MAX) (или sysconf(_SC_GETGR_R_SIZE_MAX) для функций, имеющих отношение к группам). Дополнительные сведения об этих функциях можно найти на страницах руководства.
В соответствии с положениями SUSv3, если нужная запись passwd не может быть найдена, функции getpwnam() и getpwuid() должны возвратить значение NULL, оставив значение errno в неизменном виде. Таким образом, можно различить ошибку и случаи «запись не найдена», используя следующий код:
struct passwd *pwd;
errno = 0;
pwd = getpwnam(name);
if (pwd == NULL) {
if (errno == 0)
/* Запись не найдена */;
else
/* Ошибка */;
}
Однако некоторые реализации UNIX не соответствуют [требованиям] SUSv3 по этому вопросу. Если нужная запись passwd не найдена, эти функции возвращают значение NULL и устанавливают для errno ненулевое значение, например ENOENT или ESRCH. До выхода версии 2.7 библиотека glibc выдавала в таком случае ошибку ENOENT, но, начиная с версии 2.7, она стала отвечать требованиям SUSv3. Эти расхождения в реализациях возникли отчасти из-за того, что в POSIX.1-1990 данным функциям не требовалось устанавливать для errno значения при ошибке и позволялось устанавливать значение в случае «запись не найдена». В результате при использовании этих функций стало совершенно невозможно портируемым образом отличить ошибку от ситуации «запись не найдена».
Извлечение записей из файла групп
Записи из файла групп извлекаются с помощью функций getgrnam() и getgrgid().
#include <grp.h>
struct group *getgrnam(const char *name);
struct group *getgrgid(gid_t gid);
Обе функции при успешном завершении возвращают указатель, при ошибке — NULL. Описание для случая «запись не найдена» дается в тексте подраздела
Функция getgrnam() осуществляет поиск информации о группе по имени группы, а функция getgrgid() — по идентификатору группы. Обе функции возвращают указатель на структуру следующего типа:
struct group {
char *gr_name; /* Имя группы */
char *gr_passwd; /* Зашифрованный пароль (в режиме без теневых паролей) */
gid_t gr_gid; /* Идентификатор группы */
char **gr_mem; /* Массив указателей на имена участников группы,
перечисленных в /etc/group, завершающийся значением NULL */