1998-07-28  Ulrich Drepper  <drepper@cygnus.com>

	* math/libm-test.c (tgamma_test): Remove redundant tests.

1998-07-28 16:20  Ulrich Drepper  <drepper@cygnus.com>

	* sysdeps/generic/glob.c: Correct problems with */foo and GLOB_NOCHECK
	where foo does not exist in any of the subdirectories.
	Reported by Paul D. Smith <psmith@BayNetworks.COM>.

	* posix/globtest.sh: Add test for this bug.

1998-07-28  Mark Kettenis  <kettenis@phys.uva.nl>

	* io/sys/statfs.h: Fix typos.
	* io/sys/statvfs.h: Fix typos.

1998-07-28  Ulrich Drepper  <drepper@cygnus.com>

	* version.h (VERSION): Bump to 2.0.95.

	* math/Makefile (libm-calls): Remove w_gamma, add w_tgamma.
	* math/Versions [GLIBC_2.1]: Add tgamma, tgammaf, and tgammal.
	* math/libm-test.c: Split old gamma_test and move half of it in new
	function tgamma_test.
	* math/bits/mathcalls.h: Add declaration of tgamma.
	* sysdeps/libm-ieee754/k_standard.c: Change gamma errors into
	tgamma errors.
	* sysdeps/libm-ieee754/w_gamma.c: Remove lgamma compatibility code
	and rename to ...
	* sysdeps/libm-ieee754/w_tgamma.c: ... this.  New file.
	* sysdeps/libm-ieee754/w_gammaf.c: Remove lgammaf compatibility code
	and rename to ...
	* sysdeps/libm-ieee754/w_tgammaf.c: ... this.  New file.
	* sysdeps/libm-ieee754/w_gammal.c: Remove lgammal compatibility code
	and rename to ...
	* sysdeps/libm-ieee754/w_tgammal.c: ... this.  New file.
	* sysdeps/libm-ieee754/w_lgamma.c: Add gamma as weak alias.
	* sysdeps/libm-ieee754/w_lgammaf.c: Likewise.
	* sysdeps/libm-ieee754/w_lgammal.c: Likewise.

	* stgdio-common/printf-parse.h: Implement handling of j, t, and z
	modifiers.
	* stdio-common/vfprintf.c: Likewise.
	* stdio-common/vfscanf.c: Likewise.
	* manual/stdio.texi: Document new printf/scanf modifiers.

	* sysdeps/unix/sysv/linux/recvmsg.c: Remove alias __recvmsg.
	* sysdeps/unix/sysv/linux/sendmsg.c: Remove alias __sendmsg.

1998-07-28  Thorsten Kukuk  <kukuk@vt.uni-paderborn.de>

	* sunrpc/Makefile (routines): Add clnt_unix and svc_unix.
	* sunrpc/Versions: Add new *unix_create functions.
	* sunrpc/clnt_gen.c: Add support for RPC over AF_UNIX.
	* sunrpc/clnt_unix.c: New, client side of RPC over AF_UNIX.
	* sunrpc/key_call.c: Use RPC over AF_UNIX for communication
	with keyserv daemon.
	* sunrpc/rpc/clnt.h: Add AF_UNIX based RPC function prototypes.
	* sunrpc/rpc/svc.h: Likewise.
	* sunrpc/svc_authux.c: Copy internal auth flavor if none is given.
	* sunrpc/svc_tcp.c: Fix typos.
	* sunrpc/svc_unix.c: New, server side of AF_UNIX based RPC.

	* nis/Makefile: Remove currently not working cache functions.
	* nis/Versions: Add __nisbind_* functions for rpc.nisd.
	* nis/nis_call.c: Rewrite binding to a NIS+ server to reuse
	CLIENT handles.
	* nis/nis_file.c: Fix memory leaks.
	* nis/nis_intern.h: Move internal structs from here ...
	* nis/rpcsvc/nislib.h: ... to here for NIS+ server and tools.
	* nis/nis_lookup.c: Try at first if last client handle works.
	* nis/nis_table.c: Likewise.
	* nis/nis_checkpoint.c: Adjust __do_niscall2 parameters.
	* nis/nis_mkdir.c: Likewise.
	* nis/nis_ping.c: Likewise.
	* nis/nis_rmdir.c: Likewise.
	* nis/nis_server.c: Likewise.
	* nis/nis_util.c: Likewise.
	* nis/nis_findserv.c (__nis_findfastest): Little optimization.

1998-07-28  Andreas Jaeger  <aj@arthur.rhein-neckar.de>

	* stdlib/strtol.c (STRTOL_LONG_MAX): Correct typo in last patch -
	define as LONG_MAX.

1998-07-28 09:31  Ulrich Drepper  <drepper@cygnus.com>

	* nscd/connections.c (gr_send_answer): Deal with missing UIO_MAXIOV.
	Correct test whether writev send all data.
	* nscd/nscd_getgr_r.c (__nscd_getgr_r): Correct test whether readv
	received all data.

1998-07-28  Mark Kettenis  <kettenis@phys.uva.nl>

	* nscd/nscd_getgr_r.c (__nscd_getgr_r): Deal with missing UIO_MAXIOV.

