about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1998-11-23 09:36:06 +0000
committerUlrich Drepper <drepper@redhat.com>1998-11-23 09:36:06 +0000
commit7d6a833849d8e084bbdc534698e214bca056453f (patch)
tree5e3f4055efe1797b093a2c927730ec7a0908567a
parent9dc09d3060c01726779b4a19a934e6bb0cde5f67 (diff)
downloadglibc-cvs/libc-as-981124.tar.gz
glibc-cvs/libc-as-981124.tar.xz
glibc-cvs/libc-as-981124.zip
1998-11-23  Ulrich Drepper  <drepper@cygnus.com>

	* Makeconfig: Don't read sysd-sorted unless sysd-dirs is read.
	Patch by Zack Weinberg.

	* math/bits/mathcalls.h: Adjust comments.  Remove gamma_r prototype.

	* sysdeps/i386/fpu/bits/mathinline.h: Make log2 only available if
	__USE_ISOC9X is defined.  Provide rint optimization.

1998-11-21  H.J. Lu  <hjl@gnu.org>

	* libio/Versions (_IO_popen, _IO_proc_open, _IO_proc_close,
	popen, pclose): Add to GLIBC_2.1.

	* libio/Makefile (routines): Add oldiopopen and oldpclose.
	(shared-only-routines): Likewise.

	* libio/pclose.c (pclose): Make it default for GLIBC_2.1.
	* libio/iopopen.c (_IO_proc_open, _IO_popen, popen,
	_IO_proc_close): Likewise.

	* libio/iolibio.h (_IO_new_popen, _IO_old_popen, __new_pclose,
	__old_pclose): New prototypes.

	* libio/libioP.h (_IO_new_file_jumps): Removed.
	(_IO_old_proc_jumps): Added.
	(_IO_new_proc_open, _IO_old_proc_open): New prototypes.

	* libio/oldiopopen.c: New file.

	* libio/oldpclose.c: New file.

1998-11-22  Thorsten Kukuk  <kukuk@vt.uni-paderborn.de>

	* nss/Makefile: Build and install getent.
	* nss/getent.c: New, get entries from administrative database.
-rw-r--r--ChangeLog38
-rw-r--r--libio/Makefile5
-rw-r--r--libio/Versions6
-rw-r--r--libio/iolibio.h4
-rw-r--r--libio/iopopen.c49
-rw-r--r--libio/libioP.h6
-rw-r--r--libio/oldiopopen.c282
-rw-r--r--libio/oldpclose.c44
-rw-r--r--libio/pclose.c14
-rw-r--r--math/bits/mathcalls.h12
-rw-r--r--nss/Makefile3
-rw-r--r--nss/getent.c511
-rw-r--r--sysdeps/i386/fpu/bits/mathinline.h11
13 files changed, 949 insertions, 36 deletions
diff --git a/ChangeLog b/ChangeLog
index c86980f695..026c287897 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,41 @@
+1998-11-23  Ulrich Drepper  <drepper@cygnus.com>
+
+	* Makeconfig: Don't read sysd-sorted unless sysd-dirs is read.
+	Patch by Zack Weinberg.
+
+	* math/bits/mathcalls.h: Adjust comments.  Remove gamma_r prototype.
+
+	* sysdeps/i386/fpu/bits/mathinline.h: Make log2 only available if
+	__USE_ISOC9X is defined.  Provide rint optimization.
+
+1998-11-21  H.J. Lu  <hjl@gnu.org>
+
+	* libio/Versions (_IO_popen, _IO_proc_open, _IO_proc_close,
+	popen, pclose): Add to GLIBC_2.1.
+
+	* libio/Makefile (routines): Add oldiopopen and oldpclose.
+	(shared-only-routines): Likewise.
+
+	* libio/pclose.c (pclose): Make it default for GLIBC_2.1.
+	* libio/iopopen.c (_IO_proc_open, _IO_popen, popen,
+	_IO_proc_close): Likewise.
+
+	* libio/iolibio.h (_IO_new_popen, _IO_old_popen, __new_pclose,
+	__old_pclose): New prototypes.
+
+	* libio/libioP.h (_IO_new_file_jumps): Removed.
+	(_IO_old_proc_jumps): Added.
+	(_IO_new_proc_open, _IO_old_proc_open): New prototypes.
+
+	* libio/oldiopopen.c: New file.
+
+	* libio/oldpclose.c: New file.
+
+1998-11-22  Thorsten Kukuk  <kukuk@vt.uni-paderborn.de>
+
+	* nss/Makefile: Build and install getent.
+	* nss/getent.c: New, get entries from administrative database.
+
 1998-11-22  Roland McGrath  <roland@baalperazim.frob.com>
 
 	* sysdeps/mach/hurd/i386/init-first.c (init): Provide temporary storage
diff --git a/libio/Makefile b/libio/Makefile
index 3dd3705b1a..3a7f3b473c 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -43,7 +43,8 @@ all: # Make this the default target; it will be defined in Rules.
 include ../Makeconfig
 
 ifeq ($(versioning),yes)
