aboutsummaryrefslogtreecommitdiff
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"