Next Previous Contents

25. Пользователи и Группы

Каждый пользователь, кто может войти в систему, идентифицирован уникальным числом называемым пользовательский ID.

Каждый процесс имеет эффективный пользовательский ID, который говорит, какие права доступа пользователя он имеет.

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

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

Каждый файл в системе также имеет пользовательский ID и ID группы. Управление доступом работает, сравнивая ID пользователя и группы файла с таковыми выполняющегося процесса.

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

25.1 ID пользователя и группы

Каждый пользователь компьютерной системы идентифицирован именем пользователя (или именем входа в систему) и пользовательским ID. Обычно, каждое имя пользователя имеет уникальный пользовательский ID, но возможно для отдельных имен входа в систему, иметь тот же самый пользовательский ID. Пользовательские имена и соответствующий пользовательский IDS сохранены в базе данных, к которой Вы можете обращаться как описано в Разделе 25.12 [База Данных Пользователей].

Пользователи классифицированы на группы. Каждое имя пользователя также принадлежит одной или большему количеству групп, и имеет одну заданную по умолчанию группу. Пользователи - элементы той же самой группы, могут совместно использовать ресурсы (типы файлов) которые не доступны для пользователей - не элементов этой группы. Каждая группа имеет имя группы и ID группы. См. Раздел 25.13 [База Данных Групп], для того, как найти информацию относительно ID группы или имени группы.

25.2 Persona Процесса

В любое время, каждый процесс имеет отдельный пользовательский ID и ID группы, которые определяют привилегии процесса. Они коллективно называются persona процесса, потому что они определяют " кто это " для целей управления доступом. Эти ID также называются эффективным пользовательским ID и эффективным ID группы процесса.

Ваша оболочка входа в систему начинается с persona, который состоит из вашего пользовательского ID и вашего значения ID группы по умолчанию. В нормальных обстоятельствах, все ваши другие процессы наследуют эти значения.

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

И реальный и эффективный пользовательский ID может быть изменен в течение срока службы процесса. См. Раздел 25.3 [Почему Изменяется Persona].

Кроме того, пользователь может принадлежать многим группам, так что persona включает дополнительные ID группы, которые также относятся к правам.

Пользовательский ID процесса также управляет правами для посылки сигналов, используя функцию kill. См. Раздел 21.6.2 [Передача сигналов Другому Процессу].

25.3 Почему Изменяется Persona Процесса?

Наиболее очевидная ситуация, когда процессу необходимо изменить пользователя и/или ID группы - программа входа в систему. Когда вход в систему начинает выполняться, пользовательский ID корневой. Работа должна начать оболочку, чей ID пользователя и группы являются таковыми регистрируемого пользователя. (Чтобы выполнять это полностью, вход в систему должен установить реальный ID пользователя и группы также как persona. Но это - частный случай.)

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

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

Таким образом, вообразите готовую программу, которая сохраняет очки в файле. Готовая программа непосредственно должна быть способной модифицировать этот файл независимо из того, кто выполняет ее, но если пользователи могут записывать в файл без того, чтобы пройти игру, они могут давать себе любое количество очков, которое они находят приятным. Некоторые люди рассматривают этот нежелательным, или даже предосудительным. Это может быть предотвращено, созданием нового пользовательского ID и имени входа в систему (напр. games) чтобы обладать файлом, и сделать файл перезаписываемым только этим пользователем. Когда готовая программа хочет модифицировать этот файл, она может изменять эффективный пользовательский ID на games. В действительности, программа должна принять persona games, чтобы она могла писать в этот файл.

25.4 Как Приложение Может Изменить Persona

Способность изменять persona процесса может быть источником ненамеренных нарушений секретности, или даже намеренного неправильного обращения. Из-за потенциальных проблем, замена persona ограничена специальными обстоятельствами.

Вы не можете произвольно устанавливать ваш пользовательский ID или ID группы; только привилегированные процессы могут делать это. Взамен, нормальный способ для программы, чтобы изменить persona состоит в том, чтобы было установлено заранее соглашение изменения специфического пользователя или группы. Это делают функции setuid и setgid битов режима доступа файла. См. Раздел 9.8.5 [Биты Прав].

Когда setuid бит исполняемого файла установлен, выполнение этого файла автоматически изменяет эффективный пользовательский ID на пользователя, который обладает файлом. Аналогично, при выполнении файла, чей setgid бит установлен изменяется эффективный ID группы на группу файла. См. Раздел 23.5 [Выполнение Файла]. Создание файла, который изменяется к специфическому ID пользователz или ID группы таким образом, требует полного доступа к этому пользователю или группе.

