Каждый пользователь, кто может войти в систему, идентифицирован уникальным числом называемым пользовательский ID.
Каждый процесс имеет эффективный пользовательский ID, который говорит, какие права доступа пользователя он имеет.
Пользователи классифицированы в группы для целей управления доступом. Каждый процесс имеет одно или большее количество значений ID группы, которые говорят, которую группу процесс может использовать для доступа к файлам.
Эффективные пользовательский ID и групповой ID процесса формируют persona(владельца) процесса. Он определяет, к которым файлам процесс может обращаться. Обычно, процесс наследует persona из родительского процесса, но при специальных обстоятельствах, процесс может изменять persona и таким образом изменять права доступа.
Каждый файл в системе также имеет пользовательский ID и ID группы. Управление доступом работает, сравнивая ID пользователя и группы файла с таковыми выполняющегося процесса.
Система хранит базу данных всех зарегистрированных пользователей, и другую базу данных всех определенных групп. Имеются библиотечные функции, которые Вы можете использовать, чтобы исследовать эти базы данных.
Каждый пользователь компьютерной системы идентифицирован именем пользователя (или именем входа в систему) и пользовательским ID. Обычно, каждое имя пользователя имеет уникальный пользовательский ID, но возможно для отдельных имен входа в систему, иметь тот же самый пользовательский ID. Пользовательские имена и соответствующий пользовательский IDS сохранены в базе данных, к которой Вы можете обращаться как описано в Разделе 25.12 [База Данных Пользователей].
Пользователи классифицированы на группы. Каждое имя пользователя также принадлежит одной или большему количеству групп, и имеет одну заданную по умолчанию группу. Пользователи - элементы той же самой группы, могут совместно использовать ресурсы (типы файлов) которые не доступны для пользователей - не элементов этой группы. Каждая группа имеет имя группы и ID группы. См. Раздел 25.13 [База Данных Групп], для того, как найти информацию относительно ID группы или имени группы.
В любое время, каждый процесс имеет отдельный пользовательский ID и ID группы, которые определяют привилегии процесса. Они коллективно называются persona процесса, потому что они определяют " кто это " для целей управления доступом. Эти ID также называются эффективным пользовательским ID и эффективным ID группы процесса.
Ваша оболочка входа в систему начинается с persona, который состоит из вашего пользовательского ID и вашего значения ID группы по умолчанию. В нормальных обстоятельствах, все ваши другие процессы наследуют эти значения.
Процесс также имеет реальный пользовательский ID, который идентифицирует пользователя, который создал процесс, и реальный ID группы, который идентифицирует заданную по умолчанию группу этого пользователя. Эти значения не играют роль в управлении доступом, так что мы не рассматриваем их частью persona. Но они - также важны.
И реальный и эффективный пользовательский ID может быть изменен в течение срока службы процесса. См. Раздел 25.3 [Почему Изменяется Persona].
Кроме того, пользователь может принадлежать многим группам, так что persona включает дополнительные ID группы, которые также относятся к правам.
Пользовательский ID процесса также управляет правами для посылки сигналов, используя функцию kill. См. Раздел 21.6.2 [Передача сигналов Другому Процессу].
Наиболее очевидная ситуация, когда процессу необходимо изменить пользователя и/или ID группы - программа входа в систему. Когда вход в систему начинает выполняться, пользовательский ID корневой. Работа должна начать оболочку, чей ID пользователя и группы являются таковыми регистрируемого пользователя. (Чтобы выполнять это полностью, вход в систему должен установить реальный ID пользователя и группы также как persona. Но это - частный случай.)
Более общий случай изменения persona - когда обычный пользователь программирует потребности доступа к ресурсу, который обычно не доступен для пользователя, фактически выполняющего это.
Например, Вы можете иметь файл, который управляется вашей программой, но он не должен читаться или изменяться непосредственно другими пользователями, потому что он осуществляет некоторый протокол блокировки, или потому что Вы хотите сохранять целостность или секретность информации, которую он содержит. Этот вид ограниченного доступа может быть выполнен при наличии программы, изменяющей эффективного пользователя или ID группы соответствующего таковому ресурса.
Таким образом, вообразите готовую программу, которая сохраняет очки в файле. Готовая программа непосредственно должна быть способной модифицировать этот файл независимо из того, кто выполняет ее, но если пользователи могут записывать в файл без того, чтобы пройти игру, они могут давать себе любое количество очков, которое они находят приятным. Некоторые люди рассматривают этот нежелательным, или даже предосудительным. Это может быть предотвращено, созданием нового пользовательского ID и имени входа в систему (напр. games) чтобы обладать файлом, и сделать файл перезаписываемым только этим пользователем. Когда готовая программа хочет модифицировать этот файл, она может изменять эффективный пользовательский ID на games. В действительности, программа должна принять persona games, чтобы она могла писать в этот файл.
Способность изменять persona процесса может быть источником ненамеренных нарушений секретности, или даже намеренного неправильного обращения. Из-за потенциальных проблем, замена persona ограничена специальными обстоятельствами.
Вы не можете произвольно устанавливать ваш пользовательский ID или ID группы; только привилегированные процессы могут делать это. Взамен, нормальный способ для программы, чтобы изменить persona состоит в том, чтобы было установлено заранее соглашение изменения специфического пользователя или группы. Это делают функции setuid и setgid битов режима доступа файла. См. Раздел 9.8.5 [Биты Прав].
Когда setuid бит исполняемого файла установлен, выполнение этого файла автоматически изменяет эффективный пользовательский ID на пользователя, который обладает файлом. Аналогично, при выполнении файла, чей setgid бит установлен изменяется эффективный ID группы на группу файла. См. Раздел 23.5 [Выполнение Файла]. Создание файла, который изменяется к специфическому ID пользователz или ID группы таким образом, требует полного доступа к этому пользователю или группе.
См. Раздел 9.8 [Атрибуты Файла], для более общего обсуждения режимов файла и достижимости.
Процесс может всегда изменять эффективный пользовательский (или групповой) ID обратно реальному ID. Программы делают это, чтобы выключить их специальные привилегии, когда они ненужны, что делается для большей ошибкоустойчивости.
Имеются детализированные описания функций для чтения ID пользователя и группы процесса, и реального и эффективного. Чтобы использовать эти средства, Вы должны включить заглавные файлы " sys/types.h " и " unistd.h ".
Это - целочисленный тип данных, используемый, чтобы представить пользовательский ID. В библиотеке GNU, это - побочный результат исследования для unsigned int.uid_t (тип данных)
Это - целочисленный тип данных, используемый, чтобы представить ID группы. В библиотеке GNU, это - побочный результат исследования для unsigned int.gid_t (тип данных)
Getuid функция возвращает реальный пользовательский ID процесса.uid_t getuid (void) (функция)
Getgid функция возвращает реальный ID группы процесса.gid_t getgid (void) (функция)
Geteuid функция возвращает эффективный пользовательский ID процесса.uid_t geteuid (void) (функция)
Getegid функция возвращает эффективный ID группы процесса.gid_t getegid (void) (функция)
Getgroups функция используется, чтобы запросить относительно ID дополнительные группы процесса. До count этих ID групп сохранено в массиве groups; возвращаемое значение из функции - число групп, фактически сохраненных. Если count меньше чем общее число дополнительных групп, то getgroups возвращает значение -1, и errno установлена как EINVAL.int getgroups (int count, gid_t *groups) (функция)
Если 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; }
Этот раздел описывает функции для изменения пользовательского ID (реального и/или эффективного) процесса.
Чтобы использовать эти средства, Вы должны включить заглавные файлы " sys/types.h " и " unistd.h ".
Эта функция устанавливает, и реальный и эффективный пользовательский ID процесса как newuid, если процесс имеет соответствующие привилегии.int setuid (uid_t newuid) (функция)
Если процесс не привилегирован, то newuid, должен быть равен реальному пользовательскому ID или сохраненному пользовательскому ID (если система поддерживает возможность _POSIX_SAVED_IDS). В этом случае, setuid устанавливает только эффективный пользовательский ID, а не реальный пользовательский ID.
Setuid функция возвращает значение 0, чтобы указать успешное завершение, и значение -1, чтобы указать ошибку. Следующие errno условия ошибки определены для этой функции:
Значение newuid аргумента недопустимо.
Процесс не имеет соответствующих привилегий.
Эта функция устанавливает реальный пользовательский ID процесса как ruid и эффективный пользовательский ID как euid. Если ruid -1, это означает, что реальный пользовательский ID не изменился; аналогично, если euid -1, это означает, чтобы не изменился эффективный пользовательский ID.int setreuid (uid_t ruid, uid_t euid) (функция)
Setreuid функция существует для совместимости с 4.3 UNIX BSD, который не поддерживает сохранение ID. Вы можете использовать эту функцию, чтобы изменять эффективного и реального пользователя процесса. (Привилегированные процессы не ограничены этим специфическим использованием.) если сохраненный ID обеспечивается, Вы должны использовать эту возможность вместо этой функции. См. раздел 25.8 [ВКЛЮЧЕНИЕ/ОТКЛЮЧЕНИЕ Setuid].
Возвращаемое значение - 0 при успехе и -1 при отказе. Следующие errno условия ошибки определены для этой функции:
Процесс не имеет соответствующих привилегий; Вы не имеете прав изменить на заданный ID.
Этот раздел описывает функции для изменения ID группы (реальный и эффективный) процесса. Чтобы использовать эти средства, Вы должны включить заглавные файлы " sys/types.h " и " unistd.h ".
Эта функция устанавливает, и реальный и эффективный ID группы процесса как newgid, если процесс имеет соответствующие привилегии.int setgid (gid_t newgid) (функция)
Если процесс не привилегирован, то newgid, должен также быть равен реальному ID группы или сохраненному ID группы. В этом случае, setgid устанавливает только эффективный ID группы, а не реальный ID группы.
Возвращаемые значения и условия ошибки для setgid - такие же как для setuid.
Эта функция устанавливает реальный ID группы процесса как rgid, а эффективный ID группы как egid. Если rgid -1, это означает, чтобы реальный ID группы не изменялся; аналогично, если egid -1, это означает, чтобы не изменялся эффективный ID группы.int setregid (gid_t rgid, fid_t egid) (функция)
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 условия ошибки определены для этой функции:
Вызывающий процесс не привилегирован.
Initgroups функция вызывает setgroups, чтобы установить дополнительный ID группы. ID группы gid также включен.int initgroups (const char *user, gid_t gid) (функция)
Типичная программа setuid не нуждается в специальном доступе все время. Хорошая идея выключить этот доступ, когда он ненужен, так что она возможно не может давать непривелегированный доступ.
Если система поддерживает сохраненный пользовательский ID, Вы можете выполнить это с setuid. Когда стартует программа game, ее реальный пользовательский ID - jdoe, эффективный пользовательский ID - games, и сохраненный пользовательский ID - также games. Программа должна записать оба значения пользовательских ID один раз в начале, примерно так:
Теперь она может выключить доступ к файлу gameuser_user_id = getuid (); game_user_id = geteuid ();
И и включить егоsetuid (user_user_id);
Во время этого процесса, реальный пользовательский ID остается jdoe, и сохраненный пользовательский ID остается games, так что программа может всегда устанавливать эффективный пользовательский ID как любой из них.setuid (game_user_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
Имеется пример, показывающий, как установить программу, которая изменяет эффективный пользовательский ID.
Это - часть программы game, которая манипулирует файлом " scores " который должен быть перезаписываем только программой game непосредственно. Программа считает, что исполняемый файл будет установлен с set-user-ID набором битов и принадлежать тому же самому пользователю как " scores " файл.
Исполняемому файлу дается режим 4755, при выполнении его " ls -l " производится вывод подобно:
Set-user-ID бит обнаруживается в режимах файла как " s'.-rwsr-xr-x 1 games 184422 Jul 30 15:17 caber-toss
Файл scores имеет режим 644:
Имеются части программы, которые показывают, как установить измененный пользовательский ID. Эта программа - сделана так, чтобы она использовала возможность сохранения ID, если она обеспечивается, и иначе использует setreuid, чтобы изменять эффективного и реального пользователя.-rw-r--r-- 1 games 0 Jul 31 15:33 scores
Когда программа должна открыть файл scores она включает обратно оригинальный эффективный пользовательский ID, примерно так:#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 (); . . . }
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; }
Для программ setuid возможно дать доступ пользователю, который не предусмотрен фактически, если Вы хотите избежать этого, Вы должны быть внимательны. Имеются некоторые руководящие принципы для предотвращения непредназначенного доступа и уменьшения следствий, когда он происходит:
Вы можете использовать функции, перечисленные в этом разделе, чтобы определить имя входа в систему пользователя, который выполняет процесс, и имя пользователя, который зарегистрирован в текущем сеансе. См. также функцию getuid (см. Раздел 25.5 [Чтение Persona]).
Getlogin функция объявлена в " unistd.h ", в то время как cuserid и L_cuserid объявлены в " stdio.h ".
Getlogin функция возвращает указатель на строку, содержащую имя пользователя, зарегистрированного на терминале управления процесса, или пустой указатель, если эта информация не может быть определена. Строка статически размещена и могла бы быть записана поверх при последующих обращениях к этой функции или к cuserid.char * getlogin (void) (функция)
Cuserid функция возвращает указатель на строку, содержащую имя пользователя, связанное с эффективным ID процесса. Если это - не пустой указатель, это должен быть массив, который может содержать по крайней мере L_cuserid символов; строка возвращается в этом массиве. Иначе, возвращается указатель на строку в статической области. Эта строка статически размещена и может быть записана поверх при последующих обращениях к этой функции или к getlogin.char * cuserid (char *string) (функция)
Целочисленная константа, которая указывает какой длины массив Вам нужен чтобы сохранить имя пользователя.int L_cuserid (макрос)
Эти функции допускают вашей программе идентифицировать положительно пользователя, кто выполняется или пользователь, кто зарегистрирован в этом сеансе. (Они могут отличиться, когда программы setuid включаются; См. Раздел 25.2 [Процесс Persona].) пользователь не может сделать ничего, чтобы ввести в заблуждение эти функции.
Для большинства целей более полезно использовать переменную среды LOGNAME, чтобы выяснить, кто пользователь. Это более гибко потому что пользователь может устанавливать LOGNAME произвольно. См. Раздел 22.2.2 [Стандартная Среда].
Этот раздел описывает все относительно поиска и просмотра базы данных зарегистрированных пользователей. База данных непосредственно сохраняется в файле " /etc/passwd " на большинстве систем, но на некоторых системах специальный сетевой сервер дает доступ к этому.
Функции и структуры данных для доступа к базе данных пользователей системы объявлены в заглавном файле " pwd.h ".
Passwd структуры данных используется, чтобы содержать информацию относительно входов в базу данных пользователя системы. Она имеет по крайней мере следующие элементы:struct passwd (тип данных)
Имя входа в систему пользователя.char *pw_name
Шифрованная строка пароля.char *pw_passwd.
Пользовательский ID.uid_t pw_uid
Значение по умолчанию ID группы.gid_t pw_gid
Строка, обычно содержащая реальное имя пользователя, и возможно другую информацию типа номера телефона.char *pw_gecos
Исходный каталог пользователя, или начальный рабочий каталог. Это может быть пустой указатель, когда интерпретация зависима от системы.char *pw_dir
Оболочка пользователя по умолчанию, или начальная выполненная программа, когда пользователь регистрируется. Это может быть пустой указатель, указывая, что должно использоваться системное значение по умолчанию.char *pw_shell
Вы можете искать специфического пользователя, используюя getpwuid или getpwnam. Эти функции объявлены в " pwd.h ".
Эта функция возвращает указатель на статически размещенную структуру, содержащую информацию относительно пользователя, чей пользовательский ID является uid. Эта структура может быть записана поверх на последующих обращениях к getpwuid.struct passwd * getpwuid (uid_t uid) (функция)
Пустое значение указателя указывает, что не имеется никакого пользователя в базе данных с пользовательским ID uid.
Эта функция возвращает указатель на статически размещенную структуру, содержащую информацию относительно пользователя, чье имя пользователя является name. Эта структура может быть записана поверх при последующих обращениях к getpwnam.struct passwd * getpwnam (const char *name) (функция)
Пустое значение указателя указывает, что не имеется никакого пользователя, именованного name.
Этот раздел объясняет, как программа может читать список всех пользователей в системе, по одному пользователю одновременно. Функции, описанные здесь объявлены в " pwd.h ".
Вы можете использовать fgetpwent функцию для чтения входов пользователя из специфического файла.
Эта функция читает следующий вход пользователя из потока и возвращает указатель на вход. Структура статически размещена и перезаписываема при последующих обращениях к fgetpwent. Вы должны копировать содержимое структуры, если Вы желаете сохранить информацию.struct passwd * fgetpwent (FILE *stream) (функция)
Этот поток должен соответствовать файлу в том же самом формате как стандартный файл базы данных паролей. Эта функция исходит из System V.
Способ просматривать все входы в базе данных пользователей - с setpwent, getpwent, и endpwent.
Эта функция инициализирует поток, который getpwent использует для read базу данных пользователей.void setpwent (void) (функция)
Getpwent функция читает следующий вход из потока, инициализированного setpwent.struct passwd * getpwent (void) (функция)
Она возвращает указатель на вход. Структура статически размещена и перезаписываема при последующих обращениях к getpwent. Вы должны копировать содержимое структуры, если Вы желаете сохранить информацию.
Эта функция закрывает внутренний поток, используемый getpwent.void endpwent (void) (функция)
Эта функция записывает вход пользователя *p в указанный поток, в формате, используемом для стандартного файла базы данных пользователей. Возвращаемое значение - 0 при успехе и отличное от нуля при отказе.int putpwent (const struct passwd *p, FILE *stream) (функция)
Эта функция существует для совместимости с SVID. Мы рекомендуем, чтобы Вы избегали использовать ее, потому что она имеет смысл только при условии, что структура struct passwd не имеет никаких элементов за исключением стандартных; на системе, которая обьединяет традиционную базу данных UNIX с другой расширенной информацией относительно пользователей, эта функция неизбежно не учла бы многое из важной информации.
Функция putpwent объявлена в " pwd.h ".
Этот раздел описывает все относительно того, как искать и просмотреть базу данных зарегистрированных групп. База данных непосредственно сохраняется в файле " /etc/group " на большинстве систем, но на некоторых системах, специальное сетевое обслуживание обеспечивает доступ к ней.
Функции и структуры данных для доступа к базе данных групп системы объявлены в заглавном файле " grp.h ".
Структура group используется, чтобы содержать информацию относительно входа в базе данных групп системы. Она имеет по крайней мере следующие элементы:struct group (тип данных)
Имя группы.char *gr_name
ID группы.gid_t gr_gid
Вектор указателей на имена пользователей в группе. Каждое имя пользователя - строка с нулевым символом в конце, и вектор непосредственно завершен пустым указателем.char **gr_mem
Вы можете искать специфическую группу, используя getgrgid или getgrnam. Эти функции объявлены в " grp.h ".
Эта функция возвращает указатель на статически размещенную структуру, содержащую информацию относительно группы, чей ID группы является gid. Эта структура может быть записана поверх последующими обращениями к getgrgid.struct group * getgrgid (gid_t gid) (функция)
Пустой указатель указывает, что не имеется никакой группы с ID gid.
Эта функция возвращает указатель на статически размещенную структуру, содержащую информацию относительно группы, чье имя группы является name. Эта структура может быть записана поверх последующими обращениями к getgrnam.struct group * getgrnam (const char *name) (функция)
Пустой указатель указывает, что нет никакой группы, именованной name.
Этот раздел объясняет, как программа может читать список всех групп в системе, по одной группе одновременно. Функции, описанные здесь объявлены в " grp.h ".
Вы можете использовать fgetgrent функцию, чтобы читать входы группы из специфического файла.
Fgetgrent функция читает следующий вход из потока. Она возвращает указатель на вход. Структура статически размещена и перезаписываема при последующих обращениях к fgetgrent. Вы должны копировать содержимое структуры, если Вы желаете сохранить информацию.struct group * fgetgrent (FILE *stream) (функция)
Поток должен соответствовать файлу в том же самом формате как стандартный файл базы данных групп.
Способ просматривать все входы в базе данных групп - с setgrent, getgrent, и endgrent.
Эта функция инициализирует поток для чтения из базы данных групп. Вы используете этот поток, вызывая getgrent.void setgrent (void) (функция)
Getgrent функция читает следующий вход из потока, инициализированного setgrent.struct group * getgrent (void) (функция)
Она возвращает указатель на вход. Структура статически размещена и перезаписываема при последующих обращениях к getgrent. Вы должны копировать содержимое структуры, если Вы желаете сохранить информацию.
Эта функция закрывает внутренний поток, используемый getgrent.void endgrent (void) (функция)
Вот пример программы, показывающий использование функций запроса базы данных системы. Программа печатает некоторую информацию относительно пользователя, выполняющего программу.
Вот некоторый вывод этой программы:#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