mirror of git://sourceware.org/git/glibc.git
				
				
				
			
		
			
				
	
	
		
			2062 lines
		
	
	
		
			74 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			2062 lines
		
	
	
		
			74 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| @node Users and Groups, System Management, Name Service Switch, Top
 | |
| @c %MENU% How users are identified and classified
 | |
| @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 Accounting Database::    Keeping information about users and various
 | |
|                                  actions in databases.
 | |
| 
 | |
| * 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 the use of database
 | |
| 				 inquiry functions.
 | |
| * Netgroup Database::           Functions for accessing the netgroup database.
 | |
| @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 belongs to one
 | |
| @dfn{default group} and may also belong to any number of
 | |
| @dfn{supplementary groups}. 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
 | |
| @cindex supplementary group IDs
 | |
| 
 | |
| @c When Hurd is more widely used, explain multiple effective user IDs
 | |
| @c here. -zw
 | |
| At any time, each process has an @dfn{effective user ID}, a @dfn{effective
 | |
| group ID}, and a set of @dfn{supplementary group IDs}.  These IDs
 | |
| determine the privileges of the process.  They are collectively
 | |
| called the @dfn{persona} of the process, because they determine ``who it
 | |
| is'' for purposes of access control.
 | |
| 
 | |
| Your login shell starts out with a persona which consists of your user
 | |
| ID, your default group ID, and your supplementary group IDs (if you are
 | |
| in more than one group).  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}.
 | |
| 
 | |
| For details on how a process's effective user ID and group IDs affect
 | |
| its permission to access files, see @ref{Access Permission}.
 | |
| 
 | |
| The effective user ID of a process also controls permissions for sending
 | |
| signals using the @code{kill} function.  @xref{Signaling Another
 | |
| Process}.
 | |
| 
 | |
| Finally, there are many operations which can only be performed by a
 | |
| process whose effective user ID is zero.  A process with this user ID is
 | |
| a @dfn{privileged process}.  Commonly the user name @code{root} is
 | |
| associated with user ID 0, but there may be other user names with this
 | |
| ID.
 | |
| @c !!! should mention POSIX capabilities here.
 | |
| 
 | |
| @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
 | |
| @cindex saved set-user-ID
 | |
| @cindex saved set-group-ID
 | |
| @cindex @code{_POSIX_SAVED_IDS}
 | |
| 
 | |
| 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 on, executing that file
 | |
| gives the process a third user ID: the @dfn{file user ID}.  This ID is
 | |
| set to the owner ID of the file.  The system then changes the effective
 | |
| user ID to the file user ID.  The real user ID remains as it was.
 | |
| Likewise, if the setgid bit is on, the process is given a @dfn{file
 | |
| group ID} equal to the group ID of the file, and its effective group ID
 | |
| is changed to the file group ID.
 | |
| 
 | |
| If a process has a file ID (user or group), then it can at any time
 | |
| change its effective ID to its real ID and back to its file ID.
 | |
| Programs use this feature to relinquish their special privileges except
 | |
| when they actually need them.  This makes it less likely that they can
 | |
| be tricked into doing something inappropriate with their privileges.
 | |
| 
 | |
| @strong{Portability Note:} Older systems do not have file IDs.
 | |
| To determine if a system has this feature, you can test the compiler
 | |
| define @code{_POSIX_SAVED_IDS}.  (In the POSIX standard, file IDs are
 | |
| known as saved IDs.)
 | |
| 
 | |
| @xref{File Attributes}, for a more general discussion of file modes and
 | |
| accessibility.
 | |
| 
 | |
| @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 (0, NULL);
 | |
|   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 seteuid (uid_t @var{neweuid})
 | |
| This function sets the effective user ID of a process to @var{newuid},
 | |
| provided that the process is allowed to change its effective user ID.  A
 | |
| privileged process (effective user ID zero) can change its effective
 | |
| user ID to any legal value.  An unprivileged process with a file user ID
 | |
| can change its effective user ID to its real user ID or to its file user
 | |
| ID.  Otherwise, a process may not change its effective user ID at all.
 | |
| 
 | |
| The @code{seteuid} 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 may not change to the specified ID.
 | |
| @end table
 | |
| 
 | |
| Older systems (those without the @code{_POSIX_SAVED_IDS} feature) do not
 | |
| have this function.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment unistd.h
 | |
| @comment POSIX.1
 | |
| @deftypefun int setuid (uid_t @var{newuid})
 | |
| If the calling process is privileged, this function sets both the real
 | |
| and effective user ID of the process to @var{newuid}.  It also deletes
 | |
| the file user ID of the process, if any.  @var{newuid} may be any
 | |
| legal value.  (Once this has been done, there is no way to recover the
 | |
| old effective user ID.)
 | |
| 
 | |
| If the process is not privileged, and the system supports the
 | |
| @code{_POSIX_SAVED_IDS} feature, then this function behaves like
 | |
| @code{seteuid}.
 | |
| 
 | |
| The return values and error conditions are the same as for @code{seteuid}.
 | |
| @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 file 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 file 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 setegid (gid_t @var{newgid})
 | |
| This function sets the effective group ID of the process to
 | |
| @var{newgid}, provided that the process is allowed to change its group
 | |
| ID.  Just as with @code{seteuid}, if the process is privileged it may
 | |
| change its effective group ID to any value; if it isn't, but it has a
 | |
| file group ID, then it may change to its real group ID or file group ID;
 | |
| otherwise it may not change its effective group ID.
 | |
| 
 | |
| Note that a process is only privileged if its effective @emph{user} ID
 | |
| is zero.  The effective group ID only affects access permissions.
 | |
| 
 | |
| The return values and error conditions for @code{setegid} are the same
 | |
| as those for @code{seteuid}.
 | |
| 
 | |
| This function is only present if @code{_POSIX_SAVED_IDS} is defined.
 | |
| @end deftypefun
 | |
| 
 | |
| @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 is privileged.  It also
 | |
| deletes the file group ID, if any.
 | |
| 
 | |
| If the process is not privileged, then @code{setgid} behaves like
 | |
| @code{setegid}.
 | |
| 
 | |
| The return values and error conditions for @code{setgid} are the same
 | |
| as those for @code{seteuid}.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment unistd.h
 | |
| @comment BSD
 | |
| @deftypefun int setregid (gid_t @var{rgid}, gid_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 file 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 file 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
 | |
| 
 | |
| @code{setuid} and @code{setgid} behave differently depending on whether
 | |
| the effective user ID at the time is zero.  If it is not zero, they
 | |
| behave like @code{seteuid} and @code{setegid}.  If it is, they change
 | |
| both effective and real IDs and delete the file ID.  To avoid confusion,
 | |
| we recommend you always use @code{seteuid} and @code{setegid} except
 | |
| when you know the effective user ID is zero and your intent is to change
 | |
| the persona permanently.  This case is rare---most of the programs that
 | |
| need it, such as @code{login} and @code{su}, have already been written.
 | |
| 
 | |
| Note that if your program is setuid to some user other than @code{root},
 | |
| there is no way to drop privileges permanently.
 | |
| 
 | |
| The 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{group})
 | |
