about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog106
-rw-r--r--manual/math.texi29
-rw-r--r--manual/stdio.texi38
-rw-r--r--math/Makefile2
-rw-r--r--math/Versions1
-rw-r--r--math/bits/mathcalls.h6
-rw-r--r--math/libm-test.c67
-rw-r--r--nis/Banner2
-rw-r--r--nis/Makefile6
-rw-r--r--nis/Versions7
-rw-r--r--nis/nis_call.c216
-rw-r--r--nis/nis_checkpoint.c2
-rw-r--r--nis/nis_file.c32
-rw-r--r--nis/nis_findserv.c22
-rw-r--r--nis/nis_intern.h35
-rw-r--r--nis/nis_lookup.c166
-rw-r--r--nis/nis_mkdir.c2
-rw-r--r--nis/nis_ping.c2
-rw-r--r--nis/nis_rmdir.c2
-rw-r--r--nis/nis_server.c4
-rw-r--r--nis/nis_table.c399
-rw-r--r--nis/nis_util.c2
-rw-r--r--nis/rpcsvc/nislib.h31
-rw-r--r--nscd/connections.c22
-rw-r--r--nscd/nscd_getgr_r.c23
-rwxr-xr-xposix/globtest.sh9
-rw-r--r--stdio-common/printf-parse.h25
-rw-r--r--stdio-common/vfprintf.c67
-rw-r--r--stdio-common/vfscanf.c28
-rw-r--r--stdlib/strtol.c2
-rw-r--r--sunrpc/Makefile3
-rw-r--r--sunrpc/Versions5
-rw-r--r--sunrpc/clnt_gen.c16
-rw-r--r--sunrpc/clnt_unix.c573
-rw-r--r--sunrpc/key_call.c200
-rw-r--r--sunrpc/rpc/clnt.h22
-rw-r--r--sunrpc/rpc/svc.h7
-rw-r--r--sunrpc/svc_authux.c18
-rw-r--r--sunrpc/svc_tcp.c4
-rw-r--r--sunrpc/svc_unix.c496
-rw-r--r--sysdeps/generic/glob.c61
-rw-r--r--sysdeps/libm-ieee754/k_standard.c14
-rw-r--r--sysdeps/libm-ieee754/w_gammaf.c68
-rw-r--r--sysdeps/libm-ieee754/w_gammal.c71
-rw-r--r--sysdeps/libm-ieee754/w_lgamma.c4
-rw-r--r--sysdeps/libm-ieee754/w_lgammaf.c2
-rw-r--r--sysdeps/libm-ieee754/w_lgammal.c2
-rw-r--r--sysdeps/libm-ieee754/w_tgamma.c (renamed from sysdeps/libm-ieee754/w_gamma.c)50
-rw-r--r--sysdeps/libm-ieee754/w_tgammaf.c50
-rw-r--r--sysdeps/libm-ieee754/w_tgammal.c53
-rw-r--r--sysdeps/mach/hurd/dl-sysdep.c65
-rw-r--r--sysdeps/unix/sysv/linux/recvmsg.c1
-rw-r--r--sysdeps/unix/sysv/linux/sendmsg.c1
-rw-r--r--version.h2
54 files changed, 2443 insertions, 700 deletions
diff --git a/ChangeLog b/ChangeLog
index 98f052420f..3ada154100 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,109 @@
+1998-07-28  Ulrich Drepper  <drepper@cygnus.com>
+
+	* math/libm-test.c (tgamma_test): Remove redundant tests.
+
+1998-07-28 16:20  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/generic/glob.c: Correct problems with */foo and GLOB_NOCHECK
+	where foo does not exist in any of the subdirectories.
+	Reported by Paul D. Smith <psmith@BayNetworks.COM>.
+
+	* posix/globtest.sh: Add test for this bug.
+
+1998-07-28  Mark Kettenis  <kettenis@phys.uva.nl>
+
+	* io/sys/statfs.h: Fix typos.
+	* io/sys/statvfs.h: Fix typos.
+
+1998-07-28  Ulrich Drepper  <drepper@cygnus.com>
+
+	* version.h (VERSION): Bump to 2.0.95.
+
+	* math/Makefile (libm-calls): Remove w_gamma, add w_tgamma.
+	* math/Versions [GLIBC_2.1]: Add tgamma, tgammaf, and tgammal.
+	* math/libm-test.c: Split old gamma_test and move half of it in new
+	function tgamma_test.
+	* math/bits/mathcalls.h: Add declaration of tgamma.
+	* sysdeps/libm-ieee754/k_standard.c: Change gamma errors into
+	tgamma errors.
+	* sysdeps/libm-ieee754/w_gamma.c: Remove lgamma compatibility code
+	and rename to ...
+	* sysdeps/libm-ieee754/w_tgamma.c: ... this.  New file.
+	* sysdeps/libm-ieee754/w_gammaf.c: Remove lgammaf compatibility code
+	and rename to ...
+	* sysdeps/libm-ieee754/w_tgammaf.c: ... this.  New file.
+	* sysdeps/libm-ieee754/w_gammal.c: Remove lgammal compatibility code
+	and rename to ...
+	* sysdeps/libm-ieee754/w_tgammal.c: ... this.  New file.
+	* sysdeps/libm-ieee754/w_lgamma.c: Add gamma as weak alias.
+	* sysdeps/libm-ieee754/w_lgammaf.c: Likewise.
+	* sysdeps/libm-ieee754/w_lgammal.c: Likewise.
+
+	* stgdio-common/printf-parse.h: Implement handling of j, t, and z
+	modifiers.
+	* stdio-common/vfprintf.c: Likewise.
+	* stdio-common/vfscanf.c: Likewise.
+	* manual/stdio.texi: Document new printf/scanf modifiers.
+
+	* sysdeps/unix/sysv/linux/recvmsg.c: Remove alias __recvmsg.
+	* sysdeps/unix/sysv/linux/sendmsg.c: Remove alias __sendmsg.
+
+1998-07-28  Thorsten Kukuk  <kukuk@vt.uni-paderborn.de>
+
+	* sunrpc/Makefile (routines): Add clnt_unix and svc_unix.
+	* sunrpc/Versions: Add new *unix_create functions.
+	* sunrpc/clnt_gen.c: Add support for RPC over AF_UNIX.
+	* sunrpc/clnt_unix.c: New, client side of RPC over AF_UNIX.
+	* sunrpc/key_call.c: Use RPC over AF_UNIX for communication
+	with keyserv daemon.
+	* sunrpc/rpc/clnt.h: Add AF_UNIX based RPC function prototypes.
+	* sunrpc/rpc/svc.h: Likewise.
+	* sunrpc/svc_authux.c: Copy internal auth flavor if none is given.
+	* sunrpc/svc_tcp.c: Fix typos.
+	* sunrpc/svc_unix.c: New, server side of AF_UNIX based RPC.
+
+	* nis/Makefile: Remove currently not working cache functions.
+	* nis/Versions: Add __nisbind_* functions for rpc.nisd.
+	* nis/nis_call.c: Rewrite binding to a NIS+ server to reuse
+	CLIENT handles.
+	* nis/nis_file.c: Fix memory leaks.
+	* nis/nis_intern.h: Move internal structs from here ...
+	* nis/rpcsvc/nislib.h: ... to here for NIS+ server and tools.
+	* nis/nis_lookup.c: Try at first if last client handle works.
+	* nis/nis_table.c: Likewise.
+	* nis/nis_checkpoint.c: Adjust __do_niscall2 parameters.
+	* nis/nis_mkdir.c: Likewise.
+	* nis/nis_ping.c: Likewise.
+	* nis/nis_rmdir.c: Likewise.
+	* nis/nis_server.c: Likewise.
+	* nis/nis_util.c: Likewise.
+	* nis/nis_findserv.c (__nis_findfastest): Little optimization.
+
+1998-07-28  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
+
+	* stdlib/strtol.c (STRTOL_LONG_MAX): Correct typo in last patch -
+	define as LONG_MAX.
+
+1998-07-28 09:31  Ulrich Drepper  <drepper@cygnus.com>
+
+	* nscd/connections.c (gr_send_answer): Deal with missing UIO_MAXIOV.
+	Correct test whether writev send all data.
+	* nscd/nscd_getgr_r.c (__nscd_getgr_r): Correct test whether readv
+	received all data.
+
+1998-07-28  Mark Kettenis  <kettenis@phys.uva.nl>
+
+	* nscd/nscd_getgr_r.c (__nscd_getgr_r): Deal with missing UIO_MAXIOV.
+
+1998-07-28  Mark Kettenis  <kettenis@phys.uva.nl>
+
+	* sysdeps/mach/hurd/dl-sysdep.c (open_file): Change assert call to
+	allow mode to be 0.
+	(__xstat): New function.
+	(__fxstat): New function.
+	(_dl_sysdep_read_whole_file): Removed.  The implementation in
+	`elf/dl-misc.c' now also works for the Hurd.
+
 1998-07-27 22:25  Ulrich Drepper  <drepper@cygnus.com>
 
 	* sysdeps/generic/glob.c: Handle ~ and ~NAME case correctly.
diff --git a/manual/math.texi b/manual/math.texi
index 4386c2fefc..e1d597d06a 100644
--- a/manual/math.texi
+++ b/manual/math.texi
@@ -857,7 +857,8 @@ The sign of the gamma function is stored in the global variable
 the intermediate result was positive or zero, and, @code{-1} if it was
 negative.
 
-You can compute the actual gamma function as follows:
+To compute the real gamma function you can use the @code{tgamma}
+function or you can compute the values as follows:
 @smallexample
 lgam = lgamma(x);
 gam  = signgam*exp(lgam);
@@ -878,15 +879,35 @@ the intermediate result in the variable pointed to by @var{signp}
 instead of in the @var{signgam} global.
 @end deftypefun
 
-@ignore
 @comment math.h
 @comment SVID
 @deftypefun double gamma (double @var{x})
 @deftypefunx float gammaf (float @var{x})
 @deftypefunx {long double} gammal (long double @var{x})
-??? _not_ exp(lgamma())*signgam - historical?
+These functions exist for compatibility reasons.  They are equivalent to
+@code{lgamma} etc.  It is better to use @code{lgamma} since for one the
+name reflect better the actual computation and @code{lgamma} is also
+standardized in @w{ISO C 9x} while @code{gamma} is not.
+@end deftypefun
+
+@comment math.h
+@comment XPG
+@deftypefun double tgamma (double @var{x})
+@deftypefunx float tgammaf (float @var{x})
+@deftypefunx {long double} tgammal (long double @var{x})
+@code{tgamma} applies the gamma function to @var{x}.  The gamma
+function is defined as
+@tex
+$$\Gamma(x) = \int_0^\infty t^{x-1} e^{-t} \hbox{d}t$$
+@end tex
+@ifnottex
+@smallexample
+gamma (x) = integral from 0 to @infinity{} of t^(x-1) e^-t dt
+@end smallexample
+@end ifnottex
+
+This function was introduced in @w{ISO C 9x}.
 @end deftypefun
-@end ignore
 
 @comment math.h
 @comment SVID
diff --git a/manual/stdio.texi b/manual/stdio.texi
index c930471220..531717c81f 100644
--- a/manual/stdio.texi
+++ b/manual/stdio.texi
@@ -1190,6 +1190,8 @@ char}, as appropriate.  A @code{char} argument is converted to an
 anyway, but the @samp{h} modifier says to convert it back to a
 @code{char} again.
 
+This modifier was introduced in @w{ISO C 9x}.
+
 @item h
 Specifies that the argument is a @code{short int} or @code{unsigned
 short int}, as appropriate.  A @code{short} argument is converted to an
@@ -1197,6 +1199,12 @@ short int}, as appropriate.  A @code{short} argument is converted to an
 anyway, but the @samp{h} modifier says to convert it back to a
 @code{short} again.
 
+@item j
+Specifies that the argument is a @code{intmax_t} or @code{uintmax_t}, as
+appropriate.
+
+This modifier was introduced in @w{ISO C 9x}.
+
 @item l
 Specifies that the argument is a @code{long int} or @code{unsigned long
 int}, as appropriate.  Two @samp{l} characters is like the @samp{L}
@@ -1213,8 +1221,17 @@ The @samp{q} modifier is another name for the same thing, which comes
 from 4.4 BSD; a @w{@code{long long int}} is sometimes called a ``quad''
 @code{int}.
 
-@item Z
-Specifies that the argument is a @code{size_t}.  This is a GNU extension.
+@item t
+Specifies that the argument is a @code{ptrdiff_t}.
+
+This modifier was introduced in @w{ISO C 9x}.
+
+@item z
+@itemx Z
+Specifies that the argument is a @code{size_t}.
+
+@samp{z} was introduced in @w{ISO C 9x}.  @samp{Z} is a GNU extension
+predating this addition and should not be used anymore in new code.
 @end table
 
 Here is an example.  Using the template string:
@@ -2653,10 +2670,17 @@ specify other sizes of integer:
 Specifies that the argument is a @code{signed char *} or @code{unsigned
 char *}.
 
+This modifier was introduced in @w{ISO C 9x}.
+
 @item h
 Specifies that the argument is a @code{short int *} or @code{unsigned
 short int *}.
 
+@item j
+Specifies that the argument is a @code{intmax_t *} or @code{uintmax_t *}.
+
+This modifier was introduced in @w{ISO C 9x}.
+
 @item l
 Specifies that the argument is a @code{long int *} or @code{unsigned
 long int *}.  Two @samp{l} characters is like the @samp{L} modifier, below.
@@ -2672,6 +2696,16 @@ is the same as @code{long int}.)
 The @samp{q} modifier is another name for the same thing, which comes
 from 4.4 BSD; a @w{@code{long long int}} is sometimes called a ``quad''
 @code{int}.
+
+@item t
+Specifies that the argument is a @code{ptrdiff_t *}.
+
+This modifier was introduced in @w{ISO C 9x}.
+
+@item z
+Specifies that the argument is a @code{size_t *}.
+
+This modifier was introduced in @w{ISO C 9x}.
 @end table
 
 All of the @samp{%e}, @samp{%f}, @samp{%g}, @samp{%E}, and @samp{%G}
diff --git a/math/Makefile b/math/Makefile
index 9f2d3367e5..4bd9580084 100644
--- a/math/Makefile
+++ b/math/Makefile
@@ -49,7 +49,7 @@ libm-calls = e_acos e_acosh e_asin e_atan2 e_atanh e_cosh e_exp e_fmod	\
 	     s_modf s_nextafter s_nextafterx s_rint s_scalbn s_scalbln	\
 	     s_significand s_sin s_tan s_tanh w_acos w_acosh w_asin	\
 	     w_atan2 w_atanh w_cosh w_drem w_exp w_exp2 w_exp10 w_fmod	\
-	     w_gamma w_hypot w_j0 w_j1 w_jn w_lgamma w_lgamma_r		\
+	     w_tgamma w_hypot w_j0 w_j1 w_jn w_lgamma w_lgamma_r	\
 	     w_log w_log10 w_pow w_remainder w_scalb w_sinh w_sqrt	\
 	     s_signbit s_fpclassify s_fmax s_fmin s_fdim s_nan s_trunc	\
 	     s_remquo s_log2 s_exp2 s_round s_nearbyint s_sincos	\
diff --git a/math/Versions b/math/Versions
index 8864ef1b87..580fa253aa 100644
--- a/math/Versions
+++ b/math/Versions
@@ -111,6 +111,7 @@ libm {
     scalbln; scalblnf; scalblnl;
     sincos; sincosf; sincosl;
     trunc; truncf; truncl;
+    tgamma; tgammaf; tgammal;
 
     # complex functions
     cabs; cabsf; cabsl;
diff --git a/math/bits/mathcalls.h b/math/bits/mathcalls.h
index 30bbb7c0aa..a94707ffe3 100644
--- a/math/bits/mathcalls.h
+++ b/math/bits/mathcalls.h
@@ -224,8 +224,12 @@ __MATHCALL (yn,, (int, _Mdouble_));
 /* Error, gamma, and Bessel functions.  */
 __MATHCALL (erf,, (_Mdouble_));
 __MATHCALL (erfc,, (_Mdouble_));
-__MATHCALL (gamma,, (_Mdouble_));
 __MATHCALL (lgamma,, (_Mdouble_));
+__MATHCALL (tgamma,, (_Mdouble_));
+#endif
+
+#if defined __USE_MISC || defined __USE_XOPEN
+__MATHCALL (gamma,, (_Mdouble_));
 #endif
 
 #ifdef __USE_MISC
diff --git a/math/libm-test.c b/math/libm-test.c
index 52358d5b34..95d285e1c7 100644
--- a/math/libm-test.c
+++ b/math/libm-test.c
@@ -51,7 +51,7 @@
    modf, nearbyint, nextafter,
    pow, remainder, remquo, rint, lrint, llrint,
    round, lround, llround,
-   scalb, scalbn, signbit, sin, sincos, sinh, sqrt, tan, tanh, trunc
+   scalb, scalbn, signbit, sin, sincos, sinh, sqrt, tan, tanh, tgamma, trunc
 
    and for the following complex math functions:
    cabs, cacos, cacosh, carg, casin, casinh, catan, catanh,
@@ -1413,15 +1413,9 @@ signbit_test (void)
 }
 
 
-/*
-   gamma has different semantics depending on _LIB_VERSION:
-   if _LIB_VERSION is _SVID, gamma is just an alias for lgamma,
-   otherwise gamma is the real gamma function as definied in ISO C 9X.
-*/
 static void
 gamma_test (void)
 {
-  int save_lib_version = _LIB_VERSION;
   errno = 0;
   FUNC(gamma) (1);
   if (errno == ENOSYS)
@@ -1430,14 +1424,12 @@ gamma_test (void)
   feclearexcept (FE_ALL_EXCEPT);
 
 
-  _LIB_VERSION = _SVID_;
-
   check_isinfp ("gamma (+inf) == +inf", FUNC(gamma) (plus_infty));
-  check_exc ("gamma (0) == HUGE plus divide by zero exception",
-	     FUNC(gamma) (0), HUGE, DIVIDE_BY_ZERO_EXCEPTION);
+  check_isinfp_exc ("gamma (0) == +inf plus divide by zero exception",
+		    FUNC(gamma) (0), DIVIDE_BY_ZERO_EXCEPTION);
 
-  check_exc ("gamma (x) == HUGE plus divide by zero exception for integer x <= 0",
-	     FUNC(gamma) (-3), HUGE, DIVIDE_BY_ZERO_EXCEPTION);
+  check_isinfp_exc ("gamma (x) == +inf plus divide by zero exception for integer x <= 0",
+		    FUNC(gamma) (-3), DIVIDE_BY_ZERO_EXCEPTION);
   check_isnan_exc ("gamma (-inf) == NaN plus invalid exception",
                    FUNC(gamma) (minus_infty), INVALID_EXCEPTION);
 
@@ -1459,39 +1451,43 @@ gamma_test (void)
              FUNC(log) (2*FUNC(sqrt) (M_PIl)), CHOOSE (0, 1e-15, 0));
 
   check_int ("gamma (-0.5) sets signgam to -1", signgam, -1);
+}
 
 
-  _LIB_VERSION = _IEEE_;
+static void
+tgamma_test (void)
+{
+  errno = 0;
+  FUNC(tgamma) (1);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+  feclearexcept (FE_ALL_EXCEPT);
 
-  check_isinfp ("gamma (+inf) == +inf", FUNC(gamma) (plus_infty));
-  check_isnan_exc ("gamma (0) == NaN plus invalid exception",
-                    FUNC(gamma) (0), INVALID_EXCEPTION);
 
-  check_isnan_exc_ext ("gamma (x) == NaN plus invalid exception for integer x <= 0",
-                        FUNC(gamma) (-2), INVALID_EXCEPTION, -2);
-  check_isnan_exc ("gamma (-inf) == NaN plus invalid exception",
-                   FUNC(gamma) (minus_infty), INVALID_EXCEPTION);
+  check_isinfp ("tgamma (+inf) == +inf", FUNC(tgamma) (plus_infty));
+  check_isnan_exc ("tgamma (0) == NaN plus invalid exception",
+                    FUNC(tgamma) (0), INVALID_EXCEPTION);
+
+  check_isnan_exc_ext ("tgamma (x) == NaN plus invalid exception for integer x <= 0",
+                        FUNC(tgamma) (-2), INVALID_EXCEPTION, -2);
+  check_isnan_exc ("tgamma (-inf) == NaN plus invalid exception",
+                   FUNC(tgamma) (minus_infty), INVALID_EXCEPTION);
 
 #ifdef TODO
-  check_eps ("gamma (0.5) == sqrt(pi)", FUNC(gamma) (0.5), FUNC(sqrt) (M_PIl),
-	     CHOOSE (0, 5e-16, 2e-7));
+  check_eps ("tgamma (0.5) == sqrt(pi)", FUNC(tgamma) (0.5),
+	     FUNC(sqrt) (M_PIl), CHOOSE (0, 5e-16, 2e-7));
 #endif
-  check_eps ("gamma (-0.5) == -2*sqrt(pi)", FUNC(gamma) (-0.5),
+  check_eps ("tgamma (-0.5) == -2*sqrt(pi)", FUNC(tgamma) (-0.5),
 	     -2*FUNC(sqrt) (M_PIl), CHOOSE (0, 5e-16, 3e-7));
 
-  check ("gamma (1) == 1", FUNC(gamma) (1), 1);
-  check ("gamma (4) == 6", FUNC(gamma) (4), 6);
+  check ("tgamma (1) == 1", FUNC(tgamma) (1), 1);
+  check ("tgamma (4) == 6", FUNC(tgamma) (4), 6);
 
-  check_eps ("gamma (0.7) == 1.29805...", FUNC(gamma) (0.7),
+  check_eps ("tgamma (0.7) == 1.29805...", FUNC(tgamma) (0.7),
 	     1.29805533264755778568L, CHOOSE(0, 3e-16, 2e-7));
-  check ("gamma (1.2) == 0.91816...", FUNC(gamma) (1.2), 0.91816874239976061064L);
-
-  check_isnan_exc ("gamma (0.0) == NaN plus invalid exception",
-		   FUNC(gamma) (0.0), INVALID_EXCEPTION);
-  check_isnan_exc ("gamma (-1.0) == NaN plus invalid exception",
-		   FUNC(gamma) (-1.0), INVALID_EXCEPTION);
-
-  _LIB_VERSION = save_lib_version;
+  check ("tgamma (1.2) == 0.91816...", FUNC(tgamma) (1.2),
+	 0.91816874239976061064L);
 }
 
 
@@ -6012,6 +6008,7 @@ main (int argc, char *argv[])
   erf_test ();
   erfc_test ();
   gamma_test ();
+  tgamma_test ();
   lgamma_test ();
 
   /* nearest integer functions */
diff --git a/nis/Banner b/nis/Banner
index 478c9b996e..1df3a1652b 100644
--- a/nis/Banner
+++ b/nis/Banner
@@ -1 +1 @@
-NIS(YP)/NIS+ NSS modules 0.17 by Thorsten Kukuk
+NIS(YP)/NIS+ NSS modules 0.18 by Thorsten Kukuk
diff --git a/nis/Makefile b/nis/Makefile
index c736b5a59a..78fdd072ec 100644
--- a/nis/Makefile
+++ b/nis/Makefile
@@ -23,7 +23,7 @@ subdir	:= nis
 
 headers			:= $(wildcard rpcsvc/*.[hx])
 distribute		:= nss-nis.h nss-nisplus.h nis_intern.h Banner \
-			nisplus-parser.h nis_cache2.h nis_xdr.h
+			nisplus-parser.h nis_xdr.h
 
 # These are the databases available for the nis (and perhaps later nisplus)
 # service.  This must be a superset of the services in nss.
@@ -44,8 +44,8 @@ vpath %.c $(subdir-dirs)
 
 libnsl-routines = yp_xdr ypclnt ypupdate_xdr \
                   nis_subr nis_local_names nis_free nis_file \
-                  nis_print nis_error nis_call nis_lookup nis_cache\
-                  nis_table nis_xdr nis_server nis_ping nis_cache2_xdr\
+                  nis_print nis_error nis_call nis_lookup\
+                  nis_table nis_xdr nis_server nis_ping \
 		  nis_checkpoint nis_mkdir nis_rmdir nis_getservlist\
 		  nis_verifygroup nis_ismember nis_addmember nis_util\
 		  nis_removemember nis_creategroup nis_destroygroup\
diff --git a/nis/Versions b/nis/Versions
index aa2df3a048..d26cba75b3 100644
--- a/nis/Versions
+++ b/nis/Versions
@@ -48,9 +48,10 @@ libnsl {
 
     # This functions are needed by the NIS+ tools and rpc.nisd,
     # they should never be used in a normal user program !
-    __do_niscall2;        __free_fdresult;     __nis_default_access;
-    __nis_default_group;  __nis_default_owner; __nis_default_ttl;
-    __nis_finddirectory;  __nis_hash;
+    __free_fdresult;      __nis_default_access; __nis_default_group;  
+    __nis_default_owner;  __nis_default_ttl;   __nis_finddirectory;  
+    __nis_hash;           __nisbind_connect;   __nisbind_create;
+    __nisbind_destroy;    __nisbind_next;
     readColdStartFile;    writeColdStartFile;
   }
 }
diff --git a/nis/nis_call.c b/nis/nis_call.c
index 94144d50ea..ce7607f4e1 100644
--- a/nis/nis_call.c
+++ b/nis/nis_call.c
@@ -60,8 +60,8 @@ inetstr2int (const char *str)
   return inet_addr (buffer);
 }
 
-static void
-__bind_destroy (dir_binding *bind)
+void
+__nisbind_destroy (dir_binding *bind)
 {
   if (bind->clnt != NULL)
     {
@@ -71,8 +71,8 @@ __bind_destroy (dir_binding *bind)
     }
 }
 
-static nis_error
-__bind_next (dir_binding *bind)
+nis_error
+__nisbind_next (dir_binding *bind)
 {
   u_int j;
 
@@ -91,8 +91,7 @@ __bind_next (dir_binding *bind)
        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)
+      if (bind->server_val[bind->server_used].ep.ep_val[j].proto[0] == '-')
 	{
 	  bind->current_ep = j;
 	  return NIS_SUCCESS;
@@ -115,8 +114,8 @@ __bind_next (dir_binding *bind)
   return NIS_FAIL;
 }
 
-static nis_error
-__bind_connect (dir_binding *dbp)
+nis_error
+__nisbind_connect (dir_binding *dbp)
 {
   nis_server *serv;
 
@@ -157,7 +156,7 @@ __bind_connect (dir_binding *dbp)
 
   if (dbp->use_auth)
     {
-      if (serv->key_type == NIS_PK_DH && key_secretkey_is_set ())
+      if (serv->key_type == NIS_PK_DH)
 	{
 	  char netname[MAXNETNAMELEN+1];
 	  char *p;
@@ -180,9 +179,9 @@ __bind_connect (dir_binding *dbp)
   return NIS_SUCCESS;
 }
 
-static nis_error
-__bind_create (dir_binding *dbp, const nis_server *serv_val, u_int serv_len,
-	       u_long flags, cache2_info *cinfo)
+nis_error
+__nisbind_create (dir_binding *dbp, const nis_server *serv_val, u_int serv_len,
+		  u_long flags)
 {
   dbp->clnt = NULL;
 
@@ -208,54 +207,34 @@ __bind_create (dir_binding *dbp, const nis_server *serv_val, u_int serv_len,
   dbp->trys = 1;
 
   dbp->class = -1;
-  if (cinfo != NULL && cinfo->server_used >= 0)
-    {
-      dbp->server_used = cinfo->server_used;
-      dbp->current_ep = cinfo->current_ep;
-      dbp->class = cinfo->class;
-    }
-  else if (__nis_findfastest (dbp) < 1)
+  if (__nis_findfastest (dbp) < 1)
     {
-      __bind_destroy (dbp);
+      __nisbind_destroy (dbp);
       return NIS_NAMEUNREACHABLE;
     }
 
   return NIS_SUCCESS;
 }
 
+/* __nisbind_connect (dbp) must be run before calling this function !
+   So we could use the same binding twice */
 nis_error
-__do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
-	       xdrproc_t xargs, caddr_t req, xdrproc_t xres, caddr_t resp,
-	       u_long flags, nis_cb *cb, cache2_info *cinfo)
+__do_niscall3 (dir_binding *dbp, u_long prog, xdrproc_t xargs, caddr_t req,
+	       xdrproc_t xres, caddr_t resp, u_long flags, nis_cb *cb)
 {
   enum clnt_stat result;
   nis_error retcode;
-  dir_binding dbp;
 
-  if (flags & MASTER_ONLY)
-    server_len = 1;
-
-  if (__bind_create (&dbp, server, server_len, flags, cinfo) != NIS_SUCCESS)
+  if (dbp == NULL)
     return NIS_NAMEUNREACHABLE;
-  while (__bind_connect (&dbp) != NIS_SUCCESS)
-    {
-      if (__bind_next (&dbp) != NIS_SUCCESS)
-	{
-	  __bind_destroy (&dbp);
-	  return NIS_NAMEUNREACHABLE;
-	}
-    }
 
   do
     {
     again:
-      result = clnt_call (dbp.clnt, prog, xargs, req, xres, resp, RPCTIMEOUT);
+      result = clnt_call (dbp->clnt, prog, xargs, req, xres, resp, RPCTIMEOUT);
 
       if (result != RPC_SUCCESS)
-	{
-	  __bind_destroy (&dbp);
-	  retcode = NIS_RPCERROR;
-	}
+	retcode = NIS_RPCERROR;
       else
 	{
 	  switch (prog)
@@ -264,11 +243,11 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
 	      if ((((nis_result *)resp)->status == NIS_CBRESULTS) &&
 		  (cb != NULL))
 		{
-		  __nis_do_callback(&dbp, &((nis_result *)resp)->cookie, cb);
+		  __nis_do_callback(dbp, &((nis_result *)resp)->cookie, cb);
 		  break;
 		}
-	      /* Yes, this is correct. If we doesn't have to start
-		 a callback, look if we have to search another server */
+	      /* Yes, the missing break is correct. If we doesn't have to
+		 start a callback, look if we have to search another server */
 	    case NIS_LOOKUP:
 	    case NIS_ADD:
 	    case NIS_MODIFY:
@@ -278,19 +257,16 @@ __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 *)resp)->status == NIS_NOTFOUND) ||
+	      if ((((nis_result *)resp)->status == NIS_SYSTEMERROR) ||
 		  (((nis_result *)resp)->status == NIS_NOSUCHNAME) ||
 		  (((nis_result *)resp)->status == NIS_NOT_ME))
 		{
-		  if (__bind_next (&dbp) == NIS_SUCCESS)
+		  if (__nisbind_next (dbp) == NIS_SUCCESS)
 		    {
-		      while (__bind_connect (&dbp) != NIS_SUCCESS)
+		      while (__nisbind_connect (dbp) != NIS_SUCCESS)
 			{
-			  if (__bind_next (&dbp) != NIS_SUCCESS)
-			    {
-			      __bind_destroy (&dbp);
+			  if (__nisbind_next (dbp) != NIS_SUCCESS)
 			      return NIS_SUCCESS;
-			    }
 			}
 		    }
 		  else
@@ -299,19 +275,16 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
 		}
 	      break;
 	    case NIS_FINDDIRECTORY:
-	      if ((((fd_result *)resp)->status == NIS_NOTFOUND) ||
+	      if ((((fd_result *)resp)->status == NIS_SYSTEMERROR) ||
 		  (((fd_result *)resp)->status == NIS_NOSUCHNAME) ||
 		  (((fd_result *)resp)->status == NIS_NOT_ME))
 		{
-		  if (__bind_next (&dbp) == NIS_SUCCESS)
+		  if (__nisbind_next (dbp) == NIS_SUCCESS)
 		    {
-		      while (__bind_connect (&dbp) != NIS_SUCCESS)
+		      while (__nisbind_connect (dbp) != NIS_SUCCESS)
 			{
-			  if (__bind_next (&dbp) != NIS_SUCCESS)
-			    {
-			      __bind_destroy (&dbp);
-			      return NIS_SUCCESS;
-			    }
+			  if (__nisbind_next (dbp) != NIS_SUCCESS)
+			    return NIS_SUCCESS;
 			}
 		    }
 		  else
@@ -321,19 +294,16 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
 	      break;
 	    case NIS_DUMPLOG: /* log_result */
 	    case NIS_DUMP:
-	      if ((((log_result *)resp)->lr_status == NIS_NOTFOUND) ||
+	      if ((((log_result *)resp)->lr_status == NIS_SYSTEMERROR) ||
 		  (((log_result *)resp)->lr_status == NIS_NOSUCHNAME) ||
 		  (((log_result *)resp)->lr_status == NIS_NOT_ME))
 		{
-		  if (__bind_next (&dbp) == NIS_SUCCESS)
+		  if (__nisbind_next (dbp) == NIS_SUCCESS)
 		    {
-		      while (__bind_connect (&dbp) != NIS_SUCCESS)
+		      while (__nisbind_connect (dbp) != NIS_SUCCESS)
 			{
-			  if (__bind_next (&dbp) != NIS_SUCCESS)
-			    {
-			      __bind_destroy (&dbp);
-			      return NIS_SUCCESS;
-			    }
+			  if (__nisbind_next (dbp) != NIS_SUCCESS)
+			    return NIS_SUCCESS;
 			}
 		    }
 		  else
@@ -344,7 +314,6 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
 	    default:
 	      break;
 	    }
-	  __bind_destroy (&dbp);
 	  retcode = NIS_SUCCESS;
 	}
     }
@@ -353,9 +322,37 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
   return retcode;
 }
 
+nis_error
+__do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
+	       xdrproc_t xargs, caddr_t req, xdrproc_t xres, caddr_t resp,
+	       u_long flags, nis_cb *cb)
+{
+  dir_binding dbp;
+  nis_error status;
+
+  if (flags & MASTER_ONLY)
+    server_len = 1;
+
+  status = __nisbind_create (&dbp, server, server_len, flags);
+  if (status != NIS_SUCCESS)
+    return status;
+
+  while (__nisbind_connect (&dbp) != NIS_SUCCESS)
+    {
+      if (__nisbind_next (&dbp) != NIS_SUCCESS)
+	return NIS_NAMEUNREACHABLE;
+    }
+
+  status = __do_niscall3 (&dbp, prog, xargs, req, xres, resp, flags, cb);
+
+  __nisbind_destroy (&dbp);
+
+  return status;
+
+}
+
 static directory_obj *
-rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags,
-	       nis_error *status)
+rec_dirsearch (const_nis_name name, directory_obj *dir, nis_error *status)
 {
   fd_result *fd_res;
   XDR xdrs;
@@ -396,7 +393,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, status);
+	    return rec_dirsearch (name, obj, status);
 	  }
 	else
 	  {
@@ -461,7 +458,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, status);
+	    return rec_dirsearch (name, obj, status);
 	  }
       }
     break;
@@ -478,7 +475,7 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags,
 /* We try to query the current server for the searched object,
    maybe he know about it ? */
 static directory_obj *
-first_shoot (const_nis_name name, directory_obj *dir, u_long flags)
+first_shoot (const_nis_name name, directory_obj *dir)
 {
   directory_obj *obj;
   fd_result *fd_res;
@@ -516,51 +513,57 @@ first_shoot (const_nis_name name, directory_obj *dir, u_long flags)
 }
 
 nis_error
-__do_niscall (const_nis_name name, u_long prog, xdrproc_t xargs,
-	      caddr_t req, xdrproc_t xres, caddr_t resp, u_long flags,
-	      nis_cb *cb)
+__nisfind_server (const_nis_name name, directory_obj **dir)
 {
-  nis_error retcode;
-  directory_obj *dir = NULL;
-  nis_server *server;
-  u_int server_len;
-  cache2_info cinfo = {-1, -1, -1};
-  int saved_errno = errno;
-
   if (name == NULL)
     return NIS_BADNAME;
 
+#if 0
   /* Search in local cache. In the moment, we ignore the fastest server */
   if (!(flags & NO_CACHE))
     dir = __nis_cache_search (name, flags, &cinfo);
+#endif
 
-  if (dir == NULL)
+  if (*dir == NULL)
     {
       nis_error status;
       directory_obj *obj;
 
-      dir = readColdStartFile ();
-      if (dir == NULL) /* No /var/nis/NIS_COLD_START->no NIS+ installed */
-	{
-	  __set_errno (saved_errno);
-	  return NIS_UNAVAIL;
-	}
+      *dir = readColdStartFile ();
+      if (*dir == NULL) /* No /var/nis/NIS_COLD_START->no NIS+ installed */
+	return NIS_UNAVAIL;
 
       /* Try at first, if servers in "dir" know our object */
-      obj = first_shoot (name, dir, flags);
+      obj = first_shoot (name, *dir);
       if (obj == NULL)
 	{
-	  dir = rec_dirsearch (name, dir, flags, &status);
-	  if (dir == NULL)
-	    {
-	      __set_errno (saved_errno);
-	      return status;
-	    }
+	  *dir = rec_dirsearch (name, *dir, &status);
+	  if (*dir == NULL)
+	    return status;
 	}
       else
-	dir = obj;
+	*dir = obj;
     }
 
+  return NIS_SUCCESS;
+}
+
+nis_error
+__do_niscall (const_nis_name name, u_long prog, xdrproc_t xargs,
+	      caddr_t req, xdrproc_t xres, caddr_t resp, u_long flags,
+	      nis_cb *cb)
+{
+  nis_error retcode;
+  dir_binding bptr;
+  directory_obj *dir = NULL;
+  nis_server *server;
+  u_int server_len;
+  int saved_errno = errno;
+
+  retcode = __nisfind_server (name, &dir);
+  if (retcode != NIS_SUCCESS)
+    return retcode;
+
   if (flags & MASTER_ONLY)
     {
       server = dir->do_servers.do_servers_val;
@@ -572,9 +575,22 @@ __do_niscall (const_nis_name name, u_long prog, xdrproc_t xargs,
       server_len = dir->do_servers.do_servers_len;
     }
 
+  retcode = __nisbind_create (&bptr, server, server_len, flags);
+  if (retcode == NIS_SUCCESS)
+    {
+      while (__nisbind_connect (&bptr) != NIS_SUCCESS)
+	{
+	  if (__nisbind_next (&bptr) != NIS_SUCCESS)
+	    {
+	      nis_free_directory (dir);
+	      __nisbind_destroy (&bptr);
+	      return NIS_NAMEUNREACHABLE;
+	    }
+	}
+      retcode = __do_niscall3 (&bptr, prog, xargs, req, xres, resp, flags, cb);
 
-  retcode = __do_niscall2 (server, server_len, prog, xargs, req, xres, resp,
-			   flags, cb, &cinfo);
+      __nisbind_destroy (&bptr);
+    }
 
   nis_free_directory (dir);
 
diff --git a/nis/nis_checkpoint.c b/nis/nis_checkpoint.c
index f1e860f7b8..15bae8be22 100644
--- a/nis/nis_checkpoint.c
+++ b/nis/nis_checkpoint.c
@@ -58,7 +58,7 @@ nis_checkpoint(const_nis_name dirname)
 	  if (__do_niscall2 (&NIS_RES_OBJECT(res2)->DI_data.do_servers.do_servers_val[i],
 			     1, NIS_CHECKPOINT, (xdrproc_t) _xdr_nis_name,
 			     (caddr_t) &dirname, (xdrproc_t) _xdr_cp_result,
-			     (caddr_t) &cpres, 0, NULL, NULL) != NIS_SUCCESS)
+			     (caddr_t) &cpres, 0, NULL) != NIS_SUCCESS)
 	    NIS_RES_STATUS (res) = NIS_RPCERROR;
 	  else
 	    {
diff --git a/nis/nis_file.c b/nis/nis_file.c
index 94fa4eb865..0ffac68fe2 100644
--- a/nis/nis_file.c
+++ b/nis/nis_file.c
@@ -31,18 +31,26 @@ readColdStartFile (void)
   XDR xdrs;
   FILE *in;
   bool_t status;
-  directory_obj obj;
+  directory_obj *obj = calloc (1, sizeof (directory_obj));
+
+  if (obj == NULL)
+    return NULL;
 
   in = fopen (cold_start_file, "rb");
   if (in == NULL)
     return NULL;
-  memset (&obj, '\0', sizeof (obj));
   xdrstdio_create (&xdrs, in, XDR_DECODE);
-  status = _xdr_directory_obj (&xdrs, &obj);
+  status = _xdr_directory_obj (&xdrs, obj);
   xdr_destroy (&xdrs);
   fclose (in);
 
-  return status ? nis_clone_directory (&obj, NULL) : NULL;
+  if (status)
+    return obj;
+  else
+    {
+      nis_free_directory (obj);
+      return NULL;
+    }
 }
 
 bool_t
@@ -70,19 +78,27 @@ nis_read_obj (const char *name)
   XDR xdrs;
   FILE *in;
   bool_t status;
-  nis_object obj;
+  nis_object *obj = calloc (1, sizeof (nis_object));
+
+  if (obj == NULL)
+    return NULL;
 
   in = fopen (name, "rb");
   if (in == NULL)
     return NULL;
 
-  memset (&obj, '\0', sizeof (obj));
   xdrstdio_create (&xdrs, in, XDR_DECODE);
-  status =_xdr_nis_object (&xdrs, &obj);
+  status =_xdr_nis_object (&xdrs, obj);
   xdr_destroy (&xdrs);
   fclose (in);
 
-  return status ? nis_clone_object (&obj, NULL) : NULL;
+  if (status)
+    return obj;
+  else
+    {
+      nis_free_object (obj);
+      return NULL;
+    }
 }
 
 bool_t
diff --git a/nis/nis_findserv.c b/nis/nis_findserv.c
index 832b6a541d..5b6a74981c 100644
--- a/nis/nis_findserv.c
+++ b/nis/nis_findserv.c
@@ -110,8 +110,25 @@ struct findserv_req
 };
 
 long
-__nis_findfastest (dir_binding * bind)
+__nis_findfastest (dir_binding *bind)
 {
+#if 0
+  unsigned long i, j;
+
+  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 ((bind->server_val[i].ep.ep_val[j].proto == NULL) ||
+	    (bind->server_val[i].ep.ep_val[j].proto[0] ==  '-') ||
+	    (bind->server_val[i].ep.ep_val[j].proto[0] == '\0'))
+	  {
+	    bind->server_used = i;
+	    bind->current_ep = j;
+	    return 1;
+	  }
+
+  return 0;
+#else
   const struct timeval TIMEOUT50 = {5, 0};
   const struct timeval TIMEOUT00 = {0, 0};
   struct findserv_req **pings;
@@ -137,7 +154,7 @@ __nis_findfastest (dir_binding * bind)
     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 ((bind->server_val[i].ep.ep_val[j].proto == NULL) ||
-	    (strcmp (bind->server_val[i].ep.ep_val[j].proto, "-") == 0) ||
+	    (bind->server_val[i].ep.ep_val[j].proto[0] == '-') ||
 	    (bind->server_val[i].ep.ep_val[j].proto[0] == '\0'))
 	  {
 	    sin.sin_addr.s_addr =
@@ -228,4 +245,5 @@ __nis_findfastest (dir_binding * bind)
   free (pings);
 
   return found;
+#endif
 }
diff --git a/nis/nis_intern.h b/nis/nis_intern.h
index bea4e272ce..9f515bb460 100644
--- a/nis/nis_intern.h
+++ b/nis/nis_intern.h
@@ -24,31 +24,6 @@
 
 __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 ? */
-  u_int class;                   /* From which class is server_val ? */
-  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 ? */
-  struct sockaddr_in addr;       /* Server's IP address */
-  int socket;                    /* Server's local socket */
-};
-typedef struct dir_binding dir_binding;
-
-struct cache2_info
-{
-  long server_used;
-  long current_ep;
-  long class;
-};
-typedef struct cache2_info cache2_info;
-
 struct nis_cb
   {
     nis_server *serv;
@@ -66,8 +41,7 @@ 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,
-				     u_long flags, nis_cb *cb,
-				     cache2_info *cinfo));
+				     u_long flags, nis_cb *cb));
 extern nis_error __do_niscall __P ((const_nis_name name, u_long prog,
 				    xdrproc_t xargs, caddr_t req,
 				    xdrproc_t xres, caddr_t resp,
@@ -81,13 +55,6 @@ extern struct nis_cb *__nis_create_callback
 	    const void *userdata, u_long flags));
 extern nis_error __nis_destroy_callback __P ((struct nis_cb *cb));
 
-#ifdef _LIBC
-/* NIS+ Cache functions */
-extern directory_obj *__nis_cache_search __P ((const_nis_name name,
-					       u_long flags,
-					       cache2_info *cinfo));
-#endif
-
 __END_DECLS
 
 #endif
diff --git a/nis/nis_lookup.c b/nis/nis_lookup.c
index 6a2198ac21..df16cceeac 100644
--- a/nis/nis_lookup.c
+++ b/nis/nis_lookup.c
@@ -25,20 +25,20 @@
 nis_result *
 nis_lookup (const_nis_name name, const u_long flags)
 {
-  nis_result *res;
+  nis_result *res = calloc (1, sizeof (nis_result));
   struct ns_request req;
   nis_name *names;
   nis_error status;
+  int link_first_try = 0;
   int count_links = 0;	 /* We will follow only 16 links in the deep */
   int done = 0;
   int name_nr = 0;
   nis_name namebuf[2] = {NULL, NULL};
 
-  res = calloc (1, sizeof (nis_result));
   if (res == NULL)
     return NULL;
 
-  if (flags & EXPAND_NAME)
+  if ((flags & EXPAND_NAME) && (name[strlen (name) - 1] != '.'))
     {
       names = nis_getnames (name);
       if (names == NULL)
@@ -56,51 +56,141 @@ nis_lookup (const_nis_name name, const u_long flags)
   req.ns_name = names[0];
   while (!done)
     {
+      dir_binding bptr;
+      directory_obj *dir = NULL;
       req.ns_object.ns_object_len = 0;
       req.ns_object.ns_object_val = NULL;
-      memset (res, '\0', sizeof (nis_result));
 
-      status = __do_niscall (req.ns_name, NIS_LOOKUP,
-			     (xdrproc_t) _xdr_ns_request,
-			     (caddr_t) & req,
-			     (xdrproc_t) _xdr_nis_result,
-			     (caddr_t) res, flags, NULL);
+      status = __nisfind_server (req.ns_name, &dir);
       if (status != NIS_SUCCESS)
-	NIS_RES_STATUS (res) = status;
+	{
+	  NIS_RES_STATUS (res) = status;
+	  return res;
+	}
 
-      switch (NIS_RES_STATUS (res))
+      status = __nisbind_create (&bptr, dir->do_servers.do_servers_val,
+				 dir->do_servers.do_servers_len, flags);
+      if (status != NIS_SUCCESS)
 	{
-	case NIS_PARTIAL:
-	case NIS_SUCCESS:
-	case NIS_S_SUCCESS:
-	  if (__type_of(NIS_RES_OBJECT (res)) == NIS_LINK_OBJ &&
-	      flags & FOLLOW_LINKS) /* We are following links */
+	  NIS_RES_STATUS (res) = status;
+	  nis_free_directory (dir);
+	  return res;
+	}
+
+      while (__nisbind_connect (&bptr) != NIS_SUCCESS)
+	{
+	  if (__nisbind_next (&bptr) != NIS_SUCCESS)
+	    {
+	      __nisbind_destroy (&bptr);
+	      nis_free_directory (dir);
+	      NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
+	      return res;
+	    }
+	}
+
+      do
+	{
+	  static struct timeval RPCTIMEOUT = {10, 0};
+	  enum clnt_stat result;
+
+	again:
+	  result = clnt_call (bptr.clnt, NIS_LOOKUP,
+			      (xdrproc_t) _xdr_ns_request,
+			      (caddr_t) &req, (xdrproc_t) _xdr_nis_result,
+			      (caddr_t) res, RPCTIMEOUT);
+
+	  if (result != RPC_SUCCESS)
+	    status = NIS_RPCERROR;
+	  else
 	    {
-	      /* if we hit the link limit, bail */
-	      if (count_links > NIS_MAXLINKS)
+	      if (NIS_RES_STATUS (res) == NIS_SUCCESS)
 		{
-		  NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
-		  ++done;
-		  break;
+		    if (__type_of(NIS_RES_OBJECT (res)) == NIS_LINK_OBJ &&
+			flags & FOLLOW_LINKS) /* We are following links */
+		      {
+			if (count_links)
+			  free (req.ns_name);
+			/* if we hit the link limit, bail */
+			if (count_links > NIS_MAXLINKS)
+			  {
+			    NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
+			    break;
+			  }
+			++count_links;
+			req.ns_name =
+			  strdup (NIS_RES_OBJECT (res)->LI_data.li_name);
+			nis_freeresult (res);
+			res = calloc (1, sizeof (nis_result));
+			if (res == NULL)
+			  {
+			    __nisbind_destroy (&bptr);
+			    nis_free_directory (dir);
+			    return NULL;
+			  }
+			link_first_try = 1; /* Try at first the old binding */
+			goto again;
+		      }
 		}
-	      if (count_links)
-		free (req.ns_name);
-	      ++count_links;
-	      req.ns_name = strdup (NIS_RES_OBJECT (res)->LI_data.li_name);
-	      nis_freeresult (res);
-	      res = calloc (1, sizeof (nis_result));
-	      if (res == NULL)
-		return NULL;
+	      else
+		if ((NIS_RES_STATUS (res) == NIS_SYSTEMERROR) ||
+		    (NIS_RES_STATUS (res) == NIS_NOSUCHNAME) ||
+		    (NIS_RES_STATUS (res) == NIS_NOT_ME))
+		  {
+		    if (link_first_try)
+		      {
+			__nisbind_destroy (&bptr);
+			nis_free_directory (dir);
+
+			if (__nisfind_server (req.ns_name, &dir) != NIS_SUCCESS)
+			  return res;
+
+			if (__nisbind_create (&bptr,
+					      dir->do_servers.do_servers_val,
+					      dir->do_servers.do_servers_len,
+					      flags) != NIS_SUCCESS)
+			  {
+			    nis_free_directory (dir);
+			    return res;
+			  }
+		      }
+		    else
+		      if (__nisbind_next (&bptr) != NIS_SUCCESS)
+			break; /* No more servers to search */
+
+		    while (__nisbind_connect (&bptr) != NIS_SUCCESS)
+		      {
+			if (__nisbind_next (&bptr) != NIS_SUCCESS)
+			  {
+			    __nisbind_destroy (&bptr);
+			    nis_free_directory (dir);
+			    return res;
+			  }
+		      }
+		    goto again;
+		  }
+	      break;
 	    }
-	  else
-	    ++done;
-	  break;
-	case NIS_CBRESULTS:
-	  /* The callback is handled in __do_niscall2 */
-	  ++done;
-	  break;
-	case NIS_UNAVAIL:
-	  /* NIS+ is not installed, or all servers are down */
+	  link_first_try = 0; /* Set it back */
+	  status= NIS_SUCCESS;
+	}
+      while ((flags & HARD_LOOKUP) && status == NIS_RPCERROR);
+
+      __nisbind_destroy (&bptr);
+      nis_free_directory (dir);
+
+      if (status != NIS_SUCCESS)
+	{
+	  NIS_RES_STATUS (res) = status;
+	  return res;
+	}
+
+      switch (NIS_RES_STATUS (res))
+	{
+	case NIS_PARTIAL:
+	case NIS_SUCCESS:
+	case NIS_S_SUCCESS:
+	case NIS_LINKNAMEERROR: /* We follow to max links */
+	case NIS_UNAVAIL: /* NIS+ is not installed, or all servers are down */
 	  ++done;
 	  break;
 	default:
diff --git a/nis/nis_mkdir.c b/nis/nis_mkdir.c
index 71fc4ba877..5d40daebc5 100644
--- a/nis/nis_mkdir.c
+++ b/nis/nis_mkdir.c
@@ -35,7 +35,7 @@ nis_mkdir (const_nis_name dir, const nis_server *server)
     res2 = __do_niscall2 (server, 1, NIS_MKDIR,
 			  (xdrproc_t) _xdr_nis_name,
 			  (caddr_t) &dir, (xdrproc_t) _xdr_nis_error,
-			  (caddr_t) &res, 0, NULL, NULL);
+			  (caddr_t) &res, 0, NULL);
   if (res2 != NIS_SUCCESS)
     return res2;
 
diff --git a/nis/nis_ping.c b/nis/nis_ping.c
index 1becd4bf89..3fc87551f5 100644
--- a/nis/nis_ping.c
+++ b/nis/nis_ping.c
@@ -62,7 +62,7 @@ nis_ping (const_nis_name dirname, u_long utime, const nis_object *dirobj)
     __do_niscall2 (&obj->DI_data.do_servers.do_servers_val[i], 1,
 		   NIS_PING, (xdrproc_t) _xdr_ping_args,
 		   (caddr_t) &args, (xdrproc_t) xdr_void,
-		   (caddr_t) NULL, 0, NULL, NULL);
+		   (caddr_t) NULL, 0, NULL);
   if (res)
     nis_freeresult (res);
 }
diff --git a/nis/nis_rmdir.c b/nis/nis_rmdir.c
index 1f3e91874c..0cd4458091 100644
--- a/nis/nis_rmdir.c
+++ b/nis/nis_rmdir.c
@@ -33,7 +33,7 @@ nis_rmdir (const_nis_name dir, const nis_server *server)
   res2 = __do_niscall2 (server, 1, NIS_RMDIR,
 			(xdrproc_t) _xdr_nis_name,
 			(caddr_t) &dir, (xdrproc_t) _xdr_nis_error,
-			(caddr_t) &res, 0, NULL, NULL);
+			(caddr_t) &res, 0, NULL);
   if (res2 != NIS_SUCCESS)
     return res2;
 
diff --git a/nis/nis_server.c b/nis/nis_server.c
index aa0f05eb39..84cd5fb827 100644
--- a/nis/nis_server.c
+++ b/nis/nis_server.c
@@ -41,7 +41,7 @@ nis_servstate (const nis_server *serv, const nis_tag *tags,
 
   if (__do_niscall2 (serv, 1, NIS_SERVSTATE, (xdrproc_t) _xdr_nis_taglist,
 		     (caddr_t) &taglist, (xdrproc_t) _xdr_nis_taglist,
-		     (caddr_t) &tagres, 0, NULL, NULL) != RPC_SUCCESS)
+		     (caddr_t) &tagres, 0, NULL) != RPC_SUCCESS)
     return NIS_RPCERROR;
 
   *result = tagres.tags.tags_val;
@@ -67,7 +67,7 @@ nis_stats (const nis_server *serv, const nis_tag *tags,
 
   if (__do_niscall2 (serv, 1, NIS_STATUS, (xdrproc_t) _xdr_nis_taglist,
 		     (caddr_t) &taglist, (xdrproc_t) _xdr_nis_taglist,
-		     (caddr_t) &tagres, 0, NULL, NULL) != RPC_SUCCESS)
+		     (caddr_t) &tagres, 0, NULL) != RPC_SUCCESS)
     return NIS_RPCERROR;
 
   *result = tagres.tags.tags_val;
diff --git a/nis/nis_table.c b/nis/nis_table.c
index ed4b3740dd..e0885ca024 100644
--- a/nis/nis_table.c
+++ b/nis/nis_table.c
@@ -110,6 +110,40 @@ __create_ib_request (const_nis_name name, u_long flags)
   return ibreq;
 }
 
+static struct timeval RPCTIMEOUT = {10, 0};
+
+static char *
+__get_tablepath (char *name, dir_binding *bptr)
+{
+  enum clnt_stat result;
+  nis_result *res = calloc (1, sizeof (nis_result));
+  struct ns_request req;
+
+  if (res == NULL)
+    return NULL;
+
+  req.ns_name = name;
+  req.ns_object.ns_object_len = 0;
+  req.ns_object.ns_object_val = NULL;
+
+  result = clnt_call (bptr->clnt, NIS_LOOKUP, (xdrproc_t) _xdr_ns_request,
+		      (caddr_t) &req, (xdrproc_t) _xdr_nis_result,
+		      (caddr_t) res, RPCTIMEOUT);
+
+  if (result == RPC_SUCCESS && NIS_RES_STATUS (res) == NIS_SUCCESS &&
+      __type_of (NIS_RES_OBJECT (res)) == NIS_TABLE_OBJ)
+    {
+      char *cptr = strdup (NIS_RES_OBJECT (res)->TA_data.ta_path);
+      nis_freeresult (res);
+      return cptr;
+    }
+  else
+    {
+      nis_freeresult (res);
+      return strdup ("");
+    }
+}
+
 nis_result *
 nis_list (const_nis_name name, u_long flags,
 	  int (*callback) (const_nis_name name,
@@ -120,12 +154,16 @@ nis_list (const_nis_name name, u_long flags,
   nis_result *res = NULL;
   ib_request *ibreq;
   int status;
+  enum clnt_stat clnt_status;
   int count_links = 0;		/* We will only follow NIS_MAXLINKS links! */
   int done = 0;
   nis_name *names;
   nis_name namebuf[2] = {NULL, NULL};
   int name_nr = 0;
   nis_cb *cb = NULL;
+  char *tableptr, *tablepath = NULL;
+  int have_tablepath = 0;
+  int first_try = 0; /* Do we try the old binding at first ? */
 
   res = calloc (1, sizeof (nis_result));
   if (res == NULL)
@@ -164,189 +202,230 @@ nis_list (const_nis_name name, u_long flags,
 
   cb = NULL;
 
-  if (flags & FOLLOW_PATH || flags & ALL_RESULTS)
+  while (!done)
     {
-      nis_result *lres;
-      u_long newflags = flags & ~FOLLOW_PATH & ~ALL_RESULTS;
-      char table_path[NIS_MAXPATH + 3];
-      char *ntable, *p;
-      u_long done = 0, failures = 0;
-
-      while (names[name_nr] != NULL && !done)
-	{
-	  lres = nis_lookup (names[name_nr], newflags | NO_AUTHINFO);
-	  if (lres == NULL || NIS_RES_STATUS (lres) != NIS_SUCCESS)
-	    {
-	      NIS_RES_STATUS (res) = NIS_RES_STATUS (lres);
-	      nis_freeresult (lres);
-	      ++name_nr;
-	      continue;
-	    }
-
-	  /* nis_lookup handles FOLLOW_LINKS,
-	     so we must have a table object.*/
-	  if (__type_of (NIS_RES_OBJECT (lres)) != NIS_TABLE_OBJ)
-	    {
-	      nis_freeresult (lres);
-	      NIS_RES_STATUS (res) = NIS_INVALIDOBJ;
-	      break;
-	    }
+      dir_binding bptr;
+      directory_obj *dir = NULL;
 
-	  /* Save the path, discard everything else.  */
-	  p = __stpncpy (table_path, names[name_nr], NIS_MAXPATH);
-	  *p++ = ':';
-	  p = __stpncpy (p, NIS_RES_OBJECT (lres)->TA_data.ta_path,
-			 NIS_MAXPATH - (p - table_path));
-	  *p = '\0';
-	  nis_freeresult (lres);
-	  free (res);
-	  res = NULL;
+      memset (res, '\0', sizeof (nis_result));
 
-	  p = table_path;
+      status = __nisfind_server (ibreq->ibr_name, &dir);
+      if (status != NIS_SUCCESS)
+        {
+          NIS_RES_STATUS (res) = status;
+          return res;
+        }
 
-	  while (((ntable = strsep (&p, ":")) != NULL) && !done)
-	    {
-	      char *c;
+      status = __nisbind_create (&bptr, dir->do_servers.do_servers_val,
+                                 dir->do_servers.do_servers_len, flags);
+      if (status != NIS_SUCCESS)
+        {
+          NIS_RES_STATUS (res) = status;
+          nis_free_directory (dir);
+          return res;
+        }
 
-	      if (res != NULL)
-		nis_freeresult (res);
+      while (__nisbind_connect (&bptr) != NIS_SUCCESS)
+	if (__nisbind_next (&bptr) != NIS_SUCCESS)
+	  {
+	    __nisbind_destroy (&bptr);
+	    nis_free_directory (dir);
+	    NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
+	    return res;
+	  }
 
-	      /* Do the job recursive here!  */
-	      if ((c = strchr(name, ']')) != NULL)
-		{
-		  /* Have indexed name ! */
-		  int index_len = c - name + 2;
-		  char buf[index_len + strlen (ntable) + 1];
-
-		  c = __stpncpy (buf, name, index_len);
-		  strcpy (c, ntable);
-		  res = nis_list (buf, newflags, callback,userdata);
-		}
-	      else
-		res = nis_list (ntable, newflags, callback, userdata);
-	      if (res == NULL)
-		return NULL;
-	      switch (NIS_RES_STATUS (res))
-		{
-		case NIS_SUCCESS:
-		case NIS_CBRESULTS:
-		  if (!(flags & ALL_RESULTS))
-		    done = 1;
-		  break;
-		case NIS_PARTIAL: /* The table is correct, we doesn't found
-				     the entry */
-		  break;
-		default:
-		  if (flags & ALL_RESULTS)
-		    ++failures;
-		  else
-		    done = 1;
-		  break;
-		}
-	    }
-	  if (NIS_RES_STATUS (res) == NIS_SUCCESS && failures)
-	    NIS_RES_STATUS (res) = NIS_S_SUCCESS;
-	  if (NIS_RES_STATUS (res) == NIS_NOTFOUND && failures)
-	    NIS_RES_STATUS (res) = NIS_S_NOTFOUND;
-	  break;
-	}
-    }
-  else
-    {
       if (callback != NULL)
 	{
 	  cb = __nis_create_callback (callback, userdata, flags);
 	  ibreq->ibr_cbhost.ibr_cbhost_len = 1;
 	  ibreq->ibr_cbhost.ibr_cbhost_val = cb->serv;
-	  }
-
-      while (!done)
-	{
-	  memset (res, '\0', sizeof (nis_result));
-
-	  status = __do_niscall (ibreq->ibr_name, NIS_IBLIST,
-				 (xdrproc_t) _xdr_ib_request,
-				 (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
-				 (caddr_t) res, flags, cb);
-	  if (status != NIS_SUCCESS)
-	    NIS_RES_STATUS (res) = status;
+	}
 
-	  switch (NIS_RES_STATUS (res))
-	    {
-	    case NIS_PARTIAL:
-	    case NIS_SUCCESS:
-	    case NIS_S_SUCCESS:
-	      if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ &&
-		  flags & FOLLOW_LINKS)		/* We are following links.  */
-		{
-		  /* If we hit the link limit, bail.  */
-		  if (count_links > NIS_MAXLINKS)
+    again:
+      clnt_status = clnt_call (bptr.clnt, NIS_IBLIST,
+			       (xdrproc_t) _xdr_ib_request, (caddr_t) ibreq,
+			       (xdrproc_t) _xdr_nis_result,
+			       (caddr_t) res, RPCTIMEOUT);
+
+      if (clnt_status != RPC_SUCCESS)
+	NIS_RES_STATUS (res) = NIS_RPCERROR;
+      else
+	switch (NIS_RES_STATUS (res))
+	  { /* start switch */
+	  case NIS_PARTIAL:
+	  case NIS_SUCCESS:
+	  case NIS_S_SUCCESS:
+	    if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ &&
+		flags & FOLLOW_LINKS)		/* We are following links.  */
+	      {
+		free (ibreq->ibr_name);
+		/* If we hit the link limit, bail.  */
+		if (count_links > NIS_MAXLINKS)
+		  {
+		    NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
+		    ++done;
+		    break;
+		  }
+		++count_links;
+		ibreq->ibr_name =
+		  strdup (NIS_RES_OBJECT (res)->LI_data.li_name);
+		if (NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len)
+		  if (ibreq->ibr_srch.ibr_srch_len == 0)
 		    {
-		      NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
-		      ++done;
-		      break;
+		      ibreq->ibr_srch.ibr_srch_len =
+			NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len;
+		      ibreq->ibr_srch.ibr_srch_val =
+			NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_val;
 		    }
-		  if (count_links)
-		    free (ibreq->ibr_name);
-		  ++count_links;
-		  free (ibreq->ibr_name);
-		  ibreq->ibr_name =
-		    strdup (NIS_RES_OBJECT (res)->LI_data.li_name);
-		  if (NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len)
-		    if (ibreq->ibr_srch.ibr_srch_len == 0)
+		nis_freeresult (res);
+		res = calloc (1, sizeof (nis_result));
+		if (res == NULL)
+		  {
+		    if (have_tablepath)
+		      free (tablepath);
+		    __nisbind_destroy (&bptr);
+		    nis_free_directory (dir);
+		    return NULL;
+		  }
+		first_try = 1; /* Try at first the old binding */
+		goto again;
+	      }
+	    else if ((flags & FOLLOW_PATH) &&
+		     NIS_RES_STATUS (res) == NIS_PARTIAL)
+	      {
+		if (!have_tablepath)
+		  {
+		    tablepath = __get_tablepath (ibreq->ibr_name, &bptr);
+		    tableptr = tablepath;
+		    have_tablepath = 1;
+		  }
+		if (tableptr == NULL)
+		  {
+		    ++done;
+		    break;
+		  }
+		free (ibreq->ibr_name);
+		ibreq->ibr_name = strsep (&tableptr, ":");
+		if (ibreq->ibr_name == NULL || ibreq->ibr_name[0] == '\0')
+		  {
+		    ibreq->ibr_name = strdup ("");
+		    ++done;
+		  }
+		else
+		  {
+		    ibreq->ibr_name = strdup (ibreq->ibr_name);
+		    nis_freeresult (res);
+		    res = calloc (1, sizeof (nis_result));
+		    if (res == NULL)
 		      {
-			ibreq->ibr_srch.ibr_srch_len =
-			  NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len;
-			ibreq->ibr_srch.ibr_srch_val =
-			  NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_val;
+			if (have_tablepath)
+			  free (tablepath);
+			__nisbind_destroy (&bptr);
+			nis_free_directory (dir);
+			return NULL;
 		      }
-		  nis_freeresult (res);
-		  res = calloc (1, sizeof (nis_result));
-		}
-	      else
-		++done;
-	      break;
-	    case NIS_CBRESULTS:
-	      /* Calback is handled in nis_call.c (__do_niscall2),
-		 but we have to change the error code */
-	      NIS_RES_STATUS (res) = cb->result;
+		    first_try = 1;
+		    goto again;
+		  }
+	      }
+	    else
 	      ++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)
-		{
-		  free (ibreq->ibr_name);
-		  NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
-		  ++done;
-		  break;
-		}
-	      ++name_nr;
-	      if (names[name_nr] == NULL)
-		{
+	    break;
+	  case NIS_CBRESULTS:
+	    if (cb != NULL)
+	      {
+		__nis_do_callback (&bptr, &res->cookie, cb);
+		NIS_RES_STATUS (res) = cb->result;
+
+		if (!(flags & ALL_RESULTS))
 		  ++done;
-		  break;
-		}
-	      ibreq->ibr_name = names[name_nr];
-	      break;
-	    }
+		else
+		  {
+		    if (!have_tablepath)
+		      {
+			tablepath = __get_tablepath (ibreq->ibr_name, &bptr);
+			tableptr = tablepath;
+			have_tablepath = 1;
+		      }
+		    if (tableptr == NULL)
+		      {
+			++done;
+			break;
+		      }
+		    free (ibreq->ibr_name);
+		    ibreq->ibr_name = strsep (&tableptr, ":");
+		    if (ibreq->ibr_name == NULL || ibreq->ibr_name[0] == '\0')
+		      {
+			ibreq->ibr_name = strdup ("");
+			++done;
+		      }
+		    else
+		      ibreq->ibr_name = strdup (ibreq->ibr_name);
+		  }
+	      }
+	    break;
+	  case NIS_SYSTEMERROR:
+	  case NIS_NOSUCHNAME:
+	  case NIS_NOT_ME:
+	    /* If we had first tried the old binding, do nothing, but
+	       get a new binding */
+	    if (!first_try)
+	      {
+		if (__nisbind_next (&bptr) != NIS_SUCCESS)
+		  {
+		    ++done;
+		    break; /* No more servers to search */
+		  }
+		while (__nisbind_connect (&bptr) != NIS_SUCCESS)
+		  {
+		    if (__nisbind_next (&bptr) != NIS_SUCCESS)
+		      {
+			++done;
+			break; /* No more servers to search */
+		      }
+		  }
+		goto again;
+	      }
+	    break;
+	  default:
+	    if (!first_try)
+	      {
+		/* Try the next domainname if we don't follow a link.  */
+		if (count_links)
+		  {
+		    free (ibreq->ibr_name);
+		    NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
+		    ++done;
+		    break;
+		  }
+		++name_nr;
+		if (names[name_nr] == NULL)
+		  {
+		    ++done;
+		    break;
+		  }
+		ibreq->ibr_name = names[name_nr];
+		first_try = 1; /* Try old binding at first */
+		goto again;
+	      }
+	    break;
+	  }
+      first_try = 0;
+
+      if (cb)
+	{
+	  __nis_destroy_callback (cb);
+	  ibreq->ibr_cbhost.ibr_cbhost_len = 0;
+	  ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
 	}
-    }				/* End of not FOLLOW_PATH.  */
+
+      __nisbind_destroy (&bptr);
+      nis_free_directory (dir);
+    }
 
   if (names != namebuf)
     nis_freenames (names);
 
-  if (cb)
-    {
-      __nis_destroy_callback (cb);
-      ibreq->ibr_cbhost.ibr_cbhost_len = 0;
-      ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
-    }
-
   nis_free_request (ibreq);
 
   return res;
diff --git a/nis/nis_util.c b/nis/nis_util.c
index 656b1a48c1..2b351e7339 100644
--- a/nis/nis_util.c
+++ b/nis/nis_util.c
@@ -38,7 +38,7 @@ __nis_finddirectory (directory_obj *dir, const_nis_name name)
 			  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, NULL, NULL);
+			  (caddr_t) fd_res, NO_AUTHINFO|USE_DGRAM, NULL);
   if (status != NIS_SUCCESS)
     fd_res->status = status;
 
diff --git a/nis/rpcsvc/nislib.h b/nis/rpcsvc/nislib.h
index 016bedc769..60bf8923d8 100644
--- a/nis/rpcsvc/nislib.h
+++ b/nis/rpcsvc/nislib.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
 
@@ -247,6 +247,35 @@ extern u_long __nis_hash __P ((const void *keyarg, register size_t len));
 extern int __nis_lock_cache __P ((void));
 extern int __nis_unlock_cache __P ((void));
 
+/* (XXX INTERNAL FUNCTIONS, ONLY FOR rpc.nisd AND glibc !!) */
+#if defined (NIS_INTERNAL) || defined (_LIBC)
+
+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 ? */
+  u_int class;                   /* From which class is server_val ? */
+  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 ? */
+  struct sockaddr_in addr;       /* Server's IP address */
+  int socket;                    /* Server's local socket */
+};
+typedef struct dir_binding dir_binding;
+
+extern nis_error __nisbind_create __P ((dir_binding *, const nis_server *,
+					u_int, u_long));
+extern nis_error __nisbind_connect __P ((dir_binding *));
+extern nis_error __nisbind_next __P ((dir_binding *));
+extern void __nisbind_destroy __P ((dir_binding *));
+extern nis_error __nisfind_server __P ((const_nis_name, directory_obj **));
+
+#endif
+
 __END_DECLS
 
 #endif	/* __RPCSVC_NISLIB_H__ */
diff --git a/nscd/connections.c b/nscd/connections.c
index 582a6cf8f0..4cf397d201 100644
--- a/nscd/connections.c
+++ b/nscd/connections.c
@@ -427,8 +427,9 @@ gr_send_answer (int conn, struct group *grp)
   struct iovec *vec;
   size_t *len;
   gr_response_header resp;
-  size_t total_len;
+  size_t total_len, sum;
   int nblocks;
+  size_t maxiov;
 
   resp.version = NSCD_VERSION;
   if (grp != NULL)
@@ -501,16 +502,21 @@ gr_send_answer (int conn, struct group *grp)
 	}
     }
 
+#ifdef UIO_MAXIOV
+  maxiov = UIO_MAXIOV;
+#else
+  maxiov = sysconf (_SC_UIO_MAXIOV);
+#endif
+
   /* Send all the data.  */
-  while (nblocks > UIO_MAXIOV)
+  sum = 0;
+  while (nblocks > maxiov)
     {
-      if (writev (sock[conn], vec, UIO_MAXIOV) != total_len)
-	dbg_log (_("write incomplete on send group answer: %s"),
-		 strerror (errno));
-      vec += UIO_MAXIOV;
-      nblocks -= UIO_MAXIOV;
+      sum += writev (sock[conn], vec, maxiov);
+      vec += maxiov;
+      nblocks -= maxiov;
     }
-  if (writev (sock[conn], vec, nblocks) != total_len)
+  if (sum + writev (sock[conn], vec, nblocks) != total_len)
     dbg_log (_("write incomplete on send group answer: %s"),
 	     strerror (errno));
 }
diff --git a/nscd/nscd_getgr_r.c b/nscd/nscd_getgr_r.c
index 85ebb0dc60..ec4f5a1297 100644
--- a/nscd/nscd_getgr_r.c
+++ b/nscd/nscd_getgr_r.c
@@ -99,6 +99,8 @@ __nscd_getgr_r (const char *key, request_type type, struct group *resultbuf,
   request_header req;
   gr_response_header gr_resp;
   ssize_t nbytes;
+  size_t maxiov;
+  size_t sum;
 
   if (sock == -1)
     {
@@ -232,18 +234,21 @@ __nscd_getgr_r (const char *key, request_type type, struct group *resultbuf,
 	      *p++ = '\0';
 	    }
 
-	  while (i > UIO_MAXIOV)
+#ifdef UIO_MAXIOV
+	  maxiov = UIO_MAXIOV;
+#else
+	  maxiov = sysconf (_SC_UIO_MAXIOV);
+#endif
+
+	  sum = 0;
+	  while (i > maxiov)
 	    {
-	      if (__readv (sock, vec, UIO_MAXIOV) != total_len)
-		{
-		  __close (sock);
-		  return -1;
-		}
-	      vec += UIO_MAXIOV;
-	      i -= UIO_MAXIOV;
+	      sum += __readv (sock, vec, maxiov);
+	      vec += maxiov;
+	      i -= maxiov;
 	    }
 
-	  if (__readv (sock, vec, i) != total_len)
+	  if (sum + __readv (sock, vec, i) != total_len)
 	    {
 	      __close (sock);
 	      return -1;
diff --git a/posix/globtest.sh b/posix/globtest.sh
index 919c584b59..ba41fc4896 100755
--- a/posix/globtest.sh
+++ b/posix/globtest.sh
@@ -267,6 +267,15 @@ cat <<"EOF" | cmp - $testout || result=1
 `file1'
 EOF
 