-routines += oldiofopen oldiofdopen oldiofclose oldtmpfile
+routines += oldiofopen oldiofdopen oldiofclose oldiopopen oldpclose \
+	    oldtmpfile
 endif
 
 CPPFLAGS-.o += -DIO_DEBUG
@@ -63,7 +64,7 @@ aux	+= oldfileops oldstdfiles
 endif
 
 shared-only-routines = oldiofopen oldiofdopen oldiofclose oldfileops	\
-		       oldstdfiles oldtmpfile
+		       oldstdfiles oldiopopen oldpclose oldtmpfile
 
 distribute := iolibio.h libioP.h strfile.h Banner
 
diff --git a/libio/Versions b/libio/Versions
index c9d74d3773..5073a20a0c 100644
--- a/libio/Versions
+++ b/libio/Versions
@@ -81,13 +81,13 @@ libc {
     _IO_2_1_stdin_; _IO_2_1_stdout_; _IO_2_1_stderr_;
 
     # functions used in other libraries
-    _IO_fclose; _IO_fopen; _IO_fdopen; __asprintf;
+    _IO_fclose; _IO_fopen; _IO_fdopen; _IO_popen; __asprintf;
 
     # functions used in libstdc++
     _IO_do_write; _IO_file_attach; _IO_file_close_it; _IO_file_finish;
     _IO_file_fopen; _IO_file_init; _IO_file_overflow; _IO_file_seekoff;
     _IO_file_setbuf; _IO_file_sync; _IO_file_underflow;
-    _IO_file_write; _IO_file_xsputn;
+    _IO_file_write; _IO_file_xsputn; _IO_proc_open; _IO_proc_close;
 
     # Changed getline function in libio.
     _IO_getline_info;
@@ -95,6 +95,6 @@ libc {
     # f*
     fgetpos64; fopen64; freopen64; fseeko; fseeko64; fsetpos64; ftello;
     ftello64; fopen; fclose; fdopen; fread_unlocked; fwrite_unlocked;
-    fgets_unlocked; fputs_unlocked;
+    fgets_unlocked; fputs_unlocked; popen; pclose;
   }
 }
diff --git a/libio/iolibio.h b/libio/iolibio.h
index 0ec485eaec..7b25b40212 100644
--- a/libio/iolibio.h
+++ b/libio/iolibio.h
@@ -62,6 +62,10 @@ extern int _IO_obstack_printf __P ((struct obstack *, const char *, ...));
   (_IO_file_close_it(FP), _IO_file_fopen(FP, FILENAME, MODE, 1))
 #define _IO_fileno(FP) ((FP)->_fileno)
 extern _IO_FILE* _IO_popen __P((const char*, const char*));
+extern _IO_FILE* _IO_new_popen __P((const char*, const char*));
+extern _IO_FILE* _IO_old_popen __P((const char*, const char*));
+extern int __new_pclose __P((_IO_FILE *));
+extern int __old_pclose __P((_IO_FILE *));
 #define _IO_pclose _IO_fclose
 #define _IO_setbuf(_FP, _BUF) _IO_setbuffer(_FP, _BUF, _IO_BUFSIZ)
 #define _IO_setlinebuf(_FP) _IO_setvbuf(_FP, NULL, 1, 0)
diff --git a/libio/iopopen.c b/libio/iopopen.c
index 62a6de20f5..31f9e02cd8 100644
--- a/libio/iopopen.c
+++ b/libio/iopopen.c
@@ -104,7 +104,7 @@ typedef struct _IO_proc_file _IO_proc_file;
 static struct _IO_proc_file *proc_file_chain = NULL;
 
 _IO_FILE *
-_IO_proc_open (fp, command, mode)
+_IO_new_proc_open (fp, command, mode)
      _IO_FILE *fp;
      const char *command;
      const char *mode;
@@ -177,7 +177,7 @@ _IO_proc_open (fp, command, mode)
 }
 
 _IO_FILE *
-_IO_popen (command, mode)
+_IO_new_popen (command, mode)
      const char *command;
      const char *mode;
 {
@@ -199,23 +199,19 @@ _IO_popen (command, mode)
   fp = &new_f->fpx.file.file;
   _IO_init (fp, 0);
   _IO_JUMPS (fp) = &_IO_proc_jumps;
-  _IO_file_init (fp);
+  _IO_new_file_init (fp);
 #if  !_IO_UNIFIED_JUMPTABLES
   new_f->fpx.file.vtable = NULL;
 #endif
-  if (_IO_proc_open (fp, command, mode) != NULL)
+  if (_IO_new_proc_open (fp, command, mode) != NULL)
     return fp;
   _IO_un_link (fp);
   free (new_f);
   return NULL;
 }
 
-#ifdef strong_alias
-strong_alias (_IO_popen, popen);
-#endif
-
 int