1998-07-28  Mark Kettenis  <kettenis@phys.uva.nl>

	* sysdeps/mach/hurd/dl-sysdep.c (open_file): Change assert call to
	allow mode to be 0.
	(__xstat): New function.
	(__fxstat): New function.
	(_dl_sysdep_read_whole_file): Removed.  The implementation in
	`elf/dl-misc.c' now also works for the Hurd.
This commit is contained in:
Ulrich Drepper 1998-07-28 16:26:04 +00:00
parent c9243dacea
commit e852e88944
54 changed files with 2459 additions and 716 deletions

106
ChangeLog
View File

@ -1,3 +1,109 @@
1998-07-28 Ulrich Drepper <drepper@cygnus.com>
* math/libm-test.c (tgamma_test): Remove redundant tests.
1998-07-28 16:20 Ulrich Drepper <drepper@cygnus.com>
* sysdeps/generic/glob.c: Correct problems with */foo and GLOB_NOCHECK
where foo does not exist in any of the subdirectories.
Reported by Paul D. Smith <psmith@BayNetworks.COM>.
* posix/globtest.sh: Add test for this bug.
1998-07-28 Mark Kettenis <kettenis@phys.uva.nl>
* io/sys/statfs.h: Fix typos.
* io/sys/statvfs.h: Fix typos.
1998-07-28 Ulrich Drepper <drepper@cygnus.com>
* version.h (VERSION): Bump to 2.0.95.
* math/Makefile (libm-calls): Remove w_gamma, add w_tgamma.
* math/Versions [GLIBC_2.1]: Add tgamma, tgammaf, and tgammal.
* math/libm-test.c: Split old gamma_test and move half of it in new
function tgamma_test.
* math/bits/mathcalls.h: Add declaration of tgamma.
* sysdeps/libm-ieee754/k_standard.c: Change gamma errors into
tgamma errors.
* sysdeps/libm-ieee754/w_gamma.c: Remove lgamma compatibility code
and rename to ...
* sysdeps/libm-ieee754/w_tgamma.c: ... this. New file.
* sysdeps/libm-ieee754/w_gammaf.c: Remove lgammaf compatibility code
and rename to ...
* sysdeps/libm-ieee754/w_tgammaf.c: ... this. New file.
* sysdeps/libm-ieee754/w_gammal.c: Remove lgammal compatibility code
and rename to ...
* sysdeps/libm-ieee754/w_tgammal.c: ... this. New file.
* sysdeps/libm-ieee754/w_lgamma.c: Add gamma as weak alias.
* sysdeps/libm-ieee754/w_lgammaf.c: Likewise.
* sysdeps/libm-ieee754/w_lgammal.c: Likewise.
* stgdio-common/printf-parse.h: Implement handling of j, t, and z
modifiers.
* stdio-common/vfprintf.c: Likewise.
* stdio-common/vfscanf.c: Likewise.
* manual/stdio.texi: Document new printf/scanf modifiers.
* sysdeps/unix/sysv/linux/recvmsg.c: Remove alias __recvmsg.
* sysdeps/unix/sysv/linux/sendmsg.c: Remove alias __sendmsg.
1998-07-28 Thorsten Kukuk <kukuk@vt.uni-paderborn.de>
* sunrpc/Makefile (routines): Add clnt_unix and svc_unix.
* sunrpc/Versions: Add new *unix_create functions.
* sunrpc/clnt_gen.c: Add support for RPC over AF_UNIX.
* sunrpc/clnt_unix.c: New, client side of RPC over AF_UNIX.
* sunrpc/key_call.c: Use RPC over AF_UNIX for communication
with keyserv daemon.
* sunrpc/rpc/clnt.h: Add AF_UNIX based RPC function prototypes.
* sunrpc/rpc/svc.h: Likewise.
* sunrpc/svc_authux.c: Copy internal auth flavor if none is given.
* sunrpc/svc_tcp.c: Fix typos.
* sunrpc/svc_unix.c: New, server side of AF_UNIX based RPC.
* nis/Makefile: Remove currently not working cache functions.
* nis/Versions: Add __nisbind_* functions for rpc.nisd.
* nis/nis_call.c: Rewrite binding to a NIS+ server to reuse
CLIENT handles.
* nis/nis_file.c: Fix memory leaks.
* nis/nis_intern.h: Move internal structs from here ...
* nis/rpcsvc/nislib.h: ... to here for NIS+ server and tools.
* nis/nis_lookup.c: Try at first if last client handle works.
* nis/nis_table.c: Likewise.
* nis/nis_checkpoint.c: Adjust __do_niscall2 parameters.
* nis/nis_mkdir.c: Likewise.
* nis/nis_ping.c: Likewise.
* nis/nis_rmdir.c: Likewise.
* nis/nis_server.c: Likewise.
* nis/nis_util.c: Likewise.
* nis/nis_findserv.c (__nis_findfastest): Little optimization.
1998-07-28 Andreas Jaeger <aj@arthur.rhein-neckar.de>
* stdlib/strtol.c (STRTOL_LONG_MAX): Correct typo in last patch -
define as LONG_MAX.
1998-07-28 09:31 Ulrich Drepper <drepper@cygnus.com>
* nscd/connections.c (gr_send_answer): Deal with missing UIO_MAXIOV.
Correct test whether writev send all data.
* nscd/nscd_getgr_r.c (__nscd_getgr_r): Correct test whether readv
received all data.
1998-07-28 Mark Kettenis <kettenis@phys.uva.nl>
* nscd/nscd_getgr_r.c (__nscd_getgr_r): Deal with missing UIO_MAXIOV.
1998-07-28 Mark Kettenis <kettenis@phys.uva.nl>
* sysdeps/mach/hurd/dl-sysdep.c (open_file): Change assert call to
allow mode to be 0.
(__xstat): New function.
(__fxstat): New function.
(_dl_sysdep_read_whole_file): Removed. The implementation in
`elf/dl-misc.c' now also works for the Hurd.
1998-07-27 22:25 Ulrich Drepper <drepper@cygnus.com>
* sysdeps/generic/glob.c: Handle ~ and ~NAME case correctly.

View File

@ -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

View File

@ -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}

View File

@ -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 \

View File

@ -111,6 +111,7 @@ libm {
scalbln; scalblnf; scalblnl;
sincos; sincosf; sincosl;
trunc; truncf; truncl;
tgamma; tgammaf; tgammal;
# complex functions
cabs; cabsf; cabsl;

View File

@ -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

View File

@ -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 */

View File

@ -1 +1 @@
NIS(YP)/NIS+ NSS modules 0.17 by Thorsten Kukuk
NIS(YP)/NIS+ NSS modules 0.18 by Thorsten Kukuk

View File

@ -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\

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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
{

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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:

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1997 Free Software Foundation, Inc.
/* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
@ -247,6 +247,35 @@ extern u_long __nis_hash __P ((const void *keyarg, register size_t len));
extern int __nis_lock_cache __P ((void));
extern int __nis_unlock_cache __P ((void));
/* (XXX INTERNAL FUNCTIONS, ONLY FOR rpc.nisd AND glibc !!) */
#if defined (NIS_INTERNAL) || defined (_LIBC)
struct dir_binding
{
CLIENT *clnt; /* RPC CLIENT handle */
nis_server *server_val; /* List of servers */
u_int server_len; /* # of servers */
u_int server_used; /* Which server we are bind in the moment ? */
u_int current_ep; /* Which endpoint of the server are in use? */
u_int trys; /* How many server have we tried ? */
u_int class; /* From which class is server_val ? */
bool_t master_only; /* Is only binded to the master */
bool_t use_auth; /* Do we use AUTH ? */
bool_t use_udp; /* Do we use UDP ? */
struct sockaddr_in addr; /* Server's IP address */
int socket; /* Server's local socket */
};
typedef struct dir_binding dir_binding;
extern nis_error __nisbind_create __P ((dir_binding *, const nis_server *,
u_int, u_long));
extern nis_error __nisbind_connect __P ((dir_binding *));
extern nis_error __nisbind_next __P ((dir_binding *));
extern void __nisbind_destroy __P ((dir_binding *));
extern nis_error __nisfind_server __P ((const_nis_name, directory_obj **));
#endif
__END_DECLS
#endif /* __RPCSVC_NISLIB_H__ */

View File

@ -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));
}

View File

@ -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;

View File

@ -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

View File

@ -19,8 +19,9 @@
#include <ctype.h>
#include <printf.h>
#include <string.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#define NDEBUG 1
#include <assert.h>
@ -271,7 +272,8 @@ parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec,
spec->info.is_char = 0;
if (*format == L_('h') || *format == L_('l') || *format == L_('L') ||
*format == L_('Z') || *format == L_('q'))
*format == L_('Z') || *format == L_('q') || *format == L_('z') ||
*format == L_('t') || *format == L_('j'))
switch (*format++)
{
case L_('h'):
@ -297,11 +299,24 @@ parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec,
/* 4.4 uses this for long long. */
spec->info.is_long_double = 1;
break;
case L_('z'):
case L_('Z'):
/* int's are size_t's. */
assert (sizeof(size_t) <= sizeof(unsigned long long int));
spec->info.is_longlong = sizeof(size_t) > sizeof(unsigned long int);
spec->info.is_long = sizeof(size_t) > sizeof(unsigned int);
assert (sizeof (size_t) <= sizeof (unsigned long long int));
spec->info.is_longlong = sizeof (size_t) > sizeof (unsigned long int);
spec->info.is_long = sizeof (size_t) > sizeof (unsigned int);
break;
case L_('t'):
assert (sizeof (ptrdiff_t) <= sizeof (unsigned long long int));
spec->info.is_longlong = (sizeof (ptrdiff_t)
> sizeof (unsigned long int));
spec->info.is_long = sizeof (ptrdiff_t) > sizeof (unsigned int);
break;
case L_('j'):
assert (sizeof (intmax_t) <= sizeof (unsigned long long int));
spec->info.is_longlong = (sizeof (intmax_t)
> sizeof (unsigned long int));
spec->info.is_long = sizeof (intmax_t) > sizeof (unsigned int);
break;
}

View File

