Программирование в стандарте POSIX

Данные, ассоциированные с пользователем


Операционная система, соответствующая стандарту POSIX, должна поддерживать базу данных пользователей, в которой о каждом из них хранится по крайней мере следующая информация:

  • имя пользователя;
  • числовой идентификатор пользователя;
  • числовой идентификатор начальной группы;
  • начальный рабочий каталог;
  • начальная программа пользователя.

Поясним смысл перечисленных элементов данных.

Каждый зарегистрированный пользователь ОС имеет имя, которое он указывает для целей идентификации при входе в систему. После проведения идентификации и, как правило, аутентификации пользователя, с ним ассоциируются (неотрицательные) числовые идентификаторы пользователя и начальной группы. В отличие от имен, ОС оперирует ими во всех случаях, кроме первоначальной идентификации. Затем запускается начальная программа пользователя (например, командный интерпретатор shell) с указанным начальным рабочим каталогом.

Поля начального рабочего каталога и начальной программы пользователя могут быть пустыми; в таком случае их трактовка зависит от реализации. Обычно в системе определена подразумеваемая начальная программа, в качестве которой обычно используется /bin/sh.

Пользователи объединяются в группы; каждый пользователь является членом хотя бы одной из них. Для групп также существует база данных, ее записи содержат по крайней мере следующие поля:

  • имя группы;
  • числовой идентификатор группы;
  • список пользователей, которым разрешено становиться членами данной группы.

В базе данных пользователей указывается идентификатор начальной группы, в нее пользователь попадает сразу после входа в систему. В процессе работы возможен переход в другую группу (см. далее описание утилиты newgrp), однако на эти переходы наложены ограничения в виде списка возможных членов группы.

С объектно-ориентированной точки зрения можно считать, что класс "пользователь" предоставляет один метод - начальную программу. Его можно применить для программирования определенных услуг. Например, если нужно дать возможность любому человеку (не обязательно зарегистрированному пользователю), оказавшемуся рядом со свободным терминалом, узнать текущие дату и время, заводят пользователя date с начальной программой /bin/date.


Опросить ассоциированные с пользователем данные (точнее, идентификаторы и имена пользователя и начальной группы, а также всех групп, членами которых ему разрешено быть, - так называемых дополнительных групп) позволяет служебная программа

id [имя_пользователя]

Если имя_пользователя опущено, выдается информация о текущем пользователе и его текущей группе.

Пример использования служебной программы id. Команда

id root



может выдать на стандартный вывод следующий результат:

uid=0(root) gid=0(root) groups=0(root), 1(bin),2(daemon),3(sys),4(adm),6(disk), 10(wheel)

Числовой идентификатор 0 характеризует суперпользователя, который в большинстве Unix-систем не подвержен контролю прав доступа.

Входное имя текущего пользователя можно узнать также с помощью утилиты

logname

и функции getlogin():

#include <unistd.h> char *getlogin (void);

Отметим, что одному идентификатору пользователя может соответствовать несколько записей в базе данных пользователей, различающихся входными именами и, возможно, другими атрибутами; logname и getlogin() выдают имя, под которым начат текущий сеанс работы с ОС.

Над базой данных пользователей определены операции поиска по идентификатору или имени пользователя, реализуемые, соответственно, функциями getpwuid() и getpwnam() (см. пример 3.1):

#include <pwd.h> struct passwd *getpwuid (uid_t uid); #include <pwd.h> struct passwd *getpwnam (const char *name);

Листинг 3.1. Описание функций getpwuid() и getpwnam(). (html, txt)

По стандарту структура passwd должна содержать по крайней мере следующие поля, соответствующие описанным выше обязательным элементам базы данных пользователей:

char *pw_name; /* Имя пользователя */

uid_t pw_uid; /* Числовой идентификатор пользователя */ gid_t pw_gid; /* Числовой идентификатор начальной группы */ char *pw_dir; /* Начальный рабочий каталог */ char *pw_shell; /* Начальная программа пользователя */

Типы uid_t и gid_t определяются в заголовочном файле <sys/types.h>.

Приведем пример выдачи информации о текущем пользователе и пользователе root с идентификатором 0 (см.


пример 3.2).

Листинг 3.2. Пример работы с базой данных пользователей. (html, txt)

