mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-22 13:00:06 +00:00
0413b54c02
1997-08-10 18:48 Ulrich Drepper <drepper@cygnus.com> * Makeconfig: Define build-programs to no if not set and $(config-os) is none. * Makerules (+depfiles): Don't add $(others) if not build-programs. * Rules (others): Don't depend on $(install-bin), $(install-rootbin) and $(install-sbin) if not build-programs. * Makefile (subdirs): Remove login. * sysdeps/mach/hurd/Subdirs: Add login. * sysdeps/unix/Subdirs: Add login. * sysdeps/generic/sys/mman.h: Test feature macros before defining non-POSIX things. Add MAP_FAILED. * sysdeps/unix/bsd/osf/sys/mman.h: Likewise. * sysdeps/unix/bsd/sun/sunos4/sys/mman.h: Likewise. * sysdeps/unix/bsd/ultrix4/sys/mman.h: Likewise. * sysdeps/unix/sysv/irix4/sys/mman.h: Likewise. * sysdeps/unix/sysv/linux/sys/mman.h: Rewrite to not use kernel header but bits/mman.h. Test feature macros before definitions non-POSIX functions. * sysdeps/unix/sysv/linux/alpha/bits/mman.h: New file. * sysdeps/unix/sysv/linux/i386/bits/mman.h: New file. * sysdeps/unix/sysv/linux/m68k/bits/mman.h: New file. * sysdeps/unix/sysv/linux/mips/bits/mman.h: New file. * sysdeps/unix/sysv/linux/powerpc/bits/mman.h: New file. * sysdeps/unix/sysv/linux/sparc/bits/mman.h: New file. * sysdeps/unix/sysv/linux/sparc64/bits/mman.h: New file. * sysdeps/unix/sysv/linux/alpha/Dist: Add bits/mman.h. * sysdeps/unix/sysv/linux/i386/Dist: Likewise. * sysdeps/unix/sysv/linux/m68k/Dist: Likewise. * sysdeps/unix/sysv/linux/mips/Dist: Likewise. * sysdeps/unix/sysv/linux/powerpc/Dist: Likewise. * sysdeps/unix/sysv/linux/sparc/Dist: Likewise. * sysdeps/unix/sysv/linux/sparc64/Dist: New file. Likewise. * catgets/open_catalog.c (__open_catalog): Compare result of mmap with MAP_FAILED and not -1. * elf/dl-load.c (_dl_map_object_from_fd): Likewise. * elf/dl-minimal.c (malloc): Likewise. * elf/dl-misc.c (_dl_sysdep_read_whole_file): Likewise. * locale/loadlocale.c (_nl_load_locale): Likewise. * locale/programs/localedef.c: Likewise. * malloc/malloc.c (mmap_chunk): Likewise. (new_heap): Likewise. * string/stratcliff.c: Likewise. * string/tester.c: Add tests for stpcpy. * gmon/gmon.c (__monstartup): Use calloc instead of malloc+memset. * gmon/sys/gmon.h: Add prototype for write_profiling. * elf/dl-profile.c: Add decsriptions and implement reading of existing data in profiling file. * gmon/sys/gmon_out.h (GMON_SHOBJ_VERSION): New macro for shared lib profiling data. * sysdeps/stub/bits/libc-lock.h (__libc_once_define): Add new first parameter for class. * inet/inet_ntoa.c: Make once control variable static. Correctly handle case where key cannot be retrieved. * inet/Makefile (tests): Add tst-ntoa. * inet/tst-ntoa.c: New file. * manual/time.texi: Document localtime_r, gmtime_r, asctime_r, and ctime_r. Mention that tzname values must not be changed. * manual/users.texi: Document UTMP/WTMP handling functions. Mainly written by Mark Kettenis. * math/libm-test.c (cbrt_test): Add test for number with aboslute value < 1.0. * nss/nss_files/files-XXX.c (internal_setent): If opening of file failed with EGAIN return NSS_STATUS_TRYAGAIN. * nss/nss_files/files-alias.c (internal_setent): Likewise. * sysdeps/generic/bits/utmp.h: Pretty print. * sysdeps/i386/i586/strcpy.S: New file. Much faster implementation. * sysdeps/i386/i586/stpcpy.S: New file. * sysdeps/i386/i686/Implies: Don't fall back on i586 versions since these are less efficient than i486/i386 versions. * sysdeps/libm-i387/e_rem_pio2.c: Add empty file to prevent the version from libm-ieee754 be compiled since the later is not needed. * sysdeps/libm-i387/e_rem_pio2f.c: Likewise. * sysdeps/libm-i387/e_rem_pio2l.c: Likewise. * sysdeps/libm-i387/k_rem_pio2.c: Likewise. * sysdeps/libm-i387/k_rem_pio2f.c: Likewise. * sysdeps/libm-i387/k_rem_pio2l.c: Likewise. * sysdeps/m68k/fpu/e_rem_pio2.c: Likewise. * sysdeps/m68k/fpu/e_rem_pio2f.c: Likewise. * sysdeps/m68k/fpu/e_rem_pio2l.c: Likewise. * sysdeps/m68k/fpu/k_rem_pio2.c: Likewise. * sysdeps/m68k/fpu/k_rem_pio2f.c: Likewise. * sysdeps/m68k/fpu/k_rem_pio2l.c: Likewise. * sysdeps/libm-i387/s_cbrt.S: Fix several bugs. * sysdeps/libm-i387/s_cbrtf.S: Likewise. * sysdeps/libm-i387/s_cbrtl.S: Likewise. * sysdeps/unix/sysv/linux/if_index.c (if_indextoname): Correct little bug. * sysdeps/unix/sysv/linux/bits/socket.h (struct msghdr): Make field msg_iovlen of type int. * time/tzfile.c: Change return type of __tzstring to char *. * time/tzset.c: Likewise. Change definition of __tzstring. * time/tzset.c: Interpret no DST information in user provided time zone specification as it is meant: no DST. Patch by Paul Eggert <eggert@twinsun.com>. 1997-07-20 03:01 Geoff Keating <geoffk@ozemail.com.au> * sysdeps/elf/dl-load.c (add_name_to_object): New procedure. (_dl_map_object_from_fd): Use add_name_to_object. (_dl_map_object): If an object's SONAME is used to resolve a dependency, add it to the list of the object's names. * inet/getnameinfo.c: Make `domain' non-const. * sysdeps/unix/sysv/linux/powerpc/kernel_termios.c: Clean up. * math/test-fenv.c (feenv_nomask_test): Don't execute if FE_NOMASK_ENV is not defined, or if fesetenv(FE_NOMASK_ENV) sets errno to ENOSYS. * sysdeps/powerpc/dl-machine.h: Print proper error message on unknown reloc type (rather than using assert). * sysdeps/unix/sysv/linux/powerpc/profil-counter.h: New file. * sysdeps/unix/sysv/linux/powerpc/profil.c: Deleted. 1997-07-16 12:47 Geoff Keating <geoffk@ozemail.com.au> * sysdeps/powerpc/bits/fenv.h (feraiseexcept): New optimising macro. (feclearexcept): New optimising macro. (FE_NOMASK_ENV): Change to procedure so it can enable exceptions. (FE_ENABLED_ENV): Add. (FE_NONIEEE_ENV): Add. * sysdeps/powerpc/bits/fenv_const.c: Add __fe_enabled_env, __fe_nonieee_env; delete __fe_nomask_env. * sysdeps/powerpc/bits/fe_nomask.c: New file (stub warning until it gets implemented in the kernel). * sysdeps/powerpc/fraiseenv.c: Deal with chips that don't have FE_INVALID_SOFTWARE implemented. Use macros for bit names for clarity. * sysdeps/powerpc/fsetexcptflag.c: Likewise. * io/ftw.c: Don't compare holes in structures. * sysdeps/unix/sysv/linux/sys/sysmacros.h: Cast the result of the macros to `int', because otherwise it might be `long long' which the calling code is probably not expecting. * sysdeps/libm-ieee754/s_lround.c [NO_LONG_DOUBLE]: Fix a few bugs, document the existence of some more. * sysdeps/powerpc/s_llrint.c: New file. * sysdeps/powerpc/s_lrint.c: New file. * sysdeps/powerpc/s_llround.c: New file. * sysdeps/powerpc/s_lround.c: New file. * sysdeps/powerpc/s_sqrt.c: New file. * sysdeps/powerpc/s_sqrtf.c: New file. * sysdeps/powerpc/w_sqrt.s: New empty file. * sysdeps/powerpc/w_sqrtf.s: New empty file. * sysdeps/powerpc/t_sqrt.c: New file. * sysdeps/powerpc/test-arithf.c: New file. * sysdeps/powerpc/Makefile [subdir=math]: Add t_sqrt to support routines. Add test-arithf to test programs. * sysdeps/powerpc/bits/mathdef.h: Add FP_ILOGB0, FP_ILOGBNAN. * sysdeps/powerpc/strcmp.s: Simplify drastically. Now much neater, and possibly faster (or possibly slower, depending on input). 1997-06-08 22:55 Geoff Keating <geoffk@ozemail.com.au> * sysdeps/powerpc/fenvbits.h: Correct FE_DFL_ENV and FE_NOMASK_ENV macros. * sysdeps/powerpc/s_rint.c: New file. 1997-05-22 08:47 Geoff Keating <geoffk@ozemail.com.au> * sysdeps/powerpc/Makefile [subdir=math]: Add q_* routines. * sysdeps/powerpc/Dist: Add quad_float.h. * sysdeps/powerpc/q_dtoq.c: New file. * sysdeps/powerpc/q_itoq.c: New file. * sysdeps/powerpc/q_lltoq.c: New file. * sysdeps/powerpc/q_neg.c: New file. * sysdeps/powerpc/q_qtoi.c: New file. * sysdeps/powerpc/q_qtoll.c: New file. * sysdeps/powerpc/q_qtos.c: New file. * sysdeps/powerpc/q_qtou.c: New file. * sysdeps/powerpc/q_qtoull.c: New file. * sysdeps/powerpc/q_stoq.c: New file. * sysdeps/powerpc/q_ulltoq.c: New file. * sysdeps/powerpc/q_utoq.c: New file. * sysdeps/powerpc/quad_float.h: New file. * sysdeps/powerpc/test-arith.c: New file. * sysdeps/powerpc/fpu_control.h: Fix _FPU_GETCW. * sysdeps/powerpc/fegetround.c: Use mcrfs to be faster and not require a stack frame. * sysdeps/powerpc/bits/fenv.h: Include inline macro for fegetround. 1997-05-18 05:55 Geoff Keating <geoffk@ozemail.com.au> * sysdeps/powerpc/fenv_libc.h (fegetenv_register, fesetenv_register): Add 'volatile'. (set_fpscr_bit, reset_fpscr_bit): New macros, FPSCR_* constants to use with them. * sysdeps/powerpc/s_copysign.S: New file. * sysdeps/powerpc/s_copysignf.s: New file. * sysdeps/powerpc/s_fabs.S: New file. * sysdeps/powerpc/s_fabsf.s: New file. * sysdeps/powerpc/s_isnan.c: New file. * sysdeps/powerpc/s_isnanf.s: New file. * sysdeps/powerpc/s_rintf.c: New file. * sysdeps/powerpc/fenvbits.h: Make FE_INVALID the summary bit in the FPSCR, not the enable bit. * sysdeps/powerpc/fraiseexcpt.c: Consequent change to the above. * sysdeps/powerpc/fclrexcpt.c: Correct. * sysdeps/powerpc/fsetexcptflag.c: Correct. * sysdeps/powerpc/ftestexcpt.c: Is now much simpler. * sysdeps/powerpc/fgetexcptflg.c: Simplify. * sysdeps/powerpc/strlen.s: Schedule better, save 3 clocks :-). * sysdeps/powerpc/dl-machine.h (elf_machine_rela): Add comment explaining some reentrancy issues with lazy PLT entries. 1997-08-09 13:04 Mark Kettenis <kettenis@phys.uva.nl> * login/logout.c (logout): utmpname returns -1 on error. * login/libutil.map: Remove updwtmp. * login/getutline.c: Rename getutline to __getutline and make getutline a weak alias. Make getutxline a weak alias for __getutline. * login/getutid.c: Rename getutid to __getutid and make getutid a weak alias. Make getutxid a weak alias for __getutid. * libc.map: Add getutxid, getutxline. * login/utmpname.c (__utmpname): Reset backend right after backend endutent call. * login/utmp_file.c: Reordered functions. Remove unecessary header files. (getutent_r_file, pututline_file): Do not call setutent_file. At this point the file is guaranteed to be open (assert!). (getutid_r_file, getutline_r_file): Remove check for validity of file descriptor. At this point the file is guaranteed to be open. (getutent_r_file, internal_getut_r, getutline_r_file, pututline_file, updwtmp_file): Do not wait when unlocking file. * login/utmp_daemon.c: General cleanup and a bit of reordering. (getutent_r_daemon, pututline_daemon): Do not call setutent_daemon. At this point the socket is guaranteed to be open (assert!). (getutid_r_daemon, getutline_r_daemon): Do not check if daemon_sock is valid. At this point the socket is guaranteed to be open (assert!). * login/getutline_r.c: Remove unnecessary header files. (__getutline_r): Do not call backend setutent. * login/getutid_r.c: Remove unnecessary header files. (__getutid_r): Do not call backend setutent. * login/getutent_r.c: Remove unneccesary header files. (__libc_utmp_unknown_functions): Added getutid_r_unknown, getutline_r_unknown. (setutent_unknown): Only set file backend if setutent for the file backend was successful. (getutent_r_unknown, pututline_unknown): Call setutent_unknown instead of __setutent. Report failure if no backend was selected. (getutid_r_unknown): New function. (getutline_r_unknown): New function. (__endutent): Reset backend. This makes sure all backends are checked on the next setutent call. 1997-08-08 20:20 Thorsten Kukuk <kukuk@vt.uni-paderborn.de> * nis_cache.c: Replace dummy functions. * libc.map: Add xdr_sizeof symbol. * sunrpc/Makefile: Add xdr_sizeof to routines. * sunrpc/rpc/xdr.h: Add xdr_sizeof prototype. * sunrpc/xdr_sizeof.c: New, from tirpc 2.3. 1997-08-08 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> * sysdeps/mach/bits/libc-lock.h (__libc_once): Define correctly. 1997-08-07 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> * sysdeps/mach/hurd/profil.c (fetch_samples): Put parens in the right place. 1997-08-06 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> * sysdeps/mach/hurd/profil.c (fetch_samples): Do arithmetic on PC's in long long to avoid overflow. 1997-08-07 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> * sysdeps/mach/bits/libc-lock.h (__libc_once, __libc_once_define): New macros. 1997-08-06 Andreas Jaeger <aj@arthur.rhein-neckar.de> * nis/Makefile (headers): Remove bits/nislib.h. 1997-08-06 14:54 Ulrich Drepper <drepper@cygnus.com> * sysdeps/mach/hurd/Subdirs: Add login. 1997-08-06 14:23 Klaus Espenlaub <kespenla@hydra.informatik.uni-ulm.de> * db/hash/hash.c (init_hash): Don't use stat() if it doesn't provide the preferred block size. * login/programs/database.c (store_state_entry): Don't compile if there is no ut_type field. (store_state_entry, store_process_entry): Use the ut_tv field for timestamps if supported. * login/programs/utmpdump.c (print_entry): Always use ut_tv field. * login/programs/xtmp.c: Fix numerous xtmp/utmp typos. Use the ut_tv field for timestamps if supported. * login/programs/xtmp.h: Fix xtmp/utmp typo. * sysdeps/posix/defs.c (stdstream): Change (PTR) to (void *). * sysdeps/stub/connect.c (connect): Change to __connect, add alias. * sysdeps/stub/send.c (send): Likewise. * sysdeps/stub/s_exp2f.c: Emit correct stub_warning(). * sysdeps/stub/statfs.c: Move stub_warning() to the usual place. * sysdeps/stub/init-first.c: Add definition of __libc_pid. 1997-08-05 13:28 Philip Blundell <pb@spring.nexus.co.uk> * sysdeps/standalone/arm/bits/errno.h: Add EISDIR, EOPNOTSUPP; tidy up formatting. * Makefile (subdirs): Remove `login'. * sysdeps/unix/Subdirs: New file; build `login' subdirectory for Unix systems. 1997-08-05 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> * sysdeps/generic/bits/utmpx.h: New file. * sysdeps/mach/hurd/Dist: Add some files. * sysdeps/mips/Dist: Likewise. * sysdeps/mips/mips64/Dist: Likewise. * sysdeps/sparc/Dist: Likewise. * sysdeps/unix/sysv/linux/mips/Dist: Likewise. * sysdeps/unix/sysv/linux/sparc/Dist: Likewise. * sysdeps/mips/mipsel/Dist: New file. * sysdeps/sparc64/elf/Dist: New file. * sysdeps/unix/sysv/linux/sparc64/Dist: New file. 1997-08-05 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> * libc.map: Add missing symbols. 1997-08-05 Andreas Jaeger <aj@arthur.rhein-neckar.de> * manual/socket.texi: Correct typos. * manual/math.texi: Correct typos. * manual/time.texi (Formatting Date and Time): Likewise. 1997-08-04 13:06 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> * gmon/gmon.c (write_gmon): New function; guts from _mcleanup. (_mcleanup): Use write_gmon. (write_profiling): This function can be safely called at any time to write a current histogram without interfering with ongoing profiling. * sysdeps/mach/hurd/profil.c (fetch_samples): Initialize NSAMPLES. 1997-08-01 17:53 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> * sysdeps/mach/hurd/profil.c (fetch_samples): Sample buffer need not be vm_deallocated; it's a stack buffer. (profil_vm_deallocate): Delete prototype. (#include <../mach/RPC_vm_deallocate_rpc.c>): Drop this inclusion. * sysdeps/mach/hurd/Makefile ($(common-objpfx)hurd/../mach/RPC_vm_deallocate_rpc.c): Delete this rule. * sysdeps/mach/hurd/profil.c (fetch_samples): New function, guts from profile_waiter. (profile_waiter): Use fetch_samples. (profil): When turning off profiling, fetch the last bunch of samples before disabling PC sampling. (fetch_samples): Add prototype. 1997-07-30 12:53 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> * sysdeps/mach/hurd/Makefile: Give normal rules for the mach RPC source included by profil.c instead of trying to use before-compile grot. 1997-07-23 15:04 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> * sysdeps/mach/hurd/profil.c (profile_waiter): Do vm_deallocate after releasing lock. Use special RPC stubs and avoid assert, thus making this function entirely independent of the threadvar mechanism and of cthreads. (lock): Convert to be a spin lock instead of a mutex, so that the waiter thread need not use cthreads. Use a fork prepare hook instead of _hurd_fork_locks to make sure we are clean before forking. (fork_profil_child): Renamed from fork_profil. (profil_reply_port): New variable. (profil_vm_deallocate, profil_task_get_sampled_pcs): Special RPC stubs made by special hacks. * sysdeps/mach/hurd/Makefile (before-compile): Add the mach RPC source files that profil.c needs if we are in the gmon directory. * mach/setup-thread.c (__mach_setup_thread): Delete avoidance of a cthreads bug that hasn't existed for two years. * stdio-common/printf_fp.c (__printf_fp): Correct rounding of numbers * locale/programs/locale.c (print_escaped): New function. * time/australasia: Likewise. (open_database, synchronize_database, initialize_database): * nss/nss_files/files-netgrp.c (_nss_netgroup_parseline): Don't * Makerules (load-map-file): Currectly handle missing map file. cannot rely on M_SQRT2 being defined. (log1p): Use __M_SQRT2 not M_SQRT2.
1930 lines
70 KiB
Plaintext
1930 lines
70 KiB
Plaintext
@node Users and Groups
|
|
@chapter Users and Groups
|
|
|
|
Every user who can log in on the system is identified by a unique number
|
|
called the @dfn{user ID}. Each process has an effective user ID which
|
|
says which user's access permissions it has.
|
|
|
|
Users are classified into @dfn{groups} for access control purposes. Each
|
|
process has one or more @dfn{group ID values} which say which groups the
|
|
process can use for access to files.
|
|
|
|
The effective user and group IDs of a process collectively form its
|
|
@dfn{persona}. This determines which files the process can access.
|
|
Normally, a process inherits its persona from the parent process, but
|
|
under special circumstances a process can change its persona and thus
|
|
change its access permissions.
|
|
|
|
Each file in the system also has a user ID and a group ID. Access
|
|
control works by comparing the user and group IDs of the file with those
|
|
of the running process.
|
|
|
|
The system keeps a database of all the registered users, and another
|
|
database of all the defined groups. There are library functions you
|
|
can use to examine these databases.
|
|
|
|
@menu
|
|
* User and Group IDs:: Each user has a unique numeric ID;
|
|
likewise for groups.
|
|
* Process Persona:: The user IDs and group IDs of a process.
|
|
* Why Change Persona:: Why a program might need to change
|
|
its user and/or group IDs.
|
|
* How Change Persona:: Changing the user and group IDs.
|
|
* Reading Persona:: How to examine the user and group IDs.
|
|
|
|
* Setting User ID:: Functions for setting the user ID.
|
|
* Setting Groups:: Functions for setting the group IDs.
|
|
|
|
* Enable/Disable Setuid:: Turning setuid access on and off.
|
|
* Setuid Program Example:: The pertinent parts of one sample program.
|
|
* Tips for Setuid:: How to avoid granting unlimited access.
|
|
|
|
* Who Logged In:: Getting the name of the user who logged in,
|
|
or of the real user ID of the current process.
|
|
|
|
* User Accounting Database:: Keeping information about users and various
|
|
actions in databases.
|
|
|
|
* User Database:: Functions and data structures for
|
|
accessing the user database.
|
|
* Group Database:: Functions and data structures for
|
|
accessing the group database.
|
|
* Netgroup Database:: Functions for accessing the netgroup database.
|
|
* Database Example:: Example program showing use of database
|
|
inquiry functions.
|
|
@end menu
|
|
|
|
@node User and Group IDs
|
|
@section User and Group IDs
|
|
|
|
@cindex login name
|
|
@cindex user name
|
|
@cindex user ID
|
|
Each user account on a computer system is identified by a @dfn{user
|
|
name} (or @dfn{login name}) and @dfn{user ID}. Normally, each user name
|
|
has a unique user ID, but it is possible for several login names to have
|
|
the same user ID. The user names and corresponding user IDs are stored
|
|
in a data base which you can access as described in @ref{User Database}.
|
|
|
|
@cindex group name
|
|
@cindex group ID
|
|
Users are classified in @dfn{groups}. Each user name also belongs to
|
|
one or more groups, and has one @dfn{default group}. Users who are
|
|
members of the same group can share resources (such as files) that are
|
|
not accessible to users who are not a member of that group. Each group
|
|
has a @dfn{group name} and @dfn{group ID}. @xref{Group Database},
|
|
for how to find information about a group ID or group name.
|
|
|
|
@node Process Persona
|
|
@section The Persona of a Process
|
|
@cindex persona
|
|
@cindex effective user ID
|
|
@cindex effective group ID
|
|
|
|
@c !!! bogus; not single ID. set of effective group IDs (and, in GNU,
|
|
@c set of effective UIDs) determines privilege. lying here and then
|
|
@c telling the truth below is confusing.
|
|
At any time, each process has a single user ID and a group ID which
|
|
determine the privileges of the process. These are collectively called
|
|
the @dfn{persona} of the process, because they determine ``who it is''
|
|
for purposes of access control. These IDs are also called the
|
|
@dfn{effective user ID} and @dfn{effective group ID} of the process.
|
|
|
|
Your login shell starts out with a persona which consists of your user
|
|
ID and your default group ID.
|
|
@c !!! also supplementary group IDs.
|
|
In normal circumstances, all your other processes inherit these values.
|
|
|
|
@cindex real user ID
|
|
@cindex real group ID
|
|
A process also has a @dfn{real user ID} which identifies the user who
|
|
created the process, and a @dfn{real group ID} which identifies that
|
|
user's default group. These values do not play a role in access
|
|
control, so we do not consider them part of the persona. But they are
|
|
also important.
|
|
|
|
Both the real and effective user ID can be changed during the lifetime
|
|
of a process. @xref{Why Change Persona}.
|
|
|
|
@cindex supplementary group IDs
|
|
In addition, a user can belong to multiple groups, so the persona
|
|
includes @dfn{supplementary group IDs} that also contribute to access
|
|
permission.
|
|
|
|
For details on how a process's effective user IDs and group IDs affect
|
|
its permission to access files, see @ref{Access Permission}.
|
|
|
|
The user ID of a process also controls permissions for sending signals
|
|
using the @code{kill} function. @xref{Signaling Another Process}.
|
|
|
|
@node Why Change Persona
|
|
@section Why Change the Persona of a Process?
|
|
|
|
The most obvious situation where it is necessary for a process to change
|
|
its user and/or group IDs is the @code{login} program. When
|
|
@code{login} starts running, its user ID is @code{root}. Its job is to
|
|
start a shell whose user and group IDs are those of the user who is
|
|
logging in. (To accomplish this fully, @code{login} must set the real
|
|
user and group IDs as well as its persona. But this is a special case.)
|
|
|
|
The more common case of changing persona is when an ordinary user
|
|
program needs access to a resource that wouldn't ordinarily be
|
|
accessible to the user actually running it.
|
|
|
|
For example, you may have a file that is controlled by your program but
|
|
that shouldn't be read or modified directly by other users, either
|
|
because it implements some kind of locking protocol, or because you want
|
|
to preserve the integrity or privacy of the information it contains.
|
|
This kind of restricted access can be implemented by having the program
|
|
change its effective user or group ID to match that of the resource.
|
|
|
|
Thus, imagine a game program that saves scores in a file. The game
|
|
program itself needs to be able to update this file no matter who is
|
|
running it, but if users can write the file without going through the
|
|
game, they can give themselves any scores they like. Some people
|
|
consider this undesirable, or even reprehensible. It can be prevented
|
|
by creating a new user ID and login name (say, @code{games}) to own the
|
|
scores file, and make the file writable only by this user. Then, when
|
|
the game program wants to update this file, it can change its effective
|
|
user ID to be that for @code{games}. In effect, the program must
|
|
adopt the persona of @code{games} so it can write the scores file.
|
|
|
|
@node How Change Persona
|
|
@section How an Application Can Change Persona
|
|
@cindex @code{setuid} programs
|
|
|
|
The ability to change the persona of a process can be a source of
|
|
unintentional privacy violations, or even intentional abuse. Because of
|
|
the potential for problems, changing persona is restricted to special
|
|
circumstances.
|
|
|
|
You can't arbitrarily set your user ID or group ID to anything you want;
|
|
only privileged processes can do that. Instead, the normal way for a
|
|
program to change its persona is that it has been set up in advance to
|
|
change to a particular user or group. This is the function of the setuid
|
|
and setgid bits of a file's access mode. @xref{Permission Bits}.
|
|
|
|
When the setuid bit of an executable file is set, executing that file
|
|
automatically changes the effective user ID to the user that owns the
|
|
file. Likewise, executing a file whose setgid bit is set changes the
|
|
effective group ID to the group of the file. @xref{Executing a File}.
|
|
Creating a file that changes to a particular user or group ID thus
|
|
requires full access to that user or group ID.
|
|
|
|
@xref{File Attributes}, for a more general discussion of file modes and
|
|
accessibility.
|
|
|
|
A process can always change its effective user (or group) ID back to its
|
|
real ID. Programs do this so as to turn off their special privileges
|
|
when they are not needed, which makes for more robustness.
|
|
|
|
@c !!! talk about _POSIX_SAVED_IDS
|
|
|
|
@node Reading Persona
|
|
@section Reading the Persona of a Process
|
|
|
|
Here are detailed descriptions of the functions for reading the user and
|
|
group IDs of a process, both real and effective. To use these
|
|
facilities, you must include the header files @file{sys/types.h} and
|
|
@file{unistd.h}.
|
|
@pindex unistd.h
|
|
@pindex sys/types.h
|
|
|
|
@comment sys/types.h
|
|
@comment POSIX.1
|
|
@deftp {Data Type} uid_t
|
|
This is an integer data type used to represent user IDs. In the GNU
|
|
library, this is an alias for @code{unsigned int}.
|
|
@end deftp
|
|
|
|
@comment sys/types.h
|
|
@comment POSIX.1
|
|
@deftp {Data Type} gid_t
|
|
This is an integer data type used to represent group IDs. In the GNU
|
|
library, this is an alias for @code{unsigned int}.
|
|
@end deftp
|
|
|
|
@comment unistd.h
|
|
@comment POSIX.1
|
|
@deftypefun uid_t getuid (void)
|
|
The @code{getuid} function returns the real user ID of the process.
|
|
@end deftypefun
|
|
|
|
@comment unistd.h
|
|
@comment POSIX.1
|
|
@deftypefun gid_t getgid (void)
|
|
The @code{getgid} function returns the real group ID of the process.
|
|
@end deftypefun
|
|
|
|
@comment unistd.h
|
|
@comment POSIX.1
|
|
@deftypefun uid_t geteuid (void)
|
|
The @code{geteuid} function returns the effective user ID of the process.
|
|
@end deftypefun
|
|
|
|
@comment unistd.h
|
|
@comment POSIX.1
|
|
@deftypefun gid_t getegid (void)
|
|
The @code{getegid} function returns the effective group ID of the process.
|
|
@end deftypefun
|
|
|
|
@comment unistd.h
|
|
@comment POSIX.1
|
|
@deftypefun int getgroups (int @var{count}, gid_t *@var{groups})
|
|
The @code{getgroups} function is used to inquire about the supplementary
|
|
group IDs of the process. Up to @var{count} of these group IDs are
|
|
stored in the array @var{groups}; the return value from the function is
|
|
the number of group IDs actually stored. If @var{count} is smaller than
|
|
the total number of supplementary group IDs, then @code{getgroups}
|
|
returns a value of @code{-1} and @code{errno} is set to @code{EINVAL}.
|
|
|
|
If @var{count} is zero, then @code{getgroups} just returns the total
|
|
number of supplementary group IDs. On systems that do not support
|
|
supplementary groups, this will always be zero.
|
|
|
|
Here's how to use @code{getgroups} to read all the supplementary group
|
|
IDs:
|
|
|
|
@smallexample
|
|
@group
|
|
gid_t *
|
|
read_all_groups (void)
|
|
@{
|
|
int ngroups = getgroups (0, NULL);
|
|
gid_t *groups
|
|
= (gid_t *) xmalloc (ngroups * sizeof (gid_t));
|
|
int val = getgroups (ngroups, groups);
|
|
if (val < 0)
|
|
@{
|
|
free (groups);
|
|
return NULL;
|
|
@}
|
|
return groups;
|
|
@}
|
|
@end group
|
|
@end smallexample
|
|
@end deftypefun
|
|
|
|
@node Setting User ID
|
|
@section Setting the User ID
|
|
|
|
This section describes the functions for altering the user ID (real
|
|
and/or effective) of a process. To use these facilities, you must
|
|
include the header files @file{sys/types.h} and @file{unistd.h}.
|
|
@pindex unistd.h
|
|
@pindex sys/types.h
|
|
|
|
@comment unistd.h
|
|
@comment POSIX.1
|
|
@deftypefun int setuid (uid_t @var{newuid})
|
|
This function sets both the real and effective user ID of the process
|
|
to @var{newuid}, provided that the process has appropriate privileges.
|
|
@c !!! also sets saved-id
|
|
|
|
If the process is not privileged, then @var{newuid} must either be equal
|
|
to the real user ID or the saved user ID (if the system supports the
|
|
@code{_POSIX_SAVED_IDS} feature). In this case, @code{setuid} sets only
|
|
the effective user ID and not the real user ID.
|
|
@c !!! xref to discussion of _POSIX_SAVED_IDS
|
|
|
|
The @code{setuid} function returns a value of @code{0} to indicate
|
|
successful completion, and a value of @code{-1} to indicate an error.
|
|
The following @code{errno} error conditions are defined for this
|
|
function:
|
|
|
|
@table @code
|
|
@item EINVAL
|
|
The value of the @var{newuid} argument is invalid.
|
|
|
|
@item EPERM
|
|
The process does not have the appropriate privileges; you do not
|
|
have permission to change to the specified ID.
|
|
@end table
|
|
@end deftypefun
|
|
|
|
@comment unistd.h
|
|
@comment BSD
|
|
@deftypefun int setreuid (uid_t @var{ruid}, uid_t @var{euid})
|
|
This function sets the real user ID of the process to @var{ruid} and the
|
|
effective user ID to @var{euid}. If @var{ruid} is @code{-1}, it means
|
|
not to change the real user ID; likewise if @var{euid} is @code{-1}, it
|
|
means not to change the effective user ID.
|
|
|
|
The @code{setreuid} function exists for compatibility with 4.3 BSD Unix,
|
|
which does not support saved IDs. You can use this function to swap the
|
|
effective and real user IDs of the process. (Privileged processes are
|
|
not limited to this particular usage.) If saved IDs are supported, you
|
|
should use that feature instead of this function. @xref{Enable/Disable
|
|
Setuid}.
|
|
|
|
The return value is @code{0} on success and @code{-1} on failure.
|
|
The following @code{errno} error conditions are defined for this
|
|
function:
|
|
|
|
@table @code
|
|
@item EPERM
|
|
The process does not have the appropriate privileges; you do not
|
|
have permission to change to the specified ID.
|
|
@end table
|
|
@end deftypefun
|
|
|
|
@node Setting Groups
|
|
@section Setting the Group IDs
|
|
|
|
This section describes the functions for altering the group IDs (real
|
|
and effective) of a process. To use these facilities, you must include
|
|
the header files @file{sys/types.h} and @file{unistd.h}.
|
|
@pindex unistd.h
|
|
@pindex sys/types.h
|
|
|
|
@comment unistd.h
|
|
@comment POSIX.1
|
|
@deftypefun int setgid (gid_t @var{newgid})
|
|
This function sets both the real and effective group ID of the process
|
|
to @var{newgid}, provided that the process has appropriate privileges.
|
|
@c !!! also sets saved-id
|
|
|
|
If the process is not privileged, then @var{newgid} must either be equal
|
|
to the real group ID or the saved group ID. In this case, @code{setgid}
|
|
sets only the effective group ID and not the real group ID.
|
|
|
|
The return values and error conditions for @code{setgid} are the same
|
|
as those for @code{setuid}.
|
|
@end deftypefun
|
|
|
|
@comment unistd.h
|
|
@comment BSD
|
|
@deftypefun int setregid (gid_t @var{rgid}, fid_t @var{egid})
|
|
This function sets the real group ID of the process to @var{rgid} and
|
|
the effective group ID to @var{egid}. If @var{rgid} is @code{-1}, it
|
|
means not to change the real group ID; likewise if @var{egid} is
|
|
@code{-1}, it means not to change the effective group ID.
|
|
|
|
The @code{setregid} function is provided for compatibility with 4.3 BSD
|
|
Unix, which does not support saved IDs. You can use this function to
|
|
swap the effective and real group IDs of the process. (Privileged
|
|
processes are not limited to this usage.) If saved IDs are supported,
|
|
you should use that feature instead of using this function.
|
|
@xref{Enable/Disable Setuid}.
|
|
|
|
The return values and error conditions for @code{setregid} are the same
|
|
as those for @code{setreuid}.
|
|
@end deftypefun
|
|
|
|
The GNU system also lets privileged processes change their supplementary
|
|
group IDs. To use @code{setgroups} or @code{initgroups}, your programs
|
|
should include the header file @file{grp.h}.
|
|
@pindex grp.h
|
|
|
|
@comment grp.h
|
|
@comment BSD
|
|
@deftypefun int setgroups (size_t @var{count}, gid_t *@var{groups})
|
|
This function sets the process's supplementary group IDs. It can only
|
|
be called from privileged processes. The @var{count} argument specifies
|
|
the number of group IDs in the array @var{groups}.
|
|
|
|
This function returns @code{0} if successful and @code{-1} on error.
|
|
The following @code{errno} error conditions are defined for this
|
|
function:
|
|
|
|
@table @code
|
|
@item EPERM
|
|
The calling process is not privileged.
|
|
@end table
|
|
@end deftypefun
|
|
|
|
@comment grp.h
|
|
@comment BSD
|
|
@deftypefun int initgroups (const char *@var{user}, gid_t @var{gid})
|
|
The @code{initgroups} function effectively calls @code{setgroups} to
|
|
set the process's supplementary group IDs to be the normal default for
|
|
the user name @var{user}. The group ID @var{gid} is also included.
|
|
@c !!! explain that this works by reading the group file looking for
|
|
@c groups USER is a member of.
|
|
@end deftypefun
|
|
|
|
@node Enable/Disable Setuid
|
|
@section Enabling and Disabling Setuid Access
|
|
|
|
A typical setuid program does not need its special access all of the
|
|
time. It's a good idea to turn off this access when it isn't needed,
|
|
so it can't possibly give unintended access.
|
|
|
|
If the system supports the saved user ID feature, you can accomplish
|
|
this with @code{setuid}. When the game program starts, its real user ID
|
|
is @code{jdoe}, its effective user ID is @code{games}, and its saved
|
|
user ID is also @code{games}. The program should record both user ID
|
|
values once at the beginning, like this:
|
|
|
|
@smallexample
|
|
user_user_id = getuid ();
|
|
game_user_id = geteuid ();
|
|
@end smallexample
|
|
|
|
Then it can turn off game file access with
|
|
|
|
@smallexample
|
|
setuid (user_user_id);
|
|
@end smallexample
|
|
|
|
@noindent
|
|
and turn it on with
|
|
|
|
@smallexample
|
|
setuid (game_user_id);
|
|
@end smallexample
|
|
|
|
@noindent
|
|
Throughout this process, the real user ID remains @code{jdoe} and the
|
|
saved user ID remains @code{games}, so the program can always set its
|
|
effective user ID to either one.
|
|
|
|
On other systems that don't support the saved user ID feature, you can
|
|
turn setuid access on and off by using @code{setreuid} to swap the real
|
|
and effective user IDs of the process, as follows:
|
|
|
|
@smallexample
|
|
setreuid (geteuid (), getuid ());
|
|
@end smallexample
|
|
|
|
@noindent
|
|
This special case is always allowed---it cannot fail.
|
|
|
|
Why does this have the effect of toggling the setuid access? Suppose a
|
|
game program has just started, and its real user ID is @code{jdoe} while
|
|
its effective user ID is @code{games}. In this state, the game can
|
|
write the scores file. If it swaps the two uids, the real becomes
|
|
@code{games} and the effective becomes @code{jdoe}; now the program has
|
|
only @code{jdoe} access. Another swap brings @code{games} back to
|
|
the effective user ID and restores access to the scores file.
|
|
|
|
In order to handle both kinds of systems, test for the saved user ID
|
|
feature with a preprocessor conditional, like this:
|
|
|
|
@smallexample
|
|
#ifdef _POSIX_SAVED_IDS
|
|
setuid (user_user_id);
|
|
#else
|
|
setreuid (geteuid (), getuid ());
|
|
#endif
|
|
@end smallexample
|
|
|
|
@node Setuid Program Example
|
|
@section Setuid Program Example
|
|
|
|
Here's an example showing how to set up a program that changes its
|
|
effective user ID.
|
|
|
|
This is part of a game program called @code{caber-toss} that
|
|
manipulates a file @file{scores} that should be writable only by the game
|
|
program itself. The program assumes that its executable
|
|
file will be installed with the set-user-ID bit set and owned by the
|
|
same user as the @file{scores} file. Typically, a system
|
|
administrator will set up an account like @code{games} for this purpose.
|
|
|
|
The executable file is given mode @code{4755}, so that doing an
|
|
@samp{ls -l} on it produces output like:
|
|
|
|
@smallexample
|
|
-rwsr-xr-x 1 games 184422 Jul 30 15:17 caber-toss
|
|
@end smallexample
|
|
|
|
@noindent
|
|
The set-user-ID bit shows up in the file modes as the @samp{s}.
|
|
|
|
The scores file is given mode @code{644}, and doing an @samp{ls -l} on
|
|
it shows:
|
|
|
|
@smallexample
|
|
-rw-r--r-- 1 games 0 Jul 31 15:33 scores
|
|
@end smallexample
|
|
|
|
Here are the parts of the program that show how to set up the changed
|
|
user ID. This program is conditionalized so that it makes use of the
|
|
saved IDs feature if it is supported, and otherwise uses @code{setreuid}
|
|
to swap the effective and real user IDs.
|
|
|
|
@smallexample
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
|
|
|
|
/* @r{Save the effective and real UIDs.} */
|
|
|
|
static uid_t euid, ruid;
|
|
|
|
|
|
/* @r{Restore the effective UID to its original value.} */
|
|
|
|
void
|
|
do_setuid (void)
|
|
@{
|
|
int status;
|
|
|
|
#ifdef _POSIX_SAVED_IDS
|
|
status = setuid (euid);
|
|
#else
|
|
status = setreuid (ruid, euid);
|
|
#endif
|
|
if (status < 0) @{
|
|
fprintf (stderr, "Couldn't set uid.\n");
|
|
exit (status);
|
|
@}
|
|
@}
|
|
|
|
|
|
@group
|
|
/* @r{Set the effective UID to the real UID.} */
|
|
|
|
void
|
|
undo_setuid (void)
|
|
@{
|
|
int status;
|
|
|
|
#ifdef _POSIX_SAVED_IDS
|
|
status = setuid (ruid);
|
|
#else
|
|
status = setreuid (euid, ruid);
|
|
#endif
|
|
if (status < 0) @{
|
|
fprintf (stderr, "Couldn't set uid.\n");
|
|
exit (status);
|
|
@}
|
|
@}
|
|
@end group
|
|
|
|
/* @r{Main program.} */
|
|
|
|
int
|
|
main (void)
|
|
@{
|
|
/* @r{Save the real and effective user IDs.} */
|
|
ruid = getuid ();
|
|
euid = geteuid ();
|
|
undo_setuid ();
|
|
|
|
/* @r{Do the game and record the score.} */
|
|
@dots{}
|
|
@}
|
|
@end smallexample
|
|
|
|
Notice how the first thing the @code{main} function does is to set the
|
|
effective user ID back to the real user ID. This is so that any other
|
|
file accesses that are performed while the user is playing the game use
|
|
the real user ID for determining permissions. Only when the program
|
|
needs to open the scores file does it switch back to the original
|
|
effective user ID, like this:
|
|
|
|
@smallexample
|
|
/* @r{Record the score.} */
|
|
|
|
int
|
|
record_score (int score)
|
|
@{
|
|
FILE *stream;
|
|
char *myname;
|
|
|
|
/* @r{Open the scores file.} */
|
|
do_setuid ();
|
|
stream = fopen (SCORES_FILE, "a");
|
|
undo_setuid ();
|
|
|
|
@group
|
|
/* @r{Write the score to the file.} */
|
|
if (stream)
|
|
@{
|
|
myname = cuserid (NULL);
|
|
if (score < 0)
|
|
fprintf (stream, "%10s: Couldn't lift the caber.\n", myname);
|
|
else
|
|
fprintf (stream, "%10s: %d feet.\n", myname, score);
|
|
fclose (stream);
|
|
return 0;
|
|
@}
|
|
else
|
|
return -1;
|
|
@}
|
|
@end group
|
|
@end smallexample
|
|
|
|
@node Tips for Setuid
|
|
@section Tips for Writing Setuid Programs
|
|
|
|
It is easy for setuid programs to give the user access that isn't
|
|
intended---in fact, if you want to avoid this, you need to be careful.
|
|
Here are some guidelines for preventing unintended access and
|
|
minimizing its consequences when it does occur:
|
|
|
|
@itemize @bullet
|
|
@item
|
|
Don't have @code{setuid} programs with privileged user IDs such as
|
|
@code{root} unless it is absolutely necessary. If the resource is
|
|
specific to your particular program, it's better to define a new,
|
|
nonprivileged user ID or group ID just to manage that resource.
|
|
|
|
@item
|
|
Be cautious about using the @code{system} and @code{exec} functions in
|
|
combination with changing the effective user ID. Don't let users of
|
|
your program execute arbitrary programs under a changed user ID.
|
|
Executing a shell is especially bad news. Less obviously, the
|
|
@code{execlp} and @code{execvp} functions are a potential risk (since
|
|
the program they execute depends on the user's @code{PATH} environment
|
|
variable).
|
|
|
|
If you must @code{exec} another program under a changed ID, specify an
|
|
absolute file name (@pxref{File Name Resolution}) for the executable,
|
|
and make sure that the protections on that executable and @emph{all}
|
|
containing directories are such that ordinary users cannot replace it
|
|
with some other program.
|
|
|
|
@item
|
|
Only use the user ID controlling the resource in the part of the program
|
|
that actually uses that resource. When you're finished with it, restore
|
|
the effective user ID back to the actual user's user ID.
|
|
@xref{Enable/Disable Setuid}.
|
|
|
|
@item
|
|
If the @code{setuid} part of your program needs to access other files
|
|
besides the controlled resource, it should verify that the real user
|
|
would ordinarily have permission to access those files. You can use the
|
|
@code{access} function (@pxref{Access Permission}) to check this; it
|
|
uses the real user and group IDs, rather than the effective IDs.
|
|
@end itemize
|
|
|
|
@node Who Logged In
|
|
@section Identifying Who Logged In
|
|
@cindex login name, determining
|
|
@cindex user ID, determining
|
|
|
|
You can use the functions listed in this section to determine the login
|
|
name of the user who is running a process, and the name of the user who
|
|
logged in the current session. See also the function @code{getuid} and
|
|
friends (@pxref{Reading Persona}). How this information is collected by
|
|
the system and how to control/add/remove information from the background
|
|
storage is described in @ref{User Accounting Database}.
|
|
|
|
The @code{getlogin} function is declared in @file{unistd.h}, while
|
|
@code{cuserid} and @code{L_cuserid} are declared in @file{stdio.h}.
|
|
@pindex stdio.h
|
|
@pindex unistd.h
|
|
|
|
@comment unistd.h
|
|
@comment POSIX.1
|
|
@deftypefun {char *} getlogin (void)
|
|
The @code{getlogin} function returns a pointer to a string containing the
|
|
name of the user logged in on the controlling terminal of the process,
|
|
or a null pointer if this information cannot be determined. The string
|
|
is statically allocated and might be overwritten on subsequent calls to
|
|
this function or to @code{cuserid}.
|
|
@end deftypefun
|
|
|
|
@comment stdio.h
|
|
@comment POSIX.1
|
|
@deftypefun {char *} cuserid (char *@var{string})
|
|
The @code{cuserid} function returns a pointer to a string containing a
|
|
user name associated with the effective ID of the process. If
|
|
@var{string} is not a null pointer, it should be an array that can hold
|
|
at least @code{L_cuserid} characters; the string is returned in this
|
|
array. Otherwise, a pointer to a string in a static area is returned.
|
|
This string is statically allocated and might be overwritten on
|
|
subsequent calls to this function or to @code{getlogin}.
|
|
|
|
The use of this function is deprecated since it is marked to be
|
|
withdrawn in XPG4.2 and it is already removed in POSIX.1.
|
|
@end deftypefun
|
|
|
|
@comment stdio.h
|
|
@comment POSIX.1
|
|
@deftypevr Macro int L_cuserid
|
|
An integer constant that indicates how long an array you might need to
|
|
store a user name.
|
|
@end deftypevr
|
|
|
|
These functions let your program identify positively the user who is
|
|
running or the user who logged in this session. (These can differ when
|
|
setuid programs are involved; @xref{Process Persona}.) The user cannot
|
|
do anything to fool these functions.
|
|
|
|
For most purposes, it is more useful to use the environment variable
|
|
@code{LOGNAME} to find out who the user is. This is more flexible
|
|
precisely because the user can set @code{LOGNAME} arbitrarily.
|
|
@xref{Standard Environment}.
|
|
|
|
|
|
@node User Accounting Database
|
|
@section The User Accounting Database
|
|
@cindex user accounting database
|
|
|
|
Most Unix-like operating systems keep track of logged in users by
|
|
maintaining a user accounting database. This user accounting database
|
|
stores for each terminal, who has logged on, at what time, the process
|
|
ID of the user's login shell, etc., etc., but also stores information
|
|
about the run level of the system, the time of the last system reboot,
|
|
and possibly more.
|
|
|
|
The user accounting database typically lives in @file{/etc/utmp},
|
|
@file{/var/adm/utmp} or @file{/var/run/utmp}. However, these files
|
|
should @strong{never} be accessed directly. For reading information
|
|
from and writing information to the user accounting database, the
|
|
functions described in this section should be used.
|
|
|
|
|
|
@menu
|
|
* Manipulating the Database:: Scanning and modifying the user
|
|
accounting database.
|
|
* XPG Functions:: A standardized way for doing the same thing.
|
|
* Logging In and Out:: Functions from BSD that modify the user
|
|
accounting database.
|
|
@end menu
|
|
|
|
@node Manipulating the Database
|
|
@subsection Manipulating the User Accounting Database
|
|
|
|
These functions and the corresponding data structures are declared in
|
|
the header file @file{utmp.h}.
|
|
@pindex utmp.h
|
|
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@deftp {Data Type} {struct exit_status}
|
|
The @code{exit_status} data structure is used to hold information about
|
|
the exit status of processes marked as @code{DEAD_PROCESS} in the user
|
|
accounting database.
|
|
|
|
@table @code
|
|
@item short int e_termination
|
|
The exit status of the process.
|
|
|
|
@item short int e_exit
|
|
The exit status of the process.
|
|
@end table
|
|
@end deftp
|
|
|
|
@deftp {Data Type} {struct utmp}
|
|
The @code{utmp} data structure is used to hold information about entries
|
|
in the user accounting database. On the GNU system it has the following
|
|
members:
|
|
|
|
@table @code
|
|
@item short int ut_type
|
|
Specifies the type of login; one of @code{EMPTY}, @code{RUN_LVL},
|
|
@code{BOOT_TIME}, @code{OLD_TIME}, @code{NEW_TIME}, @code{INIT_PROCESS},
|
|
@code{LOGIN_PROCESS}, @code{USER_PROCESS}, @code{DEAD_PROCESS} or
|
|
@code{ACCOUNTING}.
|
|
|
|
@item pid_t ut_pid
|
|
The process ID number of the login process.
|
|
|
|
@item char ut_line[]
|
|
The device name of the tty (without @file{/dev/}).
|
|
|
|
@item char ut_id[]
|
|
The inittab ID of the process.
|
|
|
|
@item char ut_user[]
|
|
The user's login name.
|
|
|
|
@item char ut_host[]
|
|
The name of the host from which the user logged in.
|
|
|
|
@item struct exit_status ut_exit
|
|
The exit status of a process marked as @code{DEAD_PROCESS}.
|
|
|
|
@item long ut_session
|
|
The Session ID, used for windowing.
|
|
|
|
@item struct timeval ut_tv
|
|
Time the entry was made. For entries of type @code{OLD_TIME} this is
|
|
the time when the system clock changed, and for entries of type
|
|
@code{NEW_TIME} this is the time the system clock was set to.
|
|
|
|
@item int32_t ut_addr_v6[4]
|
|
The Internet address of a remote host.
|
|
@end table
|
|
@end deftp
|
|
|
|
The @code{ut_type}, @code{ut_pid}, @code{ut_id}, @code{ut_tv}, and
|
|
@code{ut_host} fields are not available on all systems. Portable
|
|
applications therefore should be prepared for these situations. To help
|
|
doing this the @file{utmp.h} header provides macros
|
|
@code{_HAVE_UT_TYPE}, @code{_HAVE_UT_PID}, @code{_HAVE_UT_ID},
|
|
@code{_HAVE_UT_TV}, and @code{_HAVE_UT_HOST} if the respective field is
|
|
available. The programmer can handle the situations by using
|
|
@code{#ifdef} in the program code.
|
|
|
|
The following macros are defined for use as values for the
|
|
@code{ut_type} member of the @code{utmp} structure. The values are
|
|
integer constants.
|
|
|
|
@table @code
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@vindex EMPTY
|
|
@item EMPTY
|
|
This macro is used to indicate that the entry contains no valid user
|
|
accounting information.
|
|
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@vindex RUN_LVL
|
|
@item RUN_LVL
|
|
This macro is used to identify the systems runlevel.
|
|
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@vindex BOOT_TIME
|
|
@item BOOT_TIME
|
|
This macro is used to identify the time of system boot.
|
|
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@vindex OLD_TIME
|
|
@item OLD_TIME
|
|
This macro is used to identify the time when the system clock changed.
|
|
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@vindex NEW_TIME
|
|
@item NEW_TIME
|
|
This macro is used to identify the time after the system changed.
|
|
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@vindex INIT_PROCESS
|
|
@item INIT_PROCESS
|
|
This macro is used to identify a process spawned by the init process.
|
|
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@vindex LOGIN_PROCESS
|
|
@item LOGIN_PROCESS
|
|
This macro is used to identify the session leader of a logged in user.
|
|
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@vindex USER_PROCESS
|
|
@item USER_PROCESS
|
|
This macro is used to identify a user process.
|
|
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@vindex DEAD_PROCESS
|
|
@item DEAD_PROCESS
|
|
This macro is used to identify a terminated process.
|
|
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@vindex ACCOUNTING
|
|
@item ACCOUNTING
|
|
???
|
|
@end table
|
|
|
|
The size of the @code{ut_line}, @code{ut_id}, @code{ut_user} and
|
|
@code{ut_host} arrays can be found using the @code{sizeof} operator.
|
|
|
|
Many older systems have, instead of an @code{ut_tv} member, an
|
|
@code{ut_time} member, usually of type @code{time_t}, for representing
|
|
the time associated with the entry. Therefore, for backwards
|
|
compatibility only, @file{utmp.h} defines @code{ut_time} as an alias for
|
|
@code{ut_tv.tv_sec}.
|
|
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@deftypefun void setutent (void)
|
|
This function opens the user accounting database to begin scanning it.
|
|
You can then call @code{getutent}, @code{getutid} or @code{getutline} to
|
|
read entries and @code{pututline} to write entries.
|
|
|
|
If the database is already open, it resets the input to the beginning of
|
|
the database.
|
|
@end deftypefun
|
|
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@deftypefun {struct utmp *} getutent (void)
|
|
The @code{getutent} function reads the next entry from the user
|
|
accounting database. It returns a pointer to the entry, which is
|
|
statically allocated and may be overwritten by subsequent calls to
|
|
@code{getutent}. You must copy the contents of the structure if you
|
|
wish to save the information or you can use the @code{getutent_r}
|
|
function which stores the data in a user-provided buffer.
|
|
|
|
A null pointer is returned in case no further entry is available.
|
|
@end deftypefun
|
|
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@deftypefun void endutent (void)
|
|
This function closes the user accounting database.
|
|
@end deftypefun
|
|
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@deftypefun {struct utmp *} getutid (const struct utmp *@var{id})
|
|
This function searches forward from the current point in the database
|
|
for an entry that matches @var{id}. If the @code{ut_type} member of the
|
|
@var{id} structure is one of @code{RUN_LVL}, @code{BOOT_TIME},
|
|
@code{OLD_TIME} or @code{NEW_TIME} the entries match if the
|
|
@code{ut_type} members are identical. If the @code{ut_type} member of
|
|
the @var{id} structure is @code{INIT_PROCESS}, @code{LOGIN_PROCESS},
|
|
@code{USER_PROCESS} or @code{DEAD_PROCESS}, the entries match if the the
|
|
@code{ut_type} member of the entry read from the database is one of
|
|
these four, and the @code{ut_id} members match. However if the
|
|
@code{ut_id} member of either the @var{id} structure or the entry read
|
|
from the database is empty it checks if the @code{ut_line} members match
|
|
instead. If a matching entry is found, @code{getutid} returns a pointer
|
|
to the entry, which is statically allocated, and may be overwritten by a
|
|
subsequent call to @code{getutent}, @code{getutid} or @code{getutline}.
|
|
You must copy the contents of the structure if you wish to save the
|
|
information.
|
|
|
|
A null pointer is returned in case the end of the database is reached
|
|
without a match.
|
|
|
|
The @code{getutid} function may cache the last read entry. Therefore,
|
|
if you are using @code{getutid} to search for multiple occurrences, it
|
|
is necessary to zero out the static data after each call. Otherwise
|
|
@code{getutid} could just return a pointer to the same entry over and
|
|
over again.
|
|
@end deftypefun
|
|
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@deftypefun {struct utmp *} getutline (const struct utmp *@var{line})
|
|
This function searches forward from the current point in the database
|
|
until it finds an entry whose @code{ut_type} value is
|
|
@code{LOGIN_PROCESS} or @code{USER_PROCESS}, and whose @code{ut_line}
|
|
member matches the @code{ut_line} member of the @var{line} structure.
|
|
If it finds such an entry, it returns a pointer to the entry which is
|
|
statically allocated, and may be overwritten by a subsequent call to
|
|
@code{getutent}, @code{getutid} or @code{getutline}. You must copy the
|
|
contents of the structure if you wish to save the information.
|
|
|
|
A null pointer is returned in case the end of the database is reached
|
|
without a match.
|
|
|
|
The @code{getutline} function may cache the last read entry. Therefore
|
|
if you are using @code{getutline} to search for multiple occurrences, it
|
|
is necessary to zero out the static data after each call. Otherwise
|
|
@code{getutline} could just return a pointer to the same entry over and
|
|
over again.
|
|
@end deftypefun
|
|
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@deftypefun {struct utmp *} pututline (const struct utmp *@var{utmp})
|
|
The @code{pututline} function inserts the entry @code{*@var{utmp}} at
|
|
the appropriate place in the user accounting database. If it finds that
|
|
it is not already at the correct place in the database, it uses
|
|
@code{getutid} to search for the position to insert the entry, however
|
|
this will not modify the static structure returned by @code{getutent},
|
|
@code{getutid} and @code{getutline}. If this search fails, the entry
|
|
is appended to the database.
|
|
|
|
The @code{pututline} function returns a pointer to a copy of the entry
|
|
inserted in the user accounting database, or a null pointer if the entry
|
|
could not be added. The following @code{errno} error conditions are
|
|
defined for this function:
|
|
|
|
@table @code
|
|
@item EPERM
|
|
The process does not have the appropriate privileges; you cannot modify
|
|
the user accounting database.
|
|
@end table
|
|
@end deftypefun
|
|
|
|
All the @code{get*} functions mentioned before store the information
|
|
they return in a static buffer. This can be a problem in multi-threaded
|
|
programs since the data return for the request is overwritten be the
|
|
return value data in another thread. Therefore the GNU C Library
|
|
provides as extensions three more functions which return the data in a
|
|
user-provided buffer.
|
|
|
|
@comment utmp.h
|
|
@comment GNU
|
|
@deftypefun int getutent_r (struct utmp *@var{buffer}, struct utmp **@var{result})
|
|
The @code{getutent_r} is equivalent to the @code{getutent} function. It
|
|
returns the next entry from the database. But instead of storing the
|
|
information in a static buffer it stores it in the buffer pointed to by
|
|
the parameter @var{buffer}.
|
|
|
|
If the call was successful, the function returns @code{0} and the
|
|
pointer variable pointed to by the parameter @var{result} contains a
|
|
pointer to the buffer which contains the result (this is most probably
|
|
the same value as @var{buffer}). If something went wrong during the
|
|
execution of @code{getutent_r} the function returns @code{-1}.
|
|
|
|
This function is a GNU extension.
|
|
@end deftypefun
|
|
|
|
@comment utmp.h
|
|
@comment GNU
|
|
@deftypefun int getutid_r (const struct utmp *@var{id}, struct utmp *@var{buffer}, struct utmp **@var{result})
|
|
This function retrieves just like @code{getutid} the next entry matching
|
|
the information stored in @var{id}. But the result is stored in the
|
|
buffer pointed to by the parameter @var{buffer}.
|
|
|
|
If successful the function returns @code{0} and the pointer variable
|
|
pointed to by the parameter @var{result} contains a pointer to the
|
|
buffer with the result (probably the same as @var{result}. If not
|
|
successful the function return @code{-1}.
|
|
|
|
This function is a GNU extension.
|
|
@end deftypefun
|
|
|
|
@comment utmp.h
|
|
@comment GNU
|
|
@deftypefun int getutline_r (const struct utmp *@var{line}, struct utmp *@var{buffer}, struct utmp **@var{result})
|
|
This function retrieves just like @code{getutline} the next entry
|
|
matching the information stored in @var{line}. But the result is stored
|
|
in the buffer pointed to by the parameter @var{buffer}.
|
|
|
|
If successful the function returns @code{0} and the pointer variable
|
|
pointed to by the parameter @var{result} contains a pointer to the
|
|
buffer with the result (probably the same as @var{result}. If not
|
|
successful the function return @code{-1}.
|
|
|
|
This function is a GNU extension.
|
|
@end deftypefun
|
|
|
|
|
|
In addition to the user accounting database, most systems keep a number
|
|
of similar databases. For example most systems keep a log file with all
|
|
previous logins (usually in @file{/etc/wtmp} or @file{/var/log/wtmp}).
|
|
|
|
For specifying which database to examine, the following function should
|
|
be used.
|
|
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@deftypefun int utmpname (const char *@var{file})
|
|
The @code{utmpname} function changes the name of the database to be
|
|
examined to @var{file}, and closes any previously opened database. By
|
|
default @code{getutent}, @code{getutid}, @code{getutline} and
|
|
@code{pututline} read from and write to the user accounting database.
|
|
|
|
The following macros are defined for use as the @var{file} argument:
|
|
|
|
@deftypevr Macro {char *} _PATH_UTMP
|
|
This macro is used to specify the user accounting database.
|
|
@end deftypevr
|
|
|
|
@deftypevr Macro {char *} _PATH_WTMP
|
|
This macro is used to specify the user accounting log file.
|
|
@end deftypevr
|
|
|
|
The @code{utmpname} function returns a value of @code{0} if the new name
|
|
was successfully stored, and a value of @code{-1} to indicate an error.
|
|
Note that @code{utmpname} does not try open the database, and that
|
|
therefore the return value does not say anything about whether the
|
|
database can be successfully opened.
|
|
@end deftypefun
|
|
|
|
Specially for maintaining log-like databases the GNU C Library provides
|
|
the following function:
|
|
|
|
@comment utmp.h
|
|
@comment SVID
|
|
@deftypefun void updwtmp (const char *@var{wtmp_file}, const struct utmp *@var{utmp})
|
|
The @code{updwtmp} function appends the entry *@var{utmp} to the
|
|
database specified by @var{wtmp_file}. For possible values for the
|
|
@var{wtmp_file} argument see the @code{utmpname} function.
|
|
@end deftypefun
|
|
|
|
@strong{Portability Note:} Although many operating systems provide a
|
|
subset of these functions, they are not standardized. There are often
|
|
subtle differences in the return types, and there are considerable
|
|
differences between the various definitions of @code{struct utmp}. When
|
|
programming for the GNU system, it is probably probably best to stick
|
|
with the functions described in this section. If however, you want your
|
|
program to be portable, consider using the XPG functions described in
|
|
@ref{XPG Functions}, or take a look at the BSD compatible functions in
|
|
@ref{Logging In and Out}.
|
|
|
|
|
|
@node XPG Functions
|
|
@subsection XPG User Accounting Database Functions
|
|
|
|
These functions, described in the X/Open Portability Guide, are declared
|
|
in the header file @file{utmpx.h}.
|
|
@pindex utmpx.h
|
|
|
|
@deftp {Data Type} {struct utmpx}
|
|
The @code{utmpx} data structure contains at least the following members:
|
|
|
|
@table @code
|
|
@item short int ut_type
|
|
Specifies the type of login; one of @code{EMPTY}, @code{RUN_LVL},
|
|
@code{BOOT_TIME}, @code{OLD_TIME}, @code{NEW_TIME}, @code{INIT_PROCESS},
|
|
@code{LOGIN_PROCESS}, @code{USER_PROCESS} or @code{DEAD_PROCESS}.
|
|
|
|
@item pid_t ut_pid
|
|
The process ID number of the login process.
|
|
|
|
@item char ut_line[]
|
|
The device name of the tty (without @file{/dev/}).
|
|
|
|
@item char ut_id[]
|
|
The inittab ID of the process.
|
|
|
|
@item char ut_user[]
|
|
The user's login name.
|
|
|
|
@item struct timeval ut_tv
|
|
Time the entry was made. For entries of type @code{OLD_TIME} this is
|
|
the time when the system clock changed, and for entries of type
|
|
@code{NEW_TIME} this is the time the system clock was set to.
|
|
@end table
|
|
On the GNU system, @code{struct utmpx} is identical to @code{struct
|
|
utmp} except for the fact that including @file{utmpx.h} does not make
|
|
visible the declaration of @code{struct exit_status}.
|
|
@end deftp
|
|
|
|
The following macros are defined for use as values for the
|
|
@code{ut_type} member of the @code{utmpx} structure. The values are
|
|
integer constants and are, on the GNU system, identical to the
|
|
definitions in @file{utmp.h}.
|
|
|
|
@table @code
|
|
@comment utmpx.h
|
|
@comment XPG4.2
|
|
@vindex EMPTY
|
|
@item EMPTY
|
|
This macro is used to indicate that the entry contains no valid user
|
|
accounting information.
|
|
|
|
@comment utmpx.h
|
|
@comment XPG4.2
|
|
@vindex RUN_LVL
|
|
@item RUN_LVL
|
|
This macro is used to identify the systems runlevel.
|
|
|
|
@comment utmpx.h
|
|
@comment XPG4.2
|
|
@vindex BOOT_TIME
|
|
@item BOOT_TIME
|
|
This macro is used to identify the time of system boot.
|
|
|
|
@comment utmpx.h
|
|
@comment XPG4.2
|
|
@vindex OLD_TIME
|
|
@item OLD_TIME
|
|
This macro is used to identify the time when the system clock changed.
|
|
|
|
@comment utmpx.h
|
|
@comment XPG4.2
|
|
@vindex NEW_TIME
|
|
@item NEW_TIME
|
|
This macro is used to identify the time after the system changed.
|
|
|
|
@comment utmpx.h
|
|
@comment XPG4.2
|
|
@vindex INIT_PROCESS
|
|
@item INIT_PROCESS
|
|
This macro is used to identify a process spawned by the init process.
|
|
|
|
@comment utmpx.h
|
|
@comment XPG4.2
|
|
@vindex LOGIN_PROCESS
|
|
@item LOGIN_PROCESS
|
|
This macro is used to identify the session leader of a logged in user.
|
|
|
|
@comment utmpx.h
|
|
@comment XPG4.2
|
|
@vindex USER_PROCESS
|
|
@item USER_PROCESS
|
|
This macro is used to identify a user process.
|
|
|
|
@comment utmpx.h
|
|
@comment XPG4.2
|
|
@vindex DEAD_PROCESS
|
|
@item DEAD_PROCESS
|
|
This macro is used to identify a terminated process.
|
|
@end table
|
|
|
|
The size of the @code{ut_line}, @code{ut_id} and @code{ut_user} arrays
|
|
can be found using the @code{sizeof} operator.
|
|
|
|
@comment utmpx.h
|
|
@comment XPG4.2
|
|
@deftypefun void setutxent (void)
|
|
This function is similar to @code{setutent}. On the GNU system it is
|
|
simply an alias for @code{setutent}.
|
|
@end deftypefun
|
|
|
|
@comment utmpx.h
|
|
@comment XPG4.2
|
|
@deftypefun {struct utmpx *} getutxent (void)
|
|
The @code{getutxent} function is similar to @code{getutent}, but returns
|
|
a pointer to a @code{struct utmpx} instead of @code{struct utmp}. On
|
|
the GNU system it simply is an alias for @code{getutent}.
|
|
@end deftypefun
|
|
|
|
@comment utmpx.h
|
|
@comment XPG4.2
|
|
@deftypefun void endutxent (void)
|
|
This function is similar to @code{endutent}. On the GNU system it is
|
|
simply an alias for @code{endutent}.
|
|
@end deftypefun
|
|
|
|
@comment utmpx.h
|
|
@comment XPG4.2
|
|
@deftypefun {struct utmpx *} getutxid (const struct utmpx *@var{id})
|
|
This function is similar to @code{getutid}, but uses @code{struct utmpx}
|
|
instead of @code{struct utmp}. On the GNU system it is simply an alias
|
|
for @code{getutid}.
|
|
@end deftypefun
|
|
|
|
@comment utmpx.h
|
|
@comment XPG4.2
|
|
@deftypefun {struct utmpx *} getutxline (const struct utmpx *@var{line})
|
|
This function is similar to @code{getutid}, but uses @code{struct utmpx}
|
|
instead of @code{struct utmp}. On the GNU system it is simply an alias
|
|
for @code{getutline}.
|
|
@end deftypefun
|
|
|
|
@comment utmpx.h
|
|
@comment XPG4.2
|
|
@deftypefun {struct utmpx *} pututxline (const struct utmpx *@var{utmp})
|
|
The @code{pututxline} function provides functionality identical to
|
|
@code{pututline}, but uses @code{struct utmpx} instead of @code{struct
|
|
utmp}. On the GNU system @code{pututxline} is simply an alias for
|
|
@code{pututline}.
|
|
@end deftypefun
|
|
|
|
|
|
@node Logging In and Out
|
|
@subsection Logging In and Out
|
|
|
|
These functions, derived from BSD, are available in the separate
|
|
@file{libutil} library, and declared in @file{utmp.h}.
|
|
@pindex utmp.h
|
|
|
|
Note that the @code{ut_user} member of @code{struct utmp} is called
|
|
@code{ut_name} in BSD. Therefore, @code{ut_name} is defined as an alias
|
|
for @code{ut_user} in @file{utmp.h}.
|
|
|
|
@comment utmp.h
|
|
@comment BSD
|
|
@deftypefun int login_tty (int @var{filedes})
|
|
This function makes @var{filedes} the controlling terminal of the
|
|
current process, redirects standard input, standard output and
|
|
standard error output to this terminal, and closes @var{filedes}.
|
|
|
|
This function returns @code{0} on successful completion, and @code{-1}
|
|
on error.
|
|
@end deftypefun
|
|
|
|
@comment utmp.h
|
|
@comment BSD
|
|
@deftypefun void login (const struct utmp *@var{entry})
|
|
The @code{login} functions inserts an entry into the user accounting
|
|
database. The @code{ut_line} member is set to the name of the terminal
|
|
on standard input. If standard input is not a terminal @code{login}
|
|
uses standard output or standard error output to determine the name of
|
|
the terminal. If @code{struct utmp} has a @code{ut_type} member,
|
|
@code{login} sets it to @code{USER_PROCESS}, and if there is an
|
|
@code{ut_pid} member, it will be set to the process ID of the current
|
|
process. The remaining entries are copied from @var{entry}.
|
|
|
|
A copy of the entry is written to the user accounting log file.
|
|
@end deftypefun
|
|
|
|
@comment utmp.h
|
|
@comment BSD
|
|
@deftypefun int logout (const char *@var{ut_line})
|
|
This function modifies the user accounting database to indicate that the
|
|
user on @var{ut_line} has logged out.
|
|
|
|
The @code{logout} function returns @code{1} if the entry was successfully
|
|
written to the database, or @code{0} on error.
|
|
@end deftypefun
|
|
|
|
@comment utmp.h
|
|
@comment BSD
|
|
@deftypefun void logwtmp (const char *@var{ut_line}, const char *@var{ut_name}, const char *@var{ut_host})
|
|
The @code{logwtmp} function appends an entry to the user accounting log
|
|
file, for the current time and the information provided in the
|
|
@var{ut_line}, @var{ut_name} and @var{ut_host} arguments.
|
|
@end deftypefun
|
|
|
|
@strong{Portability Note:} The BSD @code{struct utmp} only has the
|
|
@code{ut_line}, @code{ut_name}, @code{ut_host} and @code{ut_time}
|
|
members. Older systems do not even have the @code{ut_host} member.
|
|
|
|
|
|
@node User Database
|
|
@section User Database
|
|
@cindex user database
|
|
@cindex password database
|
|
@pindex /etc/passwd
|
|
|
|
This section describes all about how to search and scan the database of
|
|
registered users. The database itself is kept in the file
|
|
@file{/etc/passwd} on most systems, but on some systems a special
|
|
network server gives access to it.
|
|
|
|
@menu
|
|
* User Data Structure:: What each user record contains.
|
|
* Lookup User:: How to look for a particular user.
|
|
* Scanning All Users:: Scanning the list of all users, one by one.
|
|
* Writing a User Entry:: How a program can rewrite a user's record.
|
|
@end menu
|
|
|
|
@node User Data Structure
|
|
@subsection The Data Structure that Describes a User
|
|
|
|
The functions and data structures for accessing the system user database
|
|
are declared in the header file @file{pwd.h}.
|
|
@pindex pwd.h
|
|
|
|
@comment pwd.h
|
|
@comment POSIX.1
|
|
@deftp {Data Type} {struct passwd}
|
|
The @code{passwd} data structure is used to hold information about
|
|
entries in the system user data base. It has at least the following members:
|
|
|
|
@table @code
|
|
@item char *pw_name
|
|
The user's login name.
|
|
|
|
@item char *pw_passwd.
|
|
The encrypted password string.
|
|
|
|
@item uid_t pw_uid
|
|
The user ID number.
|
|
|
|
@item gid_t pw_gid
|
|
The user's default group ID number.
|
|
|
|
@item char *pw_gecos
|
|
A string typically containing the user's real name, and possibly other
|
|
information such as a phone number.
|
|
|
|
@item char *pw_dir
|
|
The user's home directory, or initial working directory. This might be
|
|
a null pointer, in which case the interpretation is system-dependent.
|
|
|
|
@item char *pw_shell
|
|
The user's default shell, or the initial program run when the user logs in.
|
|
This might be a null pointer, indicating that the system default should
|
|
be used.
|
|
@end table
|
|
@end deftp
|
|
|
|
@node Lookup User
|
|
@subsection Looking Up One User
|
|
@cindex converting user ID to user name
|
|
@cindex converting user name to user ID
|
|
|
|
You can search the system user database for information about a
|
|
specific user using @code{getpwuid} or @code{getpwnam}. These
|
|
functions are declared in @file{pwd.h}.
|
|
|
|
@comment pwd.h
|
|
@comment POSIX.1
|
|
@deftypefun {struct passwd *} getpwuid (uid_t @var{uid})
|
|
This function returns a pointer to a statically-allocated structure
|
|
containing information about the user whose user ID is @var{uid}. This
|
|
structure may be overwritten on subsequent calls to @code{getpwuid}.
|
|
|
|
A null pointer value indicates there is no user in the data base with
|
|
user ID @var{uid}.
|
|
@end deftypefun
|
|
|
|
@comment pwd.h
|
|
@comment POSIX.1c
|
|
@deftypefun int getpwuid_r (uid_t @var{uid}, struct passwd *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct passwd **@var{result})
|
|
This function is similar to @code{getpwuid} in that is returns
|
|
information about the user whose user ID is @var{uid}. But the result
|
|
is not placed in a static buffer. Instead the user supplied structure
|
|
pointed to by @var{result_buf} is filled with the information. The
|
|
first @var{buflen} bytes of the additional buffer pointed to by
|
|
@var{buffer} are used to contain additional information, normally
|
|
strings which are pointed to by the elements of the result structure.
|
|
|
|
If the return value is @code{0} the pointer returned in @var{result}
|
|
points to the record which contains the wanted data (i.e., @var{result}
|
|
contains the value @var{result_buf}). In case the return value is non
|
|
null there is no user in the data base with user ID @var{uid} or the
|
|
buffer @var{buffer} is too small to contain all the needed information.
|
|
In the later case the global @var{errno} variable is set to
|
|
@code{ERANGE}.
|
|
@end deftypefun
|
|
|
|
|
|
@comment pwd.h
|
|
@comment POSIX.1
|
|
@deftypefun {struct passwd *} getpwnam (const char *@var{name})
|
|
This function returns a pointer to a statically-allocated structure
|
|
containing information about the user whose user name is @var{name}.
|
|
This structure may be overwritten on subsequent calls to
|
|
@code{getpwnam}.
|
|
|
|
A null pointer value indicates there is no user named @var{name}.
|
|
@end deftypefun
|
|
|
|
@comment pwd.h
|
|
@comment POSIX.1c
|
|
@deftypefun int getpwnam_r (const char *@var{name}, struct passwd *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct passwd **@var{result})
|
|
This function is similar to @code{getpwnam} in that is returns
|
|
information about the user whose user name is @var{name}. But the result
|
|
is not placed in a static buffer. Instead the user supplied structure
|
|
pointed to by @var{result_buf} is filled with the information. The
|
|
first @var{buflen} bytes of the additional buffer pointed to by
|
|
@var{buffer} are used to contain additional information, normally
|
|
strings which are pointed to by the elements of the result structure.
|
|
|
|
If the return value is @code{0} the pointer returned in @var{result}
|
|
points to the record which contains the wanted data (i.e., @var{result}
|
|
contains the value @var{result_buf}). In case the return value is non
|
|
null there is no user in the data base with user name @var{name} or the
|
|
buffer @var{buffer} is too small to contain all the needed information.
|
|
In the later case the global @var{errno} variable is set to
|
|
@code{ERANGE}.
|
|
@end deftypefun
|
|
|
|
|
|
@node Scanning All Users
|
|
@subsection Scanning the List of All Users
|
|
@cindex scanning the user list
|
|
|
|
This section explains how a program can read the list of all users in
|
|
the system, one user at a time. The functions described here are
|
|
declared in @file{pwd.h}.
|
|
|
|
You can use the @code{fgetpwent} function to read user entries from a
|
|
particular file.
|
|
|
|
@comment pwd.h
|
|
@comment SVID
|
|
@deftypefun {struct passwd *} fgetpwent (FILE *@var{stream})
|
|
This function reads the next user entry from @var{stream} and returns a
|
|
pointer to the entry. The structure is statically allocated and is
|
|
rewritten on subsequent calls to @code{fgetpwent}. You must copy the
|
|
contents of the structure if you wish to save the information.
|
|
|
|
This stream must correspond to a file in the same format as the standard
|
|
password database file. This function comes from System V.
|
|
@end deftypefun
|
|
|
|
@comment pwd.h
|
|
@comment GNU
|
|
@deftypefun int fgetpwent_r (FILE *@var{stream}, struct passwd *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct passwd **@var{result})
|
|
This function is similar to @code{fgetpwent} in that it reads the next
|
|
user entry from @var{stream}. But the result is returned in the
|
|
structure pointed to by @var{result_buf}. The
|
|
first @var{buflen} bytes of the additional buffer pointed to by
|
|
@var{buffer} are used to contain additional information, normally
|
|
strings which are pointed to by the elements of the result structure.
|
|
|
|
This stream must correspond to a file in the same format as the standard
|
|
password database file.
|
|
|
|
If the function returns null @var{result} points to the structure with
|
|
the wanted data (normally this is in @var{result_buf}). If errors
|
|
occurred the return value is non-null and @var{result} contains a null
|
|
pointer.
|
|
@end deftypefun
|
|
|
|
The way to scan all the entries in the user database is with
|
|
@code{setpwent}, @code{getpwent}, and @code{endpwent}.
|
|
|
|
@comment pwd.h
|
|
@comment SVID, BSD
|
|
@deftypefun void setpwent (void)
|
|
This function initializes a stream which @code{getpwent} and
|
|
@code{getpwent_r} use to read the user database.
|
|
@end deftypefun
|
|
|
|
@comment pwd.h
|
|
@comment POSIX.1
|
|
@deftypefun {struct passwd *} getpwent (void)
|
|
The @code{getpwent} function reads the next entry from the stream
|
|
initialized by @code{setpwent}. It returns a pointer to the entry. The
|
|
structure is statically allocated and is rewritten on subsequent calls
|
|
to @code{getpwent}. You must copy the contents of the structure if you
|
|
wish to save the information.
|
|
|
|
A null pointer is returned in case no further entry is available.
|
|
@end deftypefun
|
|
|
|
@comment pwd.h
|
|
@comment GNU
|
|
@deftypefun int getpwent_r (struct passwd *@var{result_buf}, char *@var{buffer}, int @var{buflen}, struct passwd **@var{result})
|
|
This function is similar to @code{getpwent} in that it returns the next
|
|
entry from the stream initialized by @code{setpwent}. But in contrast
|
|
to the @code{getpwent} function this function is reentrant since the
|
|
result is placed in the user supplied structure pointed to by
|
|
@var{result_buf}. Additional data, normally the strings pointed to by
|
|
the elements of the result structure, are placed in the additional
|
|
buffer or length @var{buflen} starting at @var{buffer}.
|
|
|
|
If the function returns zero @var{result} points to the structure with
|
|
the wanted data (normally this is in @var{result_buf}). If errors
|
|
occurred the return value is non-zero and @var{result} contains a null
|
|
pointer.
|
|
@end deftypefun
|
|
|
|
@comment pwd.h
|
|
@comment SVID, BSD
|
|
@deftypefun void endpwent (void)
|
|
This function closes the internal stream used by @code{getpwent} or
|
|
@code{getpwent_r}.
|
|
@end deftypefun
|
|
|
|
@node Writing a User Entry
|
|
@subsection Writing a User Entry
|
|
|
|
@comment pwd.h
|
|
@comment SVID
|
|
@deftypefun int putpwent (const struct passwd *@var{p}, FILE *@var{stream})
|
|
This function writes the user entry @code{*@var{p}} to the stream
|
|
@var{stream}, in the format used for the standard user database
|
|
file. The return value is zero on success and nonzero on failure.
|
|
|
|
This function exists for compatibility with SVID. We recommend that you
|
|
avoid using it, because it makes sense only on the assumption that the
|
|
@code{struct passwd} structure has no members except the standard ones;
|
|
on a system which merges the traditional Unix data base with other
|
|
extended information about users, adding an entry using this function
|
|
would inevitably leave out much of the important information.
|
|
|
|
The function @code{putpwent} is declared in @file{pwd.h}.
|
|
@end deftypefun
|
|
|
|
@node Group Database
|
|
@section Group Database
|
|
@cindex group database
|
|
@pindex /etc/group
|
|
|
|
This section describes all about how to search and scan the database of
|
|
registered groups. The database itself is kept in the file
|
|
@file{/etc/group} on most systems, but on some systems a special network
|
|
service provides access to it.
|
|
|
|
@menu
|
|
* Group Data Structure:: What each group record contains.
|
|
* Lookup Group:: How to look for a particular group.
|
|
* Scanning All Groups:: Scanning the list of all groups.
|
|
@end menu
|
|
|
|
@node Group Data Structure
|
|
@subsection The Data Structure for a Group
|
|
|
|
The functions and data structures for accessing the system group
|
|
database are declared in the header file @file{grp.h}.
|
|
@pindex grp.h
|
|
|
|
@comment grp.h
|
|
@comment POSIX.1
|
|
@deftp {Data Type} {struct group}
|
|
The @code{group} structure is used to hold information about an entry in
|
|
the system group database. It has at least the following members:
|
|
|
|
@table @code
|
|
@item char *gr_name
|
|
The name of the group.
|
|
|
|
@item gid_t gr_gid
|
|
The group ID of the group.
|
|
|
|
@item char **gr_mem
|
|
A vector of pointers to the names of users in the group. Each user name
|
|
is a null-terminated string, and the vector itself is terminated by a
|
|
null pointer.
|
|
@end table
|
|
@end deftp
|
|
|
|
@node Lookup Group
|
|
@subsection Looking Up One Group
|
|
@cindex converting group name to group ID
|
|
@cindex converting group ID to group name
|
|
|
|
You can search the group database for information about a specific
|
|
group using @code{getgrgid} or @code{getgrnam}. These functions are
|
|
declared in @file{grp.h}.
|
|
|
|
@comment grp.h
|
|
@comment POSIX.1
|
|
@deftypefun {struct group *} getgrgid (gid_t @var{gid})
|
|
This function returns a pointer to a statically-allocated structure
|
|
containing information about the group whose group ID is @var{gid}.
|
|
This structure may be overwritten by subsequent calls to
|
|
@code{getgrgid}.
|
|
|
|
A null pointer indicates there is no group with ID @var{gid}.
|
|
@end deftypefun
|
|
|
|
@comment grp.h
|
|
@comment POSIX.1c
|
|
@deftypefun int getgrgid_r (gid_t @var{gid}, struct group *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct group **@var{result})
|
|
This function is similar to @code{getgrgid} in that is returns
|
|
information about the group whose group ID is @var{gid}. But the result
|
|
is not placed in a static buffer. Instead the user supplied structure
|
|
pointed to by @var{result_buf} is filled with the information. The
|
|
first @var{buflen} bytes of the additional buffer pointed to by
|
|
@var{buffer} are used to contain additional information, normally
|
|
strings which are pointed to by the elements of the result structure.
|
|
|
|
If the return value is @code{0} the pointer returned in @var{result}
|
|
points to the record which contains the wanted data (i.e., @var{result}
|
|
contains the value @var{result_buf}). If the return value is non-zero
|
|
there is no group in the data base with group ID @var{gid} or the
|
|
buffer @var{buffer} is too small to contain all the needed information.
|
|
In the later case the global @var{errno} variable is set to
|
|
@code{ERANGE}.
|
|
@end deftypefun
|
|
|
|
@comment grp.h
|
|
@comment SVID, BSD
|
|
@deftypefun {struct group *} getgrnam (const char *@var{name})
|
|
This function returns a pointer to a statically-allocated structure
|
|
containing information about the group whose group name is @var{name}.
|
|
This structure may be overwritten by subsequent calls to
|
|
@code{getgrnam}.
|
|
|
|
A null pointer indicates there is no group named @var{name}.
|
|
@end deftypefun
|
|
|
|
@comment grp.h
|
|
@comment POSIX.1c
|
|
@deftypefun int getgrnam_r (const char *@var{name}, struct group *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct group **@var{result})
|
|
This function is similar to @code{getgrnam} in that is returns
|
|
information about the group whose group name is @var{name}. But the result
|
|
is not placed in a static buffer. Instead the user supplied structure
|
|
pointed to by @var{result_buf} is filled with the information. The
|
|
first @var{buflen} bytes of the additional buffer pointed to by
|
|
@var{buffer} are used to contain additional information, normally
|
|
strings which are pointed to by the elements of the result structure.
|
|
|
|
If the return value is @code{0} the pointer returned in @var{result}
|
|
points to the record which contains the wanted data (i.e., @var{result}
|
|
contains the value @var{result_buf}). If the return value is non-zero
|
|
there is no group in the data base with group name @var{name} or the
|
|
buffer @var{buffer} is too small to contain all the needed information.
|
|
In the later case the global @var{errno} variable is set to
|
|
@code{ERANGE}.
|
|
@end deftypefun
|
|
|
|
@node Scanning All Groups
|
|
@subsection Scanning the List of All Groups
|
|
@cindex scanning the group list
|
|
|
|
This section explains how a program can read the list of all groups in
|
|
the system, one group at a time. The functions described here are
|
|
declared in @file{grp.h}.
|
|
|
|
You can use the @code{fgetgrent} function to read group entries from a
|
|
particular file.
|
|
|
|
@comment grp.h
|
|
@comment SVID
|
|
@deftypefun {struct group *} fgetgrent (FILE *@var{stream})
|
|
The @code{fgetgrent} function reads the next entry from @var{stream}.
|
|
It returns a pointer to the entry. The structure is statically
|
|
allocated and is rewritten on subsequent calls to @code{fgetgrent}. You
|
|
must copy the contents of the structure if you wish to save the
|
|
information.
|
|
|
|
The stream must correspond to a file in the same format as the standard
|
|
group database file.
|
|
@end deftypefun
|
|
|
|
@comment grp.h
|
|
@comment GNU
|
|
@deftypefun int fgetgrent_r (FILE *@var{stream}, struct group *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct group **@var{result})
|
|
This function is similar to @code{fgetgrent} in that it reads the next
|
|
user entry from @var{stream}. But the result is returned in the
|
|
structure pointed to by @var{result_buf}. The
|
|
first @var{buflen} bytes of the additional buffer pointed to by
|
|
@var{buffer} are used to contain additional information, normally
|
|
strings which are pointed to by the elements of the result structure.
|
|
|
|
This stream must correspond to a file in the same format as the standard
|
|
group database file.
|
|
|
|
If the function returns zero @var{result} points to the structure with
|
|
the wanted data (normally this is in @var{result_buf}). If errors
|
|
occurred the return value is non-zero and @var{result} contains a null
|
|
pointer.
|
|
@end deftypefun
|
|
|
|
The way to scan all the entries in the group database is with
|
|
@code{setgrent}, @code{getgrent}, and @code{endgrent}.
|
|
|
|
@comment grp.h
|
|
@comment SVID, BSD
|
|
@deftypefun void setgrent (void)
|
|
This function initializes a stream for reading from the group data base.
|
|
You use this stream by calling @code{getgrent} or @code{getgrent_r}.
|
|
@end deftypefun
|
|
|
|
@comment grp.h
|
|
@comment SVID, BSD
|
|
@deftypefun {struct group *} getgrent (void)
|
|
The @code{getgrent} function reads the next entry from the stream
|
|
initialized by @code{setgrent}. It returns a pointer to the entry. The
|
|
structure is statically allocated and is rewritten on subsequent calls
|
|
to @code{getgrent}. You must copy the contents of the structure if you
|
|
wish to save the information.
|
|
@end deftypefun
|
|
|
|
@comment grp.h
|
|
@comment GNU
|
|
@deftypefun int getgrent_r (struct group *@var{result_buf}, char *@var{buffer}, size_t @var{buflen}, struct group **@var{result})
|
|
This function is similar to @code{getgrent} in that it returns the next
|
|
entry from the stream initialized by @code{setgrent}. But in contrast
|
|
to the @code{getgrent} function this function is reentrant since the
|
|
result is placed in the user supplied structure pointed to by
|
|
@var{result_buf}. Additional data, normally the strings pointed to by
|
|
the elements of the result structure, are placed in the additional
|
|
buffer or length @var{buflen} starting at @var{buffer}.
|
|
|
|
If the function returns zero @var{result} points to the structure with
|
|
the wanted data (normally this is in @var{result_buf}). If errors
|
|
occurred the return value is non-zero and @var{result} contains a null
|
|
pointer.
|
|
@end deftypefun
|
|
|
|
@comment grp.h
|
|
@comment SVID, BSD
|
|
@deftypefun void endgrent (void)
|
|
This function closes the internal stream used by @code{getgrent} or
|
|
@code{getgrent_r}.
|
|
@end deftypefun
|
|
|
|
@node Netgroup Database
|
|
@section Netgroup Database
|
|
|
|
@menu
|
|
* Netgroup Data:: Data in the Netgroup database and where
|
|
it comes from.
|
|
* Lookup Netgroup:: How to look for a particular netgroup.
|
|
* Netgroup Membership:: How to test for netgroup membership.
|
|
@end menu
|
|
|
|
@node Netgroup Data
|
|
@subsection Netgroup Data
|
|
|
|
@cindex Netgroup
|
|
Sometimes it is useful group users according to other criterias like the
|
|
ones used in the @xref{Group Database}. E.g., it is useful to associate
|
|
a certain group of users with a certain machine. On the other hand
|
|
grouping of host names is not supported so far.
|
|
|
|
In Sun Microsystems SunOS appeared a new kind of database, the netgroup
|
|
database. It allows to group hosts, users, and domain freely, giving
|
|
them individual names. More concrete: a netgroup is a list of triples
|
|
consisting of a host name, a user name, and a domain name, where any of
|
|
the entries can be a wildcard entry, matching all inputs. A last
|
|
possibility is that names of other netgroups can also be given in the
|
|
list specifying a netgroup. So one can construct arbitrary hierarchies
|
|
without loops.
|
|
|
|
Sun's implementation allows netgroups only for the @code{nis} or
|
|
@code{nisplus} service @pxref{Services in the NSS configuration}. The
|
|
implementation in the GNU C library has no such restriction. An entry
|
|
in either of the input services must have the following form:
|
|
|
|
@smallexample
|
|
@var{groupname} ( @var{groupname} | @code{(}@var{hostname}@code{,}@var{username}@code{,}@code{domainname}@code{)} )+
|
|
@end smallexample
|
|
|
|
Any of the fields in the triple can be empty which means anything
|
|
matches. While describing the functions we will see that the opposite
|
|
case is useful as well. I.e., there may be entries which will not
|
|
match any input. For entries like a name consisting of the single
|
|
character @code{-} shall be used.
|
|
|
|
@node Lookup Netgroup
|
|
@subsection Looking up one Netgroup
|
|
|
|
The lookup functions for netgroups are a bit different to all other
|
|
system database handling functions. Since a single netgroup can contain
|
|
many entries a two-step process is needed. First a single netgroup is
|
|
selected and then one can iterate over all entries in this netgroup.
|
|
These functions are declared in @file{netdb.h}.
|
|
|
|
@comment netdb.h
|
|
@deftypefun int setnetgrent (const char *@var{netgroup})
|
|
A call to this function initializes the internal state of the library to
|
|
allow following calls of the @code{getnetgrent} iterate over all entries
|
|
in the netgroup with name @var{netgroup}.
|
|
|
|
When the call is successful (i.e., when a netgroup with this name exist)
|
|
the return value is @code{1}. When the return value is @code{0} no
|
|
netgroup of this name is known or some other error occurred.
|
|
@end deftypefun
|
|
|
|
It is important to remember that there is only one single state for
|
|
iterating the netgroups. Even if the programmer uses the
|
|
@code{getnetgrent_r} function the result is not really reentrant since
|
|
always only one single netgroup at a time can be processed. If the
|
|
program needs to process more than one netgroup simultaneously she
|
|
must protect this by using external locking. This problem was
|
|
introduced in the original netgroups implementation in SunOS and since
|
|
we must stay compatible it is not possible to change this.
|
|
|
|
Some other functions also use the netgroups state. Currently these are
|
|
the @code{innetgr} function and parts of the implementation of the
|
|
@code{compat} service part of the NSS implementation.
|
|
|
|
@comment netdb.h
|
|
@deftypefun int getnetgrent (char **@var{hostp}, char **@var{userp}, char **@var{domainp})
|
|
This function returns the next unprocessed entry of the currently
|
|
selected netgroup. The string pointers, which addresses are passed in
|
|
the arguments @var{hostp}, @var{userp}, and @var{domainp}, will contain
|
|
after a successful call pointers to appropriate strings. If the string
|
|
in the next entry is empty the pointer has the value @code{NULL}.
|
|
The returned string pointers are only valid unless no of the netgroup
|
|
related functions are called.
|
|
|
|
The return value is @code{1} if the next entry was successfully read. A
|
|
value of @code{0} means no further entries exist or internal errors occurred.
|
|
@end deftypefun
|
|
|
|
@comment netdb.h
|
|
@deftypefun int getnetgrent_r (char **@var{hostp}, char **@var{userp}, char **@var{domainp}, char *@var{buffer}, int @var{buflen})
|
|
This function is similar to @code{getnetgrent} with only one exception:
|
|
the strings the three string pointers @var{hostp}, @var{userp}, and
|
|
@var{domainp} point to, are placed in the buffer of @var{buflen} bytes
|
|
starting at @var{buffer}. This means the returned values are valid
|
|
even after other netgroup related functions are called.
|
|
|
|
The return value is @code{1} if the next entry was successfully read and
|
|
the buffer contains enough room to place the strings in it. @code{0} is
|
|
returned in case no more entries are found, the buffer is too small, or
|
|
internal errors occurred.
|
|
|
|
This function is a GNU extension. The original implementation in the
|
|
SunOS libc does not provide this function.
|
|
@end deftypefun
|
|
|
|
@comment netdb.h
|
|
@deftypefun void endnetgrent (void)
|
|
This function free all buffers which were allocated to process the last
|
|
selected netgroup. As a result all string pointers returned by calls
|
|
to @code{getnetgrent} are invalid afterwards.
|
|
@end deftypefun
|
|
|
|
@node Netgroup Membership
|
|
@subsection Testing for Netgroup Membership
|
|
|
|
It is often not necessary to scan the whole netgroup since often the
|
|
only interesting question is whether a given entry is part of the
|
|
selected netgroup.
|
|
|
|
@comment netdb.h
|
|
@deftypefun int innetgr (const char *@var{netgroup}, const char *@var{host}, const char *@var{user}, const char *@var{domain})
|
|
This function tests whether the triple specified by the parameters
|
|
@var{hostp}, @var{userp}, and @var{domainp} is part of the netgroup
|
|
@var{netgroup}. Using this function has the advantage that
|
|
|
|
@enumerate
|
|
@item
|
|
no other netgroup function can use the global netgroup state since
|
|
internal locking is used and
|
|
@item
|
|
the function is implemented more efficiently than successive calls
|
|
to the other @code{set}/@code{get}/@code{endnetgrent} functions.
|
|
@end enumerate
|
|
|
|
Any of the pointers @var{hostp}, @var{userp}, and @var{domainp} can be
|
|
@code{NULL} which means any value is excepted in this position. This is
|
|
also true for the name @code{-} which should not match any other string
|
|
otherwise.
|
|
|
|
The return value is @code{1} if an entry matching the given triple is
|
|
found in the netgroup. The return value is @code{0} if the netgroup
|
|
itself is not found, the netgroup does not contain the triple or
|
|
internal errors occurred.
|
|
@end deftypefun
|
|
|
|
@node Database Example
|
|
@section User and Group Database Example
|
|
|
|
Here is an example program showing the use of the system database inquiry
|
|
functions. The program prints some information about the user running
|
|
the program.
|
|
|
|
@smallexample
|
|
@include db.c.texi
|
|
@end smallexample
|
|
|
|
Here is some output from this program:
|
|
|
|
@smallexample
|
|
I am Throckmorton Snurd.
|
|
My login name is snurd.
|
|
My uid is 31093.
|
|
My home directory is /home/fsg/snurd.
|
|
My default shell is /bin/sh.
|
|
My default group is guest (12).
|
|
The members of this group are:
|
|
friedman
|
|
tami
|
|
@end smallexample
|