@ -20,6 +20,7 @@
#include <limits.h>
#include <printf.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <wchar.h>
@ -250,14 +251,14 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
0, 0, 0, 0,
0, /* 'a' */ 26, 0, /* 'c' */ 20,
/* 'd' */ 15, /* 'e' */ 19, /* 'f' */ 19, /* 'g' */ 19,
/* 'h' */ 10, /* 'i' */ 15, 0, 0,
/* 'h' */ 10, /* 'i' */ 15, /* 'j' */ 28, 0,
/* 'l' */ 11, /* 'm' */ 24, /* 'n' */ 23, /* 'o' */ 17,
/* 'p' */ 22, /* 'q' */ 12, 0, /* 's' */ 21,
0, /* 'u' */ 16, 0, 0,
/* 'x' */ 18
/* 't' */ 27, /* 'u' */ 16, 0, 0,
/* 'x' */ 18, 0, /* 'z' */ 13
};
#define NOT_IN_JUMP_RANGE(Ch) ((Ch) < ' ' || (Ch) > 'x')
#define NOT_IN_JUMP_RANGE(Ch) ((Ch) < ' ' || (Ch) > 'z')
#define CHAR_CLASS(Ch) (jump_table[(int) (Ch) - ' '])
#define JUMP(ChExpr, table) \
do \
@ -272,7 +273,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
#define STEP0_3_TABLE \
/* Step 0: at the beginning. */ \
static const void *step0_jumps[27] = \
static const void *step0_jumps[29] = \
{ \
REF (form_unknown), \
REF (flag_space), /* for ' ' */ \
@ -287,7 +288,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
REF (mod_half), /* for 'h' */ \
REF (mod_long), /* for 'l' */ \
REF (mod_longlong), /* for 'L', 'q' */ \
REF (mod_size_t), /* for 'Z' */ \
REF (mod_size_t), /* for 'z', 'Z' */ \
REF (form_percent), /* for '%' */ \
REF (form_integer), /* for 'd', 'i' */ \
REF (form_unsigned), /* for 'u' */ \
@ -300,10 +301,12 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
REF (form_number), /* for 'n' */ \
REF (form_strerror), /* for 'm' */ \
REF (form_wcharacter), /* for 'C' */ \
REF (form_floathex) /* for 'A', 'a' */ \
REF (form_floathex), /* for 'A', 'a' */ \
REF (mod_ptrdiff_t), /* for 't' */ \
REF (mod_intmax_t), /* for 'j' */ \
}; \
/* Step 1: after processing width. */ \
static const void *step1_jumps[27] = \
static const void *step1_jumps[29] = \
{ \
REF (form_unknown), \
REF (form_unknown), /* for ' ' */ \
@ -318,7 +321,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
REF (mod_half), /* for 'h' */ \
REF (mod_long), /* for 'l' */ \
REF (mod_longlong), /* for 'L', 'q' */ \
REF (mod_size_t), /* for 'Z' */ \
REF (mod_size_t), /* for 'z', 'Z' */ \
REF (form_percent), /* for '%' */ \
REF (form_integer), /* for 'd', 'i' */ \
REF (form_unsigned), /* for 'u' */ \
@ -331,10 +334,12 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
REF (form_number), /* for 'n' */ \
REF (form_strerror), /* for 'm' */ \
REF (form_wcharacter), /* for 'C' */ \
REF (form_floathex) /* for 'A', 'a' */ \
REF (form_floathex), /* for 'A', 'a' */ \
REF (mod_ptrdiff_t), /* for 't' */ \
REF (mod_intmax_t) /* for 'j' */ \
}; \
/* Step 2: after processing precision. */ \
static const void *step2_jumps[27] = \
static const void *step2_jumps[29] = \
{ \
REF (form_unknown), \
REF (form_unknown), /* for ' ' */ \
@ -349,7 +354,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
REF (mod_half), /* for 'h' */ \
REF (mod_long), /* for 'l' */ \
REF (mod_longlong), /* for 'L', 'q' */ \
REF (mod_size_t), /* for 'Z' */ \
REF (mod_size_t), /* for 'z', 'Z' */ \
REF (form_percent), /* for '%' */ \
REF (form_integer), /* for 'd', 'i' */ \
REF (form_unsigned), /* for 'u' */ \
@ -362,10 +367,12 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
REF (form_number), /* for 'n' */ \
REF (form_strerror), /* for 'm' */ \
REF (form_wcharacter), /* for 'C' */ \
REF (form_floathex) /* for 'A', 'a' */ \
REF (form_floathex), /* for 'A', 'a' */ \
REF (mod_ptrdiff_t), /* for 't' */ \
REF (mod_intmax_t) /* for 'j' */ \
}; \
/* Step 3a: after processing first 'h' modifier. */ \
static const void *step3a_jumps[27] = \
static const void *step3a_jumps[29] = \
{ \
REF (form_unknown), \
REF (form_unknown), /* for ' ' */ \
@ -380,7 +387,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
REF (mod_halfhalf), /* for 'h' */ \
REF (form_unknown), /* for 'l' */ \
REF (form_unknown), /* for 'L', 'q' */ \
REF (form_unknown), /* for 'Z' */ \
REF (form_unknown), /* for 'z', 'Z' */ \
REF (form_percent), /* for '%' */ \
REF (form_integer), /* for 'd', 'i' */ \
REF (form_unsigned), /* for 'u' */ \
@ -393,10 +400,12 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
REF (form_number), /* for 'n' */ \
REF (form_unknown), /* for 'm' */ \
REF (form_unknown), /* for 'C' */ \
REF (form_unknown) /* for 'A', 'a' */ \
REF (form_unknown), /* for 'A', 'a' */ \
REF (form_unknown), /* for 't' */ \
REF (form_unknown) /* for 'j' */ \
}; \
/* Step 3b: after processing first 'l' modifier. */ \
static const void *step3b_jumps[27] = \
static const void *step3b_jumps[29] = \
{ \
REF (form_unknown), \
REF (form_unknown), /* for ' ' */ \
@ -411,7 +420,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
REF (form_unknown), /* for 'h' */ \
REF (mod_longlong), /* for 'l' */ \
REF (form_unknown), /* for 'L', 'q' */ \
REF (form_unknown), /* for 'Z' */ \
REF (form_unknown), /* for 'z', 'Z' */ \
REF (form_percent), /* for '%' */ \
REF (form_integer), /* for 'd', 'i' */ \
REF (form_unsigned), /* for 'u' */ \
@ -424,12 +433,14 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
REF (form_number), /* for 'n' */ \
REF (form_strerror), /* for 'm' */ \
REF (form_wcharacter), /* for 'C' */ \
REF (form_floathex) /* for 'A', 'a' */ \
REF (form_floathex), /* for 'A', 'a' */ \
REF (form_unknown), /* for 't' */ \
REF (form_unknown) /* for 'j' */ \
}
#define STEP4_TABLE \
/* Step 4: processing format specifier. */ \
static const void *step4_jumps[27] = \
static const void *step4_jumps[29] = \
{ \
REF (form_unknown), \
REF (form_unknown), /* for ' ' */ \
@ -444,7 +455,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
REF (form_unknown), /* for 'h' */ \
REF (form_unknown), /* for 'l' */ \
REF (form_unknown), /* for 'L', 'q' */ \
REF (form_unknown), /* for 'Z' */ \
REF (form_unknown), /* for 'z', 'Z' */ \
REF (form_percent), /* for '%' */ \
REF (form_integer), /* for 'd', 'i' */ \
REF (form_unsigned), /* for 'u' */ \
@ -457,7 +468,9 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
REF (form_number), /* for 'n' */ \
REF (form_strerror), /* for 'm' */ \
REF (form_wcharacter), /* for 'C' */ \
REF (form_floathex) /* for 'A', 'a' */ \
REF (form_floathex), /* for 'A', 'a' */ \
REF (form_unknown), /* for 't' */ \
REF (form_unknown) /* for 'j' */ \
}
@ -1178,6 +1191,16 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
is_long = sizeof (size_t) > sizeof (unsigned int);
JUMP (*++f, step4_jumps);
LABEL (mod_ptrdiff_t):
is_longlong = sizeof (ptrdiff_t) > sizeof (unsigned long int);
is_long = sizeof (ptrdiff_t) > sizeof (unsigned int);
JUMP (*++f, step4_jumps);
LABEL (mod_intmax_t):
is_longlong = sizeof (intmax_t) > sizeof (unsigned long int);
is_long = sizeof (intmax_t) > sizeof (unsigned int);
JUMP (*++f, step4_jumps);
/* Process current format. */
while (1)
{

View File

@ -21,6 +21,7 @@
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wctype.h>
@ -407,7 +408,8 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
width = -1;
/* Check for type modifiers. */
while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'a' || *f == 'q')
while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'a' || *f == 'q'
|| *f == 'z' || *f == 't' || *f == 'j')
switch (*f++)
{
case 'h':
@ -459,6 +461,30 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
arg and fill it in with a malloc'd pointer. */
flags |= MALLOC;
break;
case 'z':
if (flags & (SHORT|LONGDBL|CHAR))
conv_error ();
if (sizeof (size_t) > sizeof (unsigned long int))
flags |= LONGDBL;
else if (sizeof (size_t) > sizeof (unsigned int))
flags |= LONG;
break;
case 'j':
if (flags & (SHORT|LONGDBL|CHAR))
conv_error ();
if (sizeof (intmax_t) > sizeof (unsigned long int))
flags |= LONGDBL;
else if (sizeof (intmax_t) > sizeof (unsigned int))
flags |= LONG;
break;
case 't':
if (flags & (SHORT|LONGDBL|CHAR))
conv_error ();
if (sizeof (ptrdiff_t) > sizeof (unsigned long int))
flags |= LONGDBL;
else if (sizeof (ptrdiff_t) > sizeof (unsigned int))
flags |= LONG;
break;
}
/* End of the format string? */

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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,