+# Test NOCHECK with non-existing file in subdir.
+${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${common_objpfx}posix/globtest -c "$testdir" "*/blahblah" |
+sort > $testout
+cat <<"EOF" | cmp - $testout || result=1
+`dir1/blahblah'
+`dir2/blahblah'
+EOF
+
 if test $result -eq 0; then
     rm -fr $testdir $testout
 fi
diff --git a/stdio-common/printf-parse.h b/stdio-common/printf-parse.h
index 036b3b4dfe..61468ebdd3 100644
--- a/stdio-common/printf-parse.h
+++ b/stdio-common/printf-parse.h
@@ -19,8 +19,9 @@
 
 #include <ctype.h>
 #include <printf.h>
-#include <string.h>
+#include <stdint.h>
 #include <stddef.h>
+#include <string.h>
 
 #define NDEBUG 1
 #include <assert.h>
@@ -271,7 +272,8 @@ parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec,
   spec->info.is_char = 0;
 
   if (*format == L_('h') || *format == L_('l') || *format == L_('L') ||
-      *format == L_('Z') || *format == L_('q'))
+      *format == L_('Z') || *format == L_('q') || *format == L_('z') ||
+      *format == L_('t') || *format == L_('j'))
     switch (*format++)
       {
       case L_('h'):
@@ -297,11 +299,24 @@ parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec,
 	/* 4.4 uses this for long long.  */
 	spec->info.is_long_double = 1;
 	break;
+      case L_('z'):
       case L_('Z'):
 	/* int's are size_t's.  */
-	assert (sizeof(size_t) <= sizeof(unsigned long long int));
-	spec->info.is_longlong = sizeof(size_t) > sizeof(unsigned long int);
-	spec->info.is_long = sizeof(size_t) > sizeof(unsigned int);
+	assert (sizeof (size_t) <= sizeof (unsigned long long int));
+	spec->info.is_longlong = sizeof (size_t) > sizeof (unsigned long int);
+	spec->info.is_long = sizeof (size_t) > sizeof (unsigned int);
+	break;
+      case L_('t'):
+	assert (sizeof (ptrdiff_t) <= sizeof (unsigned long long int));
+	spec->info.is_longlong = (sizeof (ptrdiff_t)
+				  > sizeof (unsigned long int));
+	spec->info.is_long = sizeof (ptrdiff_t) > sizeof (unsigned int);
+	break;
+      case L_('j'):
+	assert (sizeof (intmax_t) <= sizeof (unsigned long long int));
+	spec->info.is_longlong = (sizeof (intmax_t)
+				  > sizeof (unsigned long int));
+	spec->info.is_long = sizeof (intmax_t) > sizeof (unsigned int);
 	break;
       }
 
diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
index a40acb75d4..a3281c2e0e 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf.c
@@ -20,6 +20,7 @@
 #include <limits.h>
 #include <printf.h>
 #include <stdarg.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <wchar.h>
@@ -250,14 +251,14 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	       0,            0,            0,            0,
 	       0, /* 'a' */ 26,            0, /* 'c' */ 20,
     /* 'd' */ 15, /* 'e' */ 19, /* 'f' */ 19, /* 'g' */ 19,
-    /* 'h' */ 10, /* 'i' */ 15,            0,            0,
+    /* 'h' */ 10, /* 'i' */ 15, /* 'j' */ 28,            0,
     /* 'l' */ 11, /* 'm' */ 24, /* 'n' */ 23, /* 'o' */ 17,
     /* 'p' */ 22, /* 'q' */ 12,            0, /* 's' */ 21,
-	       0, /* 'u' */ 16,            0,            0,
-    /* 'x' */ 18
+    /* 't' */ 27, /* 'u' */ 16,            0,            0,
+    /* 'x' */ 18,            0, /* 'z' */ 13
   };
 
-#define NOT_IN_JUMP_RANGE(Ch) ((Ch) < ' ' || (Ch) > 'x')
+#define NOT_IN_JUMP_RANGE(Ch) ((Ch) < ' ' || (Ch) > 'z')
 #define CHAR_CLASS(Ch) (jump_table[(int) (Ch) - ' '])
 #define JUMP(ChExpr, table)						      \
       do								      \