См. Раздел 9.8 [Атрибуты Файла], для более общего обсуждения режимов файла и достижимости.

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

25.5 Чтение Persona Процесса

Имеются детализированные описания функций для чтения ID пользователя и группы процесса, и реального и эффективного. Чтобы использовать эти средства, Вы должны включить заглавные файлы " sys/types.h " и " unistd.h ".

       uid_t  (тип данных)
Это - целочисленный тип данных, используемый, чтобы представить пользовательский ID. В библиотеке GNU, это - побочный результат исследования для unsigned int.
       gid_t                              (тип данных)
Это - целочисленный тип данных, используемый, чтобы представить ID группы. В библиотеке GNU, это - побочный результат исследования для unsigned int.
       uid_t getuid (void)  (функция)
Getuid функция возвращает реальный пользовательский ID процесса.
       gid_t getgid (void)  (функция)
Getgid функция возвращает реальный ID группы процесса.
       uid_t geteuid (void)  (функция) 
Geteuid функция возвращает эффективный пользовательский ID процесса.
       gid_t getegid (void)  (функция) 
Getegid функция возвращает эффективный ID группы процесса.
       int getgroups (int count, gid_t *groups)  (функция) 
Getgroups функция используется, чтобы запросить относительно ID дополнительные группы процесса. До count этих ID групп сохранено в массиве groups; возвращаемое значение из функции - число групп, фактически сохраненных. Если count меньше чем общее число дополнительных групп, то getgroups возвращает значение -1, и errno установлена как EINVAL.

Если count - 0, то getgroups только возвращает общее число дополнительных групп. Для систем, которые не поддерживают дополнительные группы, это будет всегда 0.

Вот как использовать getgroups для чтения вся ID дополнительных групп:

                gid_t *
                read_all_groups (void)
                {
                        int ngroups = getgroups (NULL, 0);
                        gid_t *groups = (gid_t *) xmalloc                       
                (ngroups * sizeof (gid_t));
                        int val = getgroups (ngroups, groups);
                        if (val < 0)
                        {
                                free (groups);
                                return NULL;
                        }
                        return groups;
                }

25.6 Установка Пользовательского ID

Этот раздел описывает функции для изменения пользовательского ID (реального и/или эффективного) процесса.

Чтобы использовать эти средства, Вы должны включить заглавные файлы " sys/types.h " и " unistd.h ".

       int setuid (uid_t newuid)  (функция)
Эта функция устанавливает, и реальный и эффективный пользовательский ID процесса как newuid, если процесс имеет соответствующие привилегии.

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

Setuid функция возвращает значение 0, чтобы указать успешное завершение, и значение -1, чтобы указать ошибку. Следующие errno условия ошибки определены для этой функции:

EINVAL

Значение newuid аргумента недопустимо.

EPERM

Процесс не имеет соответствующих привилегий.

       int setreuid (uid_t ruid, uid_t euid)  (функция)
Эта функция устанавливает реальный пользовательский ID процесса как ruid и эффективный пользовательский ID как euid. Если ruid -1, это означает, что реальный пользовательский ID не изменился; аналогично, если euid -1, это означает, чтобы не изменился эффективный пользовательский ID.

Setreuid функция существует для совместимости с 4.3 UNIX BSD, который не поддерживает сохранение ID. Вы можете использовать эту функцию, чтобы изменять эффективного и реального пользователя процесса. (Привилегированные процессы не ограничены этим специфическим использованием.) если сохраненный ID обеспечивается, Вы должны использовать эту возможность вместо этой функции. См. раздел 25.8 [ВКЛЮЧЕНИЕ/ОТКЛЮЧЕНИЕ Setuid].

Возвращаемое значение - 0 при успехе и -1 при отказе. Следующие errno условия ошибки определены для этой функции:

EPERM

Процесс не имеет соответствующих привилегий; Вы не имеете прав изменить на заданный ID.

25.7 Установка ID Группы

Этот раздел описывает функции для изменения ID группы (реальный и эффективный) процесса. Чтобы использовать эти средства, Вы должны включить заглавные файлы " sys/types.h " и " unistd.h ".

       int setgid (gid_t newgid)  (функция)