-_IO_proc_close (fp)
+_IO_new_proc_close (fp)
      _IO_FILE *fp;
 {
   /* This is not name-space clean. FIXME! */
@@ -257,23 +253,40 @@ _IO_proc_close (fp)
 
 struct _IO_jump_t _IO_proc_jumps = {
   JUMP_INIT_DUMMY,
-  JUMP_INIT(finish, _IO_file_finish),
-  JUMP_INIT(overflow, _IO_file_overflow),
-  JUMP_INIT(underflow, _IO_file_underflow),
+  JUMP_INIT(finish, _IO_new_file_finish),
+  JUMP_INIT(overflow, _IO_new_file_overflow),
+  JUMP_INIT(underflow, _IO_new_file_underflow),
   JUMP_INIT(uflow, _IO_default_uflow),
   JUMP_INIT(pbackfail, _IO_default_pbackfail),
-  JUMP_INIT(xsputn, _IO_file_xsputn),
+  JUMP_INIT(xsputn, _IO_new_file_xsputn),
   JUMP_INIT(xsgetn, _IO_default_xsgetn),
-  JUMP_INIT(seekoff, _IO_file_seekoff),
+  JUMP_INIT(seekoff, _IO_new_file_seekoff),
   JUMP_INIT(seekpos, _IO_default_seekpos),
-  JUMP_INIT(setbuf, _IO_file_setbuf),
-  JUMP_INIT(sync, _IO_file_sync),
+  JUMP_INIT(setbuf, _IO_new_file_setbuf),
+  JUMP_INIT(sync, _IO_new_file_sync),
   JUMP_INIT(doallocate, _IO_file_doallocate),
   JUMP_INIT(read, _IO_file_read),
-  JUMP_INIT(write, _IO_file_write),
+  JUMP_INIT(write, _IO_new_file_write),
   JUMP_INIT(seek, _IO_file_seek),
-  JUMP_INIT(close, _IO_proc_close),
+  JUMP_INIT(close, _IO_new_proc_close),
   JUMP_INIT(stat, _IO_file_stat),
   JUMP_INIT(showmanyc, _IO_default_showmanyc),
   JUMP_INIT(imbue, _IO_default_imbue)
 };
+
+#if defined PIC && DO_VERSIONING
+strong_alias (_IO_new_popen, __new_popen)
+default_symbol_version (_IO_new_popen, _IO_popen, GLIBC_2.1);
+default_symbol_version (__new_popen, popen, GLIBC_2.1);
+default_symbol_version (_IO_new_proc_open, _IO_proc_open, GLIBC_2.1);
+default_symbol_version (_IO_new_proc_close, _IO_proc_close, GLIBC_2.1);
+#else
+# ifdef strong_alias
+strong_alias (_IO_new_popen, popen)
+# endif
+# ifdef weak_alias
+weak_alias (_IO_new_popen, _IO_popen)
+weak_alias (_IO_new_proc_open, _IO_proc_open)
+weak_alias (_IO_new_proc_close, _IO_proc_close)
+# endif
+#endif
diff --git a/libio/libioP.h b/libio/libioP.h
index 43fdb4047c..a9577cec74 100644
--- a/libio/libioP.h
+++ b/libio/libioP.h
@@ -334,10 +334,10 @@ extern int _IO_default_showmanyc __P ((_IO_FILE *));
 extern void _IO_default_imbue __P ((_IO_FILE *, void *));
 
 extern struct _IO_jump_t _IO_file_jumps;
-extern struct _IO_jump_t _IO_new_file_jumps;
 extern struct _IO_jump_t _IO_old_file_jumps;
 extern struct _IO_jump_t _IO_streambuf_jumps;
 extern struct _IO_jump_t _IO_proc_jumps;
+extern struct _IO_jump_t _IO_old_proc_jumps;
 extern struct _IO_jump_t _IO_str_jumps;
 extern int _IO_do_write __P ((_IO_FILE *, const char *, _IO_size_t));
 extern int _IO_new_do_write __P ((_IO_FILE *, const char *, _IO_size_t));
@@ -424,7 +424,11 @@ extern void _IO_old_file_finish __P ((_IO_FILE *, int));
 
 /* Jumptable functions for proc_files. */
 extern _IO_FILE* _IO_proc_open __P ((_IO_FILE *, const char *, const char *));
+extern _IO_FILE* _IO_new_proc_open __P ((_IO_FILE *, const char *, const char *));
+extern _IO_FILE* _IO_old_proc_open __P ((_IO_FILE *, const char *, const char *));
 extern int _IO_proc_close __P ((_IO_FILE *));
+extern int _IO_new_proc_close __P ((_IO_FILE *));
+extern int _IO_old_proc_close __P ((_IO_FILE *));
 
 /* Jumptable functions for strfiles. */
 extern int _IO_str_underflow __P ((_IO_FILE *));
diff --git a/libio/oldiopopen.c b/libio/oldiopopen.c
new file mode 100644
index 0000000000..c2e7f25707
--- /dev/null
+++ b/libio/oldiopopen.c
@@ -0,0 +1,282 @@
+/* Copyright (C) 1998 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+   Written by Per Bothner <bothner@cygnus.com>.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This 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
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#define _IO_USE_OLD_IO_FILE
+#ifndef _POSIX_SOURCE
+# define _POSIX_SOURCE
+#endif
+#include "libioP.h"
+#if _IO_HAVE_SYS_WAIT
+#include <signal.h>
+#include <unistd.h>
+#ifdef __STDC__
+#include <stdlib.h>
+#endif
+#ifdef _LIBC
+# include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#ifndef _IO_fork
+#ifdef _LIBC
+#define _IO_fork __vfork
+#else
+#define _IO_fork vfork /* defined in libiberty, if needed */
+#endif
+extern _IO_pid_t _IO_fork __P ((void));
+#endif
+
+#endif /* _IO_HAVE_SYS_WAIT */
+
+#ifndef _IO_pipe
+#ifdef _LIBC
+#define _IO_pipe __pipe
+#else
+#define _IO_pipe pipe
+#endif
+extern int _IO_pipe __P ((int des[2]));
+#endif
+
+#ifndef _IO_dup2
+#ifdef _LIBC
+#define _IO_dup2 __dup2
+#else
+#define _IO_dup2 dup2
+#endif
+extern int _IO_dup2 __P ((int fd, int fd2));
+#endif
+
+#ifndef _IO_waitpid
+#ifdef _LIBC
+#define _IO_waitpid __waitpid
+#else
+#define _IO_waitpid waitpid
+#endif
+#endif
+
+#ifndef _IO_execl
+#define _IO_execl execl
+#endif
+#ifndef _IO__exit
+#define _IO__exit _exit
+#endif
+
+#ifndef _IO_close
+#ifdef _LIBC
+#define _IO_close __close
+#else
+#define _IO_close close
+#endif
+#endif
+
+struct _IO_proc_file
+{
+  struct _IO_FILE_plus file;
+  /* Following fields must match those in class procbuf (procbuf.h) */
+  _IO_pid_t pid;
+  struct _IO_proc_file *next;
+};
+typedef struct _IO_proc_file _IO_proc_file;
+
+static struct _IO_proc_file *old_proc_file_chain = NULL;
+
+_IO_FILE *
+_IO_old_proc_open (fp, command, mode)
+     _IO_FILE *fp;
+     const char *command;
+     const char *mode;
+{
+#if _IO_HAVE_SYS_WAIT
+  volatile int read_or_write;
+  volatile int parent_end, child_end;
+  int pipe_fds[2];
+  _IO_pid_t child_pid;
+  if (_IO_file_is_open (fp))
+    return NULL;
+  if (_IO_pipe (pipe_fds) < 0)
+    return NULL;
+  if (mode[0] == 'r' && mode[1] == '\0')
+    {
+      parent_end = pipe_fds[0];
+      child_end = pipe_fds[1];
+      read_or_write = _IO_NO_WRITES;
+    }
+  else if (mode[0] == 'w' && mode[1] == '\0')
+    {
+      parent_end = pipe_fds[1];
+      child_end = pipe_fds[0];
+      read_or_write = _IO_NO_READS;
+    }
+  else
+    {
+      __set_errno (EINVAL);
+      return NULL;
+    }
+  ((_IO_proc_file *) fp)->pid = child_pid = _IO_fork ();
+  if (child_pid == 0)
+    {
+      int child_std_end = mode[0] == 'r' ? 1 : 0;
+      _IO_close (parent_end);
+      if (child_end != child_std_end)
+	{
+	  _IO_dup2 (child_end, child_std_end);
+	  _IO_close (child_end);
+	}
+      /* POSIX.2:  "popen() shall ensure that any streams from previous
+         popen() calls that remain open in the parent process are closed
+	 in the new child process." */
+      while (old_proc_file_chain)
+	{
+	  _IO_close (_IO_fileno ((_IO_FILE *) old_proc_file_chain));
+	  old_proc_file_chain = old_proc_file_chain->next;
+	}
+
+      _IO_execl ("/bin/sh", "sh", "-c", command, (char *) 0);
+      _IO__exit (127);
+    }
+  _IO_close (child_end);
+  if (child_pid < 0)
+    {
+      _IO_close (parent_end);
+      return NULL;
+    }
+  _IO_fileno (fp) = parent_end;
+
+  /* Link into old_proc_file_chain. */
+  ((_IO_proc_file *) fp)->next = old_proc_file_chain;
+  old_proc_file_chain = (_IO_proc_file *) fp;
+
+  _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
+  return fp;
+#else /* !_IO_HAVE_SYS_WAIT */
+  return NULL;
+#endif
+}
+
+_IO_FILE *
+_IO_old_popen (command, mode)
+     const char *command;
+     const char *mode;
+{
+  struct locked_FILE
+  {
+    struct _IO_proc_file fpx;
+#ifdef _IO_MTSAFE_IO
+    _IO_lock_t lock;
+#endif
+  } *new_f;
+  _IO_FILE *fp;
+
+  new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
+  if (new_f == NULL)
+    return NULL;
+#ifdef _IO_MTSAFE_IO
+  new_f->fpx.file.file._lock = &new_f->lock;
+#endif
+  fp = &new_f->fpx.file.file;
+  _IO_init (fp, 0);
+  _IO_JUMPS (fp) = &_IO_old_proc_jumps;
+  _IO_old_file_init (fp);
+#if  !_IO_UNIFIED_JUMPTABLES
+  new_f->fpx.file.vtable = NULL;
+#endif
+  if (_IO_old_proc_open (fp, command, mode) != NULL)
+    return fp;
+  _IO_un_link (fp);
+  free (new_f);
+  return NULL;
+}
+
+int
+_IO_old_proc_close (fp)
+     _IO_FILE *fp;
+{
+  /* This is not name-space clean. FIXME! */
+#if _IO_HAVE_SYS_WAIT
+  int wstatus;
+  _IO_proc_file **ptr = &old_proc_file_chain;
+  _IO_pid_t wait_pid;
+  int status = -1;
+
+  /* Unlink from old_proc_file_chain. */
+  for ( ; *ptr != NULL; ptr = &(*ptr)->next)
+    {
+      if (*ptr == (_IO_proc_file *) fp)
+	{
+	  *ptr = (*ptr)->next;
+	  status = 0;
+	  break;
+	}
+    }
+
+  if (status < 0 || _IO_close (_IO_fileno(fp)) < 0)
+    return -1;
+  /* POSIX.2 Rationale:  "Some historical implementations either block
+     or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
+     for the child process to terminate.  Since this behavior is not
+     described in POSIX.2, such implementations are not conforming." */
+  do
+    {
+      wait_pid = _IO_waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0);
+    }
+  while (wait_pid == -1 && errno == EINTR);
+  if (wait_pid == -1)
+    return -1;
+  return wstatus;
+#else /* !_IO_HAVE_SYS_WAIT */
+  return -1;
+#endif
+}
+
+struct _IO_jump_t _IO_old_proc_jumps = {
+  JUMP_INIT_DUMMY,
+  JUMP_INIT(finish, _IO_old_file_finish),
+  JUMP_INIT(overflow, _IO_old_file_overflow),
+  JUMP_INIT(underflow, _IO_old_file_underflow),
+  JUMP_INIT(uflow, _IO_default_uflow),
+  JUMP_INIT(pbackfail, _IO_default_pbackfail),
+  JUMP_INIT(xsputn, _IO_old_file_xsputn),
+  JUMP_INIT(xsgetn, _IO_default_xsgetn),
+  JUMP_INIT(seekoff, _IO_old_file_seekoff),
+  JUMP_INIT(seekpos, _IO_default_seekpos),
+  JUMP_INIT(setbuf, _IO_old_file_setbuf),
+  JUMP_INIT(sync, _IO_old_file_sync),
+  JUMP_INIT(doallocate, _IO_file_doallocate),
+  JUMP_INIT(read, _IO_file_read),
+  JUMP_INIT(write, _IO_old_file_write),
+  JUMP_INIT(seek, _IO_file_seek),
+  JUMP_INIT(close, _IO_old_proc_close),
+  JUMP_INIT(stat, _IO_file_stat),
+  JUMP_INIT(showmanyc, _IO_default_showmanyc),
+  JUMP_INIT(imbue, _IO_default_imbue)
+};
+
+strong_alias (_IO_old_popen, __old_popen)
+symbol_version (_IO_old_popen, _IO_popen, GLIBC_2.0);
+symbol_version (__old_popen, popen, GLIBC_2.0);
+symbol_version (_IO_old_proc_open, _IO_proc_open, GLIBC_2.0);
+symbol_version (_IO_old_proc_close, _IO_proc_close, GLIBC_2.0);
diff --git a/libio/oldpclose.c b/libio/oldpclose.c
new file mode 100644
index 0000000000..dc789c055a
--- /dev/null
+++ b/libio/oldpclose.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 1998 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This 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
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#define _IO_USE_OLD_IO_FILE
+#include "libioP.h"
+#include "stdio.h"
+#include <errno.h>
+
+int
+__old_pclose (fp)
+     FILE *fp;
+{
+#if 0
+  /* Does not actually test that stream was created by popen(). Instead,
+     it depends on the filebuf::sys_close() virtual to Do The Right Thing. */
+  if (fp is not a proc_file)
+    return -1;
+#endif
+  return _IO_old_fclose (fp);
+}
+
+symbol_version (__old_pclose, pclose, GLIBC_2.0);
diff --git a/libio/pclose.c b/libio/pclose.c
index 0640d47599..944365934d 100644
--- a/libio/pclose.c
+++ b/libio/pclose.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -28,7 +28,7 @@
 #include <errno.h>
 
 int