@@ -272,7 +273,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 
 #define STEP0_3_TABLE							      \
     /* Step 0: at the beginning.  */					      \
-    static const void *step0_jumps[27] =				      \
+    static const void *step0_jumps[29] =				      \
     {									      \
       REF (form_unknown),						      \
       REF (flag_space),		/* for ' ' */				      \
@@ -287,7 +288,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       REF (mod_half),		/* for 'h' */				      \
       REF (mod_long),		/* for 'l' */				      \
       REF (mod_longlong),	/* for 'L', 'q' */			      \
-      REF (mod_size_t),		/* for 'Z' */				      \
+      REF (mod_size_t),		/* for 'z', 'Z' */			      \
       REF (form_percent),	/* for '%' */				      \
       REF (form_integer),	/* for 'd', 'i' */			      \
       REF (form_unsigned),	/* for 'u' */				      \
@@ -300,10 +301,12 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       REF (form_number),	/* for 'n' */				      \
       REF (form_strerror),	/* for 'm' */				      \
       REF (form_wcharacter),	/* for 'C' */				      \
-      REF (form_floathex)	/* for 'A', 'a' */			      \
+      REF (form_floathex),	/* for 'A', 'a' */			      \
+      REF (mod_ptrdiff_t),      /* for 't' */				      \
+      REF (mod_intmax_t),       /* for 'j' */				      \
     };									      \
     /* Step 1: after processing width.  */				      \