Эта функция устанавливает, и реальный и эффективный ID группы процесса как newgid, если процесс имеет соответствующие привилегии.

Если процесс не привилегирован, то newgid, должен также быть равен реальному ID группы или сохраненному ID группы. В этом случае, setgid устанавливает только эффективный ID группы, а не реальный ID группы.

Возвращаемые значения и условия ошибки для setgid - такие же как для setuid.

       int setregid (gid_t rgid, fid_t egid)  (функция)
Эта функция устанавливает реальный ID группы процесса как rgid, а эффективный ID группы как egid. Если rgid -1, это означает, чтобы реальный ID группы не изменялся; аналогично, если egid -1, это означает, чтобы не изменялся эффективный ID группы.

Setregid функция предусмотрена для совместимости с 4.3 UNIX BSD, который не поддерживает сохраненные ID. Вы можете использовать эту функцию, чтобы изменять эффективный и реальный ID группы процесса. (Привилегированные процессы не ограничены этим использованием.) если сохраненные ID обеспечиваются, Вы должны использовать эту возможность вместо того, чтобы использовать эту функцию. См. раздел 25.8 [ВКЛЮЧЕНИЕ/ОТКЛЮЧЕНИЕ Setuid].

Возвращаемые значения и условия ошибки для setregid - такие же как для setreuid.

Система GNU также допускает привилегированным процессам, изменять их дополнительные ID группы. Чтобы использовать setgroups или initgroups, ваши программы должны включить заглавный файл " grp.h ". int setgroups (size_t count, gid_t *groups) (функция)

Эта функция устанавливает дополнительный ID группы процесса. Она может вызываться только из привилегированных процессов. Аргумент count определяет число ID групп в массиве groups.

Эта функция возвращает 0 в случае успеха и -1 при ошибке. Следующие errno условия ошибки определены для этой функции:

EPERM

Вызывающий процесс не привилегирован.

       int initgroups (const char *user, gid_t gid)  (функция)
Initgroups функция вызывает setgroups, чтобы установить дополнительный ID группы. ID группы gid также включен.

25.8 Предоставление и Отключение Setuid

Типичная программа setuid не нуждается в специальном доступе все время. Хорошая идея выключить этот доступ, когда он ненужен, так что она возможно не может давать непривелегированный доступ.

Если система поддерживает сохраненный пользовательский ID, Вы можете выполнить это с setuid. Когда стартует программа game, ее реальный пользовательский ID - jdoe, эффективный пользовательский ID - games, и сохраненный пользовательский ID - также games. Программа должна записать оба значения пользовательских ID один раз в начале, примерно так:

                user_user_id = getuid ();
                game_user_id = geteuid ();
Теперь она может выключить доступ к файлу game
                setuid (user_user_id);
И и включить его
                setuid (game_user_id);
Во время этого процесса, реальный пользовательский ID остается jdoe, и сохраненный пользовательский ID остается games, так что программа может всегда устанавливать эффективный пользовательский ID как любой из них.

На других системах, которые не поддерживают сохраненный пользовательский ID, Вы можете переключать доступ setuid используя setreuid, чтобы менять реального и эффективного пользователя процесса, следующим образом:

                setreuid (geteuid (), getuid ());
Этот частный случай не может терпеть неудачу.

Почему это имеет эффект переключения доступа setuid? Предположите, что программа game только что началась, и реальный пользовательский ID - jdoe, в то время как эффективный пользовательский ID - games. В этом состоянии, game может запись файл scores (очков). Если она меняет два универсальных идентификатора, реальный, становится games, а эффективный становится jdoe; теперь программа имеет только jdoe доступ. Другая перестановка приводит games обратно к эффективному пользовательскому ID и восстанавливает доступ к файлу scores.

Чтобы обрабатывать оба вида систем, проверьте сохранение пользовательского ID условным выражением препроцессора, примерно так:

                #ifdef _POSIX_SAVED_IDS
                        setuid (user_user_id);
                #else
                        setreuid (geteuid (), getuid ());
                #endif

25.9 Пример Setuid Программы

Имеется пример, показывающий, как установить программу, которая изменяет эффективный пользовательский ID.

Это - часть программы game, которая манипулирует файлом " scores " который должен быть перезаписываем только программой game непосредственно. Программа считает, что исполняемый файл будет установлен с set-user-ID набором битов и принадлежать тому же самому пользователю как " scores " файл.

