From e852e889444a8bf27f3e5075d064e9922b38e7e2 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Tue, 28 Jul 1998 16:26:04 +0000 Subject: [PATCH] Update. 1998-07-28 Ulrich Drepper * math/libm-test.c (tgamma_test): Remove redundant tests. 1998-07-28 16:20 Ulrich Drepper * 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 . * posix/globtest.sh: Add test for this bug. 1998-07-28 Mark Kettenis * io/sys/statfs.h: Fix typos. * io/sys/statvfs.h: Fix typos. 1998-07-28 Ulrich Drepper * 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 * 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 * stdlib/strtol.c (STRTOL_LONG_MAX): Correct typo in last patch - define as LONG_MAX. 1998-07-28 09:31 Ulrich Drepper * 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 * nscd/nscd_getgr_r.c (__nscd_getgr_r): Deal with missing UIO_MAXIOV. 1998-07-28 Mark Kettenis * 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. --- ChangeLog | 106 ++++ manual/math.texi | 29 +- manual/stdio.texi | 38 +- math/Makefile | 2 +- math/Versions | 1 + math/bits/mathcalls.h | 6 +- math/libm-test.c | 67 +- nis/Banner | 2 +- nis/Makefile | 6 +- nis/Versions | 7 +- nis/nis_call.c | 234 +++---- nis/nis_checkpoint.c | 2 +- nis/nis_file.c | 32 +- nis/nis_findserv.c | 22 +- nis/nis_intern.h | 35 +- nis/nis_lookup.c | 166 +++-- nis/nis_mkdir.c | 2 +- nis/nis_ping.c | 2 +- nis/nis_rmdir.c | 2 +- nis/nis_server.c | 4 +- nis/nis_table.c | 413 ++++++++----- nis/nis_util.c | 2 +- nis/rpcsvc/nislib.h | 31 +- nscd/connections.c | 22 +- nscd/nscd_getgr_r.c | 23 +- posix/globtest.sh | 9 + stdio-common/printf-parse.h | 25 +- stdio-common/vfprintf.c | 67 +- stdio-common/vfscanf.c | 28 +- stdlib/strtol.c | 2 +- sunrpc/Makefile | 3 +- sunrpc/Versions | 5 +- sunrpc/clnt_gen.c | 16 + sunrpc/clnt_unix.c | 573 ++++++++++++++++++ sunrpc/key_call.c | 200 +++++- sunrpc/rpc/clnt.h | 22 +- sunrpc/rpc/svc.h | 7 + sunrpc/svc_authux.c | 18 +- sunrpc/svc_tcp.c | 4 +- sunrpc/svc_unix.c | 496 +++++++++++++++ sysdeps/generic/glob.c | 61 +- sysdeps/libm-ieee754/k_standard.c | 14 +- sysdeps/libm-ieee754/w_gammaf.c | 68 --- sysdeps/libm-ieee754/w_gammal.c | 71 --- sysdeps/libm-ieee754/w_lgamma.c | 4 + sysdeps/libm-ieee754/w_lgammaf.c | 2 + sysdeps/libm-ieee754/w_lgammal.c | 2 + .../libm-ieee754/{w_gamma.c => w_tgamma.c} | 50 +- sysdeps/libm-ieee754/w_tgammaf.c | 50 ++ sysdeps/libm-ieee754/w_tgammal.c | 53 ++ sysdeps/mach/hurd/dl-sysdep.c | 65 +- sysdeps/unix/sysv/linux/recvmsg.c | 1 - sysdeps/unix/sysv/linux/sendmsg.c | 1 - version.h | 2 +- 54 files changed, 2459 insertions(+), 716 deletions(-) create mode 100644 sunrpc/clnt_unix.c create mode 100644 sunrpc/svc_unix.c delete mode 100644 sysdeps/libm-ieee754/w_gammaf.c delete mode 100644 sysdeps/libm-ieee754/w_gammal.c rename sysdeps/libm-ieee754/{w_gamma.c => w_tgamma.c} (50%) create mode 100644 sysdeps/libm-ieee754/w_tgammaf.c create mode 100644 sysdeps/libm-ieee754/w_tgammal.c diff --git a/ChangeLog b/ChangeLog index 98f052420f..3ada154100 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,109 @@ +1998-07-28 Ulrich Drepper + + * math/libm-test.c (tgamma_test): Remove redundant tests. + +1998-07-28 16:20 Ulrich Drepper + + * 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 . + + * posix/globtest.sh: Add test for this bug. + +1998-07-28 Mark Kettenis + + * io/sys/statfs.h: Fix typos. + * io/sys/statvfs.h: Fix typos. + +1998-07-28 Ulrich Drepper + + * 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 + + * 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 + + * stdlib/strtol.c (STRTOL_LONG_MAX): Correct typo in last patch - + define as LONG_MAX. + +1998-07-28 09:31 Ulrich Drepper + + * 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 + + * nscd/nscd_getgr_r.c (__nscd_getgr_r): Deal with missing UIO_MAXIOV. + +1998-07-28 Mark Kettenis + + * 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 * 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) + if (__nis_findfastest (dbp) < 1) { - dbp->server_used = cinfo->server_used; - dbp->current_ep = cinfo->current_ep; - dbp->class = cinfo->class; - } - else 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; @@ -515,51 +512,57 @@ first_shoot (const_nis_name name, directory_obj *dir, u_long flags) return NULL; } +nis_error +__nisfind_server (const_nis_name name, directory_obj **dir) +{ + 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) + { + nis_error status; + directory_obj *obj; + + *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); + if (obj == NULL) + { + *dir = rec_dirsearch (name, *dir, &status); + if (*dir == NULL) + return status; + } + else + *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; - cache2_info cinfo = {-1, -1, -1}; int saved_errno = errno; - if (name == NULL) - return NIS_BADNAME; - - /* Search in local cache. In the moment, we ignore the fastest server */ - if (!(flags & NO_CACHE)) - dir = __nis_cache_search (name, flags, &cinfo); - - 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; - } - - /* Try at first, if servers in "dir" know our object */ - obj = first_shoot (name, dir, flags); - if (obj == NULL) - { - dir = rec_dirsearch (name, dir, flags, &status); - if (dir == NULL) - { - __set_errno (saved_errno); - return status; - } - } - else - dir = obj; - } + retcode = __nisfind_server (name, &dir); + if (retcode != NIS_SUCCESS) + return retcode; if (flags & MASTER_ONLY) { @@ -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; + } + + 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; + } + + 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 (NIS_RES_STATUS (res) == NIS_SUCCESS) + { + 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; + } + } + 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; + } + 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: - 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) - { - NIS_RES_STATUS (res) = NIS_LINKNAMEERROR; - ++done; - break; - } - 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 - ++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 */ + 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; + dir_binding bptr; + directory_obj *dir = NULL; - 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; - } + memset (res, '\0', sizeof (nis_result)); - /* 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; - } + status = __nisfind_server (ibreq->ibr_name, &dir); + if (status != NIS_SUCCESS) + { + NIS_RES_STATUS (res) = status; + return res; + } - /* 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; + 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; + } - p = table_path; + 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; + } - while (((ntable = strsep (&p, ":")) != NULL) && !done) - { - char *c; - - if (res != NULL) - nis_freeresult (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) - { - NIS_RES_STATUS (res) = NIS_LINKNAMEERROR; - ++done; - break; - } - 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) - { - 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; - } - 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; - ++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) - { - ++done; - break; - } - ibreq->ibr_name = names[name_nr]; - break; - } } - } /* End of not FOLLOW_PATH. */ + + 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) + { + 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; + } + 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) + { + if (have_tablepath) + free (tablepath); + __nisbind_destroy (&bptr); + nis_free_directory (dir); + return NULL; + } + first_try = 1; + goto again; + } + } + else + ++done; + 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; + 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; + } + + __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 , 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 #include -#include +#include #include +#include #define NDEBUG 1 #include @@ -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 #include #include +#include #include #include #include @@ -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 #include #include +#include #include #include #include @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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 #include +#include #include #include #include @@ -47,6 +48,7 @@ #include #include #include +#include #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 #include #include +#include __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 +#include +#include +#include +#include +#include +#include +#include + +/* + * 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 similarity index 50% rename from sysdeps/libm-ieee754/w_gamma.c rename to 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"