-    static const void *step1_jumps[27] =				      \
+    static const void *step1_jumps[29] =				      \
     {									      \
       REF (form_unknown),						      \
       REF (form_unknown),	/* for ' ' */				      \
@@ -318,7 +321,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       REF (mod_half),		/* for 'h' */				      \
       REF (mod_long),		/* for 'l' */				      \
       REF (mod_longlong),	/* for 'L', 'q' */			      \
-      REF (mod_size_t),		/* for 'Z' */				      \
+      REF (mod_size_t),		/* for 'z', 'Z' */			      \
       REF (form_percent),	/* for '%' */				      \
       REF (form_integer),	/* for 'd', 'i' */			      \
       REF (form_unsigned),	/* for 'u' */				      \
@@ -331,10 +334,12 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       REF (form_number),	/* for 'n' */				      \
       REF (form_strerror),	/* for 'm' */				      \
       REF (form_wcharacter),	/* for 'C' */				      \
-      REF (form_floathex)	/* for 'A', 'a' */			      \
+      REF (form_floathex),	/* for 'A', 'a' */			      \
+      REF (mod_ptrdiff_t),      /* for 't' */				      \
+      REF (mod_intmax_t)        /* for 'j' */				      \
     };									      \
     /* Step 2: after processing precision.  */				      \
-    static const void *step2_jumps[27] =				      \
+    static const void *step2_jumps[29] =				      \
     {									      \
       REF (form_unknown),						      \
       REF (form_unknown),	/* for ' ' */				      \
@@ -349,7 +354,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       REF (mod_half),		/* for 'h' */				      \
       REF (mod_long),		/* for 'l' */				      \
       REF (mod_longlong),	/* for 'L', 'q' */			      \
-      REF (mod_size_t),		/* for 'Z' */				      \
+      REF (mod_size_t),		/* for 'z', 'Z' */			      \
       REF (form_percent),	/* for '%' */				      \
       REF (form_integer),	/* for 'd', 'i' */			      \
       REF (form_unsigned),	/* for 'u' */				      \
@@ -362,10 +367,12 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       REF (form_number),	/* for 'n' */				      \
       REF (form_strerror),	/* for 'm' */				      \
       REF (form_wcharacter),	/* for 'C' */				      \
-      REF (form_floathex)	/* for 'A', 'a' */			      \
+      REF (form_floathex),	/* for 'A', 'a' */			      \
+      REF (mod_ptrdiff_t),      /* for 't' */				      \
+      REF (mod_intmax_t)        /* for 'j' */				      \
     };									      \
     /* Step 3a: after processing first 'h' modifier.  */		      \
-    static const void *step3a_jumps[27] =				      \
+    static const void *step3a_jumps[29] =				      \
     {									      \
       REF (form_unknown),						      \
       REF (form_unknown),	/* for ' ' */				      \
@@ -380,7 +387,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       REF (mod_halfhalf),	/* for 'h' */				      \
       REF (form_unknown),	/* for 'l' */				      \
       REF (form_unknown),	/* for 'L', 'q' */			      \
-      REF (form_unknown),	/* for 'Z' */				      \
+      REF (form_unknown),	/* for 'z', 'Z' */			      \
       REF (form_percent),	/* for '%' */				      \
       REF (form_integer),	/* for 'd', 'i' */			      \
       REF (form_unsigned),	/* for 'u' */				      \
@@ -393,10 +400,12 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       REF (form_number),	/* for 'n' */				      \
       REF (form_unknown),	/* for 'm' */				      \
       REF (form_unknown),	/* for 'C' */				      \
-      REF (form_unknown)	/* for 'A', 'a' */			      \
+      REF (form_unknown),	/* for 'A', 'a' */			      \
+      REF (form_unknown),       /* for 't' */				      \
+      REF (form_unknown)        /* for 'j' */				      \
     };									      \
     /* Step 3b: after processing first 'l' modifier.  */		      \
-    static const void *step3b_jumps[27] =				      \
+    static const void *step3b_jumps[29] =				      \
     {									      \
       REF (form_unknown),						      \
       REF (form_unknown),	/* for ' ' */				      \
@@ -411,7 +420,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       REF (form_unknown),	/* for 'h' */				      \
       REF (mod_longlong),	/* for 'l' */				      \
       REF (form_unknown),	/* for 'L', 'q' */			      \
-      REF (form_unknown),	/* for 'Z' */				      \
+      REF (form_unknown),	/* for 'z', 'Z' */			      \
       REF (form_percent),	/* for '%' */				      \
       REF (form_integer),	/* for 'd', 'i' */			      \
       REF (form_unsigned),	/* for 'u' */				      \
@@ -424,12 +433,14 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       REF (form_number),	/* for 'n' */				      \
       REF (form_strerror),	/* for 'm' */				      \
       REF (form_wcharacter),	/* for 'C' */				      \
-      REF (form_floathex)	/* for 'A', 'a' */			      \
+      REF (form_floathex),	/* for 'A', 'a' */			      \
+      REF (form_unknown),       /* for 't' */				      \
+      REF (form_unknown)        /* for 'j' */				      \
     }
 
 #define STEP4_TABLE							      \
     /* Step 4: processing format specifier.  */				      \
-    static const void *step4_jumps[27] =				      \
+    static const void *step4_jumps[29] =				      \
     {									      \
       REF (form_unknown),						      \
       REF (form_unknown),	/* for ' ' */				      \
@@ -444,7 +455,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       REF (form_unknown),	/* for 'h' */				      \
       REF (form_unknown),	/* for 'l' */				      \
       REF (form_unknown),	/* for 'L', 'q' */			      \
-      REF (form_unknown),	/* for 'Z' */				      \
+      REF (form_unknown),	/* for 'z', 'Z' */			      \
       REF (form_percent),	/* for '%' */				      \
       REF (form_integer),	/* for 'd', 'i' */			      \
       REF (form_unsigned),	/* for 'u' */				      \
@@ -457,7 +468,9 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       REF (form_number),	/* for 'n' */				      \
       REF (form_strerror),	/* for 'm' */				      \
       REF (form_wcharacter),	/* for 'C' */				      \
-      REF (form_floathex)	/* for 'A', 'a' */			      \
+      REF (form_floathex),	/* for 'A', 'a' */			      \
+      REF (form_unknown),       /* for 't' */				      \
+      REF (form_unknown)        /* for 'j' */				      \
     }
 
 
@@ -1178,6 +1191,16 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       is_long = sizeof (size_t) > sizeof (unsigned int);
       JUMP (*++f, step4_jumps);
 
+    LABEL (mod_ptrdiff_t):
+      is_longlong = sizeof (ptrdiff_t) > sizeof (unsigned long int);
+      is_long = sizeof (ptrdiff_t) > sizeof (unsigned int);
+      JUMP (*++f, step4_jumps);
+
+    LABEL (mod_intmax_t):
+      is_longlong = sizeof (intmax_t) > sizeof (unsigned long int);
+      is_long = sizeof (intmax_t) > sizeof (unsigned int);
+      JUMP (*++f, step4_jumps);
+
       /* Process current format.  */
       while (1)
 	{
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
index bd167b9a5b..ce5e5125f7 100644
--- a/stdio-common/vfscanf.c
+++ b/stdio-common/vfscanf.c
@@ -21,6 +21,7 @@
 #include <ctype.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 #include <wctype.h>
@@ -407,7 +408,8 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	width = -1;
 
       /* Check for type modifiers.  */
-      while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'a' || *f == 'q')
+      while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'a' || *f == 'q'
+	     || *f == 'z' || *f == 't' || *f == 'j')
 	switch (*f++)
 	  {
 	  case 'h':
@@ -459,6 +461,30 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	       arg and fill it in with a malloc'd pointer.  */
 	    flags |= MALLOC;
 	    break;
+	  case 'z':
+	    if (flags & (SHORT|LONGDBL|CHAR))
+	      conv_error ();
+	    if (sizeof (size_t) > sizeof (unsigned long int))
+	      flags |= LONGDBL;
+	    else if (sizeof (size_t) > sizeof (unsigned int))
+	      flags |= LONG;
+	    break;
+	  case 'j':
+	    if (flags & (SHORT|LONGDBL|CHAR))
+	      conv_error ();
+	    if (sizeof (intmax_t) > sizeof (unsigned long int))
+	      flags |= LONGDBL;
+	    else if (sizeof (intmax_t) > sizeof (unsigned int))
+	      flags |= LONG;
+	    break;
+	  case 't':
+	    if (flags & (SHORT|LONGDBL|CHAR))
+	      conv_error ();
+	    if (sizeof (ptrdiff_t) > sizeof (unsigned long int))
+	      flags |= LONGDBL;
+	    else if (sizeof (ptrdiff_t) > sizeof (unsigned int))
+	      flags |= LONG;
+	    break;
 	  }
 
       /* End of the format string?  */
diff --git a/stdlib/strtol.c b/stdlib/strtol.c
index 8db108c2de..2a750d7dc2 100644
--- a/stdlib/strtol.c
+++ b/stdlib/strtol.c
@@ -147,7 +147,7 @@ extern int errno;
 #  define LONG_MAX ((long int) (ULONG_MAX >> 1))
 # endif
 # define STRTOL_LONG_MIN LONG_MIN
-# define STRTOL_LONG_MAX ULONG_MAX
+# define STRTOL_LONG_MAX LONG_MAX
 # define STRTOL_ULONG_MAX ULONG_MAX
 #endif
 
diff --git a/sunrpc/Makefile b/sunrpc/Makefile
index 2ab2577f08..2dac9937f3 100644
--- a/sunrpc/Makefile
+++ b/sunrpc/Makefile
@@ -66,7 +66,8 @@ routines := auth_none auth_unix authuxprot bindrsvprt \
 	    svc_tcp svc_udp xdr xdr_array xdr_float xdr_mem \
 	    xdr_rec xdr_ref xdr_stdio publickey xdr_sizeof \
 	    auth_des authdes_prot des_crypt des_impl des_soft \
-	    key_call key_prot netname openchild rtime svcauth_des xcrypt
+	    key_call key_prot netname openchild rtime svcauth_des xcrypt\
+	    clnt_unix svc_unix
 
 others := rpcinfo
 install-bin := rpcgen