Исполняемому файлу дается режим 4755, при выполнении его " ls -l " производится вывод подобно:

        -rwsr-xr-x   1 games   184422 Jul 30 15:17 caber-toss
Set-user-ID бит обнаруживается в режимах файла как " s'.

Файл scores имеет режим 644:

        -rw-r--r--  1 games         0 Jul 31 15:33 scores
Имеются части программы, которые показывают, как установить измененный пользовательский ID. Эта программа - сделана так, чтобы она использовала возможность сохранения ID, если она обеспечивается, и иначе использует setreuid, чтобы изменять эффективного и реального пользователя.
                #include <stdio.h>
                #include <sys/types.h>
                #include <unistd.h>
                #include <stdlib.h>
                static uid_t euid, ruid;
                void
                do_setuid (void)
                {
                        int status;
                #ifdef _POSIX_SAVED_IDS
                        status = setuid (euid);
                #else
                        status = setreuid (ruid, euid);
                #endif
                        if (status < 0) {
                                fprintf (stderr, "Couldn't set uid.\n");
                                exit (status);
                        }
                }
                void
                undo_setuid (void)
                {
                        int status;
                #ifdef _POSIX_SAVED_IDS
                        status = setuid (ruid);
                #else
                        status = setreuid (euid, ruid);
                #endif
                        if (status < 0) {
                                fprintf (stderr, "Couldn't set uid.\n");
                                exit (status);
                        }
                }
                int
                main (void)
                {
                        ruid = getuid ();
                        euid = geteuid ();
                        undo_setuid ();
                        . . .
                }
