aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog108
-rw-r--r--aout/Makefile30
-rwxr-xr-xconfig.guess12
-rw-r--r--csu/gmon-start.c4
-rw-r--r--elf/Makefile3
-rw-r--r--elf/dl-load.c7
-rw-r--r--elf/dl-profile.c267
-rw-r--r--elf/dl-reloc.c3
-rw-r--r--elf/dl-runtime.c71
-rw-r--r--elf/dl-support.c4
-rw-r--r--elf/do-rel.h6
-rw-r--r--elf/dynamic-link.h13
-rw-r--r--elf/link.h13
-rw-r--r--elf/rtld.c32
-rw-r--r--gmon/bb_exit_func.c6
-rw-r--r--gmon/gmon.c26
-rw-r--r--gmon/sys/gmon.h5
-rw-r--r--gmon/sys/gmon_out.h2
-rw-r--r--include/sys/gmon_out.h1
-rw-r--r--inet/netinet/icmp6.h270
-rw-r--r--inet/netinet/in.h96
-rw-r--r--inet/netinet/ip6.h101
-rw-r--r--libc.map2
-rw-r--r--manual/libc.texinfo2
-rw-r--r--manual/socket.texi134
-rw-r--r--manual/texinfo.tex17
-rw-r--r--nis/Makefile3
-rw-r--r--nis/TODO1
-rw-r--r--nis/lckcache.c8
-rw-r--r--nis/nis_call.c251
-rw-r--r--nis/nis_findserv.c251
-rw-r--r--nis/nis_intern.h24
-rw-r--r--nis/nis_lookup.c4
-rw-r--r--nis/nis_ping.c8
-rw-r--r--nis/nis_table.c6
-rw-r--r--nis/nis_util.c16
-rw-r--r--nis/nss_compat/compat-grp.c29
-rw-r--r--nis/nss_compat/compat-pwd.c43
-rw-r--r--nis/nss_compat/compat-spwd.c29
-rw-r--r--nis/ypclnt.c16
-rw-r--r--nss/nss_db/db-XXX.c24
-rw-r--r--nss/nss_db/db-alias.c22
-rw-r--r--nss/nss_db/db-netgrp.c20
-rw-r--r--nss/nss_files/files-XXX.c21
-rw-r--r--nss/nss_files/files-alias.c23
-rw-r--r--nss/nss_files/files-hosts.c20
-rw-r--r--posix/sys/types.h1
-rw-r--r--string/string.h13
-rw-r--r--sysdeps/alpha/dl-machine.h6
-rw-r--r--sysdeps/generic/htons.c2
-rw-r--r--sysdeps/i386/dl-machine.h51
-rw-r--r--sysdeps/i386/fpu/bits/mathinline.h868
-rw-r--r--sysdeps/m68k/bits/byteswap.h63
-rw-r--r--sysdeps/m68k/dl-machine.h7
-rw-r--r--sysdeps/mips/dl-machine.h6
-rw-r--r--sysdeps/mips/mips64/dl-machine.h6
-rw-r--r--sysdeps/powerpc/dl-machine.h6
-rw-r--r--sysdeps/sparc/dl-machine.h2
-rw-r--r--sysdeps/sparc64/dl-machine.h6
-rw-r--r--sysdeps/unix/sysv/linux/bits/socket.h8
60 files changed, 2180 insertions, 919 deletions
diff --git a/ChangeLog b/ChangeLog
index 842ed6f0dc..b57649c6d2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,111 @@
+1997-07-28 23:35 Ulrich Drepper <drepper@cygnus.com>
+
+ * csu/gmon-start.c (__gmon_start__): Call __monstartup not
+ monstartup.
+ * gmon/gmon.c: Rename moncontrol to __moncontrol and monstartup
+ to __monstartup.
+ * gmon/sys/gmon.h: Fix prototypes.
+ * gmon/sys/gmon_out.h: Pretty print.
+
+ * gmon/bb_exit_func.c (__bb_exit_func): Use memcpy instead of bcopy.
+ * gmon/gmon.c (__monstartup): Likewise.
+ (write_hist): Remove dependency on 32 int.
+ (_mcleanup): Don't call perror, use fprintf.
+
+ * elf/dl-load.c: Fix handling of current directory in search path.
+
+ * elf/Makefile (dl-routines): Add dl-profile.
+ * elf/dl-profile.c: New file.
+ * elf/dl-runtime.c (fixup): Add new parameter with address to store
+ relocation result in to elf_machine_relplt.
+ (profile_fixup): New function.
+ * elf/do-rel.h (elf_dynamic_do_rel): Add new parameter with address
+ to store relocation result in to elf_machine_relplt.
+ * elf/dl-support.c: Define _dl_profile and _dl_profile_map.
+ * elf/dynamic-link.h (ELF_DYNAMIC_RELOCATE): Add new parameter and
+ call elf_machine_runtime_setup with extra argument.
+ * elf/dl-reloc.c (_dl_relocate_object): Add new argument to
+ ELF_DYNAMIC_RELOCATE.
+ * elf/link.h: Add prototypes for new functions and variables.
+ * elf/rtld.c: Parse LD_PROFILE and LD_PROFILE_OUTPUT environment
+ variables and call _dl_start_profile if necessary.
+ * include/sys/gmon_out.h: New file.
+ * sysdeps/alpha/dl-machine.h (elf_machine_runtime_setup): Add
+ new parameter to enable profiling.
+ (elf_machine_rela): Add new parameter to specify place to store
+ result in.
+ * sysdeps/m68k/dl-machine.h: Likewise.
+ * sysdeps/mips/dl-machine.h: Likewise.
+ * sysdeps/mips/mips64/dl-machine.h: Likewise.
+ * sysdeps/powerpc/dl-machine.h: Likewise.
+ * sysdeps/sparc/dl-machine.h: Likewise.
+ * sysdeps/sparc64/dl-machine.h: Likewise.
+ * sysdeps/i386/dl-machine.h: Likewise.
+ (elf_machine_runtime_setup): Setup got[2] to _dl_runtime_resolve if
+ we do profiling.
+ (ELF_MACHINE_RUNTIME_TRAMPOLINE): Add code for _dl_runtime_profile.
+
+ * nis/nss_compat/compat-grp.c (internal_setgrent): Set FD_CLOEXEC
+ for stream on input file.
+ * nis/nss_compat/compat-pwd.c (internal_setpwent): Likewise.
+ * nis/nss_compat/compat-spwd.c (internal_setspent): Likewise.
+ * nss/nss_db/db-XXX.c (internal_setent): Likewise.
+ * nss/nss_db/db-alias.c (internal_setent): Likewise.
+ * nss/nss_db/db-netgrp.c (internal_setent): Likewise.
+ * nss/nss_files/files-XXX.c (internal_setent): Likewise.
+ * nss/nss_files/files-alias.c (internal_setent): Likewise.
+ * nss/nss_files/files-netgrp.c (internal_setent): Likewise.
+
+ * string/string.h: Pretty print.
+
+ * sysdeps/i386/fpu/bits/mathinline.h: Major update by John Bowman.
+ Add float and long double versions.
+
+1997-07-27 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * elf/rtld.c (print_unresolved): Replace empty object name by main
+ program name.
+
+1997-07-27 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * sysdeps/generic/htons.c (htons): Renamed from __htons.
+
+1997-07-27 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * sysdeps/m68k/bits/byteswap.h: New file.
+
+1997-07-27 23:50 Philip Blundell <Philip.Blundell@pobox.com>
+
+ * inet/netinet/icmp6.h: Update for new drafts of POSIX.1g and IPv6
+ advanced API.
+ * inet/netinet/in.h: Likewise.
+ * inet/netinet/ip6.h: Likewise.
+ * sysdeps/unix/sysv/linux/bits/socket.h: Likewise.
+ * posix/sys/types.h: Add socklen_t.
+
+ * manual/socket.texi: Document some more IPv6 things.
+ * manual/libc.texinfo: Likewise.
+
+1997-07-26 Andreas Jaeger <aj@arthur.rhein-neckar.de>
+
+ * libc.map: Define missing symbol.
+
+1997-07-27 14:31 Thorsten Kukuk <kukuk@vt.uni-paderborn.de>
+
+ * nis/Makefile: Add nis_findserv.
+ * nis/lckcache.c: Fix typo.
+ * nis/nis_call.c: Fix problems with multihomed servers.
+ * nis/nis_findserv.c: New file.
+ * nis/nis_intern.h: Add more prototypes.
+ * nis/nis_lookup.c (nis_lookup): Don't try the next server if network
+ is unreachable.
+ * nis/nis_table.c (nis_list): Likewise.
+ * nis/nis_ping.c (nis_ping): Use MASTER_ONLY, don't call abort()
+ in error case.
+ * nis/nis_util.c (__nis_finddirectory): Give the right error code
+ back.
+ * nis/ypclnt.c: Make sure, that all sockets are closed.
+
1997-07-26 04:14 Ulrich Drepper <drepper@cygnus.com>
* elf/Makefile (distribute): Add genrtldtbl.awk.
diff --git a/aout/Makefile b/aout/Makefile
new file mode 100644
index 0000000000..b1e2d643be
--- /dev/null
+++ b/aout/Makefile
@@ -0,0 +1,30 @@
+# Makefile for aout subdirectory of GNU C Library.
+
+# Copyright (C) 1995, 1996, 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.
+
+subdir := aout
+
+headers =
+routines = enbl-secure
+
+all: # Make this the default target; it will be defined in Rules.
+
+include ../Makeconfig
+include ../Rules
+
diff --git a/config.guess b/config.guess
index a73a8d93c0..ee2742b9e0 100755
--- a/config.guess
+++ b/config.guess
@@ -157,6 +157,18 @@ EOF
sun3*:SunOS:*:*)
echo m68k-sun-sunos${UNAME_RELEASE}
exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
aushp:SunOS:*:*)
echo sparc-auspex-sunos${UNAME_RELEASE}
exit 0 ;;
diff --git a/csu/gmon-start.c b/csu/gmon-start.c
index 02c44e2fcf..8c66905a3b 100644
--- a/csu/gmon-start.c
+++ b/csu/gmon-start.c
@@ -1,5 +1,5 @@
/* Code to enable profiling at program startup.
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 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
@@ -50,7 +50,7 @@ __gmon_start__ (void)
#endif
/* Start keeping profiling records. */
- monstartup ((u_long) &_start, (u_long) &etext);
+ __monstartup ((u_long) &_start, (u_long) &etext);
/* Call _mcleanup before exiting; it will write out gmon.out from the
collected data. */
diff --git a/elf/Makefile b/elf/Makefile
index e44711471b..904099cbeb 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -27,7 +27,8 @@ routines = $(dl-routines) dl-open dl-close dl-symbol dl-support \
# The core dynamic linking functions are in libc for the static and
# profiled libraries.
dl-routines = $(addprefix dl-,load cache lookup object reloc deps \
- runtime error init fini debug misc)
+ runtime error init fini debug misc \
+ profile)
# But they are absent from the shared libc, because that code is in ld.so.
elide-routines.so = $(dl-routines) dl-support enbl-secure
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 1301e73996..f7c2c53f7e 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -193,7 +193,10 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
"cannot create cache for search path");
dirp->dirnamelen = len;
- dirp->dirstatus = unknown;
+ /* We have to make sure all the relative directories are never
+ ignored. The current directory might change and all our
+ saved information would be void. */
+ dirp->dirstatus = cp[0] != '/' ? existing : unknown;
/* Add the name of the machine dependent directory if a machine
is defined. */
@@ -212,7 +215,7 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
tmp[len + _dl_platformlen + 1] = '\0';
dirp->dirname = tmp;
- dirp->machdirstatus = unknown;
+ dirp->machdirstatus = dirp->dirstatus;
if (max_dirnamelen < dirp->machdirnamelen)
max_dirnamelen = dirp->machdirnamelen;
diff --git a/elf/dl-profile.c b/elf/dl-profile.c
new file mode 100644
index 0000000000..cc25b6105f
--- /dev/null
+++ b/elf/dl-profile.c
@@ -0,0 +1,267 @@
+/* Profiling of shared libraries.
+ 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 <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <link.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/gmon.h>
+#include <sys/gmon_out.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+/* The LD_PROFILE feature has to be implemented different to the
+ normal profiling using the gmon/ functions. The problem is that an
+ arbitrary amount of processes simulataneously can be run using
+ profiling and all write the results in the same file. To provide
+ this mechanism one could implement a complicated mechanism to merge
+ the content of two profiling runs or one could extend the file
+ format to allow more than one data set. For the second solution we
+ would have the problem that the file can grow in size beyond any
+ limit and both solutions have the problem that the concurrency of
+ writing the results is a big problem.
+
+ Another much simpler method is to use mmap to map the same file in
+ all using programs and modify the data in the mmap'ed area and so
+ also automatically on the disk. Using the MAP_SHARED option of
+ mmap(2) this can be done without big problems in more than one
+ file.
+
+ 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. */
+
+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));
+ };
+
+static struct here_cg_arc_record *data;
+
+
+void
+_dl_start_profile (struct link_map *map, const char *output_dir)
+{
+ char *filename;
+ int fd;
+ struct stat st;
+ 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;
+
+ /* Compute the size of the sections which contain program code. */
+ for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
+ if (ph->p_type == PT_LOAD && (ph->p_flags & PF_X))
+ {
+ ElfW(Addr) start = (ph->p_vaddr & ~(_dl_pagesize - 1));
+ ElfW(Addr) end = ((ph->p_vaddr + ph->p_memsz + _dl_pagesize - 1)
+ & ~(_dl_pagesize - 1));
+
+ if (start < mapstart)
+ mapstart = start;
+ if (end > mapend)
+ mapend = end;
+ }
+
+ /* 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;
+ 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);
+
+ expected_size = (sizeof (struct gmon_hdr)
+ + 1 + sizeof (struct gmon_hist_hdr)
+ + ((1 + sizeof (struct gmon_cg_arc_record))
+ * (param.fromssize / sizeof (*param.froms))));
+
+ /* 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;
+
+ /* 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.prof_rate = __profile_frequency ();
+ strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen));
+ hist_hdr.dimen_abbrev = 's';
+
+ /* First determine the output name. We write in the directory
+ OUTPUT_DIR and the name is composed from the shared objects
+ soname (or the file name) and the ending ".profile". */
+ filename = (char *) alloca (strlen (output_dir) + 1 + strlen (_dl_profile)
+ + sizeof ".profile");
+ __stpcpy (__stpcpy (__stpcpy (__stpcpy (filename, output_dir), "/"),
+ _dl_profile),
+ ".profile");
+
+ fd = __open (filename, O_RDWR | O_CREAT, 0666);
+ if (fd == -1)
+ /* We cannot write the profiling data so don't do anthing. */
+ return;
+
+ if (fstat (fd, &st) < 0 || !S_ISREG (st.st_mode))
+ {
+ /* Not stat'able or not a regular file => don't use it. */
+ close (fd);
+ return;
+ }
+
+ /* Test the size. If it does not match what we expect from the size
+ values in the map MAP we don't use it and warn the user. */
+ if (st.st_size == 0)
+ {
+ /* We have to create the file. */
+ char buf[_dl_pagesize];
+
+ memset (buf, '\0', _dl_pagesize);
+
+ if (__lseek (fd, expected_size & ~(_dl_pagesize - 1), SEEK_SET) == -1)
+ {
+ char buf[400];
+ int errnum;
+ cannot_create:
+ errnum = errno;
+ __close (fd);
+ fprintf (stderr, "%s: cannot create file: %s\n", filename,
+ _strerror_internal (errnum, buf, sizeof buf));
+ return;
+ }
+
+ if (TEMP_FAILURE_RETRY (__write (fd, buf, (expected_size
+ & (_dl_pagesize - 1)))) < 0)
+ goto cannot_create;
+ }
+ else if (st.st_size != expected_size)
+ {
+ __close (fd);
+ wrong_format:
+ fprintf (stderr, "%s: file is no correct profile data file for `%s'\n",
+ filename, _dl_profile);
+ return;
+ }
+
+ addr = (void *) __mmap (NULL, expected_size, PROT_READ|PROT_WRITE,
+ MAP_SHARED|MAP_FILE, fd, 0);
+ if (addr == (void *) -1)
+ {
+ char buf[400];
+ int errnum = errno;
+ __close (fd);
+ fprintf (stderr, "%s: cannot map file: %s\n", filename,
+ _strerror_internal (errnum, buf, sizeof buf));
+ return;
+ }
+
+ /* We don't need the file desriptor anymore. */
+ __close (fd);
+
+ /* Pointer to data after the header. */
+ hist = (char *) (addr + 1);
+
+ /* Compute pointer to array of the arc information. */
+ data = (struct here_cg_arc_record *) (hist + 1
+ + sizeof (struct gmon_hist_hdr));
+
+ 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));
+
+ for (cnt = 0; cnt < param.fromssize / sizeof (*param.froms); ++cnt)
+ data[cnt].tag = 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)
+ goto wrong_format;
+ }
+
+ /* Turn on profiling. */
+ param.state = GMON_PROF_ON;
+}
+
+
+void
+_dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc)
+{
+ if (param.state != GMON_PROF_ON)
+ return;
+ param.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 = 0;
+ selfpc -= param.lowpc;
+
+ param.state = GMON_PROF_ON;
+}
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 5b22a506da..4f6eff8835 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -24,6 +24,7 @@
#include <errno.h>
#include "dynamic-link.h"
+
void
_dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy)
{
@@ -65,7 +66,7 @@ _dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy)
l->l_name, (flags)))
#include "dynamic-link.h"
- ELF_DYNAMIC_RELOCATE (l, lazy);
+ ELF_DYNAMIC_RELOCATE (l, lazy, 1);
}
/* Mark the object so we know this work has been done. */
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index 7a44ea4ce3..1b34026d38 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -137,17 +137,18 @@ fixup (
/* Perform the specified relocation. */
if (l->l_info[VERSYMIDX (DT_VERSYM)])
{
- const ElfW(Half) * version =
+ const ElfW(Half) *version =
(const ElfW(Half) *) (l->l_addr +
l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr);
ElfW(Half) ndx = version[ELFW(R_SYM) (reloc->r_info)];
elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)],
- &l->l_versions[ndx]);
+ &l->l_versions[ndx],
+ (void *) (l->l_addr + reloc->r_offset));
}
else
elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)],
- NULL);
+ NULL, (void *) (l->l_addr + reloc->r_offset));
}
*_dl_global_scope_end = NULL;
@@ -161,6 +162,70 @@ fixup (
}
+#ifndef PROF
+static ElfW(Addr)
+profile_fixup (
+#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
+ ELF_MACHINE_RUNTIME_FIXUP_ARGS,
+#endif
+ struct link_map *l, ElfW(Word) reloc_offset, ElfW(Addr) retaddr)
+{
+ void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount;
+ const ElfW(Sym) *const symtab
+ = (const ElfW(Sym) *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
+ const char *strtab =
+ (const char *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
+
+ const PLTREL *const reloc
+ = (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
+ reloc_offset);
+ ElfW(Addr) result;
+
+ /* Set up the scope to find symbols referenced by this object. */
+ struct link_map **scope = _dl_object_relocation_scope (l);
+
+ {
+ /* This macro is used as a callback from the elf_machine_relplt code. */
+#define RESOLVE(ref, version, flags) \
+ ((version) != NULL && (version)->hash != 0 \
+ ? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, (ref), scope, \
+ l->l_name, (version), (flags)) \
+ : _dl_lookup_symbol (strtab + (*ref)->st_name, (ref), scope, \
+ l->l_name, (flags)))
+#include "dynamic-link.h"
+
+ /* Perform the specified relocation. */
+ if (l->l_info[VERSYMIDX (DT_VERSYM)])
+ {
+ const ElfW(Half) *version =
+ (const ElfW(Half) *) (l->l_addr +
+ l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr);
+ ElfW(Half) ndx = version[ELFW(R_SYM) (reloc->r_info)];
+
+ elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)],
+ &l->l_versions[ndx], (void *) &result);
+ }
+ else
+ elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)],
+ NULL, (void *) &result);
+ }
+
+ *_dl_global_scope_end = NULL;
+
+ /* Return the address that was written by the relocation. */
+#ifdef ELF_FIXUP_RETURNS_ADDRESS
+ (*mcount_fct) (retaddr, result);
+
+ return &result; /* XXX This cannot work. What to do??? --drepper */
+#else
+ (*mcount_fct) (retaddr, result);
+
+ return result;
+#endif
+}
+#endif
+
+
/* This macro is defined in dl-machine.h to define the entry point called
by the PLT. The `fixup' function above does the real work, but a little
more twiddling is needed to get the stack right and jump to the address
diff --git a/elf/dl-support.c b/elf/dl-support.c
index 3333bf10fb..41997ccafb 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -42,6 +42,10 @@ int _dl_verbose;
/* Structure to store information about search paths. */
struct r_search_path *_dl_search_paths;
+/* We never do profiling. */
+const char *_dl_profile;
+struct link_map *_dl_profile_map;
+
static void non_dynamic_init (void) __attribute__ ((unused));
diff --git a/elf/do-rel.h b/elf/do-rel.h
index 766e62c219..7f4b1259a2 100644
--- a/elf/do-rel.h
+++ b/elf/do-rel.h
@@ -63,12 +63,14 @@ elf_dynamic_do_rel (struct link_map *map,
{
ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)];
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
- &map->l_versions[ndx]);
+ &map->l_versions[ndx],
+ (void *) (map->l_addr + r->r_offset));
}
}
else
for (; r < end; ++r)
- elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL);
+ elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
+ (void *) (map->l_addr + r->r_offset));
}
}
diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h
index 3377ee7ff6..4a946f8ad8 100644
--- a/elf/dynamic-link.h
+++ b/elf/dynamic-link.h
@@ -102,11 +102,14 @@ elf_get_dynamic_info (ElfW(Dyn) *dyn,
/* This can't just be an inline function because GCC is too dumb
to inline functions containing inlines themselves. */
-#define ELF_DYNAMIC_RELOCATE(map, lazy) \
- do { \
- int edr_lazy = elf_machine_runtime_setup((map), (lazy)); \
- ELF_DYNAMIC_DO_REL ((map), edr_lazy); \
- ELF_DYNAMIC_DO_RELA ((map), edr_lazy); \
+#define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile) \
+ do { \
+ int profile = (consider_profile && _dl_profile != NULL \
+ && _dl_name_match_p (_dl_profile, (map))); \
+ int edr_lazy = elf_machine_runtime_setup ((map), (lazy) || profile, \
+ profile); \
+ ELF_DYNAMIC_DO_REL ((map), edr_lazy); \
+ ELF_DYNAMIC_DO_RELA ((map), edr_lazy); \
} while (0)
#endif
diff --git a/elf/link.h b/elf/link.h
index e0fccd0fca..38a7c88d9a 100644
--- a/elf/link.h
+++ b/elf/link.h
@@ -225,6 +225,11 @@ extern size_t _dl_pagesize;
/* File descriptor referring to the zero-fill device. */
extern int _dl_zerofd;
+/* Name of the shared object to be profiled (if any). */
+extern const char *_dl_profile;
+/* Map of shared object to be profiled. */
+extern struct link_map *_dl_profile_map;
+
/* OS-dependent function to open the zero-fill device. */
extern int _dl_sysdep_open_zero_fill (void); /* dl-sysdep.c */
@@ -430,8 +435,14 @@ extern void _dl_debug_state (void);
extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase);
/* Initialize the basic data structure for the search paths. */
-void _dl_init_paths (void);
+extern void _dl_init_paths (void);
+
+/* Gather the information needed to install the profiling tables and start
+ the timers. */
+extern void _dl_start_profile (struct link_map *map, const char *output_dir);
+/* The actual functions used to keep book on the calls. */
+extern void _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc);
__END_DECLS
diff --git a/elf/rtld.c b/elf/rtld.c
index 7189ca6b2b..726463c882 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -61,6 +61,9 @@ int _dl_verbose;
const char *_dl_platform;
size_t _dl_platformlen;
struct r_search_path *_dl_search_paths;
+const char *_dl_profile;
+const char *_dl_profile_output;
+struct link_map *_dl_profile_map;
/* Set nonzero during loading and initialization of executable and
libraries, cleared before the executable's entry point runs. This
@@ -109,7 +112,7 @@ _dl_start (void *arg)
/* Relocate ourselves so we can do normal function calls and
data access using the global offset table. */
- ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0);
+ ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0);
/* Now life is sane; we can call functions and access global data.
Set up to use the operating system facilities, and find out from
@@ -269,6 +272,26 @@ dl_main (const ElfW(Phdr) *phdr,
else
lazy = !__libc_enable_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0';
+ /* See whether we want to use profiling. */
+ _dl_profile = getenv ("LD_PROFILE");
+ if (_dl_profile != NULL)
+ if (_dl_profile[0] == '\0')
+ /* An empty string is of not much help. Disable profiling. */
+ _dl_profile = NULL;
+ else
+ {
+ /* OK, we have the name of a shared object we want to
+ profile. It's up to the user to provide a good name, it
+ must match the file name or soname of one of the loaded
+ objects. Now let's see where we are supposed to place the
+ result. */
+ _dl_profile_output = getenv ("LD_PROFILE_OUTPUT");
+
+ if (_dl_profile_output == NULL || _dl_profile_output[0] == '\0')
+ /* This is the default place. */
+ _dl_profile_output = "/var/tmp";
+ }
+
/* Set up a flag which tells we are just starting. */
_dl_starting_up = 1;
@@ -814,6 +837,11 @@ of this helper program; chances are you did not intend to run this program.\n",
_dl_debug_state ();
}
+ /* Now enable profiling if needed. */
+ if (_dl_profile_map != NULL)
+ /* We must prepare the profiling. */
+ _dl_start_profile (_dl_profile_map, _dl_profile_output);
+
/* Once we return, _dl_sysdep_start will invoke
the DT_INIT functions and then *USER_ENTRY. */
}
@@ -824,6 +852,8 @@ static void
print_unresolved (int errcode __attribute__ ((unused)), const char *objname,
const char *errstring)
{
+ if (objname[0] == '\0')
+ objname = _dl_argv[0] ?: "<main program>";
_dl_sysdep_error (errstring, " (", objname, ")\n", NULL);
}
diff --git a/gmon/bb_exit_func.c b/gmon/bb_exit_func.c
index dc9def2bb5..53ddbfdbe9 100644
--- a/gmon/bb_exit_func.c
+++ b/gmon/bb_exit_func.c
@@ -18,7 +18,7 @@
Boston, MA 02111-1307, USA. */
/* __bb_exit_func() dumps all the basic-block statistics linked into
- the bb_head chain to .d files. */
+ the __bb_head chain to .d files. */
#include <sys/gmon_out.h>
#include <sys/types.h>
@@ -55,8 +55,8 @@ __bb_exit_func (void)
perror (OUT_NAME);
return;
}
- bcopy (GMON_MAGIC, &ghdr.cookie[0], 4);
- bcopy (&version, &ghdr.version, sizeof (version));
+ memcpy (&ghdr.cookie[0], GMON_MAGIC, 4);
+ memcpy (&ghdr.version, &version, sizeof (version));
fwrite (&ghdr, sizeof (ghdr), 1, fp);
for (ptr = __bb_head; ptr != 0; ptr = ptr->next)
diff --git a/gmon/gmon.c b/gmon/gmon.c
index d484ec2c9e..6b7ef81d93 100644
--- a/gmon/gmon.c
+++ b/gmon/gmon.c
@@ -36,6 +36,7 @@
#include <sys/gmon_out.h>
#include <sys/uio.h>
+#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
@@ -60,6 +61,7 @@ static int s_scale;
#define ERR(s) write(2, s, sizeof(s) - 1)
void moncontrol __P ((int mode));
+void __moncontrol __P ((int mode));
static void write_hist __P ((int fd));
static void write_call_graph __P ((int fd));
static void write_bb_counts __P ((int fd));
@@ -70,7 +72,7 @@ static void write_bb_counts __P ((int fd));
* all the data structures are ready.
*/
void
-moncontrol (mode)
+__moncontrol (mode)
int mode;
{
struct gmonparam *p = &_gmonparam;
@@ -91,7 +93,7 @@ moncontrol (mode)
void
-monstartup (lowpc, highpc)
+__monstartup (lowpc, highpc)
u_long lowpc;
u_long highpc;
{
@@ -128,7 +130,7 @@ monstartup (lowpc, highpc)
ERR(_("monstartup: out of memory\n"));
return;
}
- bzero(cp, p->kcountsize + p->fromssize + p->tossize);
+ memset (cp, '\0', p->kcountsize + p->fromssize + p->tossize);
p->tos = (struct tostruct *)cp;
cp += p->tossize;
p->kcount = (u_short *)cp;
@@ -158,7 +160,7 @@ monstartup (lowpc, highpc)
} else
s_scale = SCALE_1_TO_1;
- moncontrol(1);
+ __moncontrol(1);
}
@@ -180,8 +182,9 @@ write_hist (fd)
*(char **) thdr.low_pc = (char *) _gmonparam.lowpc;
*(char **) thdr.high_pc = (char *) _gmonparam.highpc;
- *(int *) thdr.hist_size = _gmonparam.kcountsize / sizeof (HISTCOUNTER);
- *(int *) thdr.prof_rate = __profile_frequency ();
+ *(int32_t *) thdr.hist_size = (_gmonparam.kcountsize
+ / sizeof (HISTCOUNTER));
+ *(int32_t *) thdr.prof_rate = __profile_frequency ();
strncpy (thdr.dimen, "seconds", sizeof (thdr.dimen));
thdr.dimen_abbrev = 's';
@@ -296,18 +299,21 @@ _mcleanup ()
struct gmon_hdr ghdr __attribute__ ((aligned (__alignof__ (int))));
int fd;
- moncontrol (0);
+ __moncontrol (0);
fd = __open ("gmon.out", O_CREAT|O_TRUNC|O_WRONLY, 0666);
if (fd < 0)
{
- perror ("_mcleanup: gmon.out");
+ char buf[300];
+ int errnum = errno;
+ fprintf (stderr, "_mcleanup: gmon.out: %s\n",
+ _strerror_internal (errnum, buf, sizeof buf));
return;
}
/* write gmon.out header: */
- memset (&ghdr, 0, sizeof (struct gmon_hdr));
+ memset (&ghdr, '\0', sizeof (struct gmon_hdr));
memcpy (&ghdr.cookie[0], GMON_MAGIC, sizeof (ghdr.cookie));
- *(int *) ghdr.version = GMON_VERSION;
+ *(int32_t *) ghdr.version = GMON_VERSION;
__write (fd, &ghdr, sizeof (struct gmon_hdr));
/* write PC histogram: */
diff --git a/gmon/sys/gmon.h b/gmon/sys/gmon.h
index 2eff69b01c..8368ca1ce3 100644
--- a/gmon/sys/gmon.h
+++ b/gmon/sys/gmon.h
@@ -169,10 +169,11 @@ extern struct gmonparam _gmonparam;
__BEGIN_DECLS
/* Set up data structures and start profiling. */
-void monstartup __P ((u_long lowpc, u_long highpc));
+extern void __monstartup __P ((u_long __lowpc, u_long __highpc));
+extern void monstartup __P ((u_long __lowpc, u_long __highpc));
/* Clean up profiling and write out gmon.out. */
-void _mcleanup __P ((void));
+extern void _mcleanup __P ((void));
__END_DECLS
diff --git a/gmon/sys/gmon_out.h b/gmon/sys/gmon_out.h
index bb80a1a16f..c84f945ce8 100644
--- a/gmon/sys/gmon_out.h
+++ b/gmon/sys/gmon_out.h
@@ -70,7 +70,7 @@ struct gmon_cg_arc_record
char from_pc[sizeof (char *)]; /* address within caller's body */
char self_pc[sizeof (char *)]; /* address within callee's body */
char count[4]; /* number of arc traversals */
-};
+ };
__END_DECLS
diff --git a/include/sys/gmon_out.h b/include/sys/gmon_out.h
new file mode 100644
index 0000000000..249f834ba3
--- /dev/null
+++ b/include/sys/gmon_out.h
@@ -0,0 +1 @@
+#include <gmon/sys/gmon_out.h>
diff --git a/inet/netinet/icmp6.h b/inet/netinet/icmp6.h
index 224fb64f08..38c1bc19dd 100644
--- a/inet/netinet/icmp6.h
+++ b/inet/netinet/icmp6.h
@@ -19,6 +19,8 @@
#ifndef _NETINET_ICMP6_H
#define _NETINET_ICMP6_H 1
+#include <inttypes.h>
+#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
@@ -29,160 +31,202 @@
#define ICMPV6_FILTER_BLOCKOTHERS 3
#define ICMPV6_FILTER_PASSONLY 4
-struct icmpv6_filter
+struct icmp6_filter
{
- u_int32_t data[8];
+ uint32_t data[8];
};
-struct icmpv6hdr
+struct icmp6_hdr
{
- u_int8_t icmpv6_type; /* type field */
- u_int8_t icmpv6_code; /* code field */
- u_int16_t icmpv6_cksum; /* checksum field */
- union
+ uint8_t icmp6_type; /* type field */
+ uint8_t icmp6_code; /* code field */
+ uint16_t icmp6_cksum; /* checksum field */
+ union
{
- u_int32_t un_data32[1]; /* type-specific field */
- u_int16_t un_data16[2]; /* type-specific field */
- u_int8_t un_data8[4]; /* type-specific field */
- } icmpv6_dataun;
- };
-
-#define icmpv6_data32 icmpv6_dataun.un_data32
-#define icmpv6_data16 icmpv6_dataun.un_data16
-#define icmpv6_data8 icmpv6_dataun.un_data8
-#define icmpv6_pptr icmpv6_data32[0] /* parameter prob */
-#define icmpv6_mtu icmpv6_data32[0] /* packet too big */
-#define icmpv6_id icmpv6_data16[0] /* echo request/reply */
-#define icmpv6_seq icmpv6_data16[1] /* echo request/reply */
-#define icmpv6_maxdelay icmpv6_data16[0] /* mcast group membership */
-
-#define ICMPV6_DEST_UNREACH 1
-#define ICMPV6_PACKET_TOOBIG 2
-#define ICMPV6_TIME_EXCEEDED 3
-#define ICMPV6_PARAMETER_PROBLEM 4
-#define ICMPV6_INFOMSG_MASK 128 /* message is info if bit set */
-#define ICMPV6_ECHOREQUEST 128
-#define ICMPV6_ECHOREPLY 129
-#define ICMPV6_MGM_QUERY 130
-#define ICMPV6_MGM_REPORT 131
-#define ICMPV6_MGM_REDUCTION 132
-
-#define ICMPV6_DEST_UNREACH_NOROUTE 0
-#define ICMPV6_DEST_UNREACH_ADMIN 1 /* administratively prohibited */
-#define ICMPV6_DEST_UNREACH_NOTNEIGHBOR 2 /* not a neighbor (and must be) */
-#define ICMPV6_DEST_UNREACH_ADDR 3
-#define ICMPV6_DEST_UNREACH_NOPORT 4
-#define ICMPV6_TIME_EXCEED_HOPS 0 /* Hop Limit == 0 in transit */
-#define ICMPV6_TIME_EXCEED_REASSEMBLY 1 /* Reassembly time out */
-#define ICMPV6_PARAMPROB_HEADER 0 /* erroneous header field */
-#define ICMPV6_PARAMPROB_NEXTHEADER 1 /* unrecognized Next Header */
-#define ICMPV6_PARAMPROB_OPTION 2 /* unrecognized option */
-
-#define ICMPV6_FILTER_WILLPASS(type, filterp) \
+ uint32_t icmp6_un_data32[1]; /* type-specific field */
+ uint16_t icmp6_un_data16[2]; /* type-specific field */
+ uint8_t icmp6_un_data8[4]; /* type-specific field */
+ } icmp6_dataun;
+ };
+
+#define icmp6_data32 icmp6_dataun.icmp6_un_data32
+#define icmp6_data16 icmp6_dataun.icmp6_un_data16
+#define icmp6_data8 icmp6_dataun.icmp6_un_data8
+#define icmp6_pptr icmp6_data32[0] /* parameter prob */
+#define icmp6_mtu icmp6_data32[0] /* packet too big */
+#define icmp6_id icmp6_data16[0] /* echo request/reply */
+#define icmp6_seq icmp6_data16[1] /* echo request/reply */
+#define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */
+
+#define ICMP6_DST_UNREACH 1
+#define ICMP6_PACKET_TOO_BIG 2
+#define ICMP6_TIME_EXCEEDED 3
+#define ICMP6_PARAM_PROB 4
+
+#define ICMP6_INFOMSG_MASK 0x80 /* all informational messages */
+
+#define ICMP6_ECHO_REQUEST 128
+#define ICMP6_ECHO_REPLY 129
+#define ICMP6_MEMBERSHIP_QUERY 130
+#define ICMP6_MEMBERSHIP_REPORT 131
+#define ICMP6_MEMBERSHIP_REDUCTION 132
+
+#define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */
+#define ICMP6_DST_UNREACH_ADMIN 1 /* communication with destination */
+ /* administratively prohibited */
+#define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 /* not a neighbor */
+#define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */
+#define ICMP6_DST_UNREACH_NOPORT 4 /* bad port */
+
+#define ICMP6_TIME_EXCEED_TRANSIT 0 /* Hop Limit == 0 in transit */
+#define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* Reassembly time out */
+
+#define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */
+#define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized Next Header */
+#define ICMP6_PARAMPROB_OPTION 2 /* unrecognized IPv6 option */
+
+#define ICMP6_FILTER_WILLPASS(type, filterp) \
((((filterp)->data[(type) >> 5]) & (1 << ((type) & 31))) == 0)
-#define ICMPV6_FILTER_WILLBLOCK(type, filterp) \
+#define ICMP6_FILTER_WILLBLOCK(type, filterp) \
((((filterp)->data[(type) >> 5]) & (1 << ((type) & 31))) != 0)
-#define ICMPV6_FILTER_SETPASS(type, filterp) \
+#define ICMP6_FILTER_SETPASS(type, filterp) \
((((filterp)->data[(type) >> 5]) &= ~(1 << ((type) & 31))))
-#define ICMPV6_FILTER_SETBLOCK(type, filterp) \
+#define ICMP6_FILTER_SETBLOCK(type, filterp) \
((((filterp)->data[(type) >> 5]) |= (1 << ((type) & 31))))
-#define ICMPV6_FILTER_SETPASSALL(filterp) \
- memset (filterp, 0, sizeof (struct icmpv6_filter));
+#define ICMP6_FILTER_SETPASSALL(filterp) \
+ memset (filterp, 0, sizeof (struct icmp6_filter));
-#define ICMPV6_FILTER_SETBLOCKALL(filterp) \
- memset (filterp, 0xFF, sizeof (struct icmpv6_filter));
+#define ICMP6_FILTER_SETBLOCKALL(filterp) \
+ memset (filterp, 0xFF, sizeof (struct icmp6_filter));
-#define ND6_ROUTER_SOLICITATION 133
-#define ND6_ROUTER_ADVERTISEMENT 134
-#define ND6_NEIGHBOR_SOLICITATION 135
-#define ND6_NEIGHBOR_ADVERTISEMENT 136
-#define ND6_REDIRECT 137
+#define ND_ROUTER_SOLICIT 133
+#define ND_ROUTER_ADVERT 134
+#define ND_NEIGHBOR_SOLICIT 135
+#define ND_NEIGHBOR_ADVERT 136
+#define ND_REDIRECT 137
-enum nd6_option
+struct nd_router_solicit /* router solicitation */
{
- ND6_OPT_SOURCE_LINKADDR=1,
- ND6_OPT_TARGET_LINKADDR=2,
- ND6_OPT_PREFIX_INFORMATION=3,
- ND6_OPT_REDIRECTED_HEADER=4,
- ND6_OPT_MTU=5,
- ND6_OPT_ENDOFLIST=256
+ struct icmp6_hdr nd_rs_hdr;
+ /* could be followed by options */
};
-struct nd6_router_solicit /* router solicitation */
+#define nd_rs_type nd_rs_hdr.icmp6_type
+#define nd_rs_code nd_rs_hdr.icmp6_code
+#define nd_rs_cksum nd_rs_hdr.icmp6_cksum
+#define nd_rs_reserved nd_rs_hdr.icmp6_data32[0]
+
+struct nd_router_advert /* router advertisement */
{
- struct icmpv6hdr rsol_hdr;
+ struct icmp6_hdr nd_ra_hdr;
+ uint32_t nd_ra_reachable; /* reachable time */
+ uint32_t nd_ra_retransmit; /* retransmit timer */
+ /* could be followed by options */
};
-#define rsol_type rsol_hdr.icmpv6_type
-#define rsol_code rsol_hdr.icmpv6_code
-#define rsol_cksum rsol_hdr.icmpv6_cksum
-#define rsol_reserved rsol_hdr.icmpv6_data32[0]
+#define nd_ra_type nd_ra_hdr.icmp6_type
+#define nd_ra_code nd_ra_hdr.icmp6_code
+#define nd_ra_cksum nd_ra_hdr.icmp6_cksum
+#define nd_ra_curhoplimit nd_ra_hdr.icmp6_data8[0]
+#define nd_ra_flags_reserved nd_ra_hdr.icmp6_data8[1]
+#define ND_RA_FLAG_MANAGED 0x80
+#define ND_RA_FLAG_OTHER 0x40
+#define nd_ra_router_lifetime nd_ra_hdr.icmp6_data16[1]
-struct nd6_router_advert
+struct nd_neighbor_solicit /* neighbor solicitation */
{
- struct icmpv6hdr radv_hdr;
- u_int32_t radv_reachable; /* reachable time */
- u_int32_t radv_retransmit; /* reachable retransmit time */
+ struct icmp6_hdr nd_ns_hdr;
+ struct in6_addr nd_ns_target; /* target address */
+ /* could be followed by options */
};
-#define radv_type radv_hdr.icmpv6_type
-#define radv_code radv_hdr.icmpv6_code
-#define radv_cksum radv_hdr.icmpv6_cksum
-#define radv_maxhoplimit radv_hdr.icmpv6_data8[0]
-#define radv_m_o_res radv_hdr.icmpv6_data8[1]
-#define ND6_RADV_M_BIT 0x80
-#define ND6_RADV_O_BIT 0x40
-#define radv_router_lifetime radv_hdr.icmpv6_data16[1]
+#define nd_ns_type nd_ns_hdr.icmp6_type
+#define nd_ns_code nd_ns_hdr.icmp6_code
+#define nd_ns_cksum nd_ns_hdr.icmp6_cksum
+#define nd_ns_reserved nd_ns_hdr.icmp6_data32[0]
-struct nd6_nsolicitation /* neighbor solicitation */
+struct nd_neighbor_advert /* neighbor advertisement */
{
- struct icmpv6hdr nsol6_hdr;
- struct in6_addr nsol6_target;
+ struct icmp6_hdr nd_na_hdr;
+ struct in6_addr nd_na_target; /* target address */
+ /* could be followed by options */
};
-struct nd6_nadvertisement /* neighbor advertisement */
+#define nd_na_type nd_na_hdr.icmp6_type
+#define nd_na_code nd_na_hdr.icmp6_code
+#define nd_na_cksum nd_na_hdr.icmp6_cksum
+#define nd_na_flags_reserved nd_na_hdr.icmp6_data32[0]
+#if BYTE_ORDER == BIG_ENDIAN
+#define ND_NA_FLAG_ROUTER 0x80000000
+#define ND_NA_FLAG_SOLICITED 0x40000000
+#define ND_NA_FLAG_OVERRIDE 0x20000000
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+#define ND_NA_FLAG_ROUTER 0x00000080
+#define ND_NA_FLAG_SOLICITED 0x00000040
+#define ND_NA_FLAG_OVERRIDE 0x00000020
+#endif
+
+struct nd_redirect /* redirect */
{
- struct icmpv6hdr nadv6_hdr;
- struct in6_addr nadv6_target;
+ struct icmp6_hdr nd_rd_hdr;
+ struct in6_addr nd_rd_target; /* target address */
+ struct in6_addr nd_rd_dst; /* destination address */
+ /* could be followed by options */
};
+
+#define nd_rd_type nd_rd_hdr.icmp6_type
+#define nd_rd_code nd_rd_hdr.icmp6_code
+#define nd_rd_cksum nd_rd_hdr.icmp6_cksum
+#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0]
-#define nadv6_flags nadv6_hdr.icmpv6_data32[0]
-#define ND6_NADVERFLAG_ISROUTER 0x80
-#define ND6_NADVERFLAG_SOLICITED 0x40
-#define ND6_NADVERFLAG_OVERRIDE 0x20
-
-struct nd6_redirect /* redirect */
+struct nd_opt_hdr /* Neighbor discovery option header */
{
- struct icmpv6hdr redirect_hdr;
- struct in6_addr redirect_target;
- struct in6_addr redirect_destination;
+ uint8_t nd_opt_type;
+ uint8_t nd_opt_len; /* in units of 8 octets */
+ /* followed by option specific data */
};
-struct nd6_opt_prefix_info /* prefix information */
+#define ND_OPT_SOURCE_LINKADDR 1
+#define ND_OPT_TARGET_LINKADDR 2
+#define ND_OPT_PREFIX_INFORMATION 3
+#define ND_OPT_REDIRECTED_HEADER 4
+#define ND_OPT_MTU 5
+
+struct nd_opt_prefix_info /* prefix information */
{
- u_int8_t opt_type;
- u_int8_t opt_length;
- u_int8_t opt_prefix_length;
- u_int8_t opt_l_a_res;
- u_int32_t opt_valid_life;
- u_int32_t opt_preferred_life;
- u_int32_t opt_reserved2;
- struct in6_addr opt_prefix;
+ uint8_t nd_opt_pi_type;
+ uint8_t nd_opt_pi_len;
+ uint8_t nd_opt_pi_prefix_len;
+ uint8_t nd_opt_pi_flags_reserved;
+ uint32_t nd_opt_pi_valid_time;
+ uint32_t nd_opt_pi_preferred_time;
+ uint32_t nd_opt_pi_reserved2;
+ struct in6_addr nd_opt_pi_prefix;
};
-#define ND6_OPT_PI_L_BIT 0x80
-#define ND6_OPT_PI_A_BIT 0x40
+#define ND_OPT_PI_FLAG_ONLINK 0x80
+#define ND_OPT_PI_FLAG_AUTO 0x40
-struct nd6_opt_mtu /* MTU option */
+struct nd_opt_rd_hdr /* redirected header */
{
- u_int8_t opt_type;
- u_int8_t opt_length;
- u_int16_t opt_reserved;
- u_int32_t opt_mtu;
+ uint8_t nd_opt_rh_type;
+ uint8_t nd_opt_rh_len;
+ uint16_t nd_opt_rh_reserved1;
+ uint32_t nd_opt_rh_reserved2;
+ /* followed by IP header and data */
};
+struct nd_opt_mtu /* MTU option */
+ {
+ uint8_t nd_opt_mtu_type;
+ uint8_t nd_opt_mtu_len;
+ uint16_t nd_opt_mtu_reserved;
+ uint32_t nd_opt_mtu_mtu;
+ };
+
+
#endif /* netinet/icmpv6.h */
diff --git a/inet/netinet/in.h b/inet/netinet/in.h
index d2a366b51c..9eda281360 100644
--- a/inet/netinet/in.h
+++ b/inet/netinet/in.h
@@ -20,6 +20,7 @@
#define _NETINET_IN_H 1
#include <features.h>
+#include <inttypes.h>
#include <sys/socket.h>
#include <sys/types.h>
@@ -30,19 +31,25 @@ __BEGIN_DECLS
/* Standard well-defined IP protocols. */
enum
{
- IPPROTO_IP = 0, /* Dummy protocol for TCP. */
- IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */
- IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */
- IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94). */
- IPPROTO_TCP = 6, /* Transmission Control Protocol. */
- IPPROTO_EGP = 8, /* Exterior Gateway Protocol. */
- IPPROTO_PUP = 12, /* PUP protocol. */
- IPPROTO_UDP = 17, /* User Datagram Protocol. */
- IPPROTO_IDP = 22, /* XNS IDP protocol. */
- IPPROTO_IPV6 = 41, /* IPv6-in-IPv4 tunnelling. */
- IPPROTO_ICMPV6 = 58, /* ICMPv6. */
-
- IPPROTO_RAW = 255, /* Raw IP packets. */
+ IPPROTO_IP = 0, /* Dummy protocol for TCP. */
+ IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
+ IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */
+ IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */
+ IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94). */
+ IPPROTO_TCP = 6, /* Transmission Control Protocol. */
+ IPPROTO_EGP = 8, /* Exterior Gateway Protocol. */
+ IPPROTO_PUP = 12, /* PUP protocol. */
+ IPPROTO_UDP = 17, /* User Datagram Protocol. */
+ IPPROTO_IDP = 22, /* XNS IDP protocol. */
+ IPPROTO_IPV6 = 41, /* IPv6 header. */
+ IPPROTO_ROUTING = 43, /* IPv6 routing header. */
+ IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */
+ IPPROTO_ESP = 50, /* encapsulating security payload. */
+ IPPROTO_AH = 51, /* authentication header. */
+ IPPROTO_ICMPV6 = 58, /* ICMPv6. */
+ IPPROTO_NONE = 59, /* IPv6 no next header. */
+ IPPROTO_DSTOPTS = 60, /* IPv6 destination options. */
+ IPPROTO_RAW = 255, /* Raw IP packets. */
IPPROTO_MAX
};
@@ -90,7 +97,7 @@ enum
/* Internet address. */
struct in_addr
{
- u_int32_t s_addr;
+ uint32_t s_addr;
};
@@ -142,11 +149,11 @@ struct in6_addr
{
union
{
- u_int8_t u6_addr8[16];
- u_int16_t u6_addr16[8];
- u_int32_t u6_addr32[4];
+ uint8_t u6_addr8[16];
+ uint16_t u6_addr16[8];
+ uint32_t u6_addr32[4];
#if (~0UL) > 0xffffffff
- u_int64_t u6_addr64[2];
+ uint64_t u6_addr64[2];
#endif
} in6_u;
#define s6_addr in6_u.u6_addr8
@@ -171,13 +178,13 @@ extern const struct in6_addr in6addr_loopback; /* ::1 */
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_);
- unsigned short int sin_port; /* Port number. */
+ uint16_t sin_port; /* Port number. */
struct in_addr sin_addr; /* Internet address. */
/* Pad to size of `struct sockaddr'. */
unsigned char sin_zero[sizeof (struct sockaddr) -
__SOCKADDR_COMMON_SIZE -
- sizeof (unsigned short int) -
+ sizeof (uint16_t) -
sizeof (struct in_addr)];
};
@@ -185,8 +192,8 @@ struct sockaddr_in
struct sockaddr_in6
{
__SOCKADDR_COMMON (sin6_);
- u_int16_t sin6_port; /* Transport layer port # */
- u_int32_t sin6_flowinfo; /* IPv6 flow information */
+ uint16_t sin6_port; /* Transport layer port # */
+ uint32_t sin6_flowinfo; /* IPv6 flow information */
struct in6_addr sin6_addr; /* IPv6 address */
};
@@ -196,8 +203,8 @@ struct ipv6_mreq
/* IPv6 multicast address of group */
struct in6_addr ipv6mr_multiaddr;
- /* local IPv6 address of interface */
- int ipv6mr_ifindex;
+ /* local interface */
+ unsigned int ipv6mr_ifindex;
};
/* Get system-specific definitions. */
@@ -210,10 +217,10 @@ struct ipv6_mreq
this was a short-sighted decision since on different systems the types
may have different representations but the values are always the same. */
-extern u_int32_t ntohl __P ((u_int32_t __netlong));
-extern u_int16_t ntohs __P ((u_int16_t __netshort));
-extern u_int32_t htonl __P ((u_int32_t __hostlong));
-extern u_int16_t htons __P ((u_int16_t __hostshort));
+extern uint32_t ntohl __P ((uint32_t __netlong));
+extern uint16_t ntohs __P ((uint16_t __netshort));
+extern uint32_t htonl __P ((uint32_t __hostlong));
+extern uint16_t htons __P ((uint16_t __hostshort));
#include <endian.h>
@@ -237,30 +244,35 @@ extern u_int16_t htons __P ((u_int16_t __hostshort));
#endif
#define IN6_IS_ADDR_UNSPECIFIED(a) \
- ((((u_int32_t *) (a))[0] == 0) && ((u_int32_t *) (a))[1] == 0) && \
- (((u_int32_t *) (a))[2] == 0) && ((u_int32_t *) (a))[3] == 0))
+ ((((uint32_t *) (a))[0] == 0) && ((uint32_t *) (a))[1] == 0) && \
+ (((uint32_t *) (a))[2] == 0) && ((uint32_t *) (a))[3] == 0))
#define IN6_IS_ADDR_LOOPBACK(a) \
- ((((u_int32_t *) (a))[0] == 0) && ((u_int32_t *) (a))[1] == 0) && \
- (((u_int32_t *) (a))[2] == 0) && ((u_int32_t *) (a))[3] == htonl (1)))
+ ((((uint32_t *) (a))[0] == 0) && ((uint32_t *) (a))[1] == 0) && \
+ (((uint32_t *) (a))[2] == 0) && ((uint32_t *) (a))[3] == htonl (1)))
#define IN6_IS_ADDR_MULTICAST(a) (((u_int8_t *) (a))[0] == 0xff)
#define IN6_IS_ADDR_LINKLOCAL(a) \
- ((((u_int32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfe800000))
+ ((((uint32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfe800000))
#define IN6_IS_ADDR_SITELOCAL(a) \
- ((((u_int32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfec00000))
+ ((((uint32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfec00000))
#define IN6_IS_ADDR_V4MAPPED(a) \
- ((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \
- (((u_int32_t *) (a))[2] == htonl (0xffff)))
+ ((((uint32_t *) (a))[0] == 0) && (((uint32_t *) (a))[1] == 0) && \
+ (((uint32_t *) (a))[2] == htonl (0xffff)))
#define IN6_IS_ADDR_V4COMPAT(a) \
- ((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \
- (((u_int32_t *) (a))[2] == 0) && (ntohl (((u_int32_t *) (a))[3]) > 1))
-
-
+ ((((uint32_t *) (a))[0] == 0) && (((uint32_t *) (a))[1] == 0) && \
+ (((uint32_t *) (a))[2] == 0) && (ntohl (((uint32_t *) (a))[3]) > 1))
+
+#define IN6_ARE_ADDR_EQUAL(a,b) \
+ ((((uint32_t *) (a))[0] == ((uint32_t *) (b))[0]) && \
+ (((uint32_t *) (a))[1] == ((uint32_t *) (b))[2]) && \
+ (((uint32_t *) (a))[2] == ((uint32_t *) (b))[1]) && \
+ (((uint32_t *) (a))[3] == ((uint32_t *) (b))[3]))
+
/* Bind socket to a privileged IP port. */
extern int bindresvport __P ((int __sockfd, struct sockaddr_in *__sin));
@@ -268,8 +280,8 @@ extern int bindresvport __P ((int __sockfd, struct sockaddr_in *__sin));
/* IPv6 packet information. */
struct in6_pktinfo
{
- struct in6_addr ipi6_addr; /* src/dst IPv6 address */
- int ipi6_ifindex; /* send/recv interface index */
+ struct in6_addr ipi6_addr; /* src/dst IPv6 address */
+ unsigned int ipi6_ifindex; /* send/recv interface index */
};
__END_DECLS
diff --git a/inet/netinet/ip6.h b/inet/netinet/ip6.h
index 2930578e4f..cd42ef64b9 100644
--- a/inet/netinet/ip6.h
+++ b/inet/netinet/ip6.h
@@ -19,27 +19,88 @@
#ifndef _NETINET_IP6_H
#define _NETINET_IP6_H 1
+#include <inttypes.h>
#include <netinet/in.h>
-#include <endian.h>
-
-struct ipv6hdr
-{
-#if __BYTE_ORDER == __LITTLE_ENDIAN
- u_int8_t ipv6_version:4;
- u_int8_t ipv6_priority:4; /* going away? */
- u_int32_t ipv6_flowid:24;
-#elif __BYTE_ORDER == __BIG_ENDIAN
- u_int32_t ipv6_flowid:24;
- u_int8_t ipv6_priority:4; /* going away? */
- u_int8_t ipv6_version:4;
-#else
-# error Unknown endianness
+
+struct ip6_hdr
+ {
+ union
+ {
+ struct ip6_hdrctl
+ {
+ uint32_t ip6_un1_flow; /* 24 bits of flow-ID */
+ uint16_t ip6_un1_plen; /* payload length */
+ uint8_t ip6_un1_nxt; /* next header */
+ uint8_t ip6_un1_hlim; /* hop limit */
+ } ip6_un1;
+ uint8_t ip6_un2_vfc; /* 4 bits version, 4 bits priority */
+ } ip6_ctlun;
+ struct in6_addr ip6_src; /* source address */
+ struct in6_addr ip6_dst; /* destination address */
+ };
+
+#define ip6_vfc ip6_ctlun.ip6_un2_vfc
+#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
+#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
+#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt
+#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim
+#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim
+
+/* Hop-by-Hop options header. */
+struct ip6_hbh
+ {
+ uint8_t ip6h_nxt; /* next hesder. */
+ uint8_t ip6h_len; /* length in units of 8 octets. */
+ /* followed by options */
+ };
+
+/* Destination options header */
+struct ip6_dest
+ {
+ uint8_t ip6d_nxt; /* next header */
+ uint8_t ip6d_len; /* length in units of 8 octets */
+ /* followed by options */
+ };
+
+/* Routing header */
+struct ip6_rthdr
+ {
+ uint8_t ip6r_nxt; /* next header */
+ uint8_t ip6r_len; /* length in units of 8 octets */
+ uint8_t ip6r_type; /* routing type */
+ uint8_t ip6r_segleft; /* segments left */
+ /* followed by routing type specific data */
+ };
+
+/* Type 0 Routing header */
+struct ip6_rthdr0
+ {
+ uint8_t ip6r0_nxt; /* next header */
+ uint8_t ip6r0_len; /* length in units of 8 octets */
+ uint8_t ip6r0_type; /* always zero */
+ uint8_t ip6r0_segleft; /* segments left */
+ uint8_t ip6r0_reserved; /* reserved field */
+ uint8_t ip6r0_slmap[3]; /* strict/loose bit map */
+ struct in6_addr ip6r0_addr[1]; /* up to 23 addresses */
+ };
+
+/* Fragment header */
+struct ip6_frag
+ {
+ uint8_t ip6f_nxt; /* next header */
+ uint8_t ip6f_reserved; /* reserved field */
+ uint16_t ip6f_offlg; /* offset, reserved, and flag */
+ uint32_t ip6f_ident; /* identification */
+ };
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define IP6F_OFF_MASK 0xfff8 /* mask out offset from _offlg */
+#define IP6F_RESERVED_MASK 0x0006 /* reserved bits in ip6f_offlg */
+#define IP6F_MORE_FRAG 0x0001 /* more-fragments flag */
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+#define IP6F_OFF_MASK 0xf8ff /* mask out offset from _offlg */
+#define IP6F_RESERVED_MASK 0x0600 /* reserved bits in ip6f_offlg */
+#define IP6F_MORE_FRAG 0x0100 /* more-fragments flag */
#endif
- u_int16_t ipv6_len;
- u_int8_t ipv6_nextheader;
- u_int8_t ipv6_hoplimit;
- struct in6_addr ipv6_src;
- struct in6_addr ipv6_dst;
-};
#endif /* netinet/ip6.h */
diff --git a/libc.map b/libc.map
index b23a8ff5d3..c9949448b8 100644
--- a/libc.map
+++ b/libc.map
@@ -7,7 +7,7 @@ GLIBC_2.0 {
_nl_msg_cat_cntr; __environ; _environ; _res;
___brk_addr; __curbrk; _nl_current_LC_CTYPE; _libc_intl_domainname;
_sys_errlist; _sys_siglist; __progname; _nl_default_dirname;
- __timezone; __daylight;
+ __timezone; __daylight; __tzname;
_nl_current_LC_COLLATE; __collate_element_hash;
__collate_element_strings; __collate_symbol_classes;
__collate_symbol_hash; __collate_symbol_strings;
diff --git a/manual/libc.texinfo b/manual/libc.texinfo
index 7d81247cdb..2d79d960af 100644
--- a/manual/libc.texinfo
+++ b/manual/libc.texinfo
@@ -514,7 +514,7 @@ Socket Addresses
Internet Domain
-* Internet Address Format:: How socket addresses are specified in the
+* Internet Address Formats:: How socket addresses are specified in the
Internet namespace.
* Host Addresses:: All about host addresses of Internet hosts.
* Protocols Database:: Referring to protocols by name.
diff --git a/manual/socket.texi b/manual/socket.texi
index c122106e2b..6efc54d1a5 100644
--- a/manual/socket.texi
+++ b/manual/socket.texi
@@ -323,7 +323,13 @@ This is a synonym for @code{AF_FILE}, for compatibility.
@vindex AF_INET
This designates the address format that goes with the Internet
namespace. (@code{PF_INET} is the name of that namespace.)
-@xref{Internet Address Format}.
+@xref{Internet Address Formats}.
+
+@comment sys/socket.h
+@comment IPv6 Basic API
+@item AF_INET6
+This is similar to @code{AF_INET}, but refers to the IPv6 protocol.
+(@code{PF_INET6} is the name of the corresponding namespace.)
@comment sys/socket.h
@comment BSD
@@ -566,7 +572,7 @@ A socket address for the Internet namespace includes the following components:
@item
The address of the machine you want to connect to. Internet addresses
can be specified in several ways; these are discussed in @ref{Internet
-Address Format}, @ref{Host Addresses}, and @ref{Host Names}.
+Address Formats}, @ref{Host Addresses}, and @ref{Host Names}.
@item
A port number for that machine. @xref{Ports}.
@@ -577,7 +583,7 @@ canonical format called @dfn{network byte order}. @xref{Byte Order},
for information about this.
@menu
-* Internet Address Format:: How socket addresses are specified in the
+* Internet Address Formats:: How socket addresses are specified in the
Internet namespace.
* Host Addresses:: All about host addresses of internet host.
* Protocols Database:: Referring to protocols by name.
@@ -589,16 +595,17 @@ for information about this.
* Inet Example:: Putting it all together.
@end menu
-@node Internet Address Format
-@subsection Internet Socket Address Format
+@node Internet Address Formats
+@subsection Internet Socket Address Formats
-In the Internet namespace, a socket address consists of a host address
+In the Internet namespace, for both IPv4 (@code{AF_INET}) and IPv6
+(@code{AF_INET6}), a socket address consists of a host address
and a port on that host. In addition, the protocol you choose serves
effectively as a part of the address because local port numbers are
meaningful only within a particular protocol.
-The data type for representing socket addresses in the Internet namespace
-is defined in the header file @file{netinet/in.h}.
+The data types for representing socket addresses in the Internet namespace
+are defined in the header file @file{netinet/in.h}.
@pindex netinet/in.h
@comment netinet/in.h
@@ -627,13 +634,39 @@ When you call @code{bind} or @code{getsockname}, you should specify
@code{sizeof (struct sockaddr_in)} as the @var{length} parameter if
you are using an Internet namespace socket address.
+@deftp {Data Type} {struct sockaddr_in6}
+This is the data type used to represent socket addresses in the IPv6
+namespace. It has the following members:
+
+@table @code
+@item short int sin6_family
+This identifies the address family or format of the socket address.
+You should store the value of @code{AF_INET6} in this member.
+@xref{Socket Addresses}.
+
+@item struct in6_addr sin6_addr
+This is the IPv6 address of the host machine. @xref{Host
+Addresses}, and @ref{Host Names}, for how to get a value to store
+here.
+
+@item uint32_t sin6_flowinfo
+This is a currently unimplemented field.
+
+@item uint16_t sin6_port
+This is the port number. @xref{Ports}.
+
+@end table
+@end deftp
+
@node Host Addresses
@subsection Host Addresses
Each computer on the Internet has one or more @dfn{Internet addresses},
numbers which identify that computer among all those on the Internet.
-Users typically write numeric host addresses as sequences of four
-numbers, separated by periods, as in @samp{128.52.46.32}.
+Users typically write IPv4 numeric host addresses as sequences of four
+numbers, separated by periods, as in @samp{128.52.46.32}, and IPv6
+numeric host addresses as sequences of up to eight numbers seperated by
+colons, as in @samp{5f03:1200:836f:c100::1}.
Each computer also has one or more @dfn{host names}, which are strings
of words separated by periods, as in @samp{churchy.gnu.ai.mit.edu}.
@@ -660,6 +693,9 @@ Each computer on the Internet has one or more Internet addresses,
numbers which identify that computer among all those on the Internet.
@end ifinfo
+@c I think this whole section could possibly be removed. It is slightly
+@c misleading these days.
+
@cindex network number
@cindex local network address number
An Internet host address is a number containing four bytes of data.
@@ -779,6 +815,31 @@ This constant is the address you use to send a broadcast message.
This constant is returned by some functions to indicate an error.
@end deftypevr
+@comment netinet/in.h
+@comment IPv6 basic API
+@deftp {Data Type} {struct in6_addr}
+This data type is used to store an IPv6 address. It stores 128 bits of
+data, which can be accessed (via a union) in a variety of ways.
+@end deftp
+
+@comment netinet/in.h
+@comment IPv6 basic API
+@deftypevr Constant {struct in6_addr} in6addr_loopback.
+This constant is the IPv6 address @samp{::1}, the loopback address. See
+above for a description of what this means. The macro
+@code{IN6ADDR_LOOPBACK_INIT} is provided to allow you to initialise your
+own variables to this value.
+@end deftypevr
+
+@comment netinet/in.h
+@comment IPv6 basic API
+@deftypevr Constant {struct in6_addr} in6addr_any
+This constant is the IPv6 address @samp{::}, the unspecified address. See
+above for a description of what this means. The macro
+@code{IN6ADDR_ANY_INIT} is provided to allow you to initialise your
+own variables to this value.
+@end deftypevr
+
@node Host Address Functions
@subsubsection Host Address Functions
@@ -854,6 +915,30 @@ This function returns the network number part of the Internet host
address @var{addr}.
@end deftypefun
+@comment arpa/inet.h
+@comment IPv6 basic API
+@deftypefun int inet_pton (int @var{af}, const char *@var{cp}, void
+*@var{buf})
+This function converts an Internet address (either IPv4 or IPv6) from
+presentation (textual) to network (binary) format. @var{af} should be
+either @code{AF_INET} or @code{AF_INET6}, as appropriate for the type of
+address being converted. @var{cp} is a pointer to the input string, and
+@var{buf} is a pointer to a buffer for the result. It is the caller's
+responsibility to make sure the buffer is large enough.
+@end deftypefun
+
+@comment arpa/inet.h
+@comment IPv6 basic API
+@deftypefun char *inet_ntop(int @var{af}, const void *@var{cp}, char
+*@var{buf}, size_t @var{len})
+This function converts an Internet address (either IPv4 or IPv6) from
+network (binary) to presentation (textual) form. @var{af} should be
+either @code{AF_INET} or @code{AF_INET6}, as appropriate. @var{cp} is a
+pointer to the address to be converted. @var{buf} should be a pointer
+to a buffer to hold the result, and @var{len} is the length of this
+buffer. The return value from the function will be this buffer address.
+@end deftypefun
+
@node Host Names
@subsubsection Host Names
@cindex hosts database
@@ -891,11 +976,12 @@ These are alternative names for the host, represented as a null-terminated
vector of strings.
@item int h_addrtype
-This is the host address type; in practice, its value is always
-@code{AF_INET}. In principle other kinds of addresses could be
-represented in the data base as well as Internet addresses; if this were
-done, you might find a value in this field other than @code{AF_INET}.
-@xref{Socket Addresses}.
+This is the host address type; in practice, its value is always either
+@code{AF_INET} or @code{AF_INET6}, with the latter being used for IPv6
+hosts. In principle other kinds of addresses could be represented in
+the data base as well as Internet addresses; if this were done, you
+might find a value in this field other than @code{AF_INET} or
+@code{AF_INET6}. @xref{Socket Addresses}.
@item int h_length
This is the length, in bytes, of each address.
@@ -917,10 +1003,12 @@ implicit assumption that you can convert this to a @code{struct in_addr} or
an @code{unsigned long int}. Host addresses in a @code{struct hostent}
structure are always given in network byte order; see @ref{Byte Order}.
-You can use @code{gethostbyname} or @code{gethostbyaddr} to search the
-hosts database for information about a particular host. The information
-is returned in a statically-allocated structure; you must copy the
-information if you need to save it across calls.
+You can use @code{gethostbyname}, @code{gethostbyname2} or
+@code{gethostbyaddr} to search the hosts database for information about
+a particular host. The information is returned in a
+statically-allocated structure; you must copy the information if you
+need to save it across calls. You can also use @code{getaddrinfo} and
+@code{getnameinfo} to obtain this information.
@comment netdb.h
@comment BSD
@@ -930,6 +1018,14 @@ named @var{name}. If the lookup fails, it returns a null pointer.
@end deftypefun
@comment netdb.h
+@comment IPv6 Basic API
+@deftypefun {struct hostent *} gethostbyname2 (const char *@var{name}, int @var{af})
+The @code{gethostbyname2} function is like @code{gethostbyname}, but
+allows the caller to specify the desired address family (e.g.@:
+@code{AF_INET} or @code{AF_INET6}) for the result.
+@end deftypefun
+
+@comment netdb.h
@comment BSD
@deftypefun {struct hostent *} gethostbyaddr (const char *@var{addr}, int @var{length}, int @var{format})
The @code{gethostbyaddr} function returns information about the host
diff --git a/manual/texinfo.tex b/manual/texinfo.tex
index fd306fa290..813d3c2bb7 100644
--- a/manual/texinfo.tex
+++ b/manual/texinfo.tex
@@ -1,5 +1,5 @@
%% TeX macros to handle Texinfo files.
-%% $Id: texinfo.tex,v 2.210 1997/07/15 19:22:46 drepper Exp $
+%% $Id: texinfo.tex,v 2.211 1997/07/28 21:55:24 drepper Exp $
% Copyright (C) 1985, 86, 88, 90, 91, 92, 93,
% 94, 95, 96, 97 Free Software Foundation, Inc.
@@ -36,7 +36,7 @@
% This automatically updates the version number based on RCS.
\def\deftexinfoversion$#1: #2 ${\def\texinfoversion{#2}}
-\deftexinfoversion$Revision: 2.210 $
+\deftexinfoversion$Revision: 2.211 $
\message{Loading texinfo package [Version \texinfoversion]:}
% If in a .fmt file, print the version number
@@ -1406,14 +1406,12 @@ where each line of input produces a line of output.}
\else{\tclose{\kbdfont\look}}\fi
\else{\tclose{\kbdfont\look}}\fi}
-% @url, @email. Quotes do not seem necessary.
-\let\url=\code % perhaps include a hypertex \special eventually
-% rms does not like the angle brackets --karl, 17may97.
-%\def\email#1{$\langle${\tt #1}$\rangle$}
-\let\email=\code
+% @url. Quotes do not seem necessary, so use \code.
+\let\url=\code
% @uref (abbreviation for `urlref') takes an optional second argument
% specifying the text to display. First (mandatory) arg is the url.
+% Perhaps eventually put in a hypertex \special here.
%
\def\uref#1{\urefxxx #1,,\finish}
\def\urefxxx#1,#2,#3\finish{%
@@ -1425,6 +1423,11 @@ where each line of input produces a line of output.}
\fi
}
+% rms does not like the angle brackets --karl, 17may97.
+% So now @email is just like @uref.
+%\def\email#1{$\langle${\tt #1}$\rangle$}
+\let\email=\uref
+
% Check if we are currently using a typewriter font. Since all the
% Computer Modern typewriter fonts have zero interword stretch (and
% shrink), and it is reasonable to expect all typewriter fonts to have
diff --git a/nis/Makefile b/nis/Makefile
index c10c175e7d..e7dd50c1d9 100644
--- a/nis/Makefile
+++ b/nis/Makefile
@@ -50,7 +50,8 @@ libnsl-routines = yp_xdr ypclnt ypupdate_xdr \
nis_verifygroup nis_ismember nis_addmember nis_util\
nis_removemember nis_creategroup nis_destroygroup\
nis_print_group_entry nis_domain_of nis_domain_of_r\
- nis_modify nis_remove nis_add nis_defaults lckcache
+ nis_modify nis_remove nis_add nis_defaults lckcache\
+ nis_findserv
libnsl-map = libnsl.map
libnss_compat-routines := $(addprefix compat-,grp pwd spwd) nisplus-parser
diff --git a/nis/TODO b/nis/TODO
index 0fe695d78b..f34bc09a06 100644
--- a/nis/TODO
+++ b/nis/TODO
@@ -9,4 +9,3 @@
* Missing flags:
- FOLLOW_PATH (nis_list, not supported)
- ALL_RESULTS (nis_list, not supported, needs server callback)
- - NO_CACHE (__do_niscall, cache not supported yet)
diff --git a/nis/lckcache.c b/nis/lckcache.c
index ead577372e..f8c0a97296 100644
--- a/nis/lckcache.c
+++ b/nis/lckcache.c
@@ -1,6 +1,6 @@
/* Handle locking of NIS+ cache file.
- Copyright (C) 1996 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ This file is part of the GNU C Library and based on shadow/lckfile.c.
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
@@ -30,7 +30,7 @@
/* How long to wait for getting the lock before returning with an
error. */
-#define TIMEOUT 15 /* sec */
+#define TIMEOUT 5 /* sec */
/* File descriptor for lock file. */
@@ -141,7 +141,7 @@ __nis_lock_cache (void)
memset (&fl, '\0', sizeof (struct flock));
fl.l_type = F_RDLCK;
fl.l_whence = SEEK_SET;
- result = fcntl (lock_fd, F_SETLK, &fl);
+ result = fcntl (lock_fd, F_SETLKW, &fl);
RETURN_CLEAR_ALARM (result);
}
diff --git a/nis/nis_call.c b/nis/nis_call.c
index f25b8017a5..1dfb12944a 100644
--- a/nis/nis_call.c
+++ b/nis/nis_call.c
@@ -29,30 +29,7 @@
static struct timeval TIMEOUT = {10, 0};
-struct dir_binding
-{
- CLIENT *clnt; /* RPC CLIENT handle */
- nis_server *server_val; /* List of servers */
- u_int server_len; /* # of servers */
- u_int server_used; /* Which server we are bind in the moment ? */
- u_int trys; /* How many server have we tried ? */
- bool_t master_only; /* Is only binded to the master */
- bool_t use_auth; /* Do we use AUTH ? */
- bool_t use_udp; /* Do we use UDP ? */
- time_t create; /* Binding creation time */
- struct sockaddr_in addr; /* Server's IP address */
- int socket; /* Server's local socket */
- unsigned short port; /* Local port */
-};
-typedef struct dir_binding dir_binding;
-
-static inline u_int
-__nis_ping (const nis_server *serv, u_int serv_len)
-{
- return 0;
-}
-
-static unsigned long
+unsigned long
inetstr2int (const char *str)
{
char buffer[strlen (str) + 3];
@@ -92,12 +69,7 @@ __bind_destroy (dir_binding *bind)
static nis_error
__bind_next (dir_binding *bind)
{
- if (bind->trys >= bind->server_len)
- return NIS_FAIL;
-
- bind->server_used++;
- if (bind->server_used >= bind->server_len)
- bind->server_used = 0;
+ u_int j;
if (bind->clnt != NULL)
{
@@ -106,8 +78,38 @@ __bind_next (dir_binding *bind)
clnt_destroy (bind->clnt);
bind->clnt = NULL;
}
-
- return NIS_SUCCESS;
+
+ if (bind->trys >= bind->server_len)
+ return NIS_FAIL;
+
+ for (j = bind->current_ep + 1;
+ j < bind->server_val[bind->server_used].ep.ep_len; ++j)
+ if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].family,
+ "inet") == 0)
+ if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].proto,
+ "-") == 0)
+ {
+ bind->current_ep = j;
+ return NIS_SUCCESS;
+ }
+
+ ++bind->trys;
+ ++bind->server_used;
+ if (bind->server_used >= bind->server_len)
+ bind->server_used = 0;
+
+ for (j = bind->current_ep + 1;
+ j < bind->server_val[bind->server_used].ep.ep_len; ++j)
+ if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].family,
+ "inet") == 0)
+ if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].proto,
+ "-") == 0)
+ {
+ bind->current_ep = j;
+ return NIS_SUCCESS;
+ }
+
+ return NIS_FAIL;
}
static nis_error
@@ -116,7 +118,6 @@ __bind_connect (dir_binding *dbp)
struct sockaddr_in check;
nis_server *serv;
int checklen;
- u_int i;
if (dbp == NULL)
return NIS_FAIL;
@@ -125,26 +126,10 @@ __bind_connect (dir_binding *dbp)
memset (&dbp->addr, '\0', sizeof (dbp->addr));
dbp->addr.sin_family = AF_INET;
- for (i = 0; i < serv->ep.ep_len; ++i)
- {
- if (strcmp (serv->ep.ep_val[i].family, "inet") == 0)
- {
- if (dbp->use_udp)
- {
- if (strcmp (serv->ep.ep_val[i].proto, "udp") == 0)
- dbp->addr.sin_addr.s_addr =
- inetstr2int (serv->ep.ep_val[i].uaddr);
- else
- continue;
- }
- else
- if (strcmp (serv->ep.ep_val[i].proto, "tcp") == 0)
- dbp->addr.sin_addr.s_addr =
- inetstr2int (serv->ep.ep_val[i].uaddr);
- }
- else
- continue;
- }
+
+ dbp->addr.sin_addr.s_addr =
+ inetstr2int (serv->ep.ep_val[dbp->current_ep].uaddr);
+
if (dbp->addr.sin_addr.s_addr == 0)
return NIS_FAIL;
@@ -155,15 +140,15 @@ __bind_connect (dir_binding *dbp)
else
dbp->clnt = clnttcp_create (&dbp->addr, NIS_PROG, NIS_VERSION,
&dbp->socket, 0, 0);
-
+
if (dbp->clnt == NULL)
return NIS_RPCERROR;
-
+
clnt_control (dbp->clnt, CLSET_TIMEOUT, (caddr_t)&TIMEOUT);
/* If the program exists, close the socket */
if (fcntl (dbp->socket, F_SETFD, 1) == -1)
perror (_("fcntl: F_SETFD"));
-
+
if (dbp->use_auth)
{
#if defined(HAVE_SECURE_RPC)
@@ -171,7 +156,7 @@ __bind_connect (dir_binding *dbp)
{
char netname[MAXNETNAMELEN+1];
char *p;
-
+
p = stpcpy (netname, "unix.");
strncpy (p, serv->name,MAXNETNAMELEN-5);
netname[MAXNETNAMELEN] = '\0';
@@ -187,7 +172,7 @@ __bind_connect (dir_binding *dbp)
dbp->clnt->cl_auth = authunix_create_default ();
dbp->use_auth = TRUE;
}
-
+
/* Get port for sanity checks later */
checklen = sizeof (struct sockaddr_in);
memset (&check, 0, checklen);
@@ -207,11 +192,11 @@ __bind_create (const nis_server *serv_val, u_int serv_len, u_long flags)
{
dir_binding *dbp;
u_int i;
-
+
dbp = calloc (1, sizeof (dir_binding));
if (dbp == NULL)
return NULL;
-
+
dbp->server_len = serv_len;
dbp->server_val = calloc (1, sizeof (nis_server) * serv_len);
if (dbp->server_val == NULL)
@@ -219,17 +204,34 @@ __bind_create (const nis_server *serv_val, u_int serv_len, u_long flags)
free (dbp);
return NULL;
}
-
+
+ if (flags & USE_DGRAM)
+ dbp->use_udp = TRUE;
+ else
+ dbp->use_udp = FALSE;
+
+ if (flags & NO_AUTHINFO)
+ dbp->use_auth = FALSE;
+ else
+ dbp->use_auth = TRUE;
+
+ if (flags & MASTER_ONLY)
+ dbp->master_only = TRUE;
+ else
+ dbp->master_only = FALSE;
+
+ dbp->trys = 1;
+
for (i = 0; i < serv_len; ++i)
{
if (serv_val[i].name != NULL)
dbp->server_val[i].name = strdup (serv_val[i].name);
-
+
dbp->server_val[i].ep.ep_len = serv_val[i].ep.ep_len;
if (dbp->server_val[i].ep.ep_len > 0)
{
unsigned long j;
-
+
dbp->server_val[i].ep.ep_val =
malloc (serv_val[i].ep.ep_len * sizeof (endpoint));
for (j = 0; j < dbp->server_val[i].ep.ep_len; ++j)
@@ -267,24 +269,12 @@ __bind_create (const nis_server *serv_val, u_int serv_len, u_long flags)
else
dbp->server_val[i].pkey.n_bytes = NULL;
}
-
- dbp->server_used = __nis_ping (dbp->server_val, dbp->server_len);
- if (flags & USE_DGRAM)
- dbp->use_udp = TRUE;
- else
- dbp->use_udp = FALSE;
-
- if (flags & NO_AUTHINFO)
- dbp->use_auth = FALSE;
- else
- dbp->use_auth = TRUE;
- if (flags & MASTER_ONLY)
- dbp->master_only = TRUE;
- else
- dbp->master_only = FALSE;
-
- dbp->trys = 1;
+ if (__nis_findfastest (dbp) < 1)
+ {
+ __bind_destroy (dbp);
+ return NULL;
+ }
return dbp;
}
@@ -298,10 +288,11 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
nis_error retcode;
dir_binding *dbp;
- if (flags & MASTER_ONLY)
+ if (flags & MASTER_ONLY)
server_len = 1;
-
- dbp = __bind_create (server, server_len, flags);
+
+ if ((dbp = __bind_create (server, server_len, flags)) == NULL)
+ return NIS_UNAVAIL;
while (__bind_connect (dbp) != NIS_SUCCESS)
{
if (__bind_next (dbp) != NIS_SUCCESS)
@@ -315,7 +306,7 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
{
again:
result = clnt_call (dbp->clnt, prog, xargs, req, xres, resp, TIMEOUT);
-
+
if (result != RPC_SUCCESS)
{
clnt_perror (dbp->clnt, "__do_niscall2: clnt_call");
@@ -336,25 +327,56 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
case NIS_IBREMOVE:
case NIS_IBFIRST:
case NIS_IBNEXT:
- if ((((nis_result *)xres)->status != NIS_SUCCESS) &&
- (((nis_result *)xres)->status != NIS_S_SUCCESS))
- if (__bind_next (dbp) == NIS_SUCCESS)
+ if ((((nis_result *)xres)->status == NIS_NOTFOUND) ||
+ (((nis_result *)xres)->status == NIS_NOSUCHNAME) ||
+ (((nis_result *)xres)->status == NIS_NOT_ME))
+ {
+ if (__bind_next (dbp) == NIS_SUCCESS)
+ while (__bind_connect (dbp) != NIS_SUCCESS)
+ {
+ if (__bind_next (dbp) != NIS_SUCCESS)
+ {
+ __bind_destroy (dbp);
+ return NIS_SUCCESS;
+ }
+ }
goto again;
+ }
case NIS_FINDDIRECTORY:
- if (((fd_result *)xres)->status != NIS_SUCCESS)
- if (__bind_next (dbp) == NIS_SUCCESS)
+ if ((((fd_result *)xres)->status == NIS_NOTFOUND) ||
+ (((fd_result *)xres)->status == NIS_NOSUCHNAME) ||
+ (((fd_result *)xres)->status == NIS_NOT_ME))
+ {
+ if (__bind_next (dbp) == NIS_SUCCESS)
+ while (__bind_connect (dbp) != NIS_SUCCESS)
+ {
+ if (__bind_next (dbp) != NIS_SUCCESS)
+ {
+ __bind_destroy (dbp);
+ return NIS_SUCCESS;
+ }
+ }
goto again;
- break;
-#if 0
- case NIS_STATUS: /* nis_taglist */
- case NIS_SERVSTATE:
+ }
break;
case NIS_DUMPLOG: /* log_result */
case NIS_DUMP:
+ if ((((log_result *)xres)->lr_status == NIS_NOTFOUND) ||
+ (((log_result *)xres)->lr_status == NIS_NOSUCHNAME) ||
+ (((log_result *)xres)->lr_status == NIS_NOT_ME))
+ {
+ if (__bind_next (dbp) == NIS_SUCCESS)
+ while (__bind_connect (dbp) != NIS_SUCCESS)
+ {
+ if (__bind_next (dbp) != NIS_SUCCESS)
+ {
+ __bind_destroy (dbp);
+ return NIS_SUCCESS;
+ }
+ }
+ goto again;
+ }
break;
- case NIS_CHECKPOINT: /* cp_result */
- break;
-#endif
default:
break;
}
@@ -363,12 +385,13 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
}
}
while ((flags & HARD_LOOKUP) && retcode == NIS_RPCERROR);
-
- return retcode;
+
+ return retcode;
}
static directory_obj *
-rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
+rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags,
+ nis_error *status)
{
fd_result *fd_res;
XDR xdrs;
@@ -399,6 +422,7 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
switch (nis_dir_cmp (domain, dir->do_name))
{
case SAME_NAME:
+ *status = NIS_SUCCESS;
return dir;
case NOT_SEQUENTIAL:
/* NOT_SEQUENTIAL means, go one up and try it there ! */
@@ -413,6 +437,7 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
domain ! (Now I understand why a root server must be a
replica of the parent domain) */
fd_res = __nis_finddirectory (dir, ndomain);
+ *status = fd_res->status;
if (fd_res->status != NIS_SUCCESS)
{
nis_free_directory (dir);
@@ -431,7 +456,7 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
/* We have found a NIS+ server serving ndomain, now
let us search for "name" */
nis_free_directory (dir);
- return rec_dirsearch (name, obj, flags);
+ return rec_dirsearch (name, obj, flags, status);
}
else
{
@@ -447,7 +472,7 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
char leaf [strlen (name) + 3];
char ndomain [strlen (name) + 3];
char *cp;
-
+
do
{
if (strlen (domain) == 0)
@@ -463,8 +488,9 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
cp = strchr (leaf, '\0');
*cp++ = '.';
strcpy (cp, domain);
-
+
fd_res = __nis_finddirectory (dir, leaf);
+ *status = fd_res->status;
if (fd_res->status != NIS_SUCCESS)
{
nis_free_directory (dir);
@@ -483,15 +509,17 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
/* We have found a NIS+ server serving ndomain, now
let us search for "name" */
nis_free_directory (dir);
- return rec_dirsearch (name, obj, flags);
+ return rec_dirsearch (name, obj, flags, status);
}
}
break;
case BAD_NAME:
nis_free_directory (dir);
+ *status = NIS_BADNAME;
return NULL;
}
nis_free_directory (dir);
+ *status = NIS_FAIL;
return NULL;
}
@@ -509,19 +537,20 @@ __do_niscall (const_nis_name name, u_long prog, xdrproc_t xargs,
if ((flags & NO_CACHE) != NO_CACHE)
dir = __cache_search (name);
-
+
if (dir == NULL)
{
+ nis_error status;
dir = readColdStartFile ();
if (dir == NULL) /* No /var/nis/NIS_COLD_START->no NIS+ installed */
return NIS_UNAVAIL;
-
- dir = rec_dirsearch (name, dir, flags);
+
+ dir = rec_dirsearch (name, dir, flags, &status);
if (dir == NULL)
- return NIS_NOTFOUND;
+ return status;
}
- if (flags & MASTER_ONLY)
+ if (flags & MASTER_ONLY)
{
server = dir->do_servers.do_servers_val;
server_len = 1;
@@ -531,11 +560,11 @@ __do_niscall (const_nis_name name, u_long prog, xdrproc_t xargs,
server = dir->do_servers.do_servers_val;
server_len = dir->do_servers.do_servers_len;
}
-
-
+
+
retcode = __do_niscall2 (server, server_len, prog, xargs, req, xres, resp,
flags);
-
+
nis_free_directory (dir);
return retcode;
diff --git a/nis/nis_findserv.c b/nis/nis_findserv.c
new file mode 100644
index 0000000000..a04abd8056
--- /dev/null
+++ b/nis/nis_findserv.c
@@ -0,0 +1,251 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 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 <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <rpcsvc/nis.h>
+
+#include "nis_intern.h"
+
+/* Private data kept per client handle, from sunrpc/clnt_udp.c */
+struct cu_data
+ {
+ int cu_sock;
+ bool_t cu_closeit;
+ struct sockaddr_in cu_raddr;
+ int cu_rlen;
+ struct timeval cu_wait;
+ struct timeval cu_total;
+ struct rpc_err cu_error;
+ XDR cu_outxdrs;
+ u_int cu_xdrpos;
+ u_int cu_sendsz;
+ char *cu_outbuf;
+ u_int cu_recvsz;
+ char cu_inbuf[1];
+ };
+
+
+/* The following is the original routine from sunrpc/pm_getport.c.
+ The only change is the much shorter timeout. */
+/*
+ * pmap_getport.c
+ * Client interface to pmap rpc service.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+/*
+ * Find the mapped port for program,version.
+ * Calls the pmap service remotely to do the lookup.
+ * Returns 0 if no map exists.
+ */
+static u_short
+__pmap_getport (struct sockaddr_in *address, u_long program,
+ u_long version, u_int protocol)
+{
+ const struct timeval timeout = {1, 0};
+ const struct timeval tottimeout = {1, 0};
+ u_short port = 0;
+ int socket = -1;
+ CLIENT *client;
+ struct pmap parms;
+
+ address->sin_port = htons (PMAPPORT);
+ client = clntudp_bufcreate (address, PMAPPROG, PMAPVERS, timeout, &socket,
+ RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+ if (client != (CLIENT *) NULL)
+ {
+ parms.pm_prog = program;
+ parms.pm_vers = version;
+ parms.pm_prot = protocol;
+ parms.pm_port = 0; /* not needed or used */
+ if (CLNT_CALL (client, PMAPPROC_GETPORT, (xdrproc_t) xdr_pmap,
+ (caddr_t) & parms, (xdrproc_t) xdr_u_short,
+ (caddr_t) & port, tottimeout) != RPC_SUCCESS)
+ {
+ rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+ clnt_geterr (client, &rpc_createerr.cf_error);
+ }
+ else if (port == 0)
+ {
+ rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+ }
+ CLNT_DESTROY (client);
+ }
+ /* (void)close(socket); CLNT_DESTROY already closed it */
+ address->sin_port = 0;
+ return port;
+}
+
+/* Transmit to NULLPROC, return immediately. */
+static void *
+nis_null_3_send (void *argp, CLIENT * clnt)
+{
+ static char clnt_res;
+ struct timeval TIMEOUT = {0, 0};
+
+ memset ((char *) &clnt_res, 0, sizeof (clnt_res));
+ if (clnt_call (clnt, NULLPROC,
+ (xdrproc_t) xdr_void, (caddr_t) argp,
+ (xdrproc_t) xdr_void, (caddr_t) & clnt_res,
+ TIMEOUT) != RPC_SUCCESS)
+ return NULL;
+ return (void *) &clnt_res;
+}
+
+/* Receive request from NULLPROC asynchronously. */
+static void *
+nis_null_3_recv (void *argp, CLIENT * clnt)
+{
+ static char clnt_res;
+ struct timeval TIMEOUT = {0, 0};
+
+ memset ((char *) &clnt_res, 0, sizeof (clnt_res));
+ if (clnt_call (clnt, NULLPROC,
+ (xdrproc_t) NULL, (caddr_t) argp,
+ (xdrproc_t) xdr_void, (caddr_t) & clnt_res,
+ TIMEOUT) != RPC_SUCCESS)
+ return NULL;
+ return (void *) &clnt_res;
+}
+
+/* This is now the public functions, which should find the fastest server */
+
+struct findserv_req
+{
+ struct sockaddr_in sin;
+ u_long xid;
+ u_int server_nr;
+ u_int server_ep;
+};
+
+long
+__nis_findfastest (dir_binding * bind)
+{
+ struct timeval TIMEOUT = {5, 0};
+ struct findserv_req **pings;
+ struct sockaddr_in sin;
+ int found = -1;
+ time_t xid_seed, xid_lookup;
+ int sock, dontblock = 1;
+ CLIENT *clnt;
+ void *foo = NULL;
+ u_long i, j, pings_count, pings_max;
+ struct cu_data *cu;
+
+ pings_max = bind->server_len * 2; /* Reserve a little bit more memory
+ for multihomed hosts */
+ pings_count = 0;
+ pings = malloc (sizeof (struct findserv_req *) * pings_max);
+ xid_seed = time (NULL) ^ getpid ();
+
+ memset (&sin, '\0', sizeof (sin));
+ sin.sin_family = AF_INET;
+ for (i = 0; i < bind->server_len; i++)
+ for (j = 0; j < bind->server_val[i].ep.ep_len; ++j)
+ if (strcmp (bind->server_val[i].ep.ep_val[j].family, "inet") == 0)
+ if (strcmp (bind->server_val[i].ep.ep_val[j].proto, "-") == 0)
+ {
+ sin.sin_addr.s_addr =
+ inetstr2int (bind->server_val[i].ep.ep_val[j].uaddr);
+ if (sin.sin_addr.s_addr == 0)
+ continue;
+ sin.sin_port = htons (__pmap_getport (&sin, NIS_PROG,
+ NIS_VERSION, IPPROTO_UDP));
+ if (sin.sin_port == 0)
+ continue;
+
+ if (pings_count >= pings_max)
+ {
+ pings_max += 10;
+ pings = realloc (pings, sizeof (struct findserv_req) *
+ pings_max);
+ }
+ pings[pings_count] = calloc (1, sizeof (struct findserv_req));
+ memcpy ((char *) &pings[pings_count]->sin, (char *) &sin,
+ sizeof (sin));
+ pings[pings_count]->xid = xid_seed;
+ pings[pings_count]->server_nr = i;
+ pings[pings_count]->server_ep = j;
+ ++xid_seed;
+ ++pings_count;
+ }
+
+ /* Make sure at least one server was assigned */
+ if (pings_count == 0)
+ {
+ free (pings);
+ return -1;
+ }
+
+ /* Create RPC handle */
+ sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ clnt = clntudp_create (&sin, NIS_PROG, NIS_VERSION, TIMEOUT, &sock);
+ if (clnt == NULL)
+ {
+ close (sock);
+ for (i = 0; i < pings_count; ++i)
+ free (pings[i]);
+ free (pings);
+ return -1;
+ }
+ clnt->cl_auth = authunix_create_default ();
+ cu = (struct cu_data *) clnt->cl_private;
+ TIMEOUT.tv_sec = 0;
+ clnt_control (clnt, CLSET_TIMEOUT, (char *) &TIMEOUT);
+ ioctl (sock, FIONBIO, &dontblock);
+
+ /* Send to all servers the NULLPROC */
+ for (i = 0; i < pings_count; ++i)
+ {
+ /* clntudp_call() will increment, subtract one */
+ *((u_int32_t *) (cu->cu_outbuf)) = pings[i]->xid - 1;
+ bcopy ((char *) &pings[i]->sin, (char *) &cu->cu_raddr,
+ sizeof (struct sockaddr_in));
+ nis_null_3_send (foo, clnt);
+ }
+
+ /* Receive reply */
+ nis_null_3_recv (foo, clnt);
+
+ xid_lookup = *((u_int32_t *) (cu->cu_inbuf));
+ for (i = 0; i < pings_count; i++)
+ {
+ if (pings[i]->xid == xid_lookup)
+ {
+ bind->server_used = pings[i]->server_nr;
+ bind->current_ep = pings[i]->server_ep;
+ found = 1;
+ }
+ }
+
+ auth_destroy (clnt->cl_auth);
+ clnt_destroy (clnt);
+ close (sock);
+
+ for (i = 0; i < pings_count; ++i)
+ free (pings[i]);
+ free (pings);
+
+ return found;
+}
diff --git a/nis/nis_intern.h b/nis/nis_intern.h
index a7cb785e40..fdc392ad7f 100644
--- a/nis/nis_intern.h
+++ b/nis/nis_intern.h
@@ -24,12 +24,32 @@
__BEGIN_DECLS
+struct dir_binding
+{
+ CLIENT *clnt; /* RPC CLIENT handle */
+ nis_server *server_val; /* List of servers */
+ u_int server_len; /* # of servers */
+ u_int server_used; /* Which server we are bind in the moment ? */
+ u_int current_ep; /* Which endpoint of the server are in use? */
+ u_int trys; /* How many server have we tried ? */
+ bool_t master_only; /* Is only binded to the master */
+ bool_t use_auth; /* Do we use AUTH ? */
+ bool_t use_udp; /* Do we use UDP ? */
+ time_t create; /* Binding creation time */
+ struct sockaddr_in addr; /* Server's IP address */
+ int socket; /* Server's local socket */
+ unsigned short port; /* Local port */
+};
+typedef struct dir_binding dir_binding;
+
+extern unsigned long inetstr2int __P ((const char *str));
+extern long __nis_findfastest __P ((dir_binding *bind));
extern nis_error __do_niscall2 __P ((const nis_server *serv, u_int serv_len,
u_long prog, xdrproc_t xargs, caddr_t req,
- xdrproc_t xres, caddr_t resp,
+ xdrproc_t xres, caddr_t resp,
u_long flags));
extern nis_error __do_niscall __P ((const_nis_name name, u_long prog,
- xdrproc_t xargs, caddr_t req,
+ xdrproc_t xargs, caddr_t req,
xdrproc_t xres, caddr_t resp,
u_long flags));
#if defined (HAVE_SECURE_RPC)
diff --git a/nis/nis_lookup.c b/nis/nis_lookup.c
index 82db7b0b25..6224b1f2c4 100644
--- a/nis/nis_lookup.c
+++ b/nis/nis_lookup.c
@@ -96,6 +96,10 @@ nis_lookup (const_nis_name name, const u_long flags)
/* XXX Implement CALLBACK here ! */
++done;
break;
+ case NIS_UNAVAIL:
+ /* NIS+ is not installed, or all servers are down */
+ ++done;
+ break;
default:
/* Try the next domainname if we don't follow a link */
if (count_links)
diff --git a/nis/nis_ping.c b/nis/nis_ping.c
index 941adfbda4..4ec34ce4c0 100644
--- a/nis/nis_ping.c
+++ b/nis/nis_ping.c
@@ -34,7 +34,7 @@ nis_ping (const_nis_name dirname, u_long utime, const nis_object *dirobj)
if (dirobj == NULL)
{
- res = nis_lookup (dirname, EXPAND_NAME + FOLLOW_LINKS);
+ res = nis_lookup (dirname, MASTER_ONLY);
if (res->status != NIS_SUCCESS && res->status != NIS_S_SUCCESS)
return;
obj = res->objects.objects_val;
@@ -44,7 +44,11 @@ nis_ping (const_nis_name dirname, u_long utime, const nis_object *dirobj)
/* Check if obj is really a diryectory object */
if (obj->zo_data.zo_type != DIRECTORY_OBJ)
- abort ();
+ {
+ if (res != NULL)
+ nis_freeresult (res);
+ return;
+ }
if (dirname == NULL)
args.dir = obj->DI_data.do_name;
diff --git a/nis/nis_table.c b/nis/nis_table.c
index 16fd1e68ec..a3bfa2c0cc 100644
--- a/nis/nis_table.c
+++ b/nis/nis_table.c
@@ -248,7 +248,11 @@ nis_list (const_nis_name name, u_long flags,
/* XXX Implement CALLBACK here ! */
++done;
break;
- default:
+ case NIS_UNAVAIL:
+ /* NIS+ is not installed, or all servers are down */
+ ++done;
+ break;
+ default:
/* Try the next domainname if we don't follow a link */
if (count_links)
{
diff --git a/nis/nis_util.c b/nis/nis_util.c
index 4e39d6fb6a..b6eef9b227 100644
--- a/nis/nis_util.c
+++ b/nis/nis_util.c
@@ -24,6 +24,7 @@
fd_result *
__nis_finddirectory (directory_obj *dir, const_nis_name name)
{
+ nis_error status;
fd_args fd_args;
fd_result *fd_res;
@@ -31,13 +32,14 @@ __nis_finddirectory (directory_obj *dir, const_nis_name name)
fd_args.requester = nis_local_host();
fd_res = calloc (1, sizeof (fd_result));
- if (__do_niscall2 (dir->do_servers.do_servers_val,
- dir->do_servers.do_servers_len, NIS_FINDDIRECTORY,
- (xdrproc_t) xdr_fd_args,
- (caddr_t) &fd_args, (xdrproc_t) xdr_fd_result,
- (caddr_t) fd_res, NO_AUTHINFO|USE_DGRAM) != NIS_SUCCESS)
- fd_res->status = NIS_RPCERROR;
-
+ if ((status = __do_niscall2 (dir->do_servers.do_servers_val,
+ dir->do_servers.do_servers_len,
+ NIS_FINDDIRECTORY, (xdrproc_t) xdr_fd_args,
+ (caddr_t) &fd_args, (xdrproc_t) xdr_fd_result,
+ (caddr_t) fd_res,
+ NO_AUTHINFO|USE_DGRAM)) != NIS_SUCCESS)
+ fd_res->status = status;
+
return fd_res;
}
diff --git a/nis/nss_compat/compat-grp.c b/nis/nss_compat/compat-grp.c
index 9726784b2d..35ae2f7b02 100644
--- a/nis/nss_compat/compat-grp.c
+++ b/nis/nss_compat/compat-grp.c
@@ -18,6 +18,7 @@
Boston, MA 02111-1307, USA. */
#include <errno.h>
+#include <fcntl.h>
#include <nss.h>
#include <grp.h>
#include <ctype.h>
@@ -132,6 +133,26 @@ internal_setgrent (ent_t *ent)
if (ent->stream == NULL)
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
+ else
+ {
+ /* We have to make sure the file is `closed on exec'. */
+ int result, flags;
+
+ result = flags = fcntl (fileno (ent->stream), F_GETFD, 0);
+ if (result >= 0)
+ {
+ flags |= FD_CLOEXEC;
+ result = fcntl (fileno (ent->stream), F_SETFD, flags);
+ }
+ if (result < 0)
+ {
+ /* Something went wrong. Close the stream and return a
+ failure. */
+ fclose (ent->stream);
+ ent->stream = NULL;
+ status = NSS_STATUS_UNAVAIL;
+ }
+ }
}
else
rewind (ent->stream);
@@ -277,7 +298,7 @@ getgrent_next_nis (struct group *result, ent_t *ent, char *buffer,
if (!save_nis_first)
free (save_oldkey);
}
-
+
if (parse_res &&
in_blacklist (result->gr_name, strlen (result->gr_name), ent))
parse_res = 0; /* if result->gr_name in blacklist,search next entry */
@@ -297,7 +318,7 @@ getgrent_next_nisplus (struct group *result, ent_t *ent, char *buffer,
{
nis_result *save_oldres;
bool_t save_nis_first;
-
+
if (ent->nis_first)
{
save_oldres = ent->result;
@@ -324,7 +345,7 @@ getgrent_next_nisplus (struct group *result, ent_t *ent, char *buffer,
return niserr2nss (ent->result->status);
}
}
- if ((parse_res = _nss_nisplus_parse_grent (ent->result, 0, result,
+ if ((parse_res = _nss_nisplus_parse_grent (ent->result, 0, result,
buffer, buflen)) == -1)
{
nis_freeresult (ent->result);
@@ -370,7 +391,7 @@ getgrent_next_file_plusgroup (struct group *result, char *buffer,
nis_freeresult (res);
return status;
}
- if ((parse_res = _nss_nisplus_parse_grent (res, 0, result, buffer,
+ if ((parse_res = _nss_nisplus_parse_grent (res, 0, result, buffer,
buflen)) == -1)
{
__set_errno (ERANGE);
diff --git a/nis/nss_compat/compat-pwd.c b/nis/nss_compat/compat-pwd.c
index af1267922c..6fac0f46c6 100644
--- a/nis/nss_compat/compat-pwd.c
+++ b/nis/nss_compat/compat-pwd.c
@@ -21,6 +21,7 @@
#include <pwd.h>
#include <errno.h>
#include <ctype.h>
+#include <fcntl.h>
#include <netdb.h>
#include <string.h>
#include <bits/libc-lock.h>
@@ -232,6 +233,26 @@ internal_setpwent (ent_t *ent)
if (ent->stream == NULL)
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
+ else
+ {
+ /* We have to make sure the file is `closed on exec'. */
+ int result, flags;
+
+ result = flags = fcntl (fileno (ent->stream), F_GETFD, 0);
+ if (result >= 0)
+ {
+ flags |= FD_CLOEXEC;
+ result = fcntl (fileno (ent->stream), F_SETFD, flags);
+ }
+ if (result < 0)
+ {
+ /* Something went wrong. Close the stream and return a
+ failure. */
+ fclose (ent->stream);
+ ent->stream = NULL;
+ status = NSS_STATUS_UNAVAIL;
+ }
+ }
}
else
rewind (ent->stream);
@@ -274,7 +295,7 @@ internal_endpwent (ent_t *ent)
if (ent->netgroup)
__internal_endnetgrent (&ent->netgrdata);
-
+
ent->nis = ent->first = ent->netgroup = 0;
if (ent->oldkey != NULL)
@@ -432,13 +453,13 @@ getpwent_next_nisplus_netgr (struct passwd *result, ent_t *ent, char *group,
give_pwd_free (&ent->pwd);
return NSS_STATUS_RETURN;
}
-
+
if (user == NULL || user[0] == '-')
continue;
-
+
if (domain != NULL && strcmp (ypdomain, domain) != 0)
continue;
-
+
p2len = pwd_need_buflen (&ent->pwd);
if (p2len > buflen)
{
@@ -457,7 +478,7 @@ getpwent_next_nisplus_netgr (struct passwd *result, ent_t *ent, char *group,
nis_freeresult (nisres);
continue;
}
- if ((parse_res = _nss_nisplus_parse_pwent (nisres, result, buffer,
+ if ((parse_res = _nss_nisplus_parse_pwent (nisres, result, buffer,
buflen)) == -1)
{
nis_freeresult (nisres);
@@ -551,7 +572,7 @@ getpwent_next_nisplus (struct passwd *result, ent_t *ent, char *buffer,
if (!saved_first)
nis_freeresult (saved_res);
}
-
+
if (parse_res &&
in_blacklist (result->pw_name, strlen (result->pw_name), ent))
parse_res = 0; /* if result->pw_name in blacklist,search next entry */
@@ -592,7 +613,7 @@ getpwent_next_nis (struct passwd *result, ent_t *ent, char *buffer,
bool_t saved_first;
char *saved_oldkey;
int saved_oldlen;
-
+
if (ent->first)
{
if (yp_first (domain, "passwd.byname", &outkey, &outkeylen,
@@ -602,7 +623,7 @@ getpwent_next_nis (struct passwd *result, ent_t *ent, char *buffer,
give_pwd_free (&ent->pwd);
return NSS_STATUS_UNAVAIL;
}
-
+
saved_first = TRUE;
saved_oldkey = ent->oldkey;
saved_oldlen = ent->oldkeylen;
@@ -699,7 +720,7 @@ getpwent_next_file_plususer (struct passwd *result, char *buffer,
nis_freeresult (res);
return status;
}
- if ((parse_res = _nss_nisplus_parse_pwent (res, result, buffer,
+ if ((parse_res = _nss_nisplus_parse_pwent (res, result, buffer,
buflen)) == -1)
{
nis_freeresult (res);
@@ -713,10 +734,10 @@ getpwent_next_file_plususer (struct passwd *result, char *buffer,
char *domain;
char *outval;
int outvallen;
-
+
if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
return NSS_STATUS_TRYAGAIN;
-
+
if (yp_match (domain, "passwd.byname", &result->pw_name[1],
strlen (result->pw_name) - 1, &outval, &outvallen)
!= YPERR_SUCCESS)
diff --git a/nis/nss_compat/compat-spwd.c b/nis/nss_compat/compat-spwd.c
index 61a703c1ea..a4c6201c2d 100644
--- a/nis/nss_compat/compat-spwd.c
+++ b/nis/nss_compat/compat-spwd.c
@@ -20,6 +20,7 @@
#include <nss.h>
#include <errno.h>
#include <ctype.h>
+#include <fcntl.h>
#include <netdb.h>
#include <shadow.h>
#include <string.h>
@@ -184,6 +185,26 @@ internal_setspent (ent_t *ent)
if (ent->stream == NULL)
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
+ else
+ {
+ /* We have to make sure the file is `closed on exec'. */
+ int result, flags;
+
+ result = flags = fcntl (fileno (ent->stream), F_GETFD, 0);
+ if (result >= 0)
+ {
+ flags |= FD_CLOEXEC;
+ result = fcntl (fileno (ent->stream), F_SETFD, flags);
+ }
+ if (result < 0)
+ {
+ /* Something went wrong. Close the stream and return a
+ failure. */
+ fclose (ent->stream);
+ ent->stream = NULL;
+ status = NSS_STATUS_UNAVAIL;
+ }
+ }
}
else
rewind (ent->stream);
@@ -305,10 +326,10 @@ getspent_next_nis_netgr (struct spwd *result, ent_t *ent, char *group,
give_spwd_free (&ent->pwd);
return NSS_STATUS_RETURN;
}
-
+
if (user == NULL || user[0] == '-')
continue;
-
+
if (domain != NULL && strcmp (ypdomain, domain) != 0)
continue;
@@ -651,7 +672,7 @@ getspent_next_file_plususer (struct spwd *result, char *buffer,
nis_freeresult (res);
return status;
}
- if ((parse_res = _nss_nisplus_parse_spent (res, result, buffer,
+ if ((parse_res = _nss_nisplus_parse_spent (res, result, buffer,
buflen)) == -1)
{
nis_freeresult (res);
@@ -735,7 +756,7 @@ getspent_next_file (struct spwd *result, ent_t *ent,
__set_errno (ERANGE);
return NSS_STATUS_TRYAGAIN;
}
-
+
if (result->sp_namp[0] != '+' && result->sp_namp[0] != '-')
/* This is a real entry. */
break;
diff --git a/nis/ypclnt.c b/nis/ypclnt.c
index 85597144b2..7c9efec70a 100644
--- a/nis/ypclnt.c
+++ b/nis/ypclnt.c
@@ -130,12 +130,15 @@ __yp_bind (const char *domain, dom_binding ** ypdb)
(caddr_t) &ypbr, TIMEOUT) != RPC_SUCCESS)
{
clnt_destroy (client);
+ close (clnt_sock);
if (is_new)
free (ysd);
return YPERR_YPBIND;
}
clnt_destroy (client);
+ close (clnt_sock);
+
if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
{
switch (ypbr.ypbind_resp_u.ypbind_error)
@@ -174,7 +177,10 @@ __yp_bind (const char *domain, dom_binding ** ypdb)
}
if (ysd->dom_client)
- clnt_destroy (ysd->dom_client);
+ {
+ clnt_destroy (ysd->dom_client);
+ close (ysd->dom_socket);
+ }
ysd->dom_socket = RPC_ANYSOCK;
ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
TIMEOUT, &ysd->dom_socket);
@@ -635,18 +641,16 @@ yp_all (const char *indomain, const char *inmap,
(caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
(caddr_t) &status, TIMEOUT);
+ clnt_destroy (clnt);
+ close (clnt_sock);
if (result != RPC_SUCCESS)
{
clnt_perror (ydb->dom_client, "yp_all: clnt_call");
- clnt_destroy (clnt);
__yp_unbind (ydb);
result = YPERR_RPC;
}
else
- {
- clnt_destroy (clnt);
- result = YPERR_SUCCESS;
- }
+ result = YPERR_SUCCESS;
__libc_lock_unlock (ypbindlist_lock);
diff --git a/nss/nss_db/db-XXX.c b/nss/nss_db/db-XXX.c
index 0c1b1ada37..54e7a754c3 100644
--- a/nss/nss_db/db-XXX.c
+++ b/nss/nss_db/db-XXX.c
@@ -1,5 +1,5 @@
/* Common code for DB-based databases in nss_db module.
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 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
@@ -66,7 +66,27 @@ internal_setent (int stayopen)
db = __dbopen (DBFILE, O_RDONLY, 0, DB_BTREE, NULL);
if (db == 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'. */
+ int result, flags;
+
+ result = flags = fcntl ((*db->fd) (db), F_GETFD, 0);
+ if (result >= 0)
+ {
+ flags |= FD_CLOEXEC;
+ result = fcntl ((*db->fd) (db), F_SETFD, flags);
+ }
+ if (result < 0)
+ {
+ /* Something went wrong. Close the stream and return a
+ failure. */
+ (*db->close) (db);
+ db = NULL;
+ status = NSS_STATUS_UNAVAIL;
+ }
+ }
}
/* Remember STAYOPEN flag. */
diff --git a/nss/nss_db/db-alias.c b/nss/nss_db/db-alias.c
index 8b8cb41238..810fc3aba6 100644
--- a/nss/nss_db/db-alias.c
+++ b/nss/nss_db/db-alias.c
@@ -1,5 +1,5 @@
/* Mail alias file parser in nss_db module.
- 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.
@@ -51,6 +51,26 @@ internal_setent (int stayopen)
if (db == NULL)
status = NSS_STATUS_UNAVAIL;
+ else
+ {
+ /* We have to make sure the file is `closed on exec'. */
+ int result, flags;
+
+ result = flags = fcntl ((*db->fd) (db), F_GETFD, 0);
+ if (result >= 0)
+ {
+ flags |= FD_CLOEXEC;
+ result = fcntl ((*db->fd) (db), F_SETFD, flags);
+ }
+ if (result < 0)
+ {
+ /* Something went wrong. Close the stream and return a
+ failure. */
+ (*db->close) (db);
+ db = NULL;
+ status = NSS_STATUS_UNAVAIL;
+ }
+ }
}
/* Remember STAYOPEN flag. */
diff --git a/nss/nss_db/db-netgrp.c b/nss/nss_db/db-netgrp.c
index e716dd00b2..c301789f74 100644
--- a/nss/nss_db/db-netgrp.c
+++ b/nss/nss_db/db-netgrp.c
@@ -53,6 +53,26 @@ _nss_db_setnetgrent (const char *group)
if (db == NULL)
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
+ else
+ {
+ /* We have to make sure the file is `closed on exec'. */
+ int result, flags;
+
+ result = flags = fcntl ((*db->fd) (db), F_GETFD, 0);
+ if (result >= 0)
+ {
+ flags |= FD_CLOEXEC;
+ result = fcntl ((*db->fd) (db), F_SETFD, flags);
+ }
+ if (result < 0)
+ {
+ /* Something went wrong. Close the stream and return a
+ failure. */
+ (*db->close) (db);
+ db = NULL;
+ status = NSS_STATUS_UNAVAIL;
+ }
+ }
}
if (status == NSS_STATUS_SUCCESS)
diff --git a/nss/nss_files/files-XXX.c b/nss/nss_files/files-XXX.c
index 3281580b8f..e80c06d269 100644
--- a/nss/nss_files/files-XXX.c
+++ b/nss/nss_files/files-XXX.c
@@ -21,6 +21,7 @@
#include <ctype.h>
#include <assert.h>
#include <errno.h>
+#include <fcntl.h>
#include <bits/libc-lock.h>
#include "nsswitch.h"
@@ -72,6 +73,26 @@ internal_setent (int stayopen)
if (stream == NULL)
status = NSS_STATUS_UNAVAIL;
+ else
+ {
+ /* We have to make sure the file is `closed on exec'. */
+ int result, flags;
+
+ result = flags = fcntl (fileno (stream), F_GETFD, 0);
+ if (result >= 0)
+ {
+ flags |= FD_CLOEXEC;
+ result = fcntl (fileno (stream), F_SETFD, flags);
+ }
+ if (result < 0)
+ {
+ /* Something went wrong. Close the stream and return a
+ failure. */
+ fclose (stream);
+ stream = NULL;
+ status = NSS_STATUS_UNAVAIL;
+ }
+ }
}
else
rewind (stream);
diff --git a/nss/nss_files/files-alias.c b/nss/nss_files/files-alias.c
index 99217fa7c5..0a910aa0fe 100644
--- a/nss/nss_files/files-alias.c
+++ b/nss/nss_files/files-alias.c
@@ -1,5 +1,5 @@
/* Mail alias file parser in nss_files module.
- 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.
@@ -21,6 +21,7 @@
#include <aliases.h>
#include <ctype.h>
#include <errno.h>
+#include <fcntl.h>
#include <bits/libc-lock.h>
#include <stdlib.h>
#include <stdio.h>
@@ -49,6 +50,26 @@ internal_setent (void)
if (stream == NULL)
status = NSS_STATUS_UNAVAIL;
+ else
+ {
+ /* We have to make sure the file is `closed on exec'. */
+ int result, flags;
+
+ result = flags = fcntl (fileno (stream), F_GETFD, 0);
+ if (result >= 0)
+ {
+ flags |= FD_CLOEXEC;
+ result = fcntl (fileno (stream), F_SETFD, flags);
+ }
+ if (result < 0)
+ {
+ /* Something went wrong. Close the stream and return a
+ failure. */
+ fclose (stream);
+ stream = NULL;
+ status = NSS_STATUS_UNAVAIL;
+ }
+ }
}
else
rewind (stream);
diff --git a/nss/nss_files/files-hosts.c b/nss/nss_files/files-hosts.c
index 239dea7ebd..d6c4152507 100644
--- a/nss/nss_files/files-hosts.c
+++ b/nss/nss_files/files-hosts.c
@@ -50,12 +50,7 @@ LINE_PARSER
STRING_FIELD (addr, isspace, 1);
/* Parse address. */
- if (inet_pton (AF_INET6, p, entdata->host_addr) > 0)
- {
- result->h_addrtype = AF_INET6;
- result->h_length = IN6ADDRSZ;
- }
- else if (inet_pton (AF_INET, addr, entdata->host_addr) > 0)
+ if (inet_pton (AF_INET, addr, entdata->host_addr) > 0)
{
if (_res.options & RES_USE_INET6)
{
@@ -70,6 +65,11 @@ LINE_PARSER
result->h_length = INADDRSZ;
}
}
+ else if (inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
+ {
+ result->h_addrtype = AF_INET6;
+ result->h_length = IN6ADDRSZ;
+ }
else
/* Illegal address: ignore line. */
return 0;
@@ -85,8 +85,12 @@ LINE_PARSER
#include "files-XXX.c"
DB_LOOKUP (hostbyname, ,,
- LOOKUP_NAME (h_name, h_aliases),
- const char *name)
+ {
+ if (result->h_addrtype != ((_res.options & RES_USE_INET6)
+ ? AF_INET6 : AF_INET))
+ continue;
+ LOOKUP_NAME (h_name, h_aliases)
+ }, const char *name)
DB_LOOKUP (hostbyname2, ,,
{
diff --git a/posix/sys/types.h b/posix/sys/types.h
index f49c996a04..131966029e 100644
--- a/posix/sys/types.h
+++ b/posix/sys/types.h
@@ -68,6 +68,7 @@ typedef __key_t key_t;
#define __need_size_t
#include <stddef.h>
+typedef size_t socklen_t;
#ifdef __USE_MISC
/* Old compatibility names for C types. */
diff --git a/string/string.h b/string/string.h
index f790a246f9..5621dfb39a 100644
--- a/string/string.h
+++ b/string/string.h
@@ -118,24 +118,24 @@ extern char *strndup __P ((__const char *__string, size_t __n));
#if defined __USE_GNU && defined __GNUC__
/* Duplicate S, returning an identical alloca'd string. */
-#define strdupa(s) \
+# define strdupa(s) \
(__extension__ \
({ \
__const char *__old = (s); \
size_t __len = strlen (__old) + 1; \
char *__new = __builtin_alloca (__len); \
- memcpy (__new, __old, __len); \
+ (char *) memcpy (__new, __old, __len); \
}))
/* Return an alloca'd copy of at most N bytes of string. */
-#define strndupa(s, n) \
+# define strndupa(s, n) \
(__extension__ \
({ \
__const char *__old = (s); \
size_t __len = strnlen (__old, (n)); \
char *__new = __builtin_alloca (__len + 1); \
__new[__len] = '\0'; \
- memcpy (__new, __old, __len); \
+ (char *) memcpy (__new, __old, __len); \
}))
#endif
@@ -182,14 +182,14 @@ extern size_t strlen __P ((__const char *__s));
If no '\0' terminator is found in that many characters, return MAXLEN. */
extern size_t strnlen __P ((__const char *__string, size_t __maxlen));
-#ifdef __OPTIMIZE__
+# ifdef __OPTIMIZE__
extern __inline size_t
strnlen (__const char *__string, size_t __maxlen)
{
__const char *__end = (__const char *) memchr (__string, '\0', __maxlen);
return __end ? __end - __string : __maxlen;
}
-#endif
+# endif
#endif
@@ -207,6 +207,7 @@ extern char *strerror_r __P ((int __errnum, char *__buf, size_t __buflen));
extern void bcopy __P ((__const __ptr_t __src, __ptr_t __dest, size_t __n));
/* Set N bytes of S to 0. */
+extern void __bzero __P ((__ptr_t __s, size_t __n));
extern void bzero __P ((__ptr_t __s, size_t __n));
/* Compare N bytes of S1 and S2 (same as memcmp). */
diff --git a/sysdeps/alpha/dl-machine.h b/sysdeps/alpha/dl-machine.h
index 49d6830a65..746cdd236b 100644
--- a/sysdeps/alpha/dl-machine.h
+++ b/sysdeps/alpha/dl-machine.h
@@ -87,7 +87,7 @@ elf_machine_load_address (void)
entries will jump to the on-demand fixup code in dl-runtime.c. */
static inline int
-elf_machine_runtime_setup (struct link_map *l, int lazy)
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
Elf64_Addr plt;
extern void _dl_runtime_resolve (void);
@@ -348,9 +348,9 @@ static inline void
elf_machine_rela (struct link_map *map,
const Elf64_Rela *reloc,
const Elf64_Sym *sym,
- const struct r_found_version *version)
+ const struct r_found_version *version,
+ Elf64_Addr *const reloc_addr)
{
- Elf64_Addr * const reloc_addr = (void *)(map->l_addr + reloc->r_offset);
unsigned long const r_type = ELF64_R_TYPE (reloc->r_info);
#ifndef RTLD_BOOTSTRAP
diff --git a/sysdeps/generic/htons.c b/sysdeps/generic/htons.c
index 8914f74f2e..1bbda3fd6a 100644
--- a/sysdeps/generic/htons.c
+++ b/sysdeps/generic/htons.c
@@ -22,7 +22,7 @@
#undef ntohs
u_int16_t
-__htons (x)
+htons (x)
u_int16_t x;
{
#if BYTE_ORDER == BIG_ENDIAN
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index d6fc038411..e517cff0ff 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -81,16 +81,20 @@ elf_machine_load_address (void)
destroys the passed register information. */
static ElfW(Addr) fixup (struct link_map *l, ElfW(Word) reloc_offset)
__attribute__ ((regparm (2), unused));
+static ElfW(Addr) profile_fixup (struct link_map *l, ElfW(Word) reloc_offset,
+ ElfW(Addr) retaddr)
+ __attribute__ ((regparm (3), unused));
#endif
/* Set up the loaded object described by L so its unrelocated PLT
entries will jump to the on-demand fixup code in dl-runtime.c. */
static inline int __attribute__ ((unused))
-elf_machine_runtime_setup (struct link_map *l, int lazy)
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
Elf32_Addr *got;
extern void _dl_runtime_resolve (Elf32_Word);
+ extern void _dl_runtime_profile (Elf32_Word);
if (l->l_info[DT_JMPREL] && lazy)
{
@@ -100,9 +104,23 @@ elf_machine_runtime_setup (struct link_map *l, int lazy)
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
got = (Elf32_Addr *) (l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr);
got[1] = (Elf32_Addr) l; /* Identify this shared object. */
- /* This function will get called to fix up the GOT entry indicated by
- the offset on the stack, and then jump to the resolved address. */
- got[2] = (Elf32_Addr) &_dl_runtime_resolve;
+
+ /* The got[2] entry contains the address of a function which gets
+ called to get the address of a so far unresolved function and
+ jump to it. The profiling extension of the dynamic linker allows
+ to intercept the calls to collect information. In this case we
+ don't store the address in the GOT so that all future calls also
+ end in this function. */
+ if (profile)
+ {
+ got[2] = (Elf32_Addr) &_dl_runtime_profile;
+ /* Say that we really want profiling and the timers are started. */
+ _dl_profile_map = l;
+ }
+ else
+ /* This function will get called to fix up the GOT entry indicated by
+ the offset on the stack, and then jump to the resolved address. */
+ got[2] = (Elf32_Addr) &_dl_runtime_resolve;
}
return lazy;
@@ -126,12 +144,31 @@ _dl_runtime_resolve:
xchgl %eax, (%esp) # Get %eax contents end store function address.
ret $8 # Jump to function address.
.size _dl_runtime_resolve, .-_dl_runtime_resolve
+
+ .globl _dl_runtime_profile
+ .type _dl_runtime_profile, @function
+_dl_runtime_profile:
+ pushl %eax # Preserve registers otherwise clobbered.
+ pushl %ecx
+ pushl %edx
+ movl 20(%esp), %ecx # Load return address
+ movl 16(%esp), %edx # Copy args pushed by PLT in register. Note
+ movl 12(%esp), %eax # that `fixup' takes its parameters in regs.
+ call profile_fixup # Call resolver.
+ popl %edx # Get register content back.
+ popl %ecx
+ xchgl %eax, (%esp) # Get %eax contents end store function address.
+ ret $8 # Jump to function address.
+ .size _dl_runtime_profile, .-_dl_runtime_profile
");
#else
# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\
.globl _dl_runtime_resolve
+ .globl _dl_runtime_profile
.type _dl_runtime_resolve, @function
+ .type _dl_runtime_profile, @function
_dl_runtime_resolve:
+_dl_runtime_profile:
pushl %eax # Preserve registers otherwise clobbered.
pushl %ecx
pushl %edx
@@ -147,6 +184,7 @@ _dl_runtime_resolve:
xchgl %eax, (%esp) # Get %eax contents end store function address.
ret $8 # Jump to function address.
.size _dl_runtime_resolve, .-_dl_runtime_resolve
+ .size _dl_runtime_profile, .-_dl_runtime_profile
");
#endif
/* The PLT uses Elf32_Rel relocs. */
@@ -261,10 +299,9 @@ extern char **_dl_argv;
static inline void
elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
- const Elf32_Sym *sym, const struct r_found_version *version)
+ const Elf32_Sym *sym, const struct r_found_version *version,
+ Elf32_Addr *const reloc_addr)
{
- Elf32_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
-
if (ELF32_R_TYPE (reloc->r_info) == R_386_RELATIVE)
{
#ifndef RTLD_BOOTSTRAP
diff --git a/sysdeps/i386/fpu/bits/mathinline.h b/sysdeps/i386/fpu/bits/mathinline.h
index 4228959d23..2fc5baf81e 100644
--- a/sysdeps/i386/fpu/bits/mathinline.h
+++ b/sysdeps/i386/fpu/bits/mathinline.h
@@ -1,7 +1,7 @@
/* Inline math functions for i387.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by John C. Bowman <bowman@ipp-garching.mpg.de>, 1995.
+ Contributed by John C. Bowman <bowman@math.ualberta.ca>, 1995.
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
@@ -28,45 +28,45 @@
These must not be inline functions since we have to be able to handle
all floating-point types. */
# define isgreater(x, y) \
- ({ int result; \
+ ({ int __result; \
__asm__ ("fucompp; fnstsw; andb $0x45, %%ah; setz %%al;" \
"andl $0x01, %0" \
- : "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
- result; })
+ : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
+ __result; })
# define isgreaterequal(x, y) \
- ({ int result; \
+ ({ int __result; \
__asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al;" \
"andl $0x01, %0" \
- : "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
- result; })
+ : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
+ __result; })
# define isless(x, y) \
- ({ int result; \
+ ({ int __result; \
__asm__ ("fucompp; fnstsw; xorb $0x01, %%ah; testb $0x45, %%ah;" \
"setz %%al; andl $0x01, %0" \
- : "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
- result; })
+ : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
+ __result; })
# define islessequal(x, y) \
- ({ int result; \
+ ({ int __result; \
__asm__ ("fucompp; fnstsw; xorb $0x01, %%ah; testb $0x05, %%ah;" \
"setz %%al; andl $0x01, %0" \
- : "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
- result; })
+ : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
+ __result; })
# define islessgreater(x, y) \
- ({ int result; \
+ ({ int __result; \
__asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al;" \
"andl $0x01, %0" \
- : "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
- result; })
+ : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
+ __result; })
# define isunordered(x, y) \
- ({ int result; \
+ ({ int __result; \
__asm__ ("fucompp; fnstsw; sahf; setp %%al; andl $0x01, %0" \
- : "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
- result; })
+ : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
+ __result; })
#endif
@@ -88,425 +88,328 @@
# define __MATH_INLINE extern __inline
#endif
-__MATH_INLINE double cos (double);
-__MATH_INLINE double sin (double);
+/* A macro to define float, double, and long double versions of various
+ math functions for the ix87 FPU. FUNC is the function name (which will
+ be suffixed with f and l for the float and long double version,
+ respectively). OP is the name of the FPU operation. */
+#if defined __USE_MISC || defined __USE_ISOC9X
+# define __inline_mathop(func, op) \
+ __inline_mathop_ (double, func, op) \
+ __inline_mathop_ (float, __CONCAT(func,f), op) \
+ __inline_mathop_ (long double, __CONCAT(func,l), op)
+#else
+# define __inline_mathop(func, op) \
+ __inline_mathop_ (double, func, op)
+#endif
-__MATH_INLINE double __expm1 (double __x);
-__MATH_INLINE double
-__expm1 (double __x)
-{
- register double __value, __exponent, __temp;
- __asm __volatile__
- ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t"
- "fmul %%st(1) # x * log2(e)\n\t"
- "fstl %%st(1)\n\t"
- "frndint # int(x * log2(e))\n\t"
- "fxch\n\t"
- "fsub %%st(1) # fract(x * log2(e))\n\t"
- "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t"
- "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t"
- : "=t" (__value), "=u" (__exponent) : "0" (__x));
- __asm __volatile__
- ("fscale # 2^int(x * log2(e))\n\t"
- : "=t" (__temp) : "0" (1.0), "u" (__exponent));
- __temp -= 1.0;
-
- return __temp + __value;
-}
-
-__MATH_INLINE double __sgn1 (double __x);
-__MATH_INLINE double
-__sgn1 (double __x)
-{
- return __x >= 0.0 ? 1.0 : -1.0;
-}
-
-__MATH_INLINE double sqrt (double __x);
-__MATH_INLINE double
-sqrt (double __x)
-{
- register double __value;
- __asm __volatile__
- ("fsqrt"
- : "=t" (__value) : "0" (__x));
-
- return __value;
-}
-
-__MATH_INLINE double fabs (double __x);
-__MATH_INLINE double
-fabs (double __x)
-{
- register double __value;
- __asm __volatile__
- ("fabs"
- : "=t" (__value) : "0" (__x));
-
- return __value;
-}
-
-/* The argument range of this inline version is limited. */
-__MATH_INLINE double sin (double __x);
-__MATH_INLINE double
-sin (double __x)
-{
- register double __value;
- __asm __volatile__
- ("fsin"
- : "=t" (__value) : "0" (__x));
-
- return __value;
-}
-
-/* The argument range of this inline version is limited. */
-__MATH_INLINE double cos (double __x);
-__MATH_INLINE double
-cos (double __x)
-{
- register double __value;
- __asm __volatile__
- ("fcos"
- : "=t" (__value): "0" (__x));
-
- return __value;
-}
-
-__MATH_INLINE double tan (double __x);
-__MATH_INLINE double
-tan (double __x)
-{
- register double __value;
- register double __value2 __attribute__ ((unused));
- __asm __volatile__
- ("fptan"
- : "=t" (__value2), "=u" (__value) : "0" (__x));
-
- return __value;
-}
-
-__MATH_INLINE double atan2 (double __y, double __x);
-__MATH_INLINE double
-atan2 (double __y, double __x)
-{
- register double __value;
- __asm __volatile__
- ("fpatan\n\t"
- "fldl %%st(0)"
- : "=t" (__value) : "0" (__x), "u" (__y));
-
- return __value;
-}
-
-__MATH_INLINE double asin (double __x);
-__MATH_INLINE double
-asin (double __x)
-{
- return atan2 (__x, sqrt (1.0 - __x * __x));
-}
-
-__MATH_INLINE double acos (double __x);
-__MATH_INLINE double
-acos (double __x)
-{
- return atan2 (sqrt (1.0 - __x * __x), __x);
-}
-
-__MATH_INLINE double atan (double __x);
-__MATH_INLINE double
-atan (double __x)
-{
- register double __value;
- __asm __volatile__
- ("fld1\n\t"
- "fpatan"
- : "=t" (__value) : "0" (__x));
-
- return __value;
-}
-
-__MATH_INLINE double exp (double __x);
-__MATH_INLINE double
-exp (double __x)
-{
- register double __value, __exponent;
- __asm __volatile__
- ("fldl2e # e^x = 2^(x * log2(e))\n\t"
- "fmul %%st(1) # x * log2(e)\n\t"
- "fstl %%st(1)\n\t"
- "frndint # int(x * log2(e))\n\t"
- "fxch\n\t"
- "fsub %%st(1) # fract(x * log2(e))\n\t"
- "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t"
- : "=t" (__value), "=u" (__exponent) : "0" (__x));
- __value += 1.0;
- __asm __volatile__
- ("fscale"
- : "=t" (__value) : "0" (__value), "u" (__exponent));
-
- return __value;
-}
-
-__MATH_INLINE double sinh (double __x);
-__MATH_INLINE double
-sinh (double __x)
-{
- register double __exm1 = __expm1 (fabs (__x));
-
- return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1 (__x);
-}
-
-__MATH_INLINE double cosh (double __x);
-__MATH_INLINE double
-cosh (double __x)
-{
- register double __ex = exp (__x);
-
- return 0.5 * (__ex + 1.0 / __ex);
-}
-
-__MATH_INLINE double tanh (double __x);
-__MATH_INLINE double
-tanh (double __x)
-{
- register double __exm1 = __expm1 (-fabs (__x + __x));
-
- return __exm1 / (__exm1 + 2.0) * __sgn1 (-__x);
-}
-
-__MATH_INLINE double log (double __x);
-__MATH_INLINE double
-log (double __x)
-{
- register double __value;
- __asm __volatile__
- ("fldln2\n\t"
- "fxch\n\t"
- "fyl2x"
- : "=t" (__value) : "0" (__x));
-
- return __value;
-}
-
-__MATH_INLINE double log10 (double __x);
-__MATH_INLINE double
-log10 (double __x)
-{
- register double __value;
- __asm __volatile__
- ("fldlg2\n\t"
- "fxch\n\t"
- "fyl2x"
- : "=t" (__value) : "0" (__x));
-
- return __value;
-}
-
-__MATH_INLINE double __log2 (double __x);
-__MATH_INLINE double
-__log2 (double __x)
-{
- register double __value;
- __asm __volatile__
- ("fyl2x"
- : "=t" (__value) : "0" (__x), "u" (1.0));
-
- return __value;
-}
-
-__MATH_INLINE double fmod (double __x, double __y);
-__MATH_INLINE double
-fmod (double __x, double __y)
-{
- register double __value;
- __asm __volatile__
- ("1: fprem\n\t"
- "fstsw %%ax\n\t"
- "sahf\n\t"
- "jp 1b"
- : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc");
-
- return __value;
-}
-
-__MATH_INLINE double ldexp (double __x, int __y);
-__MATH_INLINE double
-ldexp (double __x, int __y)
-{
- register double __value;
- __asm __volatile__
- ("fscale"
- : "=t" (__value) : "0" (__x), "u" ((double) __y));
-
- return __value;
-}
+#define __inline_mathop_(float_type, func, op) \
+ __inline_mathop_decl_ (float_type, func, op, "0" (__x))
-__MATH_INLINE double pow (double __x, double __y);
-__MATH_INLINE double
-pow (double __x, double __y)
-{
- register double __value, __exponent;
- long __p = (long) __y;
-
- if (__x == 0.0 && __y > 0.0)
- return 0.0;
- if (__y == (double) __p)
- {
- double __r = 1.0;
- if (__p == 0)
- return 1.0;
- if (__p < 0)
- {
- __p = -__p;
- __x = 1.0 / __x;
- }
- while (1)
- {
- if (__p & 1)
- __r *= __x;
- __p >>= 1;
- if (__p == 0)
- return __r;
- __x *= __x;
- }
- /* NOTREACHED */
- }
- __asm __volatile__
- ("fmul %%st(1) # y * log2(x)\n\t"
- "fstl %%st(1)\n\t"
- "frndint # int(y * log2(x))\n\t"
- "fxch\n\t"
- "fsub %%st(1) # fract(y * log2(x))\n\t"
- "f2xm1 # 2^(fract(y * log2(x))) - 1\n\t"
- : "=t" (__value), "=u" (__exponent) : "0" (__log2 (__x)), "1" (__y));
- __value += 1.0;
- __asm __volatile__
- ("fscale"
- : "=t" (__value) : "0" (__value), "u" (__exponent));
-
- return __value;
-}
-__MATH_INLINE double floor (double __x);
-__MATH_INLINE double
-floor (double __x)
-{
- register double __value;
- __volatile unsigned short int __cw, __cwtmp;
+#if defined __USE_MISC || defined __USE_ISOC9X
+# define __inline_mathop_decl(func, op, params...) \
+ __inline_mathop_decl_ (double, func, op, params) \
+ __inline_mathop_decl_ (float, __CONCAT(func,f), op, params) \
+ __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params)
+#else
+# define __inline_mathop_decl(func, op, params...) \
+ __inline_mathop_decl_ (double, func, op, params)
+#endif
- __asm __volatile ("fnstcw %0" : "=m" (__cw));
- __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */
- __asm __volatile ("fldcw %0" : : "m" (__cwtmp));
- __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));
- __asm __volatile ("fldcw %0" : : "m" (__cw));
+#define __inline_mathop_decl_(float_type, func, op, params...) \
+ __MATHINLINE float_type func (float_type); \
+ __MATHINLINE float_type func (float_type __x) \
+ { \
+ register float_type __result; \
+ __asm __volatile__ (op : "=t" (__results) : params); \
+ return __result; \
+ }
+
+
+#if defined __USE_MISC || defined __USE_ISOC9X
+# define __inline_mathcode(func, arg, code) \
+ __inline_mathcode_ (double, func, arg, code) \
+ __inline_mathcode_ (float, __CONCAT(func,f), arg, code) \
+ __inline_mathcode_ (long double, __CONCAT(func,l), arg, code)
+#else
+# define __inline_mathcode(func, arg, code) \
+ __inline_mathcode_ (double, func, arg, code)
+#endif
- return __value;
-}
+#define __inline_mathcode_(float_type, func, arg, code) \
+ __MATH_INLINE float_type func (float_type); \
+ __MATH_INLINE float_type func (float_type arg) \
+ { \
+ code; \
+ }
-__MATH_INLINE double ceil (double __x);
-__MATH_INLINE double
-ceil (double __x)
-{
- register double __value;
- __volatile unsigned short int __cw, __cwtmp;
- __asm __volatile ("fnstcw %0" : "=m" (__cw));
- __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */
- __asm __volatile ("fldcw %0" : : "m" (__cwtmp));
- __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));
- __asm __volatile ("fldcw %0" : : "m" (__cw));
+#if defined __USE_MISC || defined __USE_ISOC9X
+# define __inline_mathcode2(func, arg1, arg2, code) \
+ __inline_mathcode2_ (double, func, arg1, arg2, code) \
+ __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code) \
+ __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code)
+#else
+# define __inline_mathcode2(func, arg1, arg2, code) \
+ __inline_mathcode2_ (double, func, arg1, arg2, code)
+#endif
- return __value;
-}
+#define __inline_mathcode2_(float_type, func, arg1, arg2, code) \
+ __MATH_INLINE float_type func (float_type, float_type); \
+ __MATH_INLINE float_type func (float_type arg1, float_type arg2) \
+ { \
+ code; \
+ }
+
+
+/* Optimized inline implementation, sometimes woth reduced precision
+ and/or argument range. */
+#define __expm1_code \
+ register long double __value; \
+ register long double __exponent; \
+ register long double __temp; \
+ __asm __volatile__ \
+ ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \
+ "fmul %%st(1) # x * log2(e)\n\t" \
+ "fstl %%st(1)\n\t" \
+ "frndint # int(x * log2(e))\n\t" \
+ "fxch\n\t" \
+ "fsub %%st(1) # fract(x * log2(e))\n\t" \
+ "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
+ "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
+ : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
+ __asm __volatile__ \
+ ("fscale # 2^int(x * log2(e))\n\t" \
+ : "=t" (__temp) : "0" (1.0), "u" (__exponent)); \
+ __temp -= 1.0; \
+ return __temp + __value
+__inline_mathcode_ (long double, __expm1l, __x, __expm1_code)
+
+
+#define __exp_code \
+ register long double __value; \
+ register long double __exponent; \
+ __asm __volatile__ \
+ ("fldl2e # e^x = 2^(x * log2(e))\n\t" \
+ "fmul %%st(1) # x * log2(e)\n\t" \
+ "fstl %%st(1)\n\t" \
+ "frndint # int(x * log2(e))\n\t" \
+ "fxch\n\t" \
+ "fsub %%st(1) # fract(x * log2(e))\n\t" \
+ "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
+ : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
+ __value += 1.0; \
+ __asm __volatile__ \
+ ("fscale" \
+ : "=t" (__value) : "0" (__value), "u" (__exponent)); \
+ return __value
+__inline_mathcode (exp, __x, __exp_code)
+__inline_mathcode_ (long double, __expl, __x, __exp_code)
+
+
+__inline_mathcode (tan, __x, \
+ register long double __value; \
+ register long double __value2 __attribute__ ((unused)); \
+ __asm __volatile__ \
+ ("fptan" \
+ : "=t" (__value2), "=u" (__value) : "0" (__x)); \
+ return __value)
+
+
+#define __atan2_code \
+ register long double __value; \
+ __asm __volatile__ \
+ ("fpatan\n\t" \
+ : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)"); \
+ return __value
+__inline_mathcode2 (atan2, __y, __x, __atan2_code)
+__inline_mathcode2_ (long double, __atan2l, __y, __x, __atan2_code)
+
+
+__inline_mathcode2 (fmod, __x, __y, \
+ register long double __value; \
+ __asm __volatile__ \
+ ("1: fprem\n\t" \
+ "fnstsw %%ax\n\t" \
+ "sahf\n\t" \
+ "jp 1b" \
+ : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \
+ return __value)
+
+
+__inline_mathcode2 (pow, __x, __y, \
+ register long double __value; \
+ register long double __exponent; \
+ long int __p = (long int) __y; \
+ if (__x == 0.0 && __y > 0.0) \
+ return 0.0; \
+ if (__y == (double) __p) \
+ { \
+ long double __r = 1.0; \
+ if (__p == 0) \
+ return 1.0; \
+ if (__p < 0) \
+ { \
+ __p = -__p; \
+ __x = 1.0 / __x; \
+ } \
+ while (1) \
+ { \
+ if (__p & 1) \
+ __r *= __x; \
+ __p >>= 1; \
+ if (__p == 0) \
+ return __r; \
+ __x *= __x; \
+ } \
+ /* NOTREACHED */ \
+ } \
+ __asm __volatile__ \
+ ("fyl2x" : "=t" (__value) : "0" (__x), "u" (1.0) : "st1"); \
+ __asm __volatile__ \
+ ("fmul %%st(1) # y * log2(x)\n\t" \
+ "fst %%st(1)\n\t" \
+ "frndint # int(y * log2(x))\n\t" \
+ "fxch\n\t" \
+ "fsub %%st(1) # fract(y * log2(x))\n\t" \
+ "f2xm1 # 2^(fract(y * log2(x))) - 1\n\t" \
+ : "=t" (__value), "=u" (__exponent) : "0" (__y), "1" (__value)); \
+ __value += 1.0; \
+ __asm __volatile__ \
+ ("fscale" \
+ : "=t" (__value) : "0" (__value), "u" (__exponent)); \
+ return __value)
+
+
+__inline_mathop (sqrt, "fsqrt")
+__inline_mathop_ (long double, __sqrtl, "fsqrt")
+
+__inline_mathop (fabs, "fabs")
+
+/* The argument range of this inline version is reduced. */
+__inline_mathop (sin, "fsin")
+/* The argument range of this inline version is reduced. */
+__inline_mathop (cos, "fcos")
+
+__inline_mathop (atan, "fld1; fpatan")
+__inline_mathop (log, "fldln2; fxch; fyl2x")
+__inline_mathop (log10, "fldlg2; fxch; fyl2x")
+
+__inline_mathcode (asin, __x, return __atan2l (__x, __sqrtl (1.0 - __x * __x)))
+__inline_mathcode (acos, __x, return __atan2l (__sqrtl (1.0 - __x * __x), __x))
+
+__inline_mathcode (__sgn1, __x, return __x >= 0.0 ? 1.0 : -1.0)
+
+
+/* The argument range of the inline version of sinhl is slightly reduced. */
+__inline_mathcode (sinh, __x, \
+ register long double __exm1 = __expm1l (__builtin_fabsl (__x)); \
+ return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
+
+__inline_mathcode (cosh, __x, \
+ register long double __ex = __expl (__x); \
+ return 0.5 * (__ex + 1.0 / __ex))
+
+__inline_mathcode (tanh, __x, \
+ register long double __exm1 = __expm1l (-__builtin_fabsl (__x + __x)); \
+ return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
+
+
+__inline_mathcode (floor, __x, \
+ register long double __value; \
+ __volatile unsigned short int __cw; \
+ __volatile unsigned short int __cwtmp; \
+ __asm __volatile ("fnstcw %0" : "=m" (__cw)); \
+ __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */ \
+ __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); \
+ __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); \
+ __asm __volatile ("fldcw %0" : : "m" (__cw)); \
+ return __value)
+
+__inline_mathcode (ceil, __x, \
+ register long double __value; \
+ __volatile unsigned short int __cw; \
+ __volatile unsigned short int __cwtmp; \
+ __asm __volatile ("fnstcw %0" : "=m" (__cw)); \
+ __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */ \
+ __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); \
+ __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); \
+ __asm __volatile ("fldcw %0" : : "m" (__cw)); \
+ return __value)
/* Optimized versions for some non-standardized functions. */
#if defined __USE_ISOC9X || defined __USE_MISC
-__MATH_INLINE double hypot (double __x, double __y);
-__MATH_INLINE double
-hypot (double __x, double __y)
-{
- return sqrt (__x * __x + __y * __y);
-}
+__inline_mathop_decl (log2, "fyl2x", "u" (1.0), "0" (__x) : "st(1)")
+
+__inline_mathcode (expm1, __x, __expm1_code)
/* We cannot rely on M_SQRT being defined. So we do it for ourself
here. */
# define __M_SQRT2 _Mldbl(1.41421356237309504880) /* sqrt(2) */
-__MATH_INLINE double log1p (double __x);
-__MATH_INLINE double
-log1p (double __x)
-{
- register double __value;
-
- if (fabs (__x) >= 1.0 - 0.5 * __M_SQRT2)
- __value = log (1.0 + __x);
- else
- __asm __volatile__
- ("fldln2\n\t"
- "fxch\n\t"
- "fyl2xp1"
- : "=t" (__value) : "0" (__x));
-
- return __value;
-}
-
-__MATH_INLINE double asinh (double __x);
-__MATH_INLINE double
-asinh (double __x)
-{
- register double __y = fabs (__x);
-
- return log1p ((__y * __y / (sqrt (__y * __y + 1.0) + 1.0) + __y)
- * __sgn1 (__x));
-}
-
-__MATH_INLINE double acosh (double __x);
-__MATH_INLINE double
-acosh (double __x)
-{
- return log (__x + sqrt (__x - 1.0) * sqrt (__x + 1.0));
-}
-
-__MATH_INLINE double atanh (double __x);
-__MATH_INLINE double
-atanh (double __x)
-{
- register double __y = fabs (__x);
-
- return -0.5 * __log1p (-(__y + __y) / (1.0 + __y)) * __sgn1 (__x);
-}
-
-__MATH_INLINE double logb (double __x);
-__MATH_INLINE double
-logb (double __x)
-{
- register double __value, __junk;
- __asm __volatile__
- ("fxtract\n\t"
- : "=t" (__junk), "=u" (__value) : "0" (__x));
-
- return __value;
-}
+__inline_mathcode (log1p, __x, \
+ register long double __value; \
+ if (__builtin_fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2) \
+ __value = logl (1.0 + __x); \
+ else \
+ __asm __volatile__ \
+ ("fldln2\n\t" \
+ "fxch\n\t" \
+ "fyl2xp1" \
+ : "=t" (__value) : "0" (__x)); \
+ return __value)
+
+
+/* The argument range of the inline version of asinhl is slightly reduced. */
+__inline_mathcode (asinh, __x, \
+ register long double __y = __builtin_fabsl (__x); \
+ return (log1pl (__y * __y / (__sqrtl (__y * __y + 1.0) + 1.0) + __y) \
+ * __sgn1l (__x))
+
+__inline_mathcode (acosh, __x, \
+ return logl (__x + __sqrtl (__x - 1.0) * __sqrtl (__x + 1.0)))
+
+__inline_mathcode (atanh, __x, \
+ register long double __y = __builtin_fabsl (__x); \
+ return (-0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * \
+ __sgn1l (__x)))
+
+
+/* The argument range of the inline version of hypotl is slightly reduced. */
+__inline_mathcode2 (hypot, __x, __y, return __sqrtl (__x * __x + __y * __y))
+
+__inline_mathcode(logb, __x, \
+ register long double __value; \
+ register long double __junk; \
+ __asm __volatile__ \
+ ("fxtract\n\t" \
+ : "=t" (__junk), "=u" (__value) : "0" (__x)); \
+ return __value)
+
+
+__inline_mathcode2 (ldexp, __x, __y, \
+ register long double __value; \
+ __asm __volatile__ \
+ ("fscale" \
+ : "=t" (__value) : "0" (__x), "u" ((long double) __y)); \
+ return __value)
#endif
#ifdef __USE_MISC
-__MATH_INLINE double drem (double __x, double __y);
-__MATH_INLINE double
-drem (double __x, double __y)
-{
- register double __value;
- __asm __volatile__
- ("1: fprem1\n\t"
- "fstsw %%ax\n\t"
- "sahf\n\t"
- "jp 1b"
- : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc");
-
- return __value;
-}
+__inline_mathcode2 (drem, __x, __y, \
+ register double __value; \
+ __asm __volatile__ \
+ ("1: fprem1\n\t" \
+ "fstsw %%ax\n\t" \
+ "sahf\n\t" \
+ "jp 1b" \
+ : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \
+ return __value)
+
/* This function is used in the `isfinite' macro. */
__MATH_INLINE int __finite (double __x);
@@ -522,82 +425,89 @@ __finite (double __x)
return __result;
}
-__MATH_INLINE double coshm1 (double __x);
-__MATH_INLINE double
-coshm1 (double __x)
-{
- register double __exm1 = __expm1 (fabs (__x));
-
- return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1;
-}
-
-__MATH_INLINE double acosh1p (double __x);
-__MATH_INLINE double
-acosh1p (double __x)
-{
- return __log1p (__x + sqrt (__x) * sqrt (__x + 2.0));
-}
-
-__MATH_INLINE void sincos (double __x, double *__sinx, double *__cosx);
+/* Miscellaneous functions */
+
+__inline_mathcode (__sgn, __x, \
+ return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0))
+
+__inline_mathcode (__coshm1, __x, \
+ register long double __exm1 = __expm1l (__builtin_fabsl (__x)); \
+ return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1)
+
+__inline_mathcode (__acosh1p, __x, \
+ return log1pl (__x + __sqrtl (__x) * __sqrtl (__x + 2.0)))
+
+__inline_mathcode (__pow2, __x, \
+ register long double __value; \
+ register long double __exponent; \
+ long int __p = (long int) __x; \
+ if (__x == (long double) __p) \
+ return ldexpl (1.0, __p); \
+ __asm __volatile__ \
+ ("fldl %%st(0)\n\t" \
+ "frndint # int(x)\n\t" \
+ "fxch\n\t" \
+ "fsub %%st(1) # fract(x)\n\t" \
+ "f2xm1 # 2^(fract(x)) - 1\n\t" \
+ : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
+ __value += 1.0; \
+ __asm __volatile__ \
+ ("fscale" \
+ : "=t" (__value) : "0" (__value), "u" (__exponent)); \
+ return __value)
+
+#define __sincos_code \
+ register long double __cosr; \
+ register long double __sinr; \
+ __asm __volatile__ \
+ ("fsincos\n\t" \
+ "fnstsw %%ax\n\t" \
+ "testl $0x400, %%eax\n\t" \
+ "jz 1f\n\t" \
+ "fldpi\n\t" \
+ "fadd %%st(0)\n\t" \
+ "fxch %%st(1)\n\t" \
+ "2: fprem1\n\t" \
+ "fnstsw %%ax\n\t" \
+ "testl $0x400, %%eax\n\t" \
+ "jnz 2b\n\t" \
+ "fstp %%st(1)\n\t" \
+ "fsincos\n\t" \
+ "1:" \
+ : "=t" (__cosr), "=u" (__sinr) : "0" (__x)); \
+ *__sinx = __sinr; \
+ *__cosx = __cosr
+
+__MATH_INLINE void __sincos (double __x, double *__sinx, double *__cosx);
__MATH_INLINE void
-sincos (double __x, double *__sinx, double *__cosx)
+__sincos (double __x, double *__sinx, double *__cosx)
{
- register double __cosr, __sinr;
- __asm __volatile__
- ("fsincos\n\t"
- "fnstsw %%ax\n\t"
- "testl $0x400, %%eax\n\t"
- "jz 1f\n\t"
- "fldpi\n\t"
- "fadd %%st(0)\n\t"
- "fxch %%st(1)\n\t"
- "2: fprem1\n\t"
- "fnstsw %%ax\n\t"
- "testl $0x400, %%eax\n\t"
- "jnz 2b\n\t"
- "fstp %%st(1)\n\t"
- "fsincos\n\t"
- "1:"
- : "=t" (__cosr), "=u" (__sinr) : "0" (__x));
-
- *__sinx = __sinr;
- *__cosx = __cosr;
+ __sincos_code;
}
-__MATH_INLINE double sgn (double __x);
-__MATH_INLINE double
-sgn (double __x)
+__MATH_INLINE void __sincosf (float __x, float *__sinx, float *__cosx);
+__MATH_INLINE void
+__sincosf (float __x, float *__sinx, float *__cosx)
{
- return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0);
+ __sincos_code;
}
-__MATH_INLINE double pow2 (double __x);
-__MATH_INLINE double
-pow2 (double __x)
+__MATH_INLINE void __sincosl (long double __x, long double *__sinx,
+ long double *__cosx);
+__MATH_INLINE void
+__sincosl (long double __x, long double *__sinx, long double *__cosx)
{
- register double __value, __exponent;
- long __p = (long) __x;
-
- if (__x == (double) __p)
- return ldexp (1.0, __p);
-
- __asm __volatile__
- ("fldl %%st(0)\n\t"
- "frndint # int(x)\n\t"
- "fxch\n\t"
- "fsub %%st(1) # fract(x)\n\t"
- "f2xm1 # 2^(fract(x)) - 1\n\t"
- : "=t" (__value), "=u" (__exponent) : "0" (__x));
- __value += 1.0;
- __asm __volatile__
- ("fscale"
- : "=t" (__value) : "0" (__value), "u" (__exponent));
-
- return __value;
+ __sincos_code;
}
#endif /* __USE_MISC */
+/* Undefine some of the large macros which are not used anymore. */
+#undef __expm1_code
+#undef __exp_code
+#undef __atan2_code
+#undef __sincos_code
+
#endif /* __NO_MATH_INLINES */
#endif /* __GNUC__ */
diff --git a/sysdeps/m68k/bits/byteswap.h b/sysdeps/m68k/bits/byteswap.h
new file mode 100644
index 0000000000..54ec0d1920
--- /dev/null
+++ b/sysdeps/m68k/bits/byteswap.h
@@ -0,0 +1,63 @@
+/* Macros to swap the order of bytes in integer values. m68k version.
+ 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. */
+
+#ifndef _BITS_BYTESWAP_H
+#define _BITS_BYTESWAP_H 1
+
+/* Swap bytes in 16 bit value. We don't provide an assembler version
+ because GCC is smart enough to generate optimal assembler output, and
+ this allows for better cse. */
+#define __bswap_16(x) \
+ ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
+
+/* Swap bytes in 32 bit value. */
+#define __bswap_constant_32(x) \
+ ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
+
+#if defined __GNUC__ && __GNUC__ >= 2
+#define __bswap_32(x) \
+ __extension__ \
+ ({ unsigned int __v; \
+ if (__builtin_constant_p (x)) \
+ __v = __bswap_constant_32 (x); \
+ else \
+ __asm__ __volatile__ ("ror%.w %#8, %0;" \
+ "swap %0;" \
+ "ror%.w %#8, %0" \
+ : "=d" (__v) \
+ : "0" (x)); \
+ __v; })
+#else
+#define __bswap_32(x) __bswap_constant_32 (x)
+#endif
+
+#if defined __GNUC__ && __GNUC__ >= 2
+/* Swap bytes in 64 bit value. */
+#define __bswap_64(x) \
+ __extension__ \
+ ({ union { unsigned long long int __ll; \
+ unsigned long int __l[2]; } __v, __r; \
+ __v.__ll = (x); \
+ __r.__l[0] = __bswap_32 (__v.__l[1]); \
+ __r.__l[1] = __bswap_32 (__v.__l[0]); \
+ __r.__ll; })
+#endif
+
+#endif /* bits/byteswap.h */
diff --git a/sysdeps/m68k/dl-machine.h b/sysdeps/m68k/dl-machine.h
index c0a17c73c2..7c62aa2aad 100644
--- a/sysdeps/m68k/dl-machine.h
+++ b/sysdeps/m68k/dl-machine.h
@@ -76,7 +76,7 @@ elf_machine_load_address (void)
entries will jump to the on-demand fixup code in dl-runtime.c. */
static inline int
-elf_machine_runtime_setup (struct link_map *l, int lazy)
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
Elf32_Addr *got;
extern void _dl_runtime_resolve (Elf32_Word);
@@ -211,10 +211,9 @@ _dl_start_user:
static inline void
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
- const Elf32_Sym *sym, const struct r_found_version *version)
+ const Elf32_Sym *sym, const struct r_found_version *version,
+ Elf32_Addr *const reloc_addr)
{
- Elf32_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
-
if (ELF32_R_TYPE (reloc->r_info) == R_68K_RELATIVE)
*reloc_addr = map->l_addr + reloc->r_addend;
else
diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h
index fce7cffb4a..6973f7612a 100644
--- a/sysdeps/mips/dl-machine.h
+++ b/sysdeps/mips/dl-machine.h
@@ -219,7 +219,7 @@ elf_machine_got_rel (struct link_map *map, int lazy)
will jump to the on-demand fixup code in dl-runtime.c. */
static inline int
-elf_machine_runtime_setup (struct link_map *l, int lazy)
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
ElfW(Addr) *got;
extern void _dl_runtime_resolve (ElfW(Word));
@@ -533,9 +533,9 @@ _RTLD_EPILOGUE(ENTRY_POINT)\
static inline void
elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
- const ElfW(Sym) *sym, const struct r_found_version *version)
+ const ElfW(Sym) *sym, const struct r_found_version *version,
+ ElfW(Addr) *const reloc_addr)
{
- ElfW(Addr) *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
ElfW(Addr) loadbase;
ElfW(Addr) undo __attribute__ ((unused));
diff --git a/sysdeps/mips/mips64/dl-machine.h b/sysdeps/mips/mips64/dl-machine.h
index a20835af35..e501a2520e 100644
--- a/sysdeps/mips/mips64/dl-machine.h
+++ b/sysdeps/mips/mips64/dl-machine.h
@@ -219,7 +219,7 @@ elf_machine_got_rel (struct link_map *map, int lazy)
will jump to the on-demand fixup code in dl-runtime.c. */
static inline int
-elf_machine_runtime_setup (struct link_map *l, int lazy)
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
ElfW(Addr) *got;
extern void _dl_runtime_resolve (ElfW(Word));
@@ -529,9 +529,9 @@ _RTLD_EPILOGUE(ENTRY_POINT) \
static inline void
elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
- const ElfW(Sym) *sym, const struct r_found_version *version)
+ const ElfW(Sym) *sym, const struct r_found_version *version,
+ ElfW(Addr) *const reloc_addr)
{
- ElfW(Addr) *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
ElfW(Addr) loadbase;
ElfW(Addr) undo __attribute__ ((unused));
diff --git a/sysdeps/powerpc/dl-machine.h b/sysdeps/powerpc/dl-machine.h
index 12bcf43e4d..c9d1d7332a 100644
--- a/sysdeps/powerpc/dl-machine.h
+++ b/sysdeps/powerpc/dl-machine.h
@@ -391,7 +391,7 @@ static ElfW(Addr) _dl_preferred_address = 1
ELF_MACHINE_RUNTIME_TRAMPOLINE, which resets the PLT entry to
be one of the above two types. These entries are set up here. */
static inline int
-elf_machine_runtime_setup (struct link_map *map, int lazy)
+elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
{
if (map->l_info[DT_JMPREL])
{
@@ -510,10 +510,10 @@ 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)
+ const Elf32_Sym *sym, const struct r_found_version *version,
+ Elf32_addr *const reloc_addr)
{
const Elf32_Sym *const refsym = sym;
- Elf32_Addr *const reloc_addr = (Elf32_Addr *)(map->l_addr + reloc->r_offset);
Elf32_Word loadbase, finaladdr;
const int rinfo = ELF32_R_TYPE (reloc->r_info);
diff --git a/sysdeps/sparc/dl-machine.h b/sysdeps/sparc/dl-machine.h
index 1d193ae91c..b50549c0ec 100644
--- a/sysdeps/sparc/dl-machine.h
+++ b/sysdeps/sparc/dl-machine.h
@@ -224,7 +224,7 @@ elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc)
entries will jump to the on-demand fixup code in dl-runtime.c. */
static inline int
-elf_machine_runtime_setup (struct link_map *l, int lazy)
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
Elf32_Addr *plt;
extern void _dl_runtime_resolve (Elf32_Word);
diff --git a/sysdeps/sparc64/dl-machine.h b/sysdeps/sparc64/dl-machine.h
index ad216b79dc..df09c8fc85 100644
--- a/sysdeps/sparc64/dl-machine.h
+++ b/sysdeps/sparc64/dl-machine.h
@@ -68,9 +68,9 @@ elf_machine_load_address (void)
static inline void
elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
- const Elf64_Sym *sym, const struct r_found_version *version)
+ const Elf64_Sym *sym, const struct r_found_version *version,
+ Elf64_Addr *const reloc_addr)
{
- Elf64_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
Elf64_Addr loadbase;
#ifndef RTLD_BOOTSTRAP
@@ -200,7 +200,7 @@ elf_machine_lazy_rel (struct link_map *map, const Elf64_Rela *reloc)
entries will jump to the on-demand fixup code in dl-runtime.c. */
static inline int
-elf_machine_runtime_setup (struct link_map *l, int lazy)
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
Elf64_Addr *got;
extern void _dl_runtime_resolve (Elf64_Word);
diff --git a/sysdeps/unix/sysv/linux/bits/socket.h b/sysdeps/unix/sysv/linux/bits/socket.h
index e3f53a97be..a17c37fd8e 100644
--- a/sysdeps/unix/sysv/linux/bits/socket.h
+++ b/sysdeps/unix/sysv/linux/bits/socket.h
@@ -28,6 +28,7 @@
#define __need_NULL
#include <stddef.h>
+#include <sys/types.h>
__BEGIN_DECLS
@@ -130,25 +131,26 @@ struct msghdr
{
__ptr_t msg_name; /* Address to send to/receive from. */
int msg_namelen; /* Length of address data. */
- /* XXX Should be type `size_t' according to POSIX.1g. */
+ /* XXX Should be type `socklen_t' according to POSIX.1g. */
struct iovec *msg_iov; /* Vector of data to send/receive into. */
size_t msg_iovlen; /* Number of elements in the vector. */
__ptr_t msg_control; /* Ancillary data (eg BSD filedesc passing). */
- size_t msg_controllen; /* Ancillary data buffer length. */
+ socklen_t msg_controllen; /* Ancillary data buffer length. */
int msg_flags; /* Flags on received message. */
};
/* Structure used for storage of ancillary data object information. */
struct cmsghdr
{
- size_t cmsg_len; /* Length of data in cmsg_data plus length
+ socklen_t cmsg_len; /* Length of data in cmsg_data plus length
of cmsghdr structure. */
int cmsg_level; /* Originating protocol. */
int cmsg_type; /* Protocol specific type. */
#if !defined __STRICT_ANSI__ && defined __GNUC__ && __GNUC__ >= 2
unsigned char __cmsg_data[0]; /* Ancillary data. */
+ /* XXX Perhaps this should be removed. */
#endif
};