| lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 1 | @node Users and Groups, System Management, Name Service Switch, Top | 
|  | 2 | @c %MENU% How users are identified and classified | 
|  | 3 | @chapter Users and Groups | 
|  | 4 |  | 
|  | 5 | Every user who can log in on the system is identified by a unique number | 
|  | 6 | called the @dfn{user ID}.  Each process has an effective user ID which | 
|  | 7 | says which user's access permissions it has. | 
|  | 8 |  | 
|  | 9 | Users are classified into @dfn{groups} for access control purposes.  Each | 
|  | 10 | process has one or more @dfn{group ID values} which say which groups the | 
|  | 11 | process can use for access to files. | 
|  | 12 |  | 
|  | 13 | The effective user and group IDs of a process collectively form its | 
|  | 14 | @dfn{persona}.  This determines which files the process can access. | 
|  | 15 | Normally, a process inherits its persona from the parent process, but | 
|  | 16 | under special circumstances a process can change its persona and thus | 
|  | 17 | change its access permissions. | 
|  | 18 |  | 
|  | 19 | Each file in the system also has a user ID and a group ID.  Access | 
|  | 20 | control works by comparing the user and group IDs of the file with those | 
|  | 21 | of the running process. | 
|  | 22 |  | 
|  | 23 | The system keeps a database of all the registered users, and another | 
|  | 24 | database of all the defined groups.  There are library functions you | 
|  | 25 | can use to examine these databases. | 
|  | 26 |  | 
|  | 27 | @menu | 
|  | 28 | * User and Group IDs::          Each user has a unique numeric ID; | 
|  | 29 | likewise for groups. | 
|  | 30 | * Process Persona::             The user IDs and group IDs of a process. | 
|  | 31 | * Why Change Persona::          Why a program might need to change | 
|  | 32 | its user and/or group IDs. | 
|  | 33 | * How Change Persona::          Changing the user and group IDs. | 
|  | 34 | * Reading Persona::             How to examine the user and group IDs. | 
|  | 35 |  | 
|  | 36 | * Setting User ID::             Functions for setting the user ID. | 
|  | 37 | * Setting Groups::              Functions for setting the group IDs. | 
|  | 38 |  | 
|  | 39 | * Enable/Disable Setuid::       Turning setuid access on and off. | 
|  | 40 | * Setuid Program Example::      The pertinent parts of one sample program. | 
|  | 41 | * Tips for Setuid::             How to avoid granting unlimited access. | 
|  | 42 |  | 
|  | 43 | * Who Logged In::               Getting the name of the user who logged in, | 
|  | 44 | or of the real user ID of the current process. | 
|  | 45 |  | 
|  | 46 | * User Accounting Database::    Keeping information about users and various | 
|  | 47 | actions in databases. | 
|  | 48 |  | 
|  | 49 | * User Database::               Functions and data structures for | 
|  | 50 | accessing the user database. | 
|  | 51 | * Group Database::              Functions and data structures for | 
|  | 52 | accessing the group database. | 
|  | 53 | * Database Example::            Example program showing the use of database | 
|  | 54 | inquiry functions. | 
|  | 55 | * Netgroup Database::           Functions for accessing the netgroup database. | 
|  | 56 | @end menu | 
|  | 57 |  | 
|  | 58 | @node User and Group IDs | 
|  | 59 | @section User and Group IDs | 
|  | 60 |  | 
|  | 61 | @cindex login name | 
|  | 62 | @cindex user name | 
|  | 63 | @cindex user ID | 
|  | 64 | Each user account on a computer system is identified by a @dfn{user | 
|  | 65 | name} (or @dfn{login name}) and @dfn{user ID}.  Normally, each user name | 
|  | 66 | has a unique user ID, but it is possible for several login names to have | 
|  | 67 | the same user ID.  The user names and corresponding user IDs are stored | 
|  | 68 | in a data base which you can access as described in @ref{User Database}. | 
|  | 69 |  | 
|  | 70 | @cindex group name | 
|  | 71 | @cindex group ID | 
|  | 72 | Users are classified in @dfn{groups}.  Each user name belongs to one | 
|  | 73 | @dfn{default group} and may also belong to any number of | 
|  | 74 | @dfn{supplementary groups}.  Users who are members of the same group can | 
|  | 75 | share resources (such as files) that are not accessible to users who are | 
|  | 76 | not a member of that group.  Each group has a @dfn{group name} and | 
|  | 77 | @dfn{group ID}.  @xref{Group Database}, for how to find information | 
|  | 78 | about a group ID or group name. | 
|  | 79 |  | 
|  | 80 | @node Process Persona | 
|  | 81 | @section The Persona of a Process | 
|  | 82 | @cindex persona | 
|  | 83 | @cindex effective user ID | 
|  | 84 | @cindex effective group ID | 
|  | 85 | @cindex supplementary group IDs | 
|  | 86 |  | 
|  | 87 | @c When Hurd is more widely used, explain multiple effective user IDs | 
|  | 88 | @c here. -zw | 
|  | 89 | At any time, each process has an @dfn{effective user ID}, a @dfn{effective | 
|  | 90 | group ID}, and a set of @dfn{supplementary group IDs}.  These IDs | 
|  | 91 | determine the privileges of the process.  They are collectively | 
|  | 92 | called the @dfn{persona} of the process, because they determine ``who it | 
|  | 93 | is'' for purposes of access control. | 
|  | 94 |  | 
|  | 95 | Your login shell starts out with a persona which consists of your user | 
|  | 96 | ID, your default group ID, and your supplementary group IDs (if you are | 
|  | 97 | in more than one group).  In normal circumstances, all your other processes | 
|  | 98 | inherit these values. | 
|  | 99 |  | 
|  | 100 | @cindex real user ID | 
|  | 101 | @cindex real group ID | 
|  | 102 | A process also has a @dfn{real user ID} which identifies the user who | 
|  | 103 | created the process, and a @dfn{real group ID} which identifies that | 
|  | 104 | user's default group.  These values do not play a role in access | 
|  | 105 | control, so we do not consider them part of the persona.  But they are | 
|  | 106 | also important. | 
|  | 107 |  | 
|  | 108 | Both the real and effective user ID can be changed during the lifetime | 
|  | 109 | of a process.  @xref{Why Change Persona}. | 
|  | 110 |  | 
|  | 111 | For details on how a process's effective user ID and group IDs affect | 
|  | 112 | its permission to access files, see @ref{Access Permission}. | 
|  | 113 |  | 
|  | 114 | The effective user ID of a process also controls permissions for sending | 
|  | 115 | signals using the @code{kill} function.  @xref{Signaling Another | 
|  | 116 | Process}. | 
|  | 117 |  | 
|  | 118 | Finally, there are many operations which can only be performed by a | 
|  | 119 | process whose effective user ID is zero.  A process with this user ID is | 
|  | 120 | a @dfn{privileged process}.  Commonly the user name @code{root} is | 
|  | 121 | associated with user ID 0, but there may be other user names with this | 
|  | 122 | ID. | 
|  | 123 | @c !!! should mention POSIX capabilities here. | 
|  | 124 |  | 
|  | 125 | @node Why Change Persona | 
|  | 126 | @section Why Change the Persona of a Process? | 
|  | 127 |  | 
|  | 128 | The most obvious situation where it is necessary for a process to change | 
|  | 129 | its user and/or group IDs is the @code{login} program.  When | 
|  | 130 | @code{login} starts running, its user ID is @code{root}.  Its job is to | 
|  | 131 | start a shell whose user and group IDs are those of the user who is | 
|  | 132 | logging in.  (To accomplish this fully, @code{login} must set the real | 
|  | 133 | user and group IDs as well as its persona.  But this is a special case.) | 
|  | 134 |  | 
|  | 135 | The more common case of changing persona is when an ordinary user | 
|  | 136 | program needs access to a resource that wouldn't ordinarily be | 
|  | 137 | accessible to the user actually running it. | 
|  | 138 |  | 
|  | 139 | For example, you may have a file that is controlled by your program but | 
|  | 140 | that shouldn't be read or modified directly by other users, either | 
|  | 141 | because it implements some kind of locking protocol, or because you want | 
|  | 142 | to preserve the integrity or privacy of the information it contains. | 
|  | 143 | This kind of restricted access can be implemented by having the program | 
|  | 144 | change its effective user or group ID to match that of the resource. | 
|  | 145 |  | 
|  | 146 | Thus, imagine a game program that saves scores in a file.  The game | 
|  | 147 | program itself needs to be able to update this file no matter who is | 
|  | 148 | running it, but if users can write the file without going through the | 
|  | 149 | game, they can give themselves any scores they like.  Some people | 
|  | 150 | consider this undesirable, or even reprehensible.  It can be prevented | 
|  | 151 | by creating a new user ID and login name (say, @code{games}) to own the | 
|  | 152 | scores file, and make the file writable only by this user.  Then, when | 
|  | 153 | the game program wants to update this file, it can change its effective | 
|  | 154 | user ID to be that for @code{games}.  In effect, the program must | 
|  | 155 | adopt the persona of @code{games} so it can write the scores file. | 
|  | 156 |  | 
|  | 157 | @node How Change Persona | 
|  | 158 | @section How an Application Can Change Persona | 
|  | 159 | @cindex @code{setuid} programs | 
|  | 160 | @cindex saved set-user-ID | 
|  | 161 | @cindex saved set-group-ID | 
|  | 162 | @cindex @code{_POSIX_SAVED_IDS} | 
|  | 163 |  | 
|  | 164 | The ability to change the persona of a process can be a source of | 
|  | 165 | unintentional privacy violations, or even intentional abuse.  Because of | 
|  | 166 | the potential for problems, changing persona is restricted to special | 
|  | 167 | circumstances. | 
|  | 168 |  | 
|  | 169 | You can't arbitrarily set your user ID or group ID to anything you want; | 
|  | 170 | only privileged processes can do that.  Instead, the normal way for a | 
|  | 171 | program to change its persona is that it has been set up in advance to | 
|  | 172 | change to a particular user or group.  This is the function of the setuid | 
|  | 173 | and setgid bits of a file's access mode.  @xref{Permission Bits}. | 
|  | 174 |  | 
|  | 175 | When the setuid bit of an executable file is on, executing that file | 
|  | 176 | gives the process a third user ID: the @dfn{file user ID}.  This ID is | 
|  | 177 | set to the owner ID of the file.  The system then changes the effective | 
|  | 178 | user ID to the file user ID.  The real user ID remains as it was. | 
|  | 179 | Likewise, if the setgid bit is on, the process is given a @dfn{file | 
|  | 180 | group ID} equal to the group ID of the file, and its effective group ID | 
|  | 181 | is changed to the file group ID. | 
|  | 182 |  | 
|  | 183 | If a process has a file ID (user or group), then it can at any time | 
|  | 184 | change its effective ID to its real ID and back to its file ID. | 
|  | 185 | Programs use this feature to relinquish their special privileges except | 
|  | 186 | when they actually need them.  This makes it less likely that they can | 
|  | 187 | be tricked into doing something inappropriate with their privileges. | 
|  | 188 |  | 
|  | 189 | @strong{Portability Note:} Older systems do not have file IDs. | 
|  | 190 | To determine if a system has this feature, you can test the compiler | 
|  | 191 | define @code{_POSIX_SAVED_IDS}.  (In the POSIX standard, file IDs are | 
|  | 192 | known as saved IDs.) | 
|  | 193 |  | 
|  | 194 | @xref{File Attributes}, for a more general discussion of file modes and | 
|  | 195 | accessibility. | 
|  | 196 |  | 
|  | 197 | @node Reading Persona | 
|  | 198 | @section Reading the Persona of a Process | 
|  | 199 |  | 
|  | 200 | Here are detailed descriptions of the functions for reading the user and | 
|  | 201 | group IDs of a process, both real and effective.  To use these | 
|  | 202 | facilities, you must include the header files @file{sys/types.h} and | 
|  | 203 | @file{unistd.h}. | 
|  | 204 | @pindex unistd.h | 
|  | 205 | @pindex sys/types.h | 
|  | 206 |  | 
|  | 207 | @comment sys/types.h | 
|  | 208 | @comment POSIX.1 | 
|  | 209 | @deftp {Data Type} uid_t | 
|  | 210 | This is an integer data type used to represent user IDs.  In | 
|  | 211 | @theglibc{}, this is an alias for @code{unsigned int}. | 
|  | 212 | @end deftp | 
|  | 213 |  | 
|  | 214 | @comment sys/types.h | 
|  | 215 | @comment POSIX.1 | 
|  | 216 | @deftp {Data Type} gid_t | 
|  | 217 | This is an integer data type used to represent group IDs.  In | 
|  | 218 | @theglibc{}, this is an alias for @code{unsigned int}. | 
|  | 219 | @end deftp | 
|  | 220 |  | 
|  | 221 | @comment unistd.h | 
|  | 222 | @comment POSIX.1 | 
|  | 223 | @deftypefun uid_t getuid (void) | 
|  | 224 | @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} | 
|  | 225 | @c Atomic syscall, except on hurd, where it takes a lock within a hurd | 
|  | 226 | @c critical section. | 
|  | 227 | The @code{getuid} function returns the real user ID of the process. | 
|  | 228 | @end deftypefun | 
|  | 229 |  | 
|  | 230 | @comment unistd.h | 
|  | 231 | @comment POSIX.1 | 
|  | 232 | @deftypefun gid_t getgid (void) | 
|  | 233 | @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} | 
|  | 234 | The @code{getgid} function returns the real group ID of the process. | 
|  | 235 | @end deftypefun | 
|  | 236 |  | 
|  | 237 | @comment unistd.h | 
|  | 238 | @comment POSIX.1 | 
|  | 239 | @deftypefun uid_t geteuid (void) | 
|  | 240 | @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} | 
|  | 241 | The @code{geteuid} function returns the effective user ID of the process. | 
|  | 242 | @end deftypefun | 
|  | 243 |  | 
|  | 244 | @comment unistd.h | 
|  | 245 | @comment POSIX.1 | 
|  | 246 | @deftypefun gid_t getegid (void) | 
|  | 247 | @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} | 
|  | 248 | The @code{getegid} function returns the effective group ID of the process. | 
|  | 249 | @end deftypefun | 
|  | 250 |  | 
|  | 251 | @comment unistd.h | 
|  | 252 | @comment POSIX.1 | 
|  | 253 | @deftypefun int getgroups (int @var{count}, gid_t *@var{groups}) | 
|  | 254 | @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} | 
|  | 255 | The @code{getgroups} function is used to inquire about the supplementary | 
|  | 256 | group IDs of the process.  Up to @var{count} of these group IDs are | 
|  | 257 | stored in the array @var{groups}; the return value from the function is | 
|  | 258 | the number of group IDs actually stored.  If @var{count} is smaller than | 
|  | 259 | the total number of supplementary group IDs, then @code{getgroups} | 
|  | 260 | returns a value of @code{-1} and @code{errno} is set to @code{EINVAL}. | 
|  | 261 |  | 
|  | 262 | If @var{count} is zero, then @code{getgroups} just returns the total | 
|  | 263 | number of supplementary group IDs.  On systems that do not support | 
|  | 264 | supplementary groups, this will always be zero. | 
|  | 265 |  | 
|  | 266 | Here's how to use @code{getgroups} to read all the supplementary group | 
|  | 267 | IDs: | 
|  | 268 |  | 
|  | 269 | @smallexample | 
|  | 270 | @group | 
|  | 271 | gid_t * | 
|  | 272 | read_all_groups (void) | 
|  | 273 | @{ | 
|  | 274 | int ngroups = getgroups (0, NULL); | 
|  | 275 | gid_t *groups | 
|  | 276 | = (gid_t *) xmalloc (ngroups * sizeof (gid_t)); | 
|  | 277 | int val = getgroups (ngroups, groups); | 
|  | 278 | if (val < 0) | 
|  | 279 | @{ | 
|  | 280 | free (groups); | 
|  | 281 | return NULL; | 
|  | 282 | @} | 
|  | 283 | return groups; | 
|  | 284 | @} | 
|  | 285 | @end group | 
|  | 286 | @end smallexample | 
|  | 287 | @end deftypefun | 
|  | 288 |  | 
|  | 289 | @node Setting User ID | 
|  | 290 | @section Setting the User ID | 
|  | 291 |  | 
|  | 292 | This section describes the functions for altering the user ID (real | 
|  | 293 | and/or effective) of a process.  To use these facilities, you must | 
|  | 294 | include the header files @file{sys/types.h} and @file{unistd.h}. | 
|  | 295 | @pindex unistd.h | 
|  | 296 | @pindex sys/types.h | 
|  | 297 |  | 
|  | 298 | @comment unistd.h | 
|  | 299 | @comment POSIX.1 | 
|  | 300 | @deftypefun int seteuid (uid_t @var{neweuid}) | 
|  | 301 | @safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} | 
|  | 302 | @c seteuid @asulock @aculock | 
|  | 303 | @c  INLINE_SETXID_SYSCALL @asulock @aculock | 
|  | 304 | @c    This may be just a unix syscall, or the ugliness below used by | 
|  | 305 | @c    nptl to propagate the syscall to all cloned processes used to | 
|  | 306 | @c    implement threads. | 
|  | 307 | @c   nptl_setxid @asulock @aculock | 
|  | 308 | @c     while holding the stack_alloc_lock, mark with SETXID_BITMASK all | 
|  | 309 | @c     threads that are not exiting, signal them until no thread remains | 
|  | 310 | @c     marked, clear the marks and run the syscall, then release the lock. | 
|  | 311 | @c    lll_lock @asulock @aculock | 
|  | 312 | @c    list_for_each ok | 
|  | 313 | @c    list_entry ok | 
|  | 314 | @c    setxid_mark_thread ok | 
|  | 315 | @c      if a thread is initializing, wait for it to be cloned. | 
|  | 316 | @c      mark it with SETXID_BITMASK if it's not exiting | 
|  | 317 | @c    setxid_signal_thread ok | 
|  | 318 | @c      if a thread is marked with SETXID_BITMASK, | 
|  | 319 | @c        send it the SIGSETXID signal | 
|  | 320 | @c    setxid_unmark_thread ok | 
|  | 321 | @c      clear SETXID_BITMASK and release the futex if SETXID_BITMASK is | 
|  | 322 | @c      set. | 
|  | 323 | @c    <syscall> ok | 
|  | 324 | @c    lll_unlock @aculock | 
|  | 325 | @c | 
|  | 326 | @c  sighandler_setxid ok | 
|  | 327 | @c    issue the syscall, clear SETXID_BITMASK, release the futex, and | 
|  | 328 | @c    wake up the signaller loop if the counter reached zero. | 
|  | 329 | This function sets the effective user ID of a process to @var{neweuid}, | 
|  | 330 | provided that the process is allowed to change its effective user ID.  A | 
|  | 331 | privileged process (effective user ID zero) can change its effective | 
|  | 332 | user ID to any legal value.  An unprivileged process with a file user ID | 
|  | 333 | can change its effective user ID to its real user ID or to its file user | 
|  | 334 | ID.  Otherwise, a process may not change its effective user ID at all. | 
|  | 335 |  | 
|  | 336 | The @code{seteuid} function returns a value of @code{0} to indicate | 
|  | 337 | successful completion, and a value of @code{-1} to indicate an error. | 
|  | 338 | The following @code{errno} error conditions are defined for this | 
|  | 339 | function: | 
|  | 340 |  | 
|  | 341 | @table @code | 
|  | 342 | @item EINVAL | 
|  | 343 | The value of the @var{neweuid} argument is invalid. | 
|  | 344 |  | 
|  | 345 | @item EPERM | 
|  | 346 | The process may not change to the specified ID. | 
|  | 347 | @end table | 
|  | 348 |  | 
|  | 349 | Older systems (those without the @code{_POSIX_SAVED_IDS} feature) do not | 
|  | 350 | have this function. | 
|  | 351 | @end deftypefun | 
|  | 352 |  | 
|  | 353 | @comment unistd.h | 
|  | 354 | @comment POSIX.1 | 
|  | 355 | @deftypefun int setuid (uid_t @var{newuid}) | 
|  | 356 | @safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} | 
|  | 357 | @c setuid @asulock @aculock | 
|  | 358 | @c  INLINE_SETXID_SYSCALL dup @asulock @aculock | 
|  | 359 | If the calling process is privileged, this function sets both the real | 
|  | 360 | and effective user ID of the process to @var{newuid}.  It also deletes | 
|  | 361 | the file user ID of the process, if any.  @var{newuid} may be any | 
|  | 362 | legal value.  (Once this has been done, there is no way to recover the | 
|  | 363 | old effective user ID.) | 
|  | 364 |  | 
|  | 365 | If the process is not privileged, and the system supports the | 
|  | 366 | @code{_POSIX_SAVED_IDS} feature, then this function behaves like | 
|  | 367 | @code{seteuid}. | 
|  | 368 |  | 
|  | 369 | The return values and error conditions are the same as for @code{seteuid}. | 
|  | 370 | @end deftypefun | 
|  | 371 |  | 
|  | 372 | @comment unistd.h | 
|  | 373 | @comment BSD | 
|  | 374 | @deftypefun int setreuid (uid_t @var{ruid}, uid_t @var{euid}) | 
|  | 375 | @safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} | 
|  | 376 | @c setreuid @asulock @aculock | 
|  | 377 | @c  INLINE_SETXID_SYSCALL dup @asulock @aculock | 
|  | 378 | This function sets the real user ID of the process to @var{ruid} and the | 
|  | 379 | effective user ID to @var{euid}.  If @var{ruid} is @code{-1}, it means | 
|  | 380 | not to change the real user ID; likewise if @var{euid} is @code{-1}, it | 
|  | 381 | means not to change the effective user ID. | 
|  | 382 |  | 
|  | 383 | The @code{setreuid} function exists for compatibility with 4.3 BSD Unix, | 
|  | 384 | which does not support file IDs.  You can use this function to swap the | 
|  | 385 | effective and real user IDs of the process.  (Privileged processes are | 
|  | 386 | not limited to this particular usage.)  If file IDs are supported, you | 
|  | 387 | should use that feature instead of this function.  @xref{Enable/Disable | 
|  | 388 | Setuid}. | 
|  | 389 |  | 
|  | 390 | The return value is @code{0} on success and @code{-1} on failure. | 
|  | 391 | The following @code{errno} error conditions are defined for this | 
|  | 392 | function: | 
|  | 393 |  | 
|  | 394 | @table @code | 
|  | 395 | @item EPERM | 
|  | 396 | The process does not have the appropriate privileges; you do not | 
|  | 397 | have permission to change to the specified ID. | 
|  | 398 | @end table | 
|  | 399 | @end deftypefun | 
|  | 400 |  | 
|  | 401 | @node Setting Groups | 
|  | 402 | @section Setting the Group IDs | 
|  | 403 |  | 
|  | 404 | This section describes the functions for altering the group IDs (real | 
|  | 405 | and effective) of a process.  To use these facilities, you must include | 
|  | 406 | the header files @file{sys/types.h} and @file{unistd.h}. | 
|  | 407 | @pindex unistd.h | 
|  | 408 | @pindex sys/types.h | 
|  | 409 |  | 
|  | 410 | @comment unistd.h | 
|  | 411 | @comment POSIX.1 | 
|  | 412 | @deftypefun int setegid (gid_t @var{newgid}) | 
|  | 413 | @safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} | 
|  | 414 | @c setegid @asulock @aculock | 
|  | 415 | @c  INLINE_SETXID_SYSCALL dup @asulock @aculock | 
|  | 416 | This function sets the effective group ID of the process to | 
|  | 417 | @var{newgid}, provided that the process is allowed to change its group | 
|  | 418 | ID.  Just as with @code{seteuid}, if the process is privileged it may | 
|  | 419 | change its effective group ID to any value; if it isn't, but it has a | 
|  | 420 | file group ID, then it may change to its real group ID or file group ID; | 
|  | 421 | otherwise it may not change its effective group ID. | 
|  | 422 |  | 
|  | 423 | Note that a process is only privileged if its effective @emph{user} ID | 
|  | 424 | is zero.  The effective group ID only affects access permissions. | 
|  | 425 |  | 
|  | 426 | The return values and error conditions for @code{setegid} are the same | 
|  | 427 | as those for @code{seteuid}. | 
|  | 428 |  | 
|  | 429 | This function is only present if @code{_POSIX_SAVED_IDS} is defined. | 
|  | 430 | @end deftypefun | 
|  | 431 |  | 
|  | 432 | @comment unistd.h | 
|  | 433 | @comment POSIX.1 | 
|  | 434 | @deftypefun int setgid (gid_t @var{newgid}) | 
|  | 435 | @safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} | 
|  | 436 | @c setgid @asulock @aculock | 
|  | 437 | @c  INLINE_SETXID_SYSCALL dup @asulock @aculock | 
|  | 438 | This function sets both the real and effective group ID of the process | 
|  | 439 | to @var{newgid}, provided that the process is privileged.  It also | 
|  | 440 | deletes the file group ID, if any. | 
|  | 441 |  | 
|  | 442 | If the process is not privileged, then @code{setgid} behaves like | 
|  | 443 | @code{setegid}. | 
|  | 444 |  | 
|  | 445 | The return values and error conditions for @code{setgid} are the same | 
|  | 446 | as those for @code{seteuid}. | 
|  | 447 | @end deftypefun | 
|  | 448 |  | 
|  | 449 | @comment unistd.h | 
|  | 450 | @comment BSD | 
|  | 451 | @deftypefun int setregid (gid_t @var{rgid}, gid_t @var{egid}) | 
|  | 452 | @safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} | 
|  | 453 | @c setregid @asulock @aculock | 
|  | 454 | @c  INLINE_SETXID_SYSCALL dup @asulock @aculock | 
|  | 455 | This function sets the real group ID of the process to @var{rgid} and | 
|  | 456 | the effective group ID to @var{egid}.  If @var{rgid} is @code{-1}, it | 
|  | 457 | means not to change the real group ID; likewise if @var{egid} is | 
|  | 458 | @code{-1}, it means not to change the effective group ID. | 
|  | 459 |  | 
|  | 460 | The @code{setregid} function is provided for compatibility with 4.3 BSD | 
|  | 461 | Unix, which does not support file IDs.  You can use this function to | 
|  | 462 | swap the effective and real group IDs of the process.  (Privileged | 
|  | 463 | processes are not limited to this usage.)  If file IDs are supported, | 
|  | 464 | you should use that feature instead of using this function. | 
|  | 465 | @xref{Enable/Disable Setuid}. | 
|  | 466 |  | 
|  | 467 | The return values and error conditions for @code{setregid} are the same | 
|  | 468 | as those for @code{setreuid}. | 
|  | 469 | @end deftypefun | 
|  | 470 |  | 
|  | 471 | @code{setuid} and @code{setgid} behave differently depending on whether | 
|  | 472 | the effective user ID at the time is zero.  If it is not zero, they | 
|  | 473 | behave like @code{seteuid} and @code{setegid}.  If it is, they change | 
|  | 474 | both effective and real IDs and delete the file ID.  To avoid confusion, | 
|  | 475 | we recommend you always use @code{seteuid} and @code{setegid} except | 
|  | 476 | when you know the effective user ID is zero and your intent is to change | 
|  | 477 | the persona permanently.  This case is rare---most of the programs that | 
|  | 478 | need it, such as @code{login} and @code{su}, have already been written. | 
|  | 479 |  | 
|  | 480 | Note that if your program is setuid to some user other than @code{root}, | 
|  | 481 | there is no way to drop privileges permanently. | 
|  | 482 |  | 
|  | 483 | The system also lets privileged processes change their supplementary | 
|  | 484 | group IDs.  To use @code{setgroups} or @code{initgroups}, your programs | 
|  | 485 | should include the header file @file{grp.h}. | 
|  | 486 | @pindex grp.h | 
|  | 487 |  | 
|  | 488 | @comment grp.h | 
|  | 489 | @comment BSD | 
|  | 490 | @deftypefun int setgroups (size_t @var{count}, const gid_t *@var{groups}) | 
|  | 491 | @safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} | 
|  | 492 | @c setgroups @asulock @aculock | 
|  | 493 | @c  INLINE_SETXID_SYSCALL dup @asulock @aculock | 
|  | 494 | This function sets the process's supplementary group IDs.  It can only | 
|  | 495 | be called from privileged processes.  The @var{count} argument specifies | 
|  | 496 | the number of group IDs in the array @var{groups}. | 
|  | 497 |  | 
|  | 498 | This function returns @code{0} if successful and @code{-1} on error. | 
|  | 499 | The following @code{errno} error conditions are defined for this | 
|  | 500 | function: | 
|  | 501 |  | 
|  | 502 | @table @code | 
|  | 503 | @item EPERM | 
|  | 504 | The calling process is not privileged. | 
|  | 505 | @end table | 
|  | 506 | @end deftypefun | 
|  | 507 |  | 
|  | 508 | @comment grp.h | 
|  | 509 | @comment BSD | 
|  | 510 | @deftypefun int initgroups (const char *@var{user}, gid_t @var{group}) | 
|  | 511 | @safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @acsmem{} @acsfd{} @aculock{}}} | 
|  | 512 | @c initgroups @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 513 | @c  sysconf(_SC_NGROUPS_MAX) dup @acsfd | 
|  | 514 | @c  MIN dup ok | 
|  | 515 | @c  malloc @ascuheap @acsmem | 
|  | 516 | @c  internal_getgrouplist @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 517 | @c   nscd_getgrouplist @ascuheap @acsfd @acsmem | 
|  | 518 | @c    nscd_get_map_ref dup @ascuheap @acsfd @acsmem | 
|  | 519 | @c    nscd_cache_search dup ok | 
|  | 520 | @c    nscd_open_socket dup @acsfd | 
|  | 521 | @c    realloc dup @ascuheap @acsmem | 
|  | 522 | @c    readall dup ok | 
|  | 523 | @c    memcpy dup ok | 
|  | 524 | @c    close_not_cancel_no_status dup @acsfd | 
|  | 525 | @c    nscd_drop_map_ref dup @ascuheap @acsmem | 
|  | 526 | @c    nscd_unmap dup @ascuheap @acsmem | 
|  | 527 | @c   nss_database_lookup dup @mtslocale @ascuheap @asulock @acucorrupt @acsmem @acsfd @aculock | 
|  | 528 | @c   nss_lookup_function dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 529 | @c   compat_call @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 530 | @c    sysconf(_SC_GETGR_R_SIZE_MAX) ok | 
|  | 531 | @c    nss_lookup_function dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 532 | @c    *getgrent_fct @ascuplugin | 
|  | 533 | @c    *setgrent_fct @ascuplugin | 
|  | 534 | @c    *endgrent_fct @ascuplugin | 
|  | 535 | @c    realloc dup @ascuheap @acsmem | 
|  | 536 | @c    free dup @ascuheap @acsmem | 
|  | 537 | @c   *initgroups_dyn_fct @ascuplugin | 
|  | 538 | @c   nss_next_action dup ok | 
|  | 539 | @c  setgroups dup @asulock @aculock | 
|  | 540 | @c  free dup @ascuheap @acsmem | 
|  | 541 | The @code{initgroups} function sets the process's supplementary group | 
|  | 542 | IDs to be the normal default for the user name @var{user}.  The group | 
|  | 543 | @var{group} is automatically included. | 
|  | 544 |  | 
|  | 545 | This function works by scanning the group database for all the groups | 
|  | 546 | @var{user} belongs to.  It then calls @code{setgroups} with the list it | 
|  | 547 | has constructed. | 
|  | 548 |  | 
|  | 549 | The return values and error conditions are the same as for | 
|  | 550 | @code{setgroups}. | 
|  | 551 | @end deftypefun | 
|  | 552 |  | 
|  | 553 | If you are interested in the groups a particular user belongs to, but do | 
|  | 554 | not want to change the process's supplementary group IDs, you can use | 
|  | 555 | @code{getgrouplist}.  To use @code{getgrouplist}, your programs should | 
|  | 556 | include the header file @file{grp.h}. | 
|  | 557 | @pindex grp.h | 
|  | 558 |  | 
|  | 559 | @comment grp.h | 
|  | 560 | @comment BSD | 
|  | 561 | @deftypefun int getgrouplist (const char *@var{user}, gid_t @var{group}, gid_t *@var{groups}, int *@var{ngroups}) | 
|  | 562 | @safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @acsmem{} @acsfd{} @aculock{}}} | 
|  | 563 | @c getgrouplist @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 564 | @c  MAX dup ok | 
|  | 565 | @c  malloc dup @ascuheap @acsmem | 
|  | 566 | @c  internal_getgrouplist dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 567 | @c  memcpy dup ok | 
|  | 568 | @c  free dup @ascuheap @acsmem | 
|  | 569 | The @code{getgrouplist} function scans the group database for all the | 
|  | 570 | groups @var{user} belongs to.  Up to *@var{ngroups} group IDs | 
|  | 571 | corresponding to these groups are stored in the array @var{groups}; the | 
|  | 572 | return value from the function is the number of group IDs actually | 
|  | 573 | stored.  If *@var{ngroups} is smaller than the total number of groups | 
|  | 574 | found, then @code{getgrouplist} returns a value of @code{-1} and stores | 
|  | 575 | the actual number of groups in *@var{ngroups}.  The group @var{group} is | 
|  | 576 | automatically included in the list of groups returned by | 
|  | 577 | @code{getgrouplist}. | 
|  | 578 |  | 
|  | 579 | Here's how to use @code{getgrouplist} to read all supplementary groups | 
|  | 580 | for @var{user}: | 
|  | 581 |  | 
|  | 582 | @smallexample | 
|  | 583 | @group | 
|  | 584 | gid_t * | 
|  | 585 | supplementary_groups (char *user) | 
|  | 586 | @{ | 
|  | 587 | int ngroups = 16; | 
|  | 588 | gid_t *groups | 
|  | 589 | = (gid_t *) xmalloc (ngroups * sizeof (gid_t)); | 
|  | 590 | struct passwd *pw = getpwnam (user); | 
|  | 591 |  | 
|  | 592 | if (pw == NULL) | 
|  | 593 | return NULL; | 
|  | 594 |  | 
|  | 595 | if (getgrouplist (pw->pw_name, pw->pw_gid, groups, &ngroups) < 0) | 
|  | 596 | @{ | 
|  | 597 | groups = xrealloc (ngroups * sizeof (gid_t)); | 
|  | 598 | getgrouplist (pw->pw_name, pw->pw_gid, groups, &ngroups); | 
|  | 599 | @} | 
|  | 600 | return groups; | 
|  | 601 | @} | 
|  | 602 | @end group | 
|  | 603 | @end smallexample | 
|  | 604 | @end deftypefun | 
|  | 605 |  | 
|  | 606 | @node Enable/Disable Setuid | 
|  | 607 | @section Enabling and Disabling Setuid Access | 
|  | 608 |  | 
|  | 609 | A typical setuid program does not need its special access all of the | 
|  | 610 | time.  It's a good idea to turn off this access when it isn't needed, | 
|  | 611 | so it can't possibly give unintended access. | 
|  | 612 |  | 
|  | 613 | If the system supports the @code{_POSIX_SAVED_IDS} feature, you can | 
|  | 614 | accomplish this with @code{seteuid}.  When the game program starts, its | 
|  | 615 | real user ID is @code{jdoe}, its effective user ID is @code{games}, and | 
|  | 616 | its saved user ID is also @code{games}.  The program should record both | 
|  | 617 | user ID values once at the beginning, like this: | 
|  | 618 |  | 
|  | 619 | @smallexample | 
|  | 620 | user_user_id = getuid (); | 
|  | 621 | game_user_id = geteuid (); | 
|  | 622 | @end smallexample | 
|  | 623 |  | 
|  | 624 | Then it can turn off game file access with | 
|  | 625 |  | 
|  | 626 | @smallexample | 
|  | 627 | seteuid (user_user_id); | 
|  | 628 | @end smallexample | 
|  | 629 |  | 
|  | 630 | @noindent | 
|  | 631 | and turn it on with | 
|  | 632 |  | 
|  | 633 | @smallexample | 
|  | 634 | seteuid (game_user_id); | 
|  | 635 | @end smallexample | 
|  | 636 |  | 
|  | 637 | @noindent | 
|  | 638 | Throughout this process, the real user ID remains @code{jdoe} and the | 
|  | 639 | file user ID remains @code{games}, so the program can always set its | 
|  | 640 | effective user ID to either one. | 
|  | 641 |  | 
|  | 642 | On other systems that don't support file user IDs, you can | 
|  | 643 | turn setuid access on and off by using @code{setreuid} to swap the real | 
|  | 644 | and effective user IDs of the process, as follows: | 
|  | 645 |  | 
|  | 646 | @smallexample | 
|  | 647 | setreuid (geteuid (), getuid ()); | 
|  | 648 | @end smallexample | 
|  | 649 |  | 
|  | 650 | @noindent | 
|  | 651 | This special case is always allowed---it cannot fail. | 
|  | 652 |  | 
|  | 653 | Why does this have the effect of toggling the setuid access?  Suppose a | 
|  | 654 | game program has just started, and its real user ID is @code{jdoe} while | 
|  | 655 | its effective user ID is @code{games}.  In this state, the game can | 
|  | 656 | write the scores file.  If it swaps the two uids, the real becomes | 
|  | 657 | @code{games} and the effective becomes @code{jdoe}; now the program has | 
|  | 658 | only @code{jdoe} access.  Another swap brings @code{games} back to | 
|  | 659 | the effective user ID and restores access to the scores file. | 
|  | 660 |  | 
|  | 661 | In order to handle both kinds of systems, test for the saved user ID | 
|  | 662 | feature with a preprocessor conditional, like this: | 
|  | 663 |  | 
|  | 664 | @smallexample | 
|  | 665 | #ifdef _POSIX_SAVED_IDS | 
|  | 666 | seteuid (user_user_id); | 
|  | 667 | #else | 
|  | 668 | setreuid (geteuid (), getuid ()); | 
|  | 669 | #endif | 
|  | 670 | @end smallexample | 
|  | 671 |  | 
|  | 672 | @node Setuid Program Example | 
|  | 673 | @section Setuid Program Example | 
|  | 674 |  | 
|  | 675 | Here's an example showing how to set up a program that changes its | 
|  | 676 | effective user ID. | 
|  | 677 |  | 
|  | 678 | This is part of a game program called @code{caber-toss} that manipulates | 
|  | 679 | a file @file{scores} that should be writable only by the game program | 
|  | 680 | itself.  The program assumes that its executable file will be installed | 
|  | 681 | with the setuid bit set and owned by the same user as the @file{scores} | 
|  | 682 | file.  Typically, a system administrator will set up an account like | 
|  | 683 | @code{games} for this purpose. | 
|  | 684 |  | 
|  | 685 | The executable file is given mode @code{4755}, so that doing an | 
|  | 686 | @samp{ls -l} on it produces output like: | 
|  | 687 |  | 
|  | 688 | @smallexample | 
|  | 689 | -rwsr-xr-x   1 games    184422 Jul 30 15:17 caber-toss | 
|  | 690 | @end smallexample | 
|  | 691 |  | 
|  | 692 | @noindent | 
|  | 693 | The setuid bit shows up in the file modes as the @samp{s}. | 
|  | 694 |  | 
|  | 695 | The scores file is given mode @code{644}, and doing an @samp{ls -l} on | 
|  | 696 | it shows: | 
|  | 697 |  | 
|  | 698 | @smallexample | 
|  | 699 | -rw-r--r--  1 games           0 Jul 31 15:33 scores | 
|  | 700 | @end smallexample | 
|  | 701 |  | 
|  | 702 | Here are the parts of the program that show how to set up the changed | 
|  | 703 | user ID.  This program is conditionalized so that it makes use of the | 
|  | 704 | file IDs feature if it is supported, and otherwise uses @code{setreuid} | 
|  | 705 | to swap the effective and real user IDs. | 
|  | 706 |  | 
|  | 707 | @smallexample | 
|  | 708 | #include <stdio.h> | 
|  | 709 | #include <sys/types.h> | 
|  | 710 | #include <unistd.h> | 
|  | 711 | #include <stdlib.h> | 
|  | 712 |  | 
|  | 713 |  | 
|  | 714 | /* @r{Remember the effective and real UIDs.} */ | 
|  | 715 |  | 
|  | 716 | static uid_t euid, ruid; | 
|  | 717 |  | 
|  | 718 |  | 
|  | 719 | /* @r{Restore the effective UID to its original value.} */ | 
|  | 720 |  | 
|  | 721 | void | 
|  | 722 | do_setuid (void) | 
|  | 723 | @{ | 
|  | 724 | int status; | 
|  | 725 |  | 
|  | 726 | #ifdef _POSIX_SAVED_IDS | 
|  | 727 | status = seteuid (euid); | 
|  | 728 | #else | 
|  | 729 | status = setreuid (ruid, euid); | 
|  | 730 | #endif | 
|  | 731 | if (status < 0) @{ | 
|  | 732 | fprintf (stderr, "Couldn't set uid.\n"); | 
|  | 733 | exit (status); | 
|  | 734 | @} | 
|  | 735 | @} | 
|  | 736 |  | 
|  | 737 |  | 
|  | 738 | @group | 
|  | 739 | /* @r{Set the effective UID to the real UID.} */ | 
|  | 740 |  | 
|  | 741 | void | 
|  | 742 | undo_setuid (void) | 
|  | 743 | @{ | 
|  | 744 | int status; | 
|  | 745 |  | 
|  | 746 | #ifdef _POSIX_SAVED_IDS | 
|  | 747 | status = seteuid (ruid); | 
|  | 748 | #else | 
|  | 749 | status = setreuid (euid, ruid); | 
|  | 750 | #endif | 
|  | 751 | if (status < 0) @{ | 
|  | 752 | fprintf (stderr, "Couldn't set uid.\n"); | 
|  | 753 | exit (status); | 
|  | 754 | @} | 
|  | 755 | @} | 
|  | 756 | @end group | 
|  | 757 |  | 
|  | 758 | /* @r{Main program.} */ | 
|  | 759 |  | 
|  | 760 | int | 
|  | 761 | main (void) | 
|  | 762 | @{ | 
|  | 763 | /* @r{Remember the real and effective user IDs.}  */ | 
|  | 764 | ruid = getuid (); | 
|  | 765 | euid = geteuid (); | 
|  | 766 | undo_setuid (); | 
|  | 767 |  | 
|  | 768 | /* @r{Do the game and record the score.}  */ | 
|  | 769 | @dots{} | 
|  | 770 | @} | 
|  | 771 | @end smallexample | 
|  | 772 |  | 
|  | 773 | Notice how the first thing the @code{main} function does is to set the | 
|  | 774 | effective user ID back to the real user ID.  This is so that any other | 
|  | 775 | file accesses that are performed while the user is playing the game use | 
|  | 776 | the real user ID for determining permissions.  Only when the program | 
|  | 777 | needs to open the scores file does it switch back to the file user ID, | 
|  | 778 | like this: | 
|  | 779 |  | 
|  | 780 | @smallexample | 
|  | 781 | /* @r{Record the score.} */ | 
|  | 782 |  | 
|  | 783 | int | 
|  | 784 | record_score (int score) | 
|  | 785 | @{ | 
|  | 786 | FILE *stream; | 
|  | 787 | char *myname; | 
|  | 788 |  | 
|  | 789 | /* @r{Open the scores file.} */ | 
|  | 790 | do_setuid (); | 
|  | 791 | stream = fopen (SCORES_FILE, "a"); | 
|  | 792 | undo_setuid (); | 
|  | 793 |  | 
|  | 794 | @group | 
|  | 795 | /* @r{Write the score to the file.} */ | 
|  | 796 | if (stream) | 
|  | 797 | @{ | 
|  | 798 | myname = cuserid (NULL); | 
|  | 799 | if (score < 0) | 
|  | 800 | fprintf (stream, "%10s: Couldn't lift the caber.\n", myname); | 
|  | 801 | else | 
|  | 802 | fprintf (stream, "%10s: %d feet.\n", myname, score); | 
|  | 803 | fclose (stream); | 
|  | 804 | return 0; | 
|  | 805 | @} | 
|  | 806 | else | 
|  | 807 | return -1; | 
|  | 808 | @} | 
|  | 809 | @end group | 
|  | 810 | @end smallexample | 
|  | 811 |  | 
|  | 812 | @node Tips for Setuid | 
|  | 813 | @section Tips for Writing Setuid Programs | 
|  | 814 |  | 
|  | 815 | It is easy for setuid programs to give the user access that isn't | 
|  | 816 | intended---in fact, if you want to avoid this, you need to be careful. | 
|  | 817 | Here are some guidelines for preventing unintended access and | 
|  | 818 | minimizing its consequences when it does occur: | 
|  | 819 |  | 
|  | 820 | @itemize @bullet | 
|  | 821 | @item | 
|  | 822 | Don't have @code{setuid} programs with privileged user IDs such as | 
|  | 823 | @code{root} unless it is absolutely necessary.  If the resource is | 
|  | 824 | specific to your particular program, it's better to define a new, | 
|  | 825 | nonprivileged user ID or group ID just to manage that resource. | 
|  | 826 | It's better if you can write your program to use a special group than a | 
|  | 827 | special user. | 
|  | 828 |  | 
|  | 829 | @item | 
|  | 830 | Be cautious about using the @code{exec} functions in combination with | 
|  | 831 | changing the effective user ID.  Don't let users of your program execute | 
|  | 832 | arbitrary programs under a changed user ID.  Executing a shell is | 
|  | 833 | especially bad news.  Less obviously, the @code{execlp} and @code{execvp} | 
|  | 834 | functions are a potential risk (since the program they execute depends | 
|  | 835 | on the user's @code{PATH} environment variable). | 
|  | 836 |  | 
|  | 837 | If you must @code{exec} another program under a changed ID, specify an | 
|  | 838 | absolute file name (@pxref{File Name Resolution}) for the executable, | 
|  | 839 | and make sure that the protections on that executable and @emph{all} | 
|  | 840 | containing directories are such that ordinary users cannot replace it | 
|  | 841 | with some other program. | 
|  | 842 |  | 
|  | 843 | You should also check the arguments passed to the program to make sure | 
|  | 844 | they do not have unexpected effects.  Likewise, you should examine the | 
|  | 845 | environment variables.  Decide which arguments and variables are safe, | 
|  | 846 | and reject all others. | 
|  | 847 |  | 
|  | 848 | You should never use @code{system} in a privileged program, because it | 
|  | 849 | invokes a shell. | 
|  | 850 |  | 
|  | 851 | @item | 
|  | 852 | Only use the user ID controlling the resource in the part of the program | 
|  | 853 | that actually uses that resource.  When you're finished with it, restore | 
|  | 854 | the effective user ID back to the actual user's user ID. | 
|  | 855 | @xref{Enable/Disable Setuid}. | 
|  | 856 |  | 
|  | 857 | @item | 
|  | 858 | If the @code{setuid} part of your program needs to access other files | 
|  | 859 | besides the controlled resource, it should verify that the real user | 
|  | 860 | would ordinarily have permission to access those files.  You can use the | 
|  | 861 | @code{access} function (@pxref{Access Permission}) to check this; it | 
|  | 862 | uses the real user and group IDs, rather than the effective IDs. | 
|  | 863 | @end itemize | 
|  | 864 |  | 
|  | 865 | @node Who Logged In | 
|  | 866 | @section Identifying Who Logged In | 
|  | 867 | @cindex login name, determining | 
|  | 868 | @cindex user ID, determining | 
|  | 869 |  | 
|  | 870 | You can use the functions listed in this section to determine the login | 
|  | 871 | name of the user who is running a process, and the name of the user who | 
|  | 872 | logged in the current session.  See also the function @code{getuid} and | 
|  | 873 | friends (@pxref{Reading Persona}).  How this information is collected by | 
|  | 874 | the system and how to control/add/remove information from the background | 
|  | 875 | storage is described in @ref{User Accounting Database}. | 
|  | 876 |  | 
|  | 877 | The @code{getlogin} function is declared in @file{unistd.h}, while | 
|  | 878 | @code{cuserid} and @code{L_cuserid} are declared in @file{stdio.h}. | 
|  | 879 | @pindex stdio.h | 
|  | 880 | @pindex unistd.h | 
|  | 881 |  | 
|  | 882 | @comment unistd.h | 
|  | 883 | @comment POSIX.1 | 
|  | 884 | @deftypefun {char *} getlogin (void) | 
|  | 885 | @safety{@prelim{}@mtunsafe{@mtasurace{:getlogin} @mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 886 | @c getlogin (linux) @mtasurace:getlogin @mtasurace:utent @mtascusig:ALRM @mtascutimer @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 887 | @c  getlogin_r_loginuid dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 888 | @c  getlogin_fd0 (unix) @mtasurace:getlogin @mtasurace:utent @mtascusig:ALRM @mtascutimer @ascuheap @asulock @aculock @acsfd @acsmem | 
|  | 889 | @c    uses static buffer name => @mtasurace:getlogin | 
|  | 890 | @c   ttyname_r dup @ascuheap @acsmem @acsfd | 
|  | 891 | @c   strncpy dup ok | 
|  | 892 | @c   setutent dup @mtasurace:utent @asulock @aculock @acsfd | 
|  | 893 | @c   getutline_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd | 
|  | 894 | @c   endutent dup @mtasurace:utent @asulock @aculock | 
|  | 895 | @c   libc_lock_unlock dup ok | 
|  | 896 | @c   strlen dup ok | 
|  | 897 | @c   memcpy dup ok | 
|  | 898 | @c | 
|  | 899 | @c getlogin_r (linux) @mtasurace:utent @mtascusig:ALRM @mtascutimer @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 900 | @c  getlogin_r_loginuid @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 901 | @c   open_not_cancel_2 dup @acsfd | 
|  | 902 | @c   read_not_cancel dup ok | 
|  | 903 | @c   close_not_cancel_no_status dup @acsfd | 
|  | 904 | @c   strtoul @mtslocale | 
|  | 905 | @c   getpwuid_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 906 | @c   realloc dup @asulock @aculock @acsfd @acsmem | 
|  | 907 | @c   strlen dup ok | 
|  | 908 | @c   memcpy dup ok | 
|  | 909 | @c   free dup @asulock @aculock @acsfd @acsmem | 
|  | 910 | @c  getlogin_r_fd0 (unix) @mtasurace:utent @mtascusig:ALRM @mtascutimer @ascuheap @asulock @aculock @acsmem @acsfd | 
|  | 911 | @c   ttyname_r dup @ascuheap @acsmem @acsfd | 
|  | 912 | @c   strncpy dup ok | 
|  | 913 | @c   libc_lock_lock dup @asulock @aculock | 
|  | 914 | @c   *libc_utmp_jump_table->setutent dup @mtasurace:utent @acsfd | 
|  | 915 | @c   *libc_utmp_jump_table->getutline_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer | 
|  | 916 | @c   *libc_utmp_jump_table->endutent dup @mtasurace:utent @asulock @aculock | 
|  | 917 | @c   libc_lock_unlock dup ok | 
|  | 918 | @c   strlen dup ok | 
|  | 919 | @c   memcpy dup ok | 
|  | 920 | The @code{getlogin} function returns a pointer to a string containing the | 
|  | 921 | name of the user logged in on the controlling terminal of the process, | 
|  | 922 | or a null pointer if this information cannot be determined.  The string | 
|  | 923 | is statically allocated and might be overwritten on subsequent calls to | 
|  | 924 | this function or to @code{cuserid}. | 
|  | 925 | @end deftypefun | 
|  | 926 |  | 
|  | 927 | @comment stdio.h | 
|  | 928 | @comment POSIX.1 | 
|  | 929 | @deftypefun {char *} cuserid (char *@var{string}) | 
|  | 930 | @safety{@prelim{}@mtunsafe{@mtasurace{:cuserid/!string} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 931 | @c cuserid @mtasurace:cuserid/!string @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 932 | @c   if string is NULL, cuserid will overwrite and return a static buffer | 
|  | 933 | @c  geteuid dup ok | 
|  | 934 | @c  getpwuid_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 935 | @c  strncpy dup ok | 
|  | 936 | The @code{cuserid} function returns a pointer to a string containing a | 
|  | 937 | user name associated with the effective ID of the process.  If | 
|  | 938 | @var{string} is not a null pointer, it should be an array that can hold | 
|  | 939 | at least @code{L_cuserid} characters; the string is returned in this | 
|  | 940 | array.  Otherwise, a pointer to a string in a static area is returned. | 
|  | 941 | This string is statically allocated and might be overwritten on | 
|  | 942 | subsequent calls to this function or to @code{getlogin}. | 
|  | 943 |  | 
|  | 944 | The use of this function is deprecated since it is marked to be | 
|  | 945 | withdrawn in XPG4.2 and has already been removed from newer revisions of | 
|  | 946 | POSIX.1. | 
|  | 947 | @end deftypefun | 
|  | 948 |  | 
|  | 949 | @comment stdio.h | 
|  | 950 | @comment POSIX.1 | 
|  | 951 | @deftypevr Macro int L_cuserid | 
|  | 952 | An integer constant that indicates how long an array you might need to | 
|  | 953 | store a user name. | 
|  | 954 | @end deftypevr | 
|  | 955 |  | 
|  | 956 | These functions let your program identify positively the user who is | 
|  | 957 | running or the user who logged in this session.  (These can differ when | 
|  | 958 | setuid programs are involved; see @ref{Process Persona}.)  The user cannot | 
|  | 959 | do anything to fool these functions. | 
|  | 960 |  | 
|  | 961 | For most purposes, it is more useful to use the environment variable | 
|  | 962 | @code{LOGNAME} to find out who the user is.  This is more flexible | 
|  | 963 | precisely because the user can set @code{LOGNAME} arbitrarily. | 
|  | 964 | @xref{Standard Environment}. | 
|  | 965 |  | 
|  | 966 |  | 
|  | 967 | @node User Accounting Database | 
|  | 968 | @section The User Accounting Database | 
|  | 969 | @cindex user accounting database | 
|  | 970 |  | 
|  | 971 | Most Unix-like operating systems keep track of logged in users by | 
|  | 972 | maintaining a user accounting database.  This user accounting database | 
|  | 973 | stores for each terminal, who has logged on, at what time, the process | 
|  | 974 | ID of the user's login shell, etc., etc., but also stores information | 
|  | 975 | about the run level of the system, the time of the last system reboot, | 
|  | 976 | and possibly more. | 
|  | 977 |  | 
|  | 978 | The user accounting database typically lives in @file{/etc/utmp}, | 
|  | 979 | @file{/var/adm/utmp} or @file{/var/run/utmp}.  However, these files | 
|  | 980 | should @strong{never} be accessed directly.  For reading information | 
|  | 981 | from and writing information to the user accounting database, the | 
|  | 982 | functions described in this section should be used. | 
|  | 983 |  | 
|  | 984 |  | 
|  | 985 | @menu | 
|  | 986 | * Manipulating the Database::   Scanning and modifying the user | 
|  | 987 | accounting database. | 
|  | 988 | * XPG Functions::               A standardized way for doing the same thing. | 
|  | 989 | * Logging In and Out::          Functions from BSD that modify the user | 
|  | 990 | accounting database. | 
|  | 991 | @end menu | 
|  | 992 |  | 
|  | 993 | @node Manipulating the Database | 
|  | 994 | @subsection Manipulating the User Accounting Database | 
|  | 995 |  | 
|  | 996 | These functions and the corresponding data structures are declared in | 
|  | 997 | the header file @file{utmp.h}. | 
|  | 998 | @pindex utmp.h | 
|  | 999 |  | 
|  | 1000 | @comment utmp.h | 
|  | 1001 | @comment SVID | 
|  | 1002 | @deftp {Data Type} {struct exit_status} | 
|  | 1003 | The @code{exit_status} data structure is used to hold information about | 
|  | 1004 | the exit status of processes marked as @code{DEAD_PROCESS} in the user | 
|  | 1005 | accounting database. | 
|  | 1006 |  | 
|  | 1007 | @table @code | 
|  | 1008 | @item short int e_termination | 
|  | 1009 | The exit status of the process. | 
|  | 1010 |  | 
|  | 1011 | @item short int e_exit | 
|  | 1012 | The exit status of the process. | 
|  | 1013 | @end table | 
|  | 1014 | @end deftp | 
|  | 1015 |  | 
|  | 1016 | @deftp {Data Type} {struct utmp} | 
|  | 1017 | The @code{utmp} data structure is used to hold information about entries | 
|  | 1018 | in the user accounting database.  On @gnusystems{} it has the following | 
|  | 1019 | members: | 
|  | 1020 |  | 
|  | 1021 | @table @code | 
|  | 1022 | @item short int ut_type | 
|  | 1023 | Specifies the type of login; one of @code{EMPTY}, @code{RUN_LVL}, | 
|  | 1024 | @code{BOOT_TIME}, @code{OLD_TIME}, @code{NEW_TIME}, @code{INIT_PROCESS}, | 
|  | 1025 | @code{LOGIN_PROCESS}, @code{USER_PROCESS}, @code{DEAD_PROCESS} or | 
|  | 1026 | @code{ACCOUNTING}. | 
|  | 1027 |  | 
|  | 1028 | @item pid_t ut_pid | 
|  | 1029 | The process ID number of the login process. | 
|  | 1030 |  | 
|  | 1031 | @item char ut_line[] | 
|  | 1032 | The device name of the tty (without @file{/dev/}). | 
|  | 1033 |  | 
|  | 1034 | @item char ut_id[] | 
|  | 1035 | The inittab ID of the process. | 
|  | 1036 |  | 
|  | 1037 | @item char ut_user[] | 
|  | 1038 | The user's login name. | 
|  | 1039 |  | 
|  | 1040 | @item char ut_host[] | 
|  | 1041 | The name of the host from which the user logged in. | 
|  | 1042 |  | 
|  | 1043 | @item struct exit_status ut_exit | 
|  | 1044 | The exit status of a process marked as @code{DEAD_PROCESS}. | 
|  | 1045 |  | 
|  | 1046 | @item long ut_session | 
|  | 1047 | The Session ID, used for windowing. | 
|  | 1048 |  | 
|  | 1049 | @item struct timeval ut_tv | 
|  | 1050 | Time the entry was made.  For entries of type @code{OLD_TIME} this is | 
|  | 1051 | the time when the system clock changed, and for entries of type | 
|  | 1052 | @code{NEW_TIME} this is the time the system clock was set to. | 
|  | 1053 |  | 
|  | 1054 | @item int32_t ut_addr_v6[4] | 
|  | 1055 | The Internet address of a remote host. | 
|  | 1056 | @end table | 
|  | 1057 | @end deftp | 
|  | 1058 |  | 
|  | 1059 | The @code{ut_type}, @code{ut_pid}, @code{ut_id}, @code{ut_tv}, and | 
|  | 1060 | @code{ut_host} fields are not available on all systems.  Portable | 
|  | 1061 | applications therefore should be prepared for these situations.  To help | 
|  | 1062 | doing this the @file{utmp.h} header provides macros | 
|  | 1063 | @code{_HAVE_UT_TYPE}, @code{_HAVE_UT_PID}, @code{_HAVE_UT_ID}, | 
|  | 1064 | @code{_HAVE_UT_TV}, and @code{_HAVE_UT_HOST} if the respective field is | 
|  | 1065 | available.  The programmer can handle the situations by using | 
|  | 1066 | @code{#ifdef} in the program code. | 
|  | 1067 |  | 
|  | 1068 | The following macros are defined for use as values for the | 
|  | 1069 | @code{ut_type} member of the @code{utmp} structure.  The values are | 
|  | 1070 | integer constants. | 
|  | 1071 |  | 
|  | 1072 | @table @code | 
|  | 1073 | @comment utmp.h | 
|  | 1074 | @comment SVID | 
|  | 1075 | @vindex EMPTY | 
|  | 1076 | @item EMPTY | 
|  | 1077 | This macro is used to indicate that the entry contains no valid user | 
|  | 1078 | accounting information. | 
|  | 1079 |  | 
|  | 1080 | @comment utmp.h | 
|  | 1081 | @comment SVID | 
|  | 1082 | @vindex RUN_LVL | 
|  | 1083 | @item RUN_LVL | 
|  | 1084 | This macro is used to identify the systems runlevel. | 
|  | 1085 |  | 
|  | 1086 | @comment utmp.h | 
|  | 1087 | @comment SVID | 
|  | 1088 | @vindex BOOT_TIME | 
|  | 1089 | @item BOOT_TIME | 
|  | 1090 | This macro is used to identify the time of system boot. | 
|  | 1091 |  | 
|  | 1092 | @comment utmp.h | 
|  | 1093 | @comment SVID | 
|  | 1094 | @vindex OLD_TIME | 
|  | 1095 | @item OLD_TIME | 
|  | 1096 | This macro is used to identify the time when the system clock changed. | 
|  | 1097 |  | 
|  | 1098 | @comment utmp.h | 
|  | 1099 | @comment SVID | 
|  | 1100 | @vindex NEW_TIME | 
|  | 1101 | @item NEW_TIME | 
|  | 1102 | This macro is used to identify the time after the system changed. | 
|  | 1103 |  | 
|  | 1104 | @comment utmp.h | 
|  | 1105 | @comment SVID | 
|  | 1106 | @vindex INIT_PROCESS | 
|  | 1107 | @item INIT_PROCESS | 
|  | 1108 | This macro is used to identify a process spawned by the init process. | 
|  | 1109 |  | 
|  | 1110 | @comment utmp.h | 
|  | 1111 | @comment SVID | 
|  | 1112 | @vindex LOGIN_PROCESS | 
|  | 1113 | @item LOGIN_PROCESS | 
|  | 1114 | This macro is used to identify the session leader of a logged in user. | 
|  | 1115 |  | 
|  | 1116 | @comment utmp.h | 
|  | 1117 | @comment SVID | 
|  | 1118 | @vindex USER_PROCESS | 
|  | 1119 | @item USER_PROCESS | 
|  | 1120 | This macro is used to identify a user process. | 
|  | 1121 |  | 
|  | 1122 | @comment utmp.h | 
|  | 1123 | @comment SVID | 
|  | 1124 | @vindex DEAD_PROCESS | 
|  | 1125 | @item DEAD_PROCESS | 
|  | 1126 | This macro is used to identify a terminated process. | 
|  | 1127 |  | 
|  | 1128 | @comment utmp.h | 
|  | 1129 | @comment SVID | 
|  | 1130 | @vindex ACCOUNTING | 
|  | 1131 | @item ACCOUNTING | 
|  | 1132 | ??? | 
|  | 1133 | @end table | 
|  | 1134 |  | 
|  | 1135 | The size of the @code{ut_line}, @code{ut_id}, @code{ut_user} and | 
|  | 1136 | @code{ut_host} arrays can be found using the @code{sizeof} operator. | 
|  | 1137 |  | 
|  | 1138 | Many older systems have, instead of an @code{ut_tv} member, an | 
|  | 1139 | @code{ut_time} member, usually of type @code{time_t}, for representing | 
|  | 1140 | the time associated with the entry.  Therefore, for backwards | 
|  | 1141 | compatibility only, @file{utmp.h} defines @code{ut_time} as an alias for | 
|  | 1142 | @code{ut_tv.tv_sec}. | 
|  | 1143 |  | 
|  | 1144 | @comment utmp.h | 
|  | 1145 | @comment SVID | 
|  | 1146 | @deftypefun void setutent (void) | 
|  | 1147 | @safety{@prelim{}@mtunsafe{@mtasurace{:utent}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} | 
|  | 1148 | @c Besides the static variables in utmp_file.c, there's the jump_table. | 
|  | 1149 | @c They're both modified while holding a lock, but other threads may | 
|  | 1150 | @c cause the variables to be modified between calling this function and | 
|  | 1151 | @c others that rely on the internal state it sets up. | 
|  | 1152 |  | 
|  | 1153 | @c setutent @mtasurace:utent @asulock @aculock @acsfd | 
|  | 1154 | @c  libc_lock_lock dup @asulock @aculock | 
|  | 1155 | @c  *libc_utmp_jump_table->setutent @mtasurace:utent @acsfd | 
|  | 1156 | @c   setutent_unknown @mtasurace:utent @acsfd | 
|  | 1157 | @c    *libc_utmp_file_functions.setutent = setutent_file @mtasurace:utent @acsfd | 
|  | 1158 | @c      open_not_cancel_2 dup @acsfd | 
|  | 1159 | @c      fcntl_not_cancel dup ok | 
|  | 1160 | @c      close_not_cancel_no_status dup @acsfd | 
|  | 1161 | @c      lseek64 dup ok | 
|  | 1162 | @c  libc_lock_unlock dup ok | 
|  | 1163 | This function opens the user accounting database to begin scanning it. | 
|  | 1164 | You can then call @code{getutent}, @code{getutid} or @code{getutline} to | 
|  | 1165 | read entries and @code{pututline} to write entries. | 
|  | 1166 |  | 
|  | 1167 | If the database is already open, it resets the input to the beginning of | 
|  | 1168 | the database. | 
|  | 1169 | @end deftypefun | 
|  | 1170 |  | 
|  | 1171 | @comment utmp.h | 
|  | 1172 | @comment SVID | 
|  | 1173 | @deftypefun {struct utmp *} getutent (void) | 
|  | 1174 | @safety{@prelim{}@mtunsafe{@mtuinit{} @mtasurace{:utent} @mtasurace{:utentbuf} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} | 
|  | 1175 | @c The static buffer that holds results is allocated with malloc at | 
|  | 1176 | @c the first call; the test is not thread-safe, so multiple concurrent | 
|  | 1177 | @c calls could malloc multiple buffers. | 
|  | 1178 |  | 
|  | 1179 | @c getutent @mtuinit @mtasurace:utent @mtasurace:utentbuf @mtascusig:ALRM @mtascutimer @ascuheap @asulock @aculock @acsfd @acsmem | 
|  | 1180 | @c  malloc @asulock @aculock @acsfd @acsmem | 
|  | 1181 | @c  getutent_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd | 
|  | 1182 | The @code{getutent} function reads the next entry from the user | 
|  | 1183 | accounting database.  It returns a pointer to the entry, which is | 
|  | 1184 | statically allocated and may be overwritten by subsequent calls to | 
|  | 1185 | @code{getutent}.  You must copy the contents of the structure if you | 
|  | 1186 | wish to save the information or you can use the @code{getutent_r} | 
|  | 1187 | function which stores the data in a user-provided buffer. | 
|  | 1188 |  | 
|  | 1189 | A null pointer is returned in case no further entry is available. | 
|  | 1190 | @end deftypefun | 
|  | 1191 |  | 
|  | 1192 | @comment utmp.h | 
|  | 1193 | @comment SVID | 
|  | 1194 | @deftypefun void endutent (void) | 
|  | 1195 | @safety{@prelim{}@mtunsafe{@mtasurace{:utent}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} | 
|  | 1196 | @c endutent @mtasurace:utent @asulock @aculock @acsfd | 
|  | 1197 | @c  libc_lock_lock dup @asulock @aculock | 
|  | 1198 | @c  *libc_utmp_jump_table->endutent @mtasurace:utent @acsfd | 
|  | 1199 | @c   endutent_unknown ok | 
|  | 1200 | @c   endutent_file @mtasurace:utent @acsfd | 
|  | 1201 | @c    close_not_cancel_no_status dup @acsfd | 
|  | 1202 | @c  libc_lock_unlock dup ok | 
|  | 1203 | This function closes the user accounting database. | 
|  | 1204 | @end deftypefun | 
|  | 1205 |  | 
|  | 1206 | @comment utmp.h | 
|  | 1207 | @comment SVID | 
|  | 1208 | @deftypefun {struct utmp *} getutid (const struct utmp *@var{id}) | 
|  | 1209 | @safety{@prelim{}@mtunsafe{@mtuinit{} @mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} | 
|  | 1210 | @c Same caveats as getutline. | 
|  | 1211 | @c | 
|  | 1212 | @c getutid @mtuinit @mtasurace:utent @mtascusig:ALRM @mtascutimer @ascuheap @asulock @aculock @acsmem @acsfd | 
|  | 1213 | @c   uses a static buffer malloced on the first call | 
|  | 1214 | @c  malloc dup @ascuheap @acsmem | 
|  | 1215 | @c  getutid_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd | 
|  | 1216 | This function searches forward from the current point in the database | 
|  | 1217 | for an entry that matches @var{id}.  If the @code{ut_type} member of the | 
|  | 1218 | @var{id} structure is one of @code{RUN_LVL}, @code{BOOT_TIME}, | 
|  | 1219 | @code{OLD_TIME} or @code{NEW_TIME} the entries match if the | 
|  | 1220 | @code{ut_type} members are identical.  If the @code{ut_type} member of | 
|  | 1221 | the @var{id} structure is @code{INIT_PROCESS}, @code{LOGIN_PROCESS}, | 
|  | 1222 | @code{USER_PROCESS} or @code{DEAD_PROCESS}, the entries match if the | 
|  | 1223 | @code{ut_type} member of the entry read from the database is one of | 
|  | 1224 | these four, and the @code{ut_id} members match.  However if the | 
|  | 1225 | @code{ut_id} member of either the @var{id} structure or the entry read | 
|  | 1226 | from the database is empty it checks if the @code{ut_line} members match | 
|  | 1227 | instead.  If a matching entry is found, @code{getutid} returns a pointer | 
|  | 1228 | to the entry, which is statically allocated, and may be overwritten by a | 
|  | 1229 | subsequent call to @code{getutent}, @code{getutid} or @code{getutline}. | 
|  | 1230 | You must copy the contents of the structure if you wish to save the | 
|  | 1231 | information. | 
|  | 1232 |  | 
|  | 1233 | A null pointer is returned in case the end of the database is reached | 
|  | 1234 | without a match. | 
|  | 1235 |  | 
|  | 1236 | The @code{getutid} function may cache the last read entry.  Therefore, | 
|  | 1237 | if you are using @code{getutid} to search for multiple occurrences, it | 
|  | 1238 | is necessary to zero out the static data after each call.  Otherwise | 
|  | 1239 | @code{getutid} could just return a pointer to the same entry over and | 
|  | 1240 | over again. | 
|  | 1241 | @end deftypefun | 
|  | 1242 |  | 
|  | 1243 | @comment utmp.h | 
|  | 1244 | @comment SVID | 
|  | 1245 | @deftypefun {struct utmp *} getutline (const struct utmp *@var{line}) | 
|  | 1246 | @safety{@prelim{}@mtunsafe{@mtuinit{} @mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} | 
|  | 1247 | @c The static buffer that holds results is allocated with malloc at | 
|  | 1248 | @c the first call; the test is not thread-safe, so multiple concurrent | 
|  | 1249 | @c calls could malloc multiple buffers. | 
|  | 1250 |  | 
|  | 1251 | @c getutline @mtuinit @mtasurace:utent @mtascusig:ALRM @mtascutimer @ascuheap @asulock @aculock @acsfd @acsmem | 
|  | 1252 | @c  malloc @asulock @aculock @acsfd @acsmem | 
|  | 1253 | @c  getutline_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd | 
|  | 1254 | This function searches forward from the current point in the database | 
|  | 1255 | until it finds an entry whose @code{ut_type} value is | 
|  | 1256 | @code{LOGIN_PROCESS} or @code{USER_PROCESS}, and whose @code{ut_line} | 
|  | 1257 | member matches the @code{ut_line} member of the @var{line} structure. | 
|  | 1258 | If it finds such an entry, it returns a pointer to the entry which is | 
|  | 1259 | statically allocated, and may be overwritten by a subsequent call to | 
|  | 1260 | @code{getutent}, @code{getutid} or @code{getutline}.  You must copy the | 
|  | 1261 | contents of the structure if you wish to save the information. | 
|  | 1262 |  | 
|  | 1263 | A null pointer is returned in case the end of the database is reached | 
|  | 1264 | without a match. | 
|  | 1265 |  | 
|  | 1266 | The @code{getutline} function may cache the last read entry.  Therefore | 
|  | 1267 | if you are using @code{getutline} to search for multiple occurrences, it | 
|  | 1268 | is necessary to zero out the static data after each call.  Otherwise | 
|  | 1269 | @code{getutline} could just return a pointer to the same entry over and | 
|  | 1270 | over again. | 
|  | 1271 | @end deftypefun | 
|  | 1272 |  | 
|  | 1273 | @comment utmp.h | 
|  | 1274 | @comment SVID | 
|  | 1275 | @deftypefun {struct utmp *} pututline (const struct utmp *@var{utmp}) | 
|  | 1276 | @safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} | 
|  | 1277 | @c pututline @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd | 
|  | 1278 | @c  libc_lock_lock dup @asulock @aculock | 
|  | 1279 | @c  *libc_utmp_jump_table->pututline @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd | 
|  | 1280 | @c   pututline_unknown @mtasurace:utent @acsfd | 
|  | 1281 | @c    setutent_unknown dup @mtasurace:utent @acsfd | 
|  | 1282 | @c   pututline_file @mtascusig:ALRM @mtascutimer @acsfd | 
|  | 1283 | @c    TRANSFORM_UTMP_FILE_NAME ok | 
|  | 1284 | @c     strcmp dup ok | 
|  | 1285 | @c     acesss dup ok | 
|  | 1286 | @c    open_not_cancel_2 dup @acsfd | 
|  | 1287 | @c    fcntl_not_cancel dup ok | 
|  | 1288 | @c    close_not_cancel_no_status dup @acsfd | 
|  | 1289 | @c    llseek dup ok | 
|  | 1290 | @c    dup2 dup ok | 
|  | 1291 | @c    utmp_equal dup ok | 
|  | 1292 | @c    internal_getut_r dup @mtascusig:ALRM @mtascutimer | 
|  | 1293 | @c    LOCK_FILE dup @mtascusig:ALRM @mtasctimer | 
|  | 1294 | @c    LOCKING_FAILED dup ok | 
|  | 1295 | @c    ftruncate64 dup ok | 
|  | 1296 | @c    write_not_cancel dup ok | 
|  | 1297 | @c    UNLOCK_FILE dup @mtasctimer | 
|  | 1298 | @c  libc_lock_unlock dup @aculock | 
|  | 1299 | The @code{pututline} function inserts the entry @code{*@var{utmp}} at | 
|  | 1300 | the appropriate place in the user accounting database.  If it finds that | 
|  | 1301 | it is not already at the correct place in the database, it uses | 
|  | 1302 | @code{getutid} to search for the position to insert the entry, however | 
|  | 1303 | this will not modify the static structure returned by @code{getutent}, | 
|  | 1304 | @code{getutid} and @code{getutline}.  If this search fails, the entry | 
|  | 1305 | is appended to the database. | 
|  | 1306 |  | 
|  | 1307 | The @code{pututline} function returns a pointer to a copy of the entry | 
|  | 1308 | inserted in the user accounting database, or a null pointer if the entry | 
|  | 1309 | could not be added.  The following @code{errno} error conditions are | 
|  | 1310 | defined for this function: | 
|  | 1311 |  | 
|  | 1312 | @table @code | 
|  | 1313 | @item EPERM | 
|  | 1314 | The process does not have the appropriate privileges; you cannot modify | 
|  | 1315 | the user accounting database. | 
|  | 1316 | @end table | 
|  | 1317 | @end deftypefun | 
|  | 1318 |  | 
|  | 1319 | All the @code{get*} functions mentioned before store the information | 
|  | 1320 | they return in a static buffer.  This can be a problem in multi-threaded | 
|  | 1321 | programs since the data returned for the request is overwritten by the | 
|  | 1322 | return value data in another thread.  Therefore @theglibc{} | 
|  | 1323 | provides as extensions three more functions which return the data in a | 
|  | 1324 | user-provided buffer. | 
|  | 1325 |  | 
|  | 1326 | @comment utmp.h | 
|  | 1327 | @comment GNU | 
|  | 1328 | @deftypefun int getutent_r (struct utmp *@var{buffer}, struct utmp **@var{result}) | 
|  | 1329 | @safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} | 
|  | 1330 | @c getutent_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd | 
|  | 1331 | @c  libc_lock_lock dup @asulock @aculock | 
|  | 1332 | @c  *libc_utmp_jump_table->getutent_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd | 
|  | 1333 | @c   getutent_r_unknown @mtasurace:utent @acsfd | 
|  | 1334 | @c    setutent_unknown dup @mtasurace:utent @acsfd | 
|  | 1335 | @c   getutent_r_file @mtasurace:utent @mtascusig:ALRM @mtascutimer | 
|  | 1336 | @c    LOCK_FILE @mtascusig:ALRM @mtascutimer | 
|  | 1337 | @c     alarm dup @mtascutimer | 
|  | 1338 | @c     sigemptyset dup ok | 
|  | 1339 | @c     sigaction dup ok | 
|  | 1340 | @c     memset dup ok | 
|  | 1341 | @c     fcntl_not_cancel dup ok | 
|  | 1342 | @c    LOCKING_FAILED ok | 
|  | 1343 | @c    read_not_cancel dup ok | 
|  | 1344 | @c    UNLOCK_FILE @mtascutimer | 
|  | 1345 | @c     fcntl_not_cancel dup ok | 
|  | 1346 | @c     alarm dup @mtascutimer | 
|  | 1347 | @c     sigaction dup ok | 
|  | 1348 | @c    memcpy dup ok | 
|  | 1349 | @c  libc_lock_unlock dup ok | 
|  | 1350 | The @code{getutent_r} is equivalent to the @code{getutent} function.  It | 
|  | 1351 | returns the next entry from the database.  But instead of storing the | 
|  | 1352 | information in a static buffer it stores it in the buffer pointed to by | 
|  | 1353 | the parameter @var{buffer}. | 
|  | 1354 |  | 
|  | 1355 | If the call was successful, the function returns @code{0} and the | 
|  | 1356 | pointer variable pointed to by the parameter @var{result} contains a | 
|  | 1357 | pointer to the buffer which contains the result (this is most probably | 
|  | 1358 | the same value as @var{buffer}).  If something went wrong during the | 
|  | 1359 | execution of @code{getutent_r} the function returns @code{-1}. | 
|  | 1360 |  | 
|  | 1361 | This function is a GNU extension. | 
|  | 1362 | @end deftypefun | 
|  | 1363 |  | 
|  | 1364 | @comment utmp.h | 
|  | 1365 | @comment GNU | 
|  | 1366 | @deftypefun int getutid_r (const struct utmp *@var{id}, struct utmp *@var{buffer}, struct utmp **@var{result}) | 
|  | 1367 | @safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} | 
|  | 1368 | @c getutid_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd | 
|  | 1369 | @c  libc_lock_lock dup @asulock @aculock | 
|  | 1370 | @c  *libc_utmp_jump_table->getutid_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd | 
|  | 1371 | @c   getutid_r_unknown @mtasurace:utent @acsfd | 
|  | 1372 | @c    setutent_unknown dup @mtasurace:utent @acsfd | 
|  | 1373 | @c   getutid_r_file @mtascusig:ALRM @mtascutimer | 
|  | 1374 | @c    internal_getut_r @mtascusig:ALRM @mtascutimer | 
|  | 1375 | @c     LOCK_FILE dup @mtascusig:ALRM @mtascutimer | 
|  | 1376 | @c     LOCKING_FAILED dup ok | 
|  | 1377 | @c     read_not_cancel dup ok | 
|  | 1378 | @c     utmp_equal ok | 
|  | 1379 | @c      strncmp dup ok | 
|  | 1380 | @c     UNLOCK_FILE dup @mtascutimer | 
|  | 1381 | @c    memcpy dup ok | 
|  | 1382 | @c  libc_lock_unlock dup @aculock | 
|  | 1383 | This function retrieves just like @code{getutid} the next entry matching | 
|  | 1384 | the information stored in @var{id}.  But the result is stored in the | 
|  | 1385 | buffer pointed to by the parameter @var{buffer}. | 
|  | 1386 |  | 
|  | 1387 | If successful the function returns @code{0} and the pointer variable | 
|  | 1388 | pointed to by the parameter @var{result} contains a pointer to the | 
|  | 1389 | buffer with the result (probably the same as @var{result}.  If not | 
|  | 1390 | successful the function return @code{-1}. | 
|  | 1391 |  | 
|  | 1392 | This function is a GNU extension. | 
|  | 1393 | @end deftypefun | 
|  | 1394 |  | 
|  | 1395 | @comment utmp.h | 
|  | 1396 | @comment GNU | 
|  | 1397 | @deftypefun int getutline_r (const struct utmp *@var{line}, struct utmp *@var{buffer}, struct utmp **@var{result}) | 
|  | 1398 | @safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} | 
|  | 1399 | @c getutline_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd | 
|  | 1400 | @c  libc_lock_lock dup @asulock @aculock | 
|  | 1401 | @c  *libc_utmp_jump_table->getutline_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd | 
|  | 1402 | @c   getutline_r_unknown @mtasurace:utent @acsfd | 
|  | 1403 | @c    setutent_unknown dup @mtasurace:utent @acsfd | 
|  | 1404 | @c   getutline_r_file @mtasurace:utent @mtascusig:ALRM @mtascutimer | 
|  | 1405 | @c    LOCK_FILE @mtascusig:ALRM @mtascutimer | 
|  | 1406 | @c     alarm dup @mtascutimer | 
|  | 1407 | @c     sigemptyset dup ok | 
|  | 1408 | @c     sigaction dup ok | 
|  | 1409 | @c     memset dup ok | 
|  | 1410 | @c     fcntl_not_cancel dup ok | 
|  | 1411 | @c    LOCKING_FAILED ok | 
|  | 1412 | @c    read_not_cancel dup ok | 
|  | 1413 | @c    strncmp dup ok | 
|  | 1414 | @c    UNLOCK_FILE @mtascutimer | 
|  | 1415 | @c     fcntl_not_cancel dup ok | 
|  | 1416 | @c     alarm dup @mtascutimer | 
|  | 1417 | @c     sigaction dup ok | 
|  | 1418 | @c    memcpy dup ok | 
|  | 1419 | @c  libc_lock_unlock dup ok | 
|  | 1420 | This function retrieves just like @code{getutline} the next entry | 
|  | 1421 | matching the information stored in @var{line}.  But the result is stored | 
|  | 1422 | in the buffer pointed to by the parameter @var{buffer}. | 
|  | 1423 |  | 
|  | 1424 | If successful the function returns @code{0} and the pointer variable | 
|  | 1425 | pointed to by the parameter @var{result} contains a pointer to the | 
|  | 1426 | buffer with the result (probably the same as @var{result}.  If not | 
|  | 1427 | successful the function return @code{-1}. | 
|  | 1428 |  | 
|  | 1429 | This function is a GNU extension. | 
|  | 1430 | @end deftypefun | 
|  | 1431 |  | 
|  | 1432 |  | 
|  | 1433 | In addition to the user accounting database, most systems keep a number | 
|  | 1434 | of similar databases.  For example most systems keep a log file with all | 
|  | 1435 | previous logins (usually in @file{/etc/wtmp} or @file{/var/log/wtmp}). | 
|  | 1436 |  | 
|  | 1437 | For specifying which database to examine, the following function should | 
|  | 1438 | be used. | 
|  | 1439 |  | 
|  | 1440 | @comment utmp.h | 
|  | 1441 | @comment SVID | 
|  | 1442 | @deftypefun int utmpname (const char *@var{file}) | 
|  | 1443 | @safety{@prelim{}@mtunsafe{@mtasurace{:utent}}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{}}} | 
|  | 1444 | @c utmpname @mtasurace:utent @asulock @ascuheap @aculock @acsmem | 
|  | 1445 | @c  libc_lock_lock dup @asulock @aculock | 
|  | 1446 | @c  *libc_utmp_jump_table->endutent dup @mtasurace:utent | 
|  | 1447 | @c  strcmp dup ok | 
|  | 1448 | @c  free dup @ascuheap @acsmem | 
|  | 1449 | @c  strdup dup @ascuheap @acsmem | 
|  | 1450 | @c  libc_lock_unlock dup @aculock | 
|  | 1451 | The @code{utmpname} function changes the name of the database to be | 
|  | 1452 | examined to @var{file}, and closes any previously opened database.  By | 
|  | 1453 | default @code{getutent}, @code{getutid}, @code{getutline} and | 
|  | 1454 | @code{pututline} read from and write to the user accounting database. | 
|  | 1455 |  | 
|  | 1456 | The following macros are defined for use as the @var{file} argument: | 
|  | 1457 |  | 
|  | 1458 | @deftypevr Macro {char *} _PATH_UTMP | 
|  | 1459 | This macro is used to specify the user accounting database. | 
|  | 1460 | @end deftypevr | 
|  | 1461 |  | 
|  | 1462 | @deftypevr Macro {char *} _PATH_WTMP | 
|  | 1463 | This macro is used to specify the user accounting log file. | 
|  | 1464 | @end deftypevr | 
|  | 1465 |  | 
|  | 1466 | The @code{utmpname} function returns a value of @code{0} if the new name | 
|  | 1467 | was successfully stored, and a value of @code{-1} to indicate an error. | 
|  | 1468 | Note that @code{utmpname} does not try to open the database, and that | 
|  | 1469 | therefore the return value does not say anything about whether the | 
|  | 1470 | database can be successfully opened. | 
|  | 1471 | @end deftypefun | 
|  | 1472 |  | 
|  | 1473 | Specially for maintaining log-like databases @theglibc{} provides | 
|  | 1474 | the following function: | 
|  | 1475 |  | 
|  | 1476 | @comment utmp.h | 
|  | 1477 | @comment SVID | 
|  | 1478 | @deftypefun void updwtmp (const char *@var{wtmp_file}, const struct utmp *@var{utmp}) | 
|  | 1479 | @safety{@prelim{}@mtunsafe{@mtascusig{:ALRM} @mtascutimer{}}@asunsafe{}@acunsafe{@acsfd{}}} | 
|  | 1480 | @c updwtmp @mtascusig:ALRM @mtascutimer @acsfd | 
|  | 1481 | @c  TRANSFORM_UTMP_FILE_NAME dup ok | 
|  | 1482 | @c  *libc_utmp_file_functions->updwtmp = updwtmp_file @mtascusig:ALRM @mtascutimer @acsfd | 
|  | 1483 | @c   open_not_cancel_2 dup @acsfd | 
|  | 1484 | @c   LOCK_FILE dup @mtascusig:ALRM @mtascutimer | 
|  | 1485 | @c   LOCKING_FAILED dup ok | 
|  | 1486 | @c   lseek64 dup ok | 
|  | 1487 | @c   ftruncate64 dup ok | 
|  | 1488 | @c   write_not_cancel dup ok | 
|  | 1489 | @c   UNLOCK_FILE dup @mtascutimer | 
|  | 1490 | @c   close_not_cancel_no_status dup @acsfd | 
|  | 1491 | The @code{updwtmp} function appends the entry *@var{utmp} to the | 
|  | 1492 | database specified by @var{wtmp_file}.  For possible values for the | 
|  | 1493 | @var{wtmp_file} argument see the @code{utmpname} function. | 
|  | 1494 | @end deftypefun | 
|  | 1495 |  | 
|  | 1496 | @strong{Portability Note:} Although many operating systems provide a | 
|  | 1497 | subset of these functions, they are not standardized.  There are often | 
|  | 1498 | subtle differences in the return types, and there are considerable | 
|  | 1499 | differences between the various definitions of @code{struct utmp}.  When | 
|  | 1500 | programming for @theglibc{}, it is probably best to stick | 
|  | 1501 | with the functions described in this section.  If however, you want your | 
|  | 1502 | program to be portable, consider using the XPG functions described in | 
|  | 1503 | @ref{XPG Functions}, or take a look at the BSD compatible functions in | 
|  | 1504 | @ref{Logging In and Out}. | 
|  | 1505 |  | 
|  | 1506 |  | 
|  | 1507 | @node XPG Functions | 
|  | 1508 | @subsection XPG User Accounting Database Functions | 
|  | 1509 |  | 
|  | 1510 | These functions, described in the X/Open Portability Guide, are declared | 
|  | 1511 | in the header file @file{utmpx.h}. | 
|  | 1512 | @pindex utmpx.h | 
|  | 1513 |  | 
|  | 1514 | @deftp {Data Type} {struct utmpx} | 
|  | 1515 | The @code{utmpx} data structure contains at least the following members: | 
|  | 1516 |  | 
|  | 1517 | @table @code | 
|  | 1518 | @item short int ut_type | 
|  | 1519 | Specifies the type of login; one of @code{EMPTY}, @code{RUN_LVL}, | 
|  | 1520 | @code{BOOT_TIME}, @code{OLD_TIME}, @code{NEW_TIME}, @code{INIT_PROCESS}, | 
|  | 1521 | @code{LOGIN_PROCESS}, @code{USER_PROCESS} or @code{DEAD_PROCESS}. | 
|  | 1522 |  | 
|  | 1523 | @item pid_t ut_pid | 
|  | 1524 | The process ID number of the login process. | 
|  | 1525 |  | 
|  | 1526 | @item char ut_line[] | 
|  | 1527 | The device name of the tty (without @file{/dev/}). | 
|  | 1528 |  | 
|  | 1529 | @item char ut_id[] | 
|  | 1530 | The inittab ID of the process. | 
|  | 1531 |  | 
|  | 1532 | @item char ut_user[] | 
|  | 1533 | The user's login name. | 
|  | 1534 |  | 
|  | 1535 | @item struct timeval ut_tv | 
|  | 1536 | Time the entry was made.  For entries of type @code{OLD_TIME} this is | 
|  | 1537 | the time when the system clock changed, and for entries of type | 
|  | 1538 | @code{NEW_TIME} this is the time the system clock was set to. | 
|  | 1539 | @end table | 
|  | 1540 | In @theglibc{}, @code{struct utmpx} is identical to @code{struct | 
|  | 1541 | utmp} except for the fact that including @file{utmpx.h} does not make | 
|  | 1542 | visible the declaration of @code{struct exit_status}. | 
|  | 1543 | @end deftp | 
|  | 1544 |  | 
|  | 1545 | The following macros are defined for use as values for the | 
|  | 1546 | @code{ut_type} member of the @code{utmpx} structure.  The values are | 
|  | 1547 | integer constants and are, in @theglibc{}, identical to the | 
|  | 1548 | definitions in @file{utmp.h}. | 
|  | 1549 |  | 
|  | 1550 | @table @code | 
|  | 1551 | @comment utmpx.h | 
|  | 1552 | @comment XPG4.2 | 
|  | 1553 | @vindex EMPTY | 
|  | 1554 | @item EMPTY | 
|  | 1555 | This macro is used to indicate that the entry contains no valid user | 
|  | 1556 | accounting information. | 
|  | 1557 |  | 
|  | 1558 | @comment utmpx.h | 
|  | 1559 | @comment XPG4.2 | 
|  | 1560 | @vindex RUN_LVL | 
|  | 1561 | @item RUN_LVL | 
|  | 1562 | This macro is used to identify the systems runlevel. | 
|  | 1563 |  | 
|  | 1564 | @comment utmpx.h | 
|  | 1565 | @comment XPG4.2 | 
|  | 1566 | @vindex BOOT_TIME | 
|  | 1567 | @item BOOT_TIME | 
|  | 1568 | This macro is used to identify the time of system boot. | 
|  | 1569 |  | 
|  | 1570 | @comment utmpx.h | 
|  | 1571 | @comment XPG4.2 | 
|  | 1572 | @vindex OLD_TIME | 
|  | 1573 | @item OLD_TIME | 
|  | 1574 | This macro is used to identify the time when the system clock changed. | 
|  | 1575 |  | 
|  | 1576 | @comment utmpx.h | 
|  | 1577 | @comment XPG4.2 | 
|  | 1578 | @vindex NEW_TIME | 
|  | 1579 | @item NEW_TIME | 
|  | 1580 | This macro is used to identify the time after the system changed. | 
|  | 1581 |  | 
|  | 1582 | @comment utmpx.h | 
|  | 1583 | @comment XPG4.2 | 
|  | 1584 | @vindex INIT_PROCESS | 
|  | 1585 | @item INIT_PROCESS | 
|  | 1586 | This macro is used to identify a process spawned by the init process. | 
|  | 1587 |  | 
|  | 1588 | @comment utmpx.h | 
|  | 1589 | @comment XPG4.2 | 
|  | 1590 | @vindex LOGIN_PROCESS | 
|  | 1591 | @item LOGIN_PROCESS | 
|  | 1592 | This macro is used to identify the session leader of a logged in user. | 
|  | 1593 |  | 
|  | 1594 | @comment utmpx.h | 
|  | 1595 | @comment XPG4.2 | 
|  | 1596 | @vindex USER_PROCESS | 
|  | 1597 | @item USER_PROCESS | 
|  | 1598 | This macro is used to identify a user process. | 
|  | 1599 |  | 
|  | 1600 | @comment utmpx.h | 
|  | 1601 | @comment XPG4.2 | 
|  | 1602 | @vindex DEAD_PROCESS | 
|  | 1603 | @item DEAD_PROCESS | 
|  | 1604 | This macro is used to identify a terminated process. | 
|  | 1605 | @end table | 
|  | 1606 |  | 
|  | 1607 | The size of the @code{ut_line}, @code{ut_id} and @code{ut_user} arrays | 
|  | 1608 | can be found using the @code{sizeof} operator. | 
|  | 1609 |  | 
|  | 1610 | @comment utmpx.h | 
|  | 1611 | @comment XPG4.2 | 
|  | 1612 | @deftypefun void setutxent (void) | 
|  | 1613 | @safety{@prelim{}@mtunsafe{@mtasurace{:utent}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} | 
|  | 1614 | This function is similar to @code{setutent}.  In @theglibc{} it is | 
|  | 1615 | simply an alias for @code{setutent}. | 
|  | 1616 | @end deftypefun | 
|  | 1617 |  | 
|  | 1618 | @comment utmpx.h | 
|  | 1619 | @comment XPG4.2 | 
|  | 1620 | @deftypefun {struct utmpx *} getutxent (void) | 
|  | 1621 | @safety{@prelim{}@mtunsafe{@mtuinit{} @mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} | 
|  | 1622 | The @code{getutxent} function is similar to @code{getutent}, but returns | 
|  | 1623 | a pointer to a @code{struct utmpx} instead of @code{struct utmp}.  In | 
|  | 1624 | @theglibc{} it simply is an alias for @code{getutent}. | 
|  | 1625 | @end deftypefun | 
|  | 1626 |  | 
|  | 1627 | @comment utmpx.h | 
|  | 1628 | @comment XPG4.2 | 
|  | 1629 | @deftypefun void endutxent (void) | 
|  | 1630 | @safety{@prelim{}@mtunsafe{@mtasurace{:utent}}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} | 
|  | 1631 | This function is similar to @code{endutent}.  In @theglibc{} it is | 
|  | 1632 | simply an alias for @code{endutent}. | 
|  | 1633 | @end deftypefun | 
|  | 1634 |  | 
|  | 1635 | @comment utmpx.h | 
|  | 1636 | @comment XPG4.2 | 
|  | 1637 | @deftypefun {struct utmpx *} getutxid (const struct utmpx *@var{id}) | 
|  | 1638 | @safety{@prelim{}@mtunsafe{@mtuinit{} @mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{} @acsfd{}}} | 
|  | 1639 | This function is similar to @code{getutid}, but uses @code{struct utmpx} | 
|  | 1640 | instead of @code{struct utmp}.  In @theglibc{} it is simply an alias | 
|  | 1641 | for @code{getutid}. | 
|  | 1642 | @end deftypefun | 
|  | 1643 |  | 
|  | 1644 | @comment utmpx.h | 
|  | 1645 | @comment XPG4.2 | 
|  | 1646 | @deftypefun {struct utmpx *} getutxline (const struct utmpx *@var{line}) | 
|  | 1647 | @safety{@prelim{}@mtunsafe{@mtuinit{} @mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} | 
|  | 1648 | This function is similar to @code{getutid}, but uses @code{struct utmpx} | 
|  | 1649 | instead of @code{struct utmp}.  In @theglibc{} it is simply an alias | 
|  | 1650 | for @code{getutline}. | 
|  | 1651 | @end deftypefun | 
|  | 1652 |  | 
|  | 1653 | @comment utmpx.h | 
|  | 1654 | @comment XPG4.2 | 
|  | 1655 | @deftypefun {struct utmpx *} pututxline (const struct utmpx *@var{utmp}) | 
|  | 1656 | @safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} | 
|  | 1657 | The @code{pututxline} function is functionally identical to | 
|  | 1658 | @code{pututline}, but uses @code{struct utmpx} instead of @code{struct | 
|  | 1659 | utmp}.  In @theglibc{}, @code{pututxline} is simply an alias for | 
|  | 1660 | @code{pututline}. | 
|  | 1661 | @end deftypefun | 
|  | 1662 |  | 
|  | 1663 | @comment utmpx.h | 
|  | 1664 | @comment XPG4.2 | 
|  | 1665 | @deftypefun int utmpxname (const char *@var{file}) | 
|  | 1666 | @safety{@prelim{}@mtunsafe{@mtasurace{:utent}}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{}}} | 
|  | 1667 | The @code{utmpxname} function is functionally identical to | 
|  | 1668 | @code{utmpname}.  In @theglibc{}, @code{utmpxname} is simply an | 
|  | 1669 | alias for @code{utmpname}. | 
|  | 1670 | @end deftypefun | 
|  | 1671 |  | 
|  | 1672 | You can translate between a traditional @code{struct utmp} and an XPG | 
|  | 1673 | @code{struct utmpx} with the following functions.  In @theglibc{}, | 
|  | 1674 | these functions are merely copies, since the two structures are | 
|  | 1675 | identical. | 
|  | 1676 |  | 
|  | 1677 | @comment utmpx.h | 
|  | 1678 | @comment utmp.h | 
|  | 1679 | @comment GNU | 
|  | 1680 | @deftypefun int getutmp (const struct utmpx *@var{utmpx}, struct utmp *@var{utmp}) | 
|  | 1681 | @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} | 
|  | 1682 | @code{getutmp} copies the information, insofar as the structures are | 
|  | 1683 | compatible, from @var{utmpx} to @var{utmp}. | 
|  | 1684 | @end deftypefun | 
|  | 1685 |  | 
|  | 1686 | @comment utmpx.h | 
|  | 1687 | @comment utmp.h | 
|  | 1688 | @comment GNU | 
|  | 1689 | @deftypefun int getutmpx (const struct utmp *@var{utmp}, struct utmpx *@var{utmpx}) | 
|  | 1690 | @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} | 
|  | 1691 | @code{getutmpx} copies the information, insofar as the structures are | 
|  | 1692 | compatible, from @var{utmp} to @var{utmpx}. | 
|  | 1693 | @end deftypefun | 
|  | 1694 |  | 
|  | 1695 |  | 
|  | 1696 | @node Logging In and Out | 
|  | 1697 | @subsection Logging In and Out | 
|  | 1698 |  | 
|  | 1699 | These functions, derived from BSD, are available in the separate | 
|  | 1700 | @file{libutil} library, and declared in @file{utmp.h}. | 
|  | 1701 | @pindex utmp.h | 
|  | 1702 |  | 
|  | 1703 | Note that the @code{ut_user} member of @code{struct utmp} is called | 
|  | 1704 | @code{ut_name} in BSD.  Therefore, @code{ut_name} is defined as an alias | 
|  | 1705 | for @code{ut_user} in @file{utmp.h}. | 
|  | 1706 |  | 
|  | 1707 | @comment utmp.h | 
|  | 1708 | @comment BSD | 
|  | 1709 | @deftypefun int login_tty (int @var{filedes}) | 
|  | 1710 | @safety{@prelim{}@mtunsafe{@mtasurace{:ttyname}}@asunsafe{@ascuheap{} @asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} | 
|  | 1711 | @c If this function is canceled, it may have succeeded in redirecting | 
|  | 1712 | @c only some of the standard streams to the newly opened terminal. | 
|  | 1713 | @c Should there be a safety annotation for this? | 
|  | 1714 | @c login_tty @mtasurace:ttyname @ascuheap @asulock @aculock @acsmem @acsfd | 
|  | 1715 | @c  setsid dup ok | 
|  | 1716 | @c  ioctl dup ok | 
|  | 1717 | @c  ttyname dup @mtasurace:ttyname @ascuheap @asulock @aculock @acsmem @acsfd | 
|  | 1718 | @c  close dup @acsfd | 
|  | 1719 | @c  open dup @acsfd | 
|  | 1720 | @c  dup2 dup ok | 
|  | 1721 | This function makes @var{filedes} the controlling terminal of the | 
|  | 1722 | current process, redirects standard input, standard output and | 
|  | 1723 | standard error output to this terminal, and closes @var{filedes}. | 
|  | 1724 |  | 
|  | 1725 | This function returns @code{0} on successful completion, and @code{-1} | 
|  | 1726 | on error. | 
|  | 1727 | @end deftypefun | 
|  | 1728 |  | 
|  | 1729 | @comment utmp.h | 
|  | 1730 | @comment BSD | 
|  | 1731 | @deftypefun void login (const struct utmp *@var{entry}) | 
|  | 1732 | @safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acucorrupt{} @acsfd{} @acsmem{}}} | 
|  | 1733 | @c login @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @ascuheap @aculock @acucorrupt @acsfd @acsmem | 
|  | 1734 | @c  getpid dup ok | 
|  | 1735 | @c  tty_name @ascuheap @acucorrupt @acsmem @acsfd | 
|  | 1736 | @c   ttyname_r dup @ascuheap @acsmem @acsfd | 
|  | 1737 | @c   memchr dup ok | 
|  | 1738 | @c   realloc dup @ascuheap @acsmem | 
|  | 1739 | @c   malloc dup @ascuheap @acsmem | 
|  | 1740 | @c   free dup @ascuheap @acsmem | 
|  | 1741 | @c  strncmp dup ok | 
|  | 1742 | @c  basename dup ok | 
|  | 1743 | @c  strncpy dup ok | 
|  | 1744 | @c  utmpname dup @mtasurace:utent @asulock @ascuheap @aculock @acsmem | 
|  | 1745 | @c  setutent dup @mtasurace:utent @asulock @aculock @acsfd | 
|  | 1746 | @c  pututline dup @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd | 
|  | 1747 | @c  endutent dup @mtasurace:utent @asulock @aculock | 
|  | 1748 | @c  free dup @ascuheap @acsmem | 
|  | 1749 | @c  updwtmp dup @mtascusig:ALRM @mtascutimer @acsfd | 
|  | 1750 | The @code{login} functions inserts an entry into the user accounting | 
|  | 1751 | database.  The @code{ut_line} member is set to the name of the terminal | 
|  | 1752 | on standard input.  If standard input is not a terminal @code{login} | 
|  | 1753 | uses standard output or standard error output to determine the name of | 
|  | 1754 | the terminal.  If @code{struct utmp} has a @code{ut_type} member, | 
|  | 1755 | @code{login} sets it to @code{USER_PROCESS}, and if there is an | 
|  | 1756 | @code{ut_pid} member, it will be set to the process ID of the current | 
|  | 1757 | process.  The remaining entries are copied from @var{entry}. | 
|  | 1758 |  | 
|  | 1759 | A copy of the entry is written to the user accounting log file. | 
|  | 1760 | @end deftypefun | 
|  | 1761 |  | 
|  | 1762 | @comment utmp.h | 
|  | 1763 | @comment BSD | 
|  | 1764 | @deftypefun int logout (const char *@var{ut_line}) | 
|  | 1765 | @safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} | 
|  | 1766 | @c logout @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @ascuheap @aculock @acsfd @acsmem | 
|  | 1767 | @c  utmpname dup @mtasurace:utent @asulock @ascuheap @aculock @acsmem | 
|  | 1768 | @c  setutent dup @mtasurace:utent @asulock @aculock @acsfd | 
|  | 1769 | @c  strncpy dup ok | 
|  | 1770 | @c  getutline_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd | 
|  | 1771 | @c  bzero dup ok | 
|  | 1772 | @c  gettimeofday dup ok | 
|  | 1773 | @c  time dup ok | 
|  | 1774 | @c  pututline dup @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd | 
|  | 1775 | @c  endutent dup @mtasurace:utent @asulock @aculock | 
|  | 1776 | This function modifies the user accounting database to indicate that the | 
|  | 1777 | user on @var{ut_line} has logged out. | 
|  | 1778 |  | 
|  | 1779 | The @code{logout} function returns @code{1} if the entry was successfully | 
|  | 1780 | written to the database, or @code{0} on error. | 
|  | 1781 | @end deftypefun | 
|  | 1782 |  | 
|  | 1783 | @comment utmp.h | 
|  | 1784 | @comment BSD | 
|  | 1785 | @deftypefun void logwtmp (const char *@var{ut_line}, const char *@var{ut_name}, const char *@var{ut_host}) | 
|  | 1786 | @safety{@prelim{}@mtunsafe{@mtascusig{:ALRM} @mtascutimer{}}@asunsafe{}@acunsafe{@acsfd{}}} | 
|  | 1787 | @c logwtmp @mtascusig:ALRM @mtascutimer @acsfd | 
|  | 1788 | @c  memset dup ok | 
|  | 1789 | @c  getpid dup ok | 
|  | 1790 | @c  strncpy dup ok | 
|  | 1791 | @c  gettimeofday dup ok | 
|  | 1792 | @c  time dup ok | 
|  | 1793 | @c  updwtmp dup @mtascusig:ALRM @mtascutimer @acsfd | 
|  | 1794 | The @code{logwtmp} function appends an entry to the user accounting log | 
|  | 1795 | file, for the current time and the information provided in the | 
|  | 1796 | @var{ut_line}, @var{ut_name} and @var{ut_host} arguments. | 
|  | 1797 | @end deftypefun | 
|  | 1798 |  | 
|  | 1799 | @strong{Portability Note:} The BSD @code{struct utmp} only has the | 
|  | 1800 | @code{ut_line}, @code{ut_name}, @code{ut_host} and @code{ut_time} | 
|  | 1801 | members.  Older systems do not even have the @code{ut_host} member. | 
|  | 1802 |  | 
|  | 1803 |  | 
|  | 1804 | @node User Database | 
|  | 1805 | @section User Database | 
|  | 1806 | @cindex user database | 
|  | 1807 | @cindex password database | 
|  | 1808 | @pindex /etc/passwd | 
|  | 1809 |  | 
|  | 1810 | This section describes how to search and scan the database of registered | 
|  | 1811 | users.  The database itself is kept in the file @file{/etc/passwd} on | 
|  | 1812 | most systems, but on some systems a special network server gives access | 
|  | 1813 | to it. | 
|  | 1814 |  | 
|  | 1815 | @menu | 
|  | 1816 | * User Data Structure::         What each user record contains. | 
|  | 1817 | * Lookup User::                 How to look for a particular user. | 
|  | 1818 | * Scanning All Users::          Scanning the list of all users, one by one. | 
|  | 1819 | * Writing a User Entry::        How a program can rewrite a user's record. | 
|  | 1820 | @end menu | 
|  | 1821 |  | 
|  | 1822 | @node User Data Structure | 
|  | 1823 | @subsection The Data Structure that Describes a User | 
|  | 1824 |  | 
|  | 1825 | The functions and data structures for accessing the system user database | 
|  | 1826 | are declared in the header file @file{pwd.h}. | 
|  | 1827 | @pindex pwd.h | 
|  | 1828 |  | 
|  | 1829 | @comment pwd.h | 
|  | 1830 | @comment POSIX.1 | 
|  | 1831 | @deftp {Data Type} {struct passwd} | 
|  | 1832 | The @code{passwd} data structure is used to hold information about | 
|  | 1833 | entries in the system user data base.  It has at least the following members: | 
|  | 1834 |  | 
|  | 1835 | @table @code | 
|  | 1836 | @item char *pw_name | 
|  | 1837 | The user's login name. | 
|  | 1838 |  | 
|  | 1839 | @item char *pw_passwd. | 
|  | 1840 | The encrypted password string. | 
|  | 1841 |  | 
|  | 1842 | @item uid_t pw_uid | 
|  | 1843 | The user ID number. | 
|  | 1844 |  | 
|  | 1845 | @item gid_t pw_gid | 
|  | 1846 | The user's default group ID number. | 
|  | 1847 |  | 
|  | 1848 | @item char *pw_gecos | 
|  | 1849 | A string typically containing the user's real name, and possibly other | 
|  | 1850 | information such as a phone number. | 
|  | 1851 |  | 
|  | 1852 | @item char *pw_dir | 
|  | 1853 | The user's home directory, or initial working directory.  This might be | 
|  | 1854 | a null pointer, in which case the interpretation is system-dependent. | 
|  | 1855 |  | 
|  | 1856 | @item char *pw_shell | 
|  | 1857 | The user's default shell, or the initial program run when the user logs in. | 
|  | 1858 | This might be a null pointer, indicating that the system default should | 
|  | 1859 | be used. | 
|  | 1860 | @end table | 
|  | 1861 | @end deftp | 
|  | 1862 |  | 
|  | 1863 | @node Lookup User | 
|  | 1864 | @subsection Looking Up One User | 
|  | 1865 | @cindex converting user ID to user name | 
|  | 1866 | @cindex converting user name to user ID | 
|  | 1867 |  | 
|  | 1868 | You can search the system user database for information about a | 
|  | 1869 | specific user using @code{getpwuid} or @code{getpwnam}.  These | 
|  | 1870 | functions are declared in @file{pwd.h}. | 
|  | 1871 |  | 
|  | 1872 | @comment pwd.h | 
|  | 1873 | @comment POSIX.1 | 
|  | 1874 | @deftypefun {struct passwd *} getpwuid (uid_t @var{uid}) | 
|  | 1875 | @safety{@prelim{}@mtunsafe{@mtasurace{:pwuid} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 1876 | @c getpwuid @mtasurace:pwuid @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 1877 | @c  libc_lock_lock dup @asulock @aculock | 
|  | 1878 | @c  malloc dup @ascuheap @acsmem | 
|  | 1879 | @c  getpwuid_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 1880 | @c  realloc dup @ascuheap @acsmem | 
|  | 1881 | @c  free dup @ascuheap @acsmem | 
|  | 1882 | @c  libc_lock_unlock dup @aculock | 
|  | 1883 | This function returns a pointer to a statically-allocated structure | 
|  | 1884 | containing information about the user whose user ID is @var{uid}.  This | 
|  | 1885 | structure may be overwritten on subsequent calls to @code{getpwuid}. | 
|  | 1886 |  | 
|  | 1887 | A null pointer value indicates there is no user in the data base with | 
|  | 1888 | user ID @var{uid}. | 
|  | 1889 | @end deftypefun | 
|  | 1890 |  | 
|  | 1891 | @comment pwd.h | 
|  | 1892 | @comment POSIX.1c | 
|  | 1893 | @deftypefun int getpwuid_r (uid_t @var{uid}, struct passwd *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct passwd **@var{result}) | 
|  | 1894 | @safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 1895 | @c getpwuid_r @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 1896 | @c  nscd_getpwuid_r @ascuheap @acsfd @acsmem | 
|  | 1897 | @c   itoa_word dup ok | 
|  | 1898 | @c   nscd_getpw_r @ascuheap @acsfd @acsmem | 
|  | 1899 | @c    nscd_get_map_ref @ascuheap @acsfd @acsmem | 
|  | 1900 | @c     nscd_acquire_maplock ok | 
|  | 1901 | @c     nscd_get_mapping @ascuheap @acsfd @acsmem | 
|  | 1902 | @c      open_socket dup @acsfd | 
|  | 1903 | @c      memset dup ok | 
|  | 1904 | @c      wait_on_socket dup ok | 
|  | 1905 | @c      recvmsg dup ok | 
|  | 1906 | @c      strcmp dup ok | 
|  | 1907 | @c      fstat64 dup ok | 
|  | 1908 | @c      mmap dup @acsmem | 
|  | 1909 | @c      munmap dup @acsmem | 
|  | 1910 | @c      malloc dup @ascuheap @acsmem | 
|  | 1911 | @c      close dup ok | 
|  | 1912 | @c      nscd_unmap dup @ascuheap @acsmem | 
|  | 1913 | @c    nscd_cache_search ok | 
|  | 1914 | @c     nis_hash ok | 
|  | 1915 | @c     memcmp dup ok | 
|  | 1916 | @c    nscd_open_socket @acsfd | 
|  | 1917 | @c     open_socket @acsfd | 
|  | 1918 | @c      socket dup @acsfd | 
|  | 1919 | @c      fcntl dup ok | 
|  | 1920 | @c      strcpy dup ok | 
|  | 1921 | @c      connect dup ok | 
|  | 1922 | @c      send dup ok | 
|  | 1923 | @c      gettimeofday dup ok | 
|  | 1924 | @c      poll dup ok | 
|  | 1925 | @c      close_not_cancel_no_status dup @acsfd | 
|  | 1926 | @c     wait_on_socket dup ok | 
|  | 1927 | @c     read dup ok | 
|  | 1928 | @c     close_not_cancel_no_status dup @acsfd | 
|  | 1929 | @c    readall ok | 
|  | 1930 | @c     read dup ok | 
|  | 1931 | @c     wait_on_socket ok | 
|  | 1932 | @c      poll dup ok | 
|  | 1933 | @c      gettimeofday dup ok | 
|  | 1934 | @c    memcpy dup ok | 
|  | 1935 | @c    close_not_cancel_no_status dup @acsfd | 
|  | 1936 | @c    nscd_drop_map_ref @ascuheap @acsmem | 
|  | 1937 | @c     nscd_unmap dup @ascuheap @acsmem | 
|  | 1938 | @c    nscd_unmap @ascuheap @acsmem | 
|  | 1939 | @c     munmap dup ok | 
|  | 1940 | @c     free dup @ascuheap @acsmem | 
|  | 1941 | @c  nss_passwd_lookup2 @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 1942 | @c   nss_database_lookup @mtslocale @ascuheap @asulock @acucorrupt @acsmem @acsfd @aculock | 
|  | 1943 | @c    libc_lock_lock @asulock @aculock | 
|  | 1944 | @c    libc_lock_unlock @aculock | 
|  | 1945 | @c    nss_parse_file @mtslocale @ascuheap @asulock @acucorrupt @acsmem @acsfd @aculock | 
|  | 1946 | @c     fopen dup @ascuheap @asulock @acsmem @acsfd @aculock | 
|  | 1947 | @c     fsetlocking dup ok [no concurrent uses] | 
|  | 1948 | @c     malloc dup @asulock @aculock @acsfd @acsmem | 
|  | 1949 | @c     fclose dup @ascuheap @asulock @acsmem @acsfd @aculock | 
|  | 1950 | @c     getline dup @ascuheap @aculock @acucorrupt @acsmem | 
|  | 1951 | @c     strchrnul dup ok | 
|  | 1952 | @c     nss_getline @mtslocale @ascuheap @acsmem | 
|  | 1953 | @c      isspace @mtslocale^^ | 
|  | 1954 | @c      strlen dup ok | 
|  | 1955 | @c      malloc dup @asulock @aculock @acsfd @acsmem | 
|  | 1956 | @c      memcpy dup ok | 
|  | 1957 | @c      nss_parse_service_list dup @mtslocale^, @ascuheap @acsmem | 
|  | 1958 | @c     feof_unlocked dup ok | 
|  | 1959 | @c     free dup @asulock @aculock @acsfd @acsmem | 
|  | 1960 | @c    strcmp dup ok | 
|  | 1961 | @c    nss_parse_service_list @mtslocale^, @ascuheap @acsmem | 
|  | 1962 | @c     isspace @mtslocale^^ | 
|  | 1963 | @c     malloc dup @asulock @aculock @acsfd @acsmem | 
|  | 1964 | @c     mempcpy dup ok | 
|  | 1965 | @c     strncasecmp dup ok | 
|  | 1966 | @c     free dup @asulock @aculock @acsfd @acsmem | 
|  | 1967 | @c    malloc dup @asulock @aculock @acsfd @acsmem | 
|  | 1968 | @c   nss_lookup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 1969 | @c    nss_lookup_function @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 1970 | @c     libc_lock_lock @asulock @aculock | 
|  | 1971 | @c     tsearch @ascuheap @acucorrupt @acsmem [no @mtsrace or @asucorrupt due to locking] | 
|  | 1972 | @c      known_compare ok | 
|  | 1973 | @c       strcmp dup ok | 
|  | 1974 | @c     malloc dup @ascuheap @acsmem | 
|  | 1975 | @c     tdelete @ascuheap @acucorrupt @acsmem [no @mtsrace or @asucorrupt due to locking] | 
|  | 1976 | @c     free dup @ascuheap @acsmem | 
|  | 1977 | @c     nss_load_library @ascudlopen @ascuplugin @ascuheap @asulock @aculock @acsfd @acsmem | 
|  | 1978 | @c      nss_new_service @ascuheap @acsmem | 
|  | 1979 | @c       strcmp dup ok | 
|  | 1980 | @c       malloc dup @ascuheap @acsmem | 
|  | 1981 | @c      strlen dup ok | 
|  | 1982 | @c      stpcpy dup ok | 
|  | 1983 | @c      libc_dlopen @ascudlopen @ascuheap @asulock @aculock @acsfd @acsmem | 
|  | 1984 | @c      libc_dlsym dup @asulock @aculock @acsfd @acsmem | 
|  | 1985 | @c      *ifct(*nscd_init_cb) @ascuplugin | 
|  | 1986 | @c     stpcpy dup ok | 
|  | 1987 | @c     libc_dlsym dup @asulock @aculock @acsfd @acsmem | 
|  | 1988 | @c     libc_lock_unlock dup ok | 
|  | 1989 | @c    nss_next_action ok | 
|  | 1990 | @c  *fct.l -> _nss_*_getpwuid_r @ascuplugin | 
|  | 1991 | @c  nss_next2 @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 1992 | @c   nss_next_action dup ok | 
|  | 1993 | @c   nss_lookup_function dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 1994 |  | 
|  | 1995 | @c _nss_files_getpwuid_r @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd | 
|  | 1996 | @c  libc_lock_lock dup @asulock @aculock | 
|  | 1997 | @c  internal_setent @ascuheap @asulock @aculock @acsmem @acsfd | 
|  | 1998 | @c   fopen dup @ascuheap @asulock @acsmem @acsfd @aculock | 
|  | 1999 | @c   fileno dup ok | 
|  | 2000 | @c   fcntl dup ok | 
|  | 2001 | @c   fclose dup @ascuheap @asulock @aculock @acsmem @acsfd | 
|  | 2002 | @c   rewind dup @aculock [stream guarded by non-recursive pwent lock] | 
|  | 2003 | @c  internal_getent @mtslocale^ | 
|  | 2004 | @c   fgets_unlocked dup ok [stream guarded by non-recursive pwent lock] | 
|  | 2005 | @c   isspace dup @mtslocale^^ | 
|  | 2006 | @c   _nss_files_parse_pwent = parse_line ok | 
|  | 2007 | @c    strpbrk dup ok | 
|  | 2008 | @c  internal_endent @ascuheap @asulock @aculock @acsmem @acsfd | 
|  | 2009 | @c   fclose dup @ascuheap @asulock @aculock @acsmem @acsfd | 
|  | 2010 | @c  libc_lock_unlock dup @aculock | 
|  | 2011 |  | 
|  | 2012 | @c _nss_nis_getpwuid_r ... not fully reviewed (assumed) @asuinit @asulock @acucorrupt @aculock | 
|  | 2013 | @c  yp_get_default_domain @asulock @aculock | 
|  | 2014 | @c   libc_lock_lock dup @asulock @aculock | 
|  | 2015 | @c   getdomainname dup ok | 
|  | 2016 | @c   strcmp dup ok | 
|  | 2017 | @c   libc_lock_unlock dup @aculock | 
|  | 2018 | @c  snprintf dup @ascuheap @acsmem | 
|  | 2019 | @c  yp_match | 
|  | 2020 | @c   do_ypcall_tr(xdr_ypreq_key,xdr_ypresp_val) | 
|  | 2021 | @c    do_ypcall(xdr_ypreq_key,xdr_ypresp_val) | 
|  | 2022 | @c     libc_lock_lock @asulock @aculock | 
|  | 2023 | @c     strcmp | 
|  | 2024 | @c     yp_bind | 
|  | 2025 | @c     ypclnt_call | 
|  | 2026 | @c      clnt_call | 
|  | 2027 | @c      clnt_perror | 
|  | 2028 | @c     libc_lock_unlock @aculock | 
|  | 2029 | @c     yp_unbind_locked | 
|  | 2030 | @c     yp_unbind | 
|  | 2031 | @c      strcmp dup ok | 
|  | 2032 | @c      calloc dup @asulock @aculock @acsfd @acsmem | 
|  | 2033 | @c      yp_bind_file | 
|  | 2034 | @c       strlen dup ok | 
|  | 2035 | @c       snprintf dup @ascuheap @acsmem | 
|  | 2036 | @c       open dup @acsfd [cancelpt] | 
|  | 2037 | @c       pread dup [cancelpt] | 
|  | 2038 | @c       yp_bind_client_create | 
|  | 2039 | @c       close dup @acsfd [cancelpt] | 
|  | 2040 | @c      yp_bind_ypbindprog | 
|  | 2041 | @c       clnttcp_create | 
|  | 2042 | @c       clnt_destroy | 
|  | 2043 | @c       clnt_call(xdr_domainname,xdr_ypbind_resp) | 
|  | 2044 | @c       memset dup ok | 
|  | 2045 | @c       yp_bind_client_create | 
|  | 2046 | @c      free dup @asulock @aculock @acsfd @acsmem | 
|  | 2047 | @c     calloc dup @asulock @aculock @acsfd @acsmem | 
|  | 2048 | @c     free dup @asulock @aculock @acsfd @acsmem | 
|  | 2049 | @c    ypprot_err | 
|  | 2050 | @c   memcpy dup ok | 
|  | 2051 | @c   xdr_free(xdr_ypresp_val) | 
|  | 2052 | @c    xdr_ypresp_val | 
|  | 2053 | @c     xdr_ypstat | 
|  | 2054 | @c      xdr_enum | 
|  | 2055 | @c       XDR_PUTLONG | 
|  | 2056 | @c        *x_putlong | 
|  | 2057 | @c       XDR_GETLONG | 
|  | 2058 | @c        *x_getlong | 
|  | 2059 | @c       xdr_long | 
|  | 2060 | @c        XDR_PUTLONG dup | 
|  | 2061 | @c        XDR_GETLONG dup | 
|  | 2062 | @c       xdr_short | 
|  | 2063 | @c        XDR_PUTLONG dup | 
|  | 2064 | @c        XDR_GETLONG dup | 
|  | 2065 | @c     xdr_valdat | 
|  | 2066 | @c      xdr_bytes | 
|  | 2067 | @c       xdr_u_int | 
|  | 2068 | @c        XDR_PUTLONG dup | 
|  | 2069 | @c        XDR_GETLONG dup | 
|  | 2070 | @c       mem_alloc @ascuheap @acsmem | 
|  | 2071 | @c        malloc dup @ascuheap @acsmem | 
|  | 2072 | @c       xdr_opaque | 
|  | 2073 | @c        XDR_GETBYTES | 
|  | 2074 | @c         *x_getbytes | 
|  | 2075 | @c        XDR_PUTBYTES | 
|  | 2076 | @c         *x_putbytes | 
|  | 2077 | @c       mem_free @ascuheap @acsmem | 
|  | 2078 | @c        free dup @ascuheap @acsmem | 
|  | 2079 | @c  yperr2nss ok | 
|  | 2080 | @c  strchr dup ok | 
|  | 2081 | @c  _nls_default_nss @asuinit @ascuheap @asulock @acucorrupt @acsmem @acsfd @aculock | 
|  | 2082 | @c   init @asuinit^, @ascuheap @asulock @acucorrupt @acsmem @acsfd @aculock | 
|  | 2083 | @c    fopen dup @ascuheap @asulock @acsmem @acsfd @aculock | 
|  | 2084 | @c    fsetlocking ok [no concurrent uses] | 
|  | 2085 | @c    feof_unlocked dup ok | 
|  | 2086 | @c    getline dup @ascuheap @aculock @acucorrupt @acsmem | 
|  | 2087 | @c    isspace dup @mtslocale^^ | 
|  | 2088 | @c    strncmp dup ok | 
|  | 2089 | @c    free dup @asulock @acsmem @acsfd @aculock | 
|  | 2090 | @c    fclose dup @ascuheap @asulock @aculock @acsmem @acsfd | 
|  | 2091 | @c  free dup @asulock @acsmem @acsfd @aculock | 
|  | 2092 | @c  mempcpy dup ok | 
|  | 2093 | @c  strncpy dup ok | 
|  | 2094 | @c  isspace dup @mtslocale^^ | 
|  | 2095 | @c  _nss_files_parse_pwent ok | 
|  | 2096 | This function is similar to @code{getpwuid} in that it returns | 
|  | 2097 | information about the user whose user ID is @var{uid}.  However, it | 
|  | 2098 | fills the user supplied structure pointed to by @var{result_buf} with | 
|  | 2099 | the information instead of using a static buffer.  The first | 
|  | 2100 | @var{buflen} bytes of the additional buffer pointed to by @var{buffer} | 
|  | 2101 | are used to contain additional information, normally strings which are | 
|  | 2102 | pointed to by the elements of the result structure. | 
|  | 2103 |  | 
|  | 2104 | If a user with ID @var{uid} is found, the pointer returned in | 
|  | 2105 | @var{result} points to the record which contains the wanted data (i.e., | 
|  | 2106 | @var{result} contains the value @var{result_buf}).  If no user is found | 
|  | 2107 | or if an error occurred, the pointer returned in @var{result} is a null | 
|  | 2108 | pointer.  The function returns zero or an error code.  If the buffer | 
|  | 2109 | @var{buffer} is too small to contain all the needed information, the | 
|  | 2110 | error code @code{ERANGE} is returned and @var{errno} is set to | 
|  | 2111 | @code{ERANGE}. | 
|  | 2112 | @end deftypefun | 
|  | 2113 |  | 
|  | 2114 |  | 
|  | 2115 | @comment pwd.h | 
|  | 2116 | @comment POSIX.1 | 
|  | 2117 | @deftypefun {struct passwd *} getpwnam (const char *@var{name}) | 
|  | 2118 | @safety{@prelim{}@mtunsafe{@mtasurace{:pwnam} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2119 | @c getpwnam @mtasurace:pwnam @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2120 | @c  libc_lock_lock dup @asulock @aculock | 
|  | 2121 | @c  malloc dup @ascuheap @acsmem | 
|  | 2122 | @c  getpwnam_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2123 | @c  realloc dup @ascuheap @acsmem | 
|  | 2124 | @c  free dup @ascuheap @acsmem | 
|  | 2125 | @c  libc_lock_unlock dup @aculock | 
|  | 2126 | This function returns a pointer to a statically-allocated structure | 
|  | 2127 | containing information about the user whose user name is @var{name}. | 
|  | 2128 | This structure may be overwritten on subsequent calls to | 
|  | 2129 | @code{getpwnam}. | 
|  | 2130 |  | 
|  | 2131 | A null pointer return indicates there is no user named @var{name}. | 
|  | 2132 | @end deftypefun | 
|  | 2133 |  | 
|  | 2134 | @comment pwd.h | 
|  | 2135 | @comment POSIX.1c | 
|  | 2136 | @deftypefun int getpwnam_r (const char *@var{name}, struct passwd *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct passwd **@var{result}) | 
|  | 2137 | @safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2138 | @c getpwnam_r @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2139 | @c  nscd_getpwnam_r @ascuheap @asulock @aculock @acsfd @acsmem | 
|  | 2140 | @c   strlen dup ok | 
|  | 2141 | @c   nscd_getpw_r dup @ascuheap @asulock @aculock @acsfd @acsmem | 
|  | 2142 | @c  nss_passwd_lookup2 dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2143 | @c  *fct.l @ascuplugin | 
|  | 2144 | @c  nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2145 | @c | 
|  | 2146 | @c _nss_files_getpwnam_r @mtslocale @ascuheap @asulock @aculock @acsmem @acsfd | 
|  | 2147 | @c  libc_lock_lock dup @asulock @aculock | 
|  | 2148 | @c  internal_setent dup @ascuheap @asulock @aculock @acsmem @acsfd | 
|  | 2149 | @c  internal_getent dup @mtslocale^ | 
|  | 2150 | @c  strcmp dup ok | 
|  | 2151 | @c  internal_endent dup @ascuheap @asulock @aculock @acsmem @acsfd | 
|  | 2152 | @c  libc_lock_unlock dup @aculock | 
|  | 2153 | @c | 
|  | 2154 | @c _nss_*_getpwnam_r (assumed) @asuinit @asulock @acucorrupt @aculock | 
|  | 2155 |  | 
|  | 2156 | This function is similar to @code{getpwnam} in that is returns | 
|  | 2157 | information about the user whose user name is @var{name}.  However, like | 
|  | 2158 | @code{getpwuid_r}, it fills the user supplied buffers in | 
|  | 2159 | @var{result_buf} and @var{buffer} with the information instead of using | 
|  | 2160 | a static buffer. | 
|  | 2161 |  | 
|  | 2162 | The return values are the same as for @code{getpwuid_r}. | 
|  | 2163 | @end deftypefun | 
|  | 2164 |  | 
|  | 2165 |  | 
|  | 2166 | @node Scanning All Users | 
|  | 2167 | @subsection Scanning the List of All Users | 
|  | 2168 | @cindex scanning the user list | 
|  | 2169 |  | 
|  | 2170 | This section explains how a program can read the list of all users in | 
|  | 2171 | the system, one user at a time.  The functions described here are | 
|  | 2172 | declared in @file{pwd.h}. | 
|  | 2173 |  | 
|  | 2174 | You can use the @code{fgetpwent} function to read user entries from a | 
|  | 2175 | particular file. | 
|  | 2176 |  | 
|  | 2177 | @comment pwd.h | 
|  | 2178 | @comment SVID | 
|  | 2179 | @deftypefun {struct passwd *} fgetpwent (FILE *@var{stream}) | 
|  | 2180 | @safety{@prelim{}@mtunsafe{@mtasurace{:fpwent}}@asunsafe{@asucorrupt{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{}}} | 
|  | 2181 | @c fgetpwent @mtasurace:fpwent @asucorrupt @asulock @acucorrupt @aculock | 
|  | 2182 | @c  fgetpos dup @asucorrupt @aculock @acucorrupt | 
|  | 2183 | @c  libc_lock_lock dup @asulock @aculock | 
|  | 2184 | @c  malloc dup @ascuheap @acsmem | 
|  | 2185 | @c  fgetpwent_r dup @asucorrupt @acucorrupt @aculock | 
|  | 2186 | @c  realloc dup @ascuheap @acsmem | 
|  | 2187 | @c  free dup @ascuheap @acsmem | 
|  | 2188 | @c  fsetpos dup @asucorrupt @aculock @acucorrupt | 
|  | 2189 | @c  libc_lock_unlock dup @aculock | 
|  | 2190 | This function reads the next user entry from @var{stream} and returns a | 
|  | 2191 | pointer to the entry.  The structure is statically allocated and is | 
|  | 2192 | rewritten on subsequent calls to @code{fgetpwent}.  You must copy the | 
|  | 2193 | contents of the structure if you wish to save the information. | 
|  | 2194 |  | 
|  | 2195 | The stream must correspond to a file in the same format as the standard | 
|  | 2196 | password database file. | 
|  | 2197 | @end deftypefun | 
|  | 2198 |  | 
|  | 2199 | @comment pwd.h | 
|  | 2200 | @comment GNU | 
|  | 2201 | @deftypefun int fgetpwent_r (FILE *@var{stream}, struct passwd *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct passwd **@var{result}) | 
|  | 2202 | @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} | 
|  | 2203 | @c fgetpwent_r @asucorrupt @acucorrupt @aculock | 
|  | 2204 | @c  flockfile dup @aculock | 
|  | 2205 | @c  fgets_unlocked @asucorrupt @acucorrupt [no @mtsrace due to explicit locking] | 
|  | 2206 | @c  feof_unlocked dup ok | 
|  | 2207 | @c  funlockfile dup @aculock | 
|  | 2208 | @c  isspace dup @mtslocale^^ | 
|  | 2209 | @c  parse_line dup ok | 
|  | 2210 | This function is similar to @code{fgetpwent} in that it reads the next | 
|  | 2211 | user entry from @var{stream}.  But the result is returned in the | 
|  | 2212 | structure pointed to by @var{result_buf}.  The | 
|  | 2213 | first @var{buflen} bytes of the additional buffer pointed to by | 
|  | 2214 | @var{buffer} are used to contain additional information, normally | 
|  | 2215 | strings which are pointed to by the elements of the result structure. | 
|  | 2216 |  | 
|  | 2217 | The stream must correspond to a file in the same format as the standard | 
|  | 2218 | password database file. | 
|  | 2219 |  | 
|  | 2220 | If the function returns zero @var{result} points to the structure with | 
|  | 2221 | the wanted data (normally this is in @var{result_buf}).  If errors | 
|  | 2222 | occurred the return value is nonzero and @var{result} contains a null | 
|  | 2223 | pointer. | 
|  | 2224 | @end deftypefun | 
|  | 2225 |  | 
|  | 2226 | The way to scan all the entries in the user database is with | 
|  | 2227 | @code{setpwent}, @code{getpwent}, and @code{endpwent}. | 
|  | 2228 |  | 
|  | 2229 | @comment pwd.h | 
|  | 2230 | @comment SVID, BSD | 
|  | 2231 | @deftypefun void setpwent (void) | 
|  | 2232 | @safety{@prelim{}@mtunsafe{@mtasurace{:pwent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2233 | @c setpwent @mtasurace:pwent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2234 | @c  libc_lock_lock @asulock @aculock | 
|  | 2235 | @c  nss_setent(nss_passwd_lookup2) @mtasurace:pwent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2236 | @c    ** resolv's res_maybe_init not called here | 
|  | 2237 | @c   setup(nss_passwd_lookup2) @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2238 | @c    *lookup_fct = nss_passwd_lookup2 dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2239 | @c    nss_lookup dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2240 | @c   *fct.f @mtasurace:pwent @ascuplugin | 
|  | 2241 | @c   nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2242 | @c  libc_lock_unlock @aculock | 
|  | 2243 | This function initializes a stream which @code{getpwent} and | 
|  | 2244 | @code{getpwent_r} use to read the user database. | 
|  | 2245 | @end deftypefun | 
|  | 2246 |  | 
|  | 2247 | @comment pwd.h | 
|  | 2248 | @comment POSIX.1 | 
|  | 2249 | @deftypefun {struct passwd *} getpwent (void) | 
|  | 2250 | @safety{@prelim{}@mtunsafe{@mtasurace{:pwent} @mtasurace{:pwentbuf} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2251 | @c getpwent @mtasurace:pwent @mtasurace:pwentbuf @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2252 | @c  libc_lock_lock dup @asulock @aculock | 
|  | 2253 | @c  nss_getent(getpwent_r) @mtasurace:pwent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2254 | @c   malloc dup @ascuheap @acsmem | 
|  | 2255 | @c   *func = getpwent_r dup @mtasurace:pwent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2256 | @c   realloc dup @ascuheap @acsmem | 
|  | 2257 | @c   free dup @ascuheap @acsmem | 
|  | 2258 | @c  libc_lock_unlock dup @aculock | 
|  | 2259 | The @code{getpwent} function reads the next entry from the stream | 
|  | 2260 | initialized by @code{setpwent}.  It returns a pointer to the entry.  The | 
|  | 2261 | structure is statically allocated and is rewritten on subsequent calls | 
|  | 2262 | to @code{getpwent}.  You must copy the contents of the structure if you | 
|  | 2263 | wish to save the information. | 
|  | 2264 |  | 
|  | 2265 | A null pointer is returned when no more entries are available. | 
|  | 2266 | @end deftypefun | 
|  | 2267 |  | 
|  | 2268 | @comment pwd.h | 
|  | 2269 | @comment GNU | 
|  | 2270 | @deftypefun int getpwent_r (struct passwd *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct passwd **@var{result}) | 
|  | 2271 | @safety{@prelim{}@mtunsafe{@mtasurace{:pwent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2272 | @c The static buffer here is not the result_buf, but rather the | 
|  | 2273 | @c variables that keep track of what nss backend we've last used, and | 
|  | 2274 | @c whatever internal state the nss backend uses to keep track of the | 
|  | 2275 | @c last read entry. | 
|  | 2276 | @c getpwent_r @mtasurace:pwent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2277 | @c  libc_lock_lock dup @asulock @aculock | 
|  | 2278 | @c  nss_getent_r(nss_passwd_lookup2) @mtasurace:pwent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2279 | @c   setup(nss_passwd_lookup2) dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2280 | @c   *fct.f @mtasurace:pwent @ascuplugin | 
|  | 2281 | @c   nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2282 | @c   nss_lookup dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2283 | @c   *sfct.f @mtasurace:pwent @ascuplugin | 
|  | 2284 | @c  libc_lock_unlock dup @aculock | 
|  | 2285 | This function is similar to @code{getpwent} in that it returns the next | 
|  | 2286 | entry from the stream initialized by @code{setpwent}.  Like | 
|  | 2287 | @code{fgetpwent_r}, it uses the user-supplied buffers in | 
|  | 2288 | @var{result_buf} and @var{buffer} to return the information requested. | 
|  | 2289 |  | 
|  | 2290 | The return values are the same as for @code{fgetpwent_r}. | 
|  | 2291 |  | 
|  | 2292 | @end deftypefun | 
|  | 2293 |  | 
|  | 2294 | @comment pwd.h | 
|  | 2295 | @comment SVID, BSD | 
|  | 2296 | @deftypefun void endpwent (void) | 
|  | 2297 | @safety{@prelim{}@mtunsafe{@mtasurace{:pwent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2298 | @c endpwent @mtasurace:pwent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2299 | @c  libc_lock_lock @asulock @aculock | 
|  | 2300 | @c  nss_endent(nss_passwd_lookup2) @mtasurace:pwent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2301 | @c    ** resolv's res_maybe_init not called here | 
|  | 2302 | @c   setup(nss_passwd_lookup2) dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2303 | @c   *fct.f @mtasurace:pwent @ascuplugin | 
|  | 2304 | @c   nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2305 | @c  libc_lock_unlock @aculock | 
|  | 2306 | This function closes the internal stream used by @code{getpwent} or | 
|  | 2307 | @code{getpwent_r}. | 
|  | 2308 | @end deftypefun | 
|  | 2309 |  | 
|  | 2310 | @node Writing a User Entry | 
|  | 2311 | @subsection Writing a User Entry | 
|  | 2312 |  | 
|  | 2313 | @comment pwd.h | 
|  | 2314 | @comment SVID | 
|  | 2315 | @deftypefun int putpwent (const struct passwd *@var{p}, FILE *@var{stream}) | 
|  | 2316 | @safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} | 
|  | 2317 | @c putpwent @mtslocale @asucorrupt @aculock @acucorrupt | 
|  | 2318 | @c  fprintf dup @mtslocale @asucorrupt @aculock @acucorrupt [no @ascuheap @acsmem] | 
|  | 2319 | This function writes the user entry @code{*@var{p}} to the stream | 
|  | 2320 | @var{stream}, in the format used for the standard user database | 
|  | 2321 | file.  The return value is zero on success and nonzero on failure. | 
|  | 2322 |  | 
|  | 2323 | This function exists for compatibility with SVID.  We recommend that you | 
|  | 2324 | avoid using it, because it makes sense only on the assumption that the | 
|  | 2325 | @code{struct passwd} structure has no members except the standard ones; | 
|  | 2326 | on a system which merges the traditional Unix data base with other | 
|  | 2327 | extended information about users, adding an entry using this function | 
|  | 2328 | would inevitably leave out much of the important information. | 
|  | 2329 | @c Then how are programmers to modify the password file? -zw | 
|  | 2330 |  | 
|  | 2331 | The group and user ID fields are left empty if the group or user name | 
|  | 2332 | starts with a - or +. | 
|  | 2333 |  | 
|  | 2334 | The function @code{putpwent} is declared in @file{pwd.h}. | 
|  | 2335 | @end deftypefun | 
|  | 2336 |  | 
|  | 2337 | @node Group Database | 
|  | 2338 | @section Group Database | 
|  | 2339 | @cindex group database | 
|  | 2340 | @pindex /etc/group | 
|  | 2341 |  | 
|  | 2342 | This section describes how to search and scan the database of | 
|  | 2343 | registered groups.  The database itself is kept in the file | 
|  | 2344 | @file{/etc/group} on most systems, but on some systems a special network | 
|  | 2345 | service provides access to it. | 
|  | 2346 |  | 
|  | 2347 | @menu | 
|  | 2348 | * Group Data Structure::        What each group record contains. | 
|  | 2349 | * Lookup Group::                How to look for a particular group. | 
|  | 2350 | * Scanning All Groups::         Scanning the list of all groups. | 
|  | 2351 | @end menu | 
|  | 2352 |  | 
|  | 2353 | @node Group Data Structure | 
|  | 2354 | @subsection The Data Structure for a Group | 
|  | 2355 |  | 
|  | 2356 | The functions and data structures for accessing the system group | 
|  | 2357 | database are declared in the header file @file{grp.h}. | 
|  | 2358 | @pindex grp.h | 
|  | 2359 |  | 
|  | 2360 | @comment grp.h | 
|  | 2361 | @comment POSIX.1 | 
|  | 2362 | @deftp {Data Type} {struct group} | 
|  | 2363 | The @code{group} structure is used to hold information about an entry in | 
|  | 2364 | the system group database.  It has at least the following members: | 
|  | 2365 |  | 
|  | 2366 | @table @code | 
|  | 2367 | @item char *gr_name | 
|  | 2368 | The name of the group. | 
|  | 2369 |  | 
|  | 2370 | @item gid_t gr_gid | 
|  | 2371 | The group ID of the group. | 
|  | 2372 |  | 
|  | 2373 | @item char **gr_mem | 
|  | 2374 | A vector of pointers to the names of users in the group.  Each user name | 
|  | 2375 | is a null-terminated string, and the vector itself is terminated by a | 
|  | 2376 | null pointer. | 
|  | 2377 | @end table | 
|  | 2378 | @end deftp | 
|  | 2379 |  | 
|  | 2380 | @node Lookup Group | 
|  | 2381 | @subsection Looking Up One Group | 
|  | 2382 | @cindex converting group name to group ID | 
|  | 2383 | @cindex converting group ID to group name | 
|  | 2384 |  | 
|  | 2385 | You can search the group database for information about a specific | 
|  | 2386 | group using @code{getgrgid} or @code{getgrnam}.  These functions are | 
|  | 2387 | declared in @file{grp.h}. | 
|  | 2388 |  | 
|  | 2389 | @comment grp.h | 
|  | 2390 | @comment POSIX.1 | 
|  | 2391 | @deftypefun {struct group *} getgrgid (gid_t @var{gid}) | 
|  | 2392 | @safety{@prelim{}@mtunsafe{@mtasurace{:grgid} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2393 | @c getgrgid =~ getpwuid dup @mtasurace:grgid @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2394 | @c  getgrgid_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2395 | This function returns a pointer to a statically-allocated structure | 
|  | 2396 | containing information about the group whose group ID is @var{gid}. | 
|  | 2397 | This structure may be overwritten by subsequent calls to | 
|  | 2398 | @code{getgrgid}. | 
|  | 2399 |  | 
|  | 2400 | A null pointer indicates there is no group with ID @var{gid}. | 
|  | 2401 | @end deftypefun | 
|  | 2402 |  | 
|  | 2403 | @comment grp.h | 
|  | 2404 | @comment POSIX.1c | 
|  | 2405 | @deftypefun int getgrgid_r (gid_t @var{gid}, struct group *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct group **@var{result}) | 
|  | 2406 | @safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2407 | @c getgrgid_r =~ getpwuid_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2408 | @c  nscd_getgrgid_r @ascuheap @acsfd @acsmem | 
|  | 2409 | @c   itoa_word dup ok | 
|  | 2410 | @c   nscd_getgr_r @ascuheap @acsfd @acsmem | 
|  | 2411 | @c    nscd_get_map_ref dup @ascuheap @acsfd @acsmem | 
|  | 2412 | @c    nscd_cache_search dup ok | 
|  | 2413 | @c    nscd_open_socket dup @acsfd | 
|  | 2414 | @c    readvall ok | 
|  | 2415 | @c     readv dup ok | 
|  | 2416 | @c     memcpy dup ok | 
|  | 2417 | @c      wait_on_socket dup ok | 
|  | 2418 | @c    memcpy dup ok | 
|  | 2419 | @c    readall dup ok | 
|  | 2420 | @c    close_not_cancel_no_status dup @acsfd | 
|  | 2421 | @c    nscd_drop_map_ref dup @ascuheap @acsmem | 
|  | 2422 | @c    nscd_unmap dup @ascuheap @acsmem | 
|  | 2423 | @c  nss_group_lookup2 =~ nss_passwd_lookup2 dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2424 | @c  *fct.l -> _nss_*_getgrgid_r @ascuplugin | 
|  | 2425 | @c  nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2426 | This function is similar to @code{getgrgid} in that it returns | 
|  | 2427 | information about the group whose group ID is @var{gid}.  However, it | 
|  | 2428 | fills the user supplied structure pointed to by @var{result_buf} with | 
|  | 2429 | the information instead of using a static buffer.  The first | 
|  | 2430 | @var{buflen} bytes of the additional buffer pointed to by @var{buffer} | 
|  | 2431 | are used to contain additional information, normally strings which are | 
|  | 2432 | pointed to by the elements of the result structure. | 
|  | 2433 |  | 
|  | 2434 | If a group with ID @var{gid} is found, the pointer returned in | 
|  | 2435 | @var{result} points to the record which contains the wanted data (i.e., | 
|  | 2436 | @var{result} contains the value @var{result_buf}).  If no group is found | 
|  | 2437 | or if an error occurred, the pointer returned in @var{result} is a null | 
|  | 2438 | pointer.  The function returns zero or an error code.  If the buffer | 
|  | 2439 | @var{buffer} is too small to contain all the needed information, the | 
|  | 2440 | error code @code{ERANGE} is returned and @var{errno} is set to | 
|  | 2441 | @code{ERANGE}. | 
|  | 2442 | @end deftypefun | 
|  | 2443 |  | 
|  | 2444 | @comment grp.h | 
|  | 2445 | @comment SVID, BSD | 
|  | 2446 | @deftypefun {struct group *} getgrnam (const char *@var{name}) | 
|  | 2447 | @safety{@prelim{}@mtunsafe{@mtasurace{:grnam} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2448 | @c getgrnam =~ getpwnam dup @mtasurace:grnam @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2449 | @c  getgrnam_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2450 | This function returns a pointer to a statically-allocated structure | 
|  | 2451 | containing information about the group whose group name is @var{name}. | 
|  | 2452 | This structure may be overwritten by subsequent calls to | 
|  | 2453 | @code{getgrnam}. | 
|  | 2454 |  | 
|  | 2455 | A null pointer indicates there is no group named @var{name}. | 
|  | 2456 | @end deftypefun | 
|  | 2457 |  | 
|  | 2458 | @comment grp.h | 
|  | 2459 | @comment POSIX.1c | 
|  | 2460 | @deftypefun int getgrnam_r (const char *@var{name}, struct group *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct group **@var{result}) | 
|  | 2461 | @safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2462 | @c getgrnam_r =~ getpwnam_r dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2463 | @c  nscd_getgrnam_r @ascuheap @asulock @aculock @acsfd @acsmem | 
|  | 2464 | @c   strlen dup ok | 
|  | 2465 | @c   nscd_getgr_r dup @ascuheap @asulock @aculock @acsfd @acsmem | 
|  | 2466 | @c  nss_group_lookup2 dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2467 | @c  *fct.l @ascuplugin | 
|  | 2468 | @c  nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2469 | This function is similar to @code{getgrnam} in that is returns | 
|  | 2470 | information about the group whose group name is @var{name}.  Like | 
|  | 2471 | @code{getgrgid_r}, it uses the user supplied buffers in | 
|  | 2472 | @var{result_buf} and @var{buffer}, not a static buffer. | 
|  | 2473 |  | 
|  | 2474 | The return values are the same as for @code{getgrgid_r} | 
|  | 2475 | @code{ERANGE}. | 
|  | 2476 | @end deftypefun | 
|  | 2477 |  | 
|  | 2478 | @node Scanning All Groups | 
|  | 2479 | @subsection Scanning the List of All Groups | 
|  | 2480 | @cindex scanning the group list | 
|  | 2481 |  | 
|  | 2482 | This section explains how a program can read the list of all groups in | 
|  | 2483 | the system, one group at a time.  The functions described here are | 
|  | 2484 | declared in @file{grp.h}. | 
|  | 2485 |  | 
|  | 2486 | You can use the @code{fgetgrent} function to read group entries from a | 
|  | 2487 | particular file. | 
|  | 2488 |  | 
|  | 2489 | @comment grp.h | 
|  | 2490 | @comment SVID | 
|  | 2491 | @deftypefun {struct group *} fgetgrent (FILE *@var{stream}) | 
|  | 2492 | @safety{@prelim{}@mtunsafe{@mtasurace{:fgrent}}@asunsafe{@asucorrupt{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{}}} | 
|  | 2493 | @c fgetgrent @mtasurace:fgrent @asucorrupt @asulock @acucorrupt @aculock | 
|  | 2494 | @c  fgetpos dup @asucorrupt @aculock @acucorrupt | 
|  | 2495 | @c  libc_lock_lock dup @asulock @aculock | 
|  | 2496 | @c  malloc dup @ascuheap @acsmem | 
|  | 2497 | @c  fgetgrent_r dup @asucorrupt @acucorrupt @aculock | 
|  | 2498 | @c  realloc dup @ascuheap @acsmem | 
|  | 2499 | @c  free dup @ascuheap @acsmem | 
|  | 2500 | @c  fsetpos dup @asucorrupt @aculock @acucorrupt | 
|  | 2501 | @c  libc_lock_unlock dup @aculock | 
|  | 2502 | The @code{fgetgrent} function reads the next entry from @var{stream}. | 
|  | 2503 | It returns a pointer to the entry.  The structure is statically | 
|  | 2504 | allocated and is overwritten on subsequent calls to @code{fgetgrent}.  You | 
|  | 2505 | must copy the contents of the structure if you wish to save the | 
|  | 2506 | information. | 
|  | 2507 |  | 
|  | 2508 | The stream must correspond to a file in the same format as the standard | 
|  | 2509 | group database file. | 
|  | 2510 | @end deftypefun | 
|  | 2511 |  | 
|  | 2512 | @comment grp.h | 
|  | 2513 | @comment GNU | 
|  | 2514 | @deftypefun int fgetgrent_r (FILE *@var{stream}, struct group *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct group **@var{result}) | 
|  | 2515 | @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} | 
|  | 2516 | @c fgetgrent_r @asucorrupt @acucorrupt @aculock | 
|  | 2517 | @c  flockfile dup @aculock | 
|  | 2518 | @c  fgets_unlocked @asucorrupt @acucorrupt [no @mtsrace due to explicit locking] | 
|  | 2519 | @c  feof_unlocked dup ok | 
|  | 2520 | @c  funlockfile dup @aculock | 
|  | 2521 | @c  isspace dup @mtslocale^^ | 
|  | 2522 | @c  parse_line dup ok | 
|  | 2523 | This function is similar to @code{fgetgrent} in that it reads the next | 
|  | 2524 | user entry from @var{stream}.  But the result is returned in the | 
|  | 2525 | structure pointed to by @var{result_buf}.  The first @var{buflen} bytes | 
|  | 2526 | of the additional buffer pointed to by @var{buffer} are used to contain | 
|  | 2527 | additional information, normally strings which are pointed to by the | 
|  | 2528 | elements of the result structure. | 
|  | 2529 |  | 
|  | 2530 | This stream must correspond to a file in the same format as the standard | 
|  | 2531 | group database file. | 
|  | 2532 |  | 
|  | 2533 | If the function returns zero @var{result} points to the structure with | 
|  | 2534 | the wanted data (normally this is in @var{result_buf}).  If errors | 
|  | 2535 | occurred the return value is non-zero and @var{result} contains a null | 
|  | 2536 | pointer. | 
|  | 2537 | @end deftypefun | 
|  | 2538 |  | 
|  | 2539 | The way to scan all the entries in the group database is with | 
|  | 2540 | @code{setgrent}, @code{getgrent}, and @code{endgrent}. | 
|  | 2541 |  | 
|  | 2542 | @comment grp.h | 
|  | 2543 | @comment SVID, BSD | 
|  | 2544 | @deftypefun void setgrent (void) | 
|  | 2545 | @safety{@prelim{}@mtunsafe{@mtasurace{:grent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2546 | @c setgrent =~ setpwent dup @mtasurace:grent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2547 | @c ...*lookup_fct = nss_group_lookup2 dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2548 | This function initializes a stream for reading from the group data base. | 
|  | 2549 | You use this stream by calling @code{getgrent} or @code{getgrent_r}. | 
|  | 2550 | @end deftypefun | 
|  | 2551 |  | 
|  | 2552 | @comment grp.h | 
|  | 2553 | @comment SVID, BSD | 
|  | 2554 | @deftypefun {struct group *} getgrent (void) | 
|  | 2555 | @safety{@prelim{}@mtunsafe{@mtasurace{:grent} @mtasurace{:grentbuf} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2556 | @c getgrent =~ getpwent dup @mtasurace:grent @mtasurace:grentbuf @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2557 | @c   *func = getgrent_r dup @mtasurace:grent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2558 | The @code{getgrent} function reads the next entry from the stream | 
|  | 2559 | initialized by @code{setgrent}.  It returns a pointer to the entry.  The | 
|  | 2560 | structure is statically allocated and is overwritten on subsequent calls | 
|  | 2561 | to @code{getgrent}.  You must copy the contents of the structure if you | 
|  | 2562 | wish to save the information. | 
|  | 2563 | @end deftypefun | 
|  | 2564 |  | 
|  | 2565 | @comment grp.h | 
|  | 2566 | @comment GNU | 
|  | 2567 | @deftypefun int getgrent_r (struct group *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct group **@var{result}) | 
|  | 2568 | @safety{@prelim{}@mtunsafe{@mtasurace{:grent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2569 | @c getgrent_r =~ getpwent_r dup @mtasurace:grent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2570 | This function is similar to @code{getgrent} in that it returns the next | 
|  | 2571 | entry from the stream initialized by @code{setgrent}.  Like | 
|  | 2572 | @code{fgetgrent_r}, it places the result in user-supplied buffers | 
|  | 2573 | pointed to @var{result_buf} and @var{buffer}. | 
|  | 2574 |  | 
|  | 2575 | If the function returns zero @var{result} contains a pointer to the data | 
|  | 2576 | (normally equal to @var{result_buf}).  If errors occurred the return | 
|  | 2577 | value is non-zero and @var{result} contains a null pointer. | 
|  | 2578 | @end deftypefun | 
|  | 2579 |  | 
|  | 2580 | @comment grp.h | 
|  | 2581 | @comment SVID, BSD | 
|  | 2582 | @deftypefun void endgrent (void) | 
|  | 2583 | @safety{@prelim{}@mtunsafe{@mtasurace{:grent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2584 | @c endgrent =~ endpwent dup @mtasurace:grent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2585 | This function closes the internal stream used by @code{getgrent} or | 
|  | 2586 | @code{getgrent_r}. | 
|  | 2587 | @end deftypefun | 
|  | 2588 |  | 
|  | 2589 | @node Database Example | 
|  | 2590 | @section User and Group Database Example | 
|  | 2591 |  | 
|  | 2592 | Here is an example program showing the use of the system database inquiry | 
|  | 2593 | functions.  The program prints some information about the user running | 
|  | 2594 | the program. | 
|  | 2595 |  | 
|  | 2596 | @smallexample | 
|  | 2597 | @include db.c.texi | 
|  | 2598 | @end smallexample | 
|  | 2599 |  | 
|  | 2600 | Here is some output from this program: | 
|  | 2601 |  | 
|  | 2602 | @smallexample | 
|  | 2603 | I am Throckmorton Snurd. | 
|  | 2604 | My login name is snurd. | 
|  | 2605 | My uid is 31093. | 
|  | 2606 | My home directory is /home/fsg/snurd. | 
|  | 2607 | My default shell is /bin/sh. | 
|  | 2608 | My default group is guest (12). | 
|  | 2609 | The members of this group are: | 
|  | 2610 | friedman | 
|  | 2611 | tami | 
|  | 2612 | @end smallexample | 
|  | 2613 |  | 
|  | 2614 | @node Netgroup Database | 
|  | 2615 | @section Netgroup Database | 
|  | 2616 |  | 
|  | 2617 | @menu | 
|  | 2618 | * Netgroup Data::                  Data in the Netgroup database and where | 
|  | 2619 | it comes from. | 
|  | 2620 | * Lookup Netgroup::                How to look for a particular netgroup. | 
|  | 2621 | * Netgroup Membership::            How to test for netgroup membership. | 
|  | 2622 | @end menu | 
|  | 2623 |  | 
|  | 2624 | @node Netgroup Data | 
|  | 2625 | @subsection Netgroup Data | 
|  | 2626 |  | 
|  | 2627 | @cindex Netgroup | 
|  | 2628 | Sometimes it is useful to group users according to other criteria | 
|  | 2629 | (@pxref{Group Database}).  E.g., it is useful to associate a certain | 
|  | 2630 | group of users with a certain machine.  On the other hand grouping of | 
|  | 2631 | host names is not supported so far. | 
|  | 2632 |  | 
|  | 2633 | In Sun Microsystems SunOS appeared a new kind of database, the netgroup | 
|  | 2634 | database.  It allows grouping hosts, users, and domains freely, giving | 
|  | 2635 | them individual names.  To be more concrete, a netgroup is a list of triples | 
|  | 2636 | consisting of a host name, a user name, and a domain name where any of | 
|  | 2637 | the entries can be a wildcard entry matching all inputs.  A last | 
|  | 2638 | possibility is that names of other netgroups can also be given in the | 
|  | 2639 | list specifying a netgroup.  So one can construct arbitrary hierarchies | 
|  | 2640 | without loops. | 
|  | 2641 |  | 
|  | 2642 | Sun's implementation allows netgroups only for the @code{nis} or | 
|  | 2643 | @code{nisplus} service, @pxref{Services in the NSS configuration}.  The | 
|  | 2644 | implementation in @theglibc{} has no such restriction.  An entry | 
|  | 2645 | in either of the input services must have the following form: | 
|  | 2646 |  | 
|  | 2647 | @smallexample | 
|  | 2648 | @var{groupname} ( @var{groupname} | @code{(}@var{hostname}@code{,}@var{username}@code{,}@code{domainname}@code{)} )+ | 
|  | 2649 | @end smallexample | 
|  | 2650 |  | 
|  | 2651 | Any of the fields in the triple can be empty which means anything | 
|  | 2652 | matches.  While describing the functions we will see that the opposite | 
|  | 2653 | case is useful as well.  I.e., there may be entries which will not | 
|  | 2654 | match any input.  For entries like this, a name consisting of the single | 
|  | 2655 | character @code{-} shall be used. | 
|  | 2656 |  | 
|  | 2657 | @node Lookup Netgroup | 
|  | 2658 | @subsection Looking up one Netgroup | 
|  | 2659 |  | 
|  | 2660 | The lookup functions for netgroups are a bit different to all other | 
|  | 2661 | system database handling functions.  Since a single netgroup can contain | 
|  | 2662 | many entries a two-step process is needed.  First a single netgroup is | 
|  | 2663 | selected and then one can iterate over all entries in this netgroup. | 
|  | 2664 | These functions are declared in @file{netdb.h}. | 
|  | 2665 |  | 
|  | 2666 | @comment netdb.h | 
|  | 2667 | @comment BSD | 
|  | 2668 | @deftypefun int setnetgrent (const char *@var{netgroup}) | 
|  | 2669 | @safety{@prelim{}@mtunsafe{@mtasurace{:netgrent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2670 | @c setnetgrent @mtasurace:netgrent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2671 | @c  libc_lock_lock dup @asulock @aculock | 
|  | 2672 | @c  nscd_setnetgrent @ascuheap @acsfd @acsmem | 
|  | 2673 | @c   __nscd_setnetgrent @ascuheap @acsfd @acsmem | 
|  | 2674 | @c    strlen dup ok | 
|  | 2675 | @c    nscd_get_map_ref dup @ascuheap @acsfd @acsmem | 
|  | 2676 | @c    nscd_cache_search dup ok | 
|  | 2677 | @c    nscd_open_socket dup @acsfd | 
|  | 2678 | @c    malloc dup @ascuheap @acsmem | 
|  | 2679 | @c    readall dup ok | 
|  | 2680 | @c    free dup @ascuheap @acsmem | 
|  | 2681 | @c    close_not_cancel_no_status dup @acsfd | 
|  | 2682 | @c    nscd_drop_map_ref dup @ascuheap @acsmem | 
|  | 2683 | @c    nscd_unmap dup @ascuheap @acsmem | 
|  | 2684 | @c  internal_setnetgrent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2685 | @c   free_memory dup @ascuheap @acsmem | 
|  | 2686 | @c    free dup @ascuheap @acsmem | 
|  | 2687 | @c   internal_setnetgrent_reuse @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2688 | @c    endnetgrent_hook dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2689 | @c     nss_lookup_function dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2690 | @c     *endfct @ascuplugin | 
|  | 2691 | @c    (netgroup::)setup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2692 | @c     nss_netgroup_lookup dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2693 | @c      nss_netgroup_lookup2 =~ nss_passwd_lookup2 dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2694 | @c     nss_lookup dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2695 | @c    *fct.f @ascuplugin | 
|  | 2696 | @c    nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2697 | @c    nss_lookup_function dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2698 | @c    *endfct @ascuplugin | 
|  | 2699 | @c    strlen dup ok | 
|  | 2700 | @c    malloc dup @ascuheap @acsmem | 
|  | 2701 | @c    memcpy dup ok | 
|  | 2702 | @c  libc_lock_unlock dup @aculock | 
|  | 2703 | A call to this function initializes the internal state of the library to | 
|  | 2704 | allow following calls of the @code{getnetgrent} to iterate over all entries | 
|  | 2705 | in the netgroup with name @var{netgroup}. | 
|  | 2706 |  | 
|  | 2707 | When the call is successful (i.e., when a netgroup with this name exists) | 
|  | 2708 | the return value is @code{1}.  When the return value is @code{0} no | 
|  | 2709 | netgroup of this name is known or some other error occurred. | 
|  | 2710 | @end deftypefun | 
|  | 2711 |  | 
|  | 2712 | It is important to remember that there is only one single state for | 
|  | 2713 | iterating the netgroups.  Even if the programmer uses the | 
|  | 2714 | @code{getnetgrent_r} function the result is not really reentrant since | 
|  | 2715 | always only one single netgroup at a time can be processed.  If the | 
|  | 2716 | program needs to process more than one netgroup simultaneously she | 
|  | 2717 | must protect this by using external locking.  This problem was | 
|  | 2718 | introduced in the original netgroups implementation in SunOS and since | 
|  | 2719 | we must stay compatible it is not possible to change this. | 
|  | 2720 |  | 
|  | 2721 | Some other functions also use the netgroups state.  Currently these are | 
|  | 2722 | the @code{innetgr} function and parts of the implementation of the | 
|  | 2723 | @code{compat} service part of the NSS implementation. | 
|  | 2724 |  | 
|  | 2725 | @comment netdb.h | 
|  | 2726 | @comment BSD | 
|  | 2727 | @deftypefun int getnetgrent (char **@var{hostp}, char **@var{userp}, char **@var{domainp}) | 
|  | 2728 | @safety{@prelim{}@mtunsafe{@mtasurace{:netgrent} @mtasurace{:netgrentbuf} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2729 | @c getnetgrent @mtasurace:netgrent @mtasurace:netgrentbuf @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2730 | @c   uses unsafely a static buffer allocated within a libc_once call | 
|  | 2731 | @c  allocate (libc_once) @ascuheap @acsmem | 
|  | 2732 | @c   malloc dup @ascuheap @acsmem | 
|  | 2733 | @c  getnetgrent_r dup @mtasurace:netgrent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2734 | This function returns the next unprocessed entry of the currently | 
|  | 2735 | selected netgroup.  The string pointers, in which addresses are passed in | 
|  | 2736 | the arguments @var{hostp}, @var{userp}, and @var{domainp}, will contain | 
|  | 2737 | after a successful call pointers to appropriate strings.  If the string | 
|  | 2738 | in the next entry is empty the pointer has the value @code{NULL}. | 
|  | 2739 | The returned string pointers are only valid if none of the netgroup | 
|  | 2740 | related functions are called. | 
|  | 2741 |  | 
|  | 2742 | The return value is @code{1} if the next entry was successfully read.  A | 
|  | 2743 | value of @code{0} means no further entries exist or internal errors occurred. | 
|  | 2744 | @end deftypefun | 
|  | 2745 |  | 
|  | 2746 | @comment netdb.h | 
|  | 2747 | @comment GNU | 
|  | 2748 | @deftypefun int getnetgrent_r (char **@var{hostp}, char **@var{userp}, char **@var{domainp}, char *@var{buffer}, size_t @var{buflen}) | 
|  | 2749 | @safety{@prelim{}@mtunsafe{@mtasurace{:netgrent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2750 | @c getnetgrent_r @mtasurace:netgrent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2751 | @c  libc_lock_lock dup @asulock @aculock | 
|  | 2752 | @c  internal_getnetgrent_r @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2753 | @c   nss_lookup_function dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2754 | @c   *fct @ascuplugin | 
|  | 2755 | @c   nscd_getnetgrent ok | 
|  | 2756 | @c    rawmemchr dup ok | 
|  | 2757 | @c   internal_setnetgrent_reuse dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2758 | @c   strcmp dup ok | 
|  | 2759 | @c   malloc dup @ascuheap @acsmem | 
|  | 2760 | @c   memcpy dup ok | 
|  | 2761 | @c  libc_lock_unlock dup @aculock | 
|  | 2762 | This function is similar to @code{getnetgrent} with only one exception: | 
|  | 2763 | the strings the three string pointers @var{hostp}, @var{userp}, and | 
|  | 2764 | @var{domainp} point to, are placed in the buffer of @var{buflen} bytes | 
|  | 2765 | starting at @var{buffer}.  This means the returned values are valid | 
|  | 2766 | even after other netgroup related functions are called. | 
|  | 2767 |  | 
|  | 2768 | The return value is @code{1} if the next entry was successfully read and | 
|  | 2769 | the buffer contains enough room to place the strings in it.  @code{0} is | 
|  | 2770 | returned in case no more entries are found, the buffer is too small, or | 
|  | 2771 | internal errors occurred. | 
|  | 2772 |  | 
|  | 2773 | This function is a GNU extension.  The original implementation in the | 
|  | 2774 | SunOS libc does not provide this function. | 
|  | 2775 | @end deftypefun | 
|  | 2776 |  | 
|  | 2777 | @comment netdb.h | 
|  | 2778 | @comment BSD | 
|  | 2779 | @deftypefun void endnetgrent (void) | 
|  | 2780 | @safety{@prelim{}@mtunsafe{@mtasurace{:netgrent}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2781 | @c endnetgrent @mtasurace:netgrent @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2782 | @c  libc_lock_lock dup @asulock @aculock | 
|  | 2783 | @c  internal_endnetgrent @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2784 | @c   endnetgrent_hook dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2785 | @c   free_memory dup @ascuheap @acsmem | 
|  | 2786 | @c  libc_lock_unlock dup @aculock | 
|  | 2787 | This function frees all buffers which were allocated to process the last | 
|  | 2788 | selected netgroup.  As a result all string pointers returned by calls | 
|  | 2789 | to @code{getnetgrent} are invalid afterwards. | 
|  | 2790 | @end deftypefun | 
|  | 2791 |  | 
|  | 2792 | @node Netgroup Membership | 
|  | 2793 | @subsection Testing for Netgroup Membership | 
|  | 2794 |  | 
|  | 2795 | It is often not necessary to scan the whole netgroup since often the | 
|  | 2796 | only interesting question is whether a given entry is part of the | 
|  | 2797 | selected netgroup. | 
|  | 2798 |  | 
|  | 2799 | @comment netdb.h | 
|  | 2800 | @comment BSD | 
|  | 2801 | @deftypefun int innetgr (const char *@var{netgroup}, const char *@var{host}, const char *@var{user}, const char *@var{domain}) | 
|  | 2802 | @safety{@prelim{}@mtunsafe{@mtasurace{:netgrent} @mtslocale{}}@asunsafe{@ascudlopen{} @ascuplugin{} @ascuheap{} @asulock{}}@acunsafe{@acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} | 
|  | 2803 | @c This function does not use the static data structure that the | 
|  | 2804 | @c *netgrent* ones do, but since each nss must maintains internal state | 
|  | 2805 | @c to support iteration and concurrent iteration will interfere | 
|  | 2806 | @c destructively, we regard this internal state as a static buffer. | 
|  | 2807 | @c getnetgrent_r iteration in each nss backend. | 
|  | 2808 | @c innetgr @mtasurace:netgrent @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2809 | @c  nscd_innetgr @ascuheap @acsfd @acsmem | 
|  | 2810 | @c   strlen dup ok | 
|  | 2811 | @c   malloc dup @ascuheap @acsmem | 
|  | 2812 | @c   stpcpy dup ok | 
|  | 2813 | @c   nscd_get_map_ref dup @ascuheap @acsfd @acsmem | 
|  | 2814 | @c   nscd_cache_search dup ok | 
|  | 2815 | @c   nscd_open_socket dup @acsfd | 
|  | 2816 | @c   close_not_cancel_no_status dup @acsfd | 
|  | 2817 | @c   nscd_drop_map_ref dup @ascuheap @acsmem | 
|  | 2818 | @c   nscd_unmap dup @ascuheap @acsmem | 
|  | 2819 | @c   free dup @ascuheap @acsmem | 
|  | 2820 | @c  memset dup ok | 
|  | 2821 | @c  (netgroup::)setup dup @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2822 | @c  *setfct.f @ascuplugin | 
|  | 2823 | @c  nss_lookup_function dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2824 | @c  *getfct @ascuplugin | 
|  | 2825 | @c  strcmp dup ok | 
|  | 2826 | @c  strlen dup ok | 
|  | 2827 | @c  malloc dup @ascuheap @acsmem | 
|  | 2828 | @c  memcpy dup ok | 
|  | 2829 | @c  strcasecmp dup | 
|  | 2830 | @c  *endfct @ascuplugin | 
|  | 2831 | @c  nss_next2 dup @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem | 
|  | 2832 | @c  free_memory dup @ascuheap @acsmem | 
|  | 2833 | This function tests whether the triple specified by the parameters | 
|  | 2834 | @var{hostp}, @var{userp}, and @var{domainp} is part of the netgroup | 
|  | 2835 | @var{netgroup}.  Using this function has the advantage that | 
|  | 2836 |  | 
|  | 2837 | @enumerate | 
|  | 2838 | @item | 
|  | 2839 | no other netgroup function can use the global netgroup state since | 
|  | 2840 | internal locking is used and | 
|  | 2841 | @item | 
|  | 2842 | the function is implemented more efficiently than successive calls | 
|  | 2843 | to the other @code{set}/@code{get}/@code{endnetgrent} functions. | 
|  | 2844 | @end enumerate | 
|  | 2845 |  | 
|  | 2846 | Any of the pointers @var{hostp}, @var{userp}, and @var{domainp} can be | 
|  | 2847 | @code{NULL} which means any value is accepted in this position.  This is | 
|  | 2848 | also true for the name @code{-} which should not match any other string | 
|  | 2849 | otherwise. | 
|  | 2850 |  | 
|  | 2851 | The return value is @code{1} if an entry matching the given triple is | 
|  | 2852 | found in the netgroup.  The return value is @code{0} if the netgroup | 
|  | 2853 | itself is not found, the netgroup does not contain the triple or | 
|  | 2854 | internal errors occurred. | 
|  | 2855 | @end deftypefun | 
|  | 2856 |  | 
|  | 2857 | @c FIXME these are undocumented: | 
|  | 2858 | @c setresgid | 
|  | 2859 | @c setresuid |