Когда программа должна открыть файл scores она включает обратно оригинальный эффективный пользовательский ID, примерно так:
                int
                record_score (int score)
                {
                        FILE *stream;
                        char *myname;
                        do_setuid ();
                        stream = fopen (SCORES_FILE, "a");
                        undo_setuid ();
                        if (stream)
                        {
                                myname = cuserid (NULL);
                                if (score < 0)
                                        fprintf (stream, "%10s: Couldn't        
                                        lift the caber.\n", myname);
                                else
                                        fprintf (stream, "%10s: %d              
                                feet.\n", myname, score);
                                fclose (stream);
                                return 0;
                        }
                        else
                                return -1;
                }

25.10 Советы для Написания Программы Setuid

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

25.11 Идентификация, кто Регистрируется

Вы можете использовать функции, перечисленные в этом разделе, чтобы определить имя входа в систему пользователя, который выполняет процесс, и имя пользователя, который зарегистрирован в текущем сеансе. См. также функцию getuid (см. Раздел 25.5 [Чтение Persona]).

Getlogin функция объявлена в " unistd.h ", в то время как cuserid и L_cuserid объявлены в " stdio.h ".

       char * getlogin (void)  (функция)
Getlogin функция возвращает указатель на строку, содержащую имя пользователя, зарегистрированного на терминале управления процесса, или пустой указатель, если эта информация не может быть определена. Строка статически размещена и могла бы быть записана поверх при последующих обращениях к этой функции или к cuserid.
       char * cuserid (char *string)  (функция)
Cuserid функция возвращает указатель на строку, содержащую имя пользователя, связанное с эффективным ID процесса. Если это - не пустой указатель, это должен быть массив, который может содержать по крайней мере L_cuserid символов; строка возвращается в этом массиве. Иначе, возвращается указатель на строку в статической области. Эта строка статически размещена и может быть записана поверх при последующих обращениях к этой функции или к getlogin.
       int L_cuserid  (макрос)
Целочисленная константа, которая указывает какой длины массив Вам нужен чтобы сохранить имя пользователя.

Эти функции допускают вашей программе идентифицировать положительно пользователя, кто выполняется или пользователь, кто зарегистрирован в этом сеансе. (Они могут отличиться, когда программы setuid включаются; См. Раздел 25.2 [Процесс Persona].) пользователь не может сделать ничего, чтобы ввести в заблуждение эти функции.

Для большинства целей более полезно использовать переменную среды LOGNAME, чтобы выяснить, кто пользователь. Это более гибко потому что пользователь может устанавливать LOGNAME произвольно. См. Раздел 22.2.2 [Стандартная Среда].

25.12 База данных Пользователей

Этот раздел описывает все относительно поиска и просмотра базы данных зарегистрированных пользователей. База данных непосредственно сохраняется в файле " /etc/passwd " на большинстве систем, но на некоторых системах специальный сетевой сервер дает доступ к этому.

Структура Данных, которая Описывает Пользователя

Функции и структуры данных для доступа к базе данных пользователей системы объявлены в заглавном файле " pwd.h ".

       struct passwd  (тип данных)
Passwd структуры данных используется, чтобы содержать информацию относительно входов в базу данных пользователя системы. Она имеет по крайней мере следующие элементы:
                char *pw_name
Имя входа в систему пользователя.
                char *pw_passwd.
Шифрованная строка пароля.
                uid_t pw_uid
Пользовательский ID.
                gid_t pw_gid
Значение по умолчанию ID группы.
                char *pw_gecos
Строка, обычно содержащая реальное имя пользователя, и возможно другую информацию типа номера телефона.
                char *pw_dir
Исходный каталог пользователя, или начальный рабочий каталог. Это может быть пустой указатель, когда интерпретация зависима от системы.
                char *pw_shell
Оболочка пользователя по умолчанию, или начальная выполненная программа, когда пользователь регистрируется. Это может быть пустой указатель, указывая, что должно использоваться системное значение по умолчанию.

Поиск Одного Пользователя

Вы можете искать специфического пользователя, используюя getpwuid или getpwnam. Эти функции объявлены в " pwd.h ".

       struct passwd * getpwuid (uid_t uid)  (функция)
Эта функция возвращает указатель на статически размещенную структуру, содержащую информацию относительно пользователя, чей пользовательский ID является uid. Эта структура может быть записана поверх на последующих обращениях к getpwuid.

Пустое значение указателя указывает, что не имеется никакого пользователя в базе данных с пользовательским ID uid.

       struct passwd * getpwnam (const char *name)  (функция)
Эта функция возвращает указатель на статически размещенную структуру, содержащую информацию относительно пользователя, чье имя пользователя является name. Эта структура может быть записана поверх при последующих обращениях к getpwnam.

Пустое значение указателя указывает, что не имеется никакого пользователя, именованного name.

Просмотр Списка Всех Пользователей

Этот раздел объясняет, как программа может читать список всех пользователей в системе, по одному пользователю одновременно. Функции, описанные здесь объявлены в " pwd.h ".

Вы можете использовать fgetpwent функцию для чтения входов пользователя из специфического файла.

       struct passwd * fgetpwent (FILE *stream)  (функция)
Эта функция читает следующий вход пользователя из потока и возвращает указатель на вход. Структура статически размещена и перезаписываема при последующих обращениях к fgetpwent. Вы должны копировать содержимое структуры, если Вы желаете сохранить информацию.

Этот поток должен соответствовать файлу в том же самом формате как стандартный файл базы данных паролей. Эта функция исходит из System V.

Способ просматривать все входы в базе данных пользователей - с setpwent, getpwent, и endpwent.

       void setpwent (void)  (функция)
Эта функция инициализирует поток, который getpwent использует для read базу данных пользователей.
       struct passwd * getpwent (void)  (функция)
Getpwent функция читает следующий вход из потока, инициализированного setpwent.

Она возвращает указатель на вход. Структура статически размещена и перезаписываема при последующих обращениях к getpwent. Вы должны копировать содержимое структуры, если Вы желаете сохранить информацию.

       void endpwent (void)  (функция)
Эта функция закрывает внутренний поток, используемый getpwent.

Запиись Входа Пользователя

       int putpwent (const struct passwd *p, FILE *stream)  (функция)
Эта функция записывает вход пользователя *p в указанный поток, в формате, используемом для стандартного файла базы данных пользователей. Возвращаемое значение - 0 при успехе и отличное от нуля при отказе.

Эта функция существует для совместимости с SVID. Мы рекомендуем, чтобы Вы избегали использовать ее, потому что она имеет смысл только при условии, что структура struct passwd не имеет никаких элементов за исключением стандартных; на системе, которая обьединяет традиционную базу данных UNIX с другой расширенной информацией относительно пользователей, эта функция неизбежно не учла бы многое из важной информации.

Функция putpwent объявлена в " pwd.h ".

25.13 База данных Групп

Этот раздел описывает все относительно того, как искать и просмотреть базу данных зарегистрированных групп. База данных непосредственно сохраняется в файле " /etc/group " на большинстве систем, но на некоторых системах, специальное сетевое обслуживание обеспечивает доступ к ней.

Структура Данных для Группы

Функции и структуры данных для доступа к базе данных групп системы объявлены в заглавном файле " grp.h ".

       struct group  (тип данных)
Структура group используется, чтобы содержать информацию относительно входа в базе данных групп системы. Она имеет по крайней мере следующие элементы:
                char *gr_name
Имя группы.
                gid_t gr_gid
ID группы.
                char **gr_mem
Вектор указателей на имена пользователей в группе. Каждое имя пользователя - строка с нулевым символом в конце, и вектор непосредственно завершен пустым указателем.

Поиск Одной Группы

Вы можете искать специфическую группу, используя getgrgid или getgrnam. Эти функции объявлены в " grp.h ".

       struct group * getgrgid (gid_t gid)  (функция)
Эта функция возвращает указатель на статически размещенную структуру, содержащую информацию относительно группы, чей ID группы является gid. Эта структура может быть записана поверх последующими обращениями к getgrgid.

Пустой указатель указывает, что не имеется никакой группы с ID gid.

       struct group * getgrnam (const char *name)  (функция)
Эта функция возвращает указатель на статически размещенную структуру, содержащую информацию относительно группы, чье имя группы является name. Эта структура может быть записана поверх последующими обращениями к getgrnam.

Пустой указатель указывает, что нет никакой группы, именованной name.

Просмотр Списка Всех Групп

Этот раздел объясняет, как программа может читать список всех групп в системе, по одной группе одновременно. Функции, описанные здесь объявлены в " grp.h ".

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

       struct group * fgetgrent (FILE *stream)  (функция)
Fgetgrent функция читает следующий вход из потока. Она возвращает указатель на вход. Структура статически размещена и перезаписываема при последующих обращениях к fgetgrent. Вы должны копировать содержимое структуры, если Вы желаете сохранить информацию.

Поток должен соответствовать файлу в том же самом формате как стандартный файл базы данных групп.

Способ просматривать все входы в базе данных групп - с setgrent, getgrent, и endgrent.

       void setgrent (void)  (функция)
Эта функция инициализирует поток для чтения из базы данных групп. Вы используете этот поток, вызывая getgrent.
       struct group * getgrent (void)  (функция)
Getgrent функция читает следующий вход из потока, инициализированного setgrent.

Она возвращает указатель на вход. Структура статически размещена и перезаписываема при последующих обращениях к getgrent. Вы должны копировать содержимое структуры, если Вы желаете сохранить информацию.

       void endgrent (void)  (функция)
Эта функция закрывает внутренний поток, используемый getgrent.

25.14 Пример Базы данных Пользователей и Групп

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

                #include <grp.h>
                #include <pwd.h>
                #include <sys/types.h>
                #include <unistd.h>
                #include <stdlib.h>
                int
                main (void)
                {
                        uid_t me;
                        struct passwd *my_passwd;
                        struct group *my_group;
                        char **members;
                        me = getuid ();
                        my_passwd = getpwuid (me);
                        if (!my_passwd)
                        {
                                printf ("Couldn't find out about                
                                user %d.\n", (int) me); 
                                exit (EXIT_FAILURE);
                        }
                        printf ("I am %s.\n", my_passwd->pw_gecos);
                        printf ("My login name is %s.\n",                       
                my_passwd->pw_name); 
                        printf ("My uid is %d.\n", (int)                        
                (my_passwd->pw_uid)); 
                        printf ("My home directory is %s.\n",           
                        my_passwd->pw_dir); 
                        printf ("My default shell is %s.\n",            
                        my_passwd->pw_shell);
                        my_group = getgrgid (my_passwd->pw_gid);
                        if (!my_group)
                        {
                                printf ("Couldn't find out about 
                                                group %d.\n",
                                                (int) my_passwd->pw_gid);
                                exit (EXIT_FAILURE);
                        }
                        printf ("My default group is %s (%d).\n",       
                                my_group->gr_name,                           
        (int) (my_passwd->pw_gid));
                        printf ("The members of this group are:\n");
                        members = my_group->gr_mem;
                        while (*members)
                        {
                                printf ("  %s\n", *(members)); 
                                members++;
                        }
                        return EXIT_SUCCESS;
                }
Вот некоторый вывод этой программы:
                I am Throckmorton Snurd.
                My login name is snurd.
                My uid is       31093.
                My home directory is /home/fsg/snurd.
                My default shell is /bin/sh.
                My default group is guest (12).
        The members of this group are:
                friedman
                tami


Next Previous Contents