573
sunrpc/clnt_unix.c Normal file
View File

@ -0,0 +1,573 @@
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* clnt_unix.c, Implements a TCP/IP based, client side RPC.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* TCP based RPC supports 'batched calls'.
* A sequence of calls may be batched-up in a send buffer. The rpc call
* return immediately to the client even though the call was not necessarily
* sent. The batching occurs if the results' xdr routine is NULL (0) AND
* the rpc timeout value is zero (see clnt.h, rpc).
*
* Clients should NOT casually batch calls that in fact return results; that is,
* the server side should be aware that a call is batched and not produce any
* return message. Batched calls that produce many result messages can
* deadlock (netlock) the client and the server....
*
* Now go hang yourself.
*/
#include <netdb.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <rpc/rpc.h>
#include <sys/uio.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <rpc/pmap_clnt.h>
#define MCALL_MSG_SIZE 24
struct ct_data
{
int ct_sock;
bool_t ct_closeit;
struct timeval ct_wait;
bool_t ct_waitset; /* wait set by clnt_control? */
struct sockaddr_un ct_addr;
struct rpc_err ct_error;
char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */
u_int ct_mpos; /* pos after marshal */
XDR ct_xdrs;
};
static int readunix (char *, char *, int);
static int writeunix (char *, char *, int);
static enum clnt_stat clntunix_call (CLIENT *, u_long, xdrproc_t, caddr_t,
xdrproc_t, caddr_t, struct timeval);
static void clntunix_abort (void);
static void clntunix_geterr (CLIENT *, struct rpc_err *);
static bool_t clntunix_freeres (CLIENT *, xdrproc_t, caddr_t);
static bool_t clntunix_control (CLIENT *, int, char *);
static void clntunix_destroy (CLIENT *);
static struct clnt_ops unix_ops =
{
clntunix_call,
clntunix_abort,
clntunix_geterr,
clntunix_freeres,
clntunix_destroy,
clntunix_control
};
/*
* Create a client handle for a tcp/ip connection.
* If *sockp<0, *sockp is set to a newly created TCP socket and it is
* connected to raddr. If *sockp non-negative then
* raddr is ignored. The rpc/tcp package does buffering
* similar to stdio, so the client must pick send and receive buffer sizes,];
* 0 => use the default.
* If raddr->sin_port is 0, then a binder on the remote machine is
* consulted for the right port number.
* NB: *sockp is copied into a private area.
* NB: It is the clients responsibility to close *sockp.
* NB: The rpch->cl_auth is set null authentication. Caller may wish to set this
* something more useful.
*/
CLIENT *
clntunix_create (struct sockaddr_un *raddr, u_long prog, u_long vers,
int *sockp, u_int sendsz, u_int recvsz)
{
CLIENT *h;
struct ct_data *ct = (struct ct_data *) mem_alloc (sizeof (*ct));
struct timeval now;
struct rpc_msg call_msg;
int len;
h = (CLIENT *) mem_alloc (sizeof (*h));
if (h == NULL)
{
(void) fputs (_("clntunix_create: out of memory\n"), stderr);
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
goto fooy;
}
/* ct = (struct ct_data *) mem_alloc (sizeof (*ct)); */
if (ct == NULL)
{
(void) fputs (_("clntunix_create: out of memory\n"), stderr);
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
goto fooy;
}
/*
* If no socket given, open one
*/
if (*sockp < 0)
{
*sockp = __socket (AF_UNIX, SOCK_STREAM, 0);
len = strlen (raddr->sun_path) + sizeof (raddr->sun_family) + 1;
if (*sockp < 0
|| __connect (*sockp, (struct sockaddr *) raddr, len) < 0)
{
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
if (*sockp != -1)
__close (*sockp);
goto fooy;
}
ct->ct_closeit = TRUE;
}
else
{
ct->ct_closeit = FALSE;
}
/*
* Set up private data struct
*/
ct->ct_sock = *sockp;
ct->ct_wait.tv_usec = 0;
ct->ct_waitset = FALSE;
ct->ct_addr = *raddr;
/*
* Initialize call message
*/
__gettimeofday (&now, (struct timezone *) 0);
call_msg.rm_xid = __getpid () ^ now.tv_sec ^ now.tv_usec;
call_msg.rm_direction = CALL;
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
call_msg.rm_call.cb_prog = prog;
call_msg.rm_call.cb_vers = vers;
/*
* pre-serialize the static part of the call msg and stash it away
*/
xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE);
if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg))
{
if (ct->ct_closeit)
__close (*sockp);
goto fooy;
}
ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs));
XDR_DESTROY (&(ct->ct_xdrs));
/*
* Create a client handle which uses xdrrec for serialization
* and authnone for authentication.
*/
xdrrec_create (&(ct->ct_xdrs), sendsz, recvsz,
(caddr_t) ct, readunix, writeunix);
h->cl_ops = &unix_ops;
h->cl_private = (caddr_t) ct;
h->cl_auth = authnone_create ();
return h;
fooy:
/*
* Something goofed, free stuff and barf
*/
mem_free ((caddr_t) ct, sizeof (struct ct_data));
mem_free ((caddr_t) h, sizeof (CLIENT));
return (CLIENT *) NULL;
}
static enum clnt_stat
clntunix_call (h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
CLIENT *h;
u_long proc;
xdrproc_t xdr_args;
caddr_t args_ptr;
xdrproc_t xdr_results;
caddr_t results_ptr;
struct timeval timeout;
{
struct ct_data *ct = (struct ct_data *) h->cl_private;
XDR *xdrs = &(ct->ct_xdrs);
struct rpc_msg reply_msg;
u_long x_id;
u_int32_t *msg_x_id = (u_int32_t *) (ct->ct_mcall); /* yuk */
bool_t shipnow;
int refreshes = 2;
if (!ct->ct_waitset)
{
ct->ct_wait = timeout;
}
shipnow =
(xdr_results == (xdrproc_t) 0 && timeout.tv_sec == 0
&& timeout.tv_usec == 0) ? FALSE : TRUE;
call_again:
xdrs->x_op = XDR_ENCODE;
ct->ct_error.re_status = RPC_SUCCESS;
x_id = ntohl (--(*msg_x_id));
if ((!XDR_PUTBYTES (xdrs, ct->ct_mcall, ct->ct_mpos)) ||
(!XDR_PUTLONG (xdrs, (long *) &proc)) ||
(!AUTH_MARSHALL (h->cl_auth, xdrs)) ||
(!(*xdr_args) (xdrs, args_ptr)))
{
if (ct->ct_error.re_status == RPC_SUCCESS)
ct->ct_error.re_status = RPC_CANTENCODEARGS;
(void) xdrrec_endofrecord (xdrs, TRUE);
return ct->ct_error.re_status;
}
if (!xdrrec_endofrecord (xdrs, shipnow))
return ct->ct_error.re_status = RPC_CANTSEND;
if (!shipnow)
return RPC_SUCCESS;
/*
* Hack to provide rpc-based message passing
*/
if (timeout.tv_sec == 0 && timeout.tv_usec == 0)
return ct->ct_error.re_status = RPC_TIMEDOUT;
/*
* Keep receiving until we get a valid transaction id
*/
xdrs->x_op = XDR_DECODE;
while (TRUE)
{
reply_msg.acpted_rply.ar_verf = _null_auth;
reply_msg.acpted_rply.ar_results.where = NULL;
reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
if (!xdrrec_skiprecord (xdrs))
return ct->ct_error.re_status;
/* now decode and validate the response header */
if (!xdr_replymsg (xdrs, &reply_msg))
{
if (ct->ct_error.re_status == RPC_SUCCESS)
continue;
return ct->ct_error.re_status;
}
if (reply_msg.rm_xid == x_id)
break;
}
/*
* process header
*/
_seterr_reply (&reply_msg, &(ct->ct_error));
if (ct->ct_error.re_status == RPC_SUCCESS)
{
if (!AUTH_VALIDATE (h->cl_auth, &reply_msg.acpted_rply.ar_verf))
{
ct->ct_error.re_status = RPC_AUTHERROR;
ct->ct_error.re_why = AUTH_INVALIDRESP;
}
else if (!(*xdr_results) (xdrs, results_ptr))
{
if (ct->ct_error.re_status == RPC_SUCCESS)
ct->ct_error.re_status = RPC_CANTDECODERES;
}
/* free verifier ... */
if (reply_msg.acpted_rply.ar_verf.oa_base != NULL)
{
xdrs->x_op = XDR_FREE;
(void) xdr_opaque_auth (xdrs, &(reply_msg.acpted_rply.ar_verf));
}
} /* end successful completion */
else
{
/* maybe our credentials need to be refreshed ... */
if (refreshes-- && AUTH_REFRESH (h->cl_auth))
goto call_again;
} /* end of unsuccessful completion */
return ct->ct_error.re_status;
}
static void
clntunix_geterr (CLIENT *h, struct rpc_err *errp)
{
struct ct_data *ct = (struct ct_data *) h->cl_private;
*errp = ct->ct_error;
}
static bool_t
clntunix_freeres (cl, xdr_res, res_ptr)
CLIENT *cl;
xdrproc_t xdr_res;
caddr_t res_ptr;
{
struct ct_data *ct = (struct ct_data *) cl->cl_private;
XDR *xdrs = &(ct->ct_xdrs);
xdrs->x_op = XDR_FREE;
return (*xdr_res) (xdrs, res_ptr);
}
static void
clntunix_abort ()
{
}
static bool_t
clntunix_control (CLIENT *cl, int request, char *info)
{
struct ct_data *ct = (struct ct_data *) cl->cl_private;
switch (request)
{
case CLSET_FD_CLOSE:
ct->ct_closeit = TRUE;
break;
case CLSET_FD_NCLOSE:
ct->ct_closeit = FALSE;
break;
case CLSET_TIMEOUT:
ct->ct_wait = *(struct timeval *) info;
break;
case CLGET_TIMEOUT:
*(struct timeval *) info = ct->ct_wait;
break;
case CLGET_SERVER_ADDR:
*(struct sockaddr_un *) info = ct->ct_addr;
break;
case CLGET_FD:
*(int *)info = ct->ct_sock;
break;
case CLGET_XID:
/*
* use the knowledge that xid is the
* first element in the call structure *.
* This will get the xid of the PREVIOUS call
*/
*(u_long *) info = ntohl (*(u_long *)ct->ct_mcall);
break;
case CLSET_XID:
/* This will set the xid of the NEXT call */
*(u_long *) ct->ct_mcall = htonl (*(u_long *)info - 1);
/* decrement by 1 as clntunix_call() increments once */
case CLGET_VERS:
/*
* This RELIES on the information that, in the call body,
* the version number field is the fifth field from the
* begining of the RPC header. MUST be changed if the
* call_struct is changed
*/
*(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall
+ 4 * BYTES_PER_XDR_UNIT));
break;
case CLSET_VERS:
*(u_long *) (ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT)
= htonl (*(u_long *) info);
break;
case CLGET_PROG:
/*
* This RELIES on the information that, in the call body,
* the program number field is the field from the
* begining of the RPC header. MUST be changed if the
* call_struct is changed
*/
*(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall
+ 3 * BYTES_PER_XDR_UNIT));
break;
case CLSET_PROG:
*(u_long *) (ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT)
= htonl(*(u_long *) info);
break;
/* The following are only possible with TI-RPC */
case CLGET_RETRY_TIMEOUT:
case CLSET_RETRY_TIMEOUT:
case CLGET_SVC_ADDR:
case CLSET_SVC_ADDR:
case CLSET_PUSH_TIMOD:
case CLSET_POP_TIMOD:
default:
return FALSE;
}
return TRUE;
}
static void
clntunix_destroy (CLIENT *h)
{
struct ct_data *ct =
(struct ct_data *) h->cl_private;
if (ct->ct_closeit)
{
(void) close (ct->ct_sock);
}
XDR_DESTROY (&(ct->ct_xdrs));
mem_free ((caddr_t) ct, sizeof (struct ct_data));
mem_free ((caddr_t) h, sizeof (CLIENT));
}
struct cmessage {
struct cmsghdr cmsg;
struct cmsgcred cmcred;
};
static int
__msgread (int sock, void *buf, size_t cnt)
{
struct iovec iov[1];
struct msghdr msg;
struct cmessage cm;
int on = 1;
iov[0].iov_base = buf;
iov[0].iov_len = cnt;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_control = (caddr_t)&cm;
msg.msg_controllen = sizeof(struct cmessage);
msg.msg_flags = 0;
setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on));
return recvmsg (sock, &msg, 0);
}
static int
__msgwrite (int sock, void *buf, size_t cnt)
{
#ifndef SCM_CRED
/* We cannot implement this reliably. */
__set_errno (ENOSYS);
#else
struct iovec iov[1];
struct msghdr msg;
struct cmessage cm;
int len;
iov[0].iov_base = buf;
iov[0].iov_len = cnt;
cm.cmsg.cmsg_type = SCM_CREDS;
cm.cmsg.cmsg_level = SOL_SOCKET;
cm.cmsg.cmsg_len = sizeof (struct cmessage);
/* XXX I'm not sure, if gete?id() is always correct, or if we should use
get?id(). But since keyserv needs geteuid(), we have no other chance.
It would be much better, if the kernel could pass both to the server. */
cm.cmcred.cmcred_pid = __getpid ();
cm.cmcred.cmcred_uid = __geteuid ();
cm.cmcred.cmcred_gid = __getegid ();
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_control = (caddr_t) &cm;
msg.msg_controllen = sizeof (struct cmessage);
msg.msg_flags = 0;
return sendmsg (sock, &msg, 0);
#endif
}
/*
* Interface between xdr serializer and unix connection.
* Behaves like the system calls, read & write, but keeps some error state
* around for the rpc level.
*/
static int
readunix (char *ctptr, char *buf, int len)
{
struct ct_data *ct = (struct ct_data *) ctptr;
struct pollfd fd;
int milliseconds = ((ct->ct_wait.tv_sec * 1000)
+ (ct->ct_wait.tv_usec / 1000));
if (len == 0)
return 0;
fd.fd = ct->ct_sock;
fd.events = POLLIN;
while (TRUE)
{
switch (__poll (&fd, 1, milliseconds))
{
case 0:
ct->ct_error.re_status = RPC_TIMEDOUT;
return -1;
case -1:
if (errno == EINTR)
continue;
ct->ct_error.re_status = RPC_CANTRECV;
ct->ct_error.re_errno = errno;
return -1;
}
break;
}
switch (len = __msgread (ct->ct_sock, buf, len))
{
case 0:
/* premature eof */
ct->ct_error.re_errno = ECONNRESET;
ct->ct_error.re_status = RPC_CANTRECV;
len = -1; /* it's really an error */
break;
case -1:
ct->ct_error.re_errno = errno;
ct->ct_error.re_status = RPC_CANTRECV;
break;
}
return len;
}
static int
writeunix (char *ctptr, char *buf, int len)
{
int i, cnt;
struct ct_data *ct = (struct ct_data *) ctptr;
for (cnt = len; cnt > 0; cnt -= i, buf += i)
{
if ((i = __msgwrite (ct->ct_sock, buf, cnt)) == -1)
{
ct->ct_error.re_errno = errno;
ct->ct_error.re_status = RPC_CANTSEND;
return -1;
}
}
return len;
}