| The @code{initgroups} function sets the process's supplementary group
 | |
| IDs to be the normal default for the user name @var{user}.  The group
 | |
| @var{group} is automatically included.
 | |
| 
 | |
| This function works by scanning the group database for all the groups
 | |
| @var{user} belongs to.  It then calls @code{setgroups} with the list it
 | |
| has constructed.
 | |
| 
 | |
| The return values and error conditions are the same as for
 | |
| @code{setgroups}.
 | |
| @end deftypefun
 | |
| 
 | |
| If you are interested in the groups a particular user belongs to, but do
 | |
| not want to change the process's supplementary group IDs, you can use
 | |
| @code{getgrouplist}.  To use @code{getgrouplist}, your programs should
 | |
| include the header file @file{grp.h}.
 | |
| @pindex grp.h
 | |
| 
 | |
| @comment grp.h
 | |
| @comment BSD
 | |
| @deftypefun int getgrouplist (const char *@var{user}, gid_t @var{group}, gid_t *@var{groups}, int *@var{ngroups})
 | |
| The @code{getgrouplist} function scans the group database for all the
 | |
| groups @var{user} belongs to.  Up to *@var{ngroups} group IDs
 | |
| corresponding to these groups are stored in the array @var{groups}; the
 | |
| return value from the function is the number of group IDs actually
 | |
| stored.  If *@var{ngroups} is smaller than the total number of groups
 | |
| found, then @code{getgrouplist} returns a value of @code{-1} and stores
 | |
| the actual number of groups in *@var{ngroups}.  The group @var{group} is
 | |
| automatically included in the list of groups returned by
 | |
| @code{getgrouplist}.
 | |
| 
 | |
| Here's how to use @code{getgrouplist} to read all supplementary groups
 | |
| for @var{user}:
 | |
| 
 | |
| @smallexample
 | |
| @group
 | |
| gid_t *
 | |
| supplementary_groups (char *user)
 | |
| @{
 | |
|   int ngroups = 16;
 | |
|   gid_t *groups
 | |
|     = (gid_t *) xmalloc (ngroups * sizeof (gid_t));
 | |
|   struct passwd *pw = getpwnam (user);
 | |
| 
 | |
|   if (pw == NULL)
 | |
|     return NULL;
 | |
| 
 | |
|   if (getgrouplist (pw->pw_name, pw->pw_gid, groups, &ngroups) < 0)
 | |
|     @{
 | |
|       groups = xrealloc (ngroups * sizeof (gid_t));
 | |
|       getgrouplist (pw->pw_name, pw->pw_gid, groups, &ngroups);
 | |
|     @}
 | |
|   return groups;
 | |
| @}
 | |
| @end group
 | |
| @end smallexample
 | |
| @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 @code{_POSIX_SAVED_IDS} feature, you can
 | |
| accomplish this with @code{seteuid}.  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
 | |
| seteuid (user_user_id);
 | |
| @end smallexample
 | |
| 
 | |
| @noindent
 | |
| and turn it on with
 | |
| 
 | |
| @smallexample
 | |
| seteuid (game_user_id);
 | |
| @end smallexample
 | |
| 
 | |
| @noindent
 | |
| Throughout this process, the real user ID remains @code{jdoe} and the
 | |
| file 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 file user IDs, 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
 | |
