summaryrefslogtreecommitdiff
path: root/manual/users.texi
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1995-02-18 01:27:10 +0000
committerRoland McGrath <roland@gnu.org>1995-02-18 01:27:10 +0000
commit28f540f45bbacd939bfd07f213bcad2bf730b1bf (patch)
tree15f07c4c43d635959c6afee96bde71fb1b3614ee /manual/users.texi
downloadglibc-28f540f45bbacd939bfd07f213bcad2bf730b1bf.tar.gz
initial import
Diffstat (limited to 'manual/users.texi')
-rw-r--r--manual/users.texi1012
1 files changed, 1012 insertions, 0 deletions
diff --git a/manual/users.texi b/manual/users.texi
new file mode 100644
index 0000000000..c35e8b6a5b
--- /dev/null
+++ b/manual/users.texi
@@ -0,0 +1,1012 @@
+@node Users and Groups, System Information, Job Control, Top
+@chapter Users and Groups
+
+Every user who can log in on the system is identified by a unique number
+called the @dfn{user ID}. Each process has an effective user ID which
+says which user's access permissions it has.
+
+Users are classified into @dfn{groups} for access control purposes. Each
+process has one or more @dfn{group ID values} which say which groups the
+process can use for access to files.
+
+The effective user and group IDs of a process collectively form its
+@dfn{persona}. This determines which files the process can access.
+Normally, a process inherits its persona from the parent process, but
+under special circumstances a process can change its persona and thus
+change its access permissions.
+
+Each file in the system also has a user ID and a group ID. Access
+control works by comparing the user and group IDs of the file with those
+of the running process.
+
+The system keeps a database of all the registered users, and another
+database of all the defined groups. There are library functions you
+can use to examine these databases.
+
+@menu
+* User and Group IDs:: Each user has a unique numeric ID;
+ likewise for groups.
+* Process Persona:: The user IDs and group IDs of a process.
+* Why Change Persona:: Why a program might need to change
+ its user and/or group IDs.
+* How Change Persona:: Changing the user and group IDs.
+* Reading Persona:: How to examine the user and group IDs.
+
+* Setting User ID:: Functions for setting the user ID.
+* Setting Groups:: Functions for setting the group IDs.
+
+* Enable/Disable Setuid:: Turning setuid access on and off.
+* Setuid Program Example:: The pertinent parts of one sample program.
+* Tips for Setuid:: How to avoid granting unlimited access.
+
+* Who Logged In:: Getting the name of the user who logged in,
+ or of the real user ID of the current process.
+
+* User Database:: Functions and data structures for
+ accessing the user database.
+* Group Database:: Functions and data structures for
+ accessing the group database.
+* Database Example:: Example program showing use of database
+ inquiry functions.
+@end menu
+
+@node User and Group IDs
+@section User and Group IDs
+
+@cindex login name
+@cindex user name
+@cindex user ID
+Each user account on a computer system is identified by a @dfn{user
+name} (or @dfn{login name}) and @dfn{user ID}. Normally, each user name
+has a unique user ID, but it is possible for several login names to have
+the same user ID. The user names and corresponding user IDs are stored
+in a data base which you can access as described in @ref{User Database}.
+
+@cindex group name
+@cindex group ID
+Users are classified in @dfn{groups}. Each user name also belongs to
+one or more groups, and has one @dfn{default group}. Users who are
+members of the same group can share resources (such as files) that are
+not accessible to users who are not a member of that group. Each group
+has a @dfn{group name} and @dfn{group ID}. @xref{Group Database},
+for how to find information about a group ID or group name.
+
+@node Process Persona
+@section The Persona of a Process
+@cindex persona
+@cindex effective user ID
+@cindex effective group ID
+
+@c !!! bogus; not single ID. set of effective group IDs (and, in GNU,
+@c set of effective UIDs) determines privilege. lying here and then
+@c telling the truth below is confusing.
+At any time, each process has a single user ID and a group ID which
+determine the privileges of the process. These are collectively called
+the @dfn{persona} of the process, because they determine ``who it is''
+for purposes of access control. These IDs are also called the
+@dfn{effective user ID} and @dfn{effective group ID} of the process.
+
+Your login shell starts out with a persona which consists of your user
+ID and your default group ID.
+@c !!! also supplementary group IDs.
+In normal circumstances, all your other processes inherit these values.
+
+@cindex real user ID
+@cindex real group ID
+A process also has a @dfn{real user ID} which identifies the user who
+created the process, and a @dfn{real group ID} which identifies that
+user's default group. These values do not play a role in access
+control, so we do not consider them part of the persona. But they are
+also important.
+
+Both the real and effective user ID can be changed during the lifetime
+of a process. @xref{Why Change Persona}.
+
+@cindex supplementary group IDs
+In addition, a user can belong to multiple groups, so the persona
+includes @dfn{supplementary group IDs} that also contribute to access
+permission.
+
+For details on how a process's effective user IDs and group IDs affect
+its permission to access files, see @ref{Access Permission}.
+
+The user ID of a process also controls permissions for sending signals
+using the @code{kill} function. @xref{Signaling Another Process}.
+
+@node Why Change Persona
+@section Why Change the Persona of a Process?
+
+The most obvious situation where it is necessary for a process to change
+its user and/or group IDs is the @code{login} program. When
+@code{login} starts running, its user ID is @code{root}. Its job is to
+start a shell whose user and group IDs are those of the user who is
+logging in. (To accomplish this fully, @code{login} must set the real
+user and group IDs as well as its persona. But this is a special case.)
+
+The more common case of changing persona is when an ordinary user
+program needs access to a resource that wouldn't ordinarily be
+accessible to the user actually running it.
+
+For example, you may have a file that is controlled by your program but
+that shouldn't be read or modified directly by other users, either
+because it implements some kind of locking protocol, or because you want
+to preserve the integrity or privacy of the information it contains.
+This kind of restricted access can be implemented by having the program
+change its effective user or group ID to match that of the resource.
+
+Thus, imagine a game program that saves scores in a file. The game
+program itself needs to be able to update this file no matter who is
+running it, but if users can write the file without going through the
+game, they can give themselves any scores they like. Some people
+consider this undesirable, or even reprehensible. It can be prevented
+by creating a new user ID and login name (say, @code{games}) to own the
+scores file, and make the file writable only by this user. Then, when
+the game program wants to update this file, it can change its effective
+user ID to be that for @code{games}. In effect, the program must
+adopt the persona of @code{games} so it can write the scores file.
+
+@node How Change Persona
+@section How an Application Can Change Persona
+@cindex @code{setuid} programs
+
+The ability to change the persona of a process can be a source of
+unintentional privacy violations, or even intentional abuse. Because of
+the potential for problems, changing persona is restricted to special
+circumstances.
+
+You can't arbitrarily set your user ID or group ID to anything you want;
+only privileged processes can do that. Instead, the normal way for a
+program to change its persona is that it has been set up in advance to
+change to a particular user or group. This is the function of the setuid
+and setgid bits of a file's access mode. @xref{Permission Bits}.
+
+When the setuid bit of an executable file is set, executing that file
+automatically changes the effective user ID to the user that owns the
+file. Likewise, executing a file whose setgid bit is set changes the
+effective group ID to the group of the file. @xref{Executing a File}.
+Creating a file that changes to a particular user or group ID thus
+requires full access to that user or group ID.
+
+@xref{File Attributes}, for a more general discussion of file modes and
+accessibility.
+
+A process can always change its effective user (or group) ID back to its
+real ID. Programs do this so as to turn off their special privileges
+when they are not needed, which makes for more robustness.
+
+@c !!! talk about _POSIX_SAVED_IDS
+
+@node Reading Persona
+@section Reading the Persona of a Process
+
+Here are detailed descriptions of the functions for reading the user and
+group IDs of a process, both real and effective. To use these
+facilities, you must include the header files @file{sys/types.h} and
+@file{unistd.h}.
+@pindex unistd.h
+@pindex sys/types.h
+
+@comment sys/types.h
+@comment POSIX.1
+@deftp {Data Type} uid_t
+This is an integer data type used to represent user IDs. In the GNU
+library, this is an alias for @code{unsigned int}.
+@end deftp
+
+@comment sys/types.h
+@comment POSIX.1
+@deftp {Data Type} gid_t
+This is an integer data type used to represent group IDs. In the GNU
+library, this is an alias for @code{unsigned int}.
+@end deftp
+
+@comment unistd.h
+@comment POSIX.1
+@deftypefun uid_t getuid (void)
+The @code{getuid} function returns the real user ID of the process.
+@end deftypefun
+
+@comment unistd.h
+@comment POSIX.1
+@deftypefun gid_t getgid (void)
+The @code{getgid} function returns the real group ID of the process.
+@end deftypefun
+
+@comment unistd.h
+@comment POSIX.1
+@deftypefun uid_t geteuid (void)
+The @code{geteuid} function returns the effective user ID of the process.
+@end deftypefun
+
+@comment unistd.h
+@comment POSIX.1
+@deftypefun gid_t getegid (void)
+The @code{getegid} function returns the effective group ID of the process.
+@end deftypefun
+
+@comment unistd.h
+@comment POSIX.1
+@deftypefun int getgroups (int @var{count}, gid_t *@var{groups})
+The @code{getgroups} function is used to inquire about the supplementary
+group IDs of the process. Up to @var{count} of these group IDs are
+stored in the array @var{groups}; the return value from the function is
+the number of group IDs actually stored. If @var{count} is smaller than
+the total number of supplementary group IDs, then @code{getgroups}
+returns a value of @code{-1} and @code{errno} is set to @code{EINVAL}.
+
+If @var{count} is zero, then @code{getgroups} just returns the total
+number of supplementary group IDs. On systems that do not support
+supplementary groups, this will always be zero.
+
+Here's how to use @code{getgroups} to read all the supplementary group
+IDs:
+
+@smallexample
+@group
+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;
+@}
+@end group
+@end smallexample
+@end deftypefun
+
+@node Setting User ID
+@section Setting the User ID
+
+This section describes the functions for altering the user ID (real
+and/or effective) of a process. To use these facilities, you must
+include the header files @file{sys/types.h} and @file{unistd.h}.
+@pindex unistd.h
+@pindex sys/types.h
+
+@comment unistd.h
+@comment POSIX.1
+@deftypefun int setuid (uid_t @var{newuid})
+This function sets both the real and effective user ID of the process
+to @var{newuid}, provided that the process has appropriate privileges.
+@c !!! also sets saved-id
+
+If the process is not privileged, then @var{newuid} must either be equal
+to the real user ID or the saved user ID (if the system supports the
+@code{_POSIX_SAVED_IDS} feature). In this case, @code{setuid} sets only
+the effective user ID and not the real user ID.
+@c !!! xref to discussion of _POSIX_SAVED_IDS
+
+The @code{setuid} function returns a value of @code{0} to indicate
+successful completion, and a value of @code{-1} to indicate an error.
+The following @code{errno} error conditions are defined for this
+function:
+
+@table @code
+@item EINVAL
+The value of the @var{newuid} argument is invalid.
+
+@item EPERM
+The process does not have the appropriate privileges; you do not
+have permission to change to the specified ID.
+@end table
+@end deftypefun
+
+@comment unistd.h
+@comment BSD
+@deftypefun int setreuid (uid_t @var{ruid}, uid_t @var{euid})
+This function sets the real user ID of the process to @var{ruid} and the
+effective user ID to @var{euid}. If @var{ruid} is @code{-1}, it means
+not to change the real user ID; likewise if @var{euid} is @code{-1}, it
+means not to change the effective user ID.
+
+The @code{setreuid} function exists for compatibility with 4.3 BSD Unix,
+which does not support saved IDs. You can use this function to swap the
+effective and real user IDs of the process. (Privileged processes are
+not limited to this particular usage.) If saved IDs are supported, you
+should use that feature instead of this function. @xref{Enable/Disable
+Setuid}.
+
+The return value is @code{0} on success and @code{-1} on failure.
+The following @code{errno} error conditions are defined for this
+function:
+
+@table @code
+@item EPERM
+The process does not have the appropriate privileges; you do not
+have permission to change to the specified ID.
+@end table
+@end deftypefun
+
+@node Setting Groups
+@section Setting the Group IDs
+
+This section describes the functions for altering the group IDs (real
+and effective) of a process. To use these facilities, you must include
+the header files @file{sys/types.h} and @file{unistd.h}.
+@pindex unistd.h
+@pindex sys/types.h
+
+@comment unistd.h
+@comment POSIX.1
+@deftypefun int setgid (gid_t @var{newgid})
+This function sets both the real and effective group ID of the process
+to @var{newgid}, provided that the process has appropriate privileges.
+@c !!! also sets saved-id
+
+If the process is not privileged, then @var{newgid} must either be equal
+to the real group ID or the saved group ID. In this case, @code{setgid}
+sets only the effective group ID and not the real group ID.
+
+The return values and error conditions for @code{setgid} are the same
+as those for @code{setuid}.
+@end deftypefun
+
+@comment unistd.h
+@comment BSD
+@deftypefun int setregid (gid_t @var{rgid}, fid_t @var{egid})
+This function sets the real group ID of the process to @var{rgid} and
+the effective group ID to @var{egid}. If @var{rgid} is @code{-1}, it
+means not to change the real group ID; likewise if @var{egid} is
+@code{-1}, it means not to change the effective group ID.
+
+The @code{setregid} function is provided for compatibility with 4.3 BSD
+Unix, which does not support saved IDs. You can use this function to
+swap the effective and real group IDs of the process. (Privileged
+processes are not limited to this usage.) If saved IDs are supported,
+you should use that feature instead of using this function.
+@xref{Enable/Disable Setuid}.
+
+The return values and error conditions for @code{setregid} are the same
+as those for @code{setreuid}.
+@end deftypefun
+
+The GNU system also lets privileged processes change their supplementary
+group IDs. To use @code{setgroups} or @code{initgroups}, your programs
+should include the header file @file{grp.h}.
+@pindex grp.h
+
+@comment grp.h
+@comment BSD
+@deftypefun int setgroups (size_t @var{count}, gid_t *@var{groups})
+This function sets the process's supplementary group IDs. It can only
+be called from privileged processes. The @var{count} argument specifies
+the number of group IDs in the array @var{groups}.
+
+This function returns @code{0} if successful and @code{-1} on error.
+The following @code{errno} error conditions are defined for this
+function:
+
+@table @code
+@item EPERM
+The calling process is not privileged.
+@end table
+@end deftypefun
+
+@comment grp.h
+@comment BSD
+@deftypefun int initgroups (const char *@var{user}, gid_t @var{gid})
+The @code{initgroups} function effectively calls @code{setgroups} to
+set the process's supplementary group IDs to be the normal default for
+the user name @var{user}. The group ID @var{gid} is also included.
+@c !!! explain that this works by reading the group file looking for
+@c groups USER is a member of.
+@end deftypefun
+
+@node Enable/Disable Setuid
+@section Enabling and Disabling Setuid Access
+
+A typical setuid program does not need its special access all of the
+time. It's a good idea to turn off this access when it isn't needed,
+so it can't possibly give unintended access.
+
+If the system supports the saved user ID feature, you can accomplish
+this with @code{setuid}. When the game program starts, its real user ID
+is @code{jdoe}, its effective user ID is @code{games}, and its saved
+user ID is also @code{games}. The program should record both user ID
+values once at the beginning, like this:
+
+@smallexample
+user_user_id = getuid ();
+game_user_id = geteuid ();
+@end smallexample
+
+Then it can turn off game file access with
+
+@smallexample
+setuid (user_user_id);
+@end smallexample
+
+@noindent
+and turn it on with
+
+@smallexample
+setuid (game_user_id);
+@end smallexample
+
+@noindent
+Throughout this process, the real user ID remains @code{jdoe} and the
+saved user ID remains @code{games}, so the program can always set its
+effective user ID to either one.
+
+On other systems that don't support the saved user ID feature, you can
+turn setuid access on and off by using @code{setreuid} to swap the real
+and effective user IDs of the process, as follows:
+
+@smallexample
+setreuid (geteuid (), getuid ());
+@end smallexample
+
+@noindent
+This special case is always allowed---it cannot fail.
+
+Why does this have the effect of toggling the setuid access? Suppose a
+game program has just started, and its real user ID is @code{jdoe} while
+its effective user ID is @code{games}. In this state, the game can
+write the scores file. If it swaps the two uids, the real becomes
+@code{games} and the effective becomes @code{jdoe}; now the program has
+only @code{jdoe} access. Another swap brings @code{games} back to
+the effective user ID and restores access to the scores file.
+
+In order to handle both kinds of systems, test for the saved user ID
+feature with a preprocessor conditional, like this:
+
+@smallexample
+#ifdef _POSIX_SAVED_IDS
+ setuid (user_user_id);
+#else
+ setreuid (geteuid (), getuid ());
+#endif
+@end smallexample
+
+@node Setuid Program Example
+@section Setuid Program Example
+
+Here's an example showing how to set up a program that changes its
+effective user ID.
+
+This is part of a game program called @code{caber-toss} that
+manipulates a file @file{scores} that should be writable only by the game
+program itself. The program assumes that its executable
+file will be installed with the set-user-ID bit set and owned by the
+same user as the @file{scores} file. Typically, a system
+administrator will set up an account like @code{games} for this purpose.
+
+The executable file is given mode @code{4755}, so that doing an
+@samp{ls -l} on it produces output like:
+
+@smallexample
+-rwsr-xr-x 1 games 184422 Jul 30 15:17 caber-toss
+@end smallexample
+
+@noindent
+The set-user-ID bit shows up in the file modes as the @samp{s}.
+
+The scores file is given mode @code{644}, and doing an @samp{ls -l} on
+it shows:
+
+@smallexample
+-rw-r--r-- 1 games 0 Jul 31 15:33 scores
+@end smallexample
+
+Here are the parts of the program that show how to set up the changed
+user ID. This program is conditionalized so that it makes use of the
+saved IDs feature if it is supported, and otherwise uses @code{setreuid}
+to swap the effective and real user IDs.
+
+@smallexample
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+
+/* @r{Save the effective and real UIDs.} */
+
+static uid_t euid, ruid;
+
+
+/* @r{Restore the effective UID to its original value.} */
+
+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);
+ @}
+@}
+
+
+@group
+/* @r{Set the effective UID to the real UID.} */
+
+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);
+ @}
+@}
+@end group
+
+/* @r{Main program.} */
+
+int
+main (void)
+@{
+ /* @r{Save the real and effective user IDs.} */
+ ruid = getuid ();
+ euid = geteuid ();
+ undo_setuid ();
+
+ /* @r{Do the game and record the score.} */
+ @dots{}
+@}
+@end smallexample
+
+Notice how the first thing the @code{main} function does is to set the
+effective user ID back to the real user ID. This is so that any other
+file accesses that are performed while the user is playing the game use
+the real user ID for determining permissions. Only when the program
+needs to open the scores file does it switch back to the original
+effective user ID, like this:
+
+@smallexample
+/* @r{Record the score.} */
+
+int
+record_score (int score)
+@{
+ FILE *stream;
+ char *myname;
+
+ /* @r{Open the scores file.} */
+ do_setuid ();
+ stream = fopen (SCORES_FILE, "a");
+ undo_setuid ();
+
+@group
+ /* @r{Write the score to the file.} */
+ 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;
+@}
+@end group
+@end smallexample
+
+@node Tips for Setuid
+@section Tips for Writing Setuid Programs
+
+It is easy for setuid programs to give the user access that isn't
+intended---in fact, if you want to avoid this, you need to be careful.
+Here are some guidelines for preventing unintended access and
+minimizing its consequences when it does occur:
+
+@itemize @bullet
+@item
+Don't have @code{setuid} programs with privileged user IDs such as
+@code{root} unless it is absolutely necessary. If the resource is
+specific to your particular program, it's better to define a new,
+nonprivileged user ID or group ID just to manage that resource.
+
+@item
+Be cautious about using the @code{system} and @code{exec} functions in
+combination with changing the effective user ID. Don't let users of
+your program execute arbitrary programs under a changed user ID.
+Executing a shell is especially bad news. Less obviously, the
+@code{execlp} and @code{execvp} functions are a potential risk (since
+the program they execute depends on the user's @code{PATH} environment
+variable).
+
+If you must @code{exec} another program under a changed ID, specify an
+absolute file name (@pxref{File Name Resolution}) for the executable,
+and make sure that the protections on that executable and @emph{all}
+containing directories are such that ordinary users cannot replace it
+with some other program.
+
+@item
+Only use the user ID controlling the resource in the part of the program
+that actually uses that resource. When you're finished with it, restore
+the effective user ID back to the actual user's user ID.
+@xref{Enable/Disable Setuid}.
+
+@item
+If the @code{setuid} part of your program needs to access other files
+besides the controlled resource, it should verify that the real user
+would ordinarily have permission to access those files. You can use the
+@code{access} function (@pxref{Access Permission}) to check this; it
+uses the real user and group IDs, rather than the effective IDs.
+@end itemize
+
+@node Who Logged In
+@section Identifying Who Logged In
+@cindex login name, determining
+@cindex user ID, determining
+
+You can use the functions listed in this section to determine the login
+name of the user who is running a process, and the name of the user who
+logged in the current session. See also the function @code{getuid} and
+friends (@pxref{Reading Persona}).
+
+The @code{getlogin} function is declared in @file{unistd.h}, while
+@code{cuserid} and @code{L_cuserid} are declared in @file{stdio.h}.
+@pindex stdio.h
+@pindex unistd.h
+
+@comment unistd.h
+@comment POSIX.1
+@deftypefun {char *} getlogin (void)
+The @code{getlogin} function returns a pointer to a string containing the
+name of the user logged in on the controlling terminal of the process,
+or a null pointer if this information cannot be determined. The string
+is statically allocated and might be overwritten on subsequent calls to
+this function or to @code{cuserid}.
+@end deftypefun
+
+@comment stdio.h
+@comment POSIX.1
+@deftypefun {char *} cuserid (char *@var{string})
+The @code{cuserid} function returns a pointer to a string containing a
+user name associated with the effective ID of the process. If
+@var{string} is not a null pointer, it should be an array that can hold
+at least @code{L_cuserid} characters; the string is returned in this
+array. Otherwise, a pointer to a string in a static area is returned.
+This string is statically allocated and might be overwritten on
+subsequent calls to this function or to @code{getlogin}.
+@end deftypefun
+
+@comment stdio.h
+@comment POSIX.1
+@deftypevr Macro int L_cuserid
+An integer constant that indicates how long an array you might need to
+store a user name.
+@end deftypevr
+
+These functions let your program identify positively the user who is
+running or the user who logged in this session. (These can differ when
+setuid programs are involved; @xref{Process Persona}.) The user cannot
+do anything to fool these functions.
+
+For most purposes, it is more useful to use the environment variable
+@code{LOGNAME} to find out who the user is. This is more flexible
+precisely because the user can set @code{LOGNAME} arbitrarily.
+@xref{Standard Environment}.
+
+@node User Database
+@section User Database
+@cindex user database
+@cindex password database
+@pindex /etc/passwd
+
+This section describes all about how to search and scan the database of
+registered users. The database itself is kept in the file
+@file{/etc/passwd} on most systems, but on some systems a special
+network server gives access to it.
+
+@menu
+* User Data Structure:: What each user record contains.
+* Lookup User:: How to look for a particular user.
+* Scanning All Users:: Scanning the list of all users, one by one.
+* Writing a User Entry:: How a program can rewrite a user's record.
+@end menu
+
+@node User Data Structure
+@subsection The Data Structure that Describes a User
+
+The functions and data structures for accessing the system user database
+are declared in the header file @file{pwd.h}.
+@pindex pwd.h
+
+@comment pwd.h
+@comment POSIX.1
+@deftp {Data Type} {struct passwd}
+The @code{passwd} data structure is used to hold information about
+entries in the system user data base. It has at least the following members:
+
+@table @code
+@item char *pw_name
+The user's login name.
+
+@item char *pw_passwd.
+The encrypted password string.
+
+@item uid_t pw_uid
+The user ID number.
+
+@item gid_t pw_gid
+The user's default group ID number.
+
+@item char *pw_gecos
+A string typically containing the user's real name, and possibly other
+information such as a phone number.
+
+@item char *pw_dir
+The user's home directory, or initial working directory. This might be
+a null pointer, in which case the interpretation is system-dependent.
+
+@item char *pw_shell
+The user's default shell, or the initial program run when the user logs in.
+This might be a null pointer, indicating that the system default should
+be used.
+@end table
+@end deftp
+
+@node Lookup User
+@subsection Looking Up One User
+@cindex converting user ID to user name
+@cindex converting user name to user ID
+
+You can search the system user database for information about a
+specific user using @code{getpwuid} or @code{getpwnam}. These
+functions are declared in @file{pwd.h}.
+
+@comment pwd.h
+@comment POSIX.1
+@deftypefun {struct passwd *} getpwuid (uid_t @var{uid})
+This function returns a pointer to a statically-allocated structure
+containing information about the user whose user ID is @var{uid}. This
+structure may be overwritten on subsequent calls to @code{getpwuid}.
+
+A null pointer value indicates there is no user in the data base with
+user ID @var{uid}.
+@end deftypefun
+
+@comment pwd.h
+@comment POSIX.1
+@deftypefun {struct passwd *} getpwnam (const char *@var{name})
+This function returns a pointer to a statically-allocated structure
+containing information about the user whose user name is @var{name}.
+This structure may be overwritten on subsequent calls to
+@code{getpwnam}.
+
+A null pointer value indicates there is no user named @var{name}.
+@end deftypefun
+
+@node Scanning All Users
+@subsection Scanning the List of All Users
+@cindex scanning the user list
+
+This section explains how a program can read the list of all users in
+the system, one user at a time. The functions described here are
+declared in @file{pwd.h}.
+
+You can use the @code{fgetpwent} function to read user entries from a
+particular file.
+
+@comment pwd.h
+@comment SVID
+@deftypefun {struct passwd *} fgetpwent (FILE *@var{stream})
+This function reads the next user entry from @var{stream} and returns a
+pointer to the entry. The structure is statically allocated and is
+rewritten on subsequent calls to @code{fgetpwent}. You must copy the
+contents of the structure if you wish to save the information.
+
+This stream must correspond to a file in the same format as the standard
+password database file. This function comes from System V.
+@end deftypefun
+
+The way to scan all the entries in the user database is with
+@code{setpwent}, @code{getpwent}, and @code{endpwent}.
+
+@comment pwd.h
+@comment SVID, BSD
+@deftypefun void setpwent (void)
+This function initializes a stream which @code{getpwent} uses to read
+the user database.
+@end deftypefun
+
+@comment pwd.h
+@comment POSIX.1
+@deftypefun {struct passwd *} getpwent (void)
+The @code{getpwent} function reads the next entry from the stream
+initialized by @code{setpwent}. It returns a pointer to the entry. The
+structure is statically allocated and is rewritten on subsequent calls
+to @code{getpwent}. You must copy the contents of the structure if you
+wish to save the information.
+@end deftypefun
+
+@comment pwd.h
+@comment SVID, BSD
+@deftypefun void endpwent (void)
+This function closes the internal stream used by @code{getpwent}.
+@end deftypefun
+
+@node Writing a User Entry
+@subsection Writing a User Entry
+
+@comment pwd.h
+@comment SVID
+@deftypefun int putpwent (const struct passwd *@var{p}, FILE *@var{stream})
+This function writes the user entry @code{*@var{p}} to the stream
+@var{stream}, in the format used for the standard user database
+file. The return value is zero on success and nonzero on failure.
+
+This function exists for compatibility with SVID. We recommend that you
+avoid using it, because it makes sense only on the assumption that the
+@code{struct passwd} structure has no members except the standard ones;
+on a system which merges the traditional Unix data base with other
+extended information about users, adding an entry using this function
+would inevitably leave out much of the important information.
+
+The function @code{putpwent} is declared in @file{pwd.h}.
+@end deftypefun
+
+@node Group Database
+@section Group Database
+@cindex group database
+@pindex /etc/group
+
+This section describes all about how to search and scan the database of
+registered groups. The database itself is kept in the file
+@file{/etc/group} on most systems, but on some systems a special network
+service provides access to it.
+
+@menu
+* Group Data Structure:: What each group record contains.
+* Lookup Group:: How to look for a particular group.
+* Scanning All Groups:: Scanning the list of all groups.
+@end menu
+
+@node Group Data Structure
+@subsection The Data Structure for a Group
+
+The functions and data structures for accessing the system group
+database are declared in the header file @file{grp.h}.
+@pindex grp.h
+
+@comment grp.h
+@comment POSIX.1
+@deftp {Data Type} {struct group}
+The @code{group} structure is used to hold information about an entry in
+the system group database. It has at least the following members:
+
+@table @code
+@item char *gr_name
+The name of the group.
+
+@item gid_t gr_gid
+The group ID of the group.
+
+@item char **gr_mem
+A vector of pointers to the names of users in the group. Each user name
+is a null-terminated string, and the vector itself is terminated by a
+null pointer.
+@end table
+@end deftp
+
+@node Lookup Group
+@subsection Looking Up One Group
+@cindex converting group name to group ID
+@cindex converting group ID to group name
+
+You can search the group database for information about a specific
+group using @code{getgrgid} or @code{getgrnam}. These functions are
+declared in @file{grp.h}.
+
+@comment grp.h
+@comment POSIX.1
+@deftypefun {struct group *} getgrgid (gid_t @var{gid})
+This function returns a pointer to a statically-allocated structure
+containing information about the group whose group ID is @var{gid}.
+This structure may be overwritten by subsequent calls to
+@code{getgrgid}.
+
+A null pointer indicates there is no group with ID @var{gid}.
+@end deftypefun
+
+@comment grp.h
+@comment SVID, BSD
+@deftypefun {struct group *} getgrnam (const char *@var{name})
+This function returns a pointer to a statically-allocated structure
+containing information about the group whose group name is @var{name}.
+This structure may be overwritten by subsequent calls to
+@code{getgrnam}.
+
+A null pointer indicates there is no group named @var{name}.
+@end deftypefun
+
+@node Scanning All Groups
+@subsection Scanning the List of All Groups
+@cindex scanning the group list
+
+This section explains how a program can read the list of all groups in
+the system, one group at a time. The functions described here are
+declared in @file{grp.h}.
+
+You can use the @code{fgetgrent} function to read group entries from a
+particular file.
+
+@comment grp.h
+@comment SVID
+@deftypefun {struct group *} fgetgrent (FILE *@var{stream})
+The @code{fgetgrent} function reads the next entry from @var{stream}.
+It returns a pointer to the entry. The structure is statically
+allocated and is rewritten on subsequent calls to @code{fgetgrent}. You
+must copy the contents of the structure if you wish to save the
+information.
+
+The stream must correspond to a file in the same format as the standard
+group database file.
+@end deftypefun
+
+The way to scan all the entries in the group database is with
+@code{setgrent}, @code{getgrent}, and @code{endgrent}.
+
+@comment grp.h
+@comment SVID, BSD
+@deftypefun void setgrent (void)
+This function initializes a stream for reading from the group data base.
+You use this stream by calling @code{getgrent}.
+@end deftypefun
+
+@comment grp.h
+@comment SVID, BSD
+@deftypefun {struct group *} getgrent (void)
+The @code{getgrent} function reads the next entry from the stream
+initialized by @code{setgrent}. It returns a pointer to the entry. The
+structure is statically allocated and is rewritten on subsequent calls
+to @code{getgrent}. You must copy the contents of the structure if you
+wish to save the information.
+@end deftypefun
+
+@comment grp.h
+@comment SVID, BSD
+@deftypefun void endgrent (void)
+This function closes the internal stream used by @code{getgrent}.
+@end deftypefun
+
+@node Database Example
+@section User and Group Database Example
+
+Here is an example program showing the use of the system database inquiry
+functions. The program prints some information about the user running
+the program.
+
+@smallexample
+@include db.c.texi
+@end smallexample
+
+Here is some output from this program:
+
+@smallexample
+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
+@end smallexample