View File

@ -38,6 +38,7 @@
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
@ -47,6 +48,7 @@
#include <sys/param.h>
#include <sys/socket.h>
#include <rpc/key_prot.h>
#include <bits/libc-lock.h>
#define KEY_TIMEOUT 5 /* per-try timeout in seconds */
#define KEY_NRETRY 12 /* number of retries */
@ -268,8 +270,8 @@ des_block *(*__key_gendes_LOCAL) (uid_t, char *) = 0;
static int
internal_function
key_call (u_long proc, xdrproc_t xdr_arg, char *arg,
xdrproc_t xdr_rslt, char *rslt)
key_call_keyenvoy (u_long proc, xdrproc_t xdr_arg, char *arg,
xdrproc_t xdr_rslt, char *rslt)
{
XDR xdrargs;
XDR xdrrslt;
@ -283,28 +285,6 @@ key_call (u_long proc, xdrproc_t xdr_arg, char *arg,
uid_t euid;
static char MESSENGER[] = "/usr/etc/keyenvoy";
if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL)
{
cryptkeyres *res;
res = (*__key_encryptsession_pk_LOCAL) (__geteuid (), arg);
*(cryptkeyres *) rslt = *res;
return 1;
}
else if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL)
{
cryptkeyres *res;
res = (*__key_decryptsession_pk_LOCAL) (__geteuid (), arg);
*(cryptkeyres *) rslt = *res;
return 1;
}
else if (proc == KEY_GEN && __key_gendes_LOCAL)
{
des_block *res;
res = (*__key_gendes_LOCAL) (__geteuid (), 0);
*(des_block *) rslt = *res;
return 1;
}
success = 1;
sigemptyset (&mask);
sigaddset (&mask, SIGCHLD);
@ -365,3 +345,175 @@ key_call (u_long proc, xdrproc_t xdr_arg, char *arg,
return success;
}
struct key_call_private {
CLIENT *client; /* Client handle */
pid_t pid; /* process-id at moment of creation */
uid_t uid; /* user-id at last authorization */
};
static struct key_call_private *key_call_private_main = NULL;
__libc_lock_define_initialized (static, keycall_lock)
/*
* Keep the handle cached. This call may be made quite often.
*/
static CLIENT *
getkeyserv_handle (int vers)
{
struct key_call_private *kcp = key_call_private_main;
struct timeval wait_time;
int fd;
struct sockaddr_un name;
int namelen = sizeof(struct sockaddr_un);
#define TOTAL_TIMEOUT 30 /* total timeout talking to keyserver */
#define TOTAL_TRIES 5 /* Number of tries */
if (kcp == (struct key_call_private *)NULL)
{
kcp = (struct key_call_private *)malloc (sizeof (*kcp));
if (kcp == (struct key_call_private *)NULL)
return (CLIENT *) NULL;
key_call_private_main = kcp;
kcp->client = NULL;
}
/* if pid has changed, destroy client and rebuild */
if (kcp->client != NULL && kcp->pid != __getpid ())
{
clnt_destroy (kcp->client);
kcp->client = NULL;
}
if (kcp->client != NULL)
{
/* if other side closed socket, build handle again */
clnt_control (kcp->client, CLGET_FD, (char *)&fd);
if (getpeername (fd,(struct sockaddr *)&name,&namelen) == -1)
{
auth_destroy (kcp->client->cl_auth);
clnt_destroy (kcp->client);
kcp->client = NULL;
}
}
if (kcp->client != NULL)
{
/* if uid has changed, build client handle again */
if (kcp->uid != __geteuid ())
{
kcp->uid = __geteuid ();
auth_destroy (kcp->client->cl_auth);
kcp->client->cl_auth =
authunix_create ((char *)"", kcp->uid, 0, 0, NULL);
if (kcp->client->cl_auth == NULL)
{
clnt_destroy (kcp->client);
kcp->client = NULL;
return ((CLIENT *) NULL);
}
}
/* Change the version number to the new one */
clnt_control (kcp->client, CLSET_VERS, (void *)&vers);
return kcp->client;
}
if ((kcp->client == (CLIENT *) NULL))
/* Use the AF_UNIX transport */
kcp->client = clnt_create ("/var/run/keyservsock", KEY_PROG, vers, "unix");
if (kcp->client == (CLIENT *) NULL)
return (CLIENT *) NULL;
kcp->uid = __geteuid ();
kcp->pid = __getpid ();
kcp->client->cl_auth = authunix_create ((char *)"", kcp->uid, 0, 0, NULL);
if (kcp->client->cl_auth == NULL)
{
clnt_destroy (kcp->client);
kcp->client = NULL;
return (CLIENT *) NULL;
}
wait_time.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES;
wait_time.tv_usec = 0;
clnt_control (kcp->client, CLSET_RETRY_TIMEOUT,
(char *)&wait_time);
if (clnt_control (kcp->client, CLGET_FD, (char *)&fd))
fcntl (fd, F_SETFD, 1); /* make it "close on exec" */
return kcp->client;
}
/* returns 0 on failure, 1 on success */
static int
internal_function
key_call_socket (u_long proc, xdrproc_t xdr_arg, char *arg,
xdrproc_t xdr_rslt, char *rslt)
{
CLIENT *clnt;
struct timeval wait_time;
int result = 0;
__libc_lock_lock (keycall_lock);
if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) ||
(proc == KEY_NET_GET) || (proc == KEY_NET_PUT) ||
(proc == KEY_GET_CONV))
clnt = getkeyserv_handle(2); /* talk to version 2 */
else
clnt = getkeyserv_handle(1); /* talk to version 1 */
if (clnt != NULL)
{
wait_time.tv_sec = TOTAL_TIMEOUT;
wait_time.tv_usec = 0;
if (clnt_call (clnt, proc, xdr_arg, arg, xdr_rslt, rslt,
wait_time) == RPC_SUCCESS)
result = 1;
}
__libc_lock_unlock (keycall_lock);
return result;
}
/* returns 0 on failure, 1 on success */
static int
internal_function
key_call (u_long proc, xdrproc_t xdr_arg, char *arg,
xdrproc_t xdr_rslt, char *rslt)
{
static int use_keyenvoy = 0;
if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL)
{
cryptkeyres *res;
res = (*__key_encryptsession_pk_LOCAL) (__geteuid (), arg);
*(cryptkeyres *) rslt = *res;
return 1;
}
else if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL)
{
cryptkeyres *res;
res = (*__key_decryptsession_pk_LOCAL) (__geteuid (), arg);
*(cryptkeyres *) rslt = *res;
return 1;
}
else if (proc == KEY_GEN && __key_gendes_LOCAL)
{
des_block *res;
res = (*__key_gendes_LOCAL) (__geteuid (), 0);
*(des_block *) rslt = *res;
return 1;
}
if (!use_keyenvoy)
{
if (key_call_socket (proc, xdr_arg, arg, xdr_rslt, rslt))
return 1;
use_keyenvoy = 1;
}
return key_call_keyenvoy (proc, xdr_arg, arg, xdr_rslt, rslt);
}