|   seteuid (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 setuid 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 setuid 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
 | |
| file 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{Remember 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 = seteuid (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 = seteuid (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{Remember 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 file 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.
 | |
| It's better if you can write your program to use a special group than a
 | |
| special user.
 | |
| 
 | |
| @item
 | |
| Be cautious about using the @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.
 | |
| 
 | |
| You should also check the arguments passed to the program to make sure
 | |
| they do not have unexpected effects.  Likewise, you should examine the
 | |
| environment variables.  Decide which arguments and variables are safe,
 | |
| and reject all others.
 | |
| 
 | |
| You should never use @code{system} in a privileged program, because it
 | |
| invokes a shell.
 | |
| 
 | |
| @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}).  How this information is collected by
 | |
| the system and how to control/add/remove information from the background
 | |
| storage is described in @ref{User Accounting Database}.
 | |
| 
 | |
| 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}.
 | |
| 
 | |
| The use of this function is deprecated since it is marked to be
 | |
| withdrawn in XPG4.2 and has already been removed from newer revisions of
 | |
| POSIX.1.
 | |
| @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; see @ref{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 Accounting Database
 | |
| @section The User Accounting Database
 | |
| @cindex user accounting database
 | |
| 
 | |
| Most Unix-like operating systems keep track of logged in users by
 | |
| maintaining a user accounting database.  This user accounting database
 | |
| stores for each terminal, who has logged on, at what time, the process
 | |
| ID of the user's login shell, etc., etc., but also stores information
 | |
| about the run level of the system, the time of the last system reboot,
 | |
| and possibly more.
 | |
| 
 | |
| The user accounting database typically lives in @file{/etc/utmp},
 | |
| @file{/var/adm/utmp} or @file{/var/run/utmp}.  However, these files
 | |
| should @strong{never} be accessed directly.  For reading information
 | |
| from and writing information to the user accounting database, the
 | |
| functions described in this section should be used.
 | |
| 
 | |
| 
 | |
| @menu
 | |
| * Manipulating the Database::   Scanning and modifying the user
 | |
|                                  accounting database.
 | |
| * XPG Functions::               A standardized way for doing the same thing.
 | |
| * Logging In and Out::          Functions from BSD that modify the user
 | |
|                                  accounting database.
 | |
| @end menu
 | |
| 
 | |
| @node Manipulating the Database
 | |
| @subsection Manipulating the User Accounting Database
 | |
| 
 | |
| These functions and the corresponding data structures are declared in
 | |
| the header file @file{utmp.h}.
 | |
| @pindex utmp.h
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @deftp {Data Type} {struct exit_status}
 | |
| The @code{exit_status} data structure is used to hold information about
 | |
| the exit status of processes marked as @code{DEAD_PROCESS} in the user
 | |
| accounting database.
 | |
| 
 | |
| @table @code
 | |
| @item short int e_termination
 | |
| The exit status of the process.
 | |
| 
 | |
| @item short int e_exit
 | |
| The exit status of the process.
 | |
| @end table
 | |
| @end deftp
 | |
| 
 | |
| @deftp {Data Type} {struct utmp}
 | |
| The @code{utmp} data structure is used to hold information about entries
 | |
| in the user accounting database.  On the GNU system it has the following
 | |
| members:
 | |
| 
 | |
| @table @code
 | |
| @item short int ut_type
 | |
| Specifies the type of login; one of @code{EMPTY}, @code{RUN_LVL},
 | |
| @code{BOOT_TIME}, @code{OLD_TIME}, @code{NEW_TIME}, @code{INIT_PROCESS},
 | |
| @code{LOGIN_PROCESS}, @code{USER_PROCESS}, @code{DEAD_PROCESS} or
 | |
| @code{ACCOUNTING}.
 | |
| 
 | |
| @item pid_t ut_pid
 | |
| The process ID number of the login process.
 | |
| 
 | |
| @item char ut_line[]
 | |
| The device name of the tty (without @file{/dev/}).
 | |
| 
 | |
| @item char ut_id[]
 | |
| The inittab ID of the process.
 | |
| 
 | |
| @item char ut_user[]
 | |
| The user's login name.
 | |
| 
 | |
| @item char ut_host[]
 | |
| The name of the host from which the user logged in.
 | |
| 
 | |
| @item struct exit_status ut_exit
 | |
| The exit status of a process marked as @code{DEAD_PROCESS}.
 | |
| 
 | |
| @item long ut_session
 | |
| The Session ID, used for windowing.
 | |
| 
 | |
| @item struct timeval ut_tv
 | |
| Time the entry was made.  For entries of type @code{OLD_TIME} this is
 | |
| the time when the system clock changed, and for entries of type
 | |
| @code{NEW_TIME} this is the time the system clock was set to.
 | |
| 
 | |
| @item int32_t ut_addr_v6[4]
 | |
| The Internet address of a remote host.
 | |
| @end table
 | |
| @end deftp
 | |
| 
 | |
| The @code{ut_type}, @code{ut_pid}, @code{ut_id}, @code{ut_tv}, and
 | |
| @code{ut_host} fields are not available on all systems.  Portable
 | |
| applications therefore should be prepared for these situations.  To help
 | |
| doing this the @file{utmp.h} header provides macros
 | |
| @code{_HAVE_UT_TYPE}, @code{_HAVE_UT_PID}, @code{_HAVE_UT_ID},
 | |
| @code{_HAVE_UT_TV}, and @code{_HAVE_UT_HOST} if the respective field is
 | |
| available.  The programmer can handle the situations by using
 | |
| @code{#ifdef} in the program code.
 | |
| 
 | |
| The following macros are defined for use as values for the
 | |
| @code{ut_type} member of the @code{utmp} structure.  The values are
 | |
| integer constants.
 | |
| 
 | |
| @table @code
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @vindex EMPTY
 | |
| @item EMPTY
 | |
| This macro is used to indicate that the entry contains no valid user
 | |
| accounting information.
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @vindex RUN_LVL
 | |
| @item RUN_LVL
 | |
| This macro is used to identify the systems runlevel.
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @vindex BOOT_TIME
 | |
| @item BOOT_TIME
 | |
| This macro is used to identify the time of system boot.
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @vindex OLD_TIME
 | |
| @item OLD_TIME
 | |
| This macro is used to identify the time when the system clock changed.
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @vindex NEW_TIME
 | |
| @item NEW_TIME
 | |
| This macro is used to identify the time after the system changed.
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @vindex INIT_PROCESS
 | |
| @item INIT_PROCESS
 | |
| This macro is used to identify a process spawned by the init process.
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @vindex LOGIN_PROCESS
 | |
| @item LOGIN_PROCESS
 | |
| This macro is used to identify the session leader of a logged in user.
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @vindex USER_PROCESS
 | |
| @item USER_PROCESS
 | |
| This macro is used to identify a user process.
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @vindex DEAD_PROCESS
 | |
| @item DEAD_PROCESS
 | |
| This macro is used to identify a terminated process.
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @vindex ACCOUNTING
 | |
| @item ACCOUNTING
 | |
| ???
 | |
| @end table
 | |
| 
 | |
| The size of the @code{ut_line}, @code{ut_id}, @code{ut_user} and
 | |
| @code{ut_host} arrays can be found using the @code{sizeof} operator.
 | |
| 
 | |
| Many older systems have, instead of an @code{ut_tv} member, an
 | |
| @code{ut_time} member, usually of type @code{time_t}, for representing
 | |
| the time associated with the entry.  Therefore, for backwards
 | |
| compatibility only, @file{utmp.h} defines @code{ut_time} as an alias for
 | |
| @code{ut_tv.tv_sec}.
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @deftypefun void setutent (void)
 | |
| This function opens the user accounting database to begin scanning it.
 | |
| You can then call @code{getutent}, @code{getutid} or @code{getutline} to
 | |
| read entries and @code{pututline} to write entries.
 | |
| 
 | |
| If the database is already open, it resets the input to the beginning of
 | |
| the database.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @deftypefun {struct utmp *} getutent (void)
 | |
| The @code{getutent} function reads the next entry from the user
 | |
| accounting database.  It returns a pointer to the entry, which is
 | |
| statically allocated and may be overwritten by subsequent calls to
 | |
| @code{getutent}.  You must copy the contents of the structure if you
 | |
| wish to save the information or you can use the @code{getutent_r}
 | |
| function which stores the data in a user-provided buffer.
 | |
| 
 | |
| A null pointer is returned in case no further entry is available.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @deftypefun void endutent (void)
 | |
| This function closes the user accounting database.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @deftypefun {struct utmp *} getutid (const struct utmp *@var{id})
 | |
| This function searches forward from the current point in the database
 | |
| for an entry that matches @var{id}.  If the @code{ut_type} member of the
 | |
| @var{id} structure is one of @code{RUN_LVL}, @code{BOOT_TIME},
 | |
| @code{OLD_TIME} or @code{NEW_TIME} the entries match if the
 | |
| @code{ut_type} members are identical.  If the @code{ut_type} member of
 | |
| the @var{id} structure is @code{INIT_PROCESS}, @code{LOGIN_PROCESS},
 | |
| @code{USER_PROCESS} or @code{DEAD_PROCESS}, the entries match if the
 | |
| @code{ut_type} member of the entry read from the database is one of
 | |
| these four, and the @code{ut_id} members match.  However if the
 | |
| @code{ut_id} member of either the @var{id} structure or the entry read
 | |
| from the database is empty it checks if the @code{ut_line} members match
 | |
| instead.  If a matching entry is found, @code{getutid} returns a pointer
 | |
| to the entry, which is statically allocated, and may be overwritten by a
 | |
| subsequent call to @code{getutent}, @code{getutid} or @code{getutline}.
 | |
| You must copy the contents of the structure if you wish to save the
 | |
| information.
 | |
| 
 | |
| A null pointer is returned in case the end of the database is reached
 | |
| without a match.
 | |
| 
 | |
| The @code{getutid} function may cache the last read entry.  Therefore,
 | |
| if you are using @code{getutid} to search for multiple occurrences, it
 | |
| is necessary to zero out the static data after each call.  Otherwise
 | |
| @code{getutid} could just return a pointer to the same entry over and
 | |
| over again.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @deftypefun {struct utmp *} getutline (const struct utmp *@var{line})
 | |
| This function searches forward from the current point in the database
 | |
| until it finds an entry whose @code{ut_type} value is
 | |
| @code{LOGIN_PROCESS} or @code{USER_PROCESS}, and whose @code{ut_line}
 | |
| member matches the @code{ut_line} member of the @var{line} structure.
 | |
| If it finds such an entry, it returns a pointer to the entry which is
 | |
| statically allocated, and may be overwritten by a subsequent call to
 | |
| @code{getutent}, @code{getutid} or @code{getutline}.  You must copy the
 | |
| contents of the structure if you wish to save the information.
 | |
| 
 | |
| A null pointer is returned in case the end of the database is reached
 | |
| without a match.
 | |
| 
 | |
| The @code{getutline} function may cache the last read entry.  Therefore
 | |
| if you are using @code{getutline} to search for multiple occurrences, it
 | |
| is necessary to zero out the static data after each call.  Otherwise
 | |
| @code{getutline} could just return a pointer to the same entry over and
 | |
| over again.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @deftypefun {struct utmp *} pututline (const struct utmp *@var{utmp})
 | |
| The @code{pututline} function inserts the entry @code{*@var{utmp}} at
 | |
| the appropriate place in the user accounting database.  If it finds that
 | |
| it is not already at the correct place in the database, it uses
 | |
| @code{getutid} to search for the position to insert the entry, however
 | |
| this will not modify the static structure returned by @code{getutent},
 | |
| @code{getutid} and @code{getutline}.  If this search fails, the entry
 | |
| is appended to the database.
 | |
| 
 | |
| The @code{pututline} function returns a pointer to a copy of the entry
 | |
| inserted in the user accounting database, or a null pointer if the entry
 | |
| could not be added.  The following @code{errno} error conditions are
 | |
| defined for this function:
 | |
| 
 | |
| @table @code
 | |
| @item EPERM
 | |
| The process does not have the appropriate privileges; you cannot modify
 | |
| the user accounting database.
 | |
| @end table
 | |
| @end deftypefun
 | |
| 
 | |
| All the @code{get*} functions mentioned before store the information
 | |
| they return in a static buffer.  This can be a problem in multi-threaded
 | |
| programs since the data returned for the request is overwritten by the
 | |
| return value data in another thread.  Therefore the GNU C Library
 | |
| provides as extensions three more functions which return the data in a
 | |
| user-provided buffer.
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment GNU
 | |
| @deftypefun int getutent_r (struct utmp *@var{buffer}, struct utmp **@var{result})
 | |
| The @code{getutent_r} is equivalent to the @code{getutent} function.  It
 | |
| returns the next entry from the database.  But instead of storing the
 | |
| information in a static buffer it stores it in the buffer pointed to by
 | |
| the parameter @var{buffer}.
 | |
| 
 | |
| If the call was successful, the function returns @code{0} and the
 | |
| pointer variable pointed to by the parameter @var{result} contains a
 | |
| pointer to the buffer which contains the result (this is most probably
 | |
| the same value as @var{buffer}).  If something went wrong during the
 | |
| execution of @code{getutent_r} the function returns @code{-1}.
 | |
| 
 | |
| This function is a GNU extension.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment GNU
 | |
| @deftypefun int getutid_r (const struct utmp *@var{id}, struct utmp *@var{buffer}, struct utmp **@var{result})
 | |
| This function retrieves just like @code{getutid} the next entry matching
 | |
| the information stored in @var{id}.  But the result is stored in the
 | |
| buffer pointed to by the parameter @var{buffer}.
 | |
| 
 | |
| If successful the function returns @code{0} and the pointer variable
 | |
| pointed to by the parameter @var{result} contains a pointer to the
 | |
| buffer with the result (probably the same as @var{result}.  If not
 | |
| successful the function return @code{-1}.
 | |
| 
 | |
| This function is a GNU extension.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment GNU
 | |
| @deftypefun int getutline_r (const struct utmp *@var{line}, struct utmp *@var{buffer}, struct utmp **@var{result})
 | |
| This function retrieves just like @code{getutline} the next entry
 | |
| matching the information stored in @var{line}.  But the result is stored
 | |
| in the buffer pointed to by the parameter @var{buffer}.
 | |
| 
 | |
| If successful the function returns @code{0} and the pointer variable
 | |
| pointed to by the parameter @var{result} contains a pointer to the
 | |
| buffer with the result (probably the same as @var{result}.  If not
 | |
| successful the function return @code{-1}.
 | |
| 
 | |
| This function is a GNU extension.
 | |
| @end deftypefun
 | |
| 
 | |
| 
 | |
| In addition to the user accounting database, most systems keep a number
 | |
| of similar databases.  For example most systems keep a log file with all
 | |
| previous logins (usually in @file{/etc/wtmp} or @file{/var/log/wtmp}).
 | |
| 
 | |
| For specifying which database to examine, the following function should
 | |
| be used.
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @deftypefun int utmpname (const char *@var{file})
 | |
| The @code{utmpname} function changes the name of the database to be
 | |
| examined to @var{file}, and closes any previously opened database.  By
 | |
| default @code{getutent}, @code{getutid}, @code{getutline} and
 | |
| @code{pututline} read from and write to the user accounting database.
 | |
| 
 | |
| The following macros are defined for use as the @var{file} argument:
 | |
| 
 | |
| @deftypevr Macro {char *} _PATH_UTMP
 | |
| This macro is used to specify the user accounting database.
 | |
| @end deftypevr
 | |
| 
 | |
| @deftypevr Macro {char *} _PATH_WTMP
 | |
| This macro is used to specify the user accounting log file.
 | |
| @end deftypevr
 | |
| 
 | |
| The @code{utmpname} function returns a value of @code{0} if the new name
 | |
| was successfully stored, and a value of @code{-1} to indicate an error.
 | |
| Note that @code{utmpname} does not try to open the database, and that
 | |
| therefore the return value does not say anything about whether the
 | |
| database can be successfully opened.
 | |
| @end deftypefun
 | |
| 
 | |
| Specially for maintaining log-like databases the GNU C Library provides
 | |
| the following function:
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment SVID
 | |
| @deftypefun void updwtmp (const char *@var{wtmp_file}, const struct utmp *@var{utmp})
 | |
| The @code{updwtmp} function appends the entry *@var{utmp} to the
 | |
| database specified by @var{wtmp_file}.  For possible values for the
 | |
| @var{wtmp_file} argument see the @code{utmpname} function.
 | |
| @end deftypefun
 | |
| 
 | |
| @strong{Portability Note:} Although many operating systems provide a
 | |
| subset of these functions, they are not standardized.  There are often
 | |
| subtle differences in the return types, and there are considerable
 | |
| differences between the various definitions of @code{struct utmp}.  When
 | |
| programming for the GNU system, it is probably best to stick
 | |
| with the functions described in this section.  If however, you want your
 | |
| program to be portable, consider using the XPG functions described in
 | |
| @ref{XPG Functions}, or take a look at the BSD compatible functions in
 | |
| @ref{Logging In and Out}.
 | |
| 
 | |
| 
 | |
| @node XPG Functions
 | |
| @subsection XPG User Accounting Database Functions
 | |
| 
 | |
| These functions, described in the X/Open Portability Guide, are declared
 | |
| in the header file @file{utmpx.h}.
 | |
| @pindex utmpx.h
 | |
| 
 | |
| @deftp {Data Type} {struct utmpx}
 | |
| The @code{utmpx} data structure contains at least the following members:
 | |
| 
 | |
| @table @code
 | |
| @item short int ut_type
 | |
| Specifies the type of login; one of @code{EMPTY}, @code{RUN_LVL},
 | |
| @code{BOOT_TIME}, @code{OLD_TIME}, @code{NEW_TIME}, @code{INIT_PROCESS},
 | |
| @code{LOGIN_PROCESS}, @code{USER_PROCESS} or @code{DEAD_PROCESS}.
 | |
| 
 | |
| @item pid_t ut_pid
 | |
| The process ID number of the login process.
 | |
| 
 | |
| @item char ut_line[]
 | |
| The device name of the tty (without @file{/dev/}).
 | |
| 
 | |
| @item char ut_id[]
 | |
| The inittab ID of the process.
 | |
| 
 | |
| @item char ut_user[]
 | |
| The user's login name.
 | |
| 
 | |
| @item struct timeval ut_tv
 | |
| Time the entry was made.  For entries of type @code{OLD_TIME} this is
 | |
| the time when the system clock changed, and for entries of type
 | |
| @code{NEW_TIME} this is the time the system clock was set to.
 | |
| @end table
 | |
| On the GNU system, @code{struct utmpx} is identical to @code{struct
 | |
| utmp} except for the fact that including @file{utmpx.h} does not make
 | |
| visible the declaration of @code{struct exit_status}.
 | |
| @end deftp
 | |
| 
 | |
| The following macros are defined for use as values for the
 | |
| @code{ut_type} member of the @code{utmpx} structure.  The values are
 | |
| integer constants and are, on the GNU system, identical to the
 | |
| definitions in @file{utmp.h}.
 | |
| 
 | |
| @table @code
 | |
| @comment utmpx.h
 | |
| @comment XPG4.2
 | |
| @vindex EMPTY
 | |
| @item EMPTY
 | |
| This macro is used to indicate that the entry contains no valid user
 | |
| accounting information.
 | |
| 
 | |
| @comment utmpx.h
 | |
| @comment XPG4.2
 | |
| @vindex RUN_LVL
 | |
| @item RUN_LVL
 | |
| This macro is used to identify the systems runlevel.
 | |
| 
 | |
| @comment utmpx.h
 | |
| @comment XPG4.2
 | |
| @vindex BOOT_TIME
 | |
| @item BOOT_TIME
 | |
| This macro is used to identify the time of system boot.
 | |
| 
 | |
| @comment utmpx.h
 | |
| @comment XPG4.2
 | |
| @vindex OLD_TIME
 | |
| @item OLD_TIME
 | |
| This macro is used to identify the time when the system clock changed.
 | |
| 
 | |
| @comment utmpx.h
 | |
| @comment XPG4.2
 | |
| @vindex NEW_TIME
 | |
| @item NEW_TIME
 | |
| This macro is used to identify the time after the system changed.
 | |
| 
 | |
| @comment utmpx.h
 | |
| @comment XPG4.2
 | |
| @vindex INIT_PROCESS
 | |
| @item INIT_PROCESS
 | |
| This macro is used to identify a process spawned by the init process.
 | |
| 
 | |
| @comment utmpx.h
 | |
| @comment XPG4.2
 | |
| @vindex LOGIN_PROCESS
 | |
| @item LOGIN_PROCESS
 | |
| This macro is used to identify the session leader of a logged in user.
 | |
| 
 | |
| @comment utmpx.h
 | |
| @comment XPG4.2
 | |
| @vindex USER_PROCESS
 | |
| @item USER_PROCESS
 | |
| This macro is used to identify a user process.
 | |
| 
 | |
| @comment utmpx.h
 | |
| @comment XPG4.2
 | |
| @vindex DEAD_PROCESS
 | |
| @item DEAD_PROCESS
 | |
| This macro is used to identify a terminated process.
 | |
| @end table
 | |
| 
 | |
| The size of the @code{ut_line}, @code{ut_id} and @code{ut_user} arrays
 | |
| can be found using the @code{sizeof} operator.
 | |
| 
 | |
| @comment utmpx.h
 | |
| @comment XPG4.2
 | |
| @deftypefun void setutxent (void)
 | |
| This function is similar to @code{setutent}.  On the GNU system it is
 | |
| simply an alias for @code{setutent}.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment utmpx.h
 | |
| @comment XPG4.2
 | |
| @deftypefun {struct utmpx *} getutxent (void)
 | |
| The @code{getutxent} function is similar to @code{getutent}, but returns
 | |
| a pointer to a @code{struct utmpx} instead of @code{struct utmp}.  On
 | |
| the GNU system it simply is an alias for @code{getutent}.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment utmpx.h
 | |
| @comment XPG4.2
 | |
| @deftypefun void endutxent (void)
 | |
| This function is similar to @code{endutent}.  On the GNU system it is
 | |
| simply an alias for @code{endutent}.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment utmpx.h
 | |
| @comment XPG4.2
 | |
| @deftypefun {struct utmpx *} getutxid (const struct utmpx *@var{id})
 | |
| This function is similar to @code{getutid}, but uses @code{struct utmpx}
 | |
| instead of @code{struct utmp}.  On the GNU system it is simply an alias
 | |
| for @code{getutid}.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment utmpx.h
 | |
| @comment XPG4.2
 | |
| @deftypefun {struct utmpx *} getutxline (const struct utmpx *@var{line})
 | |
| This function is similar to @code{getutid}, but uses @code{struct utmpx}
 | |
| instead of @code{struct utmp}.  On the GNU system it is simply an alias
 | |
| for @code{getutline}.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment utmpx.h
 | |
| @comment XPG4.2
 | |
| @deftypefun {struct utmpx *} pututxline (const struct utmpx *@var{utmp})
 | |
| The @code{pututxline} function is functionally identical to
 | |
| @code{pututline}, but uses @code{struct utmpx} instead of @code{struct
 | |
| utmp}.  On the GNU system, @code{pututxline} is simply an alias for
 | |
| @code{pututline}.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment utmpx.h
 | |
| @comment XPG4.2
 | |
| @deftypefun int utmpxname (const char *@var{file})
 | |
| The @code{utmpxname} function is functionally identical to
 | |
| @code{utmpname}.  On the GNU system, @code{utmpxname} is simply an
 | |
| alias for @code{utmpname}.
 | |
| @end deftypefun
 | |
| 
 | |
| You can translate between a traditional @code{struct utmp} and an XPG
 | |
| @code{struct utmpx} with the following functions.  On the GNU system,
 | |
| these functions are merely copies, since the two structures are
 | |
| identical.
 | |
| 
 | |
| @comment utmpx.h
 | |
| @comment utmp.h
 | |
| @comment GNU
 | |
| @deftypefun int getutmp (const struct utmpx *utmpx, struct utmp *utmp)
 | |
| @code{getutmp} copies the information, insofar as the structures are
 | |
| compatible, from @var{utmpx} to @var{utmp}.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment utmpx.h
 | |
| @comment utmp.h
 | |
| @comment GNU
 | |
| @deftypefun int getutmpx (const struct utmp *utmp, struct utmpx *utmpx)
 | |
| @code{getutmpx} copies the information, insofar as the structures are
 | |
| compatible, from @var{utmp} to @var{utmpx}.
 | |
| @end deftypefun
 | |
| 
 | |
| 
 | |
| @node Logging In and Out
 | |
| @subsection Logging In and Out
 | |
| 
 | |
| These functions, derived from BSD, are available in the separate
 | |
| @file{libutil} library, and declared in @file{utmp.h}.
 | |
| @pindex utmp.h
 | |
| 
 | |
| Note that the @code{ut_user} member of @code{struct utmp} is called
 | |
| @code{ut_name} in BSD.  Therefore, @code{ut_name} is defined as an alias
 | |
| for @code{ut_user} in @file{utmp.h}.
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment BSD
 | |
| @deftypefun int login_tty (int @var{filedes})
 | |
| This function makes @var{filedes} the controlling terminal of the
 | |
| current process, redirects standard input, standard output and
 | |
| standard error output to this terminal, and closes @var{filedes}.
 | |
| 
 | |
| This function returns @code{0} on successful completion, and @code{-1}
 | |
| on error.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment BSD
 | |
| @deftypefun void login (const struct utmp *@var{entry})
 | |
| The @code{login} functions inserts an entry into the user accounting
 | |
| database.  The @code{ut_line} member is set to the name of the terminal
 | |
| on standard input.  If standard input is not a terminal @code{login}
 | |
| uses standard output or standard error output to determine the name of
 | |
| the terminal.  If @code{struct utmp} has a @code{ut_type} member,
 | |
| @code{login} sets it to @code{USER_PROCESS}, and if there is an
 | |
| @code{ut_pid} member, it will be set to the process ID of the current
 | |
| process.  The remaining entries are copied from @var{entry}.
 | |
| 
 | |
| A copy of the entry is written to the user accounting log file.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment BSD
 | |
| @deftypefun int logout (const char *@var{ut_line})
 | |
| This function modifies the user accounting database to indicate that the
 | |
| user on @var{ut_line} has logged out.
 | |
| 
 | |
| The @code{logout} function returns @code{1} if the entry was successfully
 | |
| written to the database, or @code{0} on error.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment utmp.h
 | |
| @comment BSD
 | |
| @deftypefun void logwtmp (const char *@var{ut_line}, const char *@var{ut_name}, const char *@var{ut_host})
 | |
| The @code{logwtmp} function appends an entry to the user accounting log
 | |
| file, for the current time and the information provided in the
 | |
| @var{ut_line}, @var{ut_name} and @var{ut_host} arguments.
 | |
| @end deftypefun
 | |
| 
 | |
| @strong{Portability Note:} The BSD @code{struct utmp} only has the
 | |
| @code{ut_line}, @code{ut_name}, @code{ut_host} and @code{ut_time}
 | |
| members.  Older systems do not even have the @code{ut_host} member.
 | |
| 
 | |
| 
 | |
| @node User Database
 | |
| @section User Database
 | |
| @cindex user database
 | |
| @cindex password database
 | |
| @pindex /etc/passwd
 | |
| 
 | |
| This section describes 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.1c
 | |
| @deftypefun int getpwuid_r (uid_t @var{uid}, struct passwd *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct passwd **@var{result})
 | |
| This function is similar to @code{getpwuid} in that it returns
 | |
| information about the user whose user ID is @var{uid}.  However, it
 | |
| fills the user supplied structure pointed to by @var{result_buf} with
 | |
| the information instead of using a static buffer.  The first
 | |
| @var{buflen} bytes of the additional buffer pointed to by @var{buffer}
 | |
| are used to contain additional information, normally strings which are
 | |
| pointed to by the elements of the result structure.
 | |
| 
 | |
| If a user with ID @var{uid} is found, the pointer returned in
 | |
| @var{result} points to the record which contains the wanted data (i.e.,
 | |
| @var{result} contains the value @var{result_buf}).  If no user is found
 | |
| or if an error occurred, the pointer returned in @var{result} is a null
 | |
| pointer.  The function returns zero or an error code.  If the buffer
 | |
| @var{buffer} is too small to contain all the needed information, the
 | |
| error code @code{ERANGE} is returned and @var{errno} is set to
 | |
| @code{ERANGE}.
 | |
| @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 return indicates there is no user named @var{name}.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment pwd.h
 | |
| @comment POSIX.1c
 | |
| @deftypefun int getpwnam_r (const char *@var{name}, struct passwd *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct passwd **@var{result})
 | |
| This function is similar to @code{getpwnam} in that is returns
 | |
| information about the user whose user name is @var{name}.  However, like
 | |
| @code{getpwuid_r}, it fills the user supplied buffers in
 | |
| @var{result_buf} and @var{buffer} with the information instead of using
 | |
| a static buffer.
 | |
| 
 | |
| The return values are the same as for @code{getpwuid_r}.
 | |
| @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.
 | |
| 
 | |
| The stream must correspond to a file in the same format as the standard
 | |
| password database file.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment pwd.h
 | |
| @comment GNU
 | |
| @deftypefun int fgetpwent_r (FILE *@var{stream}, struct passwd *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct passwd **@var{result})
 | |
| This function is similar to @code{fgetpwent} in that it reads the next
 | |
| user entry from @var{stream}.  But the result is returned in the
 | |
| structure pointed to by @var{result_buf}.  The
 | |
| first @var{buflen} bytes of the additional buffer pointed to by
 | |
| @var{buffer} are used to contain additional information, normally
 | |
| strings which are pointed to by the elements of the result structure.
 | |
| 
 | |
| The stream must correspond to a file in the same format as the standard
 | |
| password database file.
 | |
| 
 | |
| If the function returns zero @var{result} points to the structure with
 | |
| the wanted data (normally this is in @var{result_buf}).  If errors
 | |
| occurred the return value is nonzero and @var{result} contains a null
 | |
| pointer.
 | |
| @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} and
 | |
| @code{getpwent_r} use 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.
 | |
| 
 | |
| A null pointer is returned when no more entries are available.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment pwd.h
 | |
| @comment GNU
 | |
| @deftypefun int getpwent_r (struct passwd *@var{result_buf}, char *@var{buffer}, int @var{buflen}, struct passwd **@var{result})
 | |
| This function is similar to @code{getpwent} in that it returns the next
 | |
| entry from the stream initialized by @code{setpwent}.  Like
 | |
| @code{fgetpwent_r}, it uses the user-supplied buffers in
 | |
| @var{result_buf} and @var{buffer} to return the information requested.
 | |
| 
 | |
| The return values are the same as for @code{fgetpwent_r}.
 | |
| 
 | |
| @end deftypefun
 | |
| 
 | |
| @comment pwd.h
 | |
| @comment SVID, BSD
 | |
| @deftypefun void endpwent (void)
 | |
| This function closes the internal stream used by @code{getpwent} or
 | |
| @code{getpwent_r}.
 | |
| @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.
 | |
| @c Then how are programmers to modify the password file? -zw
 | |
| 
 | |
| 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 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 POSIX.1c
 | |
| @deftypefun int getgrgid_r (gid_t @var{gid}, struct group *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct group **@var{result})
 | |
| This function is similar to @code{getgrgid} in that it returns
 | |
| information about the group whose group ID is @var{gid}.  However, it
 | |
| fills the user supplied structure pointed to by @var{result_buf} with
 | |
| the information instead of using a static buffer.  The first
 | |
| @var{buflen} bytes of the additional buffer pointed to by @var{buffer}
 | |
| are used to contain additional information, normally strings which are
 | |
| pointed to by the elements of the result structure.
 | |
| 
 | |
| If a group with ID @var{gid} is found, the pointer returned in
 | |
| @var{result} points to the record which contains the wanted data (i.e.,
 | |
| @var{result} contains the value @var{result_buf}).  If no group is found
 | |
| or if an error occurred, the pointer returned in @var{result} is a null
 | |
| pointer.  The function returns zero or an error code.  If the buffer
 | |
| @var{buffer} is too small to contain all the needed information, the
 | |
| error code @code{ERANGE} is returned and @var{errno} is set to
 | |
| @code{ERANGE}.
 | |
| @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
 | |
| 
 | |
| @comment grp.h
 | |
| @comment POSIX.1c
 | |
| @deftypefun int getgrnam_r (const char *@var{name}, struct group *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct group **@var{result})
 | |
| This function is similar to @code{getgrnam} in that is returns
 | |
| information about the group whose group name is @var{name}.  Like
 | |
| @code{getgrgid_r}, it uses the user supplied buffers in
 | |
| @var{result_buf} and @var{buffer}, not a static buffer.
 | |
| 
 | |
| The return values are the same as for @code{getgrgid_r}
 | |
| @code{ERANGE}.
 | |
| @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 overwritten 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
 | |
| 
 | |
| @comment grp.h
 | |
| @comment GNU
 | |
| @deftypefun int fgetgrent_r (FILE *@var{stream}, struct group *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct group **@var{result})
 | |
| This function is similar to @code{fgetgrent} in that it reads the next
 | |
| user entry from @var{stream}.  But the result is returned in the
 | |
| structure pointed to by @var{result_buf}.  The first @var{buflen} bytes
 | |
| of the additional buffer pointed to by @var{buffer} are used to contain
 | |
| additional information, normally strings which are pointed to by the
 | |
| elements of the result structure.
 | |
| 
 | |
| This stream must correspond to a file in the same format as the standard
 | |
| group database file.
 | |
| 
 | |
| If the function returns zero @var{result} points to the structure with
 | |
| the wanted data (normally this is in @var{result_buf}).  If errors
 | |
| occurred the return value is non-zero and @var{result} contains a null
 | |
| pointer.
 | |
| @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} or @code{getgrent_r}.
 | |
| @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 overwritten 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 GNU
 | |
| @deftypefun int getgrent_r (struct group *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct group **@var{result})
 | |
| This function is similar to @code{getgrent} in that it returns the next
 | |
| entry from the stream initialized by @code{setgrent}.  Like
 | |
| @code{fgetgrent_r}, it places the result in user-supplied buffers
 | |
| pointed to @var{result_buf} and @var{buffer}.
 | |
| 
 | |
| If the function returns zero @var{result} contains a pointer to the data
 | |
| (normally equal to @var{result_buf}).  If errors occurred the return
 | |
| value is non-zero and @var{result} contains a null pointer.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment grp.h
 | |
| @comment SVID, BSD
 | |
| @deftypefun void endgrent (void)
 | |
| This function closes the internal stream used by @code{getgrent} or
 | |
| @code{getgrent_r}.
 | |
| @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
 | |
| 
 | |
| @node Netgroup Database
 | |
| @section Netgroup Database
 | |
| 
 | |
| @menu
 | |
| * Netgroup Data::                  Data in the Netgroup database and where
 | |
|                                    it comes from.
 | |
| * Lookup Netgroup::                How to look for a particular netgroup.
 | |
| * Netgroup Membership::            How to test for netgroup membership.
 | |
| @end menu
 | |
| 
 | |
| @node Netgroup Data
 | |
| @subsection Netgroup Data
 | |
| 
 | |
| @cindex Netgroup
 | |
| Sometimes it is useful to group users according to other criteria
 | |
| (@pxref{Group Database}).  E.g., it is useful to associate a certain
 | |
| group of users with a certain machine.  On the other hand grouping of
 | |
| host names is not supported so far.
 | |
| 
 | |
| In Sun Microsystems SunOS appeared a new kind of database, the netgroup
 | |
| database.  It allows grouping hosts, users, and domains freely, giving
 | |
| them individual names.  To be more concrete, a netgroup is a list of triples
 | |
| consisting of a host name, a user name, and a domain name where any of
 | |
| the entries can be a wildcard entry matching all inputs.  A last
 | |
| possibility is that names of other netgroups can also be given in the
 | |
| list specifying a netgroup.  So one can construct arbitrary hierarchies
 | |
| without loops.
 | |
| 
 | |
| Sun's implementation allows netgroups only for the @code{nis} or
 | |
| @code{nisplus} service, @pxref{Services in the NSS configuration}.  The
 | |
| implementation in the GNU C library has no such restriction.  An entry
 | |
| in either of the input services must have the following form:
 | |
| 
 | |
| @smallexample
 | |
| @var{groupname} ( @var{groupname} | @code{(}@var{hostname}@code{,}@var{username}@code{,}@code{domainname}@code{)} )+
 | |
| @end smallexample
 | |
| 
 | |
| Any of the fields in the triple can be empty which means anything
 | |
| matches.  While describing the functions we will see that the opposite
 | |
| case is useful as well.  I.e., there may be entries which will not
 | |
| match any input.  For entries like this, a name consisting of the single
 | |
| character @code{-} shall be used.
 | |
| 
 | |
| @node Lookup Netgroup
 | |
| @subsection Looking up one Netgroup
 | |
| 
 | |
| The lookup functions for netgroups are a bit different to all other
 | |
| system database handling functions.  Since a single netgroup can contain
 | |
| many entries a two-step process is needed.  First a single netgroup is
 | |
| selected and then one can iterate over all entries in this netgroup.
 | |
| These functions are declared in @file{netdb.h}.
 | |
| 
 | |
| @comment netdb.h
 | |
| @comment BSD
 | |
| @deftypefun int setnetgrent (const char *@var{netgroup})
 | |
| A call to this function initializes the internal state of the library to
 | |
| allow following calls of the @code{getnetgrent} to iterate over all entries
 | |
| in the netgroup with name @var{netgroup}.
 | |
| 
 | |
| When the call is successful (i.e., when a netgroup with this name exists)
 | |
| the return value is @code{1}.  When the return value is @code{0} no
 | |
| netgroup of this name is known or some other error occurred.
 | |
| @end deftypefun
 | |
| 
 | |
| It is important to remember that there is only one single state for
 | |
| iterating the netgroups.  Even if the programmer uses the
 | |
| @code{getnetgrent_r} function the result is not really reentrant since
 | |
| always only one single netgroup at a time can be processed.  If the
 | |
| program needs to process more than one netgroup simultaneously she
 | |
| must protect this by using external locking.  This problem was
 | |
| introduced in the original netgroups implementation in SunOS and since
 | |
| we must stay compatible it is not possible to change this.
 | |
| 
 | |
| Some other functions also use the netgroups state.  Currently these are
 | |
| the @code{innetgr} function and parts of the implementation of the
 | |
| @code{compat} service part of the NSS implementation.
 | |
| 
 | |
| @comment netdb.h
 | |
| @comment BSD
 | |
| @deftypefun int getnetgrent (char **@var{hostp}, char **@var{userp}, char **@var{domainp})
 | |
| This function returns the next unprocessed entry of the currently
 | |
| selected netgroup.  The string pointers, in which addresses are passed in
 | |
| the arguments @var{hostp}, @var{userp}, and @var{domainp}, will contain
 | |
| after a successful call pointers to appropriate strings.  If the string
 | |
| in the next entry is empty the pointer has the value @code{NULL}.
 | |
| The returned string pointers are only valid if none of the netgroup
 | |
| related functions are called.
 | |
| 
 | |
| The return value is @code{1} if the next entry was successfully read.  A
 | |
| value of @code{0} means no further entries exist or internal errors occurred.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment netdb.h
 | |
| @comment GNU
 | |
| @deftypefun int getnetgrent_r (char **@var{hostp}, char **@var{userp}, char **@var{domainp}, char *@var{buffer}, int @var{buflen})
 | |
| This function is similar to @code{getnetgrent} with only one exception:
 | |
| the strings the three string pointers @var{hostp}, @var{userp}, and
 | |
| @var{domainp} point to, are placed in the buffer of @var{buflen} bytes
 | |
| starting at @var{buffer}.  This means the returned values are valid
 | |
| even after other netgroup related functions are called.
 | |
| 
 | |
| The return value is @code{1} if the next entry was successfully read and
 | |
| the buffer contains enough room to place the strings in it.  @code{0} is
 | |
| returned in case no more entries are found, the buffer is too small, or
 | |
| internal errors occurred.
 | |
| 
 | |
| This function is a GNU extension.  The original implementation in the
 | |
| SunOS libc does not provide this function.
 | |
| @end deftypefun
 | |
| 
 | |
| @comment netdb.h
 | |
| @comment BSD
 | |
| @deftypefun void endnetgrent (void)
 | |
| This function frees all buffers which were allocated to process the last
 | |
| selected netgroup.  As a result all string pointers returned by calls
 | |
| to @code{getnetgrent} are invalid afterwards.
 | |
| @end deftypefun
 | |
| 
 | |
| @node Netgroup Membership
 | |
| @subsection Testing for Netgroup Membership
 | |
| 
 | |
| It is often not necessary to scan the whole netgroup since often the
 | |
| only interesting question is whether a given entry is part of the
 | |
| selected netgroup.
 | |
| 
 | |
| @comment netdb.h
 | |
| @comment BSD
 | |
| @deftypefun int innetgr (const char *@var{netgroup}, const char *@var{host}, const char *@var{user}, const char *@var{domain})
 | |
| This function tests whether the triple specified by the parameters
 | |
| @var{hostp}, @var{userp}, and @var{domainp} is part of the netgroup
 | |
| @var{netgroup}.  Using this function has the advantage that
 | |
| 
 | |
| @enumerate
 | |
| @item
 | |
| no other netgroup function can use the global netgroup state since
 | |
| internal locking is used and
 | |
| @item
 | |
| the function is implemented more efficiently than successive calls
 | |
| to the other @code{set}/@code{get}/@code{endnetgrent} functions.
 | |
| @end enumerate
 | |
| 
 | |
| Any of the pointers @var{hostp}, @var{userp}, and @var{domainp} can be
 | |
| @code{NULL} which means any value is accepted in this position.  This is
 | |
| also true for the name @code{-} which should not match any other string
 | |
| otherwise.
 | |
| 
 | |
| The return value is @code{1} if an entry matching the given triple is
 | |
| found in the netgroup.  The return value is @code{0} if the netgroup
 | |
| itself is not found, the netgroup does not contain the triple or
 | |
| internal errors occurred.
 | |
| @end deftypefun
 |