mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-09 14:50:05 +00:00
Update.
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.
This commit is contained in:
parent
55c14926be
commit
0413b54c02
448
ChangeLog
448
ChangeLog
@ -1,3 +1,435 @@
|
||||
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.
|
||||
|
||||
1997-08-04 15:29 Ulrich Drepper <drepper@cygnus.com>
|
||||
|
||||
* locale/programs/localedef.c (main): Set bit in avail for those
|
||||
@ -44,7 +476,7 @@
|
||||
* sysdeps/unix/sysv/linux/bits/socket.h: Likewise.
|
||||
* sysdeps/unix/sysv/linux/mips/bits/socket.h: Likewise.
|
||||
|
||||
* stdio-common/printf_fp.c (__printf_fp): Correct rouding of number
|
||||
* stdio-common/printf_fp.c (__printf_fp): Correct rounding of numbers
|
||||
1.0 < x < 8.0.
|
||||
* stdio-common/tfformat.c: Add new tests for above bug.
|
||||
|
||||
@ -192,7 +624,7 @@
|
||||
* csu/defs.awk: Fix regexp for end and align.
|
||||
Patch by Klaus Espenlaub <kespenla@hydra.informatik.uni-ulm.de>.
|
||||
|
||||
* locale/programs/localedef.c (print_escaped): New function.
|
||||
* locale/programs/locale.c (print_escaped): New function.
|
||||
(show_info): Use print_escaped if strings can control unprintable
|
||||
characters.
|
||||
Patch by Jochen Hein <jochen.hein@delphi.central.de>.
|
||||
@ -710,7 +1142,7 @@
|
||||
|
||||
* time/africa: Update from tzdata1997g.
|
||||
* time/asia: Likewise.
|
||||
* time/australia: Likewise.
|
||||
* time/australasia: Likewise.
|
||||
* time/europe: Likewise.
|
||||
* time/iso3166.tab: Likewise.
|
||||
* time/zone.tab: Likewise.
|
||||
@ -960,7 +1392,7 @@
|
||||
* login/programs/utmpd.c:
|
||||
(main): Change handling of errors in opening the database.
|
||||
* login/programs/database.c:
|
||||
(open_database, synchronize_dtatabase, initialize_database):
|
||||
(open_database, synchronize_database, initialize_database):
|
||||
Properly handle errors.
|
||||
(get_mtime): Use fstat instead of stat. All callers changed.
|
||||
|
||||
@ -1127,7 +1559,7 @@
|
||||
* libio/strops.c: Correctly handle _IO_write_end.
|
||||
|
||||
* nss/libnss_files.map: Add __nss_netgroup_parseline.
|
||||
* nss/nss_files/files-netgroup.c (_nss_netgroup_parseline): Don't
|
||||
* nss/nss_files/files-netgrp.c (_nss_netgroup_parseline): Don't
|
||||
panic if setnetgrent wasn't called before, return error.
|
||||
Patch by Thorsten Kukuk <kukuk@uni-paderborn.de>.
|
||||
|
||||
@ -3325,7 +3757,7 @@
|
||||
|
||||
* libc.map: Add more symbols.
|
||||
|
||||
* Mwkerules (load-map-file): Currectly handle missing map file.
|
||||
* Makerules (load-map-file): Currectly handle missing map file.
|
||||
|
||||
1997-06-15 17:00 Philip Blundell <Philip.Blundell@pobox.com>
|
||||
|
||||
@ -3584,8 +4016,8 @@
|
||||
1997-06-12 12:45 Ulrich Drepper <drepper@cygnus.com>
|
||||
|
||||
* sysdeps/i386/fpu/__math.h (__M_SQRT2): Define here since we
|
||||
cannot rely on M_SQRT2 being defined. (log1p): Use __M_SQRT2 not
|
||||
M_SQRT2.
|
||||
cannot rely on M_SQRT2 being defined.
|
||||
(log1p): Use __M_SQRT2 not M_SQRT2.
|
||||
* math/math.h (_Mldbl): Define even if M_* constants are not
|
||||
defined.
|
||||
Reported by corsepiu@faw.uni-ulm.de.
|
||||
|
8
FAQ
8
FAQ
@ -618,7 +618,13 @@ invalid. I.e., an emulated FPU is for the libc as good as a real one.
|
||||
glibc 2.x?
|
||||
|
||||
[A20] {AJ} There's only support for glibc 2.0 in gcc 2.7.2.2 or later.
|
||||
For 2.7.2.2 you should use the following patch and configure for
|
||||
|
||||
gcc 2.7.2.2 has also a nasty bug. It installs its own version of
|
||||
assert.h into /usr/<machine>/include that is not compatible with
|
||||
glibc. Please remove this file - otherwise you get lots of problems
|
||||
with configure.
|
||||
|
||||
For 2.7.2.2 you should also use the following patch and configure for
|
||||
e.g. i486-linux.
|
||||
-----------------------------------------------------------------------
|
||||
--- configure Tue Feb 11 15:57:17 1997
|
||||
|
11
Makeconfig
11
Makeconfig
@ -149,6 +149,17 @@ ifeq ($(origin prefix),undefined) # ifndef would override explicit empty value.
|
||||
prefix = /usr/local
|
||||
endif
|
||||
|
||||
# Decide whether we shall build the programs or not. We always do this
|
||||
# unless the user tells us (in configparms) or we are building for a
|
||||
# standalone target.
|
||||
ifndef build-programs
|
||||
ifneq ($(config-os),none)
|
||||
build-programs=yes
|
||||
else
|
||||
build-programs=no
|
||||
endif
|
||||
endif
|
||||
|
||||
# Common prefix for machine-dependent installation directories.
|
||||
ifeq ($(origin exec_prefix),undefined)
|
||||
exec_prefix = $(prefix)
|
||||
|
2
Makefile
2
Makefile
@ -53,7 +53,7 @@ endif
|
||||
# These are the subdirectories containing the library source.
|
||||
subdirs = csu assert ctype db locale intl catgets math setjmp signal stdlib \
|
||||
stdio-common $(stdio) malloc string wcsmbs time dirent grp pwd \
|
||||
posix io termios resource misc login socket sysvipc gmon gnulib \
|
||||
posix io termios resource misc socket sysvipc gmon gnulib \
|
||||
wctype manual shadow md5-crypt nss $(sysdep-subdirs) po argp \
|
||||
$(add-ons) $(binfmt-subdir)
|
||||
export subdirs := $(subdirs) # Benign, useless in GNU make before 3.63.
|
||||
|
@ -426,9 +426,15 @@ extra-libs-left := $(extra-libs)
|
||||
include $(patsubst %,$(..)extra-lib.mk,$(extra-libs))
|
||||
endif
|
||||
|
||||
ifeq ($(build-programs),yes)
|
||||
+depfiles := $(strip $(sources:.c=.d) \
|
||||
$(patsubst %.o,%.d,$(filter %.o,$(extra-objs:.so=.o))) \
|
||||
$(addsuffix .d,$(others) $(tests) $(test-srcs)))
|
||||
else
|
||||
+depfiles := $(strip $(sources:.c=.d) \
|
||||
$(patsubst %.o,%.d,$(filter %.o,$(extra-objs:.so=.o))) \
|
||||
$(addsuffix .d,$(tests) $(test-srcs)))
|
||||
endif
|
||||
+depfiles := $(addprefix $(objpfx),\
|
||||
$(filter-out $(addsuffix .d,$(omit-deps)),\
|
||||
$(+depfiles)))
|
||||
|
14
PROJECTS
14
PROJECTS
@ -1,6 +1,6 @@
|
||||
Open jobs for finishing GNU libc:
|
||||
---------------------------------
|
||||
Status: April 1997
|
||||
Status: August 1997
|
||||
|
||||
If you have time and talent to take over any of the jobs below please
|
||||
contact <bug-glibc@prep.ai.mit.edu>
|
||||
@ -37,14 +37,6 @@ contact <bug-glibc@prep.ai.mit.edu>
|
||||
for the current status (of course better use a mirror of prep).
|
||||
|
||||
|
||||
[ 5] Write wordexp() function; this is described in POSIX.2, the
|
||||
header <wordexp.h> already exists.
|
||||
|
||||
Implementation idea: use some functions from bash.
|
||||
|
||||
**** Somebody is working on this. Help may or may not be appreciated.
|
||||
|
||||
|
||||
[ 6] Write `long double' versions of the math functions. This should be
|
||||
done in collaboration with the NetBSD and FreeBSD people.
|
||||
|
||||
@ -115,3 +107,7 @@ contact <bug-glibc@prep.ai.mit.edu>
|
||||
int foo __P ((int, int, int, int));
|
||||
|
||||
Blargh!
|
||||
|
||||
[16] Write an nss_hesiod module. The Hesiod daemon from the MIT Athena
|
||||
project should be available. The goal is to avoid the ugly NIS
|
||||
emulation interface and contacting the daemon directly.
|
||||
|
18
Rules
18
Rules
@ -38,9 +38,14 @@ export subdir := $(subdir)
|
||||
.PHONY: all
|
||||
all: objs lib others
|
||||
|
||||
ifeq ($(build-programs),yes)
|
||||
others: $(addprefix $(objpfx),$(extra-objs) \
|
||||
$(install-lib) $(install-bin) \
|
||||
$(install-rootsbin) $(install-sbin))
|
||||
else
|
||||
others: $(addprefix $(objpfx),$(extra-objs) \
|
||||
$(install-lib))
|
||||
endif
|
||||
|
||||
ifneq "$(findstring env,$(origin headers))" ""
|
||||
headers :=
|
||||
@ -81,19 +86,32 @@ common-generated := $(common-generated) dummy.o dummy.c empty.c empty.o
|
||||
# This makes all the auxiliary and test programs.
|
||||
|
||||
.PHONY: others tests
|
||||
ifeq ($(build-programs),yes)
|
||||
others: $(addprefix $(objpfx),$(others) $(extra-objs))
|
||||
else
|
||||
others: $(addprefix $(objpfx),$(extra-objs))
|
||||
endif
|
||||
ifeq ($(cross-compiling),yes)
|
||||
tests: $(addprefix $(objpfx),$(tests) $(test-srcs))
|
||||
else
|
||||
tests: $(tests:%=$(objpfx)%.out)
|
||||
endif
|
||||
|
||||
ifeq ($(build-programs),yes)
|
||||
ifneq "$(strip $(others) $(tests) $(test-srcs))" ""
|
||||
$(addprefix $(objpfx),$(others) $(tests) $(test-srcs)): %: %.o \
|
||||
$(sort $(filter $(common-objpfx)libc%,$(link-libc))) \
|
||||
$(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit)
|
||||
$(+link)
|
||||
endif
|
||||
else
|
||||
ifneq "$(strip $(tests) $(test-srcs))" ""
|
||||
$(addprefix $(objpfx),$(tests) $(test-srcs)): %: %.o \
|
||||
$(sort $(filter $(common-objpfx)libc%,$(link-libc))) \
|
||||
$(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit)
|
||||
$(+link)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq "$(strip $(tests) $(test-srcs))" ""
|
||||
# These are the implicit rules for making test outputs
|
||||
|
28
bits/utmp.h
28
bits/utmp.h
@ -17,7 +17,7 @@
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _UTMP_H
|
||||
#error "Never use <bits/utmp.h> directly; include <utmp.h> instead."
|
||||
# error "Never use <bits/utmp.h> directly; include <utmp.h> instead."
|
||||
#endif
|
||||
|
||||
|
||||
@ -33,21 +33,23 @@
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
struct lastlog {
|
||||
time_t ll_time;
|
||||
char ll_line[UT_LINESIZE];
|
||||
char ll_host[UT_HOSTSIZE];
|
||||
};
|
||||
struct lastlog
|
||||
{
|
||||
time_t ll_time;
|
||||
char ll_line[UT_LINESIZE];
|
||||
char ll_host[UT_HOSTSIZE];
|
||||
};
|
||||
|
||||
struct utmp {
|
||||
char ut_line[UT_LINESIZE];
|
||||
char ut_name[UT_NAMESIZE];
|
||||
char ut_host[UT_HOSTSIZE];
|
||||
long ut_time;
|
||||
};
|
||||
struct utmp
|
||||
{
|
||||
char ut_line[UT_LINESIZE];
|
||||
char ut_user[UT_NAMESIZE];
|
||||
#define ut_name ut_user
|
||||
char ut_host[UT_HOSTSIZE];
|
||||
long int ut_time;
|
||||
};
|
||||
|
||||
|
||||
#define _HAVE_UT_HOST 1 /* We have the ut_host field. */
|
||||
|
||||
|
||||
__END_DECLS
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>.
|
||||
|
||||
@ -183,7 +183,7 @@ __open_catalog (__nl_catd catalog, int with_path)
|
||||
catalog->file_ptr =
|
||||
(struct catalog_obj *) __mmap (NULL, st.st_size, PROT_READ,
|
||||
MAP_FILE|MAP_COPY|MAP_INHERIT, fd, 0);
|
||||
if (catalog->file_ptr != (struct catalog_obj *) -1)
|
||||
if (catalog->file_ptr != (struct catalog_obj *) MAP_FAILED)
|
||||
/* Tell the world we managed to mmap the file. */
|
||||
catalog->status = mmapped;
|
||||
else
|
||||
|
@ -282,7 +282,9 @@ init_hash(hashp, file, info)
|
||||
const char *file;
|
||||
HASHINFO *info;
|
||||
{
|
||||
#ifdef _STATBUF_ST_BLKSIZE
|
||||
struct stat statbuf;
|
||||
#endif
|
||||
int nelem;
|
||||
|
||||
nelem = 1;
|
||||
@ -299,14 +301,14 @@ init_hash(hashp, file, info)
|
||||
memset(hashp->BITMAPS, 0, sizeof (hashp->BITMAPS));
|
||||
|
||||
/* Fix bucket size to be optimal for file system */
|
||||
#ifdef _STATBUF_ST_BLKSIZE
|
||||
if (file != NULL) {
|
||||
if (stat(file, &statbuf))
|
||||
return (NULL);
|
||||
#if defined _STATBUF_ST_BLKSIZE
|
||||
hashp->BSIZE = statbuf.st_blksize;
|
||||
#endif
|
||||
hashp->BSHIFT = __hash_log2(hashp->BSIZE);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (info) {
|
||||
if (info->bsize) {
|
||||
|
@ -107,27 +107,51 @@ local_strdup (const char *s)
|
||||
return (char *) memcpy (new, s, len);
|
||||
}
|
||||
|
||||
/* Add `name' to the list of names for a particular shared object.
|
||||
`name' is expected to have been allocated with malloc and will
|
||||
be freed if the shared object already has this name.
|
||||
Returns false if the object already had this name. */
|
||||
static int
|
||||
add_name_to_object (struct link_map *l, char *name)
|
||||
{
|
||||
struct libname_list *lnp, *lastp;
|
||||
struct libname_list *newname;
|
||||
|
||||
if (name == NULL)
|
||||
{
|
||||
/* No more memory. */
|
||||
_dl_signal_error (ENOMEM, NULL, _("could not allocate name string"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
lastp = NULL;
|
||||
for (lnp = l->l_libname; lnp != NULL; lastp = lnp, lnp = lnp->next)
|
||||
if (strcmp (name, lnp->name) == 0)
|
||||
{
|
||||
free (name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
newname = malloc (sizeof *newname);
|
||||
if (newname == NULL)
|
||||
{
|
||||
/* No more memory. */
|
||||
_dl_signal_error (ENOMEM, name, _("cannot allocate name record"));
|
||||
free(name);
|
||||
return 0;
|
||||
}
|
||||
/* The object should have a libname set from _dl_new_object. */
|
||||
assert (lastp != NULL);
|
||||
|
||||
newname->name = name;
|
||||
newname->next = NULL;
|
||||
lastp->next = newname;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Implement cache for search path lookup. */
|
||||
#if 0
|
||||
/* This is how generated should look like. I'll remove this once I'm
|
||||
sure everything works correctly. */
|
||||
static struct r_search_path_elem rtld_search_dir1 =
|
||||
{ "/lib/", 5, unknown, 0, unknown, NULL };
|
||||
static struct r_search_path_elem rtld_search_dir2 =
|
||||
{ "/usr/lib/", 9, unknown, 0, unknown, &r ld_search_dir1 };
|
||||
|
||||
static struct r_search_path_elem *rtld_search_dirs[] =
|
||||
{
|
||||
&rtld_search_dir1,
|
||||
&rtld_search_dir2,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct r_search_path_elem *all_dirs = &rtld_search_dir2;
|
||||
#else
|
||||
# include "rtldtbl.h"
|
||||
#endif
|
||||
#include "rtldtbl.h"
|
||||
|
||||
static size_t max_dirnamelen;
|
||||
|
||||
@ -423,9 +447,10 @@ _dl_map_object_from_fd (char *name, int fd, char *realname,
|
||||
l->l_next->l_prev = l->l_prev;
|
||||
free (l);
|
||||
}
|
||||
free (name); /* XXX Can this be correct? --drepper */
|
||||
free (realname);
|
||||
_dl_signal_error (code, name, msg);
|
||||
free (name); /* Hmmm. Can this leak memory? Better
|
||||
than a segfault, anyway. */
|
||||
}
|
||||
|
||||
inline caddr_t map_segment (ElfW(Addr) mapstart, size_t len,
|
||||
@ -434,7 +459,7 @@ _dl_map_object_from_fd (char *name, int fd, char *realname,
|
||||
caddr_t mapat = __mmap ((caddr_t) mapstart, len, prot,
|
||||
fixed|MAP_COPY|MAP_FILE,
|
||||
fd, offset);
|
||||
if (mapat == (caddr_t) -1)
|
||||
if (mapat == MAP_FAILED)
|
||||
lose (errno, "failed to map segment from shared object");
|
||||
return mapat;
|
||||
}
|
||||
@ -451,7 +476,7 @@ _dl_map_object_from_fd (char *name, int fd, char *realname,
|
||||
mapping_size &= ~(_dl_pagesize - 1);
|
||||
result = __mmap (file_mapping, mapping_size, PROT_READ,
|
||||
MAP_COPY|MAP_FILE, fd, 0);
|
||||
if (result == (void *) -1)
|
||||
if (result == MAP_FAILED)
|
||||
lose (errno, "cannot map file data");
|
||||
file_mapping = result;
|
||||
}
|
||||
@ -467,7 +492,6 @@ _dl_map_object_from_fd (char *name, int fd, char *realname,
|
||||
for (l = _dl_loaded; l; l = l->l_next)
|
||||
if (! strcmp (realname, l->l_name))
|
||||
{
|
||||
struct libname_list *lnp, *lastp;
|
||||
/* The object is already loaded.
|
||||
Just bump its reference count and return it. */
|
||||
__close (fd);
|
||||
@ -475,26 +499,7 @@ _dl_map_object_from_fd (char *name, int fd, char *realname,
|
||||
/* If the name is not in the list of names for this object add
|
||||
it. */
|
||||
free (realname);
|
||||
lastp = NULL;
|
||||
for (lnp = l->l_libname; lnp != NULL; lastp = lnp, lnp = lnp->next)
|
||||
if (strcmp (name, lnp->name) == 0)
|
||||
{
|
||||
free (name);
|
||||
break;
|
||||
}
|
||||
if (lnp == NULL)
|
||||
{
|
||||
struct libname_list *newname = malloc (sizeof *newname);
|
||||
if (newname == NULL)
|
||||
/* No more memory. */
|
||||
lose (ENOMEM, "cannot allocate name record");
|
||||
/* The object should have a libname set. */
|
||||
assert (lastp != NULL);
|
||||
|
||||
newname->name = name;
|
||||
newname->next = NULL;
|
||||
lastp->next = newname;
|
||||
}
|
||||
add_name_to_object (l, name);
|
||||
++l->l_opencount;
|
||||
return l;
|
||||
}
|
||||
@ -701,7 +706,7 @@ _dl_map_object_from_fd (char *name, int fd, char *realname,
|
||||
mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage,
|
||||
c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
|
||||
ANONFD, 0);
|
||||
if (mapat == (caddr_t) -1)
|
||||
if (mapat == MAP_FAILED)
|
||||
lose (errno, "cannot map zero-fill pages");
|
||||
}
|
||||
}
|
||||
@ -876,6 +881,10 @@ _dl_map_object (struct link_map *loader, const char *name, int type,
|
||||
{
|
||||
/* The object is already loaded.
|
||||
Just bump its reference count and return it. */
|
||||
const char *soname = (const char *) (l->l_addr +
|
||||
l->l_info[DT_STRTAB]->d_un.d_ptr +
|
||||
l->l_info[DT_SONAME]->d_un.d_val);
|
||||
add_name_to_object (l, local_strdup (soname));
|
||||
++l->l_opencount;
|
||||
return l;
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ malloc (size_t n)
|
||||
assert (n <= _dl_pagesize);
|
||||
page = __mmap (0, _dl_pagesize, PROT_READ|PROT_WRITE,
|
||||
MAP_ANON|MAP_PRIVATE, _dl_zerofd, 0);
|
||||
assert (page != (caddr_t) -1);
|
||||
assert (page != MAP_FAILED);
|
||||
if (page != alloc_end)
|
||||
alloc_ptr = page;
|
||||
alloc_end = page + _dl_pagesize;
|
||||
|
@ -62,7 +62,7 @@ _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
|
||||
| MAP_FILE
|
||||
#endif
|
||||
, fd, 0);
|
||||
if (result == (void *) -1)
|
||||
if (result == MAP_FAILED)
|
||||
result = NULL;
|
||||
else
|
||||
*sizep = st.st_size;
|
||||
|
251
elf/dl-profile.c
251
elf/dl-profile.c
@ -50,29 +50,129 @@
|
||||
|
||||
This approach is very different from the normal profiling. We have
|
||||
to use the profiling data in exactly the way they are expected to
|
||||
be written to disk. */
|
||||
be written to disk. But the normal format used by gprof is not usable
|
||||
to do this. It is optimized for size. It writes the tags as single
|
||||
bytes but this means that the following 32/64 bit values are
|
||||
unaligned.
|
||||
|
||||
Therefore we use a new format. This will look like this
|
||||
|
||||
0 1 2 3 <- byte is 32 bit word
|
||||
0000 g m o n
|
||||
0004 *version* <- GMON_SHOBJ_VERSION
|
||||
0008 00 00 00 00
|
||||
000c 00 00 00 00
|
||||
0010 00 00 00 00
|
||||
|
||||
0014 *tag* <- GMON_TAG_TIME_HIST
|
||||
0018 ?? ?? ?? ??
|
||||
?? ?? ?? ?? <- 32/64 bit LowPC
|
||||
0018+A ?? ?? ?? ??
|
||||
?? ?? ?? ?? <- 32/64 bit HighPC
|
||||
0018+2*A *histsize*
|
||||
001c+2*A *profrate*
|
||||
0020+2*A s e c o
|
||||
0024+2*A n d s \0
|
||||
0028+2*A \0 \0 \0 \0
|
||||
002c+2*A \0 \0 \0
|
||||
002f+2*A s
|
||||
|
||||
0030+2*A ?? ?? ?? ?? <- Count data
|
||||
... ...
|
||||
0030+2*A+K ?? ?? ?? ??
|
||||
|
||||
0030+2*A+K *tag* <- GMON_TAG_CG_ARC
|
||||
0034+2*A+K *lastused*
|
||||
0038+2*A+K ?? ?? ?? ??
|
||||
?? ?? ?? ?? <- FromPC#1
|
||||
0038+3*A+K ?? ?? ?? ??
|
||||
?? ?? ?? ?? <- ToPC#1
|
||||
0038+4*A+K ?? ?? ?? ?? <- Count#1
|
||||
... ... ...
|
||||
0038+(2*(CN-1)+2)*A+(CN-1)*4+K ?? ?? ?? ??
|
||||
?? ?? ?? ?? <- FromPC#CGN
|
||||
0038+(2*(CN-1)+3)*A+(CN-1)*4+K ?? ?? ?? ??
|
||||
?? ?? ?? ?? <- ToPC#CGN
|
||||
0038+(2*CN+2)*A+(CN-1)*4+K ?? ?? ?? ?? <- Count#CGN
|
||||
|
||||
We put (for now? no basic block information in the file since this would
|
||||
introduce rase conditions among all the processes who want to write them.
|
||||
|
||||
`K' is the number of count entries which is computed as
|
||||
|
||||
textsize / HISTFRACTION
|
||||
|
||||
`CG' in the above table is the number of call graph arcs. Normally,
|
||||
the table is sparse and the profiling code writes out only the those
|
||||
entries which are really used in the program run. But since we must
|
||||
not extend this table (the profiling file) we'll keep them all here.
|
||||
So CN can be executed in advance as
|
||||
|
||||
MINARCS <= textsize*(ARCDENSITY/100) <= MAXARCS
|
||||
|
||||
Now the remaining question is: how to build the data structures we can
|
||||
work with from this data. We need the from set and must associate the
|
||||
froms with all the associated tos. We will do this by constructing this
|
||||
data structures at the program start. To do this we'll simply visit all
|
||||
entries in the call graph table and add it to the appropriate list. */
|
||||
|
||||
extern char *_strerror_internal __P ((int, char *buf, size_t));
|
||||
|
||||
extern int __profile_frequency __P ((void));
|
||||
|
||||
|
||||
static struct gmonparam param;
|
||||
|
||||
/* We define a special type to address the elements of the arc table.
|
||||
This is basically the `gmon_cg_arc_record' format but it includes
|
||||
the room for the tag and it uses real types. */
|
||||
struct here_cg_arc_record
|
||||
{
|
||||
char tag;
|
||||
uintptr_t from_pc __attribute__ ((packed));
|
||||
uintptr_t self_pc __attribute__ ((packed));
|
||||
uint32_t count __attribute__ ((packed));
|
||||
};
|
||||
uintptr_t from_pc;
|
||||
uintptr_t self_pc;
|
||||
uint32_t count;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static struct here_cg_arc_record *data;
|
||||
|
||||
/* This is the number of entry which have been incorporated in the toset. */
|
||||
static uint32_t narcs;
|
||||
/* This is a pointer to the object representing the number of entries
|
||||
currently in the mmaped file. At no point of time this has to be the
|
||||
same as NARCS. If it is equal all entries from the file are in our
|
||||
lists. */
|
||||
static uint32_t *narcsp;
|
||||
|
||||
/* Description of the currently profiled object. */
|
||||
static long int state;
|
||||
|
||||
static volatile uint16_t *kcount;
|
||||
static size_t kcountsize;
|
||||
|
||||
struct here_tostruct
|
||||
{
|
||||
struct here_cg_arc_record volatile *here;
|
||||
uint16_t link;
|
||||
};
|
||||
|
||||
static uint16_t *froms;
|
||||
static size_t fromssize;
|
||||
|
||||
static struct here_tostruct *tos;
|
||||
static size_t tossize;
|
||||
static size_t tolimit;
|
||||
static size_t toidx;
|
||||
|
||||
static uintptr_t lowpc;
|
||||
static uintptr_t highpc;
|
||||
static size_t textsize;
|
||||
static unsigned int hashfraction;
|
||||
static unsigned int log_hashfraction;
|
||||
|
||||
/* This is the information about the mmaped memory. */
|
||||
static struct gmon_hdr *addr;
|
||||
static off_t expected_size;
|
||||
|
||||
|
||||
/* Set up profiling data to profile object desribed by MAP. The output
|
||||
file is found (or created) in OUTPUT_DIR. */
|
||||
void
|
||||
_dl_start_profile (struct link_map *map, const char *output_dir)
|
||||
{
|
||||
@ -82,11 +182,10 @@ _dl_start_profile (struct link_map *map, const char *output_dir)
|
||||
const ElfW(Phdr) *ph;
|
||||
ElfW(Addr) mapstart = ~((ElfW(Addr)) 0);
|
||||
ElfW(Addr) mapend = 0;
|
||||
off_t expected_size;
|
||||
struct gmon_hdr gmon_hdr;
|
||||
struct gmon_hist_hdr hist_hdr;
|
||||
struct gmon_hdr *addr;
|
||||
char *hist;
|
||||
size_t idx;
|
||||
|
||||
/* Compute the size of the sections which contain program code. */
|
||||
for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
|
||||
@ -104,40 +203,41 @@ _dl_start_profile (struct link_map *map, const char *output_dir)
|
||||
|
||||
/* Now we can compute the size of the profiling data. This is done
|
||||
with the same formulars as in `monstartup' (see gmon.c). */
|
||||
param.state = GMON_PROF_OFF;
|
||||
param.lowpc = mapstart + map->l_addr;
|
||||
param.highpc = mapend + map->l_addr;
|
||||
param.textsize = mapend - mapstart;
|
||||
param.kcountsize = param.textsize / HISTFRACTION;
|
||||
param.hashfraction = HASHFRACTION;
|
||||
param.log_hashfraction = -1;
|
||||
state = GMON_PROF_OFF;
|
||||
lowpc = ROUNDDOWN (mapstart + map->l_addr,
|
||||
HISTFRACTION * sizeof(HISTCOUNTER));
|
||||
highpc = ROUNDUP (mapend + map->l_addr,
|
||||
HISTFRACTION * sizeof(HISTCOUNTER));
|
||||
textsize = highpc - lowpc;
|
||||
kcountsize = textsize / HISTFRACTION;
|
||||
hashfraction = HASHFRACTION;
|
||||
if ((HASHFRACTION & (HASHFRACTION - 1)) == 0)
|
||||
/* If HASHFRACTION is a power of two, mcount can use shifting
|
||||
instead of integer division. Precompute shift amount. */
|
||||
param.log_hashfraction = ffs (param.hashfraction
|
||||
* sizeof (*param.froms)) - 1;
|
||||
param.fromssize = param.textsize / HASHFRACTION;
|
||||
param.tolimit = param.textsize * ARCDENSITY / 100;
|
||||
if (param.tolimit < MINARCS)
|
||||
param.tolimit = MINARCS;
|
||||
if (param.tolimit > MAXARCS)
|
||||
param.tolimit = MAXARCS;
|
||||
param.tossize = param.tolimit * sizeof (struct tostruct);
|
||||
log_hashfraction = __builtin_ffs (hashfraction * sizeof (*froms)) - 1;
|
||||
else
|
||||
log_hashfraction = -1;
|
||||
fromssize = textsize / HASHFRACTION;
|
||||
tolimit = textsize * ARCDENSITY / 100;
|
||||
if (tolimit < MINARCS)
|
||||
tolimit = MINARCS;
|
||||
if (tolimit > MAXARCS)
|
||||
tolimit = MAXARCS;
|
||||
tossize = tolimit * sizeof (struct here_tostruct);
|
||||
|
||||
expected_size = (sizeof (struct gmon_hdr)
|
||||
+ 1 + sizeof (struct gmon_hist_hdr)
|
||||
+ ((1 + sizeof (struct gmon_cg_arc_record))
|
||||
* (param.fromssize / sizeof (*param.froms))));
|
||||
+ 4 + sizeof (struct gmon_hist_hdr) + kcountsize
|
||||
+ 4 + 4 + tossize * sizeof (struct here_cg_arc_record));
|
||||
|
||||
/* Create the gmon_hdr we expect or write. */
|
||||
memset (&gmon_hdr, '\0', sizeof (struct gmon_hdr));
|
||||
memcpy (&gmon_hdr.cookie[0], GMON_MAGIC, sizeof (gmon_hdr.cookie));
|
||||
*(int32_t *) gmon_hdr.version = GMON_VERSION;
|
||||
*(int32_t *) gmon_hdr.version = GMON_SHOBJ_VERSION;
|
||||
|
||||
/* Create the hist_hdr we expect or write. */
|
||||
*(char **) hist_hdr.low_pc = (char *) mapstart;
|
||||
*(char **) hist_hdr.high_pc = (char *) mapend;
|
||||
*(int32_t *) hist_hdr.hist_size = param.kcountsize / sizeof (HISTCOUNTER);
|
||||
*(int32_t *) hist_hdr.hist_size = kcountsize / sizeof (HISTCOUNTER);
|
||||
*(int32_t *) hist_hdr.prof_rate = __profile_frequency ();
|
||||
strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen));
|
||||
hist_hdr.dimen_abbrev = 's';
|
||||
@ -193,15 +293,19 @@ _dl_start_profile (struct link_map *map, const char *output_dir)
|
||||
{
|
||||
__close (fd);
|
||||
wrong_format:
|
||||
|
||||
if (addr != NULL)
|
||||
__munmap ((void *) addr, expected_size);
|
||||
|
||||
_dl_sysdep_error (filename,
|
||||
": file is no correct profile data file for `",
|
||||
_dl_profile, "'\n", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
addr = (void *) __mmap (NULL, expected_size, PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED|MAP_FILE, fd, 0);
|
||||
if (addr == (void *) -1)
|
||||
addr = (struct gmon_hdr *) __mmap (NULL, expected_size, PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED|MAP_FILE, fd, 0);
|
||||
if (addr == (struct gmon_hdr *) MAP_FAILED)
|
||||
{
|
||||
char buf[400];
|
||||
int errnum = errno;
|
||||
@ -217,54 +321,97 @@ _dl_start_profile (struct link_map *map, const char *output_dir)
|
||||
|
||||
/* Pointer to data after the header. */
|
||||
hist = (char *) (addr + 1);
|
||||
kcount = (uint16_t *) ((char *) hist + sizeof (uint32_t)
|
||||
+ sizeof (struct gmon_hist_hdr));
|
||||
|
||||
/* Compute pointer to array of the arc information. */
|
||||
data = (struct here_cg_arc_record *) (hist + 1
|
||||
+ sizeof (struct gmon_hist_hdr));
|
||||
data = (struct here_cg_arc_record *) ((char *) kcount + kcountsize
|
||||
+ 2 * sizeof (uint32_t));
|
||||
narcsp = (uint32_t *) (hist + sizeof (uint32_t)
|
||||
+ sizeof (struct gmon_hist_hdr) + sizeof (uint32_t));
|
||||
|
||||
if (st.st_size == 0)
|
||||
{
|
||||
/* Create the signature. */
|
||||
size_t cnt;
|
||||
|
||||
memcpy (addr, &gmon_hdr, sizeof (struct gmon_hdr));
|
||||
|
||||
*hist = GMON_TAG_TIME_HIST;
|
||||
memcpy (hist + 1, &hist_hdr, sizeof (struct gmon_hist_hdr));
|
||||
*(uint32_t *) hist = GMON_TAG_TIME_HIST;
|
||||
memcpy (hist + sizeof (uint32_t), &hist_hdr,
|
||||
sizeof (struct gmon_hist_hdr));
|
||||
|
||||
for (cnt = 0; cnt < param.fromssize / sizeof (*param.froms); ++cnt)
|
||||
data[cnt].tag = GMON_TAG_CG_ARC;
|
||||
*(uint32_t *) (hist + sizeof (uint32_t) + sizeof (struct gmon_hist_hdr)
|
||||
+ kcountsize) = GMON_TAG_CG_ARC;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Test the signature in the file. */
|
||||
if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0
|
||||
|| *hist != GMON_TAG_TIME_HIST
|
||||
|| memcmp (hist + 1, &hist_hdr, sizeof (struct gmon_hist_hdr)) != 0)
|
||||
|| *(uint32_t *) hist != GMON_TAG_TIME_HIST
|
||||
|| memcmp (hist + sizeof (uint32_t), &hist_hdr,
|
||||
sizeof (struct gmon_hist_hdr)) != 0
|
||||
|| (*(uint32_t *) (hist + sizeof (uint32_t)
|
||||
+ sizeof (struct gmon_hist_hdr) + kcountsize)
|
||||
!= GMON_TAG_CG_ARC))
|
||||
goto wrong_format;
|
||||
}
|
||||
|
||||
/* Allocate memory for the froms data and the pointer to the tos records. */
|
||||
froms = (uint16_t *) calloc (fromssize + tossize, 1);
|
||||
if (froms == NULL)
|
||||
{
|
||||
__munmap ((void *) addr, expected_size);
|
||||
_dl_sysdep_fatal ("Out of memory while initializing profiler", NULL);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
tos = (struct here_tostruct *) ((char *) froms + fromssize);
|
||||
toidx = 0;
|
||||
|
||||
/* Now we have to process all the arc count entries. BTW: it is
|
||||
not critical whether the *NARCSP value changes meanwhile. Before
|
||||
we enter a new entry in to toset we will check that everything is
|
||||
available in TOS. This happens in _dl_mcount.
|
||||
|
||||
Loading the entries in reverse order should help to get the most
|
||||
frequently used entries at the front of the list. */
|
||||
for (idx = narcs = *narcsp; idx > 0; )
|
||||
{
|
||||
size_t from_index;
|
||||
size_t newtoidx;
|
||||
--idx;
|
||||
from_index = ((data[idx].from_pc - lowpc)
|
||||
/ (hashfraction * sizeof (*froms)));
|
||||
newtoidx = toidx++;
|
||||
tos[newtoidx].here = &data[idx];
|
||||
tos[newtoidx].link = froms[from_index];
|
||||
froms[from_index] = newtoidx;
|
||||
}
|
||||
|
||||
/* Turn on profiling. */
|
||||
param.state = GMON_PROF_ON;
|
||||
state = GMON_PROF_ON;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc)
|
||||
{
|
||||
if (param.state != GMON_PROF_ON)
|
||||
if (state != GMON_PROF_ON)
|
||||
return;
|
||||
param.state = GMON_PROF_BUSY;
|
||||
state = GMON_PROF_BUSY;
|
||||
|
||||
/* Compute relative addresses. The shared object can be loaded at
|
||||
any address. The value of frompc could be anything. We cannot
|
||||
restrict it in any way, just set to a fixed value (0) in case it
|
||||
is outside the allowed range. These calls show up as calls from
|
||||
<external> in the gprof output. */
|
||||
frompc -= param.lowpc;
|
||||
if (frompc >= param.textsize)
|
||||
frompc -= lowpc;
|
||||
if (frompc >= textsize)
|
||||
frompc = 0;
|
||||
selfpc -= param.lowpc;
|
||||
selfpc -= lowpc;
|
||||
if (selfpc >= textsize)
|
||||
goto done;
|
||||
|
||||
param.state = GMON_PROF_ON;
|
||||
|
||||
done:
|
||||
state = GMON_PROF_ON;
|
||||
}
|
||||
|
35
gmon/gmon.c
35
gmon/gmon.c
@ -126,13 +126,12 @@ __monstartup (lowpc, highpc)
|
||||
p->tolimit = MAXARCS;
|
||||
p->tossize = p->tolimit * sizeof(struct tostruct);
|
||||
|
||||
cp = malloc (p->kcountsize + p->fromssize + p->tossize);
|
||||
cp = calloc (p->kcountsize + p->fromssize + p->tossize, 1);
|
||||
if (! cp)
|
||||
{
|
||||
ERR(_("monstartup: out of memory\n"));
|
||||
return;
|
||||
}
|
||||
memset (cp, '\0', p->kcountsize + p->fromssize + p->tossize);
|
||||
p->tos = (struct tostruct *)cp;
|
||||
cp += p->tossize;
|
||||
p->kcount = (u_short *)cp;
|
||||
@ -296,13 +295,12 @@ write_bb_counts (fd)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_mcleanup ()
|
||||
static void
|
||||
write_gmon (void)
|
||||
{
|
||||
struct gmon_hdr ghdr __attribute__ ((aligned (__alignof__ (int))));
|
||||
int fd;
|
||||
|
||||
__moncontrol (0);
|
||||
fd = __open ("gmon.out", O_CREAT|O_TRUNC|O_WRONLY, 0666);
|
||||
if (fd < 0)
|
||||
{
|
||||
@ -328,8 +326,29 @@ _mcleanup ()
|
||||
/* write basic-block execution counts: */
|
||||
write_bb_counts (fd);
|
||||
|
||||
/* free the memory. */
|
||||
free (_gmonparam.tos);
|
||||
|
||||
__close (fd);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__write_profiling (void)
|
||||
{
|
||||
int save = _gmonparam.state;
|
||||
_gmonparam.state = GMON_PROF_OFF;
|
||||
if (save == GMON_PROF_ON)
|
||||
write_gmon ();
|
||||
_gmonparam.state = save;
|
||||
}
|
||||
weak_alias (__write_profiling, write_profiling)
|
||||
|
||||
|
||||
void
|
||||
_mcleanup (void)
|
||||
{
|
||||
__moncontrol (0);
|
||||
|
||||
write_gmon ();
|
||||
|
||||
/* free the memory. */
|
||||
free (_gmonparam.tos);
|
||||
}
|
||||
|
@ -175,6 +175,10 @@ extern void monstartup __P ((u_long __lowpc, u_long __highpc));
|
||||
/* Clean up profiling and write out gmon.out. */
|
||||
extern void _mcleanup __P ((void));
|
||||
|
||||
/* Write current profiling data to file. */
|
||||
extern void __write_profiling __P ((void));
|
||||
extern void write_profiling __P ((void));
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* sys/gmon.h */
|
||||
|
@ -33,6 +33,9 @@
|
||||
#define GMON_MAGIC "gmon" /* magic cookie */
|
||||
#define GMON_VERSION 1 /* version number */
|
||||
|
||||
/* For profiling shared object we need a new format. */
|
||||
#define GMON_SHOBJ_VERSION 0x1ffff
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/*
|
||||
|
@ -46,7 +46,7 @@ routines := htonl htons \
|
||||
getaliasent_r getaliasent getaliasname getaliasname_r \
|
||||
in6_addr getnameinfo if_index
|
||||
|
||||
tests := htontest test_ifindex
|
||||
tests := htontest test_ifindex tst-ntoa
|
||||
|
||||
# No warnings about losing BSD code.
|
||||
CFLAGS-rcmd.c = -w
|
||||
|
@ -80,7 +80,7 @@ struct hostent *_addr2hostname_hosts (const char *, int, int);
|
||||
static const char *
|
||||
nrl_domainname (void)
|
||||
{
|
||||
static const char *domain = NULL;
|
||||
static char *domain = NULL;
|
||||
static int first = 1;
|
||||
|
||||
if (first)
|
||||
|
@ -43,7 +43,7 @@ static void free_key_mem (void *mem);
|
||||
char *
|
||||
inet_ntoa (struct in_addr in)
|
||||
{
|
||||
__libc_once_define (once);
|
||||
__libc_once_define (static, once);
|
||||
char *buffer;
|
||||
unsigned char *bytes;
|
||||
|
||||
@ -51,20 +51,22 @@ inet_ntoa (struct in_addr in)
|
||||
__libc_once (once, init);
|
||||
|
||||
if (static_buf != NULL)
|
||||
return static_buf;
|
||||
|
||||
/* We don't use the static buffer and so we have a key. Use it to
|
||||
get the thread-specific buffer. */
|
||||
buffer = __libc_getspecific (key);
|
||||
if (buffer == NULL)
|
||||
buffer = static_buf;
|
||||
else
|
||||
{
|
||||
/* No buffer allocated so far. */
|
||||
buffer = malloc (18);
|
||||
/* We don't use the static buffer and so we have a key. Use it
|
||||
to get the thread-specific buffer. */
|
||||
buffer = __libc_getspecific (key);
|
||||
if (buffer == NULL)
|
||||
/* No more memory available. We use the static buffer. */
|
||||
buffer = local_buf;
|
||||
else
|
||||
__libc_setspecific (key, buffer);
|
||||
{
|
||||
/* No buffer allocated so far. */
|
||||
buffer = malloc (18);
|
||||
if (buffer == NULL)
|
||||
/* No more memory available. We use the static buffer. */
|
||||
buffer = local_buf;
|
||||
else
|
||||
__libc_setspecific (key, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
bytes = (unsigned char *) ∈
|
||||
@ -91,4 +93,5 @@ static void
|
||||
free_key_mem (void *mem)
|
||||
{
|
||||
free (mem);
|
||||
__libc_setspecific (key, NULL);
|
||||
}
|
||||
|
36
inet/tst-ntoa.c
Normal file
36
inet/tst-ntoa.c
Normal file
@ -0,0 +1,36 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
|
||||
static int
|
||||
test (unsigned int inaddr, const char *expected)
|
||||
{
|
||||
struct in_addr addr;
|
||||
char *res;
|
||||
int fail;
|
||||
|
||||
addr.s_addr = htonl (inaddr);
|
||||
res = inet_ntoa (addr);
|
||||
fail = strcmp (res, expected);
|
||||
|
||||
printf ("%#010x -> \"%s\" -> %s%s\n", inaddr, res,
|
||||
fail ? "fail, expected" : "ok", fail ? expected : "");
|
||||
|
||||
return fail;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
result |= test (INADDR_LOOPBACK, "127.0.0.1");
|
||||
result |= test (INADDR_BROADCAST, "255.255.255.255");
|
||||
result |= test (INADDR_ANY, "0.0.0.0");
|
||||
result |= test (0xc0060746, "192.6.7.70");
|
||||
|
||||
return result;
|
||||
}
|
10
io/ftw.c
10
io/ftw.c
@ -101,8 +101,14 @@ static int
|
||||
object_compare (const void *p1, const void *p2)
|
||||
{
|
||||
/* We don't need a sophisticated and useful comparison. We are only
|
||||
interested in equality. */
|
||||
return memcmp (p1, p2, sizeof (struct known_object));
|
||||
interested in equality. However, we must be careful not to
|
||||
accidentally compare `holes' in the structure. */
|
||||
const struct known_object *kp1 = p1, *kp2 = p2;
|
||||
int cmp1;
|
||||
cmp1 = memcmp(&kp1->dev, &kp2->dev, sizeof(kp1->dev));
|
||||
if (cmp1 != 0)
|
||||
return cmp1;
|
||||
return memcmp (&kp1->ino, &kp2->ino, sizeof (kp1->ino));
|
||||
}
|
||||
|
||||
|
||||
|
30
libc.map
30
libc.map
@ -18,7 +18,9 @@ GLIBC_2.0 {
|
||||
|
||||
# functions with special/multiple interfaces
|
||||
__sigsetjmp; _setjmp; __sigaddset; __sigdelset; __sigismember;
|
||||
__sysv_signal; __bsd_getpgrp; _longjmp;
|
||||
__sysv_signal; __bsd_getpgrp; _longjmp; _mcount;
|
||||
__divqu; __remqu; __divqs; __remqs; __divlu; __remlu; __divls;
|
||||
__remls;
|
||||
|
||||
# functions which have an additional interface since they are
|
||||
# are cancelable.
|
||||
@ -179,7 +181,8 @@ GLIBC_2.0 {
|
||||
get_kernel_syms; get_myaddress; get_nprocs; get_nprocs_conf;
|
||||
get_phys_pages; getaddrinfo; getaliasbyname; getaliasbyname_r;
|
||||
getaliasent; getaliasent_r; getc; getc_unlocked; getchar;
|
||||
getchar_unlocked; getcwd; getdate; getdate_r; getdelim; getdirentries;
|
||||
getchar_unlocked; getcontext;
|
||||
getcwd; getdate; getdate_r; getdelim; getdirentries;
|
||||
getdomainname; getdtablesize; getegid; getenv; geteuid; getfsent;
|
||||
getfsfile; getfsspec; getgid; getgrent; getgrent_r; getgrgid;
|
||||
getgrgid_r; getgrnam; getgrnam_r; getgroups; gethostbyaddr;
|
||||
@ -193,6 +196,7 @@ GLIBC_2.0 {
|
||||
getprotobyname; getprotobyname_r; getprotobynumber;
|
||||
getprotobynumber_r; getprotoent; getprotoent_r; getpublickey; getpw;
|
||||
getpwent; getpwent_r; getpwnam; getpwnam_r; getpwuid; getpwuid_r;
|
||||
getresgid; getresuid;
|
||||
getrlimit; getrpcbyname; getrpcbyname_r; getrpcbynumber;
|
||||
getrpcbynumber_r; getrpcent; getrpcent_r; getrpcport; getrusage; gets;
|
||||
getsecretkey; getservbyname; getservbyname_r; getservbyport;
|
||||
@ -200,14 +204,15 @@ GLIBC_2.0 {
|
||||
getsockopt; getspent; getspent_r; getspnam; getspnam_r; getsubopt;
|
||||
gettext; gettimeofday; getttyent; getttynam; getuid; getusershell;
|
||||
getutent; getutent_r; getutid; getutid_r; getutline; getutline_r;
|
||||
getutxent; getw; getwd; glob; glob_pattern_p; globfree; gmtime;
|
||||
gmtime_r; group_member; gsignal; gtty;
|
||||
getutxent; getutxid; getutxline; getw; getwd; glob; glob_pattern_p;
|
||||
globfree; gmtime; gmtime_r; group_member; gsignal; gtty;
|
||||
|
||||
# h*
|
||||
hasmntopt; hcreate; hcreate_r; hdestroy; hdestroy_r; herror;
|
||||
host2netname; hsearch; hsearch_r; hstrerror; htonl; htons;
|
||||
|
||||
# i*
|
||||
ieee_get_fp_control; ieee_set_fp_control;
|
||||
if_freenameindex; if_indextoname; if_nameindex; if_nametoindex; index;
|
||||
inet6_isipv4mapped; inet_addr; inet_aton; inet_lnaof; inet_makeaddr;
|
||||
inet_netof; inet_network; inet_nsap_addr; inet_nsap_ntoa; inet_ntoa;
|
||||
@ -254,7 +259,7 @@ GLIBC_2.0 {
|
||||
msgsnd; msync; mtrace; munlock; munlockall; munmap; muntrace;
|
||||
|
||||
# n*
|
||||
nanosleep; netname2host; netname2user; nftw; nice; nl_langinfo;
|
||||
nanosleep; netname2host; netname2user; nftw; nfsservctl; nice; nl_langinfo;
|
||||
nrand48; nrand48_r; ntohl; ntohs;
|
||||
|
||||
# o*
|
||||
@ -262,7 +267,8 @@ GLIBC_2.0 {
|
||||
open_memstream; opendir; openlog;
|
||||
|
||||
# p*
|
||||
parse_printf_format; passwd2des; pathconf; pause; pclose; perror;
|
||||
parse_printf_format; passwd2des; pathconf; pause; pciconfig_read;
|
||||
pciconfig_write; pclose; perror;
|
||||
personality; pipe; pmap_getmaps; pmap_getport; pmap_rmtcall; pmap_set;
|
||||
pmap_unset; poll; popen; printf; printf_size; printf_size_info;
|
||||
profil; profil_counter; pselect; psignal;
|
||||
@ -287,7 +293,7 @@ GLIBC_2.0 {
|
||||
pututxline; putw; pvalloc;
|
||||
|
||||
# q*
|
||||
qecvt; qecvt_r; qfcvt; qfcvt_r; qgcvt; qsort; quotactl;
|
||||
qecvt; qecvt_r; query_module; qfcvt; qfcvt_r; qgcvt; qsort; quotactl;
|
||||
|
||||
# r*
|
||||
raise; rand; rand_r; random; random_r; rcmd;
|
||||
@ -310,11 +316,13 @@ GLIBC_2.0 {
|
||||
|
||||
seed48; seed48_r; seekdir; select;
|
||||
semctl; semget; semop; send; sendmsg; sendto; setaliasent; setbuf;
|
||||
setbuffer; setdomainname; setegid; setenv; seteuid; setfsent;
|
||||
setbuffer; setcontext;
|
||||
setdomainname; setegid; setenv; seteuid; setfsent;
|
||||
setfsgid; setfsuid; setgid; setgrent; setgroups; sethostent;
|
||||
sethostid; sethostname; setitimer; setjmp; setlinebuf; setlocale;
|
||||
setlogin; setlogmask; setmntent; setnetent; setnetgrent; setpgid;
|
||||
setpgrp; setpriority; setprotoent; setpwent; setregid; setreuid;
|
||||
setpgrp; setpriority; setprotoent; setpwent; setregid; setresgid;
|
||||
setresuid; setreuid;
|
||||
setrlimit; setrpcent; setservent; setsid; setsockopt; setspent;
|
||||
setstate; setstate_r; settimeofday; setttyent; setuid; setusershell;
|
||||
setutent; setutxent; setvbuf; sgetspent; sgetspent_r; shmat; shmctl;
|
||||
@ -342,7 +350,7 @@ GLIBC_2.0 {
|
||||
svcudp_bufcreate; svcudp_create; svcudp_enablecache;
|
||||
|
||||
swab; swapoff; swapon; symlink; sync;
|
||||
syscall; sysconf; sysctl; sysinfo; syslog;
|
||||
syscall; sysconf; sysctl; sysinfo; syslog; sysmips;
|
||||
system;
|
||||
|
||||
# t*
|
||||
@ -389,7 +397,7 @@ GLIBC_2.0 {
|
||||
xdr_keybuf; xdr_keystatus; xdr_long; xdr_netnamestr; xdr_netobj;
|
||||
xdr_opaque; xdr_opaque_auth; xdr_pmap; xdr_pmaplist; xdr_pointer;
|
||||
xdr_reference; xdr_rejected_reply; xdr_replymsg; xdr_rmtcall_args;
|
||||
xdr_rmtcallres; xdr_short; xdr_string; xdr_u_char; xdr_u_int;
|
||||
xdr_rmtcallres; xdr_short; xdr_sizeof; xdr_string; xdr_u_char; xdr_u_int;
|
||||
xdr_u_long; xdr_u_short; xdr_union; xdr_unixcred; xdr_vector;
|
||||
xdr_void; xdr_wrapstring; xdrmem_create; xdrrec_create;
|
||||
xdrrec_endofrecord; xdrrec_eof; xdrrec_skiprecord; xdrstdio_create;
|
||||
|
@ -127,7 +127,7 @@ _nl_load_locale (struct loaded_l10nfile *file, int category)
|
||||
#endif
|
||||
filedata = (void *) __mmap ((caddr_t) 0, st.st_size, PROT_READ,
|
||||
MAP_FILE|MAP_COPY|MAP_INHERIT, fd, 0);
|
||||
if (filedata == (void *) -1)
|
||||
if (filedata == MAP_FAILED)
|
||||
{
|
||||
if (errno == ENOSYS)
|
||||
{
|
||||
|
@ -279,7 +279,7 @@ cannot `stat' locale file `%s'"),
|
||||
localedef->categories[cat].generic
|
||||
= mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
|
||||
if (localedef->categories[cat].generic == (void *) -1)
|
||||
if (localedef->categories[cat].generic == MAP_FAILED)
|
||||
{
|
||||
size_t left = st.st_size;
|
||||
void *read_ptr;
|
||||
|
@ -18,20 +18,20 @@
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <bits/libc-lock.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <utmp.h>
|
||||
|
||||
#include "utmp-private.h"
|
||||
|
||||
|
||||
/* The various backends we have. */
|
||||
static int getutent_r_unknown (struct utmp *buffer, struct utmp **result);
|
||||
static struct utmp *pututline_unknown (const struct utmp *data);
|
||||
/* Functions defined here. */
|
||||
static int setutent_unknown (void);
|
||||
static int getutent_r_unknown (struct utmp *buffer, struct utmp **result);
|
||||
static int getutid_r_unknown (const struct utmp *line, struct utmp *buffer,
|
||||
struct utmp **result);
|
||||
static int getutline_r_unknown (const struct utmp *id, struct utmp *buffer,
|
||||
struct utmp **result);
|
||||
static struct utmp *pututline_unknown (const struct utmp *data);
|
||||
static void endutent_unknown (void);
|
||||
|
||||
/* Initial Jump table. */
|
||||
@ -39,8 +39,8 @@ struct utfuncs __libc_utmp_unknown_functions =
|
||||
{
|
||||
setutent_unknown,
|
||||
getutent_r_unknown,
|
||||
NULL,
|
||||
NULL,
|
||||
getutid_r_unknown,
|
||||
getutline_r_unknown,
|
||||
pututline_unknown,
|
||||
endutent_unknown,
|
||||
NULL
|
||||
@ -53,32 +53,6 @@ struct utfuncs *__libc_utmp_jump_table = &__libc_utmp_unknown_functions;
|
||||
__libc_lock_define_initialized (, __libc_utmp_lock)
|
||||
|
||||
|
||||
void
|
||||
__setutent (void)
|
||||
{
|
||||
__libc_lock_lock (__libc_utmp_lock);
|
||||
|
||||
(*__libc_utmp_jump_table->setutent) ();
|
||||
|
||||
__libc_lock_unlock (__libc_utmp_lock);
|
||||
}
|
||||
weak_alias (__setutent, setutent)
|
||||
weak_alias (__setutent, setutxent)
|
||||
|
||||
|
||||
void
|
||||
__endutent (void)
|
||||
{
|
||||
__libc_lock_lock (__libc_utmp_lock);
|
||||
|
||||
(*__libc_utmp_jump_table->endutent) ();
|
||||
|
||||
__libc_lock_unlock (__libc_utmp_lock);
|
||||
}
|
||||
weak_alias (__endutent, endutent)
|
||||
weak_alias (__endutent, endutxent)
|
||||
|
||||
|
||||
static int
|
||||
setutent_unknown (void)
|
||||
{
|
||||
@ -91,20 +65,87 @@ setutent_unknown (void)
|
||||
else
|
||||
{
|
||||
result = (*__libc_utmp_file_functions.setutent) ();
|
||||
__libc_utmp_jump_table = &__libc_utmp_file_functions;
|
||||
if (result)
|
||||
__libc_utmp_jump_table = &__libc_utmp_file_functions;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
getutent_r_unknown (struct utmp *buffer, struct utmp **result)
|
||||
{
|
||||
/* The backend was not yet initialized. */
|
||||
if (setutent_unknown ())
|
||||
return (*__libc_utmp_jump_table->getutent_r) (buffer, result);
|
||||
|
||||
/* Not available. */
|
||||
*result = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
getutid_r_unknown (const struct utmp *id, struct utmp *buffer,
|
||||
struct utmp **result)
|
||||
{
|
||||
/* The backend was not yet initialized. */
|
||||
if (setutent_unknown ())
|
||||
return (*__libc_utmp_jump_table->getutid_r) (id, buffer, result);
|
||||
|
||||
/* Not available. */
|
||||
*result = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
getutline_r_unknown (const struct utmp *line, struct utmp *buffer,
|
||||
struct utmp **result)
|
||||
{
|
||||
/* The backend was not yet initialized. */
|
||||
if (setutent_unknown ())
|
||||
return (*__libc_utmp_jump_table->getutline_r) (line, buffer, result);
|
||||
|
||||
/* Not available. */
|
||||
*result = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static struct utmp *
|
||||
pututline_unknown (const struct utmp *data)
|
||||
{
|
||||
/* The backend was not yet initialized. */
|
||||
if (setutent_unknown ())
|
||||
return (*__libc_utmp_jump_table->pututline) (data);
|
||||
|
||||
/* Not available. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
endutent_unknown (void)
|
||||
{
|
||||
/* Huh, how do we came here? Nothing to do. */
|
||||
/* Nothing to do. */
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__setutent (void)
|
||||
{
|
||||
__libc_lock_lock (__libc_utmp_lock);
|
||||
|
||||
(*__libc_utmp_jump_table->setutent) ();
|
||||
|
||||
__libc_lock_unlock (__libc_utmp_lock);
|
||||
}
|
||||
weak_alias (__setutent, setutent)
|
||||
weak_alias (__setutent, setutxent)
|
||||
|
||||
|
||||
int
|
||||
__getutent_r (struct utmp *buffer, struct utmp **result)
|
||||
{
|
||||
@ -121,16 +162,6 @@ __getutent_r (struct utmp *buffer, struct utmp **result)
|
||||
weak_alias (__getutent_r, getutent_r)
|
||||
|
||||
|
||||
static int
|
||||
getutent_r_unknown (struct utmp *buffer, struct utmp **result)
|
||||
{
|
||||
/* It is not yet initialized. */
|
||||
__setutent ();
|
||||
|
||||
return (*__libc_utmp_jump_table->getutent_r) (buffer, result);
|
||||
}
|
||||
|
||||
|
||||
struct utmp *
|
||||
__pututline (const struct utmp *data)
|
||||
{
|
||||
@ -148,11 +179,15 @@ weak_alias (__pututline, pututline)
|
||||
weak_alias (__pututline, pututxline)
|
||||
|
||||
|
||||
static struct utmp *
|
||||
pututline_unknown (const struct utmp *data)
|
||||
void
|
||||
__endutent (void)
|
||||
{
|
||||
/* It is not yet initialized. */
|
||||
__setutent ();
|
||||
__libc_lock_lock (__libc_utmp_lock);
|
||||
|
||||
return (*__libc_utmp_jump_table->pututline) (data);
|
||||
(*__libc_utmp_jump_table->endutent) ();
|
||||
__libc_utmp_jump_table = &__libc_utmp_unknown_functions;
|
||||
|
||||
__libc_lock_unlock (__libc_utmp_lock);
|
||||
}
|
||||
weak_alias (__endutent, endutent)
|
||||
weak_alias (__endutent, endutxent)
|
||||
|
@ -20,8 +20,6 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <bits/libc-lock.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <utmp.h>
|
||||
|
||||
#include "utmp-private.h"
|
||||
@ -38,7 +36,7 @@ int
|
||||
__getutid_r (const struct utmp *id, struct utmp *buffer, struct utmp **result)
|
||||
{
|
||||
#if (_HAVE_UT_ID - 0) && (_HAVE_UT_TYPE - 0)
|
||||
int retval = -1;
|
||||
int retval;
|
||||
|
||||
/* Test whether ID has any of the legal types. */
|
||||
if (id->ut_type != RUN_LVL && id->ut_type != BOOT_TIME
|
||||
@ -54,11 +52,7 @@ __getutid_r (const struct utmp *id, struct utmp *buffer, struct utmp **result)
|
||||
|
||||
__libc_lock_lock (__libc_utmp_lock);
|
||||
|
||||
/* Not yet initialized. */
|
||||
if ((*__libc_utmp_jump_table->setutent) ())
|
||||
retval = (*__libc_utmp_jump_table->getutid_r) (id, buffer, result);
|
||||
else
|
||||
*result = NULL;
|
||||
retval = (*__libc_utmp_jump_table->getutid_r) (id, buffer, result);
|
||||
|
||||
__libc_lock_unlock (__libc_utmp_lock);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||||
|
||||
@ -25,7 +25,7 @@ static struct utmp buffer;
|
||||
|
||||
|
||||
struct utmp *
|
||||
getutline (const struct utmp *line)
|
||||
__getutline (const struct utmp *line)
|
||||
{
|
||||
struct utmp *result;
|
||||
|
||||
@ -34,3 +34,5 @@ getutline (const struct utmp *line)
|
||||
|
||||
return result;
|
||||
}
|
||||
weak_alias (__getutline, getutline)
|
||||
weak_alias (__getutline, getutxline)
|
||||
|
@ -20,8 +20,6 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <bits/libc-lock.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <utmp.h>
|
||||
|
||||
#include "utmp-private.h"
|
||||
@ -38,15 +36,11 @@ int
|
||||
__getutline_r (const struct utmp *line, struct utmp *buffer,
|
||||
struct utmp **result)
|
||||
{
|
||||
int retval = -1;
|
||||
int retval;
|
||||
|
||||
__libc_lock_lock (__libc_utmp_lock);
|
||||
|
||||
/* Not yet initialized. */
|
||||
if ((*__libc_utmp_jump_table->setutent) ())
|
||||
retval = (*__libc_utmp_jump_table->getutline_r) (line, buffer, result);
|
||||
else
|
||||
*result = NULL;
|
||||
retval = (*__libc_utmp_jump_table->getutline_r) (line, buffer, result);
|
||||
|
||||
__libc_lock_unlock (__libc_utmp_lock);
|
||||
|
||||
|
@ -30,7 +30,7 @@ logout (const char *line)
|
||||
int result = 0;
|
||||
|
||||
/* Tell that we want to use the UTMP file. */
|
||||
if (utmpname (_PATH_UTMP) == 0)
|
||||
if (utmpname (_PATH_UTMP) == -1)
|
||||
return 0;
|
||||
|
||||
/* Open UTMP file. */
|
||||
|
@ -88,7 +88,7 @@ open_database (const char *file, const char *old_file)
|
||||
error (0, errno, "%s", old_file);
|
||||
goto return_error;
|
||||
}
|
||||
|
||||
|
||||
database->old_file = strdup (old_file);
|
||||
if (database->old_file == NULL)
|
||||
{
|
||||
@ -100,12 +100,12 @@ open_database (const char *file, const char *old_file)
|
||||
/* Initialize database. */
|
||||
if (initialize_database (database) < 0)
|
||||
goto return_error;
|
||||
|
||||
|
||||
return database;
|
||||
|
||||
return_error:
|
||||
close_database (database);
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -121,16 +121,16 @@ synchronize_database (utmp_database *database)
|
||||
{
|
||||
time_t curtime;
|
||||
time_t mtime;
|
||||
|
||||
|
||||
curtime = time (NULL);
|
||||
|
||||
|
||||
if (get_mtime (database->old_fd, &mtime) < 0)
|
||||
{
|
||||
error (0, errno, _("%s: cannot get modification time"),
|
||||
database->old_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (mtime >= database->mtime)
|
||||
{
|
||||
int position = 0;
|
||||
@ -141,7 +141,7 @@ synchronize_database (utmp_database *database)
|
||||
{
|
||||
if (read_old_entry (database, position, &old_entry) < 0)
|
||||
break;
|
||||
|
||||
|
||||
if (read_entry (database, position, &entry) < 0
|
||||
|| !compare_entry (&old_entry, &entry))
|
||||
{
|
||||
@ -157,7 +157,7 @@ synchronize_database (utmp_database *database)
|
||||
|
||||
database->mtime = curtime;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -175,7 +175,7 @@ close_database (utmp_database *database)
|
||||
|
||||
if (database->old_fd >= 0)
|
||||
close (database->old_fd);
|
||||
|
||||
|
||||
/* Free allocated memory. */
|
||||
if (database->file)
|
||||
free (database->file);
|
||||
@ -200,7 +200,7 @@ read_entry (utmp_database *database, int position, struct utmp *entry)
|
||||
nbytes = read (database->fd, entry, sizeof (struct utmp));
|
||||
if (nbytes != sizeof (struct utmp))
|
||||
return -1;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -221,7 +221,7 @@ write_entry (utmp_database *database, int position,
|
||||
fl.l_type = F_WRLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fcntl (database->fd, F_SETLKW, &fl);
|
||||
|
||||
|
||||
offset = position * sizeof (struct utmp);
|
||||
if (lseek (database->fd, offset, SEEK_SET) < 0)
|
||||
goto fail;
|
||||
@ -259,7 +259,7 @@ append_entry (utmp_database *database, const struct utmp *entry)
|
||||
fl.l_type = F_WRLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fcntl (database->fd, F_SETLKW, &fl);
|
||||
|
||||
|
||||
offset = lseek (database->fd, 0, SEEK_END);
|
||||
if (offset % sizeof (struct utmp) != 0)
|
||||
{
|
||||
@ -278,7 +278,7 @@ append_entry (utmp_database *database, const struct utmp *entry)
|
||||
}
|
||||
|
||||
result = offset / sizeof (struct utmp);
|
||||
|
||||
|
||||
fail:
|
||||
/* And unlock the file. */
|
||||
fl.l_type = F_UNLCK;
|
||||
@ -303,7 +303,7 @@ read_old_entry (utmp_database *database, int position,
|
||||
nbytes = read (database->old_fd, &old_entry, sizeof (struct xtmp));
|
||||
if (nbytes != sizeof (struct xtmp))
|
||||
return -1;
|
||||
|
||||
|
||||
xtmp_to_utmp (&old_entry, entry);
|
||||
return 0;
|
||||
}
|
||||
@ -318,7 +318,7 @@ write_old_entry (utmp_database *database, int position,
|
||||
off_t offset;
|
||||
|
||||
utmp_to_xtmp (entry, &old_entry);
|
||||
|
||||
|
||||
offset = position * sizeof (struct xtmp);
|
||||
if (lseek (database->old_fd, offset, SEEK_SET) < 0)
|
||||
return -1;
|
||||
@ -337,7 +337,7 @@ initialize_database (utmp_database *database)
|
||||
{
|
||||
struct utmp entry;
|
||||
int position = 0;
|
||||
|
||||
|
||||
assert (database);
|
||||
|
||||
/* Check if there is a file in the old format to read. */
|
||||
@ -395,6 +395,7 @@ initialize_database (utmp_database *database)
|
||||
}
|
||||
|
||||
|
||||
#if _HAVE_UT_TYPE - 0
|
||||
static int
|
||||
store_state_entry (utmp_database *database, int old_position,
|
||||
const struct utmp *old_entry)
|
||||
@ -413,7 +414,7 @@ store_state_entry (utmp_database *database, int old_position,
|
||||
/* Read the next entry. */
|
||||
if (read_entry (database, new_position, &new_entry) < 0)
|
||||
break;
|
||||
|
||||
|
||||
if (old_entry->ut_type == new_entry.ut_type)
|
||||
{
|
||||
found = 1;
|
||||
@ -428,16 +429,23 @@ store_state_entry (utmp_database *database, int old_position,
|
||||
{
|
||||
const struct utmp *entry;
|
||||
|
||||
if (old_entry->ut_time > new_entry.ut_time)
|
||||
if (
|
||||
#if _HAVE_UT_TV - 0
|
||||
old_entry->ut_tv.tv_sec > new_entry.ut_tv.tv_sec
|
||||
#else
|
||||
old_entry->ut_time > new_entry.ut_time
|
||||
#endif
|
||||
)
|
||||
entry = old_entry;
|
||||
else
|
||||
entry = &new_entry;
|
||||
|
||||
|
||||
return replace_entry (database, old_position, new_position, entry);
|
||||
}
|
||||
|
||||
return store_entry (database, old_position, old_entry);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
@ -468,11 +476,17 @@ store_process_entry (utmp_database *database, int old_position,
|
||||
{
|
||||
const struct utmp *entry;
|
||||
|
||||
if (old_entry->ut_time > new_entry.ut_time)
|
||||
if (
|
||||
#if _HAVE_UT_TV - 0
|
||||
old_entry->ut_tv.tv_sec > new_entry.ut_tv.tv_sec
|
||||
#else
|
||||
old_entry->ut_time > new_entry.ut_time
|
||||
#endif
|
||||
)
|
||||
entry = old_entry;
|
||||
else
|
||||
entry = &new_entry;
|
||||
|
||||
|
||||
return replace_entry (database, old_position, new_position, entry);
|
||||
}
|
||||
|
||||
@ -485,7 +499,7 @@ replace_entry (utmp_database *database, int old_position, int new_position,
|
||||
const struct utmp *entry)
|
||||
{
|
||||
struct utmp tmp;
|
||||
|
||||
|
||||
if (read_entry (database, old_position, &tmp) < 0
|
||||
|| write_entry (database, old_position, entry) < 0
|
||||
|| write_entry (database, new_position, &tmp) < 0)
|
||||
@ -518,7 +532,7 @@ static int
|
||||
get_mtime (int filedes, time_t *timer)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
|
||||
if (fstat (filedes, &st) < 0)
|
||||
return -1;
|
||||
|
||||
|
@ -29,9 +29,15 @@
|
||||
void
|
||||
print_entry (struct utmp *up)
|
||||
{
|
||||
#if _HAVE_UT_TV - 0
|
||||
printf ("[%d] [%05d] [%-4.4s] [%-8.8s] [%-12.12s] [%-15.15s] [%ld]\n",
|
||||
up->ut_type, up->ut_pid, up->ut_id, up->ut_user,
|
||||
up->ut_line, 4 + ctime (&up->ut_time), up->ut_tv.tv_usec);
|
||||
up->ut_line, 4 + ctime (&up->ut_tv.tv_sec), up->ut_tv.tv_usec);
|
||||
#else
|
||||
printf ("[%d] [%05d] [%-4.4s] [%-8.8s] [%-12.12s] [%-15.15s]\n",
|
||||
up->ut_type, up->ut_pid, up->ut_id, up->ut_user,
|
||||
up->ut_line, 4 + ctime (&up->ut_time));
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
@ -41,13 +47,13 @@ main (int argc, char *argv[])
|
||||
|
||||
if (argc > 1)
|
||||
utmpname (argv[1]);
|
||||
|
||||
|
||||
setutent ();
|
||||
|
||||
while ((up = getutent ()))
|
||||
print_entry (up);
|
||||
|
||||
endutent ();
|
||||
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -42,7 +42,11 @@ xtmp_to_utmp (const struct xtmp *xtmp, struct utmp *utmp)
|
||||
#if _HAVE_XT_ID - 0
|
||||
strncpy (utmp->ut_id, xtmp->xt_id, sizeof xtmp->xt_id);
|
||||
#endif
|
||||
#if _HAVE_UT_TV - 0
|
||||
utmp->ut_tv.tv_sec = xtmp->xt_time;
|
||||
#else
|
||||
utmp->ut_time = xtmp->xt_time;
|
||||
#endif
|
||||
strncpy (utmp->ut_user, xtmp->xt_user, XT_NAMESIZE);
|
||||
#if _HAVE_XT_HOST - 0
|
||||
strncpy (utmp->ut_host, xtmp->xt_host, XT_HOSTSIZE);
|
||||
@ -66,7 +70,11 @@ utmp_to_xtmp (const struct utmp *utmp, struct xtmp *xtmp)
|
||||
#if _HAVE_XT_ID - 0
|
||||
strncpy (xtmp->xt_id, utmp->ut_id, sizeof xtmp->xt_id);
|
||||
#endif
|
||||
#if _HAVE_UT_TV - 0
|
||||
xtmp->xt_time = utmp->ut_tv.tv_sec;
|
||||
#else
|
||||
xtmp->xt_time = utmp->ut_time;
|
||||
#endif
|
||||
strncpy (xtmp->xt_user, utmp->ut_user, XT_NAMESIZE);
|
||||
#if _HAVE_XT_HOST - 0
|
||||
strncpy (xtmp->xt_host, utmp->ut_host, XT_HOSTSIZE);
|
||||
@ -79,24 +87,28 @@ utmp_to_xtmp (const struct utmp *utmp, struct xtmp *xtmp)
|
||||
function returns 1 if the information that is in both old and new
|
||||
style entries is identical. Otherwise this function returns 0. */
|
||||
int
|
||||
compare_entry (const struct utmp *xtmp, const struct utmp *utmp)
|
||||
compare_entry (const struct xtmp *xtmp, const struct utmp *utmp)
|
||||
{
|
||||
return
|
||||
(
|
||||
#if _HAVE_XT_TYPE - 0
|
||||
xtmp->ut_type == utmp->ut_type
|
||||
xtmp->xt_type == utmp->ut_type
|
||||
#endif
|
||||
#if _HAVE_XT_PID - 0
|
||||
&& xtmp->ut_pid == utmp->ut_pid
|
||||
&& xtmp->xt_pid == utmp->ut_pid
|
||||
#endif
|
||||
&& !strncmp (xtmp->ut_line, utmp->ut_line, XT_LINESIZE - 1)
|
||||
&& !strncmp (xtmp->xt_line, utmp->ut_line, XT_LINESIZE - 1)
|
||||
#if _HAVE_XT_ID - 0
|
||||
&& !strncmp (xtmp->ut_id, utmp->ut_id, sizeof utmp->ut_id)
|
||||
&& !strncmp (xtmp->xt_id, utmp->ut_id, sizeof utmp->ut_id)
|
||||
#endif
|
||||
&& xtmp->ut_time == utmp->ut_time
|
||||
&& !strncmp (xtmp->ut_user, utmp->ut_user, XT_NAMESIZE)
|
||||
#if _HAVE_UT_TV - 0
|
||||
&& xtmp->xt_time == utmp->ut_tv.tv_sec
|
||||
#else
|
||||
&& xtmp->xt_time == utmp->ut_time
|
||||
#endif
|
||||
&& !strncmp (xtmp->xt_user, utmp->ut_user, XT_NAMESIZE)
|
||||
#if _HAVE_XT_HOST - 0
|
||||
&& !strncmp (xtmp->ut_host, utmp->ut_host, XT_HOSTSIZE - 1)
|
||||
&& !strncmp (xtmp->xt_host, utmp->ut_host, XT_HOSTSIZE - 1)
|
||||
#endif
|
||||
&& xtmp->ut_addr == utmp->ut_addr);
|
||||
&& xtmp->xt_addr == utmp->ut_addr);
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ struct xtmp
|
||||
|
||||
extern void xtmp_to_utmp (const struct xtmp *xtmp, struct utmp *utmp);
|
||||
extern void utmp_to_xtmp (const struct utmp *utmp, struct xtmp *xtmp);
|
||||
extern int compare_entry (const struct utmp *xtmp,
|
||||
extern int compare_entry (const struct xtmp *xtmp,
|
||||
const struct utmp *utmp);
|
||||
|
||||
#endif /* xtmp.h */
|
||||
|
@ -17,8 +17,8 @@
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
@ -31,7 +31,7 @@
|
||||
|
||||
|
||||
/* Descriptor for the socket. */
|
||||
static int daemon_sock = INT_MIN;
|
||||
static int daemon_sock = -1;
|
||||
|
||||
|
||||
/* Functions defined here. */
|
||||
@ -59,12 +59,13 @@ struct utfuncs __libc_utmp_daemon_functions =
|
||||
|
||||
static int do_setutent (int sock);
|
||||
static int do_getutent (int sock, struct utmp *buffer);
|
||||
static int do_endutent (int sock);
|
||||
static int do_getutline (int sock, const struct utmp *line,
|
||||
struct utmp *buffer);
|
||||
static int do_getutid (int sock, const struct utmp *id,
|
||||
struct utmp *buffer);
|
||||
static int do_pututline (int sock, const struct utmp *utmp);
|
||||
static int do_getutline (int sock, const struct utmp *line,
|
||||
struct utmp *buffer);
|
||||
static int do_pututline (int sock, const struct utmp *utmp);
|
||||
static int do_endutent (int sock);
|
||||
static int do_updwtmp (int sock, const char *file,
|
||||
const struct utmp *utmp);
|
||||
|
||||
@ -79,7 +80,7 @@ setutent_daemon (void)
|
||||
if (access (_PATH_UTMPD_RW, F_OK) == -1
|
||||
&& access (_PATH_UTMPD_RO, F_OK) == -1)
|
||||
return 0;
|
||||
|
||||
|
||||
if (daemon_sock < 0)
|
||||
{
|
||||
daemon_sock = open_socket (_PATH_UTMPD_RW);
|
||||
@ -100,33 +101,10 @@ setutent_daemon (void)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
endutent_daemon (void)
|
||||
{
|
||||
if (daemon_sock >= 0)
|
||||
{
|
||||
/* Send request to the daemon. */
|
||||
do_endutent (daemon_sock);
|
||||
close (daemon_sock);
|
||||
}
|
||||
|
||||
daemon_sock = INT_MIN;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
getutent_r_daemon (struct utmp *buffer, struct utmp **result)
|
||||
{
|
||||
/* Open connection if not already done. */
|
||||
if (daemon_sock == INT_MIN)
|
||||
setutent_daemon ();
|
||||
|
||||
if (daemon_sock < 0)
|
||||
{
|
||||
/* Not available. */
|
||||
*result = NULL;
|
||||
return -1;
|
||||
}
|
||||
assert (daemon_sock >= 0);
|
||||
|
||||
/* Send request to the daemon. */
|
||||
if (do_getutent (daemon_sock, buffer) < 0)
|
||||
@ -140,37 +118,11 @@ getutent_r_daemon (struct utmp *buffer, struct utmp **result)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
getutline_r_daemon (const struct utmp *line, struct utmp *buffer,
|
||||
struct utmp **result)
|
||||
{
|
||||
if (daemon_sock < 0)
|
||||
{
|
||||
*result = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Send request to the daemon. */
|
||||
if (do_getutline (daemon_sock, line, buffer) < 0)
|
||||
{
|
||||
*result = NULL;
|
||||
return -1;;
|
||||
}
|
||||
|
||||
*result = buffer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
getutid_r_daemon (const struct utmp *id, struct utmp *buffer,
|
||||
struct utmp **result)
|
||||
{
|
||||
if (daemon_sock < 0)
|
||||
{
|
||||
*result = NULL;
|
||||
return -1;
|
||||
}
|
||||
assert (daemon_sock >= 0);
|
||||
|
||||
/* Send request to the daemon. */
|
||||
if (do_getutid (daemon_sock, id, buffer) < 0)
|
||||
@ -184,16 +136,28 @@ getutid_r_daemon (const struct utmp *id, struct utmp *buffer,
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
getutline_r_daemon (const struct utmp *line, struct utmp *buffer,
|
||||
struct utmp **result)
|
||||
{
|
||||
assert (daemon_sock >= 0);
|
||||
|
||||
/* Send request to the daemon. */
|
||||
if (do_getutline (daemon_sock, line, buffer) < 0)
|
||||
{
|
||||
*result = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*result = buffer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct utmp *
|
||||
pututline_daemon (const struct utmp *utmp)
|
||||
{
|
||||
/* Open connection if not already done. */
|
||||
if (daemon_sock == INT_MIN)
|
||||
setutent_daemon ();
|
||||
|
||||
if (daemon_sock < 0)
|
||||
/* Something went wrong. */
|
||||
return NULL;
|
||||
assert (daemon_sock >= 0);
|
||||
|
||||
/* Send request to the daemon. */
|
||||
if (do_pututline (daemon_sock, utmp) < 0)
|
||||
@ -203,6 +167,19 @@ pututline_daemon (const struct utmp *utmp)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
endutent_daemon (void)
|
||||
{
|
||||
assert (daemon_sock >= 0);
|
||||
|
||||
/* Send request to the daemon. */
|
||||
do_endutent (daemon_sock);
|
||||
|
||||
close (daemon_sock);
|
||||
daemon_sock = -1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
updwtmp_daemon (const char *file, const struct utmp *utmp)
|
||||
{
|
||||
@ -233,11 +210,11 @@ do_setutent (int sock)
|
||||
size_t size;
|
||||
|
||||
size = sizeof (setutent_request) + strlen (__libc_utmp_file_name) + 1;
|
||||
|
||||
|
||||
request = malloc (size);
|
||||
if (request == NULL)
|
||||
return -1;
|
||||
|
||||
|
||||
request->header.version = UTMPD_VERSION;
|
||||
request->header.size = size;
|
||||
request->header.type = UTMPD_REQ_SETUTENT;
|
||||
@ -286,24 +263,27 @@ do_getutent (int sock, struct utmp *buffer)
|
||||
}
|
||||
|
||||
static int
|
||||
do_endutent (int sock)
|
||||
do_getutid (int sock, const struct utmp *id, struct utmp *buffer)
|
||||
{
|
||||
endutent_request request;
|
||||
endutent_reply reply;
|
||||
getutid_request request;
|
||||
getutid_reply reply;
|
||||
|
||||
request.header.version = UTMPD_VERSION;
|
||||
request.header.size = sizeof (endutent_request);
|
||||
request.header.type = UTMPD_REQ_ENDUTENT;
|
||||
request.header.size = sizeof (getutid_request);
|
||||
request.header.type = UTMPD_REQ_GETUTID;
|
||||
memcpy (&request.id, id, sizeof (struct utmp));
|
||||
|
||||
reply.header.version = UTMPD_VERSION;
|
||||
reply.header.size = sizeof (endutent_reply);
|
||||
reply.header.type = UTMPD_REQ_ENDUTENT;
|
||||
reply.header.size = sizeof (getutid_reply);
|
||||
reply.header.type = UTMPD_REQ_GETUTID;
|
||||
|
||||
if (send_request (sock, &request.header, &reply.header) < 0)
|
||||
return -1;
|
||||
|
||||
if (reply.result < 0)
|
||||
__set_errno (reply.errnum);
|
||||
else
|
||||
memcpy (buffer, &reply.entry, sizeof (struct utmp));
|
||||
|
||||
return reply.result;
|
||||
}
|
||||
@ -334,32 +314,6 @@ do_getutline (int sock, const struct utmp *line, struct utmp *buffer)
|
||||
return reply.result;
|
||||
}
|
||||
|
||||
static int
|
||||
do_getutid (int sock, const struct utmp *id, struct utmp *buffer)
|
||||
{
|
||||
getutid_request request;
|
||||
getutid_reply reply;
|
||||
|
||||
request.header.version = UTMPD_VERSION;
|
||||
request.header.size = sizeof (getutid_request);
|
||||
request.header.type = UTMPD_REQ_GETUTID;
|
||||
memcpy (&request.id, id, sizeof (struct utmp));
|
||||
|
||||
reply.header.version = UTMPD_VERSION;
|
||||
reply.header.size = sizeof (getutid_reply);
|
||||
reply.header.type = UTMPD_REQ_GETUTID;
|
||||
|
||||
if (send_request (sock, &request.header, &reply.header) < 0)
|
||||
return -1;
|
||||
|
||||
if (reply.result < 0)
|
||||
__set_errno (reply.errnum);
|
||||
else
|
||||
memcpy (buffer, &reply.entry, sizeof (struct utmp));
|
||||
|
||||
return reply.result;
|
||||
}
|
||||
|
||||
static int
|
||||
do_pututline (int sock, const struct utmp *utmp)
|
||||
{
|
||||
@ -384,6 +338,29 @@ do_pututline (int sock, const struct utmp *utmp)
|
||||
return reply.result;
|
||||
}
|
||||
|
||||
static int
|
||||
do_endutent (int sock)
|
||||
{
|
||||
endutent_request request;
|
||||
endutent_reply reply;
|
||||
|
||||
request.header.version = UTMPD_VERSION;
|
||||
request.header.size = sizeof (endutent_request);
|
||||
request.header.type = UTMPD_REQ_ENDUTENT;
|
||||
|
||||
reply.header.version = UTMPD_VERSION;
|
||||
reply.header.size = sizeof (endutent_reply);
|
||||
reply.header.type = UTMPD_REQ_ENDUTENT;
|
||||
|
||||
if (send_request (sock, &request.header, &reply.header) < 0)
|
||||
return -1;
|
||||
|
||||
if (reply.result < 0)
|
||||
__set_errno (reply.errnum);
|
||||
|
||||
return reply.result;
|
||||
}
|
||||
|
||||
static int
|
||||
do_updwtmp (int sock, const char *file, const struct utmp *utmp)
|
||||
{
|
||||
@ -392,11 +369,11 @@ do_updwtmp (int sock, const char *file, const struct utmp *utmp)
|
||||
size_t size;
|
||||
|
||||
size = sizeof (updwtmp_request) + strlen (file) + 1;
|
||||
|
||||
|
||||
request = malloc (size);
|
||||
if (request == NULL)
|
||||
return -1;
|
||||
|
||||
|
||||
request->header.version = UTMPD_VERSION;
|
||||
request->header.size = size;
|
||||
request->header.type = UTMPD_REQ_UPDWTMP;
|
||||
|
@ -18,13 +18,11 @@
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <utmp.h>
|
||||
|
||||
@ -32,9 +30,10 @@
|
||||
|
||||
|
||||
/* Descriptor for the file and position. */
|
||||
static int file_fd = INT_MIN;
|
||||
static int file_fd = -1;
|
||||
static off_t file_offset;
|
||||
|
||||
/* Cache for the last read entry. */
|
||||
static struct utmp last_entry;
|
||||
|
||||
|
||||
@ -68,14 +67,14 @@ setutent_file (void)
|
||||
if (file_fd < 0)
|
||||
{
|
||||
const char *file_name = __libc_utmp_file_name;
|
||||
|
||||
|
||||
if (strcmp (__libc_utmp_file_name, _PATH_UTMP) == 0
|
||||
&& __access (_PATH_UTMP "x", F_OK) == 0)
|
||||
file_name = _PATH_UTMP "x";
|
||||
else if (strcmp (__libc_utmp_file_name, _PATH_WTMP) == 0
|
||||
&& __access (_PATH_WTMP "x", F_OK) == 0)
|
||||
file_name = _PATH_WTMP "x";
|
||||
|
||||
|
||||
file_fd = open (file_name, O_RDWR);
|
||||
if (file_fd == -1)
|
||||
{
|
||||
@ -96,32 +95,20 @@ setutent_file (void)
|
||||
/* Make sure the entry won't match. */
|
||||
last_entry.ut_type = -1;
|
||||
#endif
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
endutent_file (void)
|
||||
{
|
||||
if (file_fd >= 0)
|
||||
close (file_fd);
|
||||
|
||||
file_fd = INT_MIN;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
getutent_r_file (struct utmp *buffer, struct utmp **result)
|
||||
{
|
||||
ssize_t nbytes;
|
||||
struct flock fl; /* Information struct for locking. */
|
||||
|
||||
/* Open utmp file if not already done. */
|
||||
if (file_fd == INT_MIN)
|
||||
setutent_file ();
|
||||
assert (file_fd >= 0);
|
||||
|
||||
if (file_fd == -1 || file_offset == -1l)
|
||||
if (file_offset == -1l)
|
||||
{
|
||||
/* Not available. */
|
||||
*result = NULL;
|
||||
@ -131,12 +118,16 @@ getutent_r_file (struct utmp *buffer, struct utmp **result)
|
||||
/* XXX The following is not perfect. Instead of locking the file itself
|
||||
Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl> suggests to
|
||||
use an extra locking file. */
|
||||
/* XXX I think using an extra locking file does not solve the
|
||||
problems. Instead we should set an alarm, which causes fcntl to
|
||||
fail, as in ../nis/lckcache.c.
|
||||
Mark Kettenis <kettenis@phys.uva.nl>. */
|
||||
|
||||
/* Try to get the lock. */
|
||||
memset (&fl, '\0', sizeof (struct flock));
|
||||
fl.l_type = F_RDLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fcntl (file_fd, F_SETLKW, &fl);
|
||||
fcntl (file_fd, F_SETLK, &fl);
|
||||
|
||||
/* Read the next entry. */
|
||||
nbytes = read (file_fd, &last_entry, sizeof (struct utmp));
|
||||
@ -162,62 +153,6 @@ getutent_r_file (struct utmp *buffer, struct utmp **result)
|
||||
}
|
||||
|
||||
|
||||
/* For implementing this function we don't use the getutent_r function
|
||||
because we can avoid the reposition on every new entry this way. */
|
||||
static int
|
||||
getutline_r_file (const struct utmp *line, struct utmp *buffer,
|
||||
struct utmp **result)
|
||||
{
|
||||
struct flock fl;
|
||||
|
||||
if (file_fd < 0 || file_offset == -1l)
|
||||
{
|
||||
*result = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Try to get the lock. */
|
||||
memset (&fl, '\0', sizeof (struct flock));
|
||||
fl.l_type = F_RDLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fcntl (file_fd, F_SETLKW, &fl);
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Read the next entry. */
|
||||
if (read (file_fd, &last_entry, sizeof (struct utmp))
|
||||
!= sizeof (struct utmp))
|
||||
{
|
||||
__set_errno (ESRCH);
|
||||
file_offset = -1l;
|
||||
*result = NULL;
|
||||
goto unlock_return;
|
||||
}
|
||||
file_offset += sizeof (struct utmp);
|
||||
|
||||
/* Stop if we found a user or login entry. */
|
||||
if (
|
||||
#if _HAVE_UT_TYPE - 0
|
||||
(last_entry.ut_type == USER_PROCESS
|
||||
|| last_entry.ut_type == LOGIN_PROCESS)
|
||||
&&
|
||||
#endif
|
||||
!strncmp (line->ut_line, last_entry.ut_line, sizeof line->ut_line))
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy (buffer, &last_entry, sizeof (struct utmp));
|
||||
*result = buffer;
|
||||
|
||||
unlock_return:
|
||||
/* And unlock the file. */
|
||||
fl.l_type = F_UNLCK;
|
||||
fcntl (file_fd, F_SETLKW, &fl);
|
||||
|
||||
return ((*result == NULL) ? -1 : 0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
proc_utmp_eq (const struct utmp *entry, const struct utmp *match)
|
||||
{
|
||||
@ -308,7 +243,7 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer)
|
||||
unlock_return:
|
||||
/* And unlock the file. */
|
||||
fl.l_type = F_UNLCK;
|
||||
fcntl (file_fd, F_SETLKW, &fl);
|
||||
fcntl (file_fd, F_SETLK, &fl);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -320,7 +255,9 @@ static int
|
||||
getutid_r_file (const struct utmp *id, struct utmp *buffer,
|
||||
struct utmp **result)
|
||||
{
|
||||
if (file_fd < 0 || file_offset == -1l)
|
||||
assert (file_fd >= 0);
|
||||
|
||||
if (file_offset == -1l)
|
||||
{
|
||||
*result = NULL;
|
||||
return -1;
|
||||
@ -339,6 +276,64 @@ getutid_r_file (const struct utmp *id, struct utmp *buffer,
|
||||
}
|
||||
|
||||
|
||||
/* For implementing this function we don't use the getutent_r function
|
||||
because we can avoid the reposition on every new entry this way. */
|
||||
static int
|
||||
getutline_r_file (const struct utmp *line, struct utmp *buffer,
|
||||
struct utmp **result)
|
||||
{
|
||||
struct flock fl;
|
||||
|
||||
assert (file_fd >= 0);
|
||||
|
||||
if (file_offset == -1l)
|
||||
{
|
||||
*result = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Try to get the lock. */
|
||||
memset (&fl, '\0', sizeof (struct flock));
|
||||
fl.l_type = F_RDLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fcntl (file_fd, F_SETLKW, &fl);
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Read the next entry. */
|
||||
if (read (file_fd, &last_entry, sizeof (struct utmp))
|
||||
!= sizeof (struct utmp))
|
||||
{
|
||||
__set_errno (ESRCH);
|
||||
file_offset = -1l;
|
||||
*result = NULL;
|
||||
goto unlock_return;
|
||||
}
|
||||
file_offset += sizeof (struct utmp);
|
||||
|
||||
/* Stop if we found a user or login entry. */
|
||||
if (
|
||||
#if _HAVE_UT_TYPE - 0
|
||||
(last_entry.ut_type == USER_PROCESS
|
||||
|| last_entry.ut_type == LOGIN_PROCESS)
|
||||
&&
|
||||
#endif
|
||||
!strncmp (line->ut_line, last_entry.ut_line, sizeof line->ut_line))
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy (buffer, &last_entry, sizeof (struct utmp));
|
||||
*result = buffer;
|
||||
|
||||
unlock_return:
|
||||
/* And unlock the file. */
|
||||
fl.l_type = F_UNLCK;
|
||||
fcntl (file_fd, F_SETLK, &fl);
|
||||
|
||||
return ((*result == NULL) ? -1 : 0);
|
||||
}
|
||||
|
||||
|
||||
static struct utmp *
|
||||
pututline_file (const struct utmp *data)
|
||||
{
|
||||
@ -347,13 +342,7 @@ pututline_file (const struct utmp *data)
|
||||
struct utmp *pbuf;
|
||||
int found;
|
||||
|
||||
/* Open utmp file if not already done. */
|
||||
if (file_fd == INT_MIN)
|
||||
setutent_file ();
|
||||
|
||||
if (file_fd == -1)
|
||||
/* Something went wrong. */
|
||||
return NULL;
|
||||
assert (file_fd >= 0);
|
||||
|
||||
/* Find the correct place to insert the data. */
|
||||
if (file_offset > 0
|
||||
@ -375,7 +364,7 @@ pututline_file (const struct utmp *data)
|
||||
memset (&fl, '\0', sizeof (struct flock));
|
||||
fl.l_type = F_WRLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fcntl (file_fd, F_SETLKW, &fl);
|
||||
fcntl (file_fd, F_SETLK, &fl);
|
||||
|
||||
if (found < 0)
|
||||
{
|
||||
@ -418,12 +407,22 @@ pututline_file (const struct utmp *data)
|
||||
unlock_return:
|
||||
/* And unlock the file. */
|
||||
fl.l_type = F_UNLCK;
|
||||
fcntl (file_fd, F_SETLKW, &fl);
|
||||
fcntl (file_fd, F_SETLK, &fl);
|
||||
|
||||
return pbuf;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
endutent_file (void)
|
||||
{
|
||||
assert (file_fd >= 0);
|
||||
|
||||
close (file_fd);
|
||||
file_fd = -1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
updwtmp_file (const char *file, const struct utmp *utmp)
|
||||
{
|
||||
@ -441,7 +440,7 @@ updwtmp_file (const char *file, const struct utmp *utmp)
|
||||
memset (&fl, '\0', sizeof (struct flock));
|
||||
fl.l_type = F_WRLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fcntl (fd, F_SETLKW, &fl);
|
||||
fcntl (fd, F_SETLK, &fl);
|
||||
|
||||
/* Remember original size of log file. */
|
||||
offset = lseek (fd, 0, SEEK_END);
|
||||
|
@ -44,6 +44,7 @@ __utmpname (const char *file)
|
||||
|
||||
/* Close the old file. */
|
||||
(*__libc_utmp_jump_table->endutent) ();
|
||||
__libc_utmp_jump_table = &__libc_utmp_unknown_functions;
|
||||
|
||||
if (strcmp (file, __libc_utmp_file_name) != 0)
|
||||
{
|
||||
@ -68,7 +69,6 @@ __utmpname (const char *file)
|
||||
}
|
||||
}
|
||||
|
||||
__libc_utmp_jump_table = &__libc_utmp_unknown_functions;
|
||||
result = 0;
|
||||
|
||||
done:
|
||||
|
@ -41,33 +41,14 @@ __mach_setup_thread (task_t task, thread_t thread, void *pc,
|
||||
mach_msg_type_number_t tssize = MACHINE_THREAD_STATE_COUNT;
|
||||
vm_address_t stack;
|
||||
vm_size_t size;
|
||||
int anywhere = 0;
|
||||
int anywhere;
|
||||
|
||||
size = stack_size ? *stack_size ? : STACK_SIZE : STACK_SIZE;
|
||||
stack = stack_base ? *stack_base ? : 0 : 0;
|
||||
anywhere = !stack_base || !*stack_base;
|
||||
|
||||
if (stack_base && *stack_base)
|
||||
stack = *stack_base;
|
||||
else if (size == STACK_SIZE)
|
||||
{
|
||||
/* Cthreads has a bug that makes its stack-probing code fail if
|
||||
the stack is too low in memory. It's bad to try and fix it there
|
||||
until cthreads is integrated into libc, so we'll just do it here
|
||||
by requesting a high address. When the cthreads bug is fixed,
|
||||
this assignment to STACK should be changed to 0, and the ANYWHERE
|
||||
argument to vm_allocate should be changed to 0. This comment should
|
||||
be left, however, in order to confuse people who wonder why its
|
||||
here. (Though perhaps that last sentence (and this one) should
|
||||
be deleted to maximize the effect.) */
|
||||
#ifdef STACK_GROWTH_DOWN
|
||||
stack = VM_MAX_ADDRESS - size - __vm_page_size;
|
||||
#else
|
||||
stack = VM_MIN_ADDRESS;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
anywhere = 1;
|
||||
|
||||
if (error = __vm_allocate (task, &stack, size + __vm_page_size, anywhere))
|
||||
error = __vm_allocate (task, &stack, size + __vm_page_size, anywhere);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (stack_size)
|
||||
|
@ -1684,7 +1684,7 @@ static mchunkptr mmap_chunk(size) size_t size;
|
||||
size = (size + SIZE_SZ + page_mask) & ~page_mask;
|
||||
|
||||
p = (mchunkptr)MMAP(size, PROT_READ|PROT_WRITE);
|
||||
if(p == (mchunkptr)-1) return 0;
|
||||
if(p == (mchunkptr) MAP_FAILED) return 0;
|
||||
|
||||
n_mmaps++;
|
||||
if (n_mmaps > max_n_mmaps) max_n_mmaps = n_mmaps;
|
||||
@ -1812,7 +1812,7 @@ new_heap(size) size_t size;
|
||||
size = (size + page_mask) & ~page_mask;
|
||||
|
||||
p1 = (char *)MMAP(HEAP_MAX_SIZE<<1, PROT_NONE);
|
||||
if(p1 == (char *)-1)
|
||||
if(p1 == MAP_FAILED)
|
||||
return 0;
|
||||
p2 = (char *)(((unsigned long)p1 + HEAP_MAX_SIZE) & ~(HEAP_MAX_SIZE-1));
|
||||
ul = p2 - p1;
|
||||
|
@ -232,7 +232,7 @@ infinite.
|
||||
@item
|
||||
Squre root if the operand is less then zero.
|
||||
@item
|
||||
Conversion of an internal floating-point number to an integer or toa
|
||||
Conversion of an internal floating-point number to an integer or to a
|
||||
decimal string when overflow, infinity, or NaN precludes a faithful
|
||||
representation in that format and this cannot otherwise be signaled.
|
||||
@item
|
||||
@ -247,7 +247,7 @@ If the exception does not cause a trap handler to be called the result
|
||||
of the operation is taken as a quiet NaN.
|
||||
|
||||
@item Division by Zero
|
||||
This exception is raised of the devisor is zero and the dividend is a
|
||||
This exception is raised if the devisor is zero and the dividend is a
|
||||
finite nonzero number. If no trap occurs the result is either
|
||||
@iftex
|
||||
@tex
|
||||
@ -270,8 +270,8 @@ $-\infty$
|
||||
signs of the operands.
|
||||
|
||||
@item Overflow
|
||||
This exception is signalled whenever if the result cannot be represented
|
||||
as a finite value in the destination precision's format. If no trap
|
||||
This exception is signalled whenever the result cannot be represented
|
||||
as a finite value in the precision format of the destination. If no trap
|
||||
occurs the result depends on the sign of the intermediate result and the
|
||||
current rounding mode (@w{IEEE 754}, @w{section 7.3}):
|
||||
@enumerate
|
||||
@ -334,7 +334,7 @@ $\infty$.
|
||||
@end enumerate
|
||||
|
||||
@item Underflow
|
||||
The underflow exception is created when a intermediate result is too
|
||||
The underflow exception is created when an intermediate result is too
|
||||
small for the operation or if the operations result rounded to the
|
||||
destination precision causes a loss of accuracy by approximating the
|
||||
result by denormalized numbers.
|
||||
@ -342,17 +342,17 @@ result by denormalized numbers.
|
||||
When no trap is installed for the underflow exception, underflow shall
|
||||
be signaled (via the underflow flag) only when both tininess and loss of
|
||||
accuracy have been detected. If no trap handler is installed the
|
||||
operation continues witht he inprecise small value or zero if the
|
||||
operation continues with an inprecise small value or zero if the
|
||||
destination precision cannot hold the small exact result.
|
||||
|
||||
@item Inexact
|
||||
This exception is signaled if the rounded result is not exact (such as
|
||||
This exception is signalled if the rounded result is not exact (such as
|
||||
computing the square root of two) or the result overflows without an
|
||||
overflow trap.
|
||||
@end table
|
||||
|
||||
To control whether an exception causes a trap to occur all @w{IEEE 754}
|
||||
conformant floating-point implementation (either hardware or software)
|
||||
conformant floating-point implementations (either hardware or software)
|
||||
have a control word. By setting specific bits for each exception in
|
||||
this control word the programmer can decide whether a trap is wanted or
|
||||
not.
|
||||
@ -378,42 +378,42 @@ actual implementation can be very different, depending on the underlying
|
||||
hardware or software.
|
||||
|
||||
To address the single exception the @file{fenv.h} headers defines a
|
||||
number macros:
|
||||
number of macros:
|
||||
|
||||
@vtable @code
|
||||
@comment fenv.h
|
||||
@comment ISO
|
||||
@item FE_INEXACT
|
||||
Represent the inexact exception iff the FPU supports this exception.
|
||||
Represents the inexact exception iff the FPU supports this exception.
|
||||
@comment fenv.h
|
||||
@comment ISO
|
||||
@item FE_DIVBYZERO
|
||||
Represent the divide by zero exception iff the FPU supports this exception.
|
||||
Represents the divide by zero exception iff the FPU supports this exception.
|
||||
@comment fenv.h
|
||||
@comment ISO
|
||||
@item FE_UNDERFLOW
|
||||
Represent the underflow exception iff the FPU supports this exception.
|
||||
Represents the underflow exception iff the FPU supports this exception.
|
||||
@comment fenv.h
|
||||
@comment ISO
|
||||
@item FE_OVERFLOW
|
||||
Represent the overflow exception iff the FPU supports this exception.
|
||||
Represents the overflow exception iff the FPU supports this exception.
|
||||
@comment fenv.h
|
||||
@comment ISO
|
||||
@item FE_INVALID
|
||||
Represent the invalid exception iff the FPU supports this exception.
|
||||
Represents the invalid exception iff the FPU supports this exception.
|
||||
@end vtable
|
||||
|
||||
The macro @code{FE_ALL_EXCEPT} is the bitwise OR of all exception macros
|
||||
which are supported by the FP implementation.
|
||||
|
||||
Each of the supported exception flag can either be set or unset. The
|
||||
Each of the supported exception flags can either be set or unset. The
|
||||
@w{ISO C 9X} standard defines functions to set, unset and test the
|
||||
status of the flags.
|
||||
|
||||
@comment fenv.h
|
||||
@comment ISO
|
||||
@deftypefun void feclearexcept (int @var{excepts})
|
||||
This functions clears all of the supported exception flags denoted by
|
||||
This function clears all of the supported exception flags denoted by
|
||||
@var{excepts} in the status word.
|
||||
@end deftypefun
|
||||
|
||||
@ -430,7 +430,7 @@ exception flags indicated by the parameter @var{excepts}.
|
||||
@end deftypefun
|
||||
|
||||
@noindent
|
||||
To restore the previously saved values one can use this functions:
|
||||
To restore the previously saved values one can use this function:
|
||||
|
||||
@comment fenv.h
|
||||
@comment ISO
|
||||
@ -486,7 +486,7 @@ control word for the exceptions and the rounding mode can be safed.
|
||||
|
||||
The file @file{fenv.h} defines the type @code{fenv_t}. The layout of a
|
||||
variable of this type is implementation defined but the variable is able
|
||||
to contain the complete status informations. To fill a variable of this
|
||||
to contain the complete status information. To fill a variable of this
|
||||
type one can use this function:
|
||||
|
||||
@comment fenv.h
|
||||
@ -497,7 +497,7 @@ Store the current floating-point environment in the object pointed to by
|
||||
@end deftypefun
|
||||
|
||||
@noindent
|
||||
Another possibility which is useful is several situations is
|
||||
Another possibility which is useful in several situations is
|
||||
|
||||
@comment fenv.h
|
||||
@comment ISO
|
||||
@ -505,7 +505,7 @@ Another possibility which is useful is several situations is
|
||||
Store the current floating-point environment in the object pointed to by
|
||||
@var{envp}. Afterwards, all exception flags are cleared and if
|
||||
available a mode is installed which continues on all exception and does
|
||||
not cause a trap to occur. In ths case a nonzero value is returned.
|
||||
not cause a trap to occur. In this case a nonzero value is returned.
|
||||
|
||||
If the floating-point implementation does not support such a non-stop
|
||||
mode, the return value is zero.
|
||||
@ -605,14 +605,14 @@ $-\infty$.
|
||||
Round toward zero.
|
||||
@end vtable
|
||||
|
||||
At any time one of the four rounding modes above is selected. To get
|
||||
At any time one of the above four rounding modes is selected. To get
|
||||
information about the currently selected mode one can use this function:
|
||||
|
||||
@comment fenv.h
|
||||
@comment ISO
|
||||
@deftypefun int fegetround (void)
|
||||
Return the currently selected rounding mode, represented by one of the
|
||||
values of the defined rouding mode macros.
|
||||
values of the defined rounding mode macros.
|
||||
@end deftypefun
|
||||
|
||||
@noindent
|
||||
@ -625,18 +625,18 @@ Change the currently selected rounding mode to the mode described by the
|
||||
parameter @var{round}. If @var{round} does not correspond to one of the
|
||||
supported rounding modes nothing is changed.
|
||||
|
||||
The function return a nonzero value iff the requested rounding mode can
|
||||
The function returns a nonzero value iff the requested rounding mode can
|
||||
be established. Otherwise zero is returned.
|
||||
@end deftypefun
|
||||
|
||||
Changing the rounding mode can be necessary for various reasons. But
|
||||
Changing the rounding mode might be necessary for various reasons. But
|
||||
changing the mode only to round a given number normally is no good idea.
|
||||
The standard defines a set of functions which can be used to round an
|
||||
argument according to some rules and for all of the rounding modes there
|
||||
is a corresponding function.
|
||||
|
||||
If a large set of number has to be rounded it might be good to change
|
||||
the rounding mode and do not use the function the library provides. So
|
||||
the rounding mode and to not use the function the library provides. So
|
||||
the perhaps necessary switching of the rounding mode in the library
|
||||
function can be avoided. But since not all rounding modes are
|
||||
guaranteed to exist on any platform this possible implementation cannot
|
||||
@ -684,7 +684,7 @@ The value is the reziprocal of the square root of the value of the number pi.
|
||||
|
||||
ALl values are defined as @code{long double} values unless the compiler
|
||||
does not support this type or @code{__STDC__} is not defined (both is
|
||||
unlikey). Historically the numbers were @code{double} values and some
|
||||
unlikely). Historically the numbers were @code{double} values and some
|
||||
old code still relies on this so you might want to add explizit casts if
|
||||
the extra precision of the @code{long double} value is not needed. One
|
||||
critical case are functions with a variable number of arguments, such as
|
||||
@ -705,7 +705,7 @@ this value is not added to @file{math.h}. Every program should use
|
||||
@section Floating-Point Comparison Functions
|
||||
@cindex unordered comparison
|
||||
|
||||
The @w{IEEE 754} standards defines s'a set of functions which allows to
|
||||
The @w{IEEE 754} standards defines a set of functions which allows to
|
||||
compare even those numbers which normally would cause an exception to be
|
||||
raised since they are unordered. E.g., the expression
|
||||
|
||||
@ -774,7 +774,7 @@ All the macros are defined in a way to ensure that both arguments are
|
||||
evaluated exactly once and so they can be used exactly like the builtin
|
||||
operators.
|
||||
|
||||
On several platform these macros are mapped on very efficient functions
|
||||
On several platform these macros are mapped to very efficient functions
|
||||
the processor understands. But on machines missing these functions, the
|
||||
macros above might be rather slow. So it is best to use the builtin
|
||||
operators unless it is necessary to use unordered comparisons.
|
||||
|
@ -142,11 +142,11 @@ But now the POSIX people came and unified the interface with their words
|
||||
possible.
|
||||
|
||||
A solution provides the Unix98 specification which finally introduces a
|
||||
type @code{socklen_t}. This type is used in all of the cases in
|
||||
type @code{socklen_t}. This type is used in all of the cases that were
|
||||
previously changed to use @code{size_t}. The only requirement of this
|
||||
type is that it is an unsigned type of at least 32 bits. Therefore,
|
||||
implementations which require references to 32 bit variables be passed
|
||||
can be as happy as implementations which right from the start of 64 bit
|
||||
can be as happy as implementations which use right from the start 64 bit
|
||||
values.
|
||||
|
||||
|
||||
|
@ -536,6 +536,26 @@ Calling @code{localtime} has one other effect: it sets the variable
|
||||
Zone Functions}.
|
||||
@end deftypefun
|
||||
|
||||
Using the @code{localtime} function is a big problem in multi-threaded
|
||||
programs. The result is returned in a static buffer and this is used in
|
||||
all threads. POSIX.1c introduced a varient of this function.
|
||||
|
||||
@comment time.h
|
||||
@comment POSIX.1c
|
||||
@deftypefun {struct tm *} localtime_r (const time_t *@var{time}, struct tm *@var{resultp})
|
||||
The @code{localtime_r} function works just like the @code{localtime}
|
||||
function. It takes a pointer to a variable containing the calendar time
|
||||
and converts it to the broken-down time format.
|
||||
|
||||
But the result is not placed in a static buffer. Instead it is placed
|
||||
in the object of type @code{struct tm} to which the parameter
|
||||
@var{resultp} points.
|
||||
|
||||
If the conversion is successful the function returns a pointer to the
|
||||
object the result was written into, i.e., it returns @var{resultp}.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@comment time.h
|
||||
@comment ISO
|
||||
@deftypefun {struct tm *} gmtime (const time_t *@var{time})
|
||||
@ -547,6 +567,21 @@ Recall that calendar times are @emph{always} expressed in coordinated
|
||||
universal time.
|
||||
@end deftypefun
|
||||
|
||||
As for the @code{localtime} function we have the problem that the result
|
||||
is placed ina static variable. POSIX.1c also provides a replacement for
|
||||
@code{gmtime}.
|
||||
|
||||
@comment time.h
|
||||
@comment POSIX.1c
|
||||
@deftypefun {struct tm *} gmtime_r (const time_t *@var{time}, struct tm *@var{resultp})
|
||||
This function is similar to @code{localtime_r}, except that it converts
|
||||
just like @code{gmtime} the given time as Coordinated Universal Time.
|
||||
|
||||
If the conversion is successful the function returns a pointer to the
|
||||
object the result was written into, i.e., it returns @var{resultp}.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@comment time.h
|
||||
@comment ISO
|
||||
@deftypefun time_t mktime (struct tm *@var{brokentime})
|
||||
@ -601,6 +636,20 @@ overwritten by subsequent calls to @code{asctime} or @code{ctime}.
|
||||
string.)
|
||||
@end deftypefun
|
||||
|
||||
@comment time.h
|
||||
@comment POSIX.1c
|
||||
@deftypefun {char *} asctime_r (const struct tm *@var{brokentime}, char *@var{buffer})
|
||||
This function is similar to @code{asctime} but instead of placing the
|
||||
result in a static buffer it writes the string in the buffer pointed to
|
||||
by the parameter @var{buffer}. This buffer should have at least room
|
||||
for 16 bytes.
|
||||
|
||||
If no error occurred the function returns a pointer to the string the
|
||||
result was written into, i.e., it returns @var{buffer}. Otherwise
|
||||
return @code{NULL}.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@comment time.h
|
||||
@comment ISO
|
||||
@deftypefun {char *} ctime (const time_t *@var{time})
|
||||
@ -616,6 +665,23 @@ asctime (localtime (@var{time}))
|
||||
does so. @xref{Time Zone Functions}.
|
||||
@end deftypefun
|
||||
|
||||
@comment time.h
|
||||
@comment POSIX.1c
|
||||
@deftypefun {char *} ctime_r (const time_t *@var{time}, char *@var{buffer})
|
||||
This function is similar to @code{ctime}, only that it places the result
|
||||
in the string pointed to by @var{buffer}. It is equivalent to (written
|
||||
using gcc extensions, @xref{Statement Exprs,,,gcc,Porting and Using gcc}.):
|
||||
|
||||
@smallexample
|
||||
(@{ struct tm tm; asctime_r (localtime_r (time, &tm), buf); @})
|
||||
@end smallexample
|
||||
|
||||
If no error occurred the function returns a pointer to the string the
|
||||
result was written into, i.e., it returns @var{buffer}. Otherwise
|
||||
return @code{NULL}.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@comment time.h
|
||||
@comment ISO
|
||||
@comment POSIX.2
|
||||
@ -885,7 +951,7 @@ A literal @samp{%} character.
|
||||
The @var{size} parameter can be used to specify the maximum number of
|
||||
characters to be stored in the array @var{s}, including the terminating
|
||||
null character. If the formatted time requires more than @var{size}
|
||||
characters, @code{strftime} return zero and the content of the array
|
||||
characters, @code{strftime} returns zero and the content of the array
|
||||
@var{s} is indetermined. Otherwise the return value indicates the
|
||||
number of characters placed in the array @var{s}, not including the
|
||||
terminating null character.
|
||||
@ -1095,6 +1161,10 @@ GNU programs it is better to use the @code{tm_zone} member of the
|
||||
broken-down time structure, since @code{tm_zone} reports the correct
|
||||
abbreviation even when it is not the latest one.
|
||||
|
||||
Though the strings are declared as @code{char *} the user must stay away
|
||||
from modifying these strings. Modying the strings will almost certainly
|
||||
lead to trouble.
|
||||
|
||||
@end deftypevar
|
||||
|
||||
@comment time.h
|
||||
|
@ -42,6 +42,9 @@ can use to examine these databases.
|
||||
* 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
|
||||
@ -51,7 +54,7 @@ can use to examine these databases.
|
||||
inquiry functions.
|
||||
@end menu
|
||||
|
||||
@node User and Group IDs, Process Persona, Users and Groups, Users and Groups
|
||||
@node User and Group IDs
|
||||
@section User and Group IDs
|
||||
|
||||
@cindex login name
|
||||
@ -72,7 +75,7 @@ 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, Why Change Persona, User and Group IDs, Users and Groups
|
||||
@node Process Persona
|
||||
@section The Persona of a Process
|
||||
@cindex persona
|
||||
@cindex effective user ID
|
||||
@ -114,7 +117,7 @@ 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, How Change Persona, Process Persona, Users and Groups
|
||||
@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
|
||||
@ -146,7 +149,7 @@ 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, Reading Persona, Why Change Persona, Users and Groups
|
||||
@node How Change Persona
|
||||
@section How an Application Can Change Persona
|
||||
@cindex @code{setuid} programs
|
||||
|
||||
@ -177,7 +180,7 @@ when they are not needed, which makes for more robustness.
|
||||
|
||||
@c !!! talk about _POSIX_SAVED_IDS
|
||||
|
||||
@node Reading Persona, Setting User ID, How Change Persona, Users and Groups
|
||||
@node Reading Persona
|
||||
@section Reading the Persona of a Process
|
||||
|
||||
Here are detailed descriptions of the functions for reading the user and
|
||||
@ -262,7 +265,7 @@ read_all_groups (void)
|
||||
@end smallexample
|
||||
@end deftypefun
|
||||
|
||||
@node Setting User ID, Setting Groups, Reading Persona, Users and Groups
|
||||
@node Setting User ID
|
||||
@section Setting the User ID
|
||||
|
||||
This section describes the functions for altering the user ID (real
|
||||
@ -325,7 +328,7 @@ have permission to change to the specified ID.
|
||||
@end table
|
||||
@end deftypefun
|
||||
|
||||
@node Setting Groups, Enable/Disable Setuid, Setting User ID, Users and Groups
|
||||
@node Setting Groups
|
||||
@section Setting the Group IDs
|
||||
|
||||
This section describes the functions for altering the group IDs (real
|
||||
@ -400,7 +403,7 @@ the user name @var{user}. The group ID @var{gid} is also included.
|
||||
@c groups USER is a member of.
|
||||
@end deftypefun
|
||||
|
||||
@node Enable/Disable Setuid, Setuid Program Example, Setting Groups, Users and Groups
|
||||
@node Enable/Disable Setuid
|
||||
@section Enabling and Disabling Setuid Access
|
||||
|
||||
A typical setuid program does not need its special access all of the
|
||||
@ -466,7 +469,7 @@ feature with a preprocessor conditional, like this:
|
||||
#endif
|
||||
@end smallexample
|
||||
|
||||
@node Setuid Program Example, Tips for Setuid, Enable/Disable Setuid, Users and Groups
|
||||
@node Setuid Program Example
|
||||
@section Setuid Program Example
|
||||
|
||||
Here's an example showing how to set up a program that changes its
|
||||
@ -606,7 +609,7 @@ record_score (int score)
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
@node Tips for Setuid, Who Logged In, Setuid Program Example, Users and Groups
|
||||
@node Tips for Setuid
|
||||
@section Tips for Writing Setuid Programs
|
||||
|
||||
It is easy for setuid programs to give the user access that isn't
|
||||
@ -650,7 +653,7 @@ would ordinarily have permission to access those files. You can use the
|
||||
uses the real user and group IDs, rather than the effective IDs.
|
||||
@end itemize
|
||||
|
||||
@node Who Logged In, User Database, Tips for Setuid, Users and Groups
|
||||
@node Who Logged In
|
||||
@section Identifying Who Logged In
|
||||
@cindex login name, determining
|
||||
@cindex user ID, determining
|
||||
@ -658,7 +661,9 @@ uses the real user and group IDs, rather than the effective IDs.
|
||||
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}).
|
||||
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}.
|
||||
@ -707,7 +712,610 @@ For most purposes, it is more useful to use the environment variable
|
||||
precisely because the user can set @code{LOGNAME} arbitrarily.
|
||||
@xref{Standard Environment}.
|
||||
|
||||
@node User Database, Group Database, Who Logged In, Users and Groups
|
||||
|
||||
@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
|
||||
@ -725,7 +1333,7 @@ network server gives access to it.
|
||||
* Writing a User Entry:: How a program can rewrite a user's record.
|
||||
@end menu
|
||||
|
||||
@node User Data Structure, Lookup User, User Database, User Database
|
||||
@node User Data Structure
|
||||
@subsection The Data Structure that Describes a User
|
||||
|
||||
The functions and data structures for accessing the system user database
|
||||
@ -766,7 +1374,7 @@ be used.
|
||||
@end table
|
||||
@end deftp
|
||||
|
||||
@node Lookup User, Scanning All Users, User Data Structure, User Database
|
||||
@node Lookup User
|
||||
@subsection Looking Up One User
|
||||
@cindex converting user ID to user name
|
||||
@cindex converting user name to user ID
|
||||
@ -839,7 +1447,7 @@ In the later case the global @var{errno} variable is set to
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@node Scanning All Users, Writing a User Entry, Lookup User, User Database
|
||||
@node Scanning All Users
|
||||
@subsection Scanning the List of All Users
|
||||
@cindex scanning the user list
|
||||
|
||||
@ -927,7 +1535,7 @@ This function closes the internal stream used by @code{getpwent} or
|
||||
@code{getpwent_r}.
|
||||
@end deftypefun
|
||||
|
||||
@node Writing a User Entry, , Scanning All Users, User Database
|
||||
@node Writing a User Entry
|
||||
@subsection Writing a User Entry
|
||||
|
||||
@comment pwd.h
|
||||
@ -947,7 +1555,7 @@ would inevitably leave out much of the important information.
|
||||
The function @code{putpwent} is declared in @file{pwd.h}.
|
||||
@end deftypefun
|
||||
|
||||
@node Group Database, Netgroup Database, User Database, Users and Groups
|
||||
@node Group Database
|
||||
@section Group Database
|
||||
@cindex group database
|
||||
@pindex /etc/group
|
||||
@ -963,7 +1571,7 @@ service provides access to it.
|
||||
* Scanning All Groups:: Scanning the list of all groups.
|
||||
@end menu
|
||||
|
||||
@node Group Data Structure, Lookup Group, Group Database, Group Database
|
||||
@node Group Data Structure
|
||||
@subsection The Data Structure for a Group
|
||||
|
||||
The functions and data structures for accessing the system group
|
||||
@ -990,7 +1598,7 @@ null pointer.
|
||||
@end table
|
||||
@end deftp
|
||||
|
||||
@node Lookup Group, Scanning All Groups, Group Data Structure, Group Database
|
||||
@node Lookup Group
|
||||
@subsection Looking Up One Group
|
||||
@cindex converting group name to group ID
|
||||
@cindex converting group ID to group name
|
||||
@ -1061,7 +1669,7 @@ In the later case the global @var{errno} variable is set to
|
||||
@code{ERANGE}.
|
||||
@end deftypefun
|
||||
|
||||
@node Scanning All Groups, , Lookup Group, Group Database
|
||||
@node Scanning All Groups
|
||||
@subsection Scanning the List of All Groups
|
||||
@cindex scanning the group list
|
||||
|
||||
@ -1148,7 +1756,7 @@ This function closes the internal stream used by @code{getgrent} or
|
||||
@code{getgrent_r}.
|
||||
@end deftypefun
|
||||
|
||||
@node Netgroup Database, Database Example, Group Database, Users and Groups
|
||||
@node Netgroup Database
|
||||
@section Netgroup Database
|
||||
|
||||
@menu
|
||||
@ -1158,7 +1766,7 @@ This function closes the internal stream used by @code{getgrent} or
|
||||
* Netgroup Membership:: How to test for netgroup membership.
|
||||
@end menu
|
||||
|
||||
@node Netgroup Data, Lookup Netgroup, Netgroup Database, Netgroup Database
|
||||
@node Netgroup Data
|
||||
@subsection Netgroup Data
|
||||
|
||||
@cindex Netgroup
|
||||
@ -1191,7 +1799,7 @@ 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, Netgroup Membership, Netgroup Data, Netgroup Database
|
||||
@node Lookup Netgroup
|
||||
@subsection Looking up one Netgroup
|
||||
|
||||
The lookup functions for netgroups are a bit different to all other
|
||||
@ -1262,7 +1870,7 @@ selected netgroup. As a result all string pointers returned by calls
|
||||
to @code{getnetgrent} are invalid afterwards.
|
||||
@end deftypefun
|
||||
|
||||
@node Netgroup Membership, , Lookup Netgroup, Netgroup Database
|
||||
@node Netgroup Membership
|
||||
@subsection Testing for Netgroup Membership
|
||||
|
||||
It is often not necessary to scan the whole netgroup since often the
|
||||
@ -1295,7 +1903,7 @@ itself is not found, the netgroup does not contain the triple or
|
||||
internal errors occurred.
|
||||
@end deftypefun
|
||||
|
||||
@node Database Example, , Netgroup Database, Users and Groups
|
||||
@node Database Example
|
||||
@section User and Group Database Example
|
||||
|
||||
Here is an example program showing the use of the system database inquiry
|
||||
|
@ -999,6 +999,7 @@ cbrt_test (void)
|
||||
check_isinfn ("cbrt (-inf) == -inf", FUNC(cbrt) (minus_infty));
|
||||
check_isnan ("cbrt (NaN) == NaN", FUNC(cbrt) (nan_value));
|
||||
#endif
|
||||
check ("cbrt (-0.001) == -0.1", FUNC(cbrt) (-0.001), -0.1);
|
||||
check_eps ("cbrt (8) == 2", FUNC(cbrt) (8), 2, CHOOSE (5e-17L, 0, 0));
|
||||
check_eps ("cbrt (-27) == -3", FUNC(cbrt) (-27.0), -3.0,
|
||||
CHOOSE (3e-16L, 0, 0));
|
||||
|
@ -228,8 +228,21 @@ fe_tests (void)
|
||||
static void
|
||||
feenv_nomask_test (const char *flag_name, int fe_exc)
|
||||
{
|
||||
#if defined FE_NOMASK_ENV
|
||||
int status;
|
||||
pid_t pid;
|
||||
fenv_t saved;
|
||||
|
||||
fegetenv (&saved);
|
||||
errno = 0;
|
||||
fesetenv (FE_NOMASK_ENV);
|
||||
status = errno;
|
||||
fesetenv (&saved);
|
||||
if (status == ENOSYS)
|
||||
{
|
||||
printf ("Test: not testing FE_NOMASK_ENV, it isn't implemented.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf ("Test: after fesetenv (FE_NOMASK_ENV) processes will abort\n");
|
||||
printf (" when feraiseexcept (%s) is called.\n", flag_name);
|
||||
@ -265,6 +278,7 @@ feenv_nomask_test (const char *flag_name, int fe_exc)
|
||||
++count_errors;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Test that program doesn't abort with default environment */
|
||||
|
@ -1 +1 @@
|
||||
NIS(YP)/NIS+ NSS modules 0.12 by Thorsten Kukuk
|
||||
NIS(YP)/NIS+ NSS modules 0.13 by Thorsten Kukuk
|
||||
|
@ -21,7 +21,7 @@
|
||||
#
|
||||
subdir := nis
|
||||
|
||||
headers := $(wildcard rpcsvc/*.[hx]) bits/nislib.h
|
||||
headers := $(wildcard rpcsvc/*.[hx])
|
||||
distribute := nss-nis.h nss-nisplus.h nis_intern.h Banner \
|
||||
nisplus-parser.h
|
||||
|
||||
|
275
nis/nis_cache.c
275
nis/nis_cache.c
@ -20,25 +20,288 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <rpcsvc/nis.h>
|
||||
#include <rpcsvc/nislib.h>
|
||||
#include <rpcsvc/nis_cache.h>
|
||||
#include <bits/libc-lock.h>
|
||||
|
||||
#include "nis_intern.h"
|
||||
|
||||
/* XXX Only dummy functions in the moment. The real implementation
|
||||
will follow, if we have a working nis_cachemgr */
|
||||
static struct timeval TIMEOUT = {10, 0};
|
||||
|
||||
#define HEADER_MAGIC 0x07021971
|
||||
#define SPACER_MAGIC 0x07654321
|
||||
|
||||
#define CACHE_VERSION 0x00000001
|
||||
|
||||
struct cache_header
|
||||
{
|
||||
u_long magic; /* Magic number */
|
||||
u_long vers; /* Cache file format version */
|
||||
u_short tcp_port; /* tcp port of nis_cachemgr */
|
||||
u_short udp_port; /* udp port of nis_cachemgr */
|
||||
u_long entries; /* Number of cached objs. */
|
||||
off_t used; /* How many space are used ? */
|
||||
};
|
||||
typedef struct cache_header cache_header;
|
||||
|
||||
struct cache_spacer
|
||||
{
|
||||
u_long magic; /* Magic number */
|
||||
u_long hashval;
|
||||
time_t ctime; /* time we have created this object */
|
||||
time_t ttl; /* time to life of this object */
|
||||
off_t next_offset;
|
||||
};
|
||||
typedef struct cache_spacer cache_spacer;
|
||||
|
||||
static int cache_fd = -1;
|
||||
static int clnt_sock;
|
||||
static caddr_t maddr = NULL;
|
||||
static size_t msize;
|
||||
static CLIENT *cache_clnt = NULL;
|
||||
|
||||
/* If there is no cachemgr, we shouldn't use NIS_SHARED_DIRCACHE, if
|
||||
there is no NIS_SHARED_DIRCACHE, we couldn't use nis_cachemgr.
|
||||
So, if the clnt_call to nis_cachemgr fails, we also close the cache file.
|
||||
But another thread could read the cache => lock the cache_fd and cache_clnt
|
||||
variables with the same lock */
|
||||
__libc_lock_define_initialized (static, mgrlock)
|
||||
|
||||
/* close file handles and nis_cachemgr connection */
|
||||
static void
|
||||
__cache_close (void)
|
||||
{
|
||||
if (cache_fd != -1)
|
||||
{
|
||||
close (cache_fd);
|
||||
cache_fd = -1;
|
||||
}
|
||||
if (cache_clnt != NULL)
|
||||
{
|
||||
clnt_destroy (cache_clnt);
|
||||
close (clnt_sock);
|
||||
cache_clnt = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* open the cache file and connect to nis_cachemgr */
|
||||
static bool_t
|
||||
__cache_open (void)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
cache_header hptr;
|
||||
|
||||
if ((cache_fd = open (CACHEFILE, O_RDONLY)) == -1)
|
||||
return FALSE;
|
||||
|
||||
if (read (cache_fd, &hptr, sizeof (cache_header)) == -1
|
||||
|| lseek (cache_fd, 0, SEEK_SET) < 0)
|
||||
{
|
||||
close (cache_fd);
|
||||
cache_fd = -1;
|
||||
return FALSE;
|
||||
}
|
||||
if (hptr.magic != HEADER_MAGIC)
|
||||
{
|
||||
close (cache_fd);
|
||||
cache_fd = -1;
|
||||
syslog (LOG_ERR, _("NIS+: cache file is corrupt!"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memset (&sin, '\0', sizeof (sin));
|
||||
sin.sin_family = AF_INET;
|
||||
clnt_sock = RPC_ANYSOCK;
|
||||
sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
||||
sin.sin_port = htons (hptr.tcp_port);
|
||||
cache_clnt = clnttcp_create (&sin, CACHEPROG, CACHE_VER_1, &clnt_sock, 0, 0);
|
||||
if (cache_clnt == NULL)
|
||||
{
|
||||
close (cache_fd);
|
||||
cache_fd = -1;
|
||||
return FALSE;
|
||||
}
|
||||
/* If the program exists, close the socket */
|
||||
if (fcntl (clnt_sock, F_SETFD, FD_CLOEXEC) == -1)
|
||||
perror (_("fcntl: F_SETFD"));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Ask the cache manager to update directory 'name'
|
||||
for us (because the ttl has expired). */
|
||||
static nis_error
|
||||
__cache_refresh (nis_name name)
|
||||
{
|
||||
char clnt_res = 0;
|
||||
nis_error result = NIS_SUCCESS;
|
||||
|
||||
__libc_lock_lock (mgrlock);
|
||||
|
||||
if (cache_clnt == NULL)
|
||||
result = NIS_FAIL;
|
||||
else if (clnt_call (cache_clnt, NIS_CACHE_REFRESH_ENTRY,
|
||||
(xdrproc_t) xdr_wrapstring, (caddr_t) name,
|
||||
(xdrproc_t) xdr_void, &clnt_res, TIMEOUT)
|
||||
!= RPC_SUCCESS)
|
||||
{
|
||||
__cache_close ();
|
||||
result = NIS_FAIL;
|
||||
}
|
||||
|
||||
__libc_lock_unlock (mgrlock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static nis_error
|
||||
__cache_find (const_nis_name name, directory_obj **obj)
|
||||
{
|
||||
unsigned long hash;
|
||||
struct cache_header *hptr;
|
||||
struct cache_spacer *cs;
|
||||
struct directory_obj *dir;
|
||||
XDR xdrs;
|
||||
caddr_t addr, ptr;
|
||||
time_t now = time (NULL);
|
||||
|
||||
if (maddr == NULL)
|
||||
return NIS_FAIL;
|
||||
|
||||
hash = __nis_hash (name, strlen(name));
|
||||
hptr = (cache_header *)maddr;
|
||||
if ((hptr->magic != HEADER_MAGIC) || (hptr->vers != CACHE_VERSION))
|
||||
{
|
||||
syslog (LOG_ERR, _("NIS+: cache file is corrupt!"));
|
||||
return NIS_SYSTEMERROR;
|
||||
}
|
||||
cs = (cache_spacer *)(maddr + sizeof (cache_header));
|
||||
while (cs->next_offset)
|
||||
{
|
||||
if (cs->magic != SPACER_MAGIC)
|
||||
{
|
||||
syslog (LOG_ERR, _("NIS+: cache file is corrupt!"));
|
||||
return NIS_SYSTEMERROR;
|
||||
}
|
||||
if (cs->hashval == hash)
|
||||
{
|
||||
if ((now - cs->ctime) > cs->ttl)
|
||||
return NIS_CACHEEXPIRED;
|
||||
dir = calloc (1, sizeof (directory_obj));
|
||||
addr = (caddr_t)cs + sizeof (cache_spacer);
|
||||
xdrmem_create (&xdrs, addr, cs->next_offset, XDR_DECODE);
|
||||
xdr_directory_obj (&xdrs, dir);
|
||||
xdr_destroy (&xdrs);
|
||||
*obj = dir;
|
||||
return NIS_SUCCESS;
|
||||
}
|
||||
ptr = (caddr_t)cs;
|
||||
ptr += cs->next_offset + sizeof (struct cache_spacer);
|
||||
cs = (struct cache_spacer *)ptr;
|
||||
}
|
||||
return NIS_NOTFOUND;
|
||||
}
|
||||
|
||||
static directory_obj *
|
||||
internal_cache_search (const_nis_name name)
|
||||
{
|
||||
directory_obj *dir;
|
||||
nis_error res;
|
||||
int second_refresh = 0;
|
||||
struct stat s;
|
||||
|
||||
if (cache_fd == -1)
|
||||
if (__cache_open () == FALSE)
|
||||
return NULL;
|
||||
|
||||
again:
|
||||
/* This lock is for nis_cachemgr, so it couldn't write a new cache
|
||||
file if we reading it */
|
||||
if (__nis_lock_cache () == -1)
|
||||
return NULL;
|
||||
|
||||
if (maddr != NULL)
|
||||
munmap (maddr, msize);
|
||||
if (fstat (cache_fd, &s) < 0)
|
||||
maddr = MAP_FAILED;
|
||||
else
|
||||
{
|
||||
msize = s.st_size;
|
||||
maddr = mmap (0, msize, PROT_READ, MAP_SHARED, cache_fd, 0);
|
||||
}
|
||||
if (maddr == MAP_FAILED)
|
||||
{
|
||||
__nis_unlock_cache ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = __cache_find (name, &dir);
|
||||
|
||||
munmap (maddr, msize);
|
||||
maddr = NULL;
|
||||
/* Allow nis_cachemgr to write a new cachefile */
|
||||
__nis_unlock_cache ();
|
||||
|
||||
switch(res)
|
||||
{
|
||||
case NIS_CACHEEXPIRED:
|
||||
if (second_refresh)
|
||||
{
|
||||
__cache_close ();
|
||||
syslog (LOG_WARNING,
|
||||
_("NIS+: nis_cachemgr failed to refresh object for us"));
|
||||
return NULL;
|
||||
}
|
||||
++second_refresh;
|
||||
if (__cache_refresh ((char *) name) != NIS_SUCCESS)
|
||||
return NULL;
|
||||
goto again;
|
||||
break;
|
||||
case NIS_SUCCESS:
|
||||
return dir;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
directory_obj *
|
||||
__cache_search (const_nis_name name)
|
||||
{
|
||||
return NULL;
|
||||
directory_obj *dir;
|
||||
|
||||
__libc_lock_lock (mgrlock);
|
||||
|
||||
dir = internal_cache_search (name);
|
||||
|
||||
__libc_lock_unlock (mgrlock);
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
nis_error
|
||||
nis_error
|
||||
__cache_add (fd_result *fd)
|
||||
{
|
||||
return NIS_FAIL;
|
||||
char clnt_res = 0;
|
||||
nis_error result = NIS_SUCCESS;
|
||||
|
||||
__libc_lock_lock (mgrlock);
|
||||
|
||||
if (cache_clnt == NULL)
|
||||
if (__cache_open () == FALSE)
|
||||
result = NIS_FAIL;
|
||||
|
||||
if (cache_clnt != NULL &&
|
||||
(clnt_call (cache_clnt, NIS_CACHE_ADD_ENTRY, (xdrproc_t) xdr_fd_result,
|
||||
(caddr_t)fd, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT)
|
||||
!= RPC_SUCCESS))
|
||||
{
|
||||
__cache_close ();
|
||||
result = NIS_RPCERROR;
|
||||
}
|
||||
|
||||
__libc_lock_unlock (mgrlock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ internal_setent (int stayopen)
|
||||
stream = fopen (DATAFILE, "r");
|
||||
|
||||
if (stream == NULL)
|
||||
status = NSS_STATUS_UNAVAIL;
|
||||
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
|
||||
else
|
||||
{
|
||||
/* We have to make sure the file is `closed on exec'. */
|
||||
|
@ -49,7 +49,7 @@ internal_setent (void)
|
||||
stream = fopen ("/etc/aliases", "r");
|
||||
|
||||
if (stream == NULL)
|
||||
status = NSS_STATUS_UNAVAIL;
|
||||
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
|
||||
else
|
||||
{
|
||||
/* We have to make sure the file is `closed on exec'. */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Test for string function add boundaries of usable memory.
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||||
|
||||
@ -41,7 +41,7 @@ main (int argc, char *argv[])
|
||||
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
dest = (char *) mmap (NULL, 3*size, PROT_READ|PROT_WRITE,
|
||||
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
if (adr == (char *)-1L || dest == (char *)-1L)
|
||||
if (adr == MAP_FAILED || dest == MAP_FAILED)
|
||||
{
|
||||
if (errno == ENOSYS)
|
||||
puts ("No test, mmap not available.");
|
||||
|
@ -107,6 +107,19 @@ main (void)
|
||||
(void) strcpy (one, "");
|
||||
equal (one, "", 7); /* Boundary condition. */
|
||||
|
||||
/* A closely related function is stpcpy. */
|
||||
it = "stpcpy";
|
||||
check ((stpcpy (one, "abcde") - one) == 5, 1);
|
||||
equal (one, "abcde", 2);
|
||||
|
||||
check ((stpcpy (one, "x") - one) == 1, 3);
|
||||
equal (one, "x", 4); /* Writeover. */
|
||||
equal (one+2, "cde", 5); /* Wrote too much? */
|
||||
|
||||
check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 6);
|
||||
equal (one, "abc", 7);
|
||||
equal (one + 4, "e", 8);
|
||||
|
||||
/* stpncpy. */
|
||||
it = "stpncpy";
|
||||
|
||||
|
@ -64,7 +64,7 @@ routines := auth_none auth_unix authuxprot bindrsvprt \
|
||||
pmap_prot2 pmap_rmt rpc_prot rpc_common rpc_cmsg \
|
||||
svc svc_auth svc_authux svc_raw svc_run svc_simple \
|
||||
svc_tcp svc_udp xdr xdr_array xdr_float xdr_mem \
|
||||
xdr_rec xdr_ref xdr_stdio publickey
|
||||
xdr_rec xdr_ref xdr_stdio publickey xdr_sizeof
|
||||
|
||||
others := rpcinfo
|
||||
install-bin := rpcgen
|
||||
|
@ -288,6 +288,7 @@ extern bool_t xdr_reference __P ((XDR * __xdrs, caddr_t * __pp, u_int __size,
|
||||
extern bool_t xdr_pointer __P ((XDR * __xdrs, char **__objpp,
|
||||
u_int __obj_size, xdrproc_t __xdr_obj));
|
||||
extern bool_t xdr_wrapstring __P ((XDR * __xdrs, char **__cpp));
|
||||
extern u_long xdr_sizeof __P ((xdrproc_t, void *));
|
||||
|
||||
/*
|
||||
* Common opaque bytes objects used by many rpc protocols;
|
||||
|
157
sunrpc/xdr_sizeof.c
Normal file
157
sunrpc/xdr_sizeof.c
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/*
|
||||
* xdr_sizeof.c
|
||||
*
|
||||
* Copyright 1990 Sun Microsystems, Inc.
|
||||
*
|
||||
* General purpose routine to see how much space something will use
|
||||
* when serialized using XDR.
|
||||
*/
|
||||
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* ARGSUSED */
|
||||
static bool_t
|
||||
x_putlong (XDR *xdrs, const long *longp)
|
||||
{
|
||||
xdrs->x_handy += BYTES_PER_XDR_UNIT;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static bool_t
|
||||
x_putbytes (XDR *xdrs, const char *bp, u_int len)
|
||||
{
|
||||
xdrs->x_handy += len;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static u_int
|
||||
x_getpostn (const XDR *xdrs)
|
||||
{
|
||||
return xdrs->x_handy;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static bool_t
|
||||
x_setpostn (XDR *xdrs, u_int len)
|
||||
{
|
||||
/* This is not allowed */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static long *
|
||||
x_inline (XDR *xdrs, int len)
|
||||
{
|
||||
if (len == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (xdrs->x_op != XDR_ENCODE)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (len < (int) xdrs->x_base)
|
||||
{
|
||||
/* x_private was already allocated */
|
||||
xdrs->x_handy += len;
|
||||
return (long *) xdrs->x_private;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Free the earlier space and allocate new area */
|
||||
if (xdrs->x_private)
|
||||
free (xdrs->x_private);
|
||||
if ((xdrs->x_private = (caddr_t) malloc (len)) == NULL)
|
||||
{
|
||||
xdrs->x_base = 0;
|
||||
return NULL;
|
||||
}
|
||||
xdrs->x_base = (caddr_t) len;
|
||||
xdrs->x_handy += len;
|
||||
return (long *) xdrs->x_private;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
harmless (void)
|
||||
{
|
||||
/* Always return FALSE/NULL, as the case may be */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
x_destroy (XDR *xdrs)
|
||||
{
|
||||
xdrs->x_handy = 0;
|
||||
xdrs->x_base = 0;
|
||||
if (xdrs->x_private)
|
||||
{
|
||||
free (xdrs->x_private);
|
||||
xdrs->x_private = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
xdr_sizeof (xdrproc_t func, void *data)
|
||||
{
|
||||
XDR x;
|
||||
struct xdr_ops ops;
|
||||
bool_t stat;
|
||||
/* to stop ANSI-C compiler from complaining */
|
||||
typedef bool_t (*dummyfunc1) (XDR *, long *);
|
||||
typedef bool_t (*dummyfunc2) (XDR *, caddr_t, u_int);
|
||||
|
||||
ops.x_putlong = x_putlong;
|
||||
ops.x_putbytes = x_putbytes;
|
||||
ops.x_inline = x_inline;
|
||||
ops.x_getpostn = x_getpostn;
|
||||
ops.x_setpostn = x_setpostn;
|
||||
ops.x_destroy = x_destroy;
|
||||
|
||||
/* the other harmless ones */
|
||||
ops.x_getlong = (dummyfunc1) harmless;
|
||||
ops.x_getbytes = (dummyfunc2) harmless;
|
||||
|
||||
x.x_op = XDR_ENCODE;
|
||||
x.x_ops = &ops;
|
||||
x.x_handy = 0;
|
||||
x.x_private = (caddr_t) NULL;
|
||||
x.x_base = (caddr_t) 0;
|
||||
|
||||
stat = func (&x, data);
|
||||
if (x.x_private)
|
||||
free (x.x_private);
|
||||
return stat == TRUE ? (unsigned) x.x_handy : 0;
|
||||
}
|
@ -17,7 +17,7 @@
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _UTMP_H
|
||||
#error "Never use <bits/utmp.h> directly; include <utmp.h> instead."
|
||||
# error "Never use <bits/utmp.h> directly; include <utmp.h> instead."
|
||||
#endif
|
||||
|
||||
|
||||
@ -33,21 +33,23 @@
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
struct lastlog {
|
||||
time_t ll_time;
|
||||
char ll_line[UT_LINESIZE];
|
||||
char ll_host[UT_HOSTSIZE];
|
||||
};
|
||||
struct lastlog
|
||||
{
|
||||
time_t ll_time;
|
||||
char ll_line[UT_LINESIZE];
|
||||
char ll_host[UT_HOSTSIZE];
|
||||
};
|
||||
|
||||
struct utmp {
|
||||
char ut_line[UT_LINESIZE];
|
||||
char ut_name[UT_NAMESIZE];
|
||||
char ut_host[UT_HOSTSIZE];
|
||||
long ut_time;
|
||||
};
|
||||
struct utmp
|
||||
{
|
||||
char ut_line[UT_LINESIZE];
|
||||
char ut_user[UT_NAMESIZE];
|
||||
#define ut_name ut_user
|
||||
char ut_host[UT_HOSTSIZE];
|
||||
long int ut_time;
|
||||
};
|
||||
|
||||
|
||||
#define _HAVE_UT_HOST 1 /* We have the ut_host field. */
|
||||
|
||||
|
||||
__END_DECLS
|
||||
|
34
sysdeps/generic/bits/utmpx.h
Normal file
34
sysdeps/generic/bits/utmpx.h
Normal file
@ -0,0 +1,34 @@
|
||||
/* Structures and definitions for the user accounting database. Generic/BSDish
|
||||
Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _UTMPX_H
|
||||
#error "Never use <bits/utmpx.h> directly; include <utmpx.h> instead."
|
||||
#endif
|
||||
|
||||
|
||||
#define __UT_NAMESIZE 8
|
||||
#define __UT_LINESIZE 8
|
||||
#define __UT_HOSTSIZE 16
|
||||
|
||||
struct utmpx
|
||||
{
|
||||
char ut_line[__UT_LINESIZE];
|
||||
char ut_name[__UT_NAMESIZE];
|
||||
char ut_host[__UT_HOSTSIZE];
|
||||
long ut_time;
|
||||
};
|
@ -36,38 +36,48 @@
|
||||
without PROT_READ. The only guarantees are that no writing will be
|
||||
allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */
|
||||
|
||||
#define PROT_NONE 0x00 /* No access. */
|
||||
#define PROT_READ 0x04 /* Pages can be read. */
|
||||
#define PROT_WRITE 0x02 /* Pages can be written. */
|
||||
#define PROT_EXEC 0x01 /* Pages can be executed. */
|
||||
#define PROT_NONE 0x00 /* No access. */
|
||||
#define PROT_READ 0x04 /* Pages can be read. */
|
||||
#define PROT_WRITE 0x02 /* Pages can be written. */
|
||||
#define PROT_EXEC 0x01 /* Pages can be executed. */
|
||||
|
||||
|
||||
/* Flags contain mapping type, sharing type and options. */
|
||||
|
||||
/* Mapping type (must choose one and only one of these). */
|
||||
#define MAP_FILE 0x0001 /* Mapped from a file or device. */
|
||||
#define MAP_ANON 0x0002 /* Allocated from anonymous virtual memory. */
|
||||
#define MAP_TYPE 0x000f /* Mask for type field. */
|
||||
#ifdef __USE_BSD
|
||||
# define MAP_FILE 0x0001 /* Mapped from a file or device. */
|
||||
# define MAP_ANON 0x0002 /* Allocated from anonymous virtual memory. */
|
||||
# define MAP_TYPE 0x000f /* Mask for type field. */
|
||||
#endif
|
||||
|
||||
/* Sharing types (must choose one and only one of these). */
|
||||
#define MAP_COPY 0x0020 /* Virtual copy of region at mapping time. */
|
||||
#define MAP_SHARED 0x0010 /* Share changes. */
|
||||
#define MAP_PRIVATE 0x0000 /* Changes private; copy pages on write. */
|
||||
#ifdef __USE_BSD
|
||||
# define MAP_COPY 0x0020 /* Virtual copy of region at mapping time. */
|
||||
#endif
|
||||
#define MAP_SHARED 0x0010 /* Share changes. */
|
||||
#define MAP_PRIVATE 0x0000 /* Changes private; copy pages on write. */
|
||||
|
||||
/* Other flags. */
|
||||
#define MAP_FIXED 0x0100 /* Map address must be exactly as requested. */
|
||||
#define MAP_NOEXTEND 0x0200 /* For MAP_FILE, don't change file size. */
|
||||
#define MAP_HASSEMPHORE 0x0400 /* Region may contain semaphores. */
|
||||
#define MAP_INHERIT 0x0800 /* Region is retained after exec. */
|
||||
#define MAP_FIXED 0x0100 /* Map address must be exactly as requested. */
|
||||
#ifdef __USE_BSD
|
||||
# define MAP_NOEXTEND 0x0200 /* For MAP_FILE, don't change file size. */
|
||||
# define MAP_HASSEMPHORE 0x0400 /* Region may contain semaphores. */
|
||||
# define MAP_INHERIT 0x0800 /* Region is retained after exec. */
|
||||
#endif
|
||||
|
||||
/* Advice to `madvise'. */
|
||||
#define MADV_NORMAL 0 /* No further special treatment. */
|
||||
#define MADV_RANDOM 1 /* Expect random page references. */
|
||||
#define MADV_SEQUENTIAL 2 /* Expect sequential page references. */
|
||||
#define MADV_WILLNEED 3 /* Will need these pages. */
|
||||
#define MADV_DONTNEED 4 /* Don't need these pages. */
|
||||
#ifdef __USE_BSD
|
||||
# define MADV_NORMAL 0 /* No further special treatment. */
|
||||
# define MADV_RANDOM 1 /* Expect random page references. */
|
||||
# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */
|
||||
# define MADV_WILLNEED 3 /* Will need these pages. */
|
||||
# define MADV_DONTNEED 4 /* Don't need these pages. */
|
||||
#endif
|
||||
|
||||
/* Return value of `mmap' in case of an error. */
|
||||
#define MAP_FAILED ((__caddr_t) -1)
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
/* Map addresses starting near ADDR and extending for LEN bytes. from
|
||||
@ -75,34 +85,36 @@ __BEGIN_DECLS
|
||||
is nonzero, it is the desired mapping address. If the MAP_FIXED bit is
|
||||
set in FLAGS, the mapping will be at ADDR exactly (which must be
|
||||
page-aligned); otherwise the system chooses a convenient nearby address.
|
||||
The return value is the actual mapping address chosen or (caddr_t) -1
|
||||
The return value is the actual mapping address chosen or MAP_FAILED
|
||||
for errors (in which case `errno' is set). A successful `mmap' call
|
||||
deallocates any previous mapping for the affected region. */
|
||||
|
||||
__caddr_t __mmap __P ((__caddr_t __addr, size_t __len,
|
||||
int __prot, int __flags, int __fd, __off_t __offset));
|
||||
__caddr_t mmap __P ((__caddr_t __addr, size_t __len,
|
||||
int __prot, int __flags, int __fd, __off_t __offset));
|
||||
extern __caddr_t __mmap __P ((__caddr_t __addr, size_t __len, int __prot,
|
||||
int __flags, int __fd, __off_t __offset));
|
||||
extern __caddr_t mmap __P ((__caddr_t __addr, size_t __len, int __prot,
|
||||
int __flags, int __fd, __off_t __offset));
|
||||
|
||||
/* Deallocate any mapping for the region starting at ADDR and extending LEN
|
||||
bytes. Returns 0 if successful, -1 for errors (and sets errno). */
|
||||
int __munmap __P ((__caddr_t __addr, size_t __len));
|
||||
int munmap __P ((__caddr_t __addr, size_t __len));
|
||||
extern int __munmap __P ((__caddr_t __addr, size_t __len));
|
||||
extern int munmap __P ((__caddr_t __addr, size_t __len));
|
||||
|
||||
/* Change the memory protection of the region starting at ADDR and
|
||||
extending LEN bytes to PROT. Returns 0 if successful, -1 for errors
|
||||
(and sets errno). */
|
||||
int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot));
|
||||
int mprotect __P ((__caddr_t __addr, size_t __len, int __prot));
|
||||
extern int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot));
|
||||
extern int mprotect __P ((__caddr_t __addr, size_t __len, int __prot));
|
||||
|
||||
/* Synchronize the region starting at ADDR and extending LEN bytes with the
|
||||
file it maps. Filesystem operations on a file being mapped are
|
||||
unpredictable before this is done. Flags are from the MS_* set. */
|
||||
int msync __P ((__caddr_t __addr, size_t __len, int flags));
|
||||
extern int msync __P ((__caddr_t __addr, size_t __len, int __flags));
|
||||
|
||||
#ifdef __USE_BSD
|
||||
/* Advise the system about particular usage patterns the program follows
|
||||
for the region starting at ADDR and extending LEN bytes. */
|
||||
int madvise __P ((__caddr_t __addr, size_t __len, int __advice));
|
||||
extern int madvise __P ((__caddr_t __addr, size_t __len, int __advice));
|
||||
#endif
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
6
sysdeps/i386/i586/stpcpy.S
Normal file
6
sysdeps/i386/i586/stpcpy.S
Normal file
@ -0,0 +1,6 @@
|
||||
#define USE_AS_STPCPY
|
||||
#define STRCPY __stpcpy
|
||||
|
||||
#include <sysdeps/i386/i586/strcpy.S>
|
||||
|
||||
weak_alias (__stpcpy, stpcpy)
|
147
sysdeps/i386/i586/strcpy.S
Normal file
147
sysdeps/i386/i586/strcpy.S
Normal file
@ -0,0 +1,147 @@
|
||||
/* strcpy/stpcpy implementation for i586.
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <sysdep.h>
|
||||
#include "asm-syntax.h"
|
||||
|
||||
#ifndef USE_AS_STPCPY
|
||||
# define STRCPY strcpy
|
||||
#endif
|
||||
|
||||
#define magic 0xfefefeff
|
||||
|
||||
.text
|
||||
ENTRY(STRCPY)
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
|
||||
movl 16(%esp), %edi
|
||||
movl 20(%esp), %esi
|
||||
|
||||
xorl %eax, %eax
|
||||
leal -1(%esi), %ecx
|
||||
|
||||
movl $magic, %ebx
|
||||
andl $3, %ecx
|
||||
|
||||
#ifdef PIC
|
||||
call 2f
|
||||
2: popl %edx
|
||||
/* 0xb is the distance between 2: and 1: but we avoid writing
|
||||
1f-2b because the assembler generates worse code. */
|
||||
leal 0xb(%edx,%ecx,8), %ecx
|
||||
#else
|
||||
leal 1f(,%ecx,8), %ecx
|
||||
#endif
|
||||
|
||||
jmp *%ecx
|
||||
|
||||
.align 8
|
||||
1:
|
||||
orb (%esi), %al
|
||||
jz L(end)
|
||||
stosb
|
||||
xorl %eax, %eax
|
||||
incl %esi
|
||||
|
||||
orb (%esi), %al
|
||||
jz L(end)
|
||||
stosb
|
||||
xorl %eax, %eax
|
||||
incl %esi
|
||||
|
||||
orb (%esi), %al
|
||||
jz L(end)
|
||||
stosb
|
||||
xorl %eax, %eax
|
||||
incl %esi
|
||||
|
||||
L(1): movl (%esi), %ecx
|
||||
leal 4(%esi),%esi
|
||||
|
||||
subl %ecx, %eax
|
||||
addl %ebx, %ecx
|
||||
|
||||
decl %eax
|
||||
jnc L(3)
|
||||
|
||||
movl %ecx, %edx
|
||||
xorl %ecx, %eax
|
||||
|
||||
subl %ebx, %edx
|
||||
andl $~magic, %eax
|
||||
|
||||
jne L(4)
|
||||
|
||||
movl %edx, (%edi)
|
||||
leal 4(%edi),%edi
|
||||
|
||||
jmp L(1)
|
||||
|
||||
L(3): movl %ecx, %edx
|
||||
|
||||
subl %ebx, %edx
|
||||
|
||||
L(4): movb %dl, (%edi)
|
||||
testb %dl, %dl
|
||||
|
||||
movl %edx, %eax
|
||||
jz L(end2)
|
||||
|
||||
shrl $16, %eax
|
||||
movb %dh, 1(%edi)
|
||||
#ifdef USE_AS_STPCPY
|
||||
addl $1, %edi
|
||||
#endif
|
||||
|
||||
cmpb $0, %dh
|
||||
jz L(end2)
|
||||
|
||||
#ifdef USE_AS_STPCPY
|
||||
movb %al, 1(%edi)
|
||||
addl $1, %edi
|
||||
|
||||
cmpb $0, %al
|
||||
jz L(end2)
|
||||
|
||||
addl $1, %edi
|
||||
#else
|
||||
movb %al, 2(%edi)
|
||||
testb %al, %al
|
||||
|
||||
leal 3(%edi), %edi
|
||||
jz L(end2)
|
||||
#endif
|
||||
|
||||
L(end): movb %ah, (%edi)
|
||||
|
||||
L(end2):
|
||||
#ifdef USE_AS_STPCPY
|
||||
movl %edi, %eax
|
||||
#endif
|
||||
popl %ebx
|
||||
popl %esi
|
||||
popl %edi
|
||||
#ifndef USE_AS_STPCPY
|
||||
movl 4(%esp), %eax
|
||||
#endif
|
||||
ret
|
||||
END(STRCPY)
|
@ -1,2 +1,4 @@
|
||||
# Code optimized for i586 is better than simple i386 code.
|
||||
i386/i586
|
||||
# Due to the reordering and the oher nifty extensions in the i686 it is
|
||||
# not really good to use heavily i586 optimized code on a i686. It's
|
||||
# better to use i486/i386 code.
|
||||
i386/i486
|
||||
|
3
sysdeps/libm-i387/e_rem_pio2.c
Normal file
3
sysdeps/libm-i387/e_rem_pio2.c
Normal file
@ -0,0 +1,3 @@
|
||||
/* Empty. This file is only meant to avoid compiling the file with the
|
||||
same name in the libm-ieee754 directory. The code is not used since
|
||||
there is an assembler version for all users of this file. */
|
3
sysdeps/libm-i387/e_rem_pio2f.c
Normal file
3
sysdeps/libm-i387/e_rem_pio2f.c
Normal file
@ -0,0 +1,3 @@
|
||||
/* Empty. This file is only meant to avoid compiling the file with the
|
||||
same name in the libm-ieee754 directory. The code is not used since
|
||||
there is an assembler version for all users of this file. */
|
3
sysdeps/libm-i387/e_rem_pio2l.c
Normal file
3
sysdeps/libm-i387/e_rem_pio2l.c
Normal file
@ -0,0 +1,3 @@
|
||||
/* Empty. This file is only meant to avoid compiling the file with the
|
||||
same name in the libm-ieee754 directory. The code is not used since
|
||||
there is an assembler version for all users of this file. */
|
3
sysdeps/libm-i387/k_rem_pio2.c
Normal file
3
sysdeps/libm-i387/k_rem_pio2.c
Normal file
@ -0,0 +1,3 @@
|
||||
/* Empty. This file is only meant to avoid compiling the file with the
|
||||
same name in the libm-ieee754 directory. The code is not used since
|
||||
there is an assembler version for all users of this file. */
|
3
sysdeps/libm-i387/k_rem_pio2f.c
Normal file
3
sysdeps/libm-i387/k_rem_pio2f.c
Normal file
@ -0,0 +1,3 @@
|
||||
/* Empty. This file is only meant to avoid compiling the file with the
|
||||
same name in the libm-ieee754 directory. The code is not used since
|
||||
there is an assembler version for all users of this file. */
|
3
sysdeps/libm-i387/k_rem_pio2l.c
Normal file
3
sysdeps/libm-i387/k_rem_pio2l.c
Normal file
@ -0,0 +1,3 @@
|
||||
/* Empty. This file is only meant to avoid compiling the file with the
|
||||
same name in the libm-ieee754 directory. The code is not used since
|
||||
there is an assembler version for all users of this file. */
|
@ -28,34 +28,36 @@
|
||||
#endif
|
||||
|
||||
.align ALIGNARG(4)
|
||||
ASM_TYPE_DIRECTIVE(f1,@object)
|
||||
f1: .double 0.354895765043919860
|
||||
ASM_SIZE_DIRECTIVE(f1)
|
||||
ASM_TYPE_DIRECTIVE(f2,@object)
|
||||
f2: .double 1.50819193781584896
|
||||
ASM_SIZE_DIRECTIVE(f2)
|
||||
ASM_TYPE_DIRECTIVE(f3,@object)
|
||||
f3: .double -2.11499494167371287
|
||||
ASM_SIZE_DIRECTIVE(f3)
|
||||
ASM_TYPE_DIRECTIVE(f4,@object)
|
||||
f4: .double 2.44693122563534430
|
||||
ASM_SIZE_DIRECTIVE(f4)
|
||||
ASM_TYPE_DIRECTIVE(f5,@object)
|
||||
f5: .double -1.83469277483613086
|
||||
ASM_SIZE_DIRECTIVE(f5)
|
||||
ASM_TYPE_DIRECTIVE(f6,@object)
|
||||
f6: .double 0.784932344976639262
|
||||
ASM_SIZE_DIRECTIVE(f6)
|
||||
ASM_TYPE_DIRECTIVE(f7,@object)
|
||||
f7: .double -0.145263899385486377
|
||||
ASM_SIZE_DIRECTIVE(f7)
|
||||
ASM_TYPE_DIRECTIVE(f6,@object)
|
||||
f6: .double 0.784932344976639262
|
||||
ASM_SIZE_DIRECTIVE(f6)
|
||||
ASM_TYPE_DIRECTIVE(f5,@object)
|
||||
f5: .double -1.83469277483613086
|
||||
ASM_SIZE_DIRECTIVE(f5)
|
||||
ASM_TYPE_DIRECTIVE(f4,@object)
|
||||
f4: .double 2.44693122563534430
|
||||
ASM_SIZE_DIRECTIVE(f4)
|
||||
ASM_TYPE_DIRECTIVE(f3,@object)
|
||||
f3: .double -2.11499494167371287
|
||||
ASM_SIZE_DIRECTIVE(f3)
|
||||
ASM_TYPE_DIRECTIVE(f2,@object)
|
||||
f2: .double 1.50819193781584896
|
||||
ASM_SIZE_DIRECTIVE(f2)
|
||||
ASM_TYPE_DIRECTIVE(f1,@object)
|
||||
f1: .double 0.354895765043919860
|
||||
ASM_SIZE_DIRECTIVE(f1)
|
||||
|
||||
#define CBRT2 1.2599210498948731648
|
||||
#define SQR_CBRT2 1.5874010519681994748
|
||||
#define CBRT2 1.2599210498948731648
|
||||
#define ONE_CBRT2 0.793700525984099737355196796584
|
||||
#define SQR_CBRT2 1.5874010519681994748
|
||||
#define ONE_SQR_CBRT2 0.629960524947436582364439673883
|
||||
|
||||
ASM_TYPE_DIRECTIVE(factor,@object)
|
||||
factor: .double 1.0 / SQR_CBRT2
|
||||
.double 1.0 / CBRT2
|
||||
factor: .double ONE_SQR_CBRT2
|
||||
.double ONE_CBRT2
|
||||
.double 1.0
|
||||
.double CBRT2
|
||||
.double SQR_CBRT2
|
||||
@ -67,10 +69,10 @@ two54: .byte 0, 0, 0, 0, 0, 0, 0x50, 0x43
|
||||
|
||||
#ifdef PIC
|
||||
#define MO(op) op##@GOTOFF(%ebx)
|
||||
#define MOX(op,x,f) op##@GOTOFF(%ebx,x,f)
|
||||
#define MOX(op,x) op##@GOTOFF(%ebx,x,1)
|
||||
#else
|
||||
#define MO(op) op
|
||||
#define MOX(op,x,f) op(,x,f)
|
||||
#define MOX(op,x) op(x)
|
||||
#endif
|
||||
|
||||
.text
|
||||
@ -102,8 +104,13 @@ ENTRY(__cbrt)
|
||||
#endif
|
||||
fmull MO(two54)
|
||||
movl $-54, %ecx
|
||||
#ifdef PIC
|
||||
fstpl 8(%esp)
|
||||
movl 12(%esp), %eax
|
||||
#else
|
||||
fstpl 4(%esp)
|
||||
movl 8(%esp), %eax
|
||||
#endif
|
||||
movl %eax, %edx
|
||||
andl $0x7fffffff, %eax
|
||||
|
||||
@ -123,11 +130,16 @@ ENTRY(__cbrt)
|
||||
#endif
|
||||
fabs
|
||||
|
||||
/* The following code has two track:
|
||||
/* The following code has two tracks:
|
||||
a) compute the normalized cbrt value
|
||||
b) compute xe/3 and xe%3
|
||||
The right track computes the value for b) and this is done
|
||||
in an optimized way by avoiding division. */
|
||||
in an optimized way by avoiding division.
|
||||
|
||||
But why two tracks at all? Very easy: efficiency. Some FP
|
||||
instruction can overlap with a certain amount of integer (and
|
||||
FP) instructions. So we get (except for the imull) all
|
||||
instructions for free. */
|
||||
|
||||
fld %st(0) /* xm : xm */
|
||||
|
||||
@ -161,20 +173,24 @@ ENTRY(__cbrt)
|
||||
fadd %st(0) /* 2*t2 : t2+2*xm : u : xm */
|
||||
subl %edx, %ecx
|
||||
faddp %st, %st(3) /* t2+2*xm : u : 2*t2+xm */
|
||||
shll $3, %ecx
|
||||
fmulp /* u*(t2+2*xm) : 2*t2+xm */
|
||||
fdivp %st, %st(1) /* u*(t2+2*xm)/(2*t2+xm) */
|
||||
fmull MOX(16+factor,%ecx,8) /* u*(t2+2*xm)/(2*t2+xm)*FACT */
|
||||
fmull MOX(16+factor,%ecx) /* u*(t2+2*xm)/(2*t2+xm)*FACT */
|
||||
pushl %eax
|
||||
fildl (%esp) /* xe/3 : u*(t2+2*xm)/(2*t2+xm)*FACT */
|
||||
fxch /* u*(t2+2*xm)/(2*t2+xm)*FACT : xe/3 */
|
||||
popl %eax
|
||||
fscale /* u*(t2+2*xm)/(2*t2+xm)*FACT*2^xe/3 */
|
||||
fstp %st(1)
|
||||
popl %edx
|
||||
#ifdef PIC
|
||||
movl 12(%esp), %eax
|
||||
popl %ebx
|
||||
#else
|
||||
movl 8(%esp), %eax
|
||||
#endif
|
||||
testl $0x80000000, 8(%esp)
|
||||
jz 4f
|
||||
testl %eax, %eax
|
||||
fstp %st(1)
|
||||
jns 4f
|
||||
fchs
|
||||
4: ret
|
||||
|
||||
|
@ -28,22 +28,25 @@
|
||||
#endif
|
||||
|
||||
.align ALIGNARG(4)
|
||||
ASM_TYPE_DIRECTIVE(f1,@object)
|
||||
f1: .double 0.492659620528969547
|
||||
ASM_SIZE_DIRECTIVE(f1)
|
||||
ASM_TYPE_DIRECTIVE(f2,@object)
|
||||
f2: .double 0.697570460207922770
|
||||
ASM_SIZE_DIRECTIVE(f2)
|
||||
ASM_TYPE_DIRECTIVE(f3,@object)
|
||||
f3: .double 0.191502161678719066
|
||||
ASM_SIZE_DIRECTIVE(f3)
|
||||
ASM_TYPE_DIRECTIVE(f2,@object)
|
||||
f2: .double 0.697570460207922770
|
||||
ASM_SIZE_DIRECTIVE(f2)
|
||||
ASM_TYPE_DIRECTIVE(f1,@object)
|
||||
f1: .double 0.492659620528969547
|
||||
ASM_SIZE_DIRECTIVE(f1)
|
||||
|
||||
#define CBRT2 1.2599210498948731648
|
||||
#define SQR_CBRT2 1.5874010519681994748
|
||||
#define CBRT2 1.2599210498948731648
|
||||
#define ONE_CBRT2 0.793700525984099737355196796584
|
||||
#define SQR_CBRT2 1.5874010519681994748
|
||||
#define ONE_SQR_CBRT2 0.629960524947436582364439673883
|
||||
|
||||
ASM_TYPE_DIRECTIVE(factor,@object)
|
||||
factor: .double 1.0 / SQR_CBRT2
|
||||
.double 1.0 / CBRT2
|
||||
.align ALIGNARG(4)
|
||||
factor: .double ONE_SQR_CBRT2
|
||||
.double ONE_CBRT2
|
||||
.double 1.0
|
||||
.double CBRT2
|
||||
.double SQR_CBRT2
|
||||
@ -55,10 +58,10 @@ two25: .byte 0, 0, 0, 0x4c
|
||||
|
||||
#ifdef PIC
|
||||
#define MO(op) op##@GOTOFF(%ebx)
|
||||
#define MOX(op,x,f) op##@GOTOFF(%ebx,x,f)
|
||||
#define MOX(op,x) op##@GOTOFF(%ebx,x,1)
|
||||
#else
|
||||
#define MO(op) op
|
||||
#define MOX(op,x,f) op(,x,f)
|
||||
#define MOX(op,x) op(x)
|
||||
#endif
|
||||
|
||||
.text
|
||||
@ -114,11 +117,16 @@ ENTRY(__cbrtf)
|
||||
#endif
|
||||
fabs
|
||||
|
||||
/* The following code has two track:
|
||||
/* The following code has two tracks:
|
||||
a) compute the normalized cbrt value
|
||||
b) compute xe/3 and xe%3
|
||||
The right track computes the value for b) and this is done
|
||||
in an optimized way by avoiding division. */
|
||||
in an optimized way by avoiding division.
|
||||
|
||||
But why two tracks at all? Very easy: efficiency. Some FP
|
||||
instruction can overlap with a certain amount of integer (and
|
||||
FP) instructions. So we get (except for the imull) all
|
||||
instructions for free. */
|
||||
|
||||
fld %st(0) /* xm : xm */
|
||||
fmull MO(f3) /* f3*xm : xm */
|
||||
@ -142,20 +150,24 @@ ENTRY(__cbrtf)
|
||||
fadd %st(0) /* 2*t2 : t2+2*xm : u : xm */
|
||||
subl %edx, %ecx
|
||||
faddp %st, %st(3) /* t2+2*xm : u : 2*t2+xm */
|
||||
shll $3, %ecx
|
||||
fmulp /* u*(t2+2*xm) : 2*t2+xm */
|
||||
fdivp %st, %st(1) /* u*(t2+2*xm)/(2*t2+xm) */
|
||||
fmull MOX(16+factor,%ecx,8) /* u*(t2+2*xm)/(2*t2+xm)*FACT */
|
||||
fmull MOX(16+factor,%ecx) /* u*(t2+2*xm)/(2*t2+xm)*FACT */
|
||||
pushl %eax
|
||||
fildl (%esp) /* xe/3 : u*(t2+2*xm)/(2*t2+xm)*FACT */
|
||||
fxch /* u*(t2+2*xm)/(2*t2+xm)*FACT : xe/3 */
|
||||
popl %eax
|
||||
fscale /* u*(t2+2*xm)/(2*t2+xm)*FACT*2^xe/3 */
|
||||
fstp %st(1)
|
||||
popl %edx
|
||||
#ifdef PIC
|
||||
movl 8(%esp), %eax
|
||||
popl %ebx
|
||||
#else
|
||||
movl 4(%esp), %eax
|
||||
#endif
|
||||
testl $0x80000000, 4(%esp)
|
||||
jz 4f
|
||||
testl %eax, %eax
|
||||
fstp %st(1)
|
||||
jns 4f
|
||||
fchs
|
||||
4: ret
|
||||
|
||||
|
@ -28,52 +28,69 @@
|
||||
#endif
|
||||
|
||||
.align ALIGNARG(4)
|
||||
ASM_TYPE_DIRECTIVE(f1,@object)
|
||||
f1: .double 0.338058687610520237
|
||||
ASM_SIZE_DIRECTIVE(f1)
|
||||
ASM_TYPE_DIRECTIVE(f2,@object)
|
||||
f2: .double 1.67595307700780102
|
||||
ASM_SIZE_DIRECTIVE(f2)
|
||||
ASM_TYPE_DIRECTIVE(f3,@object)
|
||||
f3: .double -2.82414939754975962
|
||||
ASM_SIZE_DIRECTIVE(f3)
|
||||
ASM_TYPE_DIRECTIVE(f4,@object)
|
||||
f4: .double 4.09559907378707839
|
||||
ASM_SIZE_DIRECTIVE(f4)
|
||||
ASM_TYPE_DIRECTIVE(f5,@object)
|
||||
f5: .double -4.11151425200350531
|
||||
ASM_SIZE_DIRECTIVE(f5)
|
||||
ASM_TYPE_DIRECTIVE(f6,@object)
|
||||
f6: .double 2.65298938441952296
|
||||
ASM_SIZE_DIRECTIVE(f6)
|
||||
ASM_TYPE_DIRECTIVE(f7,@object)
|
||||
f7: .double -0.988553671195413709
|
||||
ASM_SIZE_DIRECTIVE(f7)
|
||||
ASM_TYPE_DIRECTIVE(f8,@object)
|
||||
f8: .double 0.161617097923756032
|
||||
f8: .tfloat 0.161617097923756032
|
||||
ASM_SIZE_DIRECTIVE(f8)
|
||||
.align ALIGNARG(4)
|
||||
ASM_TYPE_DIRECTIVE(f7,@object)
|
||||
f7: .tfloat -0.988553671195413709
|
||||
ASM_SIZE_DIRECTIVE(f7)
|
||||
.align ALIGNARG(4)
|
||||
ASM_TYPE_DIRECTIVE(f6,@object)
|
||||
f6: .tfloat 2.65298938441952296
|
||||
ASM_SIZE_DIRECTIVE(f6)
|
||||
.align ALIGNARG(4)
|
||||
ASM_TYPE_DIRECTIVE(f5,@object)
|
||||
f5: .tfloat -4.11151425200350531
|
||||
ASM_SIZE_DIRECTIVE(f5)
|
||||
.align ALIGNARG(4)
|
||||
ASM_TYPE_DIRECTIVE(f4,@object)
|
||||
f4: .tfloat 4.09559907378707839
|
||||
ASM_SIZE_DIRECTIVE(f4)
|
||||
.align ALIGNARG(4)
|
||||
ASM_TYPE_DIRECTIVE(f3,@object)
|
||||
f3: .tfloat -2.82414939754975962
|
||||
ASM_SIZE_DIRECTIVE(f3)
|
||||
.align ALIGNARG(4)
|
||||
ASM_TYPE_DIRECTIVE(f2,@object)
|
||||
f2: .tfloat 1.67595307700780102
|
||||
ASM_SIZE_DIRECTIVE(f2)
|
||||
.align ALIGNARG(4)
|
||||
ASM_TYPE_DIRECTIVE(f1,@object)
|
||||
f1: .tfloat 0.338058687610520237
|
||||
ASM_SIZE_DIRECTIVE(f1)
|
||||
|
||||
#define CBRT2 1.2599210498948731648
|
||||
#define SQR_CBRT2 1.5874010519681994748
|
||||
#define CBRT2 1.2599210498948731648
|
||||
#define ONE_CBRT2 0.793700525984099737355196796584
|
||||
#define SQR_CBRT2 1.5874010519681994748
|
||||
#define ONE_SQR_CBRT2 0.629960524947436582364439673883
|
||||
|
||||
/* We make the entries in the following table all 16 bytes
|
||||
wide to avoid having to implement a multiplication by 10. */
|
||||
ASM_TYPE_DIRECTIVE(factor,@object)
|
||||
factor: .double 1.0 / SQR_CBRT2
|
||||
.double 1.0 / CBRT2
|
||||
.double 1.0
|
||||
.double CBRT2
|
||||
.double SQR_CBRT2
|
||||
.align ALIGNARG(4)
|
||||
factor: .tfloat ONE_SQR_CBRT2
|
||||
.byte 0, 0, 0, 0, 0, 0
|
||||
.tfloat ONE_CBRT2
|
||||
.byte 0, 0, 0, 0, 0, 0
|
||||
.tfloat 1.0
|
||||
.byte 0, 0, 0, 0, 0, 0
|
||||
.tfloat CBRT2
|
||||
.byte 0, 0, 0, 0, 0, 0
|
||||
.tfloat SQR_CBRT2
|
||||
ASM_SIZE_DIRECTIVE(factor)
|
||||
|
||||
ASM_TYPE_DIRECTIVE(two64,@object)
|
||||
.align ALIGNARG(4)
|
||||
two64: .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x43
|
||||
ASM_SIZE_DIRECTIVE(two64)
|
||||
|
||||
#ifdef PIC
|
||||
#define MO(op) op##@GOTOFF(%ebx)
|
||||
#define MOX(op,x,f) op##@GOTOFF(%ebx,x,f)
|
||||
#define MOX(op,x) op##@GOTOFF(%ebx,x,1)
|
||||
#else
|
||||
#define MO(op) op
|
||||
#define MOX(op,x,f) op(,x,f)
|
||||
#define MOX(op,x) op(x)
|
||||
#endif
|
||||
|
||||
.text
|
||||
@ -97,7 +114,7 @@ ENTRY(__cbrtl)
|
||||
#endif
|
||||
|
||||
cmpl $0, %eax
|
||||
je 2f
|
||||
jne 2f
|
||||
|
||||
#ifdef PIC
|
||||
fldt 8(%esp)
|
||||
@ -106,8 +123,13 @@ ENTRY(__cbrtl)
|
||||
#endif
|
||||
fmull MO(two64)
|
||||
movl $-64, %ecx
|
||||
#ifdef PIC
|
||||
fstpt 8(%esp)
|
||||
movl 16(%esp), %eax
|
||||
#else
|
||||
fstpt 4(%esp)
|
||||
movl 12(%esp), %eax
|
||||
#endif
|
||||
movl %eax, %edx
|
||||
andl $0x7fff, %eax
|
||||
|
||||
@ -126,31 +148,45 @@ ENTRY(__cbrtl)
|
||||
#endif
|
||||
fabs
|
||||
|
||||
/* The following code has two track:
|
||||
/* The following code has two tracks:
|
||||
a) compute the normalized cbrt value
|
||||
b) compute xe/3 and xe%3
|
||||
The right track computes the value for b) and this is done
|
||||
in an optimized way by avoiding division. */
|
||||
in an optimized way by avoiding division.
|
||||
|
||||
fld %st(0) /* xm : xm */
|
||||
But why two tracks at all? Very easy: efficiency. Some FP
|
||||
instruction can overlap with a certain amount of integer (and
|
||||
FP) instructions. So we get (except for the imull) all
|
||||
instructions for free. */
|
||||
|
||||
fmull MO(f7) /* f7*xm : xm */
|
||||
fldt MO(f8) /* f8 : xm */
|
||||
fmul %st(1) /* f8*xm : xm */
|
||||
|
||||
fldt MO(f7)
|
||||
faddp /* f7+f8*xm : xm */
|
||||
fmul %st(1) /* (f7+f8*xm)*xm : xm */
|
||||
movl $1431655766, %eax
|
||||
faddl MO(f6) /* f6+f7*xm : xm */
|
||||
fldt MO(f6)
|
||||
faddp /* f6+(f7+f8*xm)*xm : xm */
|
||||
imull %ecx
|
||||
fmul %st(1) /* (f6+f7*xm)*xm : xm */
|
||||
fmul %st(1) /* (f6+(f7+f8*xm)*xm)*xm : xm */
|
||||
movl %ecx, %eax
|
||||
faddl MO(f5) /* f5+(f6+f7*xm)*xm : xm */
|
||||
fldt MO(f5)
|
||||
faddp /* f5+(f6+(f7+f8*xm)*xm)*xm : xm */
|
||||
sarl $31, %eax
|
||||
fmul %st(1) /* (f5+(f6+f7*xm)*xm)*xm : xm */
|
||||
fmul %st(1) /* (f5+(f6+(f7+f8*xm)*xm)*xm)*xm : xm */
|
||||
subl %eax, %edx
|
||||
faddl MO(f4) /* f4+(f5+(f6+f7*xm)*xm)*xm : xm */
|
||||
fmul %st(1) /* (f4+(f5+(f6+f7*xm)*xm)*xm)*xm : xm */
|
||||
faddl MO(f3) /* f3+(f4+(f5+(f6+f7*xm)*xm)*xm)*xm : xm */
|
||||
fmul %st(1) /* (f3+(f4+(f5+(f6+f7*xm)*xm)*xm)*xm)*xm : xm */
|
||||
faddl MO(f2) /* f2+(f3+(f4+(f5+(f6+f7*xm)*xm)*xm)*xm)*xm : xm */
|
||||
fmul %st(1) /* (f2+(f3+(f4+(f5+(f6+f7*xm)*xm)*xm)*xm)*xm)*xm : xm */
|
||||
faddl MO(f1) /* u:=f1+(f2+(f3+(f4+(f5+(f6+f7*xm)*xm)*xm)*xm)*xm)*xm : xm */
|
||||
fldt MO(f4)
|
||||
faddp /* f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm : xm */
|
||||
fmul %st(1) /* (f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm)*xm : xm */
|
||||
fldt MO(f3)
|
||||
faddp /* f3+(f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm)*xm : xm */
|
||||
fmul %st(1) /* (f3+(f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm)*xm)*xm : xm */
|
||||
fldt MO(f2)
|
||||
faddp /* f2+(f3+(f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm)*xm)*xm : xm */
|
||||
fmul %st(1) /* (f2+(f3+(f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm)*xm)*xm)*xm : xm */
|
||||
fldt MO(f1)
|
||||
faddp /* u:=f1+(f2+(f3+(f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm)*xm)*xm)*xm : xm */
|
||||
|
||||
fld %st /* u : u : xm */
|
||||
fmul %st(1) /* u*u : u : xm */
|
||||
@ -164,19 +200,24 @@ ENTRY(__cbrtl)
|
||||
fadd %st(0) /* 2*t2 : t2+2*xm : u : xm */
|
||||
subl %edx, %ecx
|
||||
faddp %st, %st(3) /* t2+2*xm : u : 2*t2+xm */
|
||||
shll $4, %ecx
|
||||
fmulp /* u*(t2+2*xm) : 2*t2+xm */
|
||||
fdivp %st, %st(1) /* u*(t2+2*xm)/(2*t2+xm) */
|
||||
fmull MOX(16+factor,%ecx,8) /* u*(t2+2*xm)/(2*t2+xm)*FACT */
|
||||
fldt MOX(32+factor,%ecx)
|
||||
fmulp /* u*(t2+2*xm)/(2*t2+xm)*FACT */
|
||||
pushl %eax
|
||||
fildl (%esp) /* xe/3 : u*(t2+2*xm)/(2*t2+xm)*FACT */
|
||||
fxch /* u*(t2+2*xm)/(2*t2+xm)*FACT : xe/3 */
|
||||
popl %eax
|
||||
fscale /* u*(t2+2*xm)/(2*t2+xm)*FACT*2^xe/3 */
|
||||
fstp %st(1)
|
||||
popl %edx
|
||||
#ifdef PIC
|
||||
movl 16(%esp), %eax
|
||||
popl %ebx
|
||||
#else
|
||||
movl 12(%esp), %eax
|
||||
#endif
|
||||
testl $0x8000, 12(%esp)
|
||||
testl $0x8000, %eax
|
||||
fstp %st(1)
|
||||
jz 4f
|
||||
fchs
|
||||
4: ret
|
||||
|
@ -16,12 +16,8 @@ static char rcsid[] = "$NetBSD: s_isinf.c,v 1.3 1995/05/11 23:20:14 jtc Exp $";
|
||||
#include "math.h"
|
||||
#include "math_private.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
int __isinf(double x)
|
||||
#else
|
||||
int __isinf(x)
|
||||
double x;
|
||||
#endif
|
||||
int
|
||||
__isinf (double x)
|
||||
{
|
||||
int32_t hx,lx;
|
||||
EXTRACT_WORDS(hx,lx,x);
|
||||
|
@ -15,12 +15,8 @@ static char rcsid[] = "$NetBSD: s_isinff.c,v 1.3 1995/05/11 23:20:21 jtc Exp $";
|
||||
#include "math.h"
|
||||
#include "math_private.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
int __isinff(float x)
|
||||
#else
|
||||
int __isinff(x)
|
||||
float x;
|
||||
#endif
|
||||
int
|
||||
__isinff (float x)
|
||||
{
|
||||
int32_t ix,t;
|
||||
GET_FLOAT_WORD(ix,x);
|
||||
|
@ -16,12 +16,8 @@ static char rcsid[] = "$NetBSD: $";
|
||||
#include "math.h"
|
||||
#include "math_private.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
int __isinfl(long double x)
|
||||
#else
|
||||
int __isinfl(x)
|
||||
long double x;
|
||||
#endif
|
||||
int
|
||||
__isinfl (long double x)
|
||||
{
|
||||
int32_t se,hx,lx;
|
||||
GET_LDOUBLE_WORDS(se,hx,lx,x);
|
||||
|
@ -26,40 +26,40 @@
|
||||
#ifdef NO_LONG_DOUBLE
|
||||
/* The `long double' is in fact the IEEE `double' type. */
|
||||
|
||||
/* This code does not presently work. */
|
||||
|
||||
long int
|
||||
__lround (long double x)
|
||||
{
|
||||
int32_t j0;
|
||||
u_int32_t i1, i0;
|
||||
long int result;
|
||||
int sign;
|
||||
|
||||
EXTRACT_WORDS (i0, i1, x);
|
||||
j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
|
||||
sign = (i0 & 0x80000000) != 0 ? -1 : 1;
|
||||
i0 &= 0xfffff;
|
||||
if (j0 < 20)
|
||||
{
|
||||
if (j0 < 0)
|
||||
result = j0 < -1 ? 0 : ((i0 & 0x80000000) ? -1 : 1);
|
||||
result = j0 < -1 ? 0 : sign;
|
||||
else
|
||||
{
|
||||
u_int32_t i = 0xfffff >> j0;
|
||||
i0 |= 0x100000;
|
||||
if (((i0 & i) | i1) == 0)
|
||||
result = (long int) ((i0 & 0xfffff) | 0x100000) >> j0;
|
||||
result = i0 >> j0;
|
||||
else
|
||||
{
|
||||
/* X is not integral. */
|
||||
u_int32_t j = i0 + (0x80000 >> j0);
|
||||
if (j < i0)
|
||||
result = (long int) 0x80000 >> (20 - j0);
|
||||
else
|
||||
result = (j | 0x100000) >> (20 - j0);
|
||||
}
|
||||
/* X is not integral. */
|
||||
result = (i0 + (0x80000 >> j0)) >> (20 - j0);
|
||||
}
|
||||
}
|
||||
else if (j0 >= 8 * sizeof (long int) || j0 > 51)
|
||||
{
|
||||
/* The number is too large. It is left implementation defined
|
||||
what happens. */
|
||||
result = (long int) x;
|
||||
return (long int) x;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -97,7 +97,7 @@ __lround (long double x)
|
||||
}
|
||||
}
|
||||
|
||||
return i0 & 0x80000000 ? -result : result;
|
||||
return sign * result;
|
||||
}
|
||||
#else
|
||||
long int
|
||||
|
3
sysdeps/m68k/fpu/e_rem_pio2.c
Normal file
3
sysdeps/m68k/fpu/e_rem_pio2.c
Normal file
@ -0,0 +1,3 @@
|
||||
/* Empty. This file is only meant to avoid compiling the file with the
|
||||
same name in the libm-ieee754 directory. The code is not used since
|
||||
there is an assembler version for all users of this file. */
|
3
sysdeps/m68k/fpu/e_rem_pio2f.c
Normal file
3
sysdeps/m68k/fpu/e_rem_pio2f.c
Normal file
@ -0,0 +1,3 @@
|
||||
/* Empty. This file is only meant to avoid compiling the file with the
|
||||
same name in the libm-ieee754 directory. The code is not used since
|
||||
there is an assembler version for all users of this file. */
|
3
sysdeps/m68k/fpu/e_rem_pio2l.c
Normal file
3
sysdeps/m68k/fpu/e_rem_pio2l.c
Normal file
@ -0,0 +1,3 @@
|
||||
/* Empty. This file is only meant to avoid compiling the file with the
|
||||
same name in the libm-ieee754 directory. The code is not used since
|
||||
there is an assembler version for all users of this file. */
|
3
sysdeps/m68k/fpu/k_rem_pio2.c
Normal file
3
sysdeps/m68k/fpu/k_rem_pio2.c
Normal file
@ -0,0 +1,3 @@
|
||||
/* Empty. This file is only meant to avoid compiling the file with the
|
||||
same name in the libm-ieee754 directory. The code is not used since
|
||||
there is an assembler version for all users of this file. */
|
3
sysdeps/m68k/fpu/k_rem_pio2f.c
Normal file
3
sysdeps/m68k/fpu/k_rem_pio2f.c
Normal file
@ -0,0 +1,3 @@
|
||||
/* Empty. This file is only meant to avoid compiling the file with the
|
||||
same name in the libm-ieee754 directory. The code is not used since
|
||||
there is an assembler version for all users of this file. */
|
3
sysdeps/m68k/fpu/k_rem_pio2l.c
Normal file
3
sysdeps/m68k/fpu/k_rem_pio2l.c
Normal file
@ -0,0 +1,3 @@
|
||||
/* Empty. This file is only meant to avoid compiling the file with the
|
||||
same name in the libm-ieee754 directory. The code is not used since
|
||||
there is an assembler version for all users of this file. */
|
@ -75,6 +75,27 @@ typedef cthread_key_t __libc_key_t;
|
||||
(*__save_FCT)(__save_ARG); \
|
||||
}
|
||||
|
||||
/* Use mutexes as once control variables. */
|
||||
|
||||
struct __libc_once
|
||||
{
|
||||
__libc_lock_t lock;
|
||||
int done;
|
||||
};
|
||||
|
||||
#define __libc_once_define(CLASS,NAME) \
|
||||
CLASS struct __libc_once NAME = { MUTEX_INITIALZER, 0 }
|
||||
|
||||
|
||||
/* Call handler iff the first call. */
|
||||
#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
|
||||
do { \
|
||||
__libc_lock_lock (ONCE_CONTROL.lock); \
|
||||
if (!ONCE_CONTROL.done) \
|
||||
(INIT_FUNCTION) (); \
|
||||
ONCE_CONTROL.done = 1; \
|
||||
__libc_lock_lock (ONCE_CONTROL.lock); \
|
||||
} while (0)
|
||||
|
||||
#ifdef _LIBC
|
||||
/* We need portable names for some functions. E.g., when they are
|
||||
|
@ -1,3 +1,4 @@
|
||||
errnos.awk err_hurd.sub
|
||||
libc-ldscript
|
||||
libc_p-ldscript
|
||||
cthreads.c
|
||||
|
@ -18,6 +18,9 @@
|
||||
|
||||
ifdef in-Makerules
|
||||
|
||||
subdirs := $(filter-out sunrpc,$(subdirs)) # XXX skip broken dirs
|
||||
# See hurd/Makefile for commands that install some crucial sunrpc headers.
|
||||
|
||||
# Look for header files in hurd/ under the top-level library source directory.
|
||||
# Look for generated header files where they get created.
|
||||
includes += -I$(..)hurd -I$(common-objpfx)hurd/
|
||||
@ -33,7 +36,6 @@ inhibit-unix-syscalls = yes
|
||||
# be compatible with some existing binaries for that system.
|
||||
inhibit-glue = yes
|
||||
|
||||
|
||||
ifeq (,$(filter mach hurd,$(subdir)))
|
||||
# Subdirectories other than hurd/ might use the generated Hurd headers.
|
||||
# So make sure we get a chance to run in hurd/ to make them before all else.
|
||||
@ -48,6 +50,12 @@ $(patsubst %,$(hurd-objpfx)hurd/%.%,auth io fs process):
|
||||
$(MAKE) -C $(..)hurd generated no_deps=t
|
||||
endif
|
||||
|
||||
# Hurd profil.c includes this file, so give a rule to make it.
|
||||
ifeq ($(subdir),gmon)
|
||||
$(common-objpfx)hurd/../mach/RPC_task_get_sampled_pcs.c:
|
||||
$(MAKE) -C $(..)mach generated no_deps=t
|
||||
endif
|
||||
|
||||
|
||||
# Generate errnos.h from the section of the manual that lists all the errno
|
||||
# codes.
|
||||
@ -115,11 +123,6 @@ $(inst_libdir)/libc.so: $(rpcuserlibs)
|
||||
ifeq (elf,$(subdir))
|
||||
$(objpfx)librtld.so: $(rpcuserlibs:.so=_pic.a)
|
||||
endif
|
||||
|
||||
# We need the CThreads interface.
|
||||
ifeq (misc,$(subdir))
|
||||
sysdep_routines += cthreads
|
||||
endif
|
||||
|
||||
|
||||
endif # in-Makerules
|
||||
|
@ -1 +1,2 @@
|
||||
hurd
|
||||
login
|
||||
|
@ -34,10 +34,20 @@ static size_t maxsamples;
|
||||
static size_t pc_offset;
|
||||
static size_t sample_scale;
|
||||
static sampled_pc_seqno_t seqno;
|
||||
static struct mutex lock = MUTEX_INITIALIZER;
|
||||
static spin_lock_t lock = SPIN_LOCK_INITIALIZER;
|
||||
static mach_msg_timeout_t collector_timeout; /* ms between collections. */
|
||||
static int profile_tick;
|
||||
|
||||
/* Reply port used by profiler thread */
|
||||
static mach_port_t profil_reply_port;
|
||||
|
||||
/* Forwards */
|
||||
static kern_return_t profil_task_get_sampled_pcs (mach_port_t,
|
||||
sampled_pc_seqno_t *,
|
||||
sampled_pc_array_t,
|
||||
mach_msg_type_number_t *);
|
||||
static void fetch_samples (void);
|
||||
|
||||
/* Enable statistical profiling, writing samples of the PC into at most
|
||||
SIZE bytes of SAMPLE_BUFFER; every processor clock tick while profiling
|
||||
is enabled, the system examines the user PC and increments
|
||||
@ -87,7 +97,7 @@ update_waiter (u_short *sample_buffer, size_t size, size_t offset, u_int scale)
|
||||
}
|
||||
|
||||
int
|
||||
__profile_frequency ()
|
||||
__profile_frequency (void)
|
||||
{
|
||||
return profile_tick;
|
||||
}
|
||||
@ -97,13 +107,20 @@ profil (u_short *sample_buffer, size_t size, size_t offset, u_int scale)
|
||||
{
|
||||
error_t err;
|
||||
|
||||
__mutex_lock (&lock);
|
||||
__spin_lock (&lock);
|
||||
|
||||
if (scale == 0)
|
||||
{
|
||||
/* Disable profiling. */
|
||||
int count;
|
||||
__thread_suspend (profile_thread);
|
||||
|
||||
if (profile_thread != MACH_PORT_NULL)
|
||||
__thread_suspend (profile_thread);
|
||||
|
||||
/* Fetch the last set of samples */
|
||||
if (sample_scale)
|
||||
fetch_samples ();
|
||||
|
||||
err = __task_disable_pc_sampling (__mach_task_self (), &count);
|
||||
sample_scale = 0;
|
||||
seqno = 0;
|
||||
@ -111,57 +128,102 @@ profil (u_short *sample_buffer, size_t size, size_t offset, u_int scale)
|
||||
else
|
||||
err = update_waiter (sample_buffer, size, offset, scale);
|
||||
|
||||
__mutex_unlock (&lock);
|
||||
__spin_unlock (&lock);
|
||||
|
||||
return err ? __hurd_fail (err) : 0;
|
||||
}
|
||||
|
||||
/* Fetch PC samples. This function must be very careful not to depend
|
||||
on Hurd threadvar variables. We arrange that by using a special
|
||||
stub arranged for at the end of this file. */
|
||||
static void
|
||||
profile_waiter (void)
|
||||
fetch_samples (void)
|
||||
{
|
||||
sampled_pc_t pc_samples[MAX_PC_SAMPLES];
|
||||
mach_msg_type_number_t nsamples, i;
|
||||
mach_port_t rcv = __mach_reply_port ();
|
||||
mach_msg_header_t msg;
|
||||
error_t err;
|
||||
|
||||
nsamples = MAX_PC_SAMPLES;
|
||||
|
||||
err = profil_task_get_sampled_pcs (__mach_task_self (), &seqno,
|
||||
pc_samples, &nsamples);
|
||||
if (err)
|
||||
{
|
||||
static error_t special_profil_failure;
|
||||
static volatile int a, b, c;
|
||||
|
||||
special_profil_failure = err;
|
||||
a = 1;
|
||||
b = 0;
|
||||
while (1)
|
||||
c = a / b;
|
||||
}
|
||||
|
||||
for (i = 0; i < nsamples; ++i)
|
||||
{
|
||||
/* Do arithmetic in long long to avoid overflow problems. */
|
||||
long long pc_difference = pc_samples[i].pc - pc_offset;
|
||||
size_t idx = ((pc_difference / 2) * sample_scale) / 65536;
|
||||
if (idx < maxsamples)
|
||||
++samples[idx];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* This function must be very careful not to depend on Hurd threadvar
|
||||
variables. We arrange that by using special stubs arranged for at the
|
||||
end of this file. */
|
||||
static void
|
||||
profile_waiter (void)
|
||||
{
|
||||
mach_msg_header_t msg;
|
||||
mach_port_t timeout_reply_port;
|
||||
|
||||
profil_reply_port = __mach_reply_port ();
|
||||
timeout_reply_port = __mach_reply_port ();
|
||||
|
||||
while (1)
|
||||
{
|
||||
__mutex_lock (&lock);
|
||||
__spin_lock (&lock);
|
||||
|
||||
nsamples = sizeof pc_samples / sizeof pc_samples[0];
|
||||
err = __task_get_sampled_pcs (__mach_task_self (), &seqno,
|
||||
pc_samples, &nsamples);
|
||||
assert_perror (err);
|
||||
fetch_samples ();
|
||||
|
||||
for (i = 0; i < nsamples; ++i)
|
||||
{
|
||||
size_t idx = (((pc_samples[i].pc - pc_offset) / 2) *
|
||||
sample_scale / 65536);
|
||||
if (idx < maxsamples)
|
||||
++samples[idx];
|
||||
}
|
||||
|
||||
__vm_deallocate (__mach_task_self (),
|
||||
(vm_address_t) pc_samples,
|
||||
nsamples * sizeof *pc_samples);
|
||||
|
||||
__mutex_unlock (&lock);
|
||||
__spin_unlock (&lock);
|
||||
|
||||
__mach_msg (&msg, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0, sizeof msg,
|
||||
rcv, collector_timeout, MACH_PORT_NULL);
|
||||
timeout_reply_port, collector_timeout, MACH_PORT_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
data_set_element (_hurd_fork_locks, lock);
|
||||
/* Fork interaction */
|
||||
|
||||
/* Before fork, lock the interlock so that we are in a clean state. */
|
||||
static void
|
||||
fork_profil (void)
|
||||
fork_profil_prepare (void)
|
||||
{
|
||||
__spin_lock (&lock);
|
||||
}
|
||||
text_set_element (_hurd_fork_prepare_hook, fork_profil_prepare);
|
||||
|
||||
/* In the parent, unlock the interlock once fork is complete. */
|
||||
static void
|
||||
fork_profil_parent (void)
|
||||
{
|
||||
__spin_unlock (&lock);
|
||||
}
|
||||
text_set_element (_hurd_fork_parent_hook, fork_profil_parent);
|
||||
|
||||
/* In the childs, unlock the interlock, and start a profiling thread up
|
||||
if necessary. */
|
||||
static void
|
||||
fork_profil_child (void)
|
||||
{
|
||||
u_short *sb;
|
||||
size_t n, o, ss;
|
||||
error_t err;
|
||||
|
||||
__spin_unlock (&lock);
|
||||
|
||||
if (profile_thread != MACH_PORT_NULL)
|
||||
{
|
||||
__mach_port_deallocate (__mach_task_self (), profile_thread);
|
||||
@ -183,4 +245,37 @@ fork_profil (void)
|
||||
assert_perror (err);
|
||||
}
|
||||
}
|
||||
text_set_element (_hurd_fork_child_hook, fork_profil);
|
||||
text_set_element (_hurd_fork_child_hook, fork_profil_child);
|
||||
|
||||
|
||||
|
||||
|
||||
/* Special RPC stubs for profile_waiter are made by including the normal
|
||||
source code, with special CPP state to prevent it from doing the
|
||||
usual thing. */
|
||||
|
||||
/* Include these first; then our #define's will take full effect, not
|
||||
being overridden. */
|
||||
#include <mach/mig_support.h>
|
||||
|
||||
/* This need not do anything; it is always associated with errors, which
|
||||
are fatal in profile_waiter anyhow. */
|
||||
#define __mig_put_reply_port(foo)
|
||||
|
||||
/* Use our static variable instead of the usual threadvar mechanism for
|
||||
this. */
|
||||
#define __mig_get_reply_port() profil_reply_port
|
||||
|
||||
/* Make the functions show up as static */
|
||||
#define mig_external static
|
||||
|
||||
/* Turn off the attempt to generate ld aliasing records. */
|
||||
#undef weak_alias
|
||||
#define weak_alias(a,b)
|
||||
|
||||
/* And change their names to avoid confusing disasters. */
|
||||
#define __vm_deallocate_rpc profil_vm_deallocate
|
||||
#define __task_get_sampled_pcs profil_task_get_sampled_pcs
|
||||
|
||||
/* And include the source code */
|
||||
#include <../mach/RPC_task_get_sampled_pcs.c>
|
||||
|
@ -1 +1,3 @@
|
||||
setjmp_aux.c
|
||||
rtld-ldscript.in
|
||||
rtld-parms
|
||||
|
@ -1 +1,2 @@
|
||||
setjmp_aux.c
|
||||
rtld-parms
|
||||
|
1
sysdeps/mips/mipsel/Dist
Normal file
1
sysdeps/mips/mipsel/Dist
Normal file
@ -0,0 +1 @@
|
||||
rtld-parms
|
@ -32,7 +32,7 @@
|
||||
{ \
|
||||
_IOMAGIC, \
|
||||
NULL, NULL, NULL, NULL, 0, \
|
||||
(PTR) fd, \
|
||||
(void *) fd, \
|
||||
{ readwrite, /* ... */ }, \
|
||||
{ NULL, NULL, NULL, NULL, NULL }, \
|
||||
{ NULL, NULL }, \
|
||||
|
@ -1,2 +1,3 @@
|
||||
fenv_const.c
|
||||
fenv_libc.h
|
||||
quad_float.h
|
||||
|
@ -1,3 +1,13 @@
|
||||
ifeq ($(subdir),math)
|
||||
libm-support += fenv_const
|
||||
libm-support += fenv_const fe_nomask t_sqrt
|
||||
|
||||
# These routines have not been tested, so it's probable they don't work;
|
||||
# and they don't provide the complete list of FP routines. So there's
|
||||
# no point in compiling them.
|
||||
#sysdep_routines += q_feq q_fne q_utoq q_dtoq q_itoq q_stoq q_neg q_ulltoq \
|
||||
# q_lltoq q_qtou q_qtoi q_qtoull q_qtoll q_qtos
|
||||
|
||||
tests += test-arith test-arithf
|
||||
LDLIBS-test-arith = libm
|
||||
LDLIBS-test-arithf = libm
|
||||
endif
|
||||
|
@ -37,9 +37,10 @@ enum
|
||||
/* ... except for FE_INVALID, for which we use bit 31. FE_INVALID
|
||||
actually corresponds to bits 7 through 12 and 21 through 23
|
||||
in the FPSCR, but we can't use that because the current draft
|
||||
says that it must be a power of 2. Instead we use bit 24 which
|
||||
is the enable bit for all the FE_INVALID exceptions. */
|
||||
FE_INVALID = 1 << 31-24,
|
||||
says that it must be a power of 2. Instead we use bit 2 which
|
||||
is the summary bit for all the FE_INVALID exceptions, which
|
||||
kind of makes sense. */
|
||||
FE_INVALID = 1 << 31-2,
|
||||
#define FE_INVALID FE_INVALID
|
||||
|
||||
#ifdef __USE_GNU
|
||||
@ -69,19 +70,22 @@ enum
|
||||
FE_INVALID_IMZ = 1 << 31-11,
|
||||
#define FE_INVALID_IMZ FE_INVALID_IMZ
|
||||
|
||||
/* Comparison with NaN or SNaN. */
|
||||
/* Comparison with NaN or SNaN. */
|
||||
FE_INVALID_COMPARE = 1 << 31-12,
|
||||
#define FE_INVALID_COMPARE FE_INVALID_COMPARE
|
||||
|
||||
/* Invalid operation flag for software (not set by hardware). */
|
||||
/* Invalid operation flag for software (not set by hardware). */
|
||||
/* Note that some chips don't have this implemented, presumably
|
||||
because no-one expected anyone to write software for them %-). */
|
||||
FE_INVALID_SOFTWARE = 1 << 31-21,
|
||||
#define FE_INVALID_SOFTWARE FE_INVALID_SOFTWARE
|
||||
|
||||
/* Square root of negative number (including -Inf). */
|
||||
/* Square root of negative number (including -Inf). */
|
||||
/* Note that some chips don't have this implemented. */
|
||||
FE_INVALID_SQRT = 1 << 31-22,
|
||||
#define FE_INVALID_SQRT FE_INVALID_SQRT
|
||||
|
||||
/* Conversion-to-integer of a NaN or a number too large or too small. */
|
||||
/* Conversion-to-integer of a NaN or a number too large or too small. */
|
||||
FE_INVALID_INTEGER_CONVERSION = 1 << 31-23,
|
||||
#define FE_INVALID_INTEGER_CONVERSION FE_INVALID_INTEGER_CONVERSION
|
||||
|
||||
@ -122,7 +126,53 @@ extern const fenv_t __fe_dfl_env;
|
||||
#define FE_DFL_ENV (&__fe_dfl_env)
|
||||
|
||||
#ifdef __USE_GNU
|
||||
/* Floating-point environment where none of the exceptions are masked. */
|
||||
extern const fenv_t __fe_nomask_env;
|
||||
# define FE_NOMASK_ENV (&__fe_nomask_env)
|
||||
/* Floating-point environment where all exceptions are enabled. Note that
|
||||
this is not sufficient to give you SIGFPE. */
|
||||
extern const fenv_t __fe_enabled_env;
|
||||
# define FE_ENABLED_ENV (&__fe_enabled_env)
|
||||
|
||||
/* Floating-point environment with (processor-dependent) non-IEEE floating
|
||||
point. */
|
||||
extern const fenv_t __fe_nonieee_env;
|
||||
# define FE_NONIEEE_ENV (&__fe_nonieee_env)
|
||||
|
||||
/* Floating-point environment with all exceptions enabled. Note that
|
||||
just evaluating this value will set the processor into 'FPU
|
||||
exceptions imprecise recoverable' mode, which may cause a significant
|
||||
performance penalty (but have no other visible effect). */
|
||||
extern const fenv_t *__fe_nomask_env __P ((void));
|
||||
# define FE_NOMASK_ENV (__fe_nomask_env ())
|
||||
#endif
|
||||
|
||||
#ifdef __OPTIMIZE__
|
||||
/* Inline definition for fegetround. */
|
||||
# define fegetround() \
|
||||
(__extension__ ({ int __fegetround_result; \
|
||||
__asm__ ("mcrfs 7,7 ; mfcr %0" \
|
||||
: "=r"(__fegetround_result) : : "cr7"); \
|
||||
__fegetround_result & 3; }))
|
||||
|
||||
/* Inline definition for feraiseexcept. */
|
||||
# define feraiseexcept(__excepts) \
|
||||
(__extension__ ({ if (__builtin_constant_p (__excepts) \
|
||||
&& ((__excepts) & -(__excepts)) == 0 \
|
||||
&& (__excepts) != FE_INVALID) { \
|
||||
if ((__excepts) != 0) \
|
||||
__asm__ __volatile__ \
|
||||
("mtfsb1 %0" \
|
||||
: : "i"(32 - __builtin_ffs (__excepts))); \
|
||||
} else \
|
||||
(feraiseexcept) (__excepts); }))
|
||||
|
||||
/* Inline definition for feclearexcept. */
|
||||
# define feclearexcept(__excepts) \
|
||||
(__extension__ ({ if (__builtin_constant_p (__excepts) \
|
||||
&& ((__excepts) & -(__excepts)) == 0 \
|
||||
&& (__excepts) != FE_INVALID) { \
|
||||
if ((__excepts) != 0) \
|
||||
__asm__ __volatile__ \
|
||||
("mtfsb0 %0" \
|
||||
: : "i"(32 - __builtin_ffs (__excepts))); \
|
||||
} else \
|
||||
(feclearexcept) (__excepts); }))
|
||||
#endif /* __OPTIMIZE__ */
|
||||
|
@ -30,7 +30,7 @@
|
||||
#ifdef __GNUC__
|
||||
#if __STDC__ == 1
|
||||
|
||||
/* In GNU or ANSI mode, gcc leaves `float' expressions as-is, I think. */
|
||||
/* In GNU or ANSI mode, gcc leaves `float' expressions as-is. */
|
||||
typedef float float_t; /* `float' expressions are evaluated as
|
||||
`float'. */
|
||||
typedef double double_t; /* `double' expressions are evaluated as
|
||||
@ -70,3 +70,7 @@ typedef double double_t;
|
||||
#define INFINITY HUGE_VAL
|
||||
|
||||
#endif
|
||||
|
||||
/* The values returned by `ilogb' for 0 and NaN respectively. */
|
||||
#define FP_ILOGB0 0x80000001
|
||||
#define FP_ILOGBNAN 0x7fffffff
|
||||
|
@ -57,10 +57,11 @@
|
||||
#define OPCODE_LI(rd,simm) OPCODE_ADDI(rd,0,simm)
|
||||
#define OPCODE_SLWI(ra,rs,sh) OPCODE_RLWINM(ra,rs,sh,0,31-sh)
|
||||
|
||||
#define PPC_DCBST(where) asm __volatile__ ("dcbst 0,%0" : : "r"(where))
|
||||
#define PPC_SYNC asm __volatile__ ("sync")
|
||||
#define PPC_ISYNC asm __volatile__ ("sync; isync")
|
||||
#define PPC_ICBI(where) asm __volatile__ ("icbi 0,%0" : : "r"(where))
|
||||
#define PPC_DCBST(where) asm volatile ("dcbst 0,%0" : : "r"(where))
|
||||
#define PPC_SYNC asm volatile ("sync")
|
||||
#define PPC_ISYNC asm volatile ("sync; isync")
|
||||
#define PPC_ICBI(where) asm volatile ("icbi 0,%0" : : "r"(where))
|
||||
#define PPC_DIE asm volatile ("tweq 0,0")
|
||||
|
||||
/* Use this when you've modified some code, but it won't be in the
|
||||
instruction fetch queue (or when it doesn't matter if it is). */
|
||||
@ -147,9 +148,9 @@ elf_machine_load_address (void)
|
||||
/* The PLT uses Elf32_Rela relocs. */
|
||||
#define elf_machine_relplt elf_machine_rela
|
||||
|
||||
/* This code is used in dl-runtime.c to call the `fixup' function
|
||||
and then redirect to the address it returns. It is called
|
||||
from code built in the PLT by elf_machine_runtime_setup. */
|
||||
/* This code is used in dl-runtime.c to call the `fixup' function
|
||||
and then redirect to the address it returns. It is called
|
||||
from code built in the PLT by elf_machine_runtime_setup. */
|
||||
#define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\
|
||||
.section \".text\"
|
||||
.align 2
|
||||
@ -511,11 +512,14 @@ elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc)
|
||||
static inline void
|
||||
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
|
||||
const Elf32_Sym *sym, const struct r_found_version *version,
|
||||
Elf32_addr *const reloc_addr)
|
||||
Elf32_Addr *const reloc_addr)
|
||||
{
|
||||
#ifndef RTLD_BOOTSTRAP
|
||||
const Elf32_Sym *const refsym = sym;
|
||||
#endif
|
||||
Elf32_Word loadbase, finaladdr;
|
||||
const int rinfo = ELF32_R_TYPE (reloc->r_info);
|
||||
extern char **_dl_argv;
|
||||
|
||||
if (rinfo == R_PPC_NONE)
|
||||
return;
|
||||
@ -598,7 +602,6 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
|
||||
if (sym->st_size > refsym->st_size
|
||||
|| (_dl_verbose && sym->st_size < refsym->st_size))
|
||||
{
|
||||
extern char **_dl_argv;
|
||||
const char *strtab;
|
||||
|
||||
strtab = ((void *) map->l_addr
|
||||
@ -631,11 +634,31 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
|
||||
plt = (Elf32_Word *)((char *)map->l_addr
|
||||
+ map->l_info[DT_PLTGOT]->d_un.d_val);
|
||||
index = (reloc_addr - plt - PLT_INITIAL_ENTRY_WORDS)/2;
|
||||
|
||||
if (index >= PLT_DOUBLE_SIZE)
|
||||
{
|
||||
/* Slots greater than or equal to 2^13 have 4 words available
|
||||
instead of two. */
|
||||
/* FIXME: There are some possible race conditions in this code,
|
||||
when called from 'fixup'.
|
||||
|
||||
1) Suppose that a lazy PLT entry is executing, a
|
||||
context switch between threads (or a signal) occurs,
|
||||
and the new thread or signal handler calls the same
|
||||
lazy PLT entry. Then the PLT entry would be changed
|
||||
while it's being run, which will cause a segfault
|
||||
(almost always).
|
||||
|
||||
2) Suppose the reverse: that a lazy PLT entry is
|
||||
being updated, a context switch occurs, and the new
|
||||
code calls the lazy PLT entry that is being updated.
|
||||
Then the half-fixed PLT entry will be executed, which
|
||||
will also almost always cause a segfault.
|
||||
|
||||
These problems don't happen with the 2-word entries, because
|
||||
only one of the two instructions are changed when a lazy
|
||||
entry is retargeted at the actual PLT entry; the li
|
||||
instruction stays the same (we have to update it anyway,
|
||||
because we might not be updating a lazy PLT entry). */
|
||||
reloc_addr[0] = OPCODE_LI (11, finaladdr);
|
||||
reloc_addr[1] = OPCODE_ADDIS (11, 11, finaladdr + 0x8000 >> 16);
|
||||
reloc_addr[2] = OPCODE_MTCTR (11);
|
||||
@ -648,19 +671,27 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
|
||||
num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
|
||||
/ sizeof(Elf32_Rela));
|
||||
|
||||
plt[index+PLT_DATA_START_WORDS (num_plt_entries)] = finaladdr;
|
||||
reloc_addr[0] = OPCODE_LI (11, index*4);
|
||||
reloc_addr[1] =
|
||||
OPCODE_B (-(4*(index*2
|
||||
+ 1
|
||||
- PLT_LONGBRANCH_ENTRY_WORDS
|
||||
+ PLT_INITIAL_ENTRY_WORDS)));
|
||||
plt[index+PLT_DATA_START_WORDS (num_plt_entries)] = finaladdr;
|
||||
}
|
||||
}
|
||||
MODIFIED_CODE (reloc_addr);
|
||||
}
|
||||
else
|
||||
assert (! "unexpected dynamic reloc type");
|
||||
{
|
||||
#ifdef RTLD_BOOTSTRAP
|
||||
PPC_DIE; /* There is no point calling _dl_sysdep_error, it
|
||||
almost certainly hasn't been relocated properly. */
|
||||
#else
|
||||
_dl_sysdep_error (_dl_argv[0] ?: "<program name unknown>",
|
||||
": Unknown relocation type\n", NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (rinfo == R_PPC_ADDR16_LO ||
|
||||
rinfo == R_PPC_ADDR16_HI ||
|
||||
|
141
sysdeps/powerpc/e_sqrt.c
Normal file
141
sysdeps/powerpc/e_sqrt.c
Normal file
@ -0,0 +1,141 @@
|
||||
/* Single-precision floating point square root.
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <math.h>
|
||||
#include <math_private.h>
|
||||
#include <fenv_libc.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
static const double almost_half = 0.5000000000000001; /* 0.5 + 2^-53 */
|
||||
static const uint32_t a_nan = 0x7fc00000;
|
||||
static const uint32_t a_inf = 0x7f800000;
|
||||
static const float two108 = 3.245185536584267269e+32;
|
||||
static const float twom54 = 5.551115123125782702e-17;
|
||||
extern const float __t_sqrt[1024];
|
||||
|
||||
/* The method is based on a description in
|
||||
Computation of elementary functions on the IBM RISC System/6000 processor,
|
||||
P. W. Markstein, IBM J. Res. Develop, 34(1) 1990.
|
||||
Basically, it consists of two interleaved Newton-Rhapson approximations,
|
||||
one to find the actual square root, and one to find its reciprocal
|
||||
without the expense of a division operation. The tricky bit here
|
||||
is the use of the POWER/PowerPC multiply-add operation to get the
|
||||
required accuracy with high speed.
|
||||
|
||||
The argument reduction works by a combination of table lookup to
|
||||
obtain the initial guesses, and some careful modification of the
|
||||
generated guesses (which mostly runs on the integer unit, while the
|
||||
Newton-Rhapson is running on the FPU). */
|
||||
double
|
||||
__sqrt(double x)
|
||||
{
|
||||
const float inf = *(const float *)&a_inf;
|
||||
/* x = f_wash(x); *//* This ensures only one exception for SNaN. */
|
||||
if (x > 0)
|
||||
{
|
||||
if (x != inf)
|
||||
{
|
||||
/* Variables named starting with 's' exist in the
|
||||
argument-reduced space, so that 2 > sx >= 0.5,
|
||||
1.41... > sg >= 0.70.., 0.70.. >= sy > 0.35... .
|
||||
Variables named ending with 'i' are integer versions of
|
||||
floating-point values. */
|
||||
double sx; /* The value of which we're trying to find the
|
||||
square root. */
|
||||
double sg,g; /* Guess of the square root of x. */
|
||||
double sd,d; /* Difference between the square of the guess and x. */
|
||||
double sy; /* Estimate of 1/2g (overestimated by 1ulp). */
|
||||
double sy2; /* 2*sy */
|
||||
double e; /* Difference between y*g and 1/2 (se = e * fsy). */
|
||||
double shx; /* == sx * fsg */
|
||||
double fsg; /* sg*fsg == g. */
|
||||
fenv_t fe; /* Saved floating-point environment (stores rounding
|
||||
mode and whether the inexact exception is
|
||||
enabled). */
|
||||
uint32_t xi0, xi1, sxi, fsgi;
|
||||
const float *t_sqrt;
|
||||
|
||||
fe = fegetenv_register();
|
||||
EXTRACT_WORDS (xi0,xi1,x);
|
||||
relax_fenv_state();
|
||||
sxi = xi0 & 0x3fffffff | 0x3fe00000;
|
||||
INSERT_WORDS (sx, sxi, xi1);
|
||||
t_sqrt = __t_sqrt + (xi0 >> 52-32-8-1 & 0x3fe);
|
||||
sg = t_sqrt[0];
|
||||
sy = t_sqrt[1];
|
||||
|
||||
/* Here we have three Newton-Rhapson iterations each of a
|
||||
division and a square root and the remainder of the
|
||||
argument reduction, all interleaved. */
|
||||
sd = -(sg*sg - sx);
|
||||
fsgi = xi0 + 0x40000000 >> 1 & 0x7ff00000;
|
||||
sy2 = sy + sy;
|
||||
sg = sy*sd + sg; /* 16-bit approximation to sqrt(sx). */
|
||||
INSERT_WORDS (fsg, fsgi, 0);
|
||||
e = -(sy*sg - almost_half);
|
||||
sd = -(sg*sg - sx);
|
||||
if ((xi0 & 0x7ff00000) == 0)
|
||||
goto denorm;
|
||||
sy = sy + e*sy2;
|
||||
sg = sg + sy*sd; /* 32-bit approximation to sqrt(sx). */
|
||||
sy2 = sy + sy;
|
||||
e = -(sy*sg - almost_half);
|
||||
sd = -(sg*sg - sx);
|
||||
sy = sy + e*sy2;
|
||||
shx = sx * fsg;
|
||||
sg = sg + sy*sd; /* 64-bit approximation to sqrt(sx),
|
||||
but perhaps rounded incorrectly. */
|
||||
sy2 = sy + sy;
|
||||
g = sg * fsg;
|
||||
e = -(sy*sg - almost_half);
|
||||
d = -(g*sg - shx);
|
||||
sy = sy + e*sy2;
|
||||
fesetenv_register (fe);
|
||||
return g + sy*d;
|
||||
denorm:
|
||||
/* For denormalised numbers, we normalise, calculate the
|
||||
square root, and return an adjusted result. */
|
||||
fesetenv_register (fe);
|
||||
return __sqrt(x * two108) * twom54;
|
||||
}
|
||||
}
|
||||
else if (x < 0)
|
||||
{
|
||||
#ifdef FE_INVALID_SQRT
|
||||
feraiseexcept (FE_INVALID_SQRT);
|
||||
/* For some reason, some PowerPC processors don't implement
|
||||
FE_INVALID_SQRT. I guess no-one ever thought they'd be
|
||||
used for square roots... :-) */
|
||||
if (!fetestexcept (FE_INVALID))
|
||||
#endif
|
||||
feraiseexcept (FE_INVALID);
|
||||
#ifndef _IEEE_LIBM
|
||||
if (_LIB_VERSION != _IEEE_)
|
||||
x = __kernel_standard(x,x,26);
|
||||
else
|
||||
#endif
|
||||
x = *(const float*)&a_nan;
|
||||
}
|
||||
return f_wash(x);
|
||||
}
|
||||
|
||||
weak_alias (__sqrt, sqrt)
|
||||
/* Strictly, this is wrong, but the only places where _ieee754_sqrt is
|
||||
used will not pass in a negative result. */
|
||||
strong_alias(__sqrt,__ieee754_sqrt)
|
136
sysdeps/powerpc/e_sqrtf.c
Normal file
136
sysdeps/powerpc/e_sqrtf.c
Normal file
@ -0,0 +1,136 @@
|
||||
/* Single-precision floating point square root.
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <math.h>
|
||||
#include <math_private.h>
|
||||
#include <fenv_libc.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
static const float almost_half = 0.50000006; /* 0.5 + 2^-24 */
|
||||
static const uint32_t a_nan = 0x7fc00000;
|
||||
static const uint32_t a_inf = 0x7f800000;
|
||||
static const float two48 = 281474976710656.0;
|
||||
static const float twom24 = 5.9604644775390625e-8;
|
||||
extern const float __t_sqrt[1024];
|
||||
|
||||
/* The method is based on a description in
|
||||
Computation of elementary functions on the IBM RISC System/6000 processor,
|
||||
P. W. Markstein, IBM J. Res. Develop, 34(1) 1990.
|
||||
Basically, it consists of two interleaved Newton-Rhapson approximations,
|
||||
one to find the actual square root, and one to find its reciprocal
|
||||
without the expense of a division operation. The tricky bit here
|
||||
is the use of the POWER/PowerPC multiply-add operation to get the
|
||||
required accuracy with high speed.
|
||||
|
||||
The argument reduction works by a combination of table lookup to
|
||||
obtain the initial guesses, and some careful modification of the
|
||||
generated guesses (which mostly runs on the integer unit, while the
|
||||
Newton-Rhapson is running on the FPU). */
|
||||
float
|
||||
__sqrtf(float x)
|
||||
{
|
||||
const float inf = *(const float *)&a_inf;
|
||||
/* x = f_washf(x); *//* This ensures only one exception for SNaN. */
|
||||
if (x > 0)
|
||||
{
|
||||
if (x != inf)
|
||||
{
|
||||
/* Variables named starting with 's' exist in the
|
||||
argument-reduced space, so that 2 > sx >= 0.5,
|
||||
1.41... > sg >= 0.70.., 0.70.. >= sy > 0.35... .
|
||||
Variables named ending with 'i' are integer versions of
|
||||
floating-point values. */
|
||||
float sx; /* The value of which we're trying to find the square
|
||||
root. */
|
||||
float sg,g; /* Guess of the square root of x. */
|
||||
float sd,d; /* Difference between the square of the guess and x. */
|
||||
float sy; /* Estimate of 1/2g (overestimated by 1ulp). */
|
||||
float sy2; /* 2*sy */
|
||||
float e; /* Difference between y*g and 1/2 (note that e==se). */
|
||||
float shx; /* == sx * fsg */
|
||||
float fsg; /* sg*fsg == g. */
|
||||
fenv_t fe; /* Saved floating-point environment (stores rounding
|
||||
mode and whether the inexact exception is
|
||||
enabled). */
|
||||
uint32_t xi, sxi, fsgi;
|
||||
const float *t_sqrt;
|
||||
|
||||
GET_FLOAT_WORD (xi, x);
|
||||
fe = fegetenv_register ();
|
||||
relax_fenv_state ();
|
||||
sxi = xi & 0x3fffffff | 0x3f000000;
|
||||
SET_FLOAT_WORD (sx, sxi);
|
||||
t_sqrt = __t_sqrt + (xi >> 23-8-1 & 0x3fe);
|
||||
sg = t_sqrt[0];
|
||||
sy = t_sqrt[1];
|
||||
|
||||
/* Here we have three Newton-Rhapson iterations each of a
|
||||
division and a square root and the remainder of the
|
||||
argument reduction, all interleaved. */
|
||||
sd = -(sg*sg - sx);
|
||||
fsgi = xi + 0x40000000 >> 1 & 0x7f800000;
|
||||
sy2 = sy + sy;
|
||||
sg = sy*sd + sg; /* 16-bit approximation to sqrt(sx). */
|
||||
e = -(sy*sg - almost_half);
|
||||
SET_FLOAT_WORD (fsg, fsgi);
|
||||
sd = -(sg*sg - sx);
|
||||
sy = sy + e*sy2;
|
||||
if ((xi & 0x7f800000) == 0)
|
||||
goto denorm;
|
||||
shx = sx * fsg;
|
||||
sg = sg + sy*sd; /* 32-bit approximation to sqrt(sx),
|
||||
but perhaps rounded incorrectly. */
|
||||
sy2 = sy + sy;
|
||||
g = sg * fsg;
|
||||
e = -(sy*sg - almost_half);
|
||||
d = -(g*sg - shx);
|
||||
sy = sy + e*sy2;
|
||||
fesetenv_register (fe);
|
||||
return g + sy*d;
|
||||
denorm:
|
||||
/* For denormalised numbers, we normalise, calculate the
|
||||
square root, and return an adjusted result. */
|
||||
fesetenv_register (fe);
|
||||
return __sqrtf(x * two48) * twom24;
|
||||
}
|
||||
}
|
||||
else if (x < 0)
|
||||
{
|
||||
#ifdef FE_INVALID_SQRT
|
||||
feraiseexcept (FE_INVALID_SQRT);
|
||||
/* For some reason, some PowerPC processors don't implement
|
||||
FE_INVALID_SQRT. I guess no-one ever thought they'd be
|
||||
used for square roots... :-) */
|
||||
if (!fetestexcept (FE_INVALID))
|
||||
#endif
|
||||
feraiseexcept (FE_INVALID);
|
||||
#ifndef _IEEE_LIBM
|
||||
if (_LIB_VERSION != _IEEE_)
|
||||
x = __kernel_standard(x,x,126);
|
||||
else
|
||||
#endif
|
||||
x = *(const float*)&a_nan;
|
||||
}
|
||||
return f_washf(x);
|
||||
}
|
||||
|
||||
weak_alias (__sqrtf, sqrtf)
|
||||
/* Strictly, this is wrong, but the only places where _ieee754_sqrt is
|
||||
used will not pass in a negative result. */
|
||||
strong_alias(__sqrtf,__ieee754_sqrtf)
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <fenv_libc.h>
|
||||
|
||||
#undef feclearexcept
|
||||
void
|
||||
feclearexcept (int excepts)
|
||||
{
|
||||
@ -28,7 +29,8 @@ feclearexcept (int excepts)
|
||||
u.fenv = fegetenv_register ();
|
||||
|
||||
/* Clear the relevant bits. */
|
||||
u.l[1] = u.l[1] & ~FE_to_sticky (excepts);
|
||||
u.l[1] = u.l[1] & ~(-((excepts) >> 31-FPSCR_VX & 1) & FE_ALL_INVALID
|
||||
| (excepts) & FPSCR_STICKY_BITS);
|
||||
|
||||
/* Put the new state in effect. */
|
||||
fesetenv_register (u.fenv);
|
||||
|
32
sysdeps/powerpc/fe_nomask.c
Normal file
32
sysdeps/powerpc/fe_nomask.c
Normal file
@ -0,0 +1,32 @@
|
||||
/* Procedure definition for FE_NOMASK_ENV.
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <fenv.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* This is presently a stub, until it's decided how the kernels should
|
||||
support this. */
|
||||
|
||||
const fenv_t *
|
||||
__fe_nomask_env(void)
|
||||
{
|
||||
__set_errno (ENOSYS);
|
||||
return FE_ENABLED_ENV;
|
||||
}
|
||||
stub_warning (__fe_nomask_env)
|
@ -19,13 +19,11 @@
|
||||
|
||||
#include <fenv_libc.h>
|
||||
|
||||
#undef fegetround
|
||||
int
|
||||
fegetround (void)
|
||||
{
|
||||
fenv_union_t u;
|
||||
|
||||
u.fenv = fegetenv_register ();
|
||||
|
||||
/* The rounding mode is bits 30 and 31 of the FPSCR. */
|
||||
return u.l[1] & 3;
|
||||
int result;
|
||||
asm ("mcrfs 7,7 ; mfcr %0" : "=r"(result) : : "cr7"); \
|
||||
return result & 3;
|
||||
}
|
||||
|
@ -25,5 +25,9 @@ const unsigned long long __fe_dfl_env __attribute__ ((aligned (8))) =
|
||||
0xfff8000000000000ULL;
|
||||
|
||||
/* Floating-point environment where none of the exceptions are masked. */
|
||||
const unsigned long long __fe_nomask_env __attribute__ ((aligned (8))) =
|
||||
const unsigned long long __fe_enabled_env __attribute__ ((aligned (8))) =
|
||||
0xfff80000000000f8ULL;
|
||||
|
||||
/* Floating-point environment with the NI bit set. */
|
||||
const unsigned long long __fe_nonieee_env __attribute__ ((aligned (8))) =
|
||||
0xfff8000000000004ULL;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user