По окончании работы этой программы может быть получен следующий результат (см. пример 3.3):

Листинг 3.3. Возможный результат работы с базой данных пользователей. (html, txt)

Аналогичные функции имеются для поиска в базе данных групп - getgrgid() и getgrnam() (см. пример 3.4):

#include <grp.h> struct group *getgrgid (gid_t gid); #include <grp.h> struct group *getgrnam (const char *name);

Листинг 3.4. Описание функций getgrgid() и getgrnam(). (html, txt)

Структура group обязана содержать поля

char *gr_name;/* Имя группы */ gid_t gr_gid; /* Числовой идентификатор группы */ char **gr_mem; /* Указатель на ограниченный пустым указателем массив символьных указателей на имена пользователей, которым разрешено становиться членами данной группы */

Применение функции getgrgid() отражено в пример 3.5.

Листинг 3.5. Пример работы с базой данных групп. (html, txt)

Приведенная в качестве примера программа может привести к результату, показанному в пример 3.6:

Пользователи, включенные в группу с идентификатором 1: root bin daemon

Листинг 3.6. Возможный результат работы с базой данных групп. (html, txt)

Для смены текущей группы пользователя предназначена служебная программа newgrp (стандарт POSIX-2001 относит ее к числу необязательных, входящих в расширение "Мобильность пользователей", UP):

newgrp [-l] [группа]

Группа, в которую осуществляется переход, задается именем или числовым идентификатором. Будучи вызванной без аргументов, утилита newgrp возвращает пользователя в его начальную группу, заданную в базе данных пользователей.

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

Если пользователь не входит в список возможных членов новой группы, при переходе в нее может запрашиваться пароль, однако в стандарте POSIX-2001 этот аспект считается зависящим от реализации.Более того, отмечается, что в базе данных групп нет удобных способов задания паролей, поэтому их использование в приложениях не приветствуется, а со временем пароли групп могут стать ненужными.



Листинг 3.4. Описание функций getgrgid() и getgrnam().

Структура group обязана содержать поля

char *gr_name;/* Имя группы */ gid_t gr_gid; /* Числовой идентификатор группы */ char **gr_mem; /* Указатель на ограниченный пустым указателем массив символьных указателей на имена пользователей, которым разрешено становиться членами данной группы */

Применение функции getgrgid() отражено в пример 3.5.

#include <sys/types.h> #include <grp.h> #include <stdio.h> /* Печать списка пользователей, включенных в группу с заданным идентификатором */ static int print_gr_mem (const gid_t gid) { struct group *grp; /* Данные о группе */ char **c_gr_mem; /* Текущий указатель на имя члена группы */ char *c_gr_mem_name; /* Текущее имя члена группы */ if ((grp = getgrgid (gid)) == NULL) { fprintf (stderr, "\nНе удалось найти информацию о группе с идентификатором %d\n", gid); return 1; } printf ("\nПользователи, включенные в группу с идентификатором %d:\n", gid); c_gr_mem = grp->gr_mem; while ((c_gr_mem_name = *c_gr_mem++) != NULL) { printf(" %-8.8s", c_gr_mem_name); } printf ("\n"); return 0; } int main (void) { return print_gr_mem (1); }

Листинг 3.5. Пример работы с базой данных групп.

Приведенная в качестве примера программа может привести к результату, показанному в пример 3.6:

Пользователи, включенные в группу с идентификатором 1: root bin daemon

Листинг 3.6. Возможный результат работы с базой данных групп.

Для смены текущей группы пользователя предназначена служебная программа newgrp (стандарт POSIX-2001 относит ее к числу необязательных, входящих в расширение "Мобильность пользователей", UP):

newgrp [-l] [группа]

Группа, в которую осуществляется переход, задается именем или числовым идентификатором. Будучи вызванной без аргументов, утилита newgrp возвращает пользователя в его начальную группу, заданную в базе данных пользователей.

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

Если пользователь не входит в список возможных членов новой группы, при переходе в нее может запрашиваться пароль, однако в стандарте POSIX-2001 этот аспект считается зависящим от реализации. Более того, отмечается, что в базе данных групп нет удобных способов задания паролей, поэтому их использование в приложениях не приветствуется, а со временем пароли групп могут стать ненужными.


Содержание раздела