-pclose (fp)
+__new_pclose (fp)
      FILE *fp;
 {
 #if 0
@@ -37,5 +37,13 @@ pclose (fp)
   if (fp is not a proc_file)
     return -1;
 #endif
-  return _IO_fclose (fp);
+  return _IO_new_fclose (fp);
 }
+
+#if defined PIC && DO_VERSIONING
+default_symbol_version (__new_pclose, pclose, GLIBC_2.1);
+#else
+# ifdef weak_alias
+weak_alias (__new_pclose, pclose)
+# endif
+#endif
diff --git a/math/bits/mathcalls.h b/math/bits/mathcalls.h
index d23a013ae6..39979cf437 100644
--- a/math/bits/mathcalls.h
+++ b/math/bits/mathcalls.h
@@ -225,7 +225,7 @@ __MATHCALL (yn,, (int, _Mdouble_));
 
 
 #if defined __USE_MISC || defined __USE_XOPEN || defined __USE_ISOC9X
-/* Error, gamma, and Bessel functions.  */
+/* Error and gamma functions.  */
 __MATHCALL (erf,, (_Mdouble_));
 __MATHCALL (erfc,, (_Mdouble_));
 __MATHCALL (lgamma,, (_Mdouble_));
@@ -233,15 +233,15 @@ __MATHCALL (tgamma,, (_Mdouble_));
 #endif
 
 #if defined __USE_MISC || defined __USE_XOPEN
+/* Obsolete alias for `lgamma'.  */
 __MATHCALL (gamma,, (_Mdouble_));
 #endif
 
 #ifdef __USE_MISC
-/* Reentrant versions of gamma and lgamma.  Those functions use the global
-   variable `signgam'.  The reentrant versions instead take a pointer and
-   store the value through it.  */
-__MATHCALL (gamma,_r, (_Mdouble_, int *));
-__MATHCALL (lgamma,_r, (_Mdouble_, int *));
+/* Reentrant version of lgamma.  This function uses the global variable
+   `signgam'.  The reentrant version instead takes a pointer and stores
+   the value through it.  */
+__MATHCALL (lgamma,_r, (_Mdouble_, int *__signgamp));
 #endif
 
 
diff --git a/nss/Makefile b/nss/Makefile
index 07529c711c..2b7bbc3f2b 100644
--- a/nss/Makefile
+++ b/nss/Makefile
@@ -36,6 +36,9 @@ routines		= nsswitch $(addsuffix -lookup,$(databases))
 databases		= proto service hosts network grp pwd rpc ethers \
 			  spwd netgrp key alias
 
+others                  := getent
+install-bin             := getent
+
 tests			= test-netdb
 
 include ../Makeconfig
diff --git a/nss/getent.c b/nss/getent.c
new file mode 100644
index 0000000000..027ffa20e0
--- /dev/null
+++ b/nss/getent.c
@@ -0,0 +1,511 @@
+/* Copyright (c) 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1998.
+
+   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. */
+
+/* getent: get entries from administrative database
+   supported databases: passwd, group, hosts, services, protocols
+   and networks */
+
+#include <argp.h>
+#include <grp.h>
+#include <pwd.h>
+#include <ctype.h>
+#include <error.h>
+#include <libintl.h>
+#include <locale.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+/* Get libc version number.  */
+#include <version.h>
+
+#define PACKAGE _libc_intl_domainname
+
+/* Name and version of program.  */
+static void print_version (FILE *stream, struct argp_state *state);
+void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+
+/* Short description of parameters.  */
+static const char args_doc[] = N_("database [key ...]");
+
+/* Short description of program.  */
+static const char doc[] =
+                N_("getent - get entries from administrative database.");
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp = {
+  NULL, NULL, args_doc, doc,
+};
+
+/* Print the version information.  */
+static void
+print_version (FILE *stream, struct argp_state *state)
+{
+  fprintf (stream, "getent (GNU %s) %s\n", PACKAGE, VERSION);
+  fprintf (stream, gettext ("\
+Copyright (C) %s Free Software Foundation, Inc.\n\
+This is free software; see the source for copying conditions.  There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
+"), "1998");
+  fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk");
+}
+
+/* This is for group */
+static inline void
+print_group (struct group *grp)
+{
+  unsigned int i = 0;
+
+  printf ("%s:%s:%ld:", grp->gr_name ? grp->gr_name : "",
+	  grp->gr_passwd ? grp->gr_passwd : "",
+	  (unsigned long)grp->gr_gid);
+
+  while (grp->gr_mem[i] != NULL)
+    {
+      fputs (grp->gr_mem[i], stdout);
+      ++i;
+      if (grp->gr_mem[i] != NULL)
+	fputs (",", stdout);
+    }
+  fputs ("\n", stdout);
+}
+
+static inline int
+group_keys (int number, char *key[])
+{
+  int result = 0;
+  int i;
+
+  for (i = 0; i < number; ++i)
+    {
+      struct group *grp;
+
+      if (isdigit (key[i][0]))
+	grp = getgrgid (atol (key[i]));
+      else
+	grp = getgrnam (key[i]);
+
+      if (grp == NULL)
+	result = 2;
+      else
+	print_group (grp);
+    }
+
+  return result;
+}
+
+/* This is for networks */
+static inline void
+print_networks (struct netent *net)
+{
+  unsigned int i;
+  struct in_addr ip;
+  ip.s_addr = htonl (net->n_net);
+
+  fputs (net->n_name, stdout);
+  for  (i = strlen (net->n_name); i < 22; ++i)
+    fputs (" ", stdout);
+  fputs (inet_ntoa (ip), stdout);
+
+  i = 0;
+  while (net->n_aliases[i] != NULL)
+    {
+      fputs (" ", stdout);
+      fputs (net->n_aliases[i], stdout);
+      ++i;
+      if (net->n_aliases[i] != NULL)
+	fputs (",", stdout);
+    }
+  fputs ("\n", stdout);
+}
+
+static inline int
+networks_keys (int number, char *key[])
+{
+  int result = 0;
+  int i;
+
+  for (i = 0; i < number; ++i)
+    {
+      struct netent *net;
+
+      if (isdigit (key[i][0]))
+	net = getnetbyaddr (inet_addr (key[i]), AF_UNIX);
+      else
+	net = getnetbyname (key[i]);
+
+      if (net == NULL)
+	result = 2;
+      else
+	print_networks (net);
+    }
+
+  return result;
+}
+
+/* Now is all for passwd */
+static inline void
+print_passwd (struct passwd *pwd)
+{
+  printf ("%s:%s:%ld:%ld:%s:%s:%s\n",
+	  pwd->pw_name ? pwd->pw_name : "",
+	  pwd->pw_passwd ? pwd->pw_passwd : "",
+	  (unsigned long)pwd->pw_uid,
+	  (unsigned long)pwd->pw_gid,
+	  pwd->pw_gecos ? pwd->pw_gecos : "",
+	  pwd->pw_dir ? pwd->pw_dir : "",
+	  pwd->pw_shell ? pwd->pw_shell : "");
+}
+
+static inline int
+passwd_keys (int number, char *key[])
+{
+  int result = 0;
+  int i;
+
+  for (i = 0; i < number; ++i)
+    {
+      struct passwd *pwd;
+
+      if (isdigit (key[i][0]))
+	pwd = getpwuid (atol (key[i]));
+      else
+	pwd = getpwnam (key[i]);
+
+      if (pwd == NULL)
+	result = 2;
+      else
+	print_passwd (pwd);
+    }
+
+  return result;
+}
+
+/* This is for protocols */
+static inline void
+print_protocols (struct protoent *proto)
+{
+  unsigned int i;
+
+  fputs (proto->p_name, stdout);
+  for (i = strlen (proto->p_name); i < 22; ++i)
+    fputs (" ", stdout);
+  printf ("%d", proto->p_proto);
+
+  i = 0;
+  while (proto->p_aliases[i] != NULL)
+    {
+      fputs (" ", stdout);
+      fputs (proto->p_aliases[i], stdout);
+      ++i;
+    }
+  fputs ("\n", stdout);
+}
+
+static inline int
+protocols_keys (int number, char *key[])
+{
+  int result = 0;
+  int i;
+
+  for (i = 0; i < number; ++i)
+    {
+      struct protoent *proto;
+
+      if (isdigit (key[i][0]))
+	proto = getprotobynumber (atol (key[i]));
+      else
+	proto = getprotobyname (key[i]);
+
+      if (proto == NULL)
+	result = 2;
+      else
+	print_protocols (proto);
+    }
+
+  return result;
+}
+
+/* This is for hosts */
+static inline void
+print_hosts (struct hostent *host)
+{
+  unsigned int i;
+  char *ip = inet_ntoa(* (struct in_addr *) host->h_addr_list[0]);
+
+  fputs (ip, stdout);
+  for (i = strlen (ip); i < 16; ++i)
+    fputs (" ", stdout);
+  fputs (host->h_name, stdout);
+
+  i = 0;
+  while (host->h_aliases[i] != NULL)
+    {
+      fputs (" ", stdout);
+      fputs (host->h_aliases[i], stdout);
+      ++i;
+    }
+  fputs ("\n", stdout);
+}
+
+static inline int
+hosts_keys (int number, char *key[])
+{
+  int result = 0;
+  int i;
+
+  for (i = 0; i < number; ++i)
+    {
+      struct hostent *host;
+
+      if (isdigit (key[i][0]))
+	{
+	  struct in_addr addr;
+	  addr.s_addr = inet_addr (key[i]);
+
+	  host = gethostbyaddr ((char *)&addr, sizeof (struct in_addr),
+				AF_INET);
+	}
+      else
+	host = gethostbyname (key[i]);
+
+      if (host == NULL)
+	result = 2;
+      else
+	print_hosts (host);
+    }
+
+  return result;
+}
+
+/* for services */
+static inline void
+print_services (struct servent *serv)
+{
+  unsigned int i;
+
+  fputs (serv->s_name, stdout);
+  for (i = strlen (serv->s_name); i < 22; ++i)
+    fputs (" ", stdout);
+  printf ("%d/%s", ntohs (serv->s_port), serv->s_proto);
+
+  i = 0;
+  while (serv->s_aliases[i] != NULL)
+    {
+      fputs (" ", stdout);
+      fputs (serv->s_aliases[i], stdout);
+      ++i;
+    }
+  fputs ("\n", stdout);
+}
+
+static inline int
+services_keys (int number, char *key[])
+{
+  int result = 0;
+  int i;
+
+  for (i = 0; i < number; ++i)
+    {
+      struct servent *serv;
+      char *proto = strchr (key[i], '/');
+
+      if (proto == NULL)
+	{
+	  setservent (0);
+	  if (isdigit (key[i][0]))
+	    {
+	      int port = htons (atol (key[i]));
+	      while ((serv = getservent ()) != NULL)
+		if (serv->s_port == port)
+		  {
+		    print_services (serv);
+		    break;
+		  }
+	    }
+	  else
+	    {
+	      while ((serv = getservent ()) != NULL)
+		if (strcmp (serv->s_name, key[i]) == 0)
+		  {
+		    print_services (serv);
+		    break;
+		  }
+	    }
+	  endservent ();
+	}
+      else
+	{
+	  *proto++ = '\0';
+
+	  if (isdigit (key[i][0]))
+	    serv = getservbyport (atol (key[i]), proto);
+	  else
+	    serv = getservbyname (key[i], proto);
+
+	  if (serv == NULL)
+	    result = 2;
+	  else
+	    print_services (serv);
+	}
+    }
+
+  return result;
+}
+
+/* the main function */
+int
+main (int argc, char *argv[])
+{
+  int remaining;
+
+  /* Set locale via LC_ALL.  */
+  setlocale (LC_ALL, "");
+  /* Set the text message domain.  */
+  textdomain (PACKAGE);
+
+  /* Parse and process arguments.  */
+  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
+
+  if ((argc - remaining) < 1)
+    {
+      error (0, 0, gettext ("wrong number of arguments"));
+      argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name);
+      return 1;
+    }
+
+  switch(argv[1][0])
+    {
+    case 'g': /* group */
+      if (strcmp (argv[1], "group") == 0)
+	{
+	  if (argc == 2)
+	    {
+	      struct group *grp;
+
+	      setgrent ();
+	      while ((grp = getgrent()) != NULL)
+		print_group (grp);
+	      endgrent ();
+	    }
+	  else
+	    return group_keys (argc - 2, &argv[2]);
+	}
+      else
+	goto error;
+      break;
+    case 'h': /* hosts */
+      if (strcmp (argv[1], "hosts") == 0)
+	{
+	  if (argc == 2)
+	    {
+	      struct hostent *host;
+
+	      sethostent (0);
+	      while ((host = gethostent()) != NULL)
+		print_hosts (host);
+	      endhostent ();
+	    }
+	  else
+	    return hosts_keys (argc - 2, &argv[2]);
+	}
+      else
+	goto error;
+      break;
+    case 'n': /* networks */
+      if (strcmp (argv[1], "networks") == 0)
+	{
+	  if (argc == 2)
+	    {
+	      struct netent *net;
+
+	      setnetent (0);
+	      while ((net = getnetent()) != NULL)
+		print_networks (net);
+	      endnetent ();
+	    }
+	  else
+	    return networks_keys (argc - 2, &argv[2]);
+	}
+      else
+	goto error;
+      break;
+    case 'p': /* passwd, protocols */
+      if (strcmp (argv[1], "passwd") == 0)
+	{
+	  if (argc == 2)
+	    {
+	      struct passwd *pwd;
+
+	      setpwent ();
+	      while ((pwd = getpwent()) != NULL)
+		print_passwd (pwd);
+	      endpwent ();
+	    }
+	  else
+	    return passwd_keys (argc - 2, &argv[2]);
+	}
+      else if (strcmp (argv[1], "protocols") == 0)
+	{
+	  if (argc == 2)
+	    {
+	      struct protoent *proto;
+
+	      setprotoent (0);
+	      while ((proto = getprotoent()) != NULL)
+		print_protocols (proto);
+	      endprotoent ();
+	    }
+	  else
+	    return protocols_keys (argc - 2, &argv[2]);
+	}
+      else
+	goto error;
+      break;
+    case 's': /* services */
+      if (strcmp (argv[1], "services") == 0)
+	{
+	  if (argc == 2)
+	    {
+	      struct servent *serv;
+
+	      setservent (0);
+	      while ((serv = getservent()) != NULL)
+		print_services (serv);
+	      endservent ();
+	    }
+	  else
+	    return services_keys (argc - 2, &argv[2]);
+	}
+      else
+	goto error;
+      break;
+    default:
+    error:
+      fprintf (stderr, _("Unknown database: %s\n"), argv[1]);
+      argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name);
+      return 1;
+    }
+
+  return 0;
+}
diff --git a/sysdeps/i386/fpu/bits/mathinline.h b/sysdeps/i386/fpu/bits/mathinline.h
index 6e55f66c98..91dce771ab 100644
--- a/sysdeps/i386/fpu/bits/mathinline.h
+++ b/sysdeps/i386/fpu/bits/mathinline.h
@@ -499,8 +499,6 @@ ldexp (double __x, int __y)
 /* Optimized versions for some non-standardized functions.  */
 #if defined __USE_ISOC9X || defined __USE_MISC
 
-__inline_mathop(log2, "fld1; fxch; fyl2x")
-
 __inline_mathcode (expm1, __x, __expm1_code)
 
 /* We cannot rely on M_SQRT being defined.  So we do it for ourself
@@ -533,7 +531,6 @@ __inline_mathcode (atanh, __x, \
   register long double __y = __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))
 
@@ -545,6 +542,11 @@ __inline_mathcode(logb, __x, \
      : "=t" (__junk), "=u" (__value) : "0" (__x));			      \
   return __value)
 
+#endif
+
+#ifdef __USE_ISOC9X
+__inline_mathop(log2, "fld1; fxch; fyl2x")
+
 __MATH_INLINE float ldexpf (float __x, int __y);
 __MATH_INLINE float
 ldexpf (float __x, int __y)
@@ -560,6 +562,9 @@ ldexpl (long double __x, int __y)
 }
 
 __inline_mathcode3 (fma, __x, __y, __z, return (__x * __y) + __z)
+
+__inline_mathop(rint, "frndint")
+
 #endif