View File

@ -41,6 +41,7 @@
#include <sys/types.h>
#include <rpc/types.h>
#include <rpc/auth.h>
#include <sys/un.h>
__BEGIN_DECLS
@ -282,7 +283,8 @@ extern CLIENT *clntraw_create __P ((__const u_long __prog,
/*
* Generic client creation routine. Supported protocols are "udp" and "tcp"
* Generic client creation routine. Supported protocols are "udp", "tcp" and
* "unix"
* CLIENT *
* clnt_create(host, prog, vers, prot)
* char *host; -- hostname
@ -341,6 +343,24 @@ extern CLIENT *clntudp_bufcreate __P ((struct sockaddr_in *__raddr,
int *__sockp, u_int __sendsz,
u_int __recvsz));
/*
* AF_UNIX based rpc
* CLIENT *
* clntunix_create(raddr, prog, vers, sockp, sendsz, recvsz)
* struct sockaddr_un *raddr;
* u_long prog;
* u_long version;
* register int *sockp;
* u_int sendsz;
* u_int recvsz;
*/
extern CLIENT *clntunix_create __P ((struct sockaddr_un *__raddr,
u_long __program, u_long __version,
int *__sockp, u_int __sendsz,
u_int __recvsz));
extern int callrpc __P ((__const char *__host, __const u_long __prognum,
__const u_long __versnum, __const u_long __procnum,
__const xdrproc_t __inproc, __const char *__in,

View File

@ -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 */

View File

@ -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);

View File

@ -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;

496
sunrpc/svc_unix.c Normal file
View File

@ -0,0 +1,496 @@
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* svc_unix.c, Server side for TCP/IP based RPC.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* Actually implements two flavors of transporter -
* a unix rendezvouser (a listener and connection establisher)
* and a record/unix stream.
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <rpc/rpc.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <errno.h>
#include <stdlib.h>
/*
* Ops vector for AF_UNIX based rpc service handle
*/
static bool_t svcunix_recv (SVCXPRT *, struct rpc_msg *);
static enum xprt_stat svcunix_stat (SVCXPRT *);
static bool_t svcunix_getargs (SVCXPRT *, xdrproc_t, caddr_t);
static bool_t svcunix_reply (SVCXPRT *, struct rpc_msg *);
static bool_t svcunix_freeargs (SVCXPRT *, xdrproc_t, caddr_t);
static void svcunix_destroy (SVCXPRT *);
static const struct xp_ops svcunix_op =
{
svcunix_recv,
svcunix_stat,
svcunix_getargs,
svcunix_reply,
svcunix_freeargs,
svcunix_destroy
};
/*
* Ops vector for AF_UNIX rendezvous handler
*/
static bool_t rendezvous_request (SVCXPRT *, struct rpc_msg *);
static enum xprt_stat rendezvous_stat (SVCXPRT *);
static const struct xp_ops svcunix_rendezvous_op =
{
rendezvous_request,
rendezvous_stat,
(bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) abort,
(bool_t (*) (SVCXPRT *, struct rpc_msg *)) abort,
(bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) abort,
svcunix_destroy
};
static int readunix (char*, char *, int);
static int writeunix (char *, char *, int);
static SVCXPRT *makefd_xprt (int, u_int, u_int) internal_function;
struct unix_rendezvous { /* kept in xprt->xp_p1 */
u_int sendsize;
u_int recvsize;
};
struct unix_conn { /* kept in xprt->xp_p1 */
enum xprt_stat strm_stat;
u_long x_id;
XDR xdrs;
char verf_body[MAX_AUTH_BYTES];
};
/*
* Usage:
* xprt = svcunix_create(sock, send_buf_size, recv_buf_size);
*
* Creates, registers, and returns a (rpc) unix based transporter.
* Once *xprt is initialized, it is registered as a transporter
* see (svc.h, xprt_register). This routine returns
* a NULL if a problem occurred.
*
* If sock<0 then a socket is created, else sock is used.
* If the socket, sock is not bound to a port then svcunix_create
* binds it to an arbitrary port. The routine then starts a unix
* listener on the socket's associated port. In any (successful) case,
* xprt->xp_sock is the registered socket number and xprt->xp_port is the
* associated port number.
*
* Since unix streams do buffered io similar to stdio, the caller can specify
* how big the send and receive buffers are via the second and third parms;
* 0 => use the system default.
*/
SVCXPRT *
svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path)
{
bool_t madesock = FALSE;
SVCXPRT *xprt;
struct unix_rendezvous *r;
struct sockaddr_un addr;
socklen_t len = sizeof (struct sockaddr_in);
if (sock == RPC_ANYSOCK)
{
if ((sock = __socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
{
perror (_("svc_unix.c - AF_UNIX socket creation problem"));
return (SVCXPRT *) NULL;
}
madesock = TRUE;
}
memset (&addr, '\0', sizeof (addr));
addr.sun_family = AF_UNIX;
len = strlen (addr.sun_path) + 1;
memcpy (addr.sun_path, path, len);
len += sizeof (addr.sun_family);
bind (sock, (struct sockaddr *) &addr, len);
if (getsockname (sock, (struct sockaddr *) &addr, &len) != 0
|| listen (sock, 2) != 0)
{
perror (_("svc_unix.c - cannot getsockname or listen"));
if (madesock)
__close (sock);
return (SVCXPRT *) NULL;
}
r = (struct unix_rendezvous *) mem_alloc (sizeof (*r));
if (r == NULL)
{
fputs (_("svcunix_create: out of memory\n"), stderr);
return NULL;
}
r->sendsize = sendsize;
r->recvsize = recvsize;
xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
if (xprt == NULL)
{
fputs (_("svcunix_create: out of memory\n"), stderr);
return NULL;
}
xprt->xp_p2 = NULL;
xprt->xp_p1 = (caddr_t) r;
xprt->xp_verf = _null_auth;
xprt->xp_ops = &svcunix_rendezvous_op;
xprt->xp_port = -1;
xprt->xp_sock = sock;
xprt_register (xprt);
return xprt;
}
/*
* Like svunix_create(), except the routine takes any *open* UNIX file
* descriptor as its first input.
*/
SVCXPRT *
svcunixfd_create (int fd, u_int sendsize, u_int recvsize)
{
return makefd_xprt (fd, sendsize, recvsize);
}
static SVCXPRT *
internal_function
makefd_xprt (int fd, u_int sendsize, u_int recvsize)
{
SVCXPRT *xprt;
struct unix_conn *cd;
xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
if (xprt == (SVCXPRT *) NULL)
{
(void) fputs (_("svc_unix: makefd_xprt: out of memory\n"), stderr);
goto done;
}
cd = (struct unix_conn *) mem_alloc (sizeof (struct unix_conn));
if (cd == (struct unix_conn *) NULL)
{
(void) fputs (_("svc_unix: makefd_xprt: out of memory\n"), stderr);
mem_free ((char *) xprt, sizeof (SVCXPRT));
xprt = (SVCXPRT *) NULL;
goto done;
}
cd->strm_stat = XPRT_IDLE;
xdrrec_create (&(cd->xdrs), sendsize, recvsize,
(caddr_t) xprt, readunix, writeunix);
xprt->xp_p2 = NULL;
xprt->xp_p1 = (caddr_t) cd;
xprt->xp_verf.oa_base = cd->verf_body;
xprt->xp_addrlen = 0;
xprt->xp_ops = &svcunix_op; /* truly deals with calls */
xprt->xp_port = 0; /* this is a connection, not a rendezvouser */
xprt->xp_sock = fd;
xprt_register (xprt);
done:
return xprt;
}
static bool_t
rendezvous_request (SVCXPRT *xprt, struct rpc_msg *errmsg)
{
int sock;
struct unix_rendezvous *r;
struct sockaddr_un addr;
struct sockaddr_in in_addr;
socklen_t len;
r = (struct unix_rendezvous *) xprt->xp_p1;
again:
len = sizeof (struct sockaddr_un);
if ((sock = accept (xprt->xp_sock, (struct sockaddr *) &addr, &len)) < 0)
{
if (errno == EINTR)
goto again;
return FALSE;
}
/*
* make a new transporter (re-uses xprt)
*/
memset (&in_addr, '\0', sizeof (in_addr));
in_addr.sin_family = AF_UNIX;
xprt = makefd_xprt (sock, r->sendsize, r->recvsize);
xprt->xp_raddr = in_addr;
xprt->xp_addrlen = len;
return FALSE; /* there is never an rpc msg to be processed */
}
static enum xprt_stat
rendezvous_stat (SVCXPRT *xprt)
{
return XPRT_IDLE;
}
static void
svcunix_destroy (SVCXPRT *xprt)
{
struct unix_conn *cd = (struct unix_conn *) xprt->xp_p1;
xprt_unregister (xprt);
__close (xprt->xp_sock);
if (xprt->xp_port != 0)
{
/* a rendezvouser socket */
xprt->xp_port = 0;
}
else
{
/* an actual connection socket */
XDR_DESTROY (&(cd->xdrs));
}
mem_free ((caddr_t) cd, sizeof (struct unix_conn));
mem_free ((caddr_t) xprt, sizeof (SVCXPRT));
}
struct cmessage {
struct cmsghdr cmsg;
struct cmsgcred cmcred;
};
/* XXX This is not thread safe, but since the main functions in svc.c
and the rpcgen generated *_svc functions for the daemon are also not
thread safe and uses static global variables, it doesn't matter. */
static struct cmessage cm;
static int
__msgread (int sock, void *buf, size_t cnt)
{
struct iovec iov[1];
struct msghdr msg;
int len, on = 1;
iov[0].iov_base = buf;
iov[0].iov_len = cnt;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_control = (caddr_t) &cm;
msg.msg_controllen = sizeof (struct cmessage);
msg.msg_flags = 0;
setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on));
return recvmsg (sock, &msg, 0);
}
static int
__msgwrite (int sock, void *buf, size_t cnt)
{
#ifndef SCM_CRED
/* We cannot implement this reliably. */
__set_errno (ENOSYS);
#else
struct iovec iov[1];
struct msghdr msg;
int len;
iov[0].iov_base = buf;
iov[0].iov_len = cnt;
cm.cmsg.cmsg_type = SCM_CREDS;
cm.cmsg.cmsg_level = SOL_SOCKET;
cm.cmsg.cmsg_len = sizeof (struct cmessage);
/* XXX I'm not sure, if we really should use gete?id(), or get?id().
It would be much better, if the kernel could pass both to the
client. */
cm.cmcred.cmcred_pid = __getpid ();
cm.cmcred.cmcred_uid = __geteuid ();
cm.cmcred.cmcred_gid = __getegid ();
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_control = (caddr_t) &cm;
msg.msg_controllen = sizeof (struct cmessage);
msg.msg_flags = 0;
return sendmsg (sock, &msg, 0);
#endif
}
/*
* All read operations timeout after 35 seconds.
* A timeout is fatal for the connection.
*/
static struct timeval wait_per_try = {35, 0};
/*
* reads data from the unix connection.
* any error is fatal and the connection is closed.
* (And a read of zero bytes is a half closed stream => error.)
*/
static int
readunix (char *xprtptr, char *buf, int len)
{
SVCXPRT *xprt = (SVCXPRT *) xprtptr;
int sock = xprt->xp_sock;
#ifdef FD_SETSIZE
fd_set readfds;
#else
int mask = 1 << sock;
int readfds;
#endif /* def FD_SETSIZE */
while (1)
{
struct timeval timeout = wait_per_try;
readfds = svc_fdset;
#ifdef FD_SETSIZE
FD_SET (sock, &readfds);
#else
readfds |= (1 << sock);
#endif /* def FD_SETSIZE */
if (__select (_rpc_dtablesize (), &readfds, (fd_set *) NULL,
(fd_set *) NULL, &timeout) <= 0)
{
if (errno == EINTR)
continue;
goto fatal_err;
}
#ifdef FD_SETSIZE
if (FD_ISSET (sock, &readfds))
#else
if (readfds == mask)
#endif /* def FD_SETSIZE */
break;
svc_getreqset (&readfds);
}
if ((len = __msgread (sock, buf, len)) > 0)
return len;
fatal_err:
((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
return -1;
}
/*
* writes data to the unix connection.
* Any error is fatal and the connection is closed.
*/
static int
writeunix (char *xprtptr, char * buf, int len)
{
SVCXPRT *xprt = (SVCXPRT *) xprtptr;
int i, cnt;
for (cnt = len; cnt > 0; cnt -= i, buf += i)
{
if ((i = __msgwrite (xprt->xp_sock, buf, cnt)) < 0)
{
((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
return -1;
}
}
return len;
}
static enum xprt_stat
svcunix_stat (SVCXPRT *xprt)
{
struct unix_conn *cd =
(struct unix_conn *) (xprt->xp_p1);
if (cd->strm_stat == XPRT_DIED)
return XPRT_DIED;
if (!xdrrec_eof (&(cd->xdrs)))
return XPRT_MOREREQS;
return XPRT_IDLE;
}
static bool_t
svcunix_recv (SVCXPRT *xprt, struct rpc_msg *msg)
{
struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1);
XDR *xdrs = &(cd->xdrs);
xdrs->x_op = XDR_DECODE;
xdrrec_skiprecord (xdrs);
if (xdr_callmsg (xdrs, msg))
{
cd->x_id = msg->rm_xid;
/* set up verifiers */
msg->rm_call.cb_verf.oa_flavor = AUTH_UNIX;
msg->rm_call.cb_verf.oa_base = (caddr_t) &cm;
msg->rm_call.cb_verf.oa_length = sizeof (cm);
return TRUE;
}
cd->strm_stat = XPRT_DIED; /* XXXX */
return FALSE;
}
static bool_t
svcunix_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
{
return (*xdr_args) (&(((struct unix_conn *) (xprt->xp_p1))->xdrs),
args_ptr);
}
static bool_t
svcunix_freeargs (xprt, xdr_args, args_ptr)
SVCXPRT *xprt;
xdrproc_t xdr_args;
caddr_t args_ptr;
{
XDR *xdrs = &(((struct unix_conn *) (xprt->xp_p1))->xdrs);
xdrs->x_op = XDR_FREE;
return (*xdr_args) (xdrs, args_ptr);
}
static bool_t
svcunix_reply (xprt, msg)
SVCXPRT *xprt;
struct rpc_msg *msg;
{
struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1);
XDR *xdrs = &(cd->xdrs);
bool_t stat;
xdrs->x_op = XDR_ENCODE;
msg->rm_xid = cd->x_id;
stat = xdr_replymsg (xdrs, msg);
(void) xdrrec_endofrecord (xdrs, TRUE);
return stat;
}

View File

@ -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
{

View File

@ -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);

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -54,3 +54,5 @@ static char rcsid[] = "$NetBSD: $";
#endif
}
weak_alias (__lgammal, lgammal)
strong_alias (__lgammal, __gammal)
weak_alias (__gammal, gammal)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

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