diff --git a/sunrpc/Versions b/sunrpc/Versions
index d956486f9f..98dfbbc79f 100644
--- a/sunrpc/Versions
+++ b/sunrpc/Versions
@@ -59,7 +59,7 @@ libc {
     authdes_create; authdes_getucred; authdes_pk_create;
 
     # c*
-    cbc_crypt;
+    cbc_crypt; clntunix_create;
 
     # d*
     des_setparity;
@@ -87,6 +87,9 @@ libc {
     # r*
     rtime;
 
+    # s*
+    svcunix_create; svcunixfd_create;
+
     # u*
     user2netname;
 
diff --git a/sunrpc/clnt_gen.c b/sunrpc/clnt_gen.c
index b1b35ca50a..f62618bdac 100644
--- a/sunrpc/clnt_gen.c
+++ b/sunrpc/clnt_gen.c
@@ -57,11 +57,27 @@ clnt_create (const char *hostname, u_long prog, u_long vers,
   size_t prtbuflen;
   char *prttmpbuf;
   struct sockaddr_in sin;
+  struct sockaddr_un sun;
   int sock;
   struct timeval tv;
   CLIENT *client;
   int herr;
 
+  if (strcmp (proto, "unix") == 0)
+    {
+      __bzero ((char *)&sun, sizeof (sun));
+      sun.sun_family = AF_UNIX;
+      strcpy (sun.sun_path, hostname);
+      sock = RPC_ANYSOCK;
+      client = clntunix_create (&sun, prog, vers, &sock, 0, 0);
+      if (client == NULL)
+	return NULL;
+      tv.tv_sec = 25;
+      tv.tv_usec = 0;
+      clnt_control (client, CLSET_TIMEOUT, (char *)&tv);
+      return client;
+    }
+
   hstbuflen = 1024;
   hsttmpbuf = __alloca (hstbuflen);
   while (__gethostbyname_r (hostname, &hostbuf, hsttmpbuf, hstbuflen,
diff --git a/sunrpc/clnt_unix.c b/sunrpc/clnt_unix.c
new file mode 100644
index 0000000000..848b752e6b
--- /dev/null
+++ b/sunrpc/clnt_unix.c
@@ -0,0 +1,573 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * clnt_unix.c, Implements a TCP/IP based, client side RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * TCP based RPC supports 'batched calls'.
+ * A sequence of calls may be batched-up in a send buffer.  The rpc call
+ * return immediately to the client even though the call was not necessarily
+ * sent.  The batching occurs if the results' xdr routine is NULL (0) AND
+ * the rpc timeout value is zero (see clnt.h, rpc).
+ *
+ * Clients should NOT casually batch calls that in fact return results; that is,
+ * the server side should be aware that a call is batched and not produce any
+ * return message.  Batched calls that produce many result messages can
+ * deadlock (netlock) the client and the server....
+ *
+ * Now go hang yourself.
+ */
+
+#include <netdb.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <rpc/rpc.h>
+#include <sys/uio.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <rpc/pmap_clnt.h>
+
+#define MCALL_MSG_SIZE 24
+
+struct ct_data
+  {
+    int ct_sock;
+    bool_t ct_closeit;
+    struct timeval ct_wait;
+    bool_t ct_waitset;		/* wait set by clnt_control? */
+    struct sockaddr_un ct_addr;
+    struct rpc_err ct_error;
+    char ct_mcall[MCALL_MSG_SIZE];	/* marshalled callmsg */
+    u_int ct_mpos;		/* pos after marshal */
+    XDR ct_xdrs;
+  };
+
+static int readunix (char *, char *, int);
+static int writeunix (char *, char *, int);
+
+static enum clnt_stat clntunix_call (CLIENT *, u_long, xdrproc_t, caddr_t,
+				    xdrproc_t, caddr_t, struct timeval);
+static void clntunix_abort (void);
+static void clntunix_geterr (CLIENT *, struct rpc_err *);
+static bool_t clntunix_freeres (CLIENT *, xdrproc_t, caddr_t);
+static bool_t clntunix_control (CLIENT *, int, char *);
+static void clntunix_destroy (CLIENT *);
+
+static struct clnt_ops unix_ops =
+{
+  clntunix_call,
+  clntunix_abort,
+  clntunix_geterr,
+  clntunix_freeres,
+  clntunix_destroy,
+  clntunix_control
+};
+
+/*
+ * Create a client handle for a tcp/ip connection.
+ * If *sockp<0, *sockp is set to a newly created TCP socket and it is
+ * connected to raddr.  If *sockp non-negative then
+ * raddr is ignored.  The rpc/tcp package does buffering
+ * similar to stdio, so the client must pick send and receive buffer sizes,];
+ * 0 => use the default.
+ * If raddr->sin_port is 0, then a binder on the remote machine is
+ * consulted for the right port number.
+ * NB: *sockp is copied into a private area.
+ * NB: It is the clients responsibility to close *sockp.
+ * NB: The rpch->cl_auth is set null authentication.  Caller may wish to set this
+ * something more useful.
+ */
+CLIENT *
+clntunix_create (struct sockaddr_un *raddr, u_long prog, u_long vers,
+		 int *sockp, u_int sendsz, u_int recvsz)
+{
+  CLIENT *h;
+  struct ct_data *ct = (struct ct_data *) mem_alloc (sizeof (*ct));
+  struct timeval now;
+  struct rpc_msg call_msg;
+  int len;
+
+  h = (CLIENT *) mem_alloc (sizeof (*h));
+  if (h == NULL)
+    {
+      (void) fputs (_("clntunix_create: out of memory\n"), stderr);
+      rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+      rpc_createerr.cf_error.re_errno = errno;
+      goto fooy;
+    }
+  /*  ct = (struct ct_data *) mem_alloc (sizeof (*ct)); */
+  if (ct == NULL)
+    {
+      (void) fputs (_("clntunix_create: out of memory\n"), stderr);
+      rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+      rpc_createerr.cf_error.re_errno = errno;
+      goto fooy;
+    }
+
+  /*
+   * If no socket given, open one
+   */
+  if (*sockp < 0)
+    {
+      *sockp = __socket (AF_UNIX, SOCK_STREAM, 0);
+      len = strlen (raddr->sun_path) + sizeof (raddr->sun_family) + 1;
+      if (*sockp < 0
+	  || __connect (*sockp, (struct sockaddr *) raddr, len) < 0)
+	{
+	  rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+	  rpc_createerr.cf_error.re_errno = errno;
+	  if (*sockp != -1)
+	    __close (*sockp);
+	  goto fooy;
+	}
+      ct->ct_closeit = TRUE;
+    }
+  else
+    {
+      ct->ct_closeit = FALSE;
+    }
+
+  /*
+   * Set up private data struct
+   */
+  ct->ct_sock = *sockp;
+  ct->ct_wait.tv_usec = 0;
+  ct->ct_waitset = FALSE;
+  ct->ct_addr = *raddr;
+
+  /*
+   * Initialize call message
+   */
+  __gettimeofday (&now, (struct timezone *) 0);
+  call_msg.rm_xid = __getpid () ^ now.tv_sec ^ now.tv_usec;
+  call_msg.rm_direction = CALL;
+  call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+  call_msg.rm_call.cb_prog = prog;
+  call_msg.rm_call.cb_vers = vers;
+
+  /*
+   * pre-serialize the static part of the call msg and stash it away
+   */
+  xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE);
+  if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg))
+    {
+      if (ct->ct_closeit)
+	__close (*sockp);
+      goto fooy;
+    }
+  ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs));
+  XDR_DESTROY (&(ct->ct_xdrs));
+
+  /*
+   * Create a client handle which uses xdrrec for serialization
+   * and authnone for authentication.
+   */
+  xdrrec_create (&(ct->ct_xdrs), sendsz, recvsz,
+		 (caddr_t) ct, readunix, writeunix);
+  h->cl_ops = &unix_ops;
+  h->cl_private = (caddr_t) ct;
+  h->cl_auth = authnone_create ();
+  return h;
+
+fooy:
+  /*
+   * Something goofed, free stuff and barf
+   */
+  mem_free ((caddr_t) ct, sizeof (struct ct_data));
+  mem_free ((caddr_t) h, sizeof (CLIENT));
+  return (CLIENT *) NULL;
+}
+
+static enum clnt_stat
+clntunix_call (h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
+     CLIENT *h;
+     u_long proc;
+     xdrproc_t xdr_args;
+     caddr_t args_ptr;
+     xdrproc_t xdr_results;
+     caddr_t results_ptr;
+     struct timeval timeout;
+{
+  struct ct_data *ct = (struct ct_data *) h->cl_private;
+  XDR *xdrs = &(ct->ct_xdrs);
+  struct rpc_msg reply_msg;
+  u_long x_id;
+  u_int32_t *msg_x_id = (u_int32_t *) (ct->ct_mcall);	/* yuk */
+  bool_t shipnow;
+  int refreshes = 2;
+
+  if (!ct->ct_waitset)
+    {
+      ct->ct_wait = timeout;
+    }
+
+  shipnow =
+    (xdr_results == (xdrproc_t) 0 && timeout.tv_sec == 0
+     && timeout.tv_usec == 0) ? FALSE : TRUE;
+
+call_again:
+  xdrs->x_op = XDR_ENCODE;
+  ct->ct_error.re_status = RPC_SUCCESS;
+  x_id = ntohl (--(*msg_x_id));
+  if ((!XDR_PUTBYTES (xdrs, ct->ct_mcall, ct->ct_mpos)) ||
+      (!XDR_PUTLONG (xdrs, (long *) &proc)) ||
+      (!AUTH_MARSHALL (h->cl_auth, xdrs)) ||
+      (!(*xdr_args) (xdrs, args_ptr)))
+    {
+      if (ct->ct_error.re_status == RPC_SUCCESS)
+	ct->ct_error.re_status = RPC_CANTENCODEARGS;
+      (void) xdrrec_endofrecord (xdrs, TRUE);
+      return ct->ct_error.re_status;
+    }
+  if (!xdrrec_endofrecord (xdrs, shipnow))
+    return ct->ct_error.re_status = RPC_CANTSEND;
+  if (!shipnow)
+    return RPC_SUCCESS;
+  /*
+   * Hack to provide rpc-based message passing
+   */
+  if (timeout.tv_sec == 0 && timeout.tv_usec == 0)
+    return ct->ct_error.re_status = RPC_TIMEDOUT;
+
+
+  /*
+   * Keep receiving until we get a valid transaction id
+   */
+  xdrs->x_op = XDR_DECODE;
+  while (TRUE)
+    {
+      reply_msg.acpted_rply.ar_verf = _null_auth;
+      reply_msg.acpted_rply.ar_results.where = NULL;
+      reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
+      if (!xdrrec_skiprecord (xdrs))
+	return ct->ct_error.re_status;
+      /* now decode and validate the response header */
+      if (!xdr_replymsg (xdrs, &reply_msg))
+	{
+	  if (ct->ct_error.re_status == RPC_SUCCESS)
+	    continue;
+	  return ct->ct_error.re_status;
+	}
+      if (reply_msg.rm_xid == x_id)
+	break;
+    }
+
+  /*
+   * process header
+   */
+  _seterr_reply (&reply_msg, &(ct->ct_error));
+  if (ct->ct_error.re_status == RPC_SUCCESS)
+    {
+      if (!AUTH_VALIDATE (h->cl_auth, &reply_msg.acpted_rply.ar_verf))
+	{
+	  ct->ct_error.re_status = RPC_AUTHERROR;
+	  ct->ct_error.re_why = AUTH_INVALIDRESP;
+	}
+      else if (!(*xdr_results) (xdrs, results_ptr))
+	{
+	  if (ct->ct_error.re_status == RPC_SUCCESS)
+	    ct->ct_error.re_status = RPC_CANTDECODERES;
+	}
+      /* free verifier ... */
+      if (reply_msg.acpted_rply.ar_verf.oa_base != NULL)
+	{
+	  xdrs->x_op = XDR_FREE;
+	  (void) xdr_opaque_auth (xdrs, &(reply_msg.acpted_rply.ar_verf));
+	}
+    }				/* end successful completion */
+  else
+    {
+      /* maybe our credentials need to be refreshed ... */
+      if (refreshes-- && AUTH_REFRESH (h->cl_auth))
+	goto call_again;
+    }				/* end of unsuccessful completion */
+  return ct->ct_error.re_status;
+}
+
+static void
+clntunix_geterr (CLIENT *h, struct rpc_err *errp)
+{
+  struct ct_data *ct = (struct ct_data *) h->cl_private;
+
+  *errp = ct->ct_error;
+}
+
+static bool_t
+clntunix_freeres (cl, xdr_res, res_ptr)
+     CLIENT *cl;
+     xdrproc_t xdr_res;
+     caddr_t res_ptr;
+{
+  struct ct_data *ct = (struct ct_data *) cl->cl_private;
+  XDR *xdrs = &(ct->ct_xdrs);
+
+  xdrs->x_op = XDR_FREE;
+  return (*xdr_res) (xdrs, res_ptr);
+}
+
+static void
+clntunix_abort ()
+{
+}
+
+static bool_t
+clntunix_control (CLIENT *cl, int request, char *info)
+{
+  struct ct_data *ct = (struct ct_data *) cl->cl_private;
+
+
+  switch (request)
+    {
+    case CLSET_FD_CLOSE:
+      ct->ct_closeit = TRUE;
+      break;
+    case CLSET_FD_NCLOSE:
+      ct->ct_closeit = FALSE;
+      break;
+    case CLSET_TIMEOUT:
+      ct->ct_wait = *(struct timeval *) info;
+      break;
+    case CLGET_TIMEOUT:
+      *(struct timeval *) info = ct->ct_wait;
+      break;
+    case CLGET_SERVER_ADDR:
+      *(struct sockaddr_un *) info = ct->ct_addr;
+      break;
+    case CLGET_FD:
+      *(int *)info = ct->ct_sock;
+      break;
+    case CLGET_XID:
+      /*
+       * use the knowledge that xid is the
+       * first element in the call structure *.
+       * This will get the xid of the PREVIOUS call
+       */
+      *(u_long *) info = ntohl (*(u_long *)ct->ct_mcall);
+      break;
+    case CLSET_XID:
+      /* This will set the xid of the NEXT call */
+      *(u_long *) ct->ct_mcall =  htonl (*(u_long *)info - 1);
+      /* decrement by 1 as clntunix_call() increments once */
+    case CLGET_VERS:
+      /*
+       * This RELIES on the information that, in the call body,
+       * the version number field is the fifth field from the
+       * begining of the RPC header. MUST be changed if the
+       * call_struct is changed
+       */
+      *(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall
+					     + 4 * BYTES_PER_XDR_UNIT));
+      break;
+    case CLSET_VERS:
+      *(u_long *) (ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT)
+	= htonl (*(u_long *) info);
+      break;
+    case CLGET_PROG:
+      /*
+       * This RELIES on the information that, in the call body,
+       * the program number field is the  field from the
+       * begining of the RPC header. MUST be changed if the
+       * call_struct is changed
+       */
+      *(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall
+					     + 3 * BYTES_PER_XDR_UNIT));
+      break;
+    case CLSET_PROG:
+      *(u_long *) (ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT)
+	= htonl(*(u_long *) info);
+      break;
+    /* The following are only possible with TI-RPC */
+    case CLGET_RETRY_TIMEOUT:
+    case CLSET_RETRY_TIMEOUT:
+    case CLGET_SVC_ADDR:
+    case CLSET_SVC_ADDR:
+    case CLSET_PUSH_TIMOD:
+    case CLSET_POP_TIMOD:
+    default:
+      return FALSE;
+    }
+  return TRUE;
+}
+
+
+static void
+clntunix_destroy (CLIENT *h)
+{
+  struct ct_data *ct =
+  (struct ct_data *) h->cl_private;
+
+  if (ct->ct_closeit)
+    {
+      (void) close (ct->ct_sock);
+    }
+  XDR_DESTROY (&(ct->ct_xdrs));
+  mem_free ((caddr_t) ct, sizeof (struct ct_data));
+  mem_free ((caddr_t) h, sizeof (CLIENT));
+}
+
+struct cmessage {
+  struct cmsghdr cmsg;
+  struct cmsgcred cmcred;
+};
+
+static int
+__msgread (int sock, void *buf, size_t cnt)
+{
+  struct iovec iov[1];
+  struct msghdr msg;
+  struct cmessage cm;
+  int on = 1;
+
+  iov[0].iov_base = buf;
+  iov[0].iov_len = cnt;
+
+  msg.msg_iov = iov;
+  msg.msg_iovlen = 1;
+  msg.msg_name = NULL;
+  msg.msg_namelen = 0;
+  msg.msg_control = (caddr_t)&cm;
+  msg.msg_controllen = sizeof(struct cmessage);
+  msg.msg_flags = 0;
+
+  setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on));
+
+  return recvmsg (sock, &msg, 0);
+}
+
+static int
+__msgwrite (int sock, void *buf, size_t cnt)
+{
+#ifndef SCM_CRED
+  /* We cannot implement this reliably.  */
+  __set_errno (ENOSYS);
+#else
+  struct iovec iov[1];
+  struct msghdr msg;
+  struct cmessage cm;
+  int len;
+
+  iov[0].iov_base = buf;
+  iov[0].iov_len = cnt;
+
+  cm.cmsg.cmsg_type = SCM_CREDS;
+  cm.cmsg.cmsg_level = SOL_SOCKET;
+  cm.cmsg.cmsg_len = sizeof (struct cmessage);
+  /* XXX I'm not sure, if gete?id() is always correct, or if we should use
+     get?id(). But since keyserv needs geteuid(), we have no other chance.
+     It would be much better, if the kernel could pass both to the server. */
+  cm.cmcred.cmcred_pid = __getpid ();
+  cm.cmcred.cmcred_uid = __geteuid ();
+  cm.cmcred.cmcred_gid = __getegid ();
+
+  msg.msg_iov = iov;
+  msg.msg_iovlen = 1;
+  msg.msg_name = NULL;
+  msg.msg_namelen = 0;
+  msg.msg_control = (caddr_t) &cm;
+  msg.msg_controllen = sizeof (struct cmessage);
+  msg.msg_flags = 0;
+
+  return sendmsg (sock, &msg, 0);
+#endif
+}
+
+
+/*
+ * Interface between xdr serializer and unix connection.
+ * Behaves like the system calls, read & write, but keeps some error state
+ * around for the rpc level.
+ */
+static int
+readunix (char *ctptr, char *buf, int len)
+{
+  struct ct_data *ct = (struct ct_data *) ctptr;
+  struct pollfd fd;
+  int milliseconds = ((ct->ct_wait.tv_sec * 1000)
+		      + (ct->ct_wait.tv_usec / 1000));
+
+  if (len == 0)
+    return 0;
+
+  fd.fd = ct->ct_sock;
+  fd.events = POLLIN;
+  while (TRUE)
+    {
+      switch (__poll (&fd, 1, milliseconds))
+        {
+        case 0:
+          ct->ct_error.re_status = RPC_TIMEDOUT;
+          return -1;
+
+        case -1:
+          if (errno == EINTR)
+            continue;
+          ct->ct_error.re_status = RPC_CANTRECV;
+          ct->ct_error.re_errno = errno;
+          return -1;
+        }
+      break;
+    }
+  switch (len = __msgread (ct->ct_sock, buf, len))
+    {
+
+    case 0:
+      /* premature eof */
+      ct->ct_error.re_errno = ECONNRESET;
+      ct->ct_error.re_status = RPC_CANTRECV;
+      len = -1;			/* it's really an error */
+      break;
+
+    case -1:
+      ct->ct_error.re_errno = errno;
+      ct->ct_error.re_status = RPC_CANTRECV;
+      break;
+    }
+  return len;
+}
+
+static int
+writeunix (char *ctptr, char *buf, int len)
+{
+  int i, cnt;
+  struct ct_data *ct = (struct ct_data *) ctptr;
+
+  for (cnt = len; cnt > 0; cnt -= i, buf += i)
+    {
+      if ((i = __msgwrite (ct->ct_sock, buf, cnt)) == -1)
+	{
+	  ct->ct_error.re_errno = errno;
+	  ct->ct_error.re_status = RPC_CANTSEND;
+	  return -1;
+	}
+    }
+  return len;
+}
diff --git a/sunrpc/key_call.c b/sunrpc/key_call.c
index e59a8b7a37..0219eaf5ad 100644
--- a/sunrpc/key_call.c
+++ b/sunrpc/key_call.c
@@ -38,6 +38,7 @@
 
 #include <stdio.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <signal.h>
 #include <unistd.h>
 #include <string.h>
@@ -47,6 +48,7 @@
 #include <sys/param.h>
 #include <sys/socket.h>
 #include <rpc/key_prot.h>
+#include <bits/libc-lock.h>
 
 #define KEY_TIMEOUT	5	/* per-try timeout in seconds */
 #define KEY_NRETRY	12	/* number of retries */
@@ -268,8 +270,8 @@ des_block *(*__key_gendes_LOCAL) (uid_t, char *) = 0;
 
 static int
 internal_function
-key_call (u_long proc, xdrproc_t xdr_arg, char *arg,
-	  xdrproc_t xdr_rslt, char *rslt)
+key_call_keyenvoy (u_long proc, xdrproc_t xdr_arg, char *arg,
+		   xdrproc_t xdr_rslt, char *rslt)
 {
   XDR xdrargs;
   XDR xdrrslt;
@@ -283,28 +285,6 @@ key_call (u_long proc, xdrproc_t xdr_arg, char *arg,
   uid_t euid;
   static char MESSENGER[] = "/usr/etc/keyenvoy";
 
-  if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL)
-    {
-      cryptkeyres *res;
-      res = (*__key_encryptsession_pk_LOCAL) (__geteuid (), arg);
-      *(cryptkeyres *) rslt = *res;
-      return 1;
-    }
-  else if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL)
-    {
-      cryptkeyres *res;
-      res = (*__key_decryptsession_pk_LOCAL) (__geteuid (), arg);
-      *(cryptkeyres *) rslt = *res;
-      return 1;
-    }
-  else if (proc == KEY_GEN && __key_gendes_LOCAL)
-    {
-      des_block *res;
-      res = (*__key_gendes_LOCAL) (__geteuid (), 0);
-      *(des_block *) rslt = *res;
-      return 1;
-    }
-
   success = 1;
   sigemptyset (&mask);
   sigaddset (&mask, SIGCHLD);
@@ -365,3 +345,175 @@ key_call (u_long proc, xdrproc_t xdr_arg, char *arg,
 
   return success;
 }
+
+struct  key_call_private {
+  CLIENT  *client;        /* Client handle */
+  pid_t   pid;            /* process-id at moment of creation */
+  uid_t   uid;            /* user-id at last authorization */
+};
+static struct key_call_private *key_call_private_main = NULL;
+__libc_lock_define_initialized (static, keycall_lock)
+
+/*
+ * Keep the handle cached.  This call may be made quite often.
+ */
+static CLIENT *
+getkeyserv_handle (int vers)
+{
+  struct key_call_private *kcp = key_call_private_main;
+  struct timeval wait_time;
+  int fd;
+  struct sockaddr_un name;
+  int namelen = sizeof(struct sockaddr_un);
+
+#define TOTAL_TIMEOUT   30      /* total timeout talking to keyserver */
+#define TOTAL_TRIES     5       /* Number of tries */
+
+  if (kcp == (struct key_call_private *)NULL)
+    {
+      kcp = (struct key_call_private *)malloc (sizeof (*kcp));
+      if (kcp == (struct key_call_private *)NULL)
+	return (CLIENT *) NULL;
+
+      key_call_private_main = kcp;
+      kcp->client = NULL;
+    }
+
+  /* if pid has changed, destroy client and rebuild */
+  if (kcp->client != NULL && kcp->pid != __getpid ())
+    {
+      clnt_destroy (kcp->client);
+      kcp->client = NULL;
+    }
+
+  if (kcp->client != NULL)
+    {
+      /* if other side closed socket, build handle again */
+      clnt_control (kcp->client, CLGET_FD, (char *)&fd);
+      if (getpeername (fd,(struct sockaddr *)&name,&namelen) == -1)
+	{
+	  auth_destroy (kcp->client->cl_auth);
+	  clnt_destroy (kcp->client);
+	  kcp->client = NULL;
+	}
+    }
+
+  if (kcp->client != NULL)
+    {
+      /* if uid has changed, build client handle again */
+      if (kcp->uid != __geteuid ())
+	{
+        kcp->uid = __geteuid ();
+        auth_destroy (kcp->client->cl_auth);
+        kcp->client->cl_auth =
+          authunix_create ((char *)"", kcp->uid, 0, 0, NULL);
+        if (kcp->client->cl_auth == NULL)
+          {
+            clnt_destroy (kcp->client);
+            kcp->client = NULL;
+            return ((CLIENT *) NULL);
+          }
+	}
+      /* Change the version number to the new one */
+      clnt_control (kcp->client, CLSET_VERS, (void *)&vers);
+      return kcp->client;
+    }
+
+  if ((kcp->client == (CLIENT *) NULL))
+    /* Use the AF_UNIX transport */
+    kcp->client = clnt_create ("/var/run/keyservsock", KEY_PROG, vers, "unix");
+
+  if (kcp->client == (CLIENT *) NULL)
+    return (CLIENT *) NULL;
+
+  kcp->uid = __geteuid ();
+  kcp->pid = __getpid ();
+  kcp->client->cl_auth = authunix_create ((char *)"", kcp->uid, 0, 0, NULL);
+  if (kcp->client->cl_auth == NULL)
+    {
+      clnt_destroy (kcp->client);
+      kcp->client = NULL;
+      return (CLIENT *) NULL;
+    }
+
+  wait_time.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES;
+  wait_time.tv_usec = 0;
+  clnt_control (kcp->client, CLSET_RETRY_TIMEOUT,
+		(char *)&wait_time);
+  if (clnt_control (kcp->client, CLGET_FD, (char *)&fd))
+    fcntl (fd, F_SETFD, 1);  /* make it "close on exec" */
+
+  return kcp->client;
+}
+
+/* returns  0 on failure, 1 on success */
+static int
+internal_function
+key_call_socket (u_long proc, xdrproc_t xdr_arg, char *arg,
+               xdrproc_t xdr_rslt, char *rslt)
+{
+  CLIENT *clnt;
+  struct timeval wait_time;
+  int result = 0;
+
+  __libc_lock_lock (keycall_lock);
+  if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) ||
+      (proc == KEY_NET_GET) || (proc == KEY_NET_PUT) ||
+      (proc == KEY_GET_CONV))
+    clnt = getkeyserv_handle(2); /* talk to version 2 */
+  else
+    clnt = getkeyserv_handle(1); /* talk to version 1 */
+
+  if (clnt != NULL)
+    {
+      wait_time.tv_sec = TOTAL_TIMEOUT;
+      wait_time.tv_usec = 0;
+
+      if (clnt_call (clnt, proc, xdr_arg, arg, xdr_rslt, rslt,
+		     wait_time) == RPC_SUCCESS)
+	result = 1;
+    }
+
+  __libc_lock_unlock (keycall_lock);
+
+  return result;
+}
+
+/* returns  0 on failure, 1 on success */
+static int
+internal_function
+key_call (u_long proc, xdrproc_t xdr_arg, char *arg,
+	  xdrproc_t xdr_rslt, char *rslt)
+{
+  static int use_keyenvoy = 0;
+
+  if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL)
+    {
+      cryptkeyres *res;
+      res = (*__key_encryptsession_pk_LOCAL) (__geteuid (), arg);
+      *(cryptkeyres *) rslt = *res;
+      return 1;
+    }
+  else if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL)
+    {
+      cryptkeyres *res;
+      res = (*__key_decryptsession_pk_LOCAL) (__geteuid (), arg);
+      *(cryptkeyres *) rslt = *res;
+      return 1;
+    }
+  else if (proc == KEY_GEN && __key_gendes_LOCAL)
+    {
+      des_block *res;
+      res = (*__key_gendes_LOCAL) (__geteuid (), 0);
+      *(des_block *) rslt = *res;
+      return 1;
+    }
+
+  if (!use_keyenvoy)
+    {
+      if (key_call_socket (proc, xdr_arg, arg, xdr_rslt, rslt))
+	return 1;
+      use_keyenvoy = 1;
+    }
+  return key_call_keyenvoy (proc, xdr_arg, arg, xdr_rslt, rslt);
+}
diff --git a/sunrpc/rpc/clnt.h b/sunrpc/rpc/clnt.h
index 1570cba4c2..b3852927a3 100644
--- a/sunrpc/rpc/clnt.h
+++ b/sunrpc/rpc/clnt.h
@@ -41,6 +41,7 @@
 #include <sys/types.h>
 #include <rpc/types.h>
 #include <rpc/auth.h>
+#include <sys/un.h>
 
 __BEGIN_DECLS
 
@@ -282,7 +283,8 @@ extern CLIENT *clntraw_create __P ((__const u_long __prog,
 
 
 /*
- * Generic client creation routine. Supported protocols are "udp" and "tcp"
+ * Generic client creation routine. Supported protocols are "udp", "tcp" and
+ * "unix"
  * CLIENT *
  * clnt_create(host, prog, vers, prot)
  *	char *host; 	-- hostname
@@ -341,6 +343,24 @@ extern CLIENT *clntudp_bufcreate __P ((struct sockaddr_in *__raddr,
 				       int *__sockp, u_int __sendsz,
 				       u_int __recvsz));
 
+
+/*
+ * AF_UNIX based rpc
+ * CLIENT *
+ * clntunix_create(raddr, prog, vers, sockp, sendsz, recvsz)
+ *      struct sockaddr_un *raddr;
+ *      u_long prog;
+ *      u_long version;
+ *      register int *sockp;
+ *      u_int sendsz;
+ *      u_int recvsz;
+ */
+extern CLIENT *clntunix_create  __P ((struct sockaddr_un *__raddr,
+				      u_long __program, u_long __version,
+				      int *__sockp, u_int __sendsz,
+				      u_int __recvsz));
+
+
 extern int callrpc __P ((__const char *__host, __const u_long __prognum,
 			 __const u_long __versnum, __const u_long __procnum,
 			 __const xdrproc_t __inproc, __const char *__in,
diff --git a/sunrpc/rpc/svc.h b/sunrpc/rpc/svc.h
index a53bc1015f..4ac2a5cdf0 100644
--- a/sunrpc/rpc/svc.h
+++ b/sunrpc/rpc/svc.h
@@ -305,6 +305,13 @@ extern SVCXPRT *svctcp_create __P ((int __sock, u_int __sendsize,
 				    u_int __recvsize));
 
 
+/*
+ * Unix based rpc.
+ */
+extern SVCXPRT *svcunix_create __P ((int __sock, u_int __sendsize,
+				     u_int __recvsize, char *__path));
+
+
 __END_DECLS
 
 #endif /* rpc/svc.h */
diff --git a/sunrpc/svc_authux.c b/sunrpc/svc_authux.c
index 04cff9c53a..627b7e3faf 100644
--- a/sunrpc/svc_authux.c
+++ b/sunrpc/svc_authux.c
@@ -120,8 +120,22 @@ _svcauth_unix (struct svc_req *rqst, struct rpc_msg *msg)
       stat = AUTH_BADCRED;
       goto done;
     }
-  rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL;
-  rqst->rq_xprt->xp_verf.oa_length = 0;
+
+  /* get the verifier */
+  if ((u_int)msg->rm_call.cb_verf.oa_length)
+    {
+      rqst->rq_xprt->xp_verf.oa_flavor =
+	msg->rm_call.cb_verf.oa_flavor;
+      rqst->rq_xprt->xp_verf.oa_base =
+	msg->rm_call.cb_verf.oa_base;
+      rqst->rq_xprt->xp_verf.oa_length =
+	msg->rm_call.cb_verf.oa_length;
+    }
+  else
+    {
+      rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL;
+      rqst->rq_xprt->xp_verf.oa_length = 0;
+    }
   stat = AUTH_OK;
 done:
   XDR_DESTROY (&xdrs);
diff --git a/sunrpc/svc_tcp.c b/sunrpc/svc_tcp.c
index 75fa8705b6..0c2ce9650a 100644
--- a/sunrpc/svc_tcp.c
+++ b/sunrpc/svc_tcp.c
@@ -141,7 +141,7 @@ svctcp_create (int sock, u_int sendsize, u_int recvsize)
     {
       if ((sock = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
 	{
-	  perror (_("svctcp_.c - udp socket creation problem"));
+	  perror (_("svc_tcp.c - tcp socket creation problem"));
 	  return (SVCXPRT *) NULL;
 	}
       madesock = TRUE;
@@ -156,7 +156,7 @@ svctcp_create (int sock, u_int sendsize, u_int recvsize)
   if ((getsockname (sock, (struct sockaddr *) &addr, &len) != 0) ||
       (listen (sock, 2) != 0))
     {
-      perror (_("svctcp_.c - cannot getsockname or listen"));
+      perror (_("svc_tcp.c - cannot getsockname or listen"));
       if (madesock)
 	(void) __close (sock);
       return (SVCXPRT *) NULL;
diff --git a/sunrpc/svc_unix.c b/sunrpc/svc_unix.c
new file mode 100644
index 0000000000..59ae7a54e7
--- /dev/null
+++ b/sunrpc/svc_unix.c
@@ -0,0 +1,496 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * svc_unix.c, Server side for TCP/IP based RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * Actually implements two flavors of transporter -
+ * a unix rendezvouser (a listener and connection establisher)
+ * and a record/unix stream.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/*
+ * Ops vector for AF_UNIX based rpc service handle
+ */
+static bool_t svcunix_recv (SVCXPRT *, struct rpc_msg *);
+static enum xprt_stat svcunix_stat (SVCXPRT *);
+static bool_t svcunix_getargs (SVCXPRT *, xdrproc_t, caddr_t);
+static bool_t svcunix_reply (SVCXPRT *, struct rpc_msg *);
+static bool_t svcunix_freeargs (SVCXPRT *, xdrproc_t, caddr_t);
+static void svcunix_destroy (SVCXPRT *);
+
+static const struct xp_ops svcunix_op =
+{
+  svcunix_recv,
+  svcunix_stat,
+  svcunix_getargs,
+  svcunix_reply,
+  svcunix_freeargs,
+  svcunix_destroy
+};
+
+/*
+ * Ops vector for AF_UNIX rendezvous handler
+ */
+static bool_t rendezvous_request (SVCXPRT *, struct rpc_msg *);
+static enum xprt_stat rendezvous_stat (SVCXPRT *);
+
+static const struct xp_ops svcunix_rendezvous_op =
+{
+  rendezvous_request,
+  rendezvous_stat,
+  (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) abort,
+  (bool_t (*) (SVCXPRT *, struct rpc_msg *)) abort,
+  (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) abort,
+  svcunix_destroy
+};
+
+static int readunix (char*, char *, int);
+static int writeunix (char *, char *, int);
+static SVCXPRT *makefd_xprt (int, u_int, u_int) internal_function;
+
+struct unix_rendezvous {        /* kept in xprt->xp_p1 */
+  u_int sendsize;
+  u_int recvsize;
+};
+
+struct unix_conn {		/* kept in xprt->xp_p1 */
+  enum xprt_stat strm_stat;
+  u_long x_id;
+  XDR xdrs;
+  char verf_body[MAX_AUTH_BYTES];
+};
+
+/*
+ * Usage:
+ *      xprt = svcunix_create(sock, send_buf_size, recv_buf_size);
+ *
+ * Creates, registers, and returns a (rpc) unix based transporter.
+ * Once *xprt is initialized, it is registered as a transporter
+ * see (svc.h, xprt_register).  This routine returns
+ * a NULL if a problem occurred.
+ *
+ * If sock<0 then a socket is created, else sock is used.
+ * If the socket, sock is not bound to a port then svcunix_create
+ * binds it to an arbitrary port.  The routine then starts a unix
+ * listener on the socket's associated port.  In any (successful) case,
+ * xprt->xp_sock is the registered socket number and xprt->xp_port is the
+ * associated port number.
+ *
+ * Since unix streams do buffered io similar to stdio, the caller can specify
+ * how big the send and receive buffers are via the second and third parms;
+ * 0 => use the system default.
+ */
+SVCXPRT *
+svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path)
+{
+  bool_t madesock = FALSE;
+  SVCXPRT *xprt;
+  struct unix_rendezvous *r;
+  struct sockaddr_un addr;
+  socklen_t len = sizeof (struct sockaddr_in);
+
+  if (sock == RPC_ANYSOCK)
+    {
+      if ((sock = __socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
+	{
+	  perror (_("svc_unix.c - AF_UNIX socket creation problem"));
+	  return (SVCXPRT *) NULL;
+	}
+      madesock = TRUE;
+    }
+  memset (&addr, '\0', sizeof (addr));
+  addr.sun_family = AF_UNIX;
+  len = strlen (addr.sun_path) + 1;
+  memcpy (addr.sun_path, path, len);
+  len += sizeof (addr.sun_family);
+
+  bind (sock, (struct sockaddr *) &addr, len);
+
+  if (getsockname (sock, (struct sockaddr *) &addr, &len) != 0
+      || listen (sock, 2) != 0)
+    {
+      perror (_("svc_unix.c - cannot getsockname or listen"));
+      if (madesock)
+	__close (sock);
+      return (SVCXPRT *) NULL;
+    }
+
+  r = (struct unix_rendezvous *) mem_alloc (sizeof (*r));
+  if (r == NULL)
+    {
+      fputs (_("svcunix_create: out of memory\n"), stderr);
+      return NULL;
+    }
+  r->sendsize = sendsize;
+  r->recvsize = recvsize;
+  xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
+  if (xprt == NULL)
+    {
+      fputs (_("svcunix_create: out of memory\n"), stderr);
+      return NULL;
+    }
+  xprt->xp_p2 = NULL;
+  xprt->xp_p1 = (caddr_t) r;
+  xprt->xp_verf = _null_auth;
+  xprt->xp_ops = &svcunix_rendezvous_op;
+  xprt->xp_port = -1;
+  xprt->xp_sock = sock;
+  xprt_register (xprt);
+  return xprt;
+}
+
+/*
+ * Like svunix_create(), except the routine takes any *open* UNIX file
+ * descriptor as its first input.
+ */
+SVCXPRT *
+svcunixfd_create (int fd, u_int sendsize, u_int recvsize)
+{
+  return makefd_xprt (fd, sendsize, recvsize);
+}
+
+static SVCXPRT *
+internal_function
+makefd_xprt (int fd, u_int sendsize, u_int recvsize)
+{
+  SVCXPRT *xprt;
+  struct unix_conn *cd;
+
+  xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
+  if (xprt == (SVCXPRT *) NULL)
+    {
+      (void) fputs (_("svc_unix: makefd_xprt: out of memory\n"), stderr);
+      goto done;
+    }
+  cd = (struct unix_conn *) mem_alloc (sizeof (struct unix_conn));
+  if (cd == (struct unix_conn *) NULL)
+    {
+      (void) fputs (_("svc_unix: makefd_xprt: out of memory\n"), stderr);
+      mem_free ((char *) xprt, sizeof (SVCXPRT));
+      xprt = (SVCXPRT *) NULL;
+      goto done;
+    }
+  cd->strm_stat = XPRT_IDLE;
+  xdrrec_create (&(cd->xdrs), sendsize, recvsize,
+		 (caddr_t) xprt, readunix, writeunix);
+  xprt->xp_p2 = NULL;
+  xprt->xp_p1 = (caddr_t) cd;
+  xprt->xp_verf.oa_base = cd->verf_body;
+  xprt->xp_addrlen = 0;
+  xprt->xp_ops = &svcunix_op;	/* truly deals with calls */
+  xprt->xp_port = 0;		/* this is a connection, not a rendezvouser */
+  xprt->xp_sock = fd;
+  xprt_register (xprt);
+done:
+  return xprt;
+}
+
+static bool_t
+rendezvous_request (SVCXPRT *xprt, struct rpc_msg *errmsg)
+{
+  int sock;
+  struct unix_rendezvous *r;
+  struct sockaddr_un addr;
+  struct sockaddr_in in_addr;
+  socklen_t len;
+
+  r = (struct unix_rendezvous *) xprt->xp_p1;
+again:
+  len = sizeof (struct sockaddr_un);
+  if ((sock = accept (xprt->xp_sock, (struct sockaddr *) &addr, &len)) < 0)
+    {
+      if (errno == EINTR)
+	goto again;
+      return FALSE;
+    }
+  /*
+   * make a new transporter (re-uses xprt)
+   */
+  memset (&in_addr, '\0', sizeof (in_addr));
+  in_addr.sin_family = AF_UNIX;
+  xprt = makefd_xprt (sock, r->sendsize, r->recvsize);
+  xprt->xp_raddr = in_addr;
+  xprt->xp_addrlen = len;
+  return FALSE;		/* there is never an rpc msg to be processed */
+}
+
+static enum xprt_stat
+rendezvous_stat (SVCXPRT *xprt)
+{
+  return XPRT_IDLE;
+}
+
+static void
+svcunix_destroy (SVCXPRT *xprt)
+{
+  struct unix_conn *cd = (struct unix_conn *) xprt->xp_p1;
+
+  xprt_unregister (xprt);
+  __close (xprt->xp_sock);
+  if (xprt->xp_port != 0)
+    {
+      /* a rendezvouser socket */
+      xprt->xp_port = 0;
+    }
+  else
+    {
+      /* an actual connection socket */
+      XDR_DESTROY (&(cd->xdrs));
+    }
+  mem_free ((caddr_t) cd, sizeof (struct unix_conn));
+  mem_free ((caddr_t) xprt, sizeof (SVCXPRT));
+}
+
+struct cmessage {
+  struct cmsghdr cmsg;
+  struct cmsgcred cmcred;
+};
+
+/* XXX This is not thread safe, but since the main functions in svc.c
+   and the rpcgen generated *_svc functions for the daemon are also not
+   thread safe and uses static global variables, it doesn't matter. */
+static struct cmessage cm;
+
+static int
+__msgread (int sock, void *buf, size_t cnt)
+{
+  struct iovec iov[1];
+  struct msghdr msg;
+  int len, on = 1;
+
+  iov[0].iov_base = buf;
+  iov[0].iov_len = cnt;
+
+  msg.msg_iov = iov;
+  msg.msg_iovlen = 1;
+  msg.msg_name = NULL;
+  msg.msg_namelen = 0;
+  msg.msg_control = (caddr_t) &cm;
+  msg.msg_controllen = sizeof (struct cmessage);
+  msg.msg_flags = 0;
+
+  setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on));
+
+  return recvmsg (sock, &msg, 0);
+}
+
+static int
+__msgwrite (int sock, void *buf, size_t cnt)
+{
+#ifndef SCM_CRED
+  /* We cannot implement this reliably.  */
+  __set_errno (ENOSYS);
+#else
+  struct iovec iov[1];
+  struct msghdr msg;
+  int len;
+
+  iov[0].iov_base = buf;
+  iov[0].iov_len = cnt;
+
+  cm.cmsg.cmsg_type = SCM_CREDS;
+  cm.cmsg.cmsg_level = SOL_SOCKET;
+  cm.cmsg.cmsg_len = sizeof (struct cmessage);
+  /* XXX I'm not sure, if we really should use gete?id(), or get?id().
+     It would be much better, if the kernel could pass both to the
+     client. */
+  cm.cmcred.cmcred_pid = __getpid ();
+  cm.cmcred.cmcred_uid = __geteuid ();
+  cm.cmcred.cmcred_gid = __getegid ();
+
+  msg.msg_iov = iov;
+  msg.msg_iovlen = 1;
+  msg.msg_name = NULL;
+  msg.msg_namelen = 0;
+  msg.msg_control = (caddr_t) &cm;
+  msg.msg_controllen = sizeof (struct cmessage);
+  msg.msg_flags = 0;
+
+  return sendmsg (sock, &msg, 0);
+#endif
+}
+
+/*
+ * All read operations timeout after 35 seconds.
+ * A timeout is fatal for the connection.
+ */
+static struct timeval wait_per_try = {35, 0};
+
+/*
+ * reads data from the unix connection.
+ * any error is fatal and the connection is closed.
+ * (And a read of zero bytes is a half closed stream => error.)
+ */
+static int
+readunix (char *xprtptr, char *buf, int len)
+{
+  SVCXPRT *xprt = (SVCXPRT *) xprtptr;
+  int sock = xprt->xp_sock;
+#ifdef FD_SETSIZE
+  fd_set readfds;
+#else
+  int mask = 1 << sock;
+  int readfds;
+#endif /* def FD_SETSIZE */
+  while (1)
+    {
+      struct timeval timeout = wait_per_try;
+      readfds = svc_fdset;
+#ifdef FD_SETSIZE
+      FD_SET (sock, &readfds);
+#else
+      readfds |= (1 << sock);
+#endif /* def FD_SETSIZE */
+      if (__select (_rpc_dtablesize (), &readfds, (fd_set *) NULL,
+		    (fd_set *) NULL, &timeout) <= 0)
+	{
+	  if (errno == EINTR)
+	    continue;
+	  goto fatal_err;
+	}
+
+#ifdef FD_SETSIZE
+      if (FD_ISSET (sock, &readfds))
+#else
+      if (readfds == mask)
+#endif /* def FD_SETSIZE */
+	break;
+
+      svc_getreqset (&readfds);
+    }
+
+  if ((len = __msgread (sock, buf, len)) > 0)
+    return len;
+
+ fatal_err:
+  ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
+  return -1;
+}
+
+/*
+ * writes data to the unix connection.
+ * Any error is fatal and the connection is closed.
+ */
+static int
+writeunix (char *xprtptr, char * buf, int len)
+{
+  SVCXPRT *xprt = (SVCXPRT *) xprtptr;
+  int i, cnt;
+
+  for (cnt = len; cnt > 0; cnt -= i, buf += i)
+    {
+      if ((i = __msgwrite (xprt->xp_sock, buf, cnt)) < 0)
+	{
+	  ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
+	  return -1;
+	}
+    }
+  return len;
+}
+
+static enum xprt_stat
+svcunix_stat (SVCXPRT *xprt)
+{
+  struct unix_conn *cd =
+  (struct unix_conn *) (xprt->xp_p1);
+
+  if (cd->strm_stat == XPRT_DIED)
+    return XPRT_DIED;
+  if (!xdrrec_eof (&(cd->xdrs)))
+    return XPRT_MOREREQS;
+  return XPRT_IDLE;
+}
+
+static bool_t
+svcunix_recv (SVCXPRT *xprt, struct rpc_msg *msg)
+{
+  struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1);
+  XDR *xdrs = &(cd->xdrs);
+
+  xdrs->x_op = XDR_DECODE;
+  xdrrec_skiprecord (xdrs);
+  if (xdr_callmsg (xdrs, msg))
+    {
+      cd->x_id = msg->rm_xid;
+      /* set up verifiers */
+      msg->rm_call.cb_verf.oa_flavor = AUTH_UNIX;
+      msg->rm_call.cb_verf.oa_base = (caddr_t) &cm;
+      msg->rm_call.cb_verf.oa_length = sizeof (cm);
+      return TRUE;
+    }
+  cd->strm_stat = XPRT_DIED;	/* XXXX */
+  return FALSE;
+}
+
+static bool_t
+svcunix_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
+{
+  return (*xdr_args) (&(((struct unix_conn *) (xprt->xp_p1))->xdrs),
+		      args_ptr);
+}
+
+static bool_t
+svcunix_freeargs (xprt, xdr_args, args_ptr)
+     SVCXPRT *xprt;
+     xdrproc_t xdr_args;
+     caddr_t args_ptr;
+{
+  XDR *xdrs = &(((struct unix_conn *) (xprt->xp_p1))->xdrs);
+
+  xdrs->x_op = XDR_FREE;
+  return (*xdr_args) (xdrs, args_ptr);
+}
+
+static bool_t
+svcunix_reply (xprt, msg)
+     SVCXPRT *xprt;
+     struct rpc_msg *msg;
+{
+  struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1);
+  XDR *xdrs = &(cd->xdrs);
+  bool_t stat;
+
+  xdrs->x_op = XDR_ENCODE;
+  msg->rm_xid = cd->x_id;
+  stat = xdr_replymsg (xdrs, msg);
+  (void) xdrrec_endofrecord (xdrs, TRUE);
+  return stat;
+}
diff --git a/sysdeps/generic/glob.c b/sysdeps/generic/glob.c
index 5f96554bf2..c9744fc46f 100644
--- a/sysdeps/generic/glob.c
+++ b/sysdeps/generic/glob.c
@@ -808,26 +808,29 @@ glob (pattern, flags, errfunc, pglob)
 
       flags |= GLOB_MAGCHAR;
 
+      /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.
+	 But if we have not found any matching entry and thie GLOB_NOCHECK
+	 flag was set we must return the list consisting of the disrectory
+	 names followed by the filename.  */
       if (pglob->gl_pathc == oldcount)
 	/* No matches.  */
 	if (flags & GLOB_NOCHECK)
 	  {
-	    size_t len = strlen (pattern) + 1;
-	    char *patcopy = (char *) malloc (len);
-	    if (patcopy == NULL)
-	      return GLOB_NOSPACE;
-	    memcpy (patcopy, pattern, len);
+	    size_t filename_len = strlen (filename) + 1;
+	    char **new_pathv;
+	    struct stat st;
 
+	    /* This is an pessimistic guess about the size.  */
 	    pglob->gl_pathv
 	      = (char **) realloc (pglob->gl_pathv,
 				   (pglob->gl_pathc +
 				    ((flags & GLOB_DOOFFS) ?
 				     pglob->gl_offs : 0) +
-				    1 + 1) *
+				    dirs.gl_pathc + 1) *
 				   sizeof (char *));
 	    if (pglob->gl_pathv == NULL)
 	      {
-		free (patcopy);
+		globfree (&dirs);
 		return GLOB_NOSPACE;
 	      }
 
@@ -835,12 +838,54 @@ glob (pattern, flags, errfunc, pglob)
 	      while (pglob->gl_pathc < pglob->gl_offs)
 		pglob->gl_pathv[pglob->gl_pathc++] = NULL;
 
-	    pglob->gl_pathv[pglob->gl_pathc++] = patcopy;
+	    for (i = 0; i < dirs.gl_pathc; ++i)
+	      {
+		const char *dir = dirs.gl_pathv[i];
+		size_t dir_len = strlen (dir);
+
+		/* First check whether this really is a directory.  */
+		if (((flags & GLOB_ALTDIRFUNC)
+		     ? (*pglob->gl_stat) (dir, &st) : __stat (dir, &st)) != 0
+		    || !S_ISDIR (st.st_mode))
+		  /* No directory, ignore this entry.  */
+		  continue;
+
+		pglob->gl_pathv[pglob->gl_pathc] = malloc (dir_len + 1
+							   + filename_len);
+		if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
+		  {
+		    globfree (&dirs);
+		    globfree (pglob);
+		    return GLOB_NOSPACE;
+		  }
+
+#ifdef HAVE_MEMPCPY
+		mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc],
+					   dir, dir_len),
+				  "/", 1),
+			 filename, filename_len);
+#else
+		memcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len);
+		pglob->gl_pathv[pglob->gl_pathc][dir_len] = '/';
+		memcpy (&pglob->gl_pathv[pglob->gl_pathc][dir_len + 1],
+			filename, filename_len);
+#endif
+		++pglob->gl_pathc;
+	      }
+
 	    pglob->gl_pathv[pglob->gl_pathc] = NULL;
 	    pglob->gl_flags = flags;
+
+	    /* Now we know how large the gl_pathv vector must be.  */
+	    new_pathv = realloc (pglob->gl_pathv,
+				 (pglob->gl_pathc + 1) * sizeof (char *));
+	    if (new_pathv != NULL)
+	      pglob->gl_pathv = new_pathv;
 	  }
 	else
 	  return GLOB_NOMATCH;
+
+      globfree (&dirs);
     }
   else
     {
diff --git a/sysdeps/libm-ieee754/k_standard.c b/sysdeps/libm-ieee754/k_standard.c
index 82cfbe467a..42ecca9980 100644
--- a/sysdeps/libm-ieee754/k_standard.c
+++ b/sysdeps/libm-ieee754/k_standard.c
@@ -77,8 +77,8 @@ static double zero = 0.0;	/* used as const */
  *	37-- y1(x>X_TLOSS)
  *	38-- jn(|x|>X_TLOSS, n)
  *	39-- yn(x>X_TLOSS, n)
- *	40-- gamma(finite) overflow
- *	41-- gamma(-integer)
+ *	40-- tgamma(finite) overflow
+ *	41-- tgamma(-integer)
  *	42-- pow(NaN,0.0)
  *	43-- +0**neg
  *	44-- exp2 overflow
@@ -829,8 +829,8 @@ static double zero = 0.0;	/* used as const */
 	    case 240:
 		/* gamma(finite) overflow */
 		exc.type = OVERFLOW;
-		exc.name = type < 100 ? "gamma" : (type < 200
-						   ? "gammaf" : "gammal");
+		exc.name = type < 100 ? "tgamma" : (type < 200
+						   ? "tgammaf" : "tgammal");
 		exc.retval = HUGE_VAL;
                 if (_LIB_VERSION == _POSIX_)
 		  __set_errno (ERANGE);
@@ -843,14 +843,14 @@ static double zero = 0.0;	/* used as const */
 	    case 241:
 		/* gamma(-integer) or gamma(0) */
 		exc.type = SING;
-		exc.name = type < 100 ? "gamma" : (type < 200
-						   ? "gammaf" : "gammal");
+		exc.name = type < 100 ? "tgamma" : (type < 200
+						   ? "tgammaf" : "tgammal");
 		exc.retval = NAN;
 		if (_LIB_VERSION == _POSIX_)
 		  __set_errno (EDOM);
 		else if (!matherr(&exc)) {
 		  if (_LIB_VERSION == _SVID_) {
-			(void) WRITE2("gamma: SING error\n", 18);
+			(void) WRITE2("tgamma: SING error\n", 18);
 			exc.retval = HUGE_VAL;
 		      }
 		  __set_errno (EDOM);
diff --git a/sysdeps/libm-ieee754/w_gammaf.c b/sysdeps/libm-ieee754/w_gammaf.c
deleted file mode 100644
index bc251b3554..0000000000
--- a/sysdeps/libm-ieee754/w_gammaf.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/* w_gammaf.c -- float version of w_gamma.c.
- * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
- */
-
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
-
-#if defined(LIBM_SCCS) && !defined(lint)
-static char rcsid[] = "$NetBSD: w_gammaf.c,v 1.4 1995/11/20 22:06:48 jtc Exp $";
-#endif
-
-#include "math.h"
-#include "math_private.h"
-
-#ifdef __STDC__
-	float __gammaf(float x)
-#else
-	float __gammaf(x)
-	float x;
-#endif
-{
-        float y;
-#ifndef _IEEE_LIBM
-	if (_LIB_VERSION == _SVID_)
-	  {
-	    y = __ieee754_lgammaf_r(x,&signgam);
-
-	    if(!__finitef(y)&&__finitef(x)) {
-	      if(__floorf(x)==x&&x<=(float)0.0)
-		/* lgammaf pole */
-		return (float)__kernel_standard((double)x,(double)x,115);
-	      else
-		/* lgammaf overflow */
-		return (float)__kernel_standard((double)x,(double)x,114);
-	    }
-	  }
-	else
-	  {
-#endif
-	    int local_signgam;
-	    y = __ieee754_gammaf_r(x,&local_signgam);
-	    if (local_signgam < 0) y = -y;
-#ifdef _IEEE_LIBM
-	    return y;
-#else
-	    if(_LIB_VERSION == _IEEE_) return y;
-
-	    if(!__finitef(y)&&__finitef(x)) {
-	      if(__floorf(x)==x&&x<=(float)0.0)
-		/* gammaf pole */
-		return (float)__kernel_standard((double)x,(double)x,141);
-	      else
-		/* gammaf overflow */
-		return (float)__kernel_standard((double)x,(double)x,140);
-	    }
-	  }
-	return y;
-#endif
-}
-weak_alias (__gammaf, gammaf)
diff --git a/sysdeps/libm-ieee754/w_gammal.c b/sysdeps/libm-ieee754/w_gammal.c
deleted file mode 100644
index 68328f652a..0000000000
--- a/sysdeps/libm-ieee754/w_gammal.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/* w_gammal.c -- long double version of w_gamma.c.
- * Conversion to long double by Ulrich Drepper,
- * Cygnus Support, drepper@cygnus.com.
- */
-
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
-
-#if defined(LIBM_SCCS) && !defined(lint)
-static char rcsid[] = "$NetBSD: $";
-#endif
-
-/* long double gammal(double x)
- * Return the Gamma function of x.
- */
-
-#include "math.h"
-#include "math_private.h"
-
-#ifdef __STDC__
-	long double __gammal(long double x)
-#else
-	long double __gammal(x)
-	long double x;
-#endif
-{
-        long double y;
-#ifndef _IEEE_LIBM
-	if (_LIB_VERSION == _SVID_)
-	  {
-	    y = __ieee754_lgammal_r(x,&signgam);
-
-	    if(!__finitel(y)&&__finitel(x)) {
-	      if(__floorl(x)==x&&x<=(long double)0.0)
-		/* lgamma pole */
-		return (long double)__kernel_standard((double)x,(double)x,15);
-	      else
-		/* lgamma overflow */
-		return (long double)__kernel_standard((double)x,(double)x,14);
-	    }
-	  }
-	else
-	  {
-#endif
-	    int local_signgam;
-	    y = __ieee754_gammal_r(x,&local_signgam);
-	    if (local_signgam < 0) y = -y;
-#ifdef _IEEE_LIBM
-	    return y;
-#else
-	    if(_LIB_VERSION == _IEEE_) return y;
-
-	    if(!__finitel(y)&&__finitel(x)) {
-	      if(__floorl(x)==x&&x<=0.0)
-                return __kernel_standard(x,x,241); /* gamma pole */
-	      else
-                return __kernel_standard(x,x,240); /* gamma overflow */
-	    }
-	  }
-	return y;
-#endif
-}
-weak_alias (__gammal, gammal)
diff --git a/sysdeps/libm-ieee754/w_lgamma.c b/sysdeps/libm-ieee754/w_lgamma.c
index bbb53f53e8..0cc62a1784 100644
--- a/sysdeps/libm-ieee754/w_lgamma.c
+++ b/sysdeps/libm-ieee754/w_lgamma.c
@@ -50,7 +50,11 @@ static char rcsid[] = "$NetBSD: w_lgamma.c,v 1.6 1995/05/10 20:49:24 jtc Exp $";
 #endif
 }
 weak_alias (__lgamma, lgamma)
+strong_alias (__lgamma, __gamma)
+weak_alias (__gamma, gamma)
 #ifdef NO_LONG_DOUBLE
 strong_alias (__lgamma, __lgammal)
 weak_alias (__lgamma, lgammal)
+strong_alias (__gamma, __gammal)
+weak_alias (__gamma, gammal)
 #endif
diff --git a/sysdeps/libm-ieee754/w_lgammaf.c b/sysdeps/libm-ieee754/w_lgammaf.c
index 369dee6749..4c64aa4130 100644
--- a/sysdeps/libm-ieee754/w_lgammaf.c
+++ b/sysdeps/libm-ieee754/w_lgammaf.c
@@ -49,3 +49,5 @@ static char rcsid[] = "$NetBSD: w_lgammaf.c,v 1.3 1995/05/10 20:49:30 jtc Exp $"
 #endif
 }
 weak_alias (__lgammaf, lgammaf)
+strong_alias (__lgammaf, __gammaf)
+weak_alias (__gammaf, gammaf)
diff --git a/sysdeps/libm-ieee754/w_lgammal.c b/sysdeps/libm-ieee754/w_lgammal.c
index 9db2ce2693..41104e47e4 100644
--- a/sysdeps/libm-ieee754/w_lgammal.c
+++ b/sysdeps/libm-ieee754/w_lgammal.c
@@ -54,3 +54,5 @@ static char rcsid[] = "$NetBSD: $";
 #endif
 }
 weak_alias (__lgammal, lgammal)
+strong_alias (__lgammal, __gammal)
+weak_alias (__gammal, gammal)
diff --git a/sysdeps/libm-ieee754/w_gamma.c b/sysdeps/libm-ieee754/w_tgamma.c
index 3511b67d77..2adbc2e14d 100644
--- a/sysdeps/libm-ieee754/w_gamma.c
+++ b/sysdeps/libm-ieee754/w_tgamma.c
@@ -23,50 +23,32 @@ static char rcsid[] = "$NetBSD: w_gamma.c,v 1.7 1995/11/20 22:06:43 jtc Exp $";
 #include "math_private.h"
 
 #ifdef __STDC__
-	double __gamma(double x)
+	double __tgamma(double x)
 #else
-	double __gamma(x)
+	double __tgamma(x)
 	double x;
 #endif
 {
         double y;
-#ifndef _IEEE_LIBM
-	if (_LIB_VERSION == _SVID_)
-	  {
-	    y = __ieee754_lgamma_r(x,&signgam);
-
-	    if(!__finite(y)&&__finite(x)) {
-	      if(__floor(x)==x&&x<=(double)0.0)
-		/* lgamma pole */
-		return __kernel_standard(x,x,15);
-	      else
-		/* lgamma overflow */
-		return __kernel_standard(x,x,14);
-	    }
-	  }
-	else
-	  {
-#endif
-	    int local_signgam;
-	    y = __ieee754_gamma_r(x,&local_signgam);
-	    if (local_signgam < 0) y = -y;
+	int local_signgam;
+	y = __ieee754_gamma_r(x,&local_signgam);
+	if (local_signgam < 0) y = -y;
 #ifdef _IEEE_LIBM
-	    return y;
+	return y;
 #else
-	    if(_LIB_VERSION == _IEEE_) return y;
+	if(_LIB_VERSION == _IEEE_) return y;
 
-	    if(!__finite(y)&&__finite(x)) {
-	      if(__floor(x)==x&&x<=0.0)
-                return __kernel_standard(x,x,41); /* gamma pole */
-	      else
-                return __kernel_standard(x,x,40); /* gamma overflow */
-	    }
-	  }
+	if(!__finite(y)&&__finite(x)) {
+	  if(__floor(x)==x&&x<=0.0)
+	    return __kernel_standard(x,x,41); /* tgamma pole */
+	  else
+	    return __kernel_standard(x,x,40); /* tgamma overflow */
+	}
 	return y;
 #endif
 }
-weak_alias (__gamma, gamma)
+weak_alias (__tgamma, tgamma)
 #ifdef NO_LONG_DOUBLE
-strong_alias (__gamma, __gammal)
-weak_alias (__gamma, gammal)
+strong_alias (__tgamma, __tgammal)
+weak_alias (__tgamma, tgammal)
 #endif
diff --git a/sysdeps/libm-ieee754/w_tgammaf.c b/sysdeps/libm-ieee754/w_tgammaf.c
new file mode 100644
index 0000000000..152f4be156
--- /dev/null
+++ b/sysdeps/libm-ieee754/w_tgammaf.c
@@ -0,0 +1,50 @@
+/* w_gammaf.c -- float version of w_gamma.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#if defined(LIBM_SCCS) && !defined(lint)
+static char rcsid[] = "$NetBSD: w_gammaf.c,v 1.4 1995/11/20 22:06:48 jtc Exp $";
+#endif
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+	float __tgammaf(float x)
+#else
+	float __tgammaf(x)
+	float x;
+#endif
+{
+        float y;
+	int local_signgam;
+	y = __ieee754_gammaf_r(x,&local_signgam);
+	if (local_signgam < 0) y = -y;
+#ifdef _IEEE_LIBM
+	return y;
+#else
+	if(_LIB_VERSION == _IEEE_) return y;
+
+	if(!__finitef(y)&&__finitef(x)) {
+	  if(__floorf(x)==x&&x<=(float)0.0)
+	    /* tgammaf pole */
+	    return (float)__kernel_standard((double)x,(double)x,141);
+	  else
+	    /* tgammaf overflow */
+	    return (float)__kernel_standard((double)x,(double)x,140);
+	}
+	return y;
+#endif
+}
+weak_alias (__tgammaf, tgammaf)
diff --git a/sysdeps/libm-ieee754/w_tgammal.c b/sysdeps/libm-ieee754/w_tgammal.c
new file mode 100644
index 0000000000..9efce2bb95
--- /dev/null
+++ b/sysdeps/libm-ieee754/w_tgammal.c
@@ -0,0 +1,53 @@
+/* w_gammal.c -- long double version of w_gamma.c.
+ * Conversion to long double by Ulrich Drepper,
+ * Cygnus Support, drepper@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#if defined(LIBM_SCCS) && !defined(lint)
+static char rcsid[] = "$NetBSD: $";
+#endif
+
+/* long double gammal(double x)
+ * Return the Gamma function of x.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+	long double __tgammal(long double x)
+#else
+	long double __tgammal(x)
+	long double x;
+#endif
+{
+        long double y;
+	int local_signgam;
+	y = __ieee754_gammal_r(x,&local_signgam);
+	if (local_signgam < 0) y = -y;
+#ifdef _IEEE_LIBM
+	return y;
+#else
+	if(_LIB_VERSION == _IEEE_) return y;
+
+	if(!__finitel(y)&&__finitel(x)) {
+	  if(__floorl(x)==x&&x<=0.0)
+	    return __kernel_standard(x,x,241); /* tgamma pole */
+	  else
+	    return __kernel_standard(x,x,240); /* tgamma overflow */
+	}
+	return y;
+#endif
+}
+weak_alias (__tgammal, tgammal)
diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c
index 8edde69337..abaf0b2676 100644
--- a/sysdeps/mach/hurd/dl-sysdep.c
+++ b/sysdeps/mach/hurd/dl-sysdep.c
@@ -240,7 +240,7 @@ open_file (const char *file_name, int mode,
   int nloops;
   error_t err;
 
-  assert (mode == O_RDONLY);
+  assert (!(mode & ~O_READ));
 
   startdir = _dl_hurd_data->portarray[file_name[0] == '/' ?
 				      INIT_PORT_CRDIR : INIT_PORT_CWDIR];
@@ -558,6 +558,38 @@ __mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
   return err ? (__ptr_t) __hurd_fail (err) : (__ptr_t) mapaddr;
 }
 
+int weak_function
+__fxstat (int vers, int fd, struct stat *buf)
+{
+  error_t err;
+  
+  assert (vers == _STAT_VER);
+  
+  err = __io_stat ((mach_port_t) fd, buf);
+  if (err)
+    return __hurd_fail (err);
+
+  return 0;
+  
+}
+
+int weak_function
+__xstat (int vers, const char *file, struct stat *buf)
+{
+  error_t err;
+  mach_port_t port;
+  
+  assert (vers == _STAT_VER);
+
+  err = open_file (file, 0, &port, buf);
+  if (err)
+    return __hurd_fail (err);
+
+  __mach_port_deallocate (__mach_task_self (), port);
+
+  return 0;
+}
+
 void weak_function
 _exit (int status)
 {
@@ -567,37 +599,6 @@ _exit (int status)
     __mach_task_self_ = (__mach_task_self) ();
 }
 
-/* Read the whole contents of FILE into new mmap'd space with given
-   protections.  The size of the file is returned in SIZE.  */
-void *
-weak_function
-_dl_sysdep_read_whole_file (const char *file, size_t *size, int prot)
-{
-  struct stat stat;
-  mach_port_t memobj_rd;
-  void *contents;
-  error_t err = open_file (file, O_RDONLY, &memobj_rd, &stat);
-
-  if (! err)
-    {
-      /* Map a copy of the file contents.  */
-      contents = __mmap (0, stat.st_size, prot, MAP_COPY, memobj_rd, 0);
-      if (contents == (void *)-1)
-	contents = 0;
-      else
-	*size = stat.st_size;
-
-      __mach_port_deallocate (__mach_task_self (), memobj_rd);
-    }
-  else
-    {
-      __hurd_fail (err);
-      contents = 0;
-    }
-
-  return contents;
-}
-
 /* This function is called by interruptible RPC stubs.  For initial
    dynamic linking, just use the normal mach_msg.  Since this defn is
    weak, the real defn in libc.so will override it if we are linked into
diff --git a/sysdeps/unix/sysv/linux/recvmsg.c b/sysdeps/unix/sysv/linux/recvmsg.c
index 3795d91b90..66970bcb89 100644
--- a/sysdeps/unix/sysv/linux/recvmsg.c
+++ b/sysdeps/unix/sysv/linux/recvmsg.c
@@ -89,5 +89,4 @@ __libc_recvmsg (int fd, struct msghdr *message, int flags)
   return ret;
 }
 
-weak_alias (__libc_recvmsg, __recvmsg)
 weak_alias (__libc_recvmsg, recvmsg)
diff --git a/sysdeps/unix/sysv/linux/sendmsg.c b/sysdeps/unix/sysv/linux/sendmsg.c
index c0f009d0ac..304aa6e2a1 100644
--- a/sysdeps/unix/sysv/linux/sendmsg.c
+++ b/sysdeps/unix/sysv/linux/sendmsg.c
@@ -121,5 +121,4 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
   return __syscall_sendmsg (fd, message, flags);
 }
 
-weak_alias (__libc_sendmsg, __sendmsg)
 weak_alias (__libc_sendmsg, sendmsg)
diff --git a/version.h b/version.h
index 7223b3a99b..9bc6abc972 100644
--- a/version.h
+++ b/version.h
@@ -1,4 +1,4 @@
 /* This file just defines the current version number of libc.  */
 
 #define RELEASE "experimental"
-#define VERSION "2.0.94"
+#define VERSION "2.0.95"