};
Поле gr_passwd структуры group в SUSv3 не указано, но доступно в большинстве реализаций UNIX.
Как и в случае рассмотренных выше соответствующих функций работы с записями в файле паролей, эта структура перезаписывается при каждом вызове одной из этих функций.
Если функции не могут найти запись, соответствующую группе, они демонстрируют такие же варианты поведения, которые были рассмотрены для функций getpwnam() и getpwuid().
Пример программы
Один из примеров наиболее частого применения рассмотренных в этом разделе функций — преобразование символьных имен пользователя и группы в их числовые идентификаторы и наоборот. В листинге 8.1 показано это преобразование в виде четырех функций: userNameFromId(), userIdFromName(), groupNameFromId() и groupIdFromName(). Для удобства вызывающего функции userIdFromName() и groupIdFromName() также позволяют аргументу name быть числовой строкой в чистом виде. В этом случае строка преобразуется непосредственно в число и возвращается вызвавшему функцию коду. Эти функции будут использоваться в некоторых примерах программ, которые мы рассмотрим далее в книге.
Листинг 8.1. Функции для преобразования идентификаторов пользователей и групп в имена пользователей и групп и наоборот
users_groups/ugid_functions.c
#include <pwd.h>
#include <grp.h>
#include <ctype.h>
#include "ugid_functions.h" /* Объявление определяемых здесь функций */
char * /* Возвращает имя, соответствующее 'uid', или NULL при ошибке */
userNameFromId(uid_t uid)
{
struct passwd *pwd;
pwd = getpwuid(uid);
return (pwd == NULL)? NULL: pwd->pw_name;
}
uid_t /* Возвращает идентификатор пользователя,
соответствующего 'name', или –1 при ошибке */
userIdFromName(const char *name)
{
struct passwd *pwd;
uid_t u;
char *endptr;
if (name == NULL || *name == '\0') /* Возвращает ошибку, если передан NULL*/
return -1; /* или пустая строка */
u = strtol(name, &endptr, 10); /* Для удобства вызывающего */
if (*endptr == '\0') /* разрешение числовой строки */
return u;
pwd = getpwnam(name);
if (pwd == NULL)
return -1;
return pwd->pw_uid;
}
char * /* Возвращает имя, соответствующее 'gid', или NULL при ошибке */
groupNameFromId(gid_t gid)
{
struct group *grp;
grp = getgrgid(gid);
return (grp == NULL)? NULL: grp->gr_name;
}
gid_t /* Возвращает идентификатор группы, */
/* соответствующего 'name',или -1 при ошибке */
groupIdFromName(const char *name)
{
struct group *grp;
gid_t g;
char *endptr;
if (name == NULL || *name == '\0') /* Возвращает ошибку, если передан NULL*/
return -1; /* или пустая строка */
g = strtol(name, &endptr, 10); /* Для удобства вызывающего */
if (*endptr == '\0') /* разрешение числовой строки */
return g;
grp = getgrnam(name);
if (grp == NULL)
return -1;
return grp->gr_gid;
}
users_groups/ugid_functions.c
Сканирование всех записей в файлах паролей и групп
Функции setpwent(), getpwent() и endpwent() используются для выполнения последовательного сканирования записей в файле паролей.
#include <pwd.h>
struct passwd *getpwent(void);
Возвращает указатель при успешном завершении или NULL в случае конца потока или при ошибке
void setpwent(void);
void endpwent(void);
Функция getpwent() поочередно возвращает записи из файла паролей, выдавая NULL, когда записей уже больше нет (или при возникновении ошибки). При первом вызове функция автоматически открывает файл паролей. Когда работа с файлом завершена, для его закрытия вызывается функция endpwent().
С помощью следующего кода можно пройти через весь файл паролей, выводя на экран имена для входа в систему и идентификаторы пользователей:
struct passwd *pwd;
while ((pwd = getpwent())!= NULL)
printf("%-8s %5ld\n", pwd->pw_name, (long) pwd->pw_uid);
endpwent();
Вызов функции endpwent() необходим для того, чтобы при любом последующем вызове getpwent() (возможно, в другой части нашей программы или в какой-нибудь вызываемой нами библиотечной функции) файл паролей открывался заново и чтение выполнялось с начала файла. С другой стороны, если в файле пройдена только часть пути, для перезапуска чтения с начала файла можно воспользоваться функцией setpwent().
Функции getgrent(), setgrent() и endgrent() выполняют аналогичные задачи для файла групп. Здесь не будет приводиться их описание, поскольку они аналогичны уже рассмотренным функциям для файла паролей. Соответствующие подробности, относящиеся к этим функциям, можно найти на страницах руководства.
Извлечение записей из теневого файла паролей
Следующие функции используются для извлечения отдельных записей из теневого файла паролей и сканирования всех записей в этом файле.