Browse Source

Re-backport all the rpc stuff from glibc 2.2.5. This allows us to make this
junk (and I do mean that ;-) thread safe without undue pain. Adds 12k worth to
the code size I'm afraid, but since I never use NFS and therefore never include
this stuff, I guess thats acceptable. I still need to enable the multi-threaded
bits...
-Erik

Eric Andersen 23 years ago
parent
commit
cdb3c81f36
45 changed files with 8139 additions and 5018 deletions
  1. 13 11
      libc/inet/rpc/Makefile
  2. 76 69
      libc/inet/rpc/auth_none.c
  3. 221 206
      libc/inet/rpc/auth_unix.c
  4. 27 25
      libc/inet/rpc/authunix_prot.c
  5. 42 35
      libc/inet/rpc/bindresvport.c
  6. 126 68
      libc/inet/rpc/clnt_generic.c
  7. 349 206
      libc/inet/rpc/clnt_perror.c
  8. 181 157
      libc/inet/rpc/clnt_raw.c
  9. 120 71
      libc/inet/rpc/clnt_simple.c
  10. 426 349
      libc/inet/rpc/clnt_tcp.c
  11. 511 340
      libc/inet/rpc/clnt_udp.c
  12. 606 0
      libc/inet/rpc/clnt_unix.c
  13. 64 0
      libc/inet/rpc/create_xid.c
  14. 46 0
      libc/inet/rpc/errqueue.h
  15. 63 64
      libc/inet/rpc/get_myaddress.c
  16. 41 19
      libc/inet/rpc/getrpcport.c
  17. 123 66
      libc/inet/rpc/pmap_clnt.c
  18. 31 34
      libc/inet/rpc/pmap_getmaps.c
  19. 47 42
      libc/inet/rpc/pmap_getport.c
  20. 17 15
      libc/inet/rpc/pmap_prot.c
  21. 52 50
      libc/inet/rpc/pmap_prot2.c
  22. 308 307
      libc/inet/rpc/pmap_rmt.c
  23. 160 139
      libc/inet/rpc/rpc_callmsg.c
  24. 16 14
      libc/inet/rpc/rpc_commondata.c
  25. 19 12
      libc/inet/rpc/rpc_dtablesize.c
  26. 180 184
      libc/inet/rpc/rpc_prot.c
  27. 152 0
      libc/inet/rpc/rpc_thread.c
  28. 149 0
      libc/inet/rpc/rtime.c
  29. 373 357
      libc/inet/rpc/svc.c
  30. 55 44
      libc/inet/rpc/svc_auth.c
  31. 102 79
      libc/inet/rpc/svc_auth_unix.c
  32. 105 98
      libc/inet/rpc/svc_raw.c
  33. 56 37
      libc/inet/rpc/svc_run.c
  34. 146 95
      libc/inet/rpc/svc_simple.c
  35. 301 281
      libc/inet/rpc/svc_tcp.c
  36. 460 322
      libc/inet/rpc/svc_udp.c
  37. 533 0
      libc/inet/rpc/svc_unix.c
  38. 535 345
      libc/inet/rpc/xdr.c
  39. 104 79
      libc/inet/rpc/xdr_array.c
  40. 135 105
      libc/inet/rpc/xdr_float.c
  41. 203 0
      libc/inet/rpc/xdr_intXX_t.c
  42. 163 109
      libc/inet/rpc/xdr_mem.c
  43. 515 432
      libc/inet/rpc/xdr_rec.c
  44. 77 52
      libc/inet/rpc/xdr_reference.c
  45. 110 100
      libc/inet/rpc/xdr_stdio.c

+ 13 - 11
libc/inet/rpc/Makefile

@@ -23,17 +23,19 @@
 
 TOPDIR=../../../
 include $(TOPDIR)Rules.mak
-
-CSRC = auth_none.c auth_unix.c authunix_prot.c \
-	bindresvport.c clnt_generic.c clnt_perror.c \
-	clnt_raw.c clnt_simple.c clnt_tcp.c clnt_udp.c \
-	get_myaddress.c getrpcent.c getrpcport.c pmap_clnt.c \
-	pmap_getmaps.c pmap_getport.c pmap_prot.c pmap_prot2.c \
-	pmap_rmt.c rpc_callmsg.c rpc_commondata.c \
-	rpc_dtablesize.c rpc_prot.c svc.c svc_auth.c \
-	svc_auth_unix.c svc_raw.c svc_run.c svc_simple.c \
-	svc_tcp.c svc_udp.c xdr.c xdr_array.c xdr_float.c \
-	xdr_mem.c xdr_rec.c xdr_reference.c xdr_stdio.c rcmd.c
+#CFLAGS+=-Werror
+
+CSRC :=auth_none.c auth_unix.c authunix_prot.c bindresvport.c \
+	clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c clnt_tcp.c \
+	clnt_udp.c rpc_dtablesize.c get_myaddress.c getrpcent.c getrpcport.c \
+	pmap_clnt.c pmap_getmaps.c pmap_getport.c pmap_prot.c \
+	pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c rpc_callmsg.c \
+	svc.c svc_auth.c svc_auth_unix.c svc_raw.c svc_run.c svc_simple.c \
+	svc_tcp.c svc_udp.c xdr.c xdr_array.c xdr_float.c xdr_mem.c \
+	xdr_rec.c xdr_reference.c xdr_stdio.c \
+	rtime.c clnt_unix.c svc_unix.c create_xid.c xdr_intXX_t.c rcmd.c \
+	rpc_thread.c
+#openchild.c xdr_sizeof.c
 COBJS=$(patsubst %.c,%.o, $(CSRC))
 OBJS=$(COBJS)
 

+ 76 - 69
libc/inet/rpc/auth_none.c

@@ -1,4 +1,3 @@
-/* @(#)auth_none.c	2.1 88/07/29 4.0 RPCSRC */
 /*
  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  * unrestricted use provided that this legend is included on all tape
@@ -6,120 +5,128 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
-
+/*
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
 /*
  * auth_none.c
- * Creates a client authentication handle for passing "null" 
- * credentials and verifiers to remote systems. 
- * 
- * Copyright (C) 1984, Sun Microsystems, Inc. 
+ * Creates a client authentication handle for passing "null"
+ * credentials and verifiers to remote systems.
  */
 
-#include <rpc/types.h>
-#include <rpc/xdr.h>
-#include <rpc/auth.h>
+#include <rpc/rpc.h>
+
 #define MAX_MARSHEL_SIZE 20
 
 /*
  * Authenticator operations routines
  */
-static void authnone_verf();
-static void authnone_destroy();
-static bool_t authnone_marshal();
-static bool_t authnone_validate();
-static bool_t authnone_refresh();
+static void authnone_verf (AUTH *);
+static void authnone_destroy (AUTH *);
+static bool_t authnone_marshal (AUTH *, XDR *);
+static bool_t authnone_validate (AUTH *, struct opaque_auth *);
+static bool_t authnone_refresh (AUTH *);
 
 static struct auth_ops ops = {
-	authnone_verf,
-	authnone_marshal,
-	authnone_validate,
-	authnone_refresh,
-	authnone_destroy
+  authnone_verf,
+  authnone_marshal,
+  authnone_validate,
+  authnone_refresh,
+  authnone_destroy
 };
 
-static struct authnone_private {
-	AUTH no_client;
-	char marshalled_client[MAX_MARSHEL_SIZE];
-	u_int mcnt;
-} *authnone_private;
+struct authnone_private_s {
+  AUTH no_client;
+  char marshalled_client[MAX_MARSHEL_SIZE];
+  u_int mcnt;
+};
+#ifdef _RPC_THREAD_SAFE_
+#define authnone_private ((struct authnone_private_s *)RPC_THREAD_VARIABLE(authnone_private_s))
+#else
+static struct authnone_private_s *authnone_private;
+#endif
 
-AUTH *authnone_create()
+AUTH *
+authnone_create (void)
 {
-	register struct authnone_private *ap = authnone_private;
-	XDR xdr_stream;
-	register XDR *xdrs;
+  struct authnone_private_s *ap;
+  XDR xdr_stream;
+  XDR *xdrs;
 
-	if (ap == 0) {
-		ap = (struct authnone_private *) calloc(1, sizeof(*ap));
-		if (ap == 0)
-			return (0);
-		authnone_private = ap;
-	}
-	if (!ap->mcnt) {
-		ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth;
-		ap->no_client.ah_ops = &ops;
-		xdrs = &xdr_stream;
-		xdrmem_create(xdrs, ap->marshalled_client,
-					  (u_int) MAX_MARSHEL_SIZE, XDR_ENCODE);
-		(void) xdr_opaque_auth(xdrs, &ap->no_client.ah_cred);
-		(void) xdr_opaque_auth(xdrs, &ap->no_client.ah_verf);
-		ap->mcnt = XDR_GETPOS(xdrs);
-		XDR_DESTROY(xdrs);
-	}
-	return (&ap->no_client);
+  ap = (struct authnone_private_s *) authnone_private;
+  if (ap == NULL)
+    {
+      ap = (struct authnone_private_s *) calloc (1, sizeof (*ap));
+      if (ap == NULL)
+	return NULL;
+      authnone_private = ap;
+    }
+  if (!ap->mcnt)
+    {
+      ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth;
+      ap->no_client.ah_ops = &ops;
+      xdrs = &xdr_stream;
+      xdrmem_create (xdrs, ap->marshalled_client, (u_int) MAX_MARSHEL_SIZE,
+		     XDR_ENCODE);
+      (void) xdr_opaque_auth (xdrs, &ap->no_client.ah_cred);
+      (void) xdr_opaque_auth (xdrs, &ap->no_client.ah_verf);
+      ap->mcnt = XDR_GETPOS (xdrs);
+      XDR_DESTROY (xdrs);
+    }
+  return (&ap->no_client);
 }
 
- /*ARGSUSED*/ static bool_t authnone_marshal(client, xdrs)
-AUTH *client;
-XDR *xdrs;
+/*ARGSUSED */
+static bool_t
+authnone_marshal (AUTH *client, XDR *xdrs)
 {
-	register struct authnone_private *ap = authnone_private;
+  struct authnone_private_s *ap;
 
-	if (ap == 0)
-		return (0);
-	return ((*xdrs->x_ops->x_putbytes) (xdrs,
-										ap->marshalled_client, ap->mcnt));
+  ap = (struct authnone_private_s *) authnone_private;
+  if (ap == NULL)
+    return FALSE;
+  return (*xdrs->x_ops->x_putbytes) (xdrs, ap->marshalled_client, ap->mcnt);
 }
 
-static void authnone_verf()
+static void
+authnone_verf (AUTH *auth)
 {
 }
 
-static bool_t authnone_validate()
+static bool_t
+authnone_validate (AUTH *auth, struct opaque_auth *oa)
 {
-
-	return (TRUE);
+  return TRUE;
 }
 
-static bool_t authnone_refresh()
+static bool_t
+authnone_refresh (AUTH *auth)
 {
-
-	return (FALSE);
+  return FALSE;
 }
 
-static void authnone_destroy()
+static void
+authnone_destroy (AUTH *auth)
 {
 }

+ 221 - 206
libc/inet/rpc/auth_unix.c

@@ -1,4 +1,3 @@
-/* @(#)auth_unix.c	2.2 88/08/01 4.0 RPCSRC */
 /*
  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  * unrestricted use provided that this legend is included on all tape
@@ -6,11 +5,11 @@
  * 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.
@@ -18,293 +17,309 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
-
 /*
- * auth_unix.c, Implements UNIX style authentication parameters. 
- *  
  * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+/*
+ * auth_unix.c, Implements UNIX style authentication parameters.
  *
  * The system is very weak.  The client uses no encryption for it's
  * credentials and only sends null verifiers.  The server sends backs
  * null verifiers or optionally a verifier that suggests a new short hand
  * for the credentials.
- *
  */
 
+#define __FORCE_GLIBC
+#include <features.h>
+
+#include <limits.h>
 #include <stdio.h>
-#include <unistd.h>
-#include <sys/types.h>
 #include <string.h>
+#include <unistd.h>
+#include <sys/param.h>
 
 #include <rpc/types.h>
 #include <rpc/xdr.h>
 #include <rpc/auth.h>
 #include <rpc/auth_unix.h>
 
+#ifdef USE_IN_LIBIO
+# include <wchar.h>
+#endif
+
 /*
  * Unix authenticator operations vector
  */
-static void authunix_nextverf();
-static bool_t authunix_marshal();
-static bool_t authunix_validate();
-static bool_t authunix_refresh();
-static void authunix_destroy();
+static void authunix_nextverf (AUTH *);
+static bool_t authunix_marshal (AUTH *, XDR *);
+static bool_t authunix_validate (AUTH *, struct opaque_auth *);
+static bool_t authunix_refresh (AUTH *);
+static void authunix_destroy (AUTH *);
 
 static struct auth_ops auth_unix_ops = {
-	authunix_nextverf,
-	authunix_marshal,
-	authunix_validate,
-	authunix_refresh,
-	authunix_destroy
+  authunix_nextverf,
+  authunix_marshal,
+  authunix_validate,
+  authunix_refresh,
+  authunix_destroy
 };
 
 /*
  * This struct is pointed to by the ah_private field of an auth_handle.
  */
 struct audata {
-	struct opaque_auth au_origcred;	/* original credentials */
-	struct opaque_auth au_shcred;	/* short hand cred */
-	u_long au_shfaults;			/* short hand cache faults */
-	char au_marshed[MAX_AUTH_BYTES];
-	u_int au_mpos;				/* xdr pos at end of marshed */
+  struct opaque_auth au_origcred;	/* original credentials */
+  struct opaque_auth au_shcred;	/* short hand cred */
+  u_long au_shfaults;		/* short hand cache faults */
+  char au_marshed[MAX_AUTH_BYTES];
+  u_int au_mpos;		/* xdr pos at end of marshed */
 };
-
 #define	AUTH_PRIVATE(auth)	((struct audata *)auth->ah_private)
 
-static void marshal_new_auth();
+static bool_t marshal_new_auth (AUTH *) internal_function;
 
 
 /*
  * Create a unix style authenticator.
  * Returns an auth handle with the given stuff in it.
  */
-AUTH *authunix_create __P ((char *machname, uid_t uid,
-				   gid_t gid, int len,
-				   gid_t *aup_gids))
+AUTH *
+authunix_create (char *machname, uid_t uid, gid_t gid, int len,
+		 gid_t *aup_gids)
 {
-	struct authunix_parms aup;
-	char mymem[MAX_AUTH_BYTES];
-	struct timeval now;
-	XDR xdrs;
-	register AUTH *auth;
-	register struct audata *au;
-
-	/*
-	 * Allocate and set up auth handle
-	 */
-	auth = (AUTH *) mem_alloc(sizeof(*auth));
-#ifndef KERNEL
-	if (auth == NULL) {
-		(void) fprintf(stderr, "authunix_create: out of memory\n");
-		return (NULL);
-	}
-#endif
-	au = (struct audata *) mem_alloc(sizeof(*au));
-#ifndef KERNEL
-	if (au == NULL) {
-		(void) fprintf(stderr, "authunix_create: out of memory\n");
-		return (NULL);
-	}
-#endif
-	auth->ah_ops = &auth_unix_ops;
-	auth->ah_private = (caddr_t) au;
-	auth->ah_verf = au->au_shcred = _null_auth;
-	au->au_shfaults = 0;
-
-	/*
-	 * fill in param struct from the given params
-	 */
-	(void) gettimeofday(&now, (struct timezone *) 0);
-	aup.aup_time = now.tv_sec;
-	aup.aup_machname = machname;
-	aup.aup_uid = uid;
-	aup.aup_gid = gid;
-	aup.aup_len = (u_int) len;
-	aup.aup_gids = aup_gids;
-
-	/*
-	 * Serialize the parameters into origcred
-	 */
-	xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
-	if (!xdr_authunix_parms(&xdrs, &aup))
-		abort();
-	au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
-	au->au_origcred.oa_flavor = AUTH_UNIX;
-#ifdef KERNEL
-	au->au_origcred.oa_base = mem_alloc((u_int) len);
-#else
-	if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) {
-		(void) fprintf(stderr, "authunix_create: out of memory\n");
-		return (NULL);
-	}
+  struct authunix_parms aup;
+  char mymem[MAX_AUTH_BYTES];
+  struct timeval now;
+  XDR xdrs;
+  AUTH *auth;
+  struct audata *au;
+
+  /*
+   * Allocate and set up auth handle
+   */
+  auth = (AUTH *) mem_alloc (sizeof (*auth));
+  au = (struct audata *) mem_alloc (sizeof (*au));
+  if (auth == NULL || au == NULL)
+    {
+no_memory:
+#ifdef USE_IN_LIBIO
+      if (_IO_fwide (stderr, 0) > 0)
+	(void) __fwprintf (stderr, L"%s",
+			   _("authunix_create: out of memory\n"));
+      else
 #endif
-	bcopy(mymem, au->au_origcred.oa_base, (u_int) len);
-
-	/*
-	 * set auth handle to reflect new cred.
-	 */
-	auth->ah_cred = au->au_origcred;
-	marshal_new_auth(auth);
-	return (auth);
+	(void) fputs (_("authunix_create: out of memory\n"), stderr);
+      mem_free (auth, sizeof (*auth));
+      mem_free (au, sizeof (*au));
+      return NULL;
+    }
+  auth->ah_ops = &auth_unix_ops;
+  auth->ah_private = (caddr_t) au;
+  auth->ah_verf = au->au_shcred = _null_auth;
+  au->au_shfaults = 0;
+
+  /*
+   * fill in param struct from the given params
+   */
+  (void) gettimeofday (&now, (struct timezone *) 0);
+  aup.aup_time = now.tv_sec;
+  aup.aup_machname = machname;
+  aup.aup_uid = uid;
+  aup.aup_gid = gid;
+  aup.aup_len = (u_int) len;
+  aup.aup_gids = aup_gids;
+
+  /*
+   * Serialize the parameters into origcred
+   */
+  xdrmem_create (&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
+  if (!xdr_authunix_parms (&xdrs, &aup))
+    abort ();
+  au->au_origcred.oa_length = len = XDR_GETPOS (&xdrs);
+  au->au_origcred.oa_flavor = AUTH_UNIX;
+  au->au_origcred.oa_base = mem_alloc ((u_int) len);
+  if (au->au_origcred.oa_base == NULL)
+    goto no_memory;
+  memcpy(au->au_origcred.oa_base, mymem, (u_int) len);
+
+  /*
+   * set auth handle to reflect new cred.
+   */
+  auth->ah_cred = au->au_origcred;
+  marshal_new_auth (auth);
+  return auth;
 }
 
 /*
  * Returns an auth handle with parameters determined by doing lots of
  * syscalls.
  */
-AUTH *authunix_create_default()
+AUTH *
+authunix_create_default (void)
 {
-	register int len;
-	char machname[MAX_MACHINE_NAME + 1];
-	register int uid;
-	register int gid;
-	int gids[NGRPS];
-
-	if (gethostname(machname, MAX_MACHINE_NAME) == -1)
-		abort();
-	machname[MAX_MACHINE_NAME] = 0;
-	uid = geteuid();
-	gid = getegid();
-	if ((len = getgroups(NGRPS, gids)) < 0)
-		abort();
-	return (authunix_create(machname, uid, gid, len, gids));
+  int len;
+  char machname[MAX_MACHINE_NAME + 1];
+  uid_t uid;
+  gid_t gid;
+  int max_nr_groups = sysconf (_SC_NGROUPS_MAX);
+  gid_t gids[max_nr_groups];
+
+  if (gethostname (machname, MAX_MACHINE_NAME) == -1)
+    abort ();
+  machname[MAX_MACHINE_NAME] = 0;
+  uid = geteuid ();
+  gid = getegid ();
+
+  if ((len = getgroups (max_nr_groups, gids)) < 0)
+    abort ();
+  /* This braindamaged Sun code forces us here to truncate the
+     list of groups to NGRPS members since the code in
+     authuxprot.c transforms a fixed array.  Grrr.  */
+  return authunix_create (machname, uid, gid, MIN (NGRPS, len), gids);
 }
 
 /*
  * authunix operations
  */
 
-static void authunix_nextverf(auth)
-AUTH *auth;
+static void
+authunix_nextverf (AUTH *auth)
 {
-	/* no action necessary */
+  /* no action necessary */
 }
 
-static bool_t authunix_marshal(auth, xdrs)
-AUTH *auth;
-XDR *xdrs;
+static bool_t
+authunix_marshal (AUTH *auth, XDR *xdrs)
 {
-	register struct audata *au = AUTH_PRIVATE(auth);
+  struct audata *au = AUTH_PRIVATE (auth);
 
-	return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
+  return XDR_PUTBYTES (xdrs, au->au_marshed, au->au_mpos);
 }
 
-static bool_t authunix_validate(auth, verf)
-register AUTH *auth;
-struct opaque_auth verf;
+static bool_t
+authunix_validate (AUTH *auth, struct opaque_auth *verf)
 {
-	register struct audata *au;
-	XDR xdrs;
-
-	if (verf.oa_flavor == AUTH_SHORT) {
-		au = AUTH_PRIVATE(auth);
-		xdrmem_create(&xdrs, verf.oa_base, verf.oa_length, XDR_DECODE);
-
-		if (au->au_shcred.oa_base != NULL) {
-			mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
-			au->au_shcred.oa_base = NULL;
-		}
-		if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
-			auth->ah_cred = au->au_shcred;
-		} else {
-			xdrs.x_op = XDR_FREE;
-			(void) xdr_opaque_auth(&xdrs, &au->au_shcred);
-			au->au_shcred.oa_base = NULL;
-			auth->ah_cred = au->au_origcred;
-		}
-		marshal_new_auth(auth);
+  struct audata *au;
+  XDR xdrs;
+
+  if (verf->oa_flavor == AUTH_SHORT)
+    {
+      au = AUTH_PRIVATE (auth);
+      xdrmem_create (&xdrs, verf->oa_base, verf->oa_length,
+		     XDR_DECODE);
+
+      if (au->au_shcred.oa_base != NULL)
+	{
+	  mem_free (au->au_shcred.oa_base,
+		    au->au_shcred.oa_length);
+	  au->au_shcred.oa_base = NULL;
 	}
-	return (TRUE);
+      if (xdr_opaque_auth (&xdrs, &au->au_shcred))
+	{
+	  auth->ah_cred = au->au_shcred;
+	}
+      else
+	{
+	  xdrs.x_op = XDR_FREE;
+	  (void) xdr_opaque_auth (&xdrs, &au->au_shcred);
+	  au->au_shcred.oa_base = NULL;
+	  auth->ah_cred = au->au_origcred;
+	}
+      marshal_new_auth (auth);
+    }
+  return TRUE;
 }
 
-static bool_t authunix_refresh(auth)
-register AUTH *auth;
+static bool_t
+authunix_refresh (AUTH *auth)
 {
-	register struct audata *au = AUTH_PRIVATE(auth);
-	struct authunix_parms aup;
-	struct timeval now;
-	XDR xdrs;
-	register int stat;
-
-	if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
-		/* there is no hope.  Punt */
-		return (FALSE);
-	}
-	au->au_shfaults++;
-
-	/* first deserialize the creds back into a struct authunix_parms */
-	aup.aup_machname = NULL;
-	aup.aup_gids = (int *) NULL;
-	xdrmem_create(&xdrs, au->au_origcred.oa_base,
-				  au->au_origcred.oa_length, XDR_DECODE);
-	stat = xdr_authunix_parms(&xdrs, &aup);
-	if (!stat)
-		goto done;
-
-	/* update the time and serialize in place */
-	(void) gettimeofday(&now, (struct timezone *) 0);
-	aup.aup_time = now.tv_sec;
-	xdrs.x_op = XDR_ENCODE;
-	XDR_SETPOS(&xdrs, 0);
-	stat = xdr_authunix_parms(&xdrs, &aup);
-	if (!stat)
-		goto done;
-	auth->ah_cred = au->au_origcred;
-	marshal_new_auth(auth);
-  done:
-	/* free the struct authunix_parms created by deserializing */
-	xdrs.x_op = XDR_FREE;
-	(void) xdr_authunix_parms(&xdrs, &aup);
-	XDR_DESTROY(&xdrs);
-	return (stat);
+  struct audata *au = AUTH_PRIVATE (auth);
+  struct authunix_parms aup;
+  struct timeval now;
+  XDR xdrs;
+  int stat;
+
+  if (auth->ah_cred.oa_base == au->au_origcred.oa_base)
+    {
+      /* there is no hope.  Punt */
+      return FALSE;
+    }
+  au->au_shfaults++;
+
+  /* first deserialize the creds back into a struct authunix_parms */
+  aup.aup_machname = NULL;
+  aup.aup_gids = (gid_t *) NULL;
+  xdrmem_create (&xdrs, au->au_origcred.oa_base,
+		 au->au_origcred.oa_length, XDR_DECODE);
+  stat = xdr_authunix_parms (&xdrs, &aup);
+  if (!stat)
+    goto done;
+
+  /* update the time and serialize in place */
+  (void) gettimeofday (&now, (struct timezone *) 0);
+  aup.aup_time = now.tv_sec;
+  xdrs.x_op = XDR_ENCODE;
+  XDR_SETPOS (&xdrs, 0);
+  stat = xdr_authunix_parms (&xdrs, &aup);
+  if (!stat)
+    goto done;
+  auth->ah_cred = au->au_origcred;
+  marshal_new_auth (auth);
+done:
+  /* free the struct authunix_parms created by deserializing */
+  xdrs.x_op = XDR_FREE;
+  (void) xdr_authunix_parms (&xdrs, &aup);
+  XDR_DESTROY (&xdrs);
+  return stat;
 }
 
-static void authunix_destroy(auth)
-register AUTH *auth;
+static void
+authunix_destroy (AUTH *auth)
 {
-	register struct audata *au = AUTH_PRIVATE(auth);
+  struct audata *au = AUTH_PRIVATE (auth);
 
-	mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
+  mem_free (au->au_origcred.oa_base, au->au_origcred.oa_length);
 
-	if (au->au_shcred.oa_base != NULL)
-		mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
+  if (au->au_shcred.oa_base != NULL)
+    mem_free (au->au_shcred.oa_base, au->au_shcred.oa_length);
 
-	mem_free(auth->ah_private, sizeof(struct audata));
+  mem_free (auth->ah_private, sizeof (struct audata));
 
-	if (auth->ah_verf.oa_base != NULL)
-		mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
+  if (auth->ah_verf.oa_base != NULL)
+    mem_free (auth->ah_verf.oa_base, auth->ah_verf.oa_length);
 
-	mem_free((caddr_t) auth, sizeof(*auth));
+  mem_free ((caddr_t) auth, sizeof (*auth));
 }
 
 /*
  * Marshals (pre-serializes) an auth struct.
  * sets private data, au_marshed and au_mpos
  */
-static void marshal_new_auth(auth)
-register AUTH *auth;
+static bool_t
+internal_function
+marshal_new_auth (AUTH *auth)
 {
-	XDR xdr_stream;
-	register XDR *xdrs = &xdr_stream;
-	register struct audata *au = AUTH_PRIVATE(auth);
-
-	xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
-	if ((!xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
-		(!xdr_opaque_auth(xdrs, &(auth->ah_verf)))) {
-		perror("auth_none.c - Fatal marshalling problem");
-	} else {
-		au->au_mpos = XDR_GETPOS(xdrs);
-	}
-	XDR_DESTROY(xdrs);
+  XDR xdr_stream;
+  XDR *xdrs = &xdr_stream;
+  struct audata *au = AUTH_PRIVATE (auth);
+
+  xdrmem_create (xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
+  if ((!xdr_opaque_auth (xdrs, &(auth->ah_cred))) ||
+      (!xdr_opaque_auth (xdrs, &(auth->ah_verf))))
+    perror (_("auth_none.c - Fatal marshalling problem"));
+  else
+    au->au_mpos = XDR_GETPOS (xdrs);
+
+  XDR_DESTROY (xdrs);
+
+  return TRUE;
 }

+ 27 - 25
libc/inet/rpc/authunix_prot.c

@@ -1,4 +1,3 @@
-/* @(#)authunix_prot.c	2.1 88/07/29 4.0 RPCSRC */
 /*
  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  * unrestricted use provided that this legend is included on all tape
@@ -6,38 +5,35 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
-
+/*
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
 /*
  * authunix_prot.c
  * XDR for UNIX style authentication parameters for RPC
- *
- * Copyright (C) 1984, Sun Microsystems, Inc.
  */
 
-
 #include <rpc/types.h>
 #include <rpc/xdr.h>
 #include <rpc/auth.h>
@@ -45,19 +41,25 @@
 
 /*
  * XDR for unix authentication parameters.
+ * Unfortunately, none of these can be declared const.
  */
-bool_t xdr_authunix_parms(xdrs, p)
-register XDR *xdrs;
-register struct authunix_parms *p;
+bool_t
+xdr_authunix_parms (XDR * xdrs, struct authunix_parms *p)
 {
-
-	if (xdr_u_long(xdrs, &(p->aup_time))
-		&& xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME)
-		&& xdr_int(xdrs, &(p->aup_uid))
-		&& xdr_int(xdrs, &(p->aup_gid))
-		&& xdr_array(xdrs, (caddr_t *) & (p->aup_gids),
-					 &(p->aup_len), NGRPS, sizeof(int), (xdrproc_t) xdr_int)) {
-		return (TRUE);
-	}
-	return (FALSE);
+  if (xdr_u_long (xdrs, &(p->aup_time))
+      && xdr_string (xdrs, &(p->aup_machname), MAX_MACHINE_NAME)
+      && (sizeof (uid_t) == sizeof (short int)
+	  ? xdr_u_short (xdrs, (u_short *) & (p->aup_uid))
+	  : xdr_u_int (xdrs, (u_int *) & (p->aup_uid)))
+      && (sizeof (gid_t) == sizeof (short int)
+	  ? xdr_u_short (xdrs, (u_short *) & (p->aup_gid))
+	  : xdr_u_int (xdrs, (u_int *) & (p->aup_gid)))
+      && xdr_array (xdrs, (caddr_t *) & (p->aup_gids),
+		    & (p->aup_len), NGRPS, sizeof (gid_t),
+		      (sizeof (gid_t) == sizeof (short int)
+		       ? (xdrproc_t) xdr_u_short : (xdrproc_t) xdr_u_int)))
+    {
+      return TRUE;
+    }
+  return FALSE;
 }

+ 42 - 35
libc/inet/rpc/bindresvport.c

@@ -5,77 +5,84 @@
  * 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
  */
-
 /*
  * Copyright (c) 1987 by Sun Microsystems, Inc.
  */
 
 #define __FORCE_GLIBC
 #include <features.h>
+
+#include <errno.h>
 #include <unistd.h>
 #include <string.h>
 #include <sys/types.h>
-#include <sys/errno.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 
 /*
  * Bind a socket to a privileged IP port
  */
-int bindresvport(sd, sin)
-int sd;
-struct sockaddr_in *sin;
+int
+bindresvport (int sd, struct sockaddr_in *sin)
 {
-	int res;
-	static short port;
-	struct sockaddr_in myaddr;
-	extern int errno;
-	int i;
+  int res;
+  static short port;
+  struct sockaddr_in myaddr;
+  int i;
 
 #define STARTPORT 600
 #define ENDPORT (IPPORT_RESERVED - 1)
 #define NPORTS	(ENDPORT - STARTPORT + 1)
 
-	if (sin == (struct sockaddr_in *) 0) {
-		sin = &myaddr;
-		bzero(sin, sizeof(*sin));
-		sin->sin_family = AF_INET;
-	} else if (sin->sin_family != AF_INET) {
-		__set_errno(EPFNOSUPPORT);
-		return (-1);
-	}
-	if (port == 0) {
-		port = (getpid() % NPORTS) + STARTPORT;
-	}
-	res = -1;
-	__set_errno(EADDRINUSE);
-	for (i = 0; i < NPORTS && res < 0 && errno == EADDRINUSE; i++) {
-		sin->sin_port = htons(port++);
-		if (port > ENDPORT) {
-			port = STARTPORT;
-		}
-		res = bind(sd, (struct sockaddr *)sin, (socklen_t)sizeof(struct sockaddr_in));
+  if (sin == (struct sockaddr_in *) 0)
+    {
+      sin = &myaddr;
+      bzero (sin, sizeof (*sin));
+      sin->sin_family = AF_INET;
+    }
+  else if (sin->sin_family != AF_INET)
+    {
+      __set_errno (EPFNOSUPPORT);
+      return -1;
+    }
+
+  if (port == 0)
+    {
+      port = (getpid () % NPORTS) + STARTPORT;
+    }
+  res = -1;
+  __set_errno (EADDRINUSE);
+
+  for (i = 0; i < NPORTS && res < 0 && errno == EADDRINUSE; ++i)
+    {
+      sin->sin_port = htons (port++);
+      if (port > ENDPORT)
+	{
+	  port = STARTPORT;
 	}
-	return (res);
+      res = bind(sd, (struct sockaddr *)sin, sizeof(struct sockaddr_in));
+    }
+
+  return res;
 }

+ 126 - 68
libc/inet/rpc/clnt_generic.c

@@ -1,4 +1,3 @@
-/* @(#)clnt_generic.c	2.2 88/08/01 4.0 RPCSRC */
 /*
  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  * unrestricted use provided that this legend is included on all tape
@@ -6,11 +5,11 @@
  * 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.
@@ -18,20 +17,25 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
 /*
  * Copyright (C) 1987, Sun Microsystems, Inc.
  */
+
+#define __FORCE_GLIBC
+#include <features.h>
+
+#include <alloca.h>
+#include <errno.h>
+#include <string.h>
 #include <rpc/rpc.h>
 #include <sys/socket.h>
 #include <sys/errno.h>
@@ -39,72 +43,126 @@
 
 /*
  * Generic client creation: takes (hostname, program-number, protocol) and
- * returns client handle. Default options are set, which the user can 
+ * returns client handle. Default options are set, which the user can
  * change using the rpc equivalent of ioctl()'s.
  */
-CLIENT *clnt_create __P ((const char *hostname, const u_long prog,
-				 const u_long vers, const char *proto))
+CLIENT *
+clnt_create (const char *hostname, u_long prog, u_long vers,
+	     const char *proto)
 {
-	struct hostent *h;
-	struct protoent *p;
-	struct sockaddr_in sin;
-	int sock;
-	struct timeval tv;
-	CLIENT *client;
+  struct hostent hostbuf, *h;
+  size_t hstbuflen;
+  char *hsttmpbuf;
+  struct protoent *p;
+  struct sockaddr_in sin;
+  struct sockaddr_un sun;
+  int sock;
+  struct timeval tv;
+  CLIENT *client;
+  int herr;
 
-	h = gethostbyname(hostname);
-	if (h == NULL) {
-		rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
-		return (NULL);
-	}
-	if (h->h_addrtype != AF_INET) {
-		/*
-		 * Only support INET for now
-		 */
-		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
-		rpc_createerr.cf_error.re_errno = EAFNOSUPPORT;
-		return (NULL);
-	}
-#ifdef __linux__
-	bzero((char *) &sin, sizeof(sin));
-#endif
-	sin.sin_family = h->h_addrtype;
-	sin.sin_port = 0;
-#ifndef __linux__
-	bzero(sin.sin_zero, sizeof(sin.sin_zero));
+  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;
+#if 0
+      /* This is not wanted.  This would disable the user from having
+	 a timeout in the clnt_call() call.  Only a call to cnlt_control()
+	 by the user should set the timeout value.  */
+      tv.tv_sec = 25;
+      tv.tv_usec = 0;
+      clnt_control (client, CLSET_TIMEOUT, (char *)&tv);
 #endif
-	bcopy(h->h_addr, (char *) &sin.sin_addr, h->h_length);
-	p = getprotobyname(proto);
-	if (p == NULL) {
-		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
-		rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;
-		return (NULL);
+      return client;
+    }
+
+  hstbuflen = 1024;
+  hsttmpbuf = alloca (hstbuflen);
+  while (gethostbyname_r (hostname, &hostbuf, hsttmpbuf, hstbuflen,
+			    &h, &herr) != 0
+	 || h == NULL)
+    if (herr != NETDB_INTERNAL || errno != ERANGE)
+      {
+	get_rpc_createerr().cf_stat = RPC_UNKNOWNHOST;
+	return NULL;
+      }
+    else
+      {
+	/* Enlarge the buffer.  */
+	hstbuflen *= 2;
+	hsttmpbuf = alloca (hstbuflen);
+      }
+
+  if (h->h_addrtype != AF_INET)
+    {
+      /*
+       * Only support INET for now
+       */
+      struct rpc_createerr *ce = &get_rpc_createerr ();
+      ce->cf_stat = RPC_SYSTEMERROR;
+      ce->cf_error.re_errno = EAFNOSUPPORT;
+      return NULL;
+    }
+  sin.sin_family = h->h_addrtype;
+  sin.sin_port = 0;
+  bzero (sin.sin_zero, sizeof (sin.sin_zero));
+  memcpy ((char *) &sin.sin_addr, h->h_addr, h->h_length);
+
+#warning getprotobyname is not reentrant...  Add getprotobyname_r
+  p = getprotobyname(proto);
+  if (p == NULL) {
+      struct rpc_createerr *ce = &get_rpc_createerr ();
+      ce->cf_stat = RPC_UNKNOWNPROTO;
+      ce->cf_error.re_errno = EPFNOSUPPORT;
+      return NULL;
+  }
+
+  sock = RPC_ANYSOCK;
+  switch (p->p_proto)
+    {
+    case IPPROTO_UDP:
+      tv.tv_sec = 5;
+      tv.tv_usec = 0;
+      client = clntudp_create (&sin, prog, vers, tv, &sock);
+      if (client == NULL)
+	{
+	  return NULL;
 	}
-	sock = RPC_ANYSOCK;
-	switch (p->p_proto) {
-	case IPPROTO_UDP:
-		tv.tv_sec = 5;
-		tv.tv_usec = 0;
-		client = clntudp_create(&sin, prog, vers, tv, &sock);
-		if (client == NULL) {
-			return (NULL);
-		}
-		tv.tv_sec = 25;
-		clnt_control(client, CLSET_TIMEOUT, (char*)&tv);
-		break;
-	case IPPROTO_TCP:
-		client = clnttcp_create(&sin, 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);
-		break;
-	default:
-		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
-		rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;
-		return (NULL);
+#if 0
+      /* This is not wanted.  This would disable the user from having
+	 a timeout in the clnt_call() call.  Only a call to cnlt_control()
+	 by the user should set the timeout value.  */
+      tv.tv_sec = 25;
+      clnt_control (client, CLSET_TIMEOUT, (char *)&tv);
+#endif
+      break;
+    case IPPROTO_TCP:
+      client = clnttcp_create (&sin, prog, vers, &sock, 0, 0);
+      if (client == NULL)
+	{
+	  return NULL;
 	}
-	return (client);
+#if 0
+      /* This is not wanted.  This would disable the user from having
+	 a timeout in the clnt_call() call.  Only a call to cnlt_control()
+	 by the user should set the timeout value.  */
+      tv.tv_sec = 25;
+      tv.tv_usec = 0;
+      clnt_control (client, CLSET_TIMEOUT, (char *)&tv);
+#endif
+      break;
+    default:
+      {
+	struct rpc_createerr *ce = &get_rpc_createerr ();
+	ce->cf_stat = RPC_SYSTEMERROR;
+	ce->cf_error.re_errno = EPFNOSUPPORT;
+      }
+      return (NULL);
+    }
+  return client;
 }

+ 349 - 206
libc/inet/rpc/clnt_perror.c

@@ -6,29 +6,30 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro";
+#endif
 
 /*
  * clnt_perror.c
@@ -36,254 +37,396 @@
  * Copyright (C) 1984, Sun Microsystems, Inc.
  *
  */
+#define __FORCE_GLIBC
+#include <features.h>
 
 #include <stdio.h>
 #include <string.h>
+#include <rpc/rpc.h>
 
-#include <rpc/types.h>
-#include <rpc/auth.h>
-#include <rpc/clnt.h>
-
-static char *auth_errmsg();
+#ifdef USE_IN_LIBIO
+# include <wchar.h>
+# include <libio/iolibio.h>
+# define fputs(s, f) _IO_fputs (s, f)
+#endif
 
-extern char *strcpy();
+static char *auth_errmsg (enum auth_stat stat) internal_function;
 
+#ifdef _RPC_THREAD_SAFE_
+/*
+ * Making buf a preprocessor macro requires renaming the local
+ * buf variable in a few functions.  Overriding a global variable
+ * with a local variable of the same name is a bad idea, anyway.
+ */
+#define buf ((char *)RPC_THREAD_VARIABLE(clnt_perr_buf_s))
+#else
 static char *buf;
+#endif
 
-static char *_buf()
+static char *
+_buf (void)
 {
-
-	if (buf == 0)
-		buf = (char *) malloc(256);
-	return (buf);
+  if (buf == NULL)
+    buf = (char *) malloc (256);
+  return buf;
 }
 
 /*
  * Print reply error info
  */
-char *clnt_sperror __P ((CLIENT *rpch, const char *s))
+char *
+clnt_sperror (CLIENT * rpch, const char *msg)
 {
-	struct rpc_err e;
-	void clnt_perrno();
-	char *err;
-	char *str = _buf();
-	char *strstart = str;
-
-	if (str == 0)
-		return (0);
-	CLNT_GETERR(rpch, &e);
-
-	(void) sprintf(str, "%s: ", s);
-	str += strlen(str);
-
-	(void) strcpy(str, clnt_sperrno(e.re_status));
-	str += strlen(str);
-
-	switch (e.re_status) {
-	case RPC_SUCCESS:
-	case RPC_CANTENCODEARGS:
-	case RPC_CANTDECODERES:
-	case RPC_TIMEDOUT:
-	case RPC_PROGUNAVAIL:
-	case RPC_PROCUNAVAIL:
-	case RPC_CANTDECODEARGS:
-	case RPC_SYSTEMERROR:
-	case RPC_UNKNOWNHOST:
-	case RPC_UNKNOWNPROTO:
-	case RPC_PMAPFAILURE:
-	case RPC_PROGNOTREGISTERED:
-	case RPC_FAILED:
-		break;
-
-	case RPC_CANTSEND:
-	case RPC_CANTRECV:
-		(void) sprintf(str, "; errno = %s", strerror (e.re_errno));
-		str += strlen(str);
-		break;
-
-	case RPC_VERSMISMATCH:
-		(void) sprintf(str,
-					   "; low version = %lu, high version = %lu",
-					   e.re_vers.low, e.re_vers.high);
-		str += strlen(str);
-		break;
-
-	case RPC_AUTHERROR:
-		err = auth_errmsg(e.re_why);
-		(void) sprintf(str, "; why = ");
-		str += strlen(str);
-		if (err != NULL) {
-			(void) sprintf(str, "%s", err);
-		} else {
-			(void) sprintf(str,
-						   "(unknown authentication error - %d)",
-						   (int) e.re_why);
-		}
-		str += strlen(str);
-		break;
-
-	case RPC_PROGVERSMISMATCH:
-		(void) sprintf(str,
-					   "; low version = %lu, high version = %lu",
-					   e.re_vers.low, e.re_vers.high);
-		str += strlen(str);
-		break;
-
-	default:					/* unknown */
-		(void) sprintf(str,
-					   "; s1 = %lu, s2 = %lu", e.re_lb.s1, e.re_lb.s2);
-		str += strlen(str);
-		break;
+  char chrbuf[1024];
+  struct rpc_err e;
+  char *err;
+  char *str = _buf ();
+  char *strstart = str;
+  int len;
+
+  if (str == NULL)
+    return NULL;
+  CLNT_GETERR (rpch, &e);
+
+  len = sprintf (str, "%s: ", msg);
+  str += len;
+
+  (void) strcpy(str, clnt_sperrno(e.re_status));
+  str += strlen(str);
+
+  switch (e.re_status)
+    {
+    case RPC_SUCCESS:
+    case RPC_CANTENCODEARGS:
+    case RPC_CANTDECODERES:
+    case RPC_TIMEDOUT:
+    case RPC_PROGUNAVAIL:
+    case RPC_PROCUNAVAIL:
+    case RPC_CANTDECODEARGS:
+    case RPC_SYSTEMERROR:
+    case RPC_UNKNOWNHOST:
+    case RPC_UNKNOWNPROTO:
+    case RPC_PMAPFAILURE:
+    case RPC_PROGNOTREGISTERED:
+    case RPC_FAILED:
+      break;
+
+    case RPC_CANTSEND:
+    case RPC_CANTRECV:
+      strerror_r (e.re_errno, chrbuf, sizeof chrbuf);
+      len = sprintf (str, "; errno = %s", chrbuf); 
+      str += len;
+      break;
+
+    case RPC_VERSMISMATCH:
+      len= sprintf (str, _("; low version = %lu, high version = %lu"),
+		    e.re_vers.low, e.re_vers.high);
+      str += len;
+      break;
+
+    case RPC_AUTHERROR:
+      err = auth_errmsg (e.re_why);
+      (void) strcpy(str, _("; why = "));
+      str += strlen(str);
+
+      if (err != NULL)
+	{
+	  (void) strcpy(str, err);
+	  str += strlen(str);
+	}
+      else
+	{
+	  len = sprintf (str, _("(unknown authentication error - %d)"),
+			 (int) e.re_why);
+	  str += len;
 	}
-	(void) sprintf(str, "\n");
-	return (strstart);
+      break;
+
+    case RPC_PROGVERSMISMATCH:
+      len = sprintf (str, _("; low version = %lu, high version = %lu"),
+		     e.re_vers.low, e.re_vers.high);
+      str += len;
+      break;
+
+    default:			/* unknown */
+      len = sprintf (str, "; s1 = %lu, s2 = %lu", e.re_lb.s1, e.re_lb.s2);
+      str += len;
+      break;
+    }
+  *str = '\n';
+  *++str = '\0';
+  return (strstart);
 }
 
-void clnt_perror __P ((CLIENT *rpch, const char *s))
+void
+clnt_perror (CLIENT * rpch, const char *msg)
 {
-	(void) fprintf(stderr, "%s", clnt_sperror(rpch, s));
+#ifdef USE_IN_LIBIO
+  if (_IO_fwide (stderr, 0) > 0)
+    (void) __fwprintf (stderr, L"%s", clnt_sperror (rpch, msg));
+  else
+#endif
+    (void) fputs (clnt_sperror (rpch, msg), stderr);
 }
 
 
-struct rpc_errtab {
-	enum clnt_stat status;
-	char *message;
+struct rpc_errtab
+{
+  enum clnt_stat status;
+  unsigned int message_off;
 };
 
-#if 0
-static struct rpc_errtab rpc_errlist[] = {
-	{RPC_SUCCESS,
-	 "RPC: Success"},
-	{RPC_CANTENCODEARGS,
-	 "RPC: Can't encode arguments"},
-	{RPC_CANTDECODERES,
-	 "RPC: Can't decode result"},
-	{RPC_CANTSEND,
-	 "RPC: Unable to send"},
-	{RPC_CANTRECV,
-	 "RPC: Unable to receive"},
-	{RPC_TIMEDOUT,
-	 "RPC: Timed out"},
-	{RPC_VERSMISMATCH,
-	 "RPC: Incompatible versions of RPC"},
-	{RPC_AUTHERROR,
-	 "RPC: Authentication error"},
-	{RPC_PROGUNAVAIL,
-	 "RPC: Program unavailable"},
-	{RPC_PROGVERSMISMATCH,
-	 "RPC: Program/version mismatch"},
-	{RPC_PROCUNAVAIL,
-	 "RPC: Procedure unavailable"},
-	{RPC_CANTDECODEARGS,
-	 "RPC: Server can't decode arguments"},
-	{RPC_SYSTEMERROR,
-	 "RPC: Remote system error"},
-	{RPC_UNKNOWNHOST,
-	 "RPC: Unknown host"},
-	{RPC_UNKNOWNPROTO,
-	 "RPC: Unknown protocol"},
-	{RPC_PMAPFAILURE,
-	 "RPC: Port mapper failure"},
-	{RPC_PROGNOTREGISTERED,
-	 "RPC: Program not registered"},
-	{RPC_FAILED,
-	 "RPC: Failed (unspecified error)"}
+static const char rpc_errstr[] =
+{
+#define RPC_SUCCESS_IDX		0
+  _("RPC: Success")
+  "\0"
+#define RPC_CANTENCODEARGS_IDX	(RPC_SUCCESS_IDX + sizeof "RPC: Success")
+  _("RPC: Can't encode arguments")
+  "\0"
+#define RPC_CANTDECODERES_IDX	(RPC_CANTENCODEARGS_IDX \
+				 + sizeof "RPC: Can't encode arguments")
+  _("RPC: Can't decode result")
+  "\0"
+#define RPC_CANTSEND_IDX	(RPC_CANTDECODERES_IDX \
+				 + sizeof "RPC: Can't decode result")
+  _("RPC: Unable to send")
+  "\0"
+#define RPC_CANTRECV_IDX	(RPC_CANTSEND_IDX \
+				 + sizeof "RPC: Unable to send")
+  _("RPC: Unable to receive")
+  "\0"
+#define RPC_TIMEDOUT_IDX	(RPC_CANTRECV_IDX \
+				 + sizeof "RPC: Unable to receive")
+  _("RPC: Timed out")
+  "\0"
+#define RPC_VERSMISMATCH_IDX	(RPC_TIMEDOUT_IDX \
+				 + sizeof "RPC: Timed out")
+  _("RPC: Incompatible versions of RPC")
+  "\0"
+#define RPC_AUTHERROR_IDX	(RPC_VERSMISMATCH_IDX \
+				 + sizeof "RPC: Incompatible versions of RPC")
+  _("RPC: Authentication error")
+  "\0"
+#define RPC_PROGUNAVAIL_IDX		(RPC_AUTHERROR_IDX \
+				 + sizeof "RPC: Authentication error")
+  _("RPC: Program unavailable")
+  "\0"
+#define RPC_PROGVERSMISMATCH_IDX (RPC_PROGUNAVAIL_IDX \
+				  + sizeof "RPC: Program unavailable")
+  _("RPC: Program/version mismatch")
+  "\0"
+#define RPC_PROCUNAVAIL_IDX	(RPC_PROGVERSMISMATCH_IDX \
+				 + sizeof "RPC: Program/version mismatch")
+  _("RPC: Procedure unavailable")
+  "\0"
+#define RPC_CANTDECODEARGS_IDX	(RPC_PROCUNAVAIL_IDX \
+				 + sizeof "RPC: Procedure unavailable")
+  _("RPC: Server can't decode arguments")
+  "\0"
+#define RPC_SYSTEMERROR_IDX	(RPC_CANTDECODEARGS_IDX \
+				 + sizeof "RPC: Server can't decode arguments")
+  _("RPC: Remote system error")
+  "\0"
+#define RPC_UNKNOWNHOST_IDX	(RPC_SYSTEMERROR_IDX \
+				 + sizeof "RPC: Remote system error")
+  _("RPC: Unknown host")
+  "\0"
+#define RPC_UNKNOWNPROTO_IDX	(RPC_UNKNOWNHOST_IDX \
+				 + sizeof "RPC: Unknown host")
+  _("RPC: Unknown protocol")
+  "\0"
+#define RPC_PMAPFAILURE_IDX	(RPC_UNKNOWNPROTO_IDX \
+				 + sizeof "RPC: Unknown protocol")
+  _("RPC: Port mapper failure")
+  "\0"
+#define RPC_PROGNOTREGISTERED_IDX (RPC_PMAPFAILURE_IDX \
+				   + sizeof "RPC: Port mapper failure")
+  _("RPC: Program not registered")
+  "\0"
+#define RPC_FAILED_IDX		(RPC_PROGNOTREGISTERED_IDX \
+				 + sizeof "RPC: Program not registered")
+  _("RPC: Failed (unspecified error)")
 };
-#endif
+
+static const struct rpc_errtab rpc_errlist[] =
+{
+  { RPC_SUCCESS, RPC_SUCCESS_IDX },
+  { RPC_CANTENCODEARGS, RPC_CANTENCODEARGS_IDX },
+  { RPC_CANTDECODERES, RPC_CANTDECODERES_IDX },
+  { RPC_CANTSEND, RPC_CANTSEND_IDX },
+  { RPC_CANTRECV, RPC_CANTRECV_IDX },
+  { RPC_TIMEDOUT, RPC_TIMEDOUT_IDX },
+  { RPC_VERSMISMATCH, RPC_VERSMISMATCH_IDX },
+  { RPC_AUTHERROR, RPC_AUTHERROR_IDX },
+  { RPC_PROGUNAVAIL, RPC_PROGUNAVAIL_IDX },
+  { RPC_PROGVERSMISMATCH, RPC_PROGVERSMISMATCH_IDX },
+  { RPC_PROCUNAVAIL, RPC_PROCUNAVAIL_IDX },
+  { RPC_CANTDECODEARGS, RPC_CANTDECODEARGS_IDX },
+  { RPC_SYSTEMERROR, RPC_SYSTEMERROR_IDX },
+  { RPC_UNKNOWNHOST, RPC_UNKNOWNHOST_IDX },
+  { RPC_UNKNOWNPROTO, RPC_UNKNOWNPROTO_IDX },
+  { RPC_PMAPFAILURE, RPC_PMAPFAILURE_IDX },
+  { RPC_PROGNOTREGISTERED, RPC_PROGNOTREGISTERED_IDX },
+  { RPC_FAILED, RPC_FAILED_IDX }
+};
+
 
 /*
  * This interface for use by clntrpc
  */
-char *clnt_sperrno(stat)
-enum clnt_stat stat;
+char *
+clnt_sperrno (enum clnt_stat stat)
 {
-#if 0
-	int i;
+  size_t i;
 
-	for (i = 0; i < sizeof(rpc_errlist) / sizeof(struct rpc_errtab); i++) {
-		if (rpc_errlist[i].status == stat) {
-			return (rpc_errlist[i].message);
-		}
+  for (i = 0; i < sizeof (rpc_errlist) / sizeof (struct rpc_errtab); i++)
+    {
+      if (rpc_errlist[i].status == stat)
+	{
+	  return (char*)_(rpc_errstr + rpc_errlist[i].message_off);
 	}
-#endif
-	return ("RPC: (unknown error code)");
+    }
+  return _("RPC: (unknown error code)");
 }
 
-void clnt_perrno(num)
-enum clnt_stat num;
+void
+clnt_perrno (enum clnt_stat num)
 {
-	(void) fprintf(stderr, "%s", clnt_sperrno(num));
+#ifdef USE_IN_LIBIO
+  if (_IO_fwide (stderr, 0) > 0)
+    (void) __fwprintf (stderr, L"%s", clnt_sperrno (num));
+  else
+#endif
+    (void) fputs (clnt_sperrno (num), stderr);
 }
 
 
-char *clnt_spcreateerror __P ((__const char *s))
+char *
+clnt_spcreateerror (const char *msg)
 {
-#if 0
-	char *str = _buf();
-
-	if (str == 0)
-		return (0);
-	(void) sprintf(str, "%s: ", s);
-	(void) strcat(str, clnt_sperrno(rpc_createerr.cf_stat));
-	switch (rpc_createerr.cf_stat) {
-	case RPC_PMAPFAILURE:
-		(void) strcat(str, " - ");
-		(void) strcat(str, clnt_sperrno(rpc_createerr.cf_error.re_status));
-		break;
-
-	case RPC_SYSTEMERROR:
-		(void) strcat(str, " - ");
-		if (rpc_createerr.cf_error.re_errno > 0)
-			(void) strcat(str, strerror (rpc_createerr.cf_error.re_errno));
-		else
-			(void )sprintf(&str[strlen(str)], "Error %d",
-				       rpc_createerr.cf_error.re_errno);
-		break;
-	}
-	(void) strcat(str, "\n");
-	return (str);
-#endif
-	return(0);
+  char chrbuf[1024];
+  char *str = _buf ();
+  char *cp;
+  int len;
+  struct rpc_createerr *ce;
+
+  if (str == NULL)
+    return NULL;
+  ce = &get_rpc_createerr ();
+  len = sprintf (str, "%s: ", msg);
+  cp = str + len;
+  (void) strcpy(cp, clnt_sperrno (ce->cf_stat));
+  cp += strlen(cp);
+
+  switch (ce->cf_stat)
+    {
+    case RPC_PMAPFAILURE:
+      (void) strcpy(cp, " - ");
+      cp += strlen(cp);
+
+      (void) strcpy(cp, clnt_sperrno (ce->cf_error.re_status));
+      cp += strlen(cp);
+
+      break;
+
+    case RPC_SYSTEMERROR:
+      (void) strcpy(cp, " - ");
+      cp += strlen(cp);
+
+      strerror_r (ce->cf_error.re_errno, chrbuf, sizeof chrbuf);
+      (void) strcpy(cp, chrbuf);
+      cp += strlen(cp);
+      break;
+    default:
+      break;
+    }
+  *cp = '\n';
+  *++cp = '\0';
+  return str;
 }
 
-extern void clnt_pcreateerror __P ((__const char *s))
+void
+clnt_pcreateerror (const char *msg)
 {
-	(void) fprintf(stderr, "%s", clnt_spcreateerror(s));
+#ifdef USE_IN_LIBIO
+  if (_IO_fwide (stderr, 0) > 0)
+    (void) __fwprintf (stderr, L"%s", clnt_spcreateerror (msg));
+  else
+#endif
+    (void) fputs (clnt_spcreateerror (msg), stderr);
 }
 
-struct auth_errtab {
-	enum auth_stat status;
-	char *message;
+struct auth_errtab
+{
+  enum auth_stat status;
+  unsigned int message_off;
 };
 
-static struct auth_errtab auth_errlist[] = {
-	{AUTH_OK,
-	 "Authentication OK"},
-	{AUTH_BADCRED,
-	 "Invalid client credential"},
-	{AUTH_REJECTEDCRED,
-	 "Server rejected credential"},
-	{AUTH_BADVERF,
-	 "Invalid client verifier"},
-	{AUTH_REJECTEDVERF,
-	 "Server rejected verifier"},
-	{AUTH_TOOWEAK,
-	 "Client credential too weak"},
-	{AUTH_INVALIDRESP,
-	 "Invalid server verifier"},
-	{AUTH_FAILED,
-	 "Failed (unspecified error)"},
+static const char auth_errstr[] =
+{
+#define AUTH_OK_IDX		0
+   _("Authentication OK")
+   "\0"
+#define AUTH_BADCRED_IDX	(AUTH_OK_IDX + sizeof "Authentication OK")
+   _("Invalid client credential")
+   "\0"
+#define AUTH_REJECTEDCRED_IDX	(AUTH_BADCRED_IDX \
+				 + sizeof "Invalid client credential")
+   _("Server rejected credential")
+   "\0"
+#define AUTH_BADVERF_IDX	(AUTH_REJECTEDCRED_IDX \
+				 + sizeof "Server rejected credential")
+   _("Invalid client verifier")
+   "\0"
+#define AUTH_REJECTEDVERF_IDX	(AUTH_BADVERF_IDX \
+				 + sizeof "Invalid client verifier")
+   _("Server rejected verifier")
+   "\0"
+#define AUTH_TOOWEAK_IDX	(AUTH_REJECTEDVERF_IDX \
+				 + sizeof "Server rejected verifier")
+   _("Client credential too weak")
+   "\0"
+#define AUTH_INVALIDRESP_IDX	(AUTH_TOOWEAK_IDX \
+				 + sizeof "Client credential too weak")
+   _("Invalid server verifier")
+   "\0"
+#define AUTH_FAILED_IDX		(AUTH_INVALIDRESP_IDX \
+				 + sizeof "Invalid server verifier")
+   _("Failed (unspecified error)")
+};
+
+static const struct auth_errtab auth_errlist[] =
+{
+  { AUTH_OK, AUTH_OK_IDX },
+  { AUTH_BADCRED, AUTH_BADCRED_IDX },
+  { AUTH_REJECTEDCRED, AUTH_REJECTEDCRED_IDX },
+  { AUTH_BADVERF, AUTH_BADVERF_IDX },
+  { AUTH_REJECTEDVERF, AUTH_REJECTEDVERF_IDX },
+  { AUTH_TOOWEAK, AUTH_TOOWEAK_IDX },
+  { AUTH_INVALIDRESP, AUTH_INVALIDRESP_IDX },
+  { AUTH_FAILED, AUTH_FAILED_IDX }
 };
 
-static char *auth_errmsg(stat)
-enum auth_stat stat;
+static char *
+internal_function
+auth_errmsg (enum auth_stat stat)
 {
-	int i;
+  size_t i;
 
-	for (i = 0; i < sizeof(auth_errlist) / sizeof(struct auth_errtab); i++) {
-		if (auth_errlist[i].status == stat) {
-			return (auth_errlist[i].message);
-		}
+  for (i = 0; i < sizeof (auth_errlist) / sizeof (struct auth_errtab); i++)
+    {
+      if (auth_errlist[i].status == stat)
+	{
+	  return (char*)_(auth_errstr + auth_errlist[i].message_off);
 	}
-	return (NULL);
+    }
+  return NULL;
+}
+
+
+static void __attribute__ ((unused))
+free_mem (void)
+{
+  free (buf);
 }

+ 181 - 157
libc/inet/rpc/clnt_raw.c

@@ -6,11 +6,11 @@
  * 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.
@@ -18,17 +18,18 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";
+#endif
 
 /*
  * clnt_raw.c
@@ -37,193 +38,216 @@
  *
  * Memory based rpc for simple testing and timing.
  * Interface to create an rpc client and server in the same process.
- * This lets us similate rpc and get round trip overhead, without
- * any interference from the kernal.
+ * This lets us simulate rpc and get round trip overhead, without
+ * any interference from the kernel.
  */
 
 #include <rpc/rpc.h>
+#include <rpc/svc.h>
+#include <rpc/xdr.h>
 
 #define MCALL_MSG_SIZE 24
 
 /*
  * This is the "network" we will be moving stuff over.
  */
-static struct clntraw_private {
-	CLIENT client_object;
-	XDR xdr_stream;
-	char _raw_buf[UDPMSGSIZE];
-	char mashl_callmsg[MCALL_MSG_SIZE];
-	u_int mcnt;
-} *clntraw_private;
-
-static enum clnt_stat clntraw_call();
-static void clntraw_abort();
-static void clntraw_geterr();
-static bool_t clntraw_freeres();
-static bool_t clntraw_control();
-static void clntraw_destroy();
-
-static struct clnt_ops client_ops = {
-	clntraw_call,
-	clntraw_abort,
-	clntraw_geterr,
-	clntraw_freeres,
-	clntraw_destroy,
-	clntraw_control
+struct clntraw_private_s
+  {
+    CLIENT client_object;
+    XDR xdr_stream;
+    char _raw_buf[UDPMSGSIZE];
+    char mashl_callmsg[MCALL_MSG_SIZE];
+    u_int mcnt;
+  };
+#ifdef _RPC_THREAD_SAFE_
+#define clntraw_private ((struct clntraw_private_s *)RPC_THREAD_VARIABLE(clntraw_private_s))
+#else
+static struct clntraw_private_s *clntraw_private;
+#endif
+
+static enum clnt_stat clntraw_call (CLIENT *, u_long, xdrproc_t, caddr_t,
+				    xdrproc_t, caddr_t, struct timeval);
+static void clntraw_abort (void);
+static void clntraw_geterr (CLIENT *, struct rpc_err *);
+static bool_t clntraw_freeres (CLIENT *, xdrproc_t, caddr_t);
+static bool_t clntraw_control (CLIENT *, int, char *);
+static void clntraw_destroy (CLIENT *);
+
+static struct clnt_ops client_ops =
+{
+  clntraw_call,
+  clntraw_abort,
+  clntraw_geterr,
+  clntraw_freeres,
+  clntraw_destroy,
+  clntraw_control
 };
 
-void svc_getreq();
-
 /*
  * Create a client handle for memory based rpc.
  */
-CLIENT *clntraw_create(prog, vers)
-u_long prog;
-u_long vers;
+CLIENT *
+clntraw_create (u_long prog, u_long vers)
 {
-	register struct clntraw_private *clp = clntraw_private;
-	struct rpc_msg call_msg;
-	XDR *xdrs = &clp->xdr_stream;
-	CLIENT *client = &clp->client_object;
-
-	if (clp == 0) {
-		clp = (struct clntraw_private *) calloc(1, sizeof(*clp));
-		if (clp == 0)
-			return (0);
-		clntraw_private = clp;
-	}
-	/*
-	 * pre-serialize the staic part of the call msg and stash it away
-	 */
-	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;
-	xdrmem_create(xdrs, clp->mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
-	if (!xdr_callhdr(xdrs, &call_msg)) {
-		perror("clnt_raw.c - Fatal header serialization error.");
-	}
-	clp->mcnt = XDR_GETPOS(xdrs);
-	XDR_DESTROY(xdrs);
-
-	/*
-	 * Set xdrmem for client/server shared buffer
-	 */
-	xdrmem_create(xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE);
-
-	/*
-	 * create client handle
-	 */
-	client->cl_ops = &client_ops;
-	client->cl_auth = authnone_create();
-	return (client);
+  struct clntraw_private_s *clp = clntraw_private;
+  struct rpc_msg call_msg;
+  XDR *xdrs = &clp->xdr_stream;
+  CLIENT *client = &clp->client_object;
+
+  if (clp == 0)
+    {
+      clp = (struct clntraw_private_s *) calloc (1, sizeof (*clp));
+      if (clp == 0)
+	return (0);
+      clntraw_private = clp;
+    }
+  /*
+   * pre-serialize the static part of the call msg and stash it away
+   */
+  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;
+  xdrmem_create (xdrs, clp->mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
+  if (!xdr_callhdr (xdrs, &call_msg))
+    {
+      perror (_ ("clnt_raw.c - Fatal header serialization error."));
+    }
+  clp->mcnt = XDR_GETPOS (xdrs);
+  XDR_DESTROY (xdrs);
+
+  /*
+   * Set xdrmem for client/server shared buffer
+   */
+  xdrmem_create (xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE);
+
+  /*
+   * create client handle
+   */
+  client->cl_ops = &client_ops;
+  client->cl_auth = authnone_create ();
+  return client;
 }
 
 static enum clnt_stat
-clntraw_call(h, proc, xargs, argsp, xresults, resultsp, timeout)
-CLIENT *h;
-u_long proc;
-xdrproc_t xargs;
-caddr_t argsp;
-xdrproc_t xresults;
-caddr_t resultsp;
-struct timeval timeout;
+clntraw_call (h, proc, xargs, argsp, xresults, resultsp, timeout)
+     CLIENT *h;
+     u_long proc;
+     xdrproc_t xargs;
+     caddr_t argsp;
+     xdrproc_t xresults;
+     caddr_t resultsp;
+     struct timeval timeout;
 {
-	register struct clntraw_private *clp = clntraw_private;
-	register XDR *xdrs = &clp->xdr_stream;
-	struct rpc_msg msg;
-	enum clnt_stat status;
-	struct rpc_err error;
-
-	if (clp == 0)
-		return (RPC_FAILED);
-  call_again:
-	/*
-	 * send request
-	 */
-	xdrs->x_op = XDR_ENCODE;
-	XDR_SETPOS(xdrs, 0);
-	((struct rpc_msg *) clp->mashl_callmsg)->rm_xid++;
-	if ((!XDR_PUTBYTES(xdrs, clp->mashl_callmsg, clp->mcnt)) ||
-		(!XDR_PUTLONG(xdrs, (long *) &proc)) ||
-		(!AUTH_MARSHALL(h->cl_auth, xdrs)) || (!(*xargs) (xdrs, argsp))) {
-		return (RPC_CANTENCODEARGS);
+  struct clntraw_private_s *clp = clntraw_private;
+  XDR *xdrs = &clp->xdr_stream;
+  struct rpc_msg msg;
+  enum clnt_stat status;
+  struct rpc_err error;
+
+  if (clp == NULL)
+    return RPC_FAILED;
+call_again:
+  /*
+   * send request
+   */
+  xdrs->x_op = XDR_ENCODE;
+  XDR_SETPOS (xdrs, 0);
+  ((struct rpc_msg *) clp->mashl_callmsg)->rm_xid++;
+  if ((!XDR_PUTBYTES (xdrs, clp->mashl_callmsg, clp->mcnt)) ||
+      (!XDR_PUTLONG (xdrs, (long *) &proc)) ||
+      (!AUTH_MARSHALL (h->cl_auth, xdrs)) ||
+      (!(*xargs) (xdrs, argsp)))
+    {
+      return (RPC_CANTENCODEARGS);
+    }
+  (void) XDR_GETPOS (xdrs);	/* called just to cause overhead */
+
+  /*
+   * We have to call server input routine here because this is
+   * all going on in one process. Yuk.
+   */
+  svc_getreq (1);
+
+  /*
+   * get results
+   */
+  xdrs->x_op = XDR_DECODE;
+  XDR_SETPOS (xdrs, 0);
+  msg.acpted_rply.ar_verf = _null_auth;
+  msg.acpted_rply.ar_results.where = resultsp;
+  msg.acpted_rply.ar_results.proc = xresults;
+  if (!xdr_replymsg (xdrs, &msg))
+    return RPC_CANTDECODERES;
+  _seterr_reply (&msg, &error);
+  status = error.re_status;
+
+  if (status == RPC_SUCCESS)
+    {
+      if (!AUTH_VALIDATE (h->cl_auth, &msg.acpted_rply.ar_verf))
+	{
+	  status = RPC_AUTHERROR;
+	}
+    }				/* end successful completion */
+  else
+    {
+      if (AUTH_REFRESH (h->cl_auth))
+	goto call_again;
+    }				/* end of unsuccessful completion */
+
+  if (status == RPC_SUCCESS)
+    {
+      if (!AUTH_VALIDATE (h->cl_auth, &msg.acpted_rply.ar_verf))
+	{
+	  status = RPC_AUTHERROR;
 	}
-	(void) XDR_GETPOS(xdrs);	/* called just to cause overhead */
-
-	/*
-	 * We have to call server input routine here because this is
-	 * all going on in one process. Yuk.
-	 */
-	svc_getreq(1);
-
-	/*
-	 * get results
-	 */
-	xdrs->x_op = XDR_DECODE;
-	XDR_SETPOS(xdrs, 0);
-	msg.acpted_rply.ar_verf = _null_auth;
-	msg.acpted_rply.ar_results.where = resultsp;
-	msg.acpted_rply.ar_results.proc = xresults;
-	if (!xdr_replymsg(xdrs, &msg))
-		return (RPC_CANTDECODERES);
-	_seterr_reply(&msg, &error);
-	status = error.re_status;
-
-	if (status == RPC_SUCCESS) {
-		if (!AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
-			status = RPC_AUTHERROR;
-		}
-	} /* end successful completion */
-	else {
-		if (AUTH_REFRESH(h->cl_auth))
-			goto call_again;
-	}							/* end of unsuccessful completion */
-
-	if (status == RPC_SUCCESS) {
-		if (!AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
-			status = RPC_AUTHERROR;
-		}
-		if (msg.acpted_rply.ar_verf.oa_base != NULL) {
-			xdrs->x_op = XDR_FREE;
-			(void) xdr_opaque_auth(xdrs, &(msg.acpted_rply.ar_verf));
-		}
+      if (msg.acpted_rply.ar_verf.oa_base != NULL)
+	{
+	  xdrs->x_op = XDR_FREE;
+	  (void) xdr_opaque_auth (xdrs, &(msg.acpted_rply.ar_verf));
 	}
+    }
 
-	return (status);
+  return status;
 }
 
-static void clntraw_geterr()
+static void
+clntraw_geterr (CLIENT *cl, struct rpc_err *err)
 {
 }
 
 
-static bool_t clntraw_freeres(cl, xdr_res, res_ptr)
-CLIENT *cl;
-xdrproc_t xdr_res;
-caddr_t res_ptr;
+static bool_t
+clntraw_freeres (cl, xdr_res, res_ptr)
+     CLIENT *cl;
+     xdrproc_t xdr_res;
+     caddr_t res_ptr;
 {
-	register struct clntraw_private *clp = clntraw_private;
-	register XDR *xdrs = &clp->xdr_stream;
-	bool_t rval;
-
-	if (clp == 0) {
-		rval = (bool_t) RPC_FAILED;
-		return (rval);
-	}
-	xdrs->x_op = XDR_FREE;
-	return ((*xdr_res) (xdrs, res_ptr));
+  struct clntraw_private_s *clp = clntraw_private;
+  XDR *xdrs = &clp->xdr_stream;
+  bool_t rval;
+
+  if (clp == NULL)
+    {
+      rval = (bool_t) RPC_FAILED;
+      return rval;
+    }
+  xdrs->x_op = XDR_FREE;
+  return (*xdr_res) (xdrs, res_ptr);
 }
 
-static void clntraw_abort()
+static void
+clntraw_abort (void)
 {
 }
 
-static bool_t clntraw_control()
+static bool_t
+clntraw_control (CLIENT *cl, int i, char *c)
 {
-	return (FALSE);
+  return FALSE;
 }
 
-static void clntraw_destroy()
+static void
+clntraw_destroy (CLIENT *cl)
 {
 }

+ 120 - 71
libc/inet/rpc/clnt_simple.c

@@ -6,110 +6,159 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro";
+#endif
 
-/* 
+/*
  * clnt_simple.c
  * Simplified front end to rpc.
  *
  * Copyright (C) 1984, Sun Microsystems, Inc.
  */
 
+#define __FORCE_GLIBC
+#include <features.h>
+
+#include <alloca.h>
+#include <errno.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <rpc/rpc.h>
 #include <sys/socket.h>
 #include <netdb.h>
-#include <strings.h>
+#include <string.h>
 
-static struct callrpc_private {
-	CLIENT *client;
-	int socket;
-	int oldprognum, oldversnum, valid;
-	char *oldhost;
-} *callrpc_private;
+struct callrpc_private_s
+  {
+    CLIENT *client;
+    int socket;
+    u_long oldprognum, oldversnum, valid;
+    char *oldhost;
+  };
+#ifdef _RPC_THREAD_SAFE_
+#define callrpc_private ((struct callrpc_private_s *)RPC_THREAD_VARIABLE(callrpc_private_s))
+#else
+static struct callrpc_private_s *callrpc_private;
+#endif
 
-int callrpc (const char *host, const u_long prognum,
-			 const u_long versnum, const u_long procnum,
-			 const xdrproc_t inproc, const char *in,
-			 const xdrproc_t outproc, char *out)
+int
+callrpc (const char *host, u_long prognum, u_long versnum, u_long procnum,
+	 xdrproc_t inproc, const char *in, xdrproc_t outproc, char *out)
 {
-	register struct callrpc_private *crp = callrpc_private;
-	struct sockaddr_in server_addr;
-	enum clnt_stat clnt_stat;
-	struct hostent *hp;
-	struct timeval timeout, tottimeout;
+  struct callrpc_private_s *crp = callrpc_private;
+  struct sockaddr_in server_addr;
+  enum clnt_stat clnt_stat;
+  struct hostent hostbuf, *hp;
+  struct timeval timeout, tottimeout;
 
-	if (crp == 0) {
-		crp = (struct callrpc_private *) calloc(1, sizeof(*crp));
-		if (crp == 0)
-			return (0);
-		callrpc_private = crp;
-	}
-	if (crp->oldhost == NULL) {
-		crp->oldhost = malloc(256);
-		crp->oldhost[0] = 0;
-		crp->socket = RPC_ANYSOCK;
+  if (crp == 0)
+    {
+      crp = (struct callrpc_private_s *) calloc (1, sizeof (*crp));
+      if (crp == 0)
+	return 0;
+      callrpc_private = crp;
+    }
+  if (crp->oldhost == NULL)
+    {
+      crp->oldhost = malloc (256);
+      crp->oldhost[0] = 0;
+      crp->socket = RPC_ANYSOCK;
+    }
+  if (crp->valid && crp->oldprognum == prognum && crp->oldversnum == versnum
+      && strcmp (crp->oldhost, host) == 0)
+    {
+      /* reuse old client */
+    }
+  else
+    {
+      size_t buflen;
+      char *buffer;
+      int herr;
+
+      crp->valid = 0;
+      if (crp->socket != RPC_ANYSOCK)
+	{
+	  (void) close (crp->socket);
+	  crp->socket = RPC_ANYSOCK;
 	}
-	if (crp->valid && crp->oldprognum == prognum
-		&& crp->oldversnum == versnum && 
-		strcmp(crp->oldhost, host) == 0) 
+      if (crp->client)
 	{
-		/* reuse old client */
-	} else {
-		crp->valid = 0;
-		(void) close(crp->socket);
-		crp->socket = RPC_ANYSOCK;
-		if (crp->client) {
-			clnt_destroy(crp->client);
-			crp->client = NULL;
-		}
-		if ((hp = gethostbyname(host)) == NULL)
-			return ((int) RPC_UNKNOWNHOST);
-		timeout.tv_usec = 0;
-		timeout.tv_sec = 5;
-		bcopy(hp->h_addr, (char *) &server_addr.sin_addr, hp->h_length);
-		server_addr.sin_family = AF_INET;
-		server_addr.sin_port = 0;
-		if ((crp->client = clntudp_create(&server_addr, 
-				(u_long) prognum, (u_long) versnum, 
-				timeout, &crp->socket)) == NULL)
-			return ((int) rpc_createerr.cf_stat);
-		crp->valid = 1;
-		crp->oldprognum = prognum;
-		crp->oldversnum = versnum;
-		(void) strcpy(crp->oldhost, host);
+	  clnt_destroy (crp->client);
+	  crp->client = NULL;
+	}
+
+      buflen = 1024;
+      buffer = alloca (buflen);
+      while (gethostbyname_r (host, &hostbuf, buffer, buflen,
+				&hp, &herr) != 0
+	     || hp == NULL)
+	if (herr != NETDB_INTERNAL || errno != ERANGE)
+	  return (int) RPC_UNKNOWNHOST;
+	else
+	  {
+	    /* Enlarge the buffer.  */
+	    buflen *= 2;
+	    buffer = alloca (buflen);
+	  }
+
+      timeout.tv_usec = 0;
+      timeout.tv_sec = 5;
+      memcpy ((char *) &server_addr.sin_addr, hp->h_addr, hp->h_length);
+      server_addr.sin_family = AF_INET;
+      server_addr.sin_port = 0;
+      if ((crp->client = clntudp_create (&server_addr, (u_long) prognum,
+			  (u_long) versnum, timeout, &crp->socket)) == NULL)
+	return (int) get_rpc_createerr().cf_stat;
+      crp->valid = 1;
+      crp->oldprognum = prognum;
+      crp->oldversnum = versnum;
+      (void) strncpy (crp->oldhost, host, 255);
+      crp->oldhost[255] = '\0';
+    }
+  tottimeout.tv_sec = 25;
+  tottimeout.tv_usec = 0;
+  clnt_stat = clnt_call (crp->client, procnum, inproc, (char *) in,
+			 outproc, out, tottimeout);
+  /*
+   * if call failed, empty cache
+   */
+  if (clnt_stat != RPC_SUCCESS)
+    crp->valid = 0;
+  return (int) clnt_stat;
+}
+
+#ifdef _RPC_THREAD_SAFE_
+void
+__rpc_thread_clnt_cleanup (void)
+{
+	struct callrpc_private_s *rcp = RPC_THREAD_VARIABLE(callrpc_private_s);
+
+	if (rcp) {
+		if (rcp->client)
+			CLNT_DESTROY (rcp->client);
+		free (rcp);
 	}
-	tottimeout.tv_sec = 25;
-	tottimeout.tv_usec = 0;
-	clnt_stat = clnt_call(crp->client, procnum, inproc, (char*)in, 
-		outproc, out, tottimeout);
-	/* 
-	 * if call failed, empty cache
-	 */
-	if (clnt_stat != RPC_SUCCESS)
-		crp->valid = 0;
-	return ((int) clnt_stat);
 }
+#endif /* _RPC_THREAD_SAFE_ */

+ 426 - 349
libc/inet/rpc/clnt_tcp.c

@@ -6,29 +6,30 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";
+#endif
 
 /*
  * clnt_tcp.c, Implements a TCP/IP based, client side RPC.
@@ -49,47 +50,57 @@
  * Now go hang yourself.
  */
 
+#define __FORCE_GLIBC
+#include <features.h>
+
+#include <netdb.h>
+#include <errno.h>
 #include <stdio.h>
+#include <unistd.h>
 #include <rpc/rpc.h>
+#include <sys/poll.h>
 #include <sys/socket.h>
-#include <netdb.h>
-#include <errno.h>
 #include <rpc/pmap_clnt.h>
-#include <unistd.h>
+#ifdef USE_IN_LIBIO
+# include <wchar.h>
+#endif
 
-#define MCALL_MSG_SIZE 24
+extern u_long _create_xid (void);
 
-extern int errno;
-
-static int readtcp();
-static int writetcp();
-
-static enum clnt_stat clnttcp_call();
-static void clnttcp_abort();
-static void clnttcp_geterr();
-static bool_t clnttcp_freeres();
-static bool_t clnttcp_control();
-static void clnttcp_destroy();
-
-static struct clnt_ops tcp_ops = {
-	clnttcp_call,
-	clnttcp_abort,
-	clnttcp_geterr,
-	clnttcp_freeres,
-	clnttcp_destroy,
-	clnttcp_control
-};
+#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_in 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;
+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_in 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 readtcp (char *, char *, int);
+static int writetcp (char *, char *, int);
+
+static enum clnt_stat clnttcp_call (CLIENT *, u_long, xdrproc_t, caddr_t,
+				    xdrproc_t, caddr_t, struct timeval);
+static void clnttcp_abort (void);
+static void clnttcp_geterr (CLIENT *, struct rpc_err *);
+static bool_t clnttcp_freeres (CLIENT *, xdrproc_t, caddr_t);
+static bool_t clnttcp_control (CLIENT *, int, char *);
+static void clnttcp_destroy (CLIENT *);
+
+static struct clnt_ops tcp_ops =
+{
+  clnttcp_call,
+  clnttcp_abort,
+  clnttcp_geterr,
+  clnttcp_freeres,
+  clnttcp_destroy,
+  clnttcp_control
 };
 
 /*
@@ -106,282 +117,355 @@ struct ct_data {
  * NB: The rpch->cl_auth is set null authentication.  Caller may wish to set this
  * something more useful.
  */
-CLIENT *clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
-struct sockaddr_in *raddr;
-u_long prog;
-u_long vers;
-register int *sockp;
-u_int sendsz;
-u_int recvsz;
+CLIENT *
+clnttcp_create (struct sockaddr_in *raddr, u_long prog, u_long vers,
+		int *sockp, u_int sendsz, u_int recvsz)
 {
-	CLIENT *h;
-	register struct ct_data *ct;
-	struct timeval now;
-	struct rpc_msg call_msg;
-
-	ct = NULL;					/* in case of fooy */
-	h = (CLIENT *) mem_alloc(sizeof(*h));
-	if (h == NULL) {
-		(void) fprintf(stderr, "clnttcp_create: out of memory\n");
-		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
-		rpc_createerr.cf_error.re_errno = errno;
-		goto fooy;
+  CLIENT *h;
+  struct ct_data *ct;
+  struct rpc_msg call_msg;
+
+  h = (CLIENT *) mem_alloc (sizeof (*h));
+  ct = (struct ct_data *) mem_alloc (sizeof (*ct));
+  if (h == NULL || ct == NULL)
+    {
+      struct rpc_createerr *ce = &get_rpc_createerr ();
+#ifdef USE_IN_LIBIO
+      if (_IO_fwide (stderr, 0) > 0)
+	(void) __fwprintf (stderr, L"%s",
+			   _("clnttcp_create: out of memory\n"));
+      else
+#endif
+	(void) fputs (_("clnttcp_create: out of memory\n"), stderr);
+      ce->cf_stat = RPC_SYSTEMERROR;
+      ce->cf_error.re_errno = ENOMEM;
+      goto fooy;
+    }
+
+  /*
+   * If no port number given ask the pmap for one
+   */
+  if (raddr->sin_port == 0)
+    {
+      u_short port;
+      if ((port = pmap_getport (raddr, prog, vers, IPPROTO_TCP)) == 0)
+	{
+	  mem_free ((caddr_t) ct, sizeof (struct ct_data));
+	  mem_free ((caddr_t) h, sizeof (CLIENT));
+	  return ((CLIENT *) NULL);
 	}
-	ct = (struct ct_data *) mem_alloc(sizeof(*ct));
-	if (ct == NULL) {
-		(void) fprintf(stderr, "clnttcp_create: out of memory\n");
-		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
-		rpc_createerr.cf_error.re_errno = errno;
-		goto fooy;
+      raddr->sin_port = htons (port);
+    }
+
+  /*
+   * If no socket given, open one
+   */
+  if (*sockp < 0)
+    {
+      *sockp = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+      (void) bindresvport (*sockp, (struct sockaddr_in *) 0);
+      if ((*sockp < 0)
+	  || (connect (*sockp, (struct sockaddr *) raddr,
+			 sizeof (*raddr)) < 0))
+	{
+	  struct rpc_createerr *ce = &get_rpc_createerr ();
+	  ce->cf_stat = RPC_SYSTEMERROR;
+	  ce->cf_error.re_errno = errno;
+	  if (*sockp >= 0)
+	    (void) close (*sockp);
+	  goto fooy;
 	}
-
-	/*
-	 * If no port number given ask the pmap for one
-	 */
-	if (raddr->sin_port == 0) {
-		u_short port;
-
-		if ((port = pmap_getport(raddr, prog, vers, IPPROTO_TCP)) == 0) {
-			mem_free((caddr_t) ct, sizeof(struct ct_data));
-
-			mem_free((caddr_t) h, sizeof(CLIENT));
-			return ((CLIENT *) NULL);
-		}
-		raddr->sin_port = htons(port);
-	}
-
-	/*
-	 * If no socket given, open one
-	 */
-	if (*sockp < 0) {
-		*sockp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-		(void) bindresvport(*sockp, (struct sockaddr_in *) 0);
-		if ((*sockp < 0)
-			|| (connect(*sockp, (struct sockaddr *) raddr,
-						sizeof(*raddr)) < 0)) {
-			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
-			rpc_createerr.cf_error.re_errno = errno;
-			(void) close(*sockp);
-			goto fooy;
-		}
-		ct->ct_closeit = TRUE;
-	} else {
-		ct->ct_closeit = FALSE;
+      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
+   */
+  call_msg.rm_xid = _create_xid ();
+  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)
+	{
+	  (void) close (*sockp);
 	}
-
-	/*
-	 * 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
-	 */
-	(void) 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 staic 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) {
-			(void) 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, readtcp, writetcp);
-	h->cl_ops = &tcp_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);
+      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, readtcp, writetcp);
+  h->cl_ops = &tcp_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
-clnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr,
-			 timeout)
-register CLIENT *h;
-u_long proc;
-xdrproc_t xdr_args;
-caddr_t args_ptr;
-xdrproc_t xdr_results;
-caddr_t results_ptr;
-struct timeval timeout;
+clnttcp_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;
 {
-	register struct ct_data *ct = (struct ct_data *) h->cl_private;
-	register XDR *xdrs = &(ct->ct_xdrs);
-	struct rpc_msg reply_msg;
-	u_long x_id;
-	u_long *msg_x_id = (u_long *) (ct->ct_mcall);	/* yuk */
-	register bool_t shipnow;
-	int refreshes = 2;
-
-	if (!ct->ct_waitset) {
-		ct->ct_wait = 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 && ct->ct_wait.tv_sec == 0
+     && ct->ct_wait.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 (ct->ct_wait.tv_sec == 0 && ct->ct_wait.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;
 	}
-
-	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 ((u_int32_t) reply_msg.rm_xid == (u_int32_t) 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;
 	}
-	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);
+      else if (!(*xdr_results) (xdrs, results_ptr))
+	{
+	  if (ct->ct_error.re_status == RPC_SUCCESS)
+	    ct->ct_error.re_status = RPC_CANTDECODERES;
 	}
-
-
-	/*
-	 * 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;
+      /* 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));
 	}
-
-	/*
-	 * 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);
+    }				/* 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 clnttcp_geterr(h, errp)
-CLIENT *h;
-struct rpc_err *errp;
+static void
+clnttcp_geterr (h, errp)
+     CLIENT *h;
+     struct rpc_err *errp;
 {
-	register struct ct_data *ct = (struct ct_data *) h->cl_private;
+  struct ct_data *ct =
+  (struct ct_data *) h->cl_private;
 
-	*errp = ct->ct_error;
+  *errp = ct->ct_error;
 }
 
-static bool_t clnttcp_freeres(cl, xdr_res, res_ptr)
-CLIENT *cl;
-xdrproc_t xdr_res;
-caddr_t res_ptr;
+static bool_t
+clnttcp_freeres (cl, xdr_res, res_ptr)
+     CLIENT *cl;
+     xdrproc_t xdr_res;
+     caddr_t res_ptr;
 {
-	register struct ct_data *ct = (struct ct_data *) cl->cl_private;
-	register XDR *xdrs = &(ct->ct_xdrs);
+  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));
+  xdrs->x_op = XDR_FREE;
+  return (*xdr_res) (xdrs, res_ptr);
 }
 
-static void clnttcp_abort()
+static void
+clnttcp_abort ()
 {
 }
 
-static bool_t clnttcp_control(cl, request, info)
-CLIENT *cl;
-int request;
-char *info;
+static bool_t
+clnttcp_control (CLIENT *cl, int request, char *info)
 {
-	register struct ct_data *ct = (struct ct_data *) cl->cl_private;
-
-	switch (request) {
-	case CLSET_TIMEOUT:
-		ct->ct_wait = *(struct timeval *) info;
-		ct->ct_waitset = TRUE;
-		break;
-	case CLGET_TIMEOUT:
-		*(struct timeval *) info = ct->ct_wait;
-		break;
-	case CLGET_SERVER_ADDR:
-		*(struct sockaddr_in *) info = ct->ct_addr;
-		break;
-	default:
-		return (FALSE);
-	}
-	return (TRUE);
+  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;
+      ct->ct_waitset = TRUE;
+      break;
+    case CLGET_TIMEOUT:
+      *(struct timeval *) info = ct->ct_wait;
+      break;
+    case CLGET_SERVER_ADDR:
+      *(struct sockaddr_in *) 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 clnttcp_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 clnttcp_destroy(h)
-CLIENT *h;
+static void
+clnttcp_destroy (CLIENT *h)
 {
-	register 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 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));
 }
 
 /*
@@ -389,75 +473,68 @@ CLIENT *h;
  * Behaves like the system calls, read & write, but keeps some error state
  * around for the rpc level.
  */
-static int readtcp(ct, buf, len)
-register struct ct_data *ct;
-caddr_t buf;
-register int len;
+static int
+readtcp (char *ctptr, char *buf, int len)
 {
-#ifdef FD_SETSIZE
-	fd_set mask;
-	fd_set readfds;
-
-	if (len == 0)
-		return (0);
-	FD_ZERO(&mask);
-	FD_SET(ct->ct_sock, &mask);
-#else
-	register int mask = 1 << (ct->ct_sock);
-	int readfds;
-
-	if (len == 0)
-		return (0);
-
-#endif							/* def FD_SETSIZE */
-	while (TRUE) {
-		readfds = mask;
-		switch (select
-				(_rpc_dtablesize(), &readfds,  NULL,  NULL,
-				 &(ct->ct_wait))) {
-		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 = read(ct->ct_sock, buf, 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:
-		/* premature eof */
-		ct->ct_error.re_errno = ECONNRESET;
-		ct->ct_error.re_status = RPC_CANTRECV;
-		len = -1;				/* it's really an error */
-		break;
+	  ct->ct_error.re_status = RPC_TIMEDOUT;
+	  return -1;
 
 	case -1:
-		ct->ct_error.re_errno = errno;
-		ct->ct_error.re_status = RPC_CANTRECV;
-		break;
+	  if (errno == EINTR)
+	    continue;
+	  ct->ct_error.re_status = RPC_CANTRECV;
+	  ct->ct_error.re_errno = errno;
+	  return -1;
 	}
-	return (len);
+      break;
+    }
+  switch (len = read (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 writetcp(ct, buf, len)
-struct ct_data *ct;
-caddr_t buf;
-int len;
+static int
+writetcp (char *ctptr, char *buf, int len)
 {
-	register int i, cnt;
-
-	for (cnt = len; cnt > 0; cnt -= i, buf += i) {
-		if ((i = write(ct->ct_sock, buf, cnt)) == -1) {
-			ct->ct_error.re_errno = errno;
-			ct->ct_error.re_status = RPC_CANTSEND;
-			return (-1);
-		}
+  int i, cnt;
+  struct ct_data *ct = (struct ct_data*)ctptr;
+
+  for (cnt = len; cnt > 0; cnt -= i, buf += i)
+    {
+      if ((i = write (ct->ct_sock, buf, cnt)) == -1)
+	{
+	  ct->ct_error.re_errno = errno;
+	  ct->ct_error.re_status = RPC_CANTSEND;
+	  return -1;
 	}
-	return (len);
+    }
+  return len;
 }

+ 511 - 340
libc/inet/rpc/clnt_udp.c

@@ -6,29 +6,30 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";
+#endif
 
 /*
  * clnt_udp.c, Implements a UDP/IP based, client side RPC.
@@ -36,54 +37,73 @@
  * Copyright (C) 1984, Sun Microsystems, Inc.
  */
 
+#define __FORCE_GLIBC
+#include <features.h>
+
 #include <stdio.h>
+#include <unistd.h>
 #include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpc/clnt.h>
+#include <sys/poll.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <netdb.h>
 #include <errno.h>
 #include <rpc/pmap_clnt.h>
-#include <unistd.h>
+#include <net/if.h>
+#ifdef USE_IN_LIBIO
+# include <wchar.h>
+#endif
 
-extern int errno;
+#ifdef IP_RECVERR
+#include "errqueue.h"
+#include <sys/uio.h>
+#endif
+
+extern bool_t xdr_opaque_auth (XDR *, struct opaque_auth *);
+extern u_long _create_xid (void);
 
 /*
  * UDP bases client side rpc operations
  */
-static enum clnt_stat clntudp_call();
-static void clntudp_abort();
-static void clntudp_geterr();
-static bool_t clntudp_freeres();
-static bool_t clntudp_control();
-static void clntudp_destroy();
-
-static struct clnt_ops udp_ops = {
-	clntudp_call,
-	clntudp_abort,
-	clntudp_geterr,
-	clntudp_freeres,
-	clntudp_destroy,
-	clntudp_control
+static enum clnt_stat clntudp_call (CLIENT *, u_long, xdrproc_t, caddr_t,
+				    xdrproc_t, caddr_t, struct timeval);
+static void clntudp_abort (void);
+static void clntudp_geterr (CLIENT *, struct rpc_err *);
+static bool_t clntudp_freeres (CLIENT *, xdrproc_t, caddr_t);
+static bool_t clntudp_control (CLIENT *, int, char *);
+static void clntudp_destroy (CLIENT *);
+
+static struct clnt_ops udp_ops =
+{
+  clntudp_call,
+  clntudp_abort,
+  clntudp_geterr,
+  clntudp_freeres,
+  clntudp_destroy,
+  clntudp_control
 };
 
-/* 
+/*
  * Private data kept per client handle
  */
-struct cu_data {
-	int cu_sock;
-	bool_t cu_closeit;
-	struct sockaddr_in cu_raddr;
-	int cu_rlen;
-	struct timeval cu_wait;
-	struct timeval cu_total;
-	struct rpc_err cu_error;
-	XDR cu_outxdrs;
-	u_int cu_xdrpos;
-	u_int cu_sendsz;
-	char *cu_outbuf;
-	u_int cu_recvsz;
-	char cu_inbuf[1];
-};
+struct cu_data
+  {
+    int cu_sock;
+    bool_t cu_closeit;
+    struct sockaddr_in cu_raddr;
+    int cu_rlen;
+    struct timeval cu_wait;
+    struct timeval cu_total;
+    struct rpc_err cu_error;
+    XDR cu_outxdrs;
+    u_int cu_xdrpos;
+    u_int cu_sendsz;
+    char *cu_outbuf;
+    u_int cu_recvsz;
+    char cu_inbuf[1];
+  };
 
 /*
  * Create a UDP based client handle.
@@ -95,344 +115,495 @@ struct cu_data {
  *     Caller may wish to set this something more useful.
  *
  * wait is the amount of time used between retransmitting a call if
- * no response has been heard;  retransmition occurs until the actual
+ * no response has been heard; retransmission occurs until the actual
  * rpc call times out.
  *
  * sendsz and recvsz are the maximum allowable packet sizes that can be
  * sent and received.
  */
-CLIENT *clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz,
-						  recvsz)
-struct sockaddr_in *raddr;
-u_long program;
-u_long version;
-struct timeval wait;
-register int *sockp;
-u_int sendsz;
-u_int recvsz;
+CLIENT *
+clntudp_bufcreate (struct sockaddr_in *raddr, u_long program, u_long version,
+		   struct timeval wait, int *sockp, u_int sendsz,
+		   u_int recvsz)
 {
-	CLIENT *cl;
-	register struct cu_data *cu;
-	struct timeval now;
-	struct rpc_msg call_msg;
-
-	cu = NULL;					/* in case of fooy */
-	cl = (CLIENT *) mem_alloc(sizeof(CLIENT));
-	if (cl == NULL) {
-		(void) fprintf(stderr, "clntudp_create: out of memory\n");
-		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
-		rpc_createerr.cf_error.re_errno = errno;
-		goto fooy;
+  CLIENT *cl;
+  struct cu_data *cu = NULL;
+  struct rpc_msg call_msg;
+
+  cl = (CLIENT *) mem_alloc (sizeof (CLIENT));
+  sendsz = ((sendsz + 3) / 4) * 4;
+  recvsz = ((recvsz + 3) / 4) * 4;
+  cu = (struct cu_data *) mem_alloc (sizeof (*cu) + sendsz + recvsz);
+  if (cl == NULL || cu == NULL)
+    {
+      struct rpc_createerr *ce = &get_rpc_createerr ();
+#ifdef USE_IN_LIBIO
+      if (_IO_fwide (stderr, 0) > 0)
+	(void) __fwprintf (stderr, L"%s",
+			   _("clntudp_create: out of memory\n"));
+      else
+#endif
+	(void) fputs (_("clntudp_create: out of memory\n"), stderr);
+      ce->cf_stat = RPC_SYSTEMERROR;
+      ce->cf_error.re_errno = ENOMEM;
+      goto fooy;
+    }
+  cu->cu_outbuf = &cu->cu_inbuf[recvsz];
+
+  if (raddr->sin_port == 0)
+    {
+      u_short port;
+      if ((port =
+	   pmap_getport (raddr, program, version, IPPROTO_UDP)) == 0)
+	{
+	  goto fooy;
 	}
-	sendsz = ((sendsz + 3) / 4) * 4;
-	recvsz = ((recvsz + 3) / 4) * 4;
-	cu = (struct cu_data *) mem_alloc(sizeof(*cu) + sendsz + recvsz);
-	if (cu == NULL) {
-		(void) fprintf(stderr, "clntudp_create: out of memory\n");
-		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
-		rpc_createerr.cf_error.re_errno = errno;
-		goto fooy;
+      raddr->sin_port = htons (port);
+    }
+  cl->cl_ops = &udp_ops;
+  cl->cl_private = (caddr_t) cu;
+  cu->cu_raddr = *raddr;
+  cu->cu_rlen = sizeof (cu->cu_raddr);
+  cu->cu_wait = wait;
+  cu->cu_total.tv_sec = -1;
+  cu->cu_total.tv_usec = -1;
+  cu->cu_sendsz = sendsz;
+  cu->cu_recvsz = recvsz;
+  call_msg.rm_xid = _create_xid ();
+  call_msg.rm_direction = CALL;
+  call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+  call_msg.rm_call.cb_prog = program;
+  call_msg.rm_call.cb_vers = version;
+  xdrmem_create (&(cu->cu_outxdrs), cu->cu_outbuf,
+		 sendsz, XDR_ENCODE);
+  if (!xdr_callhdr (&(cu->cu_outxdrs), &call_msg))
+    {
+      goto fooy;
+    }
+  cu->cu_xdrpos = XDR_GETPOS (&(cu->cu_outxdrs));
+  if (*sockp < 0)
+    {
+      int dontblock = 1;
+
+      *sockp = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+      if (*sockp < 0)
+	{
+	  struct rpc_createerr *ce = &get_rpc_createerr ();
+	  ce->cf_stat = RPC_SYSTEMERROR;
+	  ce->cf_error.re_errno = errno;
+	  goto fooy;
 	}
-	cu->cu_outbuf = &cu->cu_inbuf[recvsz];
-
-	(void) gettimeofday(&now, (struct timezone *) 0);
-	if (raddr->sin_port == 0) {
-		u_short port;
-
-		if ((port =
-			 pmap_getport(raddr, program, version, IPPROTO_UDP)) == 0) {
-			goto fooy;
-		}
-		raddr->sin_port = htons(port);
-	}
-	cl->cl_ops = &udp_ops;
-	cl->cl_private = (caddr_t) cu;
-	cu->cu_raddr = *raddr;
-	cu->cu_rlen = sizeof(cu->cu_raddr);
-	cu->cu_wait = wait;
-	cu->cu_total.tv_sec = -1;
-	cu->cu_total.tv_usec = -1;
-	cu->cu_sendsz = sendsz;
-	cu->cu_recvsz = recvsz;
-	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 = program;
-	call_msg.rm_call.cb_vers = version;
-	xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf, sendsz, XDR_ENCODE);
-	if (!xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) {
-		goto fooy;
-	}
-	cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
-	if (*sockp < 0) {
-		int dontblock = 1;
-
-		*sockp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-		if (*sockp < 0) {
-			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
-			rpc_createerr.cf_error.re_errno = errno;
-			goto fooy;
-		}
-		/* attempt to bind to prov port */
-		(void) bindresvport(*sockp, (struct sockaddr_in *) 0);
-		/* the sockets rpc controls are non-blocking */
-		(void) ioctl(*sockp, FIONBIO, (char *) &dontblock);
-		cu->cu_closeit = TRUE;
-	} else {
-		cu->cu_closeit = FALSE;
-	}
-	cu->cu_sock = *sockp;
-	cl->cl_auth = authnone_create();
-	return (cl);
-  fooy:
-	if (cu)
-		mem_free((caddr_t) cu, sizeof(*cu) + sendsz + recvsz);
-	if (cl)
-		mem_free((caddr_t) cl, sizeof(CLIENT));
-	return ((CLIENT *) NULL);
+      /* attempt to bind to prov port */
+      (void) bindresvport (*sockp, (struct sockaddr_in *) 0);
+      /* the sockets rpc controls are non-blocking */
+      (void) ioctl (*sockp, FIONBIO, (char *) &dontblock);
+#ifdef IP_RECVERR
+      {
+	int on = 1;
+	setsockopt(*sockp, SOL_IP, IP_RECVERR, &on, sizeof(on));
+      }
+#endif
+      cu->cu_closeit = TRUE;
+    }
+  else
+    {
+      cu->cu_closeit = FALSE;
+    }
+  cu->cu_sock = *sockp;
+  cl->cl_auth = authnone_create ();
+  return cl;
+fooy:
+  if (cu)
+    mem_free ((caddr_t) cu, sizeof (*cu) + sendsz + recvsz);
+  if (cl)
+    mem_free ((caddr_t) cl, sizeof (CLIENT));
+  return (CLIENT *) NULL;
 }
 
-CLIENT *clntudp_create(raddr, program, version, wait, sockp)
-struct sockaddr_in *raddr;
-u_long program;
-u_long version;
-struct timeval wait;
-register int *sockp;
+CLIENT *
+clntudp_create (raddr, program, version, wait, sockp)
+     struct sockaddr_in *raddr;
+     u_long program;
+     u_long version;
+     struct timeval wait;
+     int *sockp;
 {
 
-	return (clntudp_bufcreate(raddr, program, version, wait, sockp,
-							  UDPMSGSIZE, UDPMSGSIZE));
+  return clntudp_bufcreate (raddr, program, version, wait, sockp,
+			    UDPMSGSIZE, UDPMSGSIZE);
 }
 
-static enum clnt_stat
-clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
-register CLIENT *cl;			/* client handle */
-u_long proc;					/* procedure number */
-xdrproc_t xargs;				/* xdr routine for args */
-caddr_t argsp;					/* pointer to args */
-xdrproc_t xresults;				/* xdr routine for results */
-caddr_t resultsp;				/* pointer to results */
-struct timeval utimeout;		/* seconds to wait before giving up */
+static int
+is_network_up (int sock)
 {
-	register struct cu_data *cu = (struct cu_data *) cl->cl_private;
-	register XDR *xdrs;
-	register int outlen;
-	register int inlen;
-	int fromlen;
-
-#ifdef FD_SETSIZE
-	fd_set readfds;
-	fd_set mask;
-#else
-	int readfds;
-	register int mask;
-#endif							/* def FD_SETSIZE */
-	struct sockaddr_in from;
-	struct rpc_msg reply_msg;
-	XDR reply_xdrs;
-	struct timeval time_waited;
-	bool_t ok;
-	int nrefreshes = 2;			/* number of times to refresh cred */
-	struct timeval timeout;
-
-	if (cu->cu_total.tv_usec == -1) {
-		timeout = utimeout;		/* use supplied timeout */
-	} else {
-		timeout = cu->cu_total;	/* use default timeout */
-	}
-
-	time_waited.tv_sec = 0;
-	time_waited.tv_usec = 0;
-  call_again:
-	xdrs = &(cu->cu_outxdrs);
-	xdrs->x_op = XDR_ENCODE;
-	XDR_SETPOS(xdrs, cu->cu_xdrpos);
-	/*
-	 * the transaction is the first thing in the out buffer
-	 */
-	(*(u_short *) (cu->cu_outbuf))++;
-	if ((!XDR_PUTLONG(xdrs, (long *) &proc)) ||
-		(!AUTH_MARSHALL(cl->cl_auth, xdrs)) || (!(*xargs) (xdrs, argsp)))
-		return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
-	outlen = (int) XDR_GETPOS(xdrs);
-
-  send_again:
-	if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0,
-			   (struct sockaddr *) &(cu->cu_raddr), cu->cu_rlen)
-		!= outlen) {
-		cu->cu_error.re_errno = errno;
-		return (cu->cu_error.re_status = RPC_CANTSEND);
+  struct ifconf ifc;
+  char buf[UDPMSGSIZE];
+  struct ifreq ifreq, *ifr;
+  int n;
+
+  ifc.ifc_len = sizeof (buf);
+  ifc.ifc_buf = buf;
+  if (ioctl(sock, SIOCGIFCONF, (char *) &ifc) == 0)
+    {
+      ifr = ifc.ifc_req;
+      for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++)
+	{
+	  ifreq = *ifr;
+	  if (ioctl (sock, SIOCGIFFLAGS, (char *) &ifreq) < 0)
+	    break;
+
+	  if ((ifreq.ifr_flags & IFF_UP)
+	      && ifr->ifr_addr.sa_family == AF_INET)
+	    return 1;
 	}
+    }
+  return 0;
+}
 
-	/*
-	 * Hack to provide rpc-based message passing
-	 */
-	if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
-		return (cu->cu_error.re_status = RPC_TIMEDOUT);
+static enum clnt_stat
+clntudp_call (cl, proc, xargs, argsp, xresults, resultsp, utimeout)
+     CLIENT *cl;	/* client handle */
+     u_long proc;		/* procedure number */
+     xdrproc_t xargs;		/* xdr routine for args */
+     caddr_t argsp;		/* pointer to args */
+     xdrproc_t xresults;	/* xdr routine for results */
+     caddr_t resultsp;		/* pointer to results */
+     struct timeval utimeout;	/* seconds to wait before giving up */
+{
+  struct cu_data *cu = (struct cu_data *) cl->cl_private;
+  XDR *xdrs;
+  int outlen = 0;
+  int inlen;
+  socklen_t fromlen;
+  struct pollfd fd;
+  int milliseconds = (cu->cu_wait.tv_sec * 1000) +
+    (cu->cu_wait.tv_usec / 1000);
+  struct sockaddr_in from;
+  struct rpc_msg reply_msg;
+  XDR reply_xdrs;
+  struct timeval time_waited;
+  bool_t ok;
+  int nrefreshes = 2;		/* number of times to refresh cred */
+  struct timeval timeout;
+  int anyup;			/* any network interface up */
+
+  if (cu->cu_total.tv_usec == -1)
+    {
+      timeout = utimeout;	/* use supplied timeout */
+    }
+  else
+    {
+      timeout = cu->cu_total;	/* use default timeout */
+    }
+
+  time_waited.tv_sec = 0;
+  time_waited.tv_usec = 0;
+call_again:
+  xdrs = &(cu->cu_outxdrs);
+  if (xargs == NULL)
+    goto get_reply;
+  xdrs->x_op = XDR_ENCODE;
+  XDR_SETPOS (xdrs, cu->cu_xdrpos);
+  /*
+   * the transaction is the first thing in the out buffer
+   */
+  (*(uint32_t *) (cu->cu_outbuf))++;
+  if ((!XDR_PUTLONG (xdrs, (long *) &proc)) ||
+      (!AUTH_MARSHALL (cl->cl_auth, xdrs)) ||
+      (!(*xargs) (xdrs, argsp)))
+    return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
+  outlen = (int) XDR_GETPOS (xdrs);
+
+send_again:
+  if (sendto (cu->cu_sock, cu->cu_outbuf, outlen, 0,
+	      (struct sockaddr *) &(cu->cu_raddr), cu->cu_rlen)
+      != outlen)
+    {
+      cu->cu_error.re_errno = errno;
+      return (cu->cu_error.re_status = RPC_CANTSEND);
+    }
+
+  /*
+   * Hack to provide rpc-based message passing
+   */
+  if (timeout.tv_sec == 0 && timeout.tv_usec == 0)
+    {
+      return (cu->cu_error.re_status = RPC_TIMEDOUT);
+    }
+ get_reply:
+  /*
+   * sub-optimal code appears here because we have
+   * some clock time to spare while the packets are in flight.
+   * (We assume that this is actually only executed once.)
+   */
+  reply_msg.acpted_rply.ar_verf = _null_auth;
+  reply_msg.acpted_rply.ar_results.where = resultsp;
+  reply_msg.acpted_rply.ar_results.proc = xresults;
+  fd.fd = cu->cu_sock;
+  fd.events = POLLIN;
+  anyup = 0;
+  for (;;)
+    {
+      switch (poll (&fd, 1, milliseconds))
+	{
+
+	case 0:
+	  if (anyup == 0)
+	    {
+	      anyup = is_network_up (cu->cu_sock);
+	      if (!anyup)
+		return (cu->cu_error.re_status = RPC_CANTRECV);
+	    }
+
+	  time_waited.tv_sec += cu->cu_wait.tv_sec;
+	  time_waited.tv_usec += cu->cu_wait.tv_usec;
+	  while (time_waited.tv_usec >= 1000000)
+	    {
+	      time_waited.tv_sec++;
+	      time_waited.tv_usec -= 1000000;
+	    }
+	  if ((time_waited.tv_sec < timeout.tv_sec) ||
+	      ((time_waited.tv_sec == timeout.tv_sec) &&
+	       (time_waited.tv_usec < timeout.tv_usec)))
+	    goto send_again;
+	  return (cu->cu_error.re_status = RPC_TIMEDOUT);
+
+	  /*
+	   * buggy in other cases because time_waited is not being
+	   * updated.
+	   */
+	case -1:
+	  if (errno == EINTR)
+	    continue;
+	  cu->cu_error.re_errno = errno;
+	  return (cu->cu_error.re_status = RPC_CANTRECV);
 	}
-	/*
-	 * sub-optimal code appears here because we have
-	 * some clock time to spare while the packets are in flight.
-	 * (We assume that this is actually only executed once.)
-	 */
-	reply_msg.acpted_rply.ar_verf = _null_auth;
-	reply_msg.acpted_rply.ar_results.where = resultsp;
-	reply_msg.acpted_rply.ar_results.proc = xresults;
-#ifdef FD_SETSIZE
-	FD_ZERO(&mask);
-	FD_SET(cu->cu_sock, &mask);
-#else
-	mask = 1 << cu->cu_sock;
-#endif							/* def FD_SETSIZE */
-	for (;;) {
-		readfds = mask;
-		switch (select(_rpc_dtablesize(), &readfds, NULL,
-					   NULL, &(cu->cu_wait))) {
-
-		case 0:
-			time_waited.tv_sec += cu->cu_wait.tv_sec;
-			time_waited.tv_usec += cu->cu_wait.tv_usec;
-			while (time_waited.tv_usec >= 1000000) {
-				time_waited.tv_sec++;
-				time_waited.tv_usec -= 1000000;
-			}
-			if ((time_waited.tv_sec < timeout.tv_sec) ||
-				((time_waited.tv_sec == timeout.tv_sec) &&
-				 (time_waited.tv_usec < timeout.tv_usec)))
-				goto send_again;
-			return (cu->cu_error.re_status = RPC_TIMEDOUT);
-
-			/*
-			 * buggy in other cases because time_waited is not being
-			 * updated.
-			 */
-		case -1:
-			if (errno == EINTR)
-				continue;
-			cu->cu_error.re_errno = errno;
-			return (cu->cu_error.re_status = RPC_CANTRECV);
+#ifdef IP_RECVERR
+      if (fd.revents & POLLERR)
+	{
+	  struct msghdr msg;
+	  struct cmsghdr *cmsg;
+	  struct sock_extended_err *e;
+	  struct sockaddr_in err_addr;
+	  struct iovec iov;
+	  char *cbuf = (char *) alloca (outlen + 256);
+	  int ret;
+
+	  iov.iov_base = cbuf + 256;
+	  iov.iov_len = outlen;
+	  msg.msg_name = (void *) &err_addr;
+	  msg.msg_namelen = sizeof (err_addr);
+	  msg.msg_iov = &iov;
+	  msg.msg_iovlen = 1;
+	  msg.msg_flags = 0;
+	  msg.msg_control = cbuf;
+	  msg.msg_controllen = 256;
+	  ret = recvmsg (cu->cu_sock, &msg, MSG_ERRQUEUE);
+	  if (ret >= 0
+	      && memcmp (cbuf + 256, cu->cu_outbuf, ret) == 0
+	      && (msg.msg_flags & MSG_ERRQUEUE)
+	      && ((msg.msg_namelen == 0
+		   && ret >= 12)
+		  || (msg.msg_namelen == sizeof (err_addr)
+		      && err_addr.sin_family == AF_INET
+		      && memcmp (&err_addr.sin_addr, &cu->cu_raddr.sin_addr,
+				 sizeof (err_addr.sin_addr)) == 0
+		      && err_addr.sin_port == cu->cu_raddr.sin_port)))
+	    for (cmsg = CMSG_FIRSTHDR (&msg); cmsg;
+		 cmsg = CMSG_NXTHDR (&msg, cmsg))
+	      if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR)
+		{
+		  e = (struct sock_extended_err *) CMSG_DATA(cmsg);
+		  cu->cu_error.re_errno = e->ee_errno;
+		  return (cu->cu_error.re_status = RPC_CANTRECV);
 		}
-		do {
-			fromlen = sizeof(struct sockaddr);
-
-			inlen = recvfrom(cu->cu_sock, cu->cu_inbuf,
-							 (int) cu->cu_recvsz, 0,
-							 (struct sockaddr *) &from, &fromlen);
-		} while (inlen < 0 && errno == EINTR);
-		if (inlen < 0) {
-			if (errno == EWOULDBLOCK)
-				continue;
-			cu->cu_error.re_errno = errno;
-			return (cu->cu_error.re_status = RPC_CANTRECV);
-		}
-		if (inlen < sizeof(u_long))
-			continue;
-		/* see if reply transaction id matches sent id */
-		if (*((u_long *) (cu->cu_inbuf)) != *((u_long *) (cu->cu_outbuf)))
-			continue;
-		/* we now assume we have the proper reply */
-		break;
 	}
-
-	/*
-	 * now decode and validate the response
-	 */
-	xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int) inlen, XDR_DECODE);
-	ok = xdr_replymsg(&reply_xdrs, &reply_msg);
-	/* XDR_DESTROY(&reply_xdrs);  save a few cycles on noop destroy */
-	if (ok) {
-		_seterr_reply(&reply_msg, &(cu->cu_error));
-		if (cu->cu_error.re_status == RPC_SUCCESS) {
-			if (!AUTH_VALIDATE(cl->cl_auth,
-							   &reply_msg.acpted_rply.ar_verf)) {
-				cu->cu_error.re_status = RPC_AUTHERROR;
-				cu->cu_error.re_why = AUTH_INVALIDRESP;
-			}
-			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 (nrefreshes > 0 && AUTH_REFRESH(cl->cl_auth)) {
-				nrefreshes--;
-				goto call_again;
-			}
-		}						/* end of unsuccessful completion */
-	} /* end of valid reply message */
-	else {
-		cu->cu_error.re_status = RPC_CANTDECODERES;
+#endif
+      do
+	{
+	  fromlen = sizeof (struct sockaddr);
+	  inlen = recvfrom (cu->cu_sock, cu->cu_inbuf,
+			    (int) cu->cu_recvsz, 0,
+			    (struct sockaddr *) &from, &fromlen);
 	}
-	return (cu->cu_error.re_status);
+      while (inlen < 0 && errno == EINTR);
+      if (inlen < 0)
+	{
+	  if (errno == EWOULDBLOCK)
+	    continue;
+	  cu->cu_error.re_errno = errno;
+	  return (cu->cu_error.re_status = RPC_CANTRECV);
+	}
+      if (inlen < 4)
+	continue;
+
+      /* see if reply transaction id matches sent id.
+        Don't do this if we only wait for a replay */
+      if (xargs != NULL
+	  && (*((u_int32_t *) (cu->cu_inbuf))
+	      != *((u_int32_t *) (cu->cu_outbuf))))
+	continue;
+      /* we now assume we have the proper reply */
+      break;
+    }
+
+  /*
+   * now decode and validate the response
+   */
+  xdrmem_create (&reply_xdrs, cu->cu_inbuf, (u_int) inlen, XDR_DECODE);
+  ok = xdr_replymsg (&reply_xdrs, &reply_msg);
+  /* XDR_DESTROY(&reply_xdrs);  save a few cycles on noop destroy */
+  if (ok)
+    {
+      _seterr_reply (&reply_msg, &(cu->cu_error));
+      if (cu->cu_error.re_status == RPC_SUCCESS)
+	{
+	  if (!AUTH_VALIDATE (cl->cl_auth,
+			      &reply_msg.acpted_rply.ar_verf))
+	    {
+	      cu->cu_error.re_status = RPC_AUTHERROR;
+	      cu->cu_error.re_why = AUTH_INVALIDRESP;
+	    }
+	  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 (nrefreshes > 0 && AUTH_REFRESH (cl->cl_auth))
+	    {
+	      nrefreshes--;
+	      goto call_again;
+	    }
+	}			/* end of unsuccessful completion */
+    }				/* end of valid reply message */
+  else
+    {
+      cu->cu_error.re_status = RPC_CANTDECODERES;
+    }
+  return cu->cu_error.re_status;
 }
 
-static void clntudp_geterr(cl, errp)
-CLIENT *cl;
-struct rpc_err *errp;
+static void
+clntudp_geterr (CLIENT *cl, struct rpc_err *errp)
 {
-	register struct cu_data *cu = (struct cu_data *) cl->cl_private;
+  struct cu_data *cu = (struct cu_data *) cl->cl_private;
 
-	*errp = cu->cu_error;
+  *errp = cu->cu_error;
 }
 
 
-static bool_t clntudp_freeres(cl, xdr_res, res_ptr)
-CLIENT *cl;
-xdrproc_t xdr_res;
-caddr_t res_ptr;
+static bool_t
+clntudp_freeres (CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr)
 {
-	register struct cu_data *cu = (struct cu_data *) cl->cl_private;
-	register XDR *xdrs = &(cu->cu_outxdrs);
+  struct cu_data *cu = (struct cu_data *) cl->cl_private;
+  XDR *xdrs = &(cu->cu_outxdrs);
 
-	xdrs->x_op = XDR_FREE;
-	return ((*xdr_res) (xdrs, res_ptr));
+  xdrs->x_op = XDR_FREE;
+  return (*xdr_res) (xdrs, res_ptr);
 }
 
-static void clntudp_abort( /*h */ )
-	/*CLIENT *h; */
+static void
+clntudp_abort (void)
 {
 }
 
-static bool_t clntudp_control(cl, request, info)
-CLIENT *cl;
-int request;
-char *info;
+static bool_t
+clntudp_control (CLIENT *cl, int request, char *info)
 {
-	register struct cu_data *cu = (struct cu_data *) cl->cl_private;
-
-	switch (request) {
-	case CLSET_TIMEOUT:
-		cu->cu_total = *(struct timeval *) info;
-		break;
-	case CLGET_TIMEOUT:
-		*(struct timeval *) info = cu->cu_total;
-		break;
-	case CLSET_RETRY_TIMEOUT:
-		cu->cu_wait = *(struct timeval *) info;
-		break;
-	case CLGET_RETRY_TIMEOUT:
-		*(struct timeval *) info = cu->cu_wait;
-		break;
-	case CLGET_SERVER_ADDR:
-		*(struct sockaddr_in *) info = cu->cu_raddr;
-		break;
-	default:
-		return (FALSE);
-	}
-	return (TRUE);
+  struct cu_data *cu = (struct cu_data *) cl->cl_private;
+
+  switch (request)
+    {
+    case CLSET_FD_CLOSE:
+      cu->cu_closeit = TRUE;
+      break;
+    case CLSET_FD_NCLOSE:
+      cu->cu_closeit = FALSE;
+      break;
+    case CLSET_TIMEOUT:
+      cu->cu_total = *(struct timeval *) info;
+      break;
+    case CLGET_TIMEOUT:
+      *(struct timeval *) info = cu->cu_total;
+      break;
+    case CLSET_RETRY_TIMEOUT:
+      cu->cu_wait = *(struct timeval *) info;
+      break;
+    case CLGET_RETRY_TIMEOUT:
+      *(struct timeval *) info = cu->cu_wait;
+      break;
+    case CLGET_SERVER_ADDR:
+      *(struct sockaddr_in *) info = cu->cu_raddr;
+      break;
+    case CLGET_FD:
+      *(int *)info = cu->cu_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 *)cu->cu_outbuf);
+      break;
+    case CLSET_XID:
+      /* This will set the xid of the NEXT call */
+      *(u_long *)cu->cu_outbuf =  htonl(*(u_long *)info - 1);
+      /* decrement by 1 as clntudp_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 *)(cu->cu_outbuf +
+					  4 * BYTES_PER_XDR_UNIT));
+      break;
+    case CLSET_VERS:
+      *(u_long *)(cu->cu_outbuf + 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 *)(cu->cu_outbuf +
+					  3 * BYTES_PER_XDR_UNIT));
+      break;
+    case CLSET_PROG:
+      *(u_long *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT)
+	= htonl(*(u_long *)info);
+      break;
+    /* The following are only possible with TI-RPC */
+    case CLGET_SVC_ADDR:
+    case CLSET_SVC_ADDR:
+    case CLSET_PUSH_TIMOD:
+    case CLSET_POP_TIMOD:
+    default:
+      return FALSE;
+    }
+  return TRUE;
 }
 
-static void clntudp_destroy(cl)
-CLIENT *cl;
+static void
+clntudp_destroy (CLIENT *cl)
 {
-	register struct cu_data *cu = (struct cu_data *) cl->cl_private;
-
-	if (cu->cu_closeit) {
-		(void) close(cu->cu_sock);
-	}
-	XDR_DESTROY(&(cu->cu_outxdrs));
-	mem_free((caddr_t) cu, (sizeof(*cu) + cu->cu_sendsz + cu->cu_recvsz));
-	mem_free((caddr_t) cl, sizeof(CLIENT));
+  struct cu_data *cu = (struct cu_data *) cl->cl_private;
+
+  if (cu->cu_closeit)
+    {
+      (void) close (cu->cu_sock);
+    }
+  XDR_DESTROY (&(cu->cu_outxdrs));
+  mem_free ((caddr_t) cu, (sizeof (*cu) + cu->cu_sendsz + cu->cu_recvsz));
+  mem_free ((caddr_t) cl, sizeof (CLIENT));
 }

+ 606 - 0
libc/inet/rpc/clnt_unix.c

@@ -0,0 +1,606 @@
+/*
+ * 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.
+ */
+
+#define __FORCE_GLIBC
+#include <features.h>
+
+#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>
+#ifdef USE_IN_LIBIO
+# include <wchar.h>
+#endif
+
+extern u_long _create_xid (void);
+
+#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 rpc_msg call_msg;
+  int len;
+
+  h = (CLIENT *) mem_alloc (sizeof (*h));
+  if (h == NULL || ct == NULL)
+    {
+      struct rpc_createerr *ce = &get_rpc_createerr ();
+#ifdef USE_IN_LIBIO
+      if (_IO_fwide (stderr, 0) > 0)
+	(void) __fwprintf (stderr, L"%s",
+			   _("clntunix_create: out of memory\n"));
+      else
+#endif
+	(void) fputs (_("clntunix_create: out of memory\n"), stderr);
+      ce->cf_stat = RPC_SYSTEMERROR;
+      ce->cf_error.re_errno = ENOMEM;
+      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)
+	{
+	  struct rpc_createerr *ce = &get_rpc_createerr ();
+	  ce->cf_stat = RPC_SYSTEMERROR;
+	  ce->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
+   */
+  call_msg.rm_xid = _create_xid ();
+  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 && ct->ct_wait.tv_sec == 0
+     && ct->ct_wait.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 (ct->ct_wait.tv_sec == 0 && ct->ct_wait.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));
+}
+
+static int
+__msgread (int sock, void *data, size_t cnt)
+{
+  struct iovec iov;
+  struct msghdr msg;
+#ifdef SCM_CREDENTIALS
+  static char cm[CMSG_SPACE(sizeof (struct ucred))];
+#endif
+  int len;
+
+  iov.iov_base = data;
+  iov.iov_len = cnt;
+
+  msg.msg_iov = &iov;
+  msg.msg_iovlen = 1;
+  msg.msg_name = NULL;
+  msg.msg_namelen = 0;
+#ifdef SCM_CREDENTIALS
+  msg.msg_control = (caddr_t) &cm;
+  msg.msg_controllen = CMSG_SPACE(sizeof (struct ucred));
+#endif
+  msg.msg_flags = 0;
+
+#ifdef SO_PASSCRED
+  {
+    int on = 1;
+    if (setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)))
+      return -1;
+  }
+#endif
+
+ restart:
+  len = recvmsg (sock, &msg, 0);
+  if (len >= 0)
+    {
+      if (msg.msg_flags & MSG_CTRUNC || len == 0)
+	return 0;
+      else
+	return len;
+    }
+  if (errno == EINTR)
+    goto restart;
+  return -1;
+}
+
+static int
+__msgwrite (int sock, void *data, size_t cnt)
+{
+#ifndef SCM_CREDENTIALS
+  /* We cannot implement this reliably.  */
+  __set_errno (ENOSYS);
+  return -1;
+#else
+  struct iovec iov;
+  struct msghdr msg;
+  struct cmsghdr *cmsg = alloca (CMSG_SPACE(sizeof (struct ucred)));
+  struct ucred cred;
+  int len;
+
+  /* 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. */
+  cred.pid = getpid ();
+  cred.uid = geteuid ();
+  cred.gid = getegid ();
+
+  memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred));
+  cmsg->cmsg_level = SOL_SOCKET;
+  cmsg->cmsg_type = SCM_CREDENTIALS;
+  cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred);
+
+  iov.iov_base = data;
+  iov.iov_len = cnt;
+
+  msg.msg_iov = &iov;
+  msg.msg_iovlen = 1;
+  msg.msg_name = NULL;
+  msg.msg_namelen = 0;
+  msg.msg_control = cmsg;
+  msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
+  msg.msg_flags = 0;
+
+ restart:
+  len = sendmsg (sock, &msg, 0);
+  if (len >= 0)
+    return len;
+  if (errno == EINTR)
+    goto restart;
+  return -1;
+
+#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;
+}

+ 64 - 0
libc/inet/rpc/create_xid.c

@@ -0,0 +1,64 @@
+/* Copyright (c) 1998, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1998.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#define __FORCE_GLIBC
+#include <features.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <rpc/rpc.h>
+
+/* The RPC code is not threadsafe, but new code should be threadsafe. */
+
+#ifdef _RPC_THREAD_SAFE_ //__UCLIBC_HAS_THREADS__
+#include <pthread.h>
+static pthread_mutex_t createxid_lock = PTHREAD_MUTEX_INITIALIZER;
+# define LOCK	pthread_mutex_lock(&createxid_lock)
+# define UNLOCK	pthread_mutex_unlock(&createxid_lock);
+#else
+# define LOCK
+# define UNLOCK
+#endif
+
+static int is_initialized;
+static struct drand48_data __rpc_lrand48_data;
+
+unsigned long
+_create_xid (void)
+{
+  unsigned long res;
+
+  LOCK;
+
+  if (!is_initialized)
+    {
+      struct timeval now;
+
+      gettimeofday (&now, (struct timezone *) 0);
+      srand48_r (now.tv_sec ^ now.tv_usec, &__rpc_lrand48_data);
+      is_initialized = 1;
+    }
+
+  lrand48_r (&__rpc_lrand48_data, &res);
+
+  UNLOCK;
+
+  return res;
+}

+ 46 - 0
libc/inet/rpc/errqueue.h

@@ -0,0 +1,46 @@
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* Linux version.  */
+
+#ifndef _BITS_ERRQUEUE_H
+#define _BITS_ERRQUEUE_H  1
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+struct sock_extended_err
+  {
+    u_int32_t ee_errno;
+    u_int8_t ee_origin;
+    u_int8_t ee_type;
+    u_int8_t ee_code;
+    u_int8_t ee_pad;
+    u_int32_t ee_info;
+    u_int32_t ee_data;
+  };
+
+#define SO_EE_ORIGIN_NONE  0
+#define SO_EE_ORIGIN_LOCAL 1
+#define SO_EE_ORIGIN_ICMP  2
+#define SO_EE_ORIGIN_ICMP6 3
+
+#define SO_EE_OFFENDER(see)	\
+  ((struct sockaddr *)(((struct sock_extended_err)(see))+1))
+
+#endif /* bits/errqueue.h */

+ 63 - 64
libc/inet/rpc/get_myaddress.c

@@ -1,4 +1,4 @@
-/* @(#)get_myaddress.c	2.1 88/07/29 4.0 RPCSRC */
+/* @(#)get_myaddress.c 2.1 88/07/29 4.0 RPCSRC */
 /*
  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  * unrestricted use provided that this legend is included on all tape
@@ -6,29 +6,30 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)get_myaddress.c 1.4 87/08/11 Copyr 1984 Sun Micro";
+#endif
 
 /*
  * get_myaddress.c
@@ -38,72 +39,70 @@
  */
 
 #include <rpc/types.h>
+#include <rpc/clnt.h>
 #include <rpc/pmap_prot.h>
 #include <sys/socket.h>
 #include <stdio.h>
-//#include <net/if.h>
+#include <unistd.h>
+#include <net/if.h>
 #include <sys/ioctl.h>
-#include <arpa/inet.h>
+/* Order of following two #includes reversed by roland@gnu */
 #include <netinet/in.h>
-#include <rpc/clnt.h>
-#include <unistd.h>
-
-#ifdef __linux__
-/* DO use gethostbyname because it's portable */
-#include <netdb.h>
-void get_myaddress(addr)
-struct sockaddr_in *addr;
-{
-	char localhost[256 + 1];
-	struct hostent *hp;
+#include <arpa/inet.h>
 
-	gethostname(localhost, 256);
-	if ((hp = gethostbyname(localhost)) == NULL) {
-		perror("get_myaddress: gethostbyname");
-		exit(1);
-	}
-	addr->sin_family = AF_INET;
-	bcopy((char *) hp->h_addr, (char *) &addr->sin_addr, hp->h_length);
-	addr->sin_port = htons(PMAPPORT);
-}
-#else
-/* 
+/*
  * don't use gethostbyname, which would invoke yellow pages
+ *
+ * Avoid loopback interfaces.  We return information from a loopback
+ * interface only if there are no other possible interfaces.
  */
-void get_myaddress(addr)
-struct sockaddr_in *addr;
+void
+get_myaddress (struct sockaddr_in *addr)
 {
-	int s;
-	char buf[BUFSIZ];
-	struct ifconf ifc;
-	struct ifreq ifreq, *ifr;
-	int len;
+  int s;
+  char buf[BUFSIZ];
+  struct ifconf ifc;
+  struct ifreq ifreq, *ifr;
+  int len, loopback = 0;
 
-	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-		perror("get_myaddress: socket");
-		exit(1);
-	}
-	ifc.ifc_len = sizeof(buf);
-	ifc.ifc_buf = buf;
-	if (ioctl(s, SIOCGIFCONF, (char *) &ifc) < 0) {
-		perror("get_myaddress: ioctl (get interface configuration)");
-		exit(1);
+  if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
+    {
+      perror ("get_myaddress: socket");
+      exit (1);
+    }
+  ifc.ifc_len = sizeof (buf);
+  ifc.ifc_buf = buf;
+  if (ioctl (s, SIOCGIFCONF, (char *) &ifc) < 0)
+    {
+      perror (_("get_myaddress: ioctl (get interface configuration)"));
+      exit (1);
+    }
+
+ again:
+  ifr = ifc.ifc_req;
+  for (len = ifc.ifc_len; len; len -= sizeof ifreq)
+    {
+      ifreq = *ifr;
+      if (ioctl (s, SIOCGIFFLAGS, (char *) &ifreq) < 0)
+	{
+          perror ("get_myaddress: ioctl");
+          exit (1);
 	}
-	ifr = ifc.ifc_req;
-	for (len = ifc.ifc_len; len; len -= sizeof ifreq) {
-		ifreq = *ifr;
-		if (ioctl(s, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
-			perror("get_myaddress: ioctl");
-			exit(1);
-		}
-		if ((ifreq.ifr_flags & IFF_UP) &&
-			ifr->ifr_addr.sa_family == AF_INET) {
-			*addr = *((struct sockaddr_in *) &ifr->ifr_addr);
-			addr->sin_port = htons(PMAPPORT);
-			break;
-		}
-		ifr++;
+      if ((ifreq.ifr_flags & IFF_UP) && (ifr->ifr_addr.sa_family == AF_INET)
+	  && (!(ifreq.ifr_flags & IFF_LOOPBACK) ||
+	      (loopback == 1 && (ifreq.ifr_flags & IFF_LOOPBACK))))
+	{
+	  *addr = *((struct sockaddr_in *) &ifr->ifr_addr);
+	  addr->sin_port = htons (PMAPPORT);
+	  close (s);
+	  return;
 	}
-	(void) close(s);
+      ifr++;
+    }
+  if (loopback == 0)
+    {
+      loopback = 1;
+      goto again;
+    }
+  close (s);
 }
-#endif

+ 41 - 19
libc/inet/rpc/getrpcport.c

@@ -1,6 +1,7 @@
 /* @(#)getrpcport.c	2.1 88/07/29 4.0 RPCSRC */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static  char sccsid[] = "@(#)getrpcport.c 1.3 87/08/11 SMI";
+#endif
 /*
  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  * unrestricted use provided that this legend is included on all tape
@@ -8,23 +9,23 @@
  * 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
@@ -34,22 +35,43 @@
  * Copyright (c) 1985 by Sun Microsystems, Inc.
  */
 
+#define __FORCE_GLIBC
+#include <features.h>
+
+#include <alloca.h>
+#include <errno.h>
 #include <stdio.h>
-#include <rpc/rpc.h>
 #include <netdb.h>
-#include <sys/socket.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpc/clnt.h>
 #include <rpc/pmap_clnt.h>
+#include <sys/socket.h>
 
-extern int getrpcport (const char * host, u_long prognum,
-			   u_long versnum, u_int proto)
+int
+getrpcport (const char *host, u_long prognum, u_long versnum, u_int proto)
 {
-	struct sockaddr_in addr;
-	struct hostent *hp;
+  struct sockaddr_in addr;
+  struct hostent hostbuf, *hp;
+  size_t buflen;
+  char *buffer;
+  int herr;
+
+  buflen = 1024;
+  buffer = alloca (buflen);
+  while (gethostbyname_r (host, &hostbuf, buffer, buflen, &hp, &herr) != 0
+	 || hp == NULL)
+    if (herr != NETDB_INTERNAL || errno != ERANGE)
+      return 0;
+    else
+      {
+	/* Enlarge the buffer.  */
+	buflen *= 2;
+	buffer = alloca (buflen);
+      }
 
-	if ((hp = gethostbyname(host)) == NULL)
-		return (0);
-	bcopy(hp->h_addr, (char *) &addr.sin_addr, hp->h_length);
-	addr.sin_family = AF_INET;
-	addr.sin_port = 0;
-	return (pmap_getport(&addr, prognum, versnum, proto));
+  memcpy ((char *) &addr.sin_addr, hp->h_addr, hp->h_length);
+  addr.sin_family = AF_INET;
+  addr.sin_port = 0;
+  return pmap_getport (&addr, prognum, versnum, proto);
 }

+ 123 - 66
libc/inet/rpc/pmap_clnt.c

@@ -1,4 +1,3 @@
-/* @(#)pmap_clnt.c	2.2 88/08/01 4.0 RPCSRC */
 /*
  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  * unrestricted use provided that this legend is included on all tape
@@ -6,111 +5,169 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
-
+/*
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
 /*
  * pmap_clnt.c
  * Client interface to pmap rpc service.
- *
- * Copyright (C) 1984, Sun Microsystems, Inc.
  */
 
+#define __FORCE_GLIBC
+#include <features.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 #include <rpc/rpc.h>
 #include <rpc/pmap_prot.h>
 #include <rpc/pmap_clnt.h>
-#include <unistd.h>
 
-static struct timeval timeout = { 5, 0 };
-static struct timeval tottimeout = { 60, 0 };
+/*
+ * Same as get_myaddress, but we try to use the loopback
+ * interface. portmap caches interfaces, and on DHCP clients,
+ * it could be that only loopback is started at this time.
+ */
+static bool_t
+__get_myaddress (struct sockaddr_in *addr)
+{
+  int s;
+  char buf[BUFSIZ];
+  struct ifconf ifc;
+  struct ifreq ifreq, *ifr;
+  int len, loopback = 1;
+
+  if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
+    {
+      perror ("__get_myaddress: socket");
+      exit (1);
+    }
+  ifc.ifc_len = sizeof (buf);
+  ifc.ifc_buf = buf;
+  if (ioctl (s, SIOCGIFCONF, (char *) &ifc) < 0)
+    {
+      perror (_("__get_myaddress: ioctl (get interface configuration)"));
+      exit (1);
+    }
+
+ again:
+  ifr = ifc.ifc_req;
+  for (len = ifc.ifc_len; len; len -= sizeof ifreq)
+    {
+      ifreq = *ifr;
+      if (ioctl (s, SIOCGIFFLAGS, (char *) &ifreq) < 0)
+        {
+          perror ("__get_myaddress: ioctl");
+          exit (1);
+        }
+      if ((ifreq.ifr_flags & IFF_UP) && (ifr->ifr_addr.sa_family == AF_INET)
+          && ((ifreq.ifr_flags & IFF_LOOPBACK) || (loopback == 0)))
+        {
+          *addr = *((struct sockaddr_in *) &ifr->ifr_addr);
+          addr->sin_port = htons (PMAPPORT);
+          close (s);
+          return TRUE;
+        }
+      ifr++;
+    }
+  if (loopback == 1)
+    {
+      loopback = 0;
+      goto again;
+    }
+  close (s);
+  return FALSE;
+}
 
-void clnt_perror();
 
+static const struct timeval timeout = {5, 0};
+static const struct timeval tottimeout = {60, 0};
 
 /*
  * Set a mapping between program,version and port.
  * Calls the pmap service remotely to do the mapping.
  */
-bool_t pmap_set(program, version, protocol, port)
-u_long program;
-u_long version;
-int protocol;
-u_short port;
+bool_t
+pmap_set (u_long program, u_long version, int protocol, u_short port)
 {
-	struct sockaddr_in myaddress;
-	int socket = -1;
-	register CLIENT *client;
-	struct pmap parms;
-	bool_t rslt;
+  struct sockaddr_in myaddress;
+  int socket = -1;
+  CLIENT *client;
+  struct pmap parms;
+  bool_t rslt;
 
-	get_myaddress(&myaddress);
-	client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS,
-							   timeout, &socket, RPCSMALLMSGSIZE,
-							   RPCSMALLMSGSIZE);
-	if (client == (CLIENT *) NULL)
-		return (FALSE);
-	parms.pm_prog = program;
-	parms.pm_vers = version;
-	parms.pm_prot = protocol;
-	parms.pm_port = port;
-	if (CLNT_CALL(client, PMAPPROC_SET, (xdrproc_t) xdr_pmap, (caddr_t) &parms,
-				  (xdrproc_t) xdr_bool, (caddr_t) &rslt,
-				  tottimeout) != RPC_SUCCESS) {
-		clnt_perror(client, "Cannot register service");
-		return (FALSE);
-	}
-	CLNT_DESTROY(client);
-	(void) close(socket);
-	return (rslt);
+  if (!__get_myaddress (&myaddress))
+    return FALSE;
+  client = clntudp_bufcreate (&myaddress, PMAPPROG, PMAPVERS,
+			timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+  if (client == (CLIENT *) NULL)
+    return (FALSE);
+  parms.pm_prog = program;
+  parms.pm_vers = version;
+  parms.pm_prot = protocol;
+  parms.pm_port = port;
+  if (CLNT_CALL (client, PMAPPROC_SET, (xdrproc_t)xdr_pmap, (caddr_t)&parms,
+		 (xdrproc_t)xdr_bool, (caddr_t)&rslt,
+		 tottimeout) != RPC_SUCCESS)
+    {
+      clnt_perror (client, _("Cannot register service"));
+      return FALSE;
+    }
+  CLNT_DESTROY (client);
+  /* (void)close(socket); CLNT_DESTROY closes it */
+  return rslt;
 }
 
 /*
  * Remove the mapping between program,version and port.
  * Calls the pmap service remotely to do the un-mapping.
  */
-bool_t pmap_unset(program, version)
-u_long program;
-u_long version;
+bool_t
+pmap_unset (u_long program, u_long version)
 {
-	struct sockaddr_in myaddress;
-	int socket = -1;
-	register CLIENT *client;
-	struct pmap parms;
-	bool_t rslt;
+  struct sockaddr_in myaddress;
+  int socket = -1;
+  CLIENT *client;
+  struct pmap parms;
+  bool_t rslt;
 
-	get_myaddress(&myaddress);
-	client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS,
-							   timeout, &socket, RPCSMALLMSGSIZE,
-							   RPCSMALLMSGSIZE);
-	if (client == (CLIENT *) NULL)
-		return (FALSE);
-	parms.pm_prog = program;
-	parms.pm_vers = version;
-	parms.pm_port = parms.pm_prot = 0;
-	CLNT_CALL(client, PMAPPROC_UNSET, (xdrproc_t) xdr_pmap, (caddr_t) &parms,
-			  (xdrproc_t) xdr_bool, (caddr_t) &rslt, tottimeout);
-	CLNT_DESTROY(client);
-	(void) close(socket);
-	return (rslt);
+  if (!__get_myaddress (&myaddress))
+    return FALSE;
+  client = clntudp_bufcreate (&myaddress, PMAPPROG, PMAPVERS,
+			timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+  if (client == (CLIENT *) NULL)
+    return FALSE;
+  parms.pm_prog = program;
+  parms.pm_vers = version;
+  parms.pm_port = parms.pm_prot = 0;
+  CLNT_CALL (client, PMAPPROC_UNSET, (xdrproc_t)xdr_pmap, (caddr_t)&parms,
+	     (xdrproc_t)xdr_bool, (caddr_t)&rslt, tottimeout);
+  CLNT_DESTROY (client);
+  /* (void)close(socket); CLNT_DESTROY already closed it */
+  return rslt;
 }

+ 31 - 34
libc/inet/rpc/pmap_getmaps.c

@@ -6,29 +6,30 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro";
+#endif
 
 /*
  * pmap_getmap.c
@@ -45,39 +46,35 @@
 #include <netdb.h>
 #include <stdio.h>
 #include <errno.h>
-//#include <net/if.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#define NAMELEN 255
-#define MAX_BROADCAST_SIZE 1400
-
-extern int errno;
 
 /*
  * Get a copy of the current port maps.
  * Calls the pmap service remotely to do get the maps.
  */
-struct pmaplist *pmap_getmaps(address)
-struct sockaddr_in *address;
+struct pmaplist *
+pmap_getmaps (struct sockaddr_in *address)
 {
-	struct pmaplist *head = (struct pmaplist *) NULL;
-	int socket = -1;
-	struct timeval minutetimeout;
-	register CLIENT *client;
+  struct pmaplist *head = (struct pmaplist *) NULL;
+  int socket = -1;
+  struct timeval minutetimeout;
+  CLIENT *client;
 
-	minutetimeout.tv_sec = 60;
-	minutetimeout.tv_usec = 0;
-	address->sin_port = htons(PMAPPORT);
-	client = clnttcp_create(address, PMAPPROG, PMAPVERS, &socket, 50, 500);
-	if (client != (CLIENT *) NULL) {
-		if (CLNT_CALL(client, PMAPPROC_DUMP, (xdrproc_t) xdr_void, NULL, 
-					  (xdrproc_t) xdr_pmaplist, (caddr_t) &head,
-					  minutetimeout) != RPC_SUCCESS) {
-			clnt_perror(client, "pmap_getmaps rpc problem");
-		}
-		CLNT_DESTROY(client);
+  minutetimeout.tv_sec = 60;
+  minutetimeout.tv_usec = 0;
+  address->sin_port = htons (PMAPPORT);
+  client = clnttcp_create (address, PMAPPROG,
+			   PMAPVERS, &socket, 50, 500);
+  if (client != (CLIENT *) NULL)
+    {
+      if (CLNT_CALL (client, PMAPPROC_DUMP, (xdrproc_t)xdr_void, NULL,
+		     (xdrproc_t)xdr_pmaplist, (caddr_t)&head,
+		     minutetimeout) != RPC_SUCCESS)
+	{
+	  clnt_perror (client, _("pmap_getmaps rpc problem"));
 	}
-	(void) close(socket);
-	address->sin_port = 0;
-	return (head);
+      CLNT_DESTROY (client);
+    }
+  /* (void)close(socket); CLNT_DESTROY already closed it */
+  address->sin_port = 0;
+  return head;
 }

+ 47 - 42
libc/inet/rpc/pmap_getport.c

@@ -6,29 +6,30 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro";
+#endif
 
 /*
  * pmap_getport.c
@@ -41,49 +42,53 @@
 #include <rpc/pmap_prot.h>
 #include <rpc/pmap_clnt.h>
 #include <sys/socket.h>
-#include <unistd.h>
-//#include <net/if.h>
 
-static struct timeval timeout = { 5, 0 };
-static struct timeval tottimeout = { 60, 0 };
+static const struct timeval timeout =
+{5, 0};
+static const struct timeval tottimeout =
+{60, 0};
 
 /*
  * Find the mapped port for program,version.
  * Calls the pmap service remotely to do the lookup.
  * Returns 0 if no map exists.
  */
-u_short pmap_getport(address, program, version, protocol)
-struct sockaddr_in *address;
-u_long program;
-u_long version;
-u_int protocol;
+u_short
+pmap_getport (address, program, version, protocol)
+     struct sockaddr_in *address;
+     u_long program;
+     u_long version;
+     u_int protocol;
 {
-	u_short port = 0;
-	int socket = -1;
-	register CLIENT *client;
-	struct pmap parms;
+  u_short port = 0;
+  int socket = -1;
+  CLIENT *client;
+  struct pmap parms;
 
-	address->sin_port = htons(PMAPPORT);
-	client = clntudp_bufcreate(address, PMAPPROG,
-							   PMAPVERS, timeout, &socket, RPCSMALLMSGSIZE,
-							   RPCSMALLMSGSIZE);
-	if (client != (CLIENT *) NULL) {
-		parms.pm_prog = program;
-		parms.pm_vers = version;
-		parms.pm_prot = protocol;
-		parms.pm_port = 0;		/* not needed or used */
-		if (CLNT_CALL(client, PMAPPROC_GETPORT,
-					  (xdrproc_t) xdr_pmap, (caddr_t) &parms,
-					  (xdrproc_t) xdr_u_short, (caddr_t) &port,
-					  tottimeout) != RPC_SUCCESS) {
-			rpc_createerr.cf_stat = RPC_PMAPFAILURE;
-			clnt_geterr(client, &rpc_createerr.cf_error);
-		} else if (port == 0) {
-			rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
-		}
-		CLNT_DESTROY(client);
+  address->sin_port = htons (PMAPPORT);
+  client = clntudp_bufcreate (address, PMAPPROG,
+	      PMAPVERS, timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+  if (client != (CLIENT *) NULL)
+    {
+      struct rpc_createerr *ce = &get_rpc_createerr ();
+      parms.pm_prog = program;
+      parms.pm_vers = version;
+      parms.pm_prot = protocol;
+      parms.pm_port = 0;	/* not needed or used */
+      if (CLNT_CALL (client, PMAPPROC_GETPORT, (xdrproc_t)xdr_pmap,
+		     (caddr_t)&parms, (xdrproc_t)xdr_u_short,
+		     (caddr_t)&port, tottimeout) != RPC_SUCCESS)
+	{
+	  ce->cf_stat = RPC_PMAPFAILURE;
+	  clnt_geterr (client, &ce->cf_error);
+	}
+      else if (port == 0)
+	{
+	  ce->cf_stat = RPC_PROGNOTREGISTERED;
 	}
-	(void) close(socket);
-	address->sin_port = 0;
-	return (port);
+      CLNT_DESTROY (client);
+    }
+  /* (void)close(socket); CLNT_DESTROY already closed it */
+  address->sin_port = 0;
+  return port;
 }

+ 17 - 15
libc/inet/rpc/pmap_prot.c

@@ -6,29 +6,30 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro";
+#endif
 
 /*
  * pmap_prot.c
@@ -42,14 +43,15 @@
 #include <rpc/pmap_prot.h>
 
 
-bool_t xdr_pmap(xdrs, regs)
-XDR *xdrs;
-struct pmap *regs;
+bool_t
+xdr_pmap (xdrs, regs)
+     XDR *xdrs;
+     struct pmap *regs;
 {
 
-	if (xdr_u_long(xdrs, &regs->pm_prog) &&
-		xdr_u_long(xdrs, &regs->pm_vers) &&
-		xdr_u_long(xdrs, &regs->pm_prot))
-			return (xdr_u_long(xdrs, &regs->pm_port));
-	return (FALSE);
+  if (xdr_u_long (xdrs, &regs->pm_prog) &&
+      xdr_u_long (xdrs, &regs->pm_vers) &&
+      xdr_u_long (xdrs, &regs->pm_prot))
+    return xdr_u_long (xdrs, &regs->pm_port);
+  return FALSE;
 }

+ 52 - 50
libc/inet/rpc/pmap_prot2.c

@@ -6,29 +6,30 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro";
+#endif
 
 /*
  * pmap_prot2.c
@@ -42,34 +43,34 @@
 #include <rpc/pmap_prot.h>
 
 
-/* 
+/*
  * What is going on with linked lists? (!)
  * First recall the link list declaration from pmap_prot.h:
  *
  * struct pmaplist {
- *	struct pmap pml_map;
- *	struct pmaplist *pml_map;
+ *      struct pmap pml_map;
+ *      struct pmaplist *pml_map;
  * };
  *
- * Compare that declaration with a corresponding xdr declaration that 
+ * Compare that declaration with a corresponding xdr declaration that
  * is (a) pointer-less, and (b) recursive:
  *
  * typedef union switch (bool_t) {
- * 
- *	case TRUE: struct {
- *		struct pmap;
- * 		pmaplist_t foo;
- *	};
  *
- *	case FALSE: struct {};
+ *      case TRUE: struct {
+ *              struct pmap;
+ *              pmaplist_t foo;
+ *      };
+ *
+ *      case FALSE: struct {};
  * } pmaplist_t;
  *
  * Notice that the xdr declaration has no nxt pointer while
  * the C declaration has no bool_t variable.  The bool_t can be
  * interpreted as ``more data follows me''; if FALSE then nothing
  * follows this bool_t; if TRUE then the bool_t is followed by
- * an actual struct pmap, and then (recursively) by the 
- * xdr union, pamplist_t.  
+ * an actual struct pmap, and then (recursively) by the
+ * xdr union, pamplist_t.
  *
  * This could be implemented via the xdr_union primitive, though this
  * would cause a one recursive call per element in the list.  Rather than do
@@ -80,37 +81,38 @@
  * the net, yet is the data that the pointer points to which is interesting;
  * this sounds like a job for xdr_reference!
  */
-bool_t xdr_pmaplist(xdrs, rp)
-register XDR *xdrs;
-register struct pmaplist **rp;
+bool_t
+xdr_pmaplist (xdrs, rp)
+     XDR *xdrs;
+     struct pmaplist **rp;
 {
-	/*
-	 * more_elements is pre-computed in case the direction is
-	 * XDR_ENCODE or XDR_FREE.  more_elements is overwritten by
-	 * xdr_bool when the direction is XDR_DECODE.
-	 */
-	bool_t more_elements;
-	register int freeing = (xdrs->x_op == XDR_FREE);
-	register struct pmaplist **next;
-#warning expect "next" might be unitialized
-
-	while (TRUE) {
-		more_elements = (bool_t) (*rp != NULL);
-		if (!xdr_bool(xdrs, &more_elements))
-			return (FALSE);
-		if (!more_elements)
-			return (TRUE);		/* we are done */
-		/*
-		 * the unfortunate side effect of non-recursion is that in
-		 * the case of freeing we must remember the next object
-		 * before we free the current object ...
-		 */
-		if (freeing)
-			next = &((*rp)->pml_next);
-		if (!xdr_reference(xdrs, (caddr_t *) rp,
-						   (u_int) sizeof(struct pmaplist), (xdrproc_t) xdr_pmap))
-			return (FALSE);
+  /*
+   * more_elements is pre-computed in case the direction is
+   * XDR_ENCODE or XDR_FREE.  more_elements is overwritten by
+   * xdr_bool when the direction is XDR_DECODE.
+   */
+  bool_t more_elements;
+  int freeing = (xdrs->x_op == XDR_FREE);
+  struct pmaplist **next = NULL;
 
-		rp = (freeing) ? next : &((*rp)->pml_next);
-	}
+  while (TRUE)
+    {
+      more_elements = (bool_t) (*rp != NULL);
+      if (!xdr_bool (xdrs, &more_elements))
+	return FALSE;
+      if (!more_elements)
+	return TRUE;		/* we are done */
+      /*
+       * the unfortunate side effect of non-recursion is that in
+       * the case of freeing we must remember the next object
+       * before we free the current object ...
+       */
+      if (freeing)
+	next = &((*rp)->pml_next);
+      if (!xdr_reference (xdrs, (caddr_t *) rp,
+			  (u_int) sizeof (struct pmaplist),
+			  (xdrproc_t) xdr_pmap))
+	  return FALSE;
+      rp = freeing ? next : &((*rp)->pml_next);
+    }
 }

+ 308 - 307
libc/inet/rpc/pmap_rmt.c

@@ -6,27 +6,30 @@
  * 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
  */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";
+#endif
 
 /*
  * pmap_rmt.c
@@ -38,25 +41,27 @@
 
 #define __FORCE_GLIBC
 #include <features.h>
+
 #include <unistd.h>
 #include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
 #include <rpc/rpc.h>
 #include <rpc/pmap_prot.h>
 #include <rpc/pmap_clnt.h>
 #include <rpc/pmap_rmt.h>
+#include <sys/poll.h>
 #include <sys/socket.h>
 #include <stdio.h>
 #include <errno.h>
-//#include <net/if.h>
+#undef	 _POSIX_SOURCE		/* Ultrix <sys/param.h> needs --roland@gnu */
+#include <sys/param.h>		/* Ultrix needs before net/if --roland@gnu */
+#include <net/if.h>
 #include <sys/ioctl.h>
 #include <arpa/inet.h>
 #define MAX_BROADCAST_SIZE 1400
 
-extern int errno;
-static struct timeval timeout = { 3, 0 };
+extern u_long _create_xid (void);
 
+static const struct timeval timeout = {3, 0};
 
 /*
  * pmapper remote-call-service interface.
@@ -64,44 +69,46 @@ static struct timeval timeout = { 3, 0 };
  * which will look up a service program in the port maps, and then
  * remotely call that routine with the given parameters.  This allows
  * programs to do a lookup and call in one step.
-*/
+ */
 enum clnt_stat
-pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout,
-			 port_ptr)
-struct sockaddr_in *addr;
-u_long prog, vers, proc;
-xdrproc_t xdrargs, xdrres;
-caddr_t argsp, resp;
-struct timeval tout;
-u_long *port_ptr;
+pmap_rmtcall (addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_ptr)
+     struct sockaddr_in *addr;
+     u_long prog, vers, proc;
+     xdrproc_t xdrargs, xdrres;
+     caddr_t argsp, resp;
+     struct timeval tout;
+     u_long *port_ptr;
 {
-	int socket = -1;
-	register CLIENT *client;
-	struct rmtcallargs a;
-	struct rmtcallres r;
-	enum clnt_stat stat;
+  int socket = -1;
+  CLIENT *client;
+  struct rmtcallargs a;
+  struct rmtcallres r;
+  enum clnt_stat stat;
 
-	addr->sin_port = htons(PMAPPORT);
-	client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &socket);
-	if (client != (CLIENT *) NULL) {
-		a.prog = prog;
-		a.vers = vers;
-		a.proc = proc;
-		a.args_ptr = argsp;
-		a.xdr_args = xdrargs;
-		r.port_ptr = port_ptr;
-		r.results_ptr = resp;
-		r.xdr_results = xdrres;
-		stat = CLNT_CALL(client, PMAPPROC_CALLIT,
-						 (xdrproc_t) xdr_rmtcall_args, (caddr_t) &a,
-						 (xdrproc_t) xdr_rmtcallres, (caddr_t) &r, tout);
-		CLNT_DESTROY(client);
-	} else {
-		stat = RPC_FAILED;
-	}
-	(void) close(socket);
-	addr->sin_port = 0;
-	return (stat);
+  addr->sin_port = htons (PMAPPORT);
+  client = clntudp_create (addr, PMAPPROG, PMAPVERS, timeout, &socket);
+  if (client != (CLIENT *) NULL)
+    {
+      a.prog = prog;
+      a.vers = vers;
+      a.proc = proc;
+      a.args_ptr = argsp;
+      a.xdr_args = xdrargs;
+      r.port_ptr = port_ptr;
+      r.results_ptr = resp;
+      r.xdr_results = xdrres;
+      stat = CLNT_CALL (client, PMAPPROC_CALLIT, (xdrproc_t)xdr_rmtcall_args,
+			(caddr_t)&a, (xdrproc_t)xdr_rmtcallres,
+			(caddr_t)&r, tout);
+      CLNT_DESTROY (client);
+    }
+  else
+    {
+      stat = RPC_FAILED;
+    }
+  /* (void)__close(socket); CLNT_DESTROY already closed it */
+  addr->sin_port = 0;
+  return stat;
 }
 
 
@@ -109,304 +116,298 @@ u_long *port_ptr;
  * XDR remote call arguments
  * written for XDR_ENCODE direction only
  */
-bool_t xdr_rmtcall_args(XDR *xdrs, struct rmtcallargs *cap)
+bool_t
+xdr_rmtcall_args (XDR *xdrs, struct rmtcallargs *cap)
 {
-	u_int lenposition, argposition, position;
+  u_int lenposition, argposition, position;
 
-	if (xdr_u_long(xdrs, &(cap->prog)) &&
-		xdr_u_long(xdrs, &(cap->vers)) && xdr_u_long(xdrs, &(cap->proc))) {
-		lenposition = XDR_GETPOS(xdrs);
-		if (!xdr_u_long(xdrs, &(cap->arglen)))
-			return (FALSE);
-		argposition = XDR_GETPOS(xdrs);
-		if (!(*(cap->xdr_args)) (xdrs, cap->args_ptr))
-			return (FALSE);
-		position = XDR_GETPOS(xdrs);
-		cap->arglen = (u_long) position - (u_long) argposition;
-		XDR_SETPOS(xdrs, lenposition);
-		if (!xdr_u_long(xdrs, &(cap->arglen)))
-			return (FALSE);
-		XDR_SETPOS(xdrs, position);
-		return (TRUE);
-	}
-	return (FALSE);
+  if (xdr_u_long (xdrs, &(cap->prog)) &&
+      xdr_u_long (xdrs, &(cap->vers)) &&
+      xdr_u_long (xdrs, &(cap->proc)))
+    {
+      lenposition = XDR_GETPOS (xdrs);
+      if (!xdr_u_long (xdrs, &(cap->arglen)))
+	return FALSE;
+      argposition = XDR_GETPOS (xdrs);
+      if (!(*(cap->xdr_args)) (xdrs, cap->args_ptr))
+	return FALSE;
+      position = XDR_GETPOS (xdrs);
+      cap->arglen = (u_long) position - (u_long) argposition;
+      XDR_SETPOS (xdrs, lenposition);
+      if (!xdr_u_long (xdrs, &(cap->arglen)))
+	return FALSE;
+      XDR_SETPOS (xdrs, position);
+      return TRUE;
+    }
+  return FALSE;
 }
 
 /*
  * XDR remote call results
  * written for XDR_DECODE direction only
  */
-bool_t xdr_rmtcallres(xdrs, crp)
-register XDR *xdrs;
-register struct rmtcallres *crp;
+bool_t
+xdr_rmtcallres (xdrs, crp)
+     XDR *xdrs;
+     struct rmtcallres *crp;
 {
-	caddr_t port_ptr;
+  caddr_t port_ptr;
 
-	port_ptr = (caddr_t) crp->port_ptr;
-	if (xdr_reference(xdrs, &port_ptr, sizeof(u_long),
-					  (xdrproc_t) xdr_u_long) && xdr_u_long(xdrs, &crp->resultslen)) {
-		crp->port_ptr = (u_long *) port_ptr;
-		return ((*(crp->xdr_results)) (xdrs, crp->results_ptr));
-	}
-	return (FALSE);
+  port_ptr = (caddr_t) crp->port_ptr;
+  if (xdr_reference (xdrs, &port_ptr, sizeof (u_long), (xdrproc_t) xdr_u_long)
+      && xdr_u_long (xdrs, &crp->resultslen))
+    {
+      crp->port_ptr = (u_long *) port_ptr;
+      return (*(crp->xdr_results)) (xdrs, crp->results_ptr);
+    }
+  return FALSE;
 }
 
-void get_myaddress( struct sockaddr_in *addr);
 
 /*
  * The following is kludged-up support for simple rpc broadcasts.
- * Someday a large, complicated system will replace these trivial 
+ * Someday a large, complicated system will replace these trivial
  * routines which only support udp/ip .
  */
 
-static int getbroadcastnets(addrs, sock, buf)
-struct in_addr *addrs;
-int sock;						/* any valid socket will do */
-char *buf;						/* why allocxate more when we can use existing... */
+static int
+internal_function
+getbroadcastnets (struct in_addr *addrs, int sock, char *buf)
+  /* int sock:  any valid socket will do */
+  /* char *buf:	why allocate more when we can use existing... */
 {
-#ifdef __linux__
-	struct sockaddr_in addr;
-
-	get_myaddress(&addr);
-#if 1
-	printf("%s(%d): no inet_makeaddr()\n", __FILE__, __LINE__);
-#else
-	addrs[0] = inet_makeaddr(inet_netof(addr.sin_addr), INADDR_ANY);
-#endif
-	return 1;
-#else
-	struct ifconf ifc;
-	struct ifreq ifreq, *ifr;
-	struct sockaddr_in *sin;
-	int n, i;
+  struct ifconf ifc;
+  struct ifreq ifreq, *ifr;
+  struct sockaddr_in *sin;
+  int n, i;
 
-	ifc.ifc_len = UDPMSGSIZE;
-	ifc.ifc_buf = buf;
-	if (ioctl(sock, SIOCGIFCONF, (char *) &ifc) < 0) {
-		perror("broadcast: ioctl (get interface configuration)");
-		return (0);
+  ifc.ifc_len = UDPMSGSIZE;
+  ifc.ifc_buf = buf;
+  if (ioctl (sock, SIOCGIFCONF, (char *) &ifc) < 0)
+    {
+      perror (_("broadcast: ioctl (get interface configuration)"));
+      return (0);
+    }
+  ifr = ifc.ifc_req;
+  for (i = 0, n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++)
+    {
+      ifreq = *ifr;
+      if (ioctl (sock, SIOCGIFFLAGS, (char *) &ifreq) < 0)
+	{
+	  perror (_("broadcast: ioctl (get interface flags)"));
+	  continue;
 	}
-	ifr = ifc.ifc_req;
-	for (i = 0, n = ifc.ifc_len / sizeof(struct ifreq); n > 0; n--, ifr++) {
-		ifreq = *ifr;
-		if (ioctl(sock, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
-			perror("broadcast: ioctl (get interface flags)");
-			continue;
-		}
-		if ((ifreq.ifr_flags & IFF_BROADCAST) &&
-			(ifreq.ifr_flags & IFF_UP) &&
-			ifr->ifr_addr.sa_family == AF_INET) {
-			sin = (struct sockaddr_in *) &ifr->ifr_addr;
-#ifdef SIOCGIFBRDADDR			/* 4.3BSD */
-			if (ioctl(sock, SIOCGIFBRDADDR, (char *) &ifreq) < 0) {
-#if 1
-				printf("%s(%d): no inet_makeaddr()\n", __FILE__, __LINE__);
-#else
-				addrs[i++] = inet_makeaddr(inet_netof
-										   (sin->sin_addr.s_addr),
-										   INADDR_ANY);
-#endif
-			} else {
-				addrs[i++] = ((struct sockaddr_in *)
-							  &ifreq.ifr_addr)->sin_addr;
-			}
-#else							/* 4.2 BSD */
-#if 1
-			printf("%s(%d): no inet_makeaddr()\n", __FILE__, __LINE__);
-#else
-			addrs[i++] = inet_makeaddr(inet_netof
-									   (sin->sin_addr.s_addr), INADDR_ANY);
-#endif
+      if ((ifreq.ifr_flags & IFF_BROADCAST) &&
+	  (ifreq.ifr_flags & IFF_UP) &&
+	  ifr->ifr_addr.sa_family == AF_INET)
+	{
+	  sin = (struct sockaddr_in *) &ifr->ifr_addr;
+#ifdef SIOCGIFBRDADDR		/* 4.3BSD */
+	  if (ioctl (sock, SIOCGIFBRDADDR, (char *) &ifreq) < 0)
+	    {
+	      addrs[i++] = inet_makeaddr (inet_netof
+	      /* Changed to pass struct instead of s_addr member
+	         by roland@gnu.  */
+					  (sin->sin_addr), INADDR_ANY);
+	    }
+	  else
+	    {
+	      addrs[i++] = ((struct sockaddr_in *)
+			    &ifreq.ifr_addr)->sin_addr;
+	    }
+#else /* 4.2 BSD */
+	  addrs[i++] = inet_makeaddr (inet_netof
+				      (sin->sin_addr.s_addr), INADDR_ANY);
 #endif
-		}
 	}
-	return (i);
-#endif
+    }
+  return i;
 }
 
-//typedef bool_t(*resultproc_t) ();
-//void _rpc_dtablesize(void );
-
 
 enum clnt_stat
-clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp,
-			   eachresult)
-u_long prog;					/* program number */
-u_long vers;					/* version number */
-u_long proc;					/* procedure number */
-xdrproc_t xargs;				/* xdr routine for args */
-caddr_t argsp;					/* pointer to args */
-xdrproc_t xresults;				/* xdr routine for results */
-caddr_t resultsp;				/* pointer to results */
-resultproc_t eachresult;		/* call with each result obtained */
+clnt_broadcast (prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
+     u_long prog;		/* program number */
+     u_long vers;		/* version number */
+     u_long proc;		/* procedure number */
+     xdrproc_t xargs;		/* xdr routine for args */
+     caddr_t argsp;		/* pointer to args */
+     xdrproc_t xresults;	/* xdr routine for results */
+     caddr_t resultsp;		/* pointer to results */
+     resultproc_t eachresult;	/* call with each result obtained */
 {
-	enum clnt_stat stat;
-	AUTH *unix_auth = authunix_create_default();
-	XDR xdr_stream;
-	register XDR *xdrs = &xdr_stream;
-	int outlen, inlen, fromlen, nets;
-	register int sock;
-	int on = 1;
-
-#ifdef FD_SETSIZE
-	fd_set mask;
-	fd_set readfds;
-#else
-	int readfds;
-	register int mask;
-#endif							/* def FD_SETSIZE */
-	register int i;
-	bool_t done = FALSE;
-	register u_long xid;
-	u_long port;
-	struct in_addr addrs[20];
-	struct sockaddr_in baddr, raddr;	/* broadcast and response addresses */
-	struct rmtcallargs a;
-	struct rmtcallres r;
-	struct rpc_msg msg;
-	struct timeval t;
-	char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE];
+  enum clnt_stat stat = RPC_FAILED;
+  AUTH *unix_auth = authunix_create_default ();
+  XDR xdr_stream;
+  XDR *xdrs = &xdr_stream;
+  struct timeval t;
+  int outlen, inlen, nets;
+  socklen_t fromlen;
+  int sock;
+  int on = 1;
+  struct pollfd fd;
+  int milliseconds;
+  int i;
+  bool_t done = FALSE;
+  u_long xid;
+  u_long port;
+  struct in_addr addrs[20];
+  struct sockaddr_in baddr, raddr;	/* broadcast and response addresses */
+  struct rmtcallargs a;
+  struct rmtcallres r;
+  struct rpc_msg msg;
+  char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE];
 
-	/*
-	 * initialization: create a socket, a broadcast address, and
-	 * preserialize the arguments into a send buffer.
-	 */
-	if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
-		perror("Cannot create socket for broadcast rpc");
-		stat = RPC_CANTSEND;
-		goto done_broad;
-	}
+  /*
+   * initialization: create a socket, a broadcast address, and
+   * preserialize the arguments into a send buffer.
+   */
+  if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+    {
+      perror (_("Cannot create socket for broadcast rpc"));
+      stat = RPC_CANTSEND;
+      goto done_broad;
+    }
 #ifdef SO_BROADCAST
-	if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) {
-		perror("Cannot set socket option SO_BROADCAST");
-		stat = RPC_CANTSEND;
-		goto done_broad;
+  if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0)
+    {
+      perror (_("Cannot set socket option SO_BROADCAST"));
+      stat = RPC_CANTSEND;
+      goto done_broad;
+    }
+#endif /* def SO_BROADCAST */
+  fd.fd = sock;
+  fd.events = POLLIN;
+  nets = getbroadcastnets (addrs, sock, inbuf);
+  bzero ((char *) &baddr, sizeof (baddr));
+  baddr.sin_family = AF_INET;
+  baddr.sin_port = htons (PMAPPORT);
+  baddr.sin_addr.s_addr = htonl (INADDR_ANY);
+/*      baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); */
+  msg.rm_xid = xid = _create_xid ();
+  t.tv_usec = 0;
+  msg.rm_direction = CALL;
+  msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+  msg.rm_call.cb_prog = PMAPPROG;
+  msg.rm_call.cb_vers = PMAPVERS;
+  msg.rm_call.cb_proc = PMAPPROC_CALLIT;
+  msg.rm_call.cb_cred = unix_auth->ah_cred;
+  msg.rm_call.cb_verf = unix_auth->ah_verf;
+  a.prog = prog;
+  a.vers = vers;
+  a.proc = proc;
+  a.xdr_args = xargs;
+  a.args_ptr = argsp;
+  r.port_ptr = &port;
+  r.xdr_results = xresults;
+  r.results_ptr = resultsp;
+  xdrmem_create (xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE);
+  if ((!xdr_callmsg (xdrs, &msg)) || (!xdr_rmtcall_args (xdrs, &a)))
+    {
+      stat = RPC_CANTENCODEARGS;
+      goto done_broad;
+    }
+  outlen = (int) xdr_getpos (xdrs);
+  xdr_destroy (xdrs);
+  /*
+   * Basic loop: broadcast a packet and wait a while for response(s).
+   * The response timeout grows larger per iteration.
+   */
+  for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2)
+    {
+      for (i = 0; i < nets; i++)
+	{
+	  baddr.sin_addr = addrs[i];
+	  if (sendto (sock, outbuf, outlen, 0,
+		      (struct sockaddr *) &baddr,
+		      sizeof (struct sockaddr)) != outlen)
+	    {
+	      perror (_("Cannot send broadcast packet"));
+	      stat = RPC_CANTSEND;
+	      goto done_broad;
+	    }
 	}
-#endif							/* def SO_BROADCAST */
-#ifdef FD_SETSIZE
-	FD_ZERO(&mask);
-	FD_SET(sock, &mask);
-#else
-	mask = (1 << sock);
-#endif							/* def FD_SETSIZE */
-	nets = getbroadcastnets(addrs, sock, inbuf);
-	bzero((char *) &baddr, sizeof(baddr));
-	baddr.sin_family = AF_INET;
-	baddr.sin_port = htons(PMAPPORT);
-	baddr.sin_addr.s_addr = htonl(INADDR_ANY);
-/*	baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); */
-	(void) gettimeofday(&t, (struct timezone *) 0);
-	msg.rm_xid = xid = getpid() ^ t.tv_sec ^ t.tv_usec;
-	t.tv_usec = 0;
-	msg.rm_direction = CALL;
-	msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
-	msg.rm_call.cb_prog = PMAPPROG;
-	msg.rm_call.cb_vers = PMAPVERS;
-	msg.rm_call.cb_proc = PMAPPROC_CALLIT;
-	msg.rm_call.cb_cred = unix_auth->ah_cred;
-	msg.rm_call.cb_verf = unix_auth->ah_verf;
-	a.prog = prog;
-	a.vers = vers;
-	a.proc = proc;
-	a.xdr_args = xargs;
-	a.args_ptr = argsp;
-	r.port_ptr = &port;
-	r.xdr_results = xresults;
-	r.results_ptr = resultsp;
-	xdrmem_create(xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE);
-	if ((!xdr_callmsg(xdrs, &msg)) || (!xdr_rmtcall_args(xdrs, &a))) {
-		stat = RPC_CANTENCODEARGS;
-		goto done_broad;
+      if (eachresult == NULL)
+	{
+	  stat = RPC_SUCCESS;
+	  goto done_broad;
 	}
-	outlen = (int) xdr_getpos(xdrs);
-	xdr_destroy(xdrs);
-	/*
-	 * Basic loop: broadcast a packet and wait a while for response(s).
-	 * The response timeout grows larger per iteration.
-	 */
-	for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) {
-		for (i = 0; i < nets; i++) {
-			baddr.sin_addr = addrs[i];
-			if (sendto(sock, outbuf, outlen, 0,
-					   (struct sockaddr *) &baddr,
-					   sizeof(struct sockaddr)) != outlen) {
-				perror("Cannot send broadcast packet");
-				stat = RPC_CANTSEND;
-				goto done_broad;
-			}
-		}
-		if (eachresult == NULL) {
-			stat = RPC_SUCCESS;
-			goto done_broad;
-		}
-	  recv_again:
-		msg.acpted_rply.ar_verf = _null_auth;
-		msg.acpted_rply.ar_results.where = (caddr_t) & r;
-		msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_rmtcallres;
-		readfds = mask;
-		switch (select(_rpc_dtablesize(), &readfds, NULL, NULL, &t)) {
-
-		case 0:				/* timed out */
-			stat = RPC_TIMEDOUT;
-			continue;
+    recv_again:
+      msg.acpted_rply.ar_verf = _null_auth;
+      msg.acpted_rply.ar_results.where = (caddr_t) & r;
+      msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_rmtcallres;
+      milliseconds = t.tv_sec * 1000 + t.tv_usec / 1000;
+      switch (poll(&fd, 1, milliseconds))
+	{
 
-		case -1:				/* some kind of error */
-			if (errno == EINTR)
-				goto recv_again;
-			perror("Broadcast select problem");
-			stat = RPC_CANTRECV;
-			goto done_broad;
+	case 0:		/* timed out */
+	  stat = RPC_TIMEDOUT;
+	  continue;
 
-		}						/* end of select results switch */
-	  try_again:
-		fromlen = sizeof(struct sockaddr);
+	case -1:		/* some kind of error */
+	  if (errno == EINTR)
+	    goto recv_again;
+	  perror (_("Broadcast poll problem"));
+	  stat = RPC_CANTRECV;
+	  goto done_broad;
 
-		inlen = recvfrom(sock, inbuf, UDPMSGSIZE, 0,
-						 (struct sockaddr *) &raddr, &fromlen);
-		if (inlen < 0) {
-			if (errno == EINTR)
-				goto try_again;
-			perror("Cannot receive reply to broadcast");
-			stat = RPC_CANTRECV;
-			goto done_broad;
-		}
-		if (inlen < sizeof(u_long))
-			goto recv_again;
-		/*
-		 * see if reply transaction id matches sent id.
-		 * If so, decode the results.
-		 */
-		xdrmem_create(xdrs, inbuf, (u_int) inlen, XDR_DECODE);
-		if (xdr_replymsg(xdrs, &msg)) {
-			if ((msg.rm_xid == xid) &&
-				(msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
-				(msg.acpted_rply.ar_stat == SUCCESS)) {
-				raddr.sin_port = htons((u_short) port);
-				done = (*eachresult) (resultsp, &raddr);
-			}
-			/* otherwise, we just ignore the errors ... */
-		} else {
+	}			/* end of poll results switch */
+    try_again:
+      fromlen = sizeof (struct sockaddr);
+      inlen = recvfrom (sock, inbuf, UDPMSGSIZE, 0,
+			(struct sockaddr *) &raddr, &fromlen);
+      if (inlen < 0)
+	{
+	  if (errno == EINTR)
+	    goto try_again;
+	  perror (_("Cannot receive reply to broadcast"));
+	  stat = RPC_CANTRECV;
+	  goto done_broad;
+	}
+      if ((size_t) inlen < sizeof (u_long))
+	goto recv_again;
+      /*
+       * see if reply transaction id matches sent id.
+       * If so, decode the results.
+       */
+      xdrmem_create (xdrs, inbuf, (u_int) inlen, XDR_DECODE);
+      if (xdr_replymsg (xdrs, &msg))
+	{
+	  if (((u_int32_t) msg.rm_xid == (u_int32_t) xid) &&
+	      (msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+	      (msg.acpted_rply.ar_stat == SUCCESS))
+	    {
+	      raddr.sin_port = htons ((u_short) port);
+	      done = (*eachresult) (resultsp, &raddr);
+	    }
+	  /* otherwise, we just ignore the errors ... */
+	}
+      else
+	{
 #ifdef notdef
-			/* some kind of deserialization problem ... */
-			if (msg.rm_xid == xid)
-				fprintf(stderr, "Broadcast deserialization problem");
-			/* otherwise, just random garbage */
+	  /* some kind of deserialization problem ... */
+	  if ((u_int32_t) msg.rm_xid == (u_int32_t) xid)
+	    fprintf (stderr, "Broadcast deserialization problem");
+	  /* otherwise, just random garbage */
 #endif
-		}
-		xdrs->x_op = XDR_FREE;
-		msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
-		(void) xdr_replymsg(xdrs, &msg);
-		(void) (*xresults) (xdrs, resultsp);
-		xdr_destroy(xdrs);
-		if (done) {
-			stat = RPC_SUCCESS;
-			goto done_broad;
-		} else {
-			goto recv_again;
-		}
 	}
-  done_broad:
-	(void) close(sock);
-	AUTH_DESTROY(unix_auth);
-	return (stat);
+      xdrs->x_op = XDR_FREE;
+      msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
+      (void) xdr_replymsg (xdrs, &msg);
+      (void) (*xresults) (xdrs, resultsp);
+      xdr_destroy (xdrs);
+      if (done)
+	{
+	  stat = RPC_SUCCESS;
+	  goto done_broad;
+	}
+      else
+	{
+	  goto recv_again;
+	}
+    }
+done_broad:
+  (void) close (sock);
+  AUTH_DESTROY (unix_auth);
+  return stat;
 }

+ 160 - 139
libc/inet/rpc/rpc_callmsg.c

@@ -6,29 +6,30 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro";
+#endif
 
 /*
  * rpc_callmsg.c
@@ -37,149 +38,169 @@
  *
  */
 
-#include <sys/param.h>
+#define __FORCE_GLIBC
+#include <features.h>
 
+#include <string.h>
+#include <sys/param.h>
 #include <rpc/rpc.h>
 
 /*
  * XDR a call message
  */
-bool_t xdr_callmsg(xdrs, cmsg)
-register XDR *xdrs;
-register struct rpc_msg *cmsg;
+bool_t
+xdr_callmsg (XDR *xdrs, struct rpc_msg *cmsg)
 {
-	register void *buf;
-	register struct opaque_auth *oa;
+  int32_t *buf;
+  struct opaque_auth *oa;
 
-	if (xdrs->x_op == XDR_ENCODE) {
-		if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) {
-			return (FALSE);
+  if (xdrs->x_op == XDR_ENCODE)
+    {
+      if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES)
+	{
+	  return (FALSE);
+	}
+      if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES)
+	{
+	  return (FALSE);
+	}
+      buf = XDR_INLINE (xdrs, 8 * BYTES_PER_XDR_UNIT
+			+ RNDUP (cmsg->rm_call.cb_cred.oa_length)
+			+ 2 * BYTES_PER_XDR_UNIT
+			+ RNDUP (cmsg->rm_call.cb_verf.oa_length));
+      if (buf != NULL)
+	{
+	  IXDR_PUT_LONG (buf, cmsg->rm_xid);
+	  IXDR_PUT_ENUM (buf, cmsg->rm_direction);
+	  if (cmsg->rm_direction != CALL)
+	    return FALSE;
+	  IXDR_PUT_LONG (buf, cmsg->rm_call.cb_rpcvers);
+	  if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION)
+	    return FALSE;
+	  IXDR_PUT_LONG (buf, cmsg->rm_call.cb_prog);
+	  IXDR_PUT_LONG (buf, cmsg->rm_call.cb_vers);
+	  IXDR_PUT_LONG (buf, cmsg->rm_call.cb_proc);
+	  oa = &cmsg->rm_call.cb_cred;
+	  IXDR_PUT_ENUM (buf, oa->oa_flavor);
+	  IXDR_PUT_INT32 (buf, oa->oa_length);
+	  if (oa->oa_length)
+	    {
+	      memcpy ((caddr_t) buf, oa->oa_base, oa->oa_length);
+	      buf = (int32_t *) ((char *) buf + RNDUP (oa->oa_length));
+	    }
+	  oa = &cmsg->rm_call.cb_verf;
+	  IXDR_PUT_ENUM (buf, oa->oa_flavor);
+	  IXDR_PUT_INT32 (buf, oa->oa_length);
+	  if (oa->oa_length)
+	    {
+	      memcpy ((caddr_t) buf, oa->oa_base, oa->oa_length);
+	      /* no real need....
+	         buf = (long *) ((char *) buf + RNDUP(oa->oa_length));
+	       */
+	    }
+	  return TRUE;
+	}
+    }
+  if (xdrs->x_op == XDR_DECODE)
+    {
+      buf = XDR_INLINE (xdrs, 8 * BYTES_PER_XDR_UNIT);
+      if (buf != NULL)
+	{
+	  cmsg->rm_xid = IXDR_GET_LONG (buf);
+	  cmsg->rm_direction = IXDR_GET_ENUM (buf, enum msg_type);
+	  if (cmsg->rm_direction != CALL)
+	    {
+	      return FALSE;
+	    }
+	  cmsg->rm_call.cb_rpcvers = IXDR_GET_LONG (buf);
+	  if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION)
+	    {
+	      return FALSE;
+	    }
+	  cmsg->rm_call.cb_prog = IXDR_GET_LONG (buf);
+	  cmsg->rm_call.cb_vers = IXDR_GET_LONG (buf);
+	  cmsg->rm_call.cb_proc = IXDR_GET_LONG (buf);
+	  oa = &cmsg->rm_call.cb_cred;
+	  oa->oa_flavor = IXDR_GET_ENUM (buf, enum_t);
+	  oa->oa_length = IXDR_GET_INT32 (buf);
+	  if (oa->oa_length)
+	    {
+	      if (oa->oa_length > MAX_AUTH_BYTES)
+		return FALSE;
+	      if (oa->oa_base == NULL)
+		{
+		  oa->oa_base = (caddr_t)
+		    mem_alloc (oa->oa_length);
 		}
-		if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) {
-			return (FALSE);
+	      buf = XDR_INLINE (xdrs, RNDUP (oa->oa_length));
+	      if (buf == NULL)
+		{
+		  if (xdr_opaque (xdrs, oa->oa_base,
+				  oa->oa_length) == FALSE)
+		    return FALSE;
 		}
-		buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT
-						 + RNDUP(cmsg->rm_call.cb_cred.oa_length)
-						 + 2 * BYTES_PER_XDR_UNIT
-						 + RNDUP(cmsg->rm_call.cb_verf.oa_length));
-		if (buf != NULL) {
-			IXDR_PUT_LONG(buf, cmsg->rm_xid);
-			IXDR_PUT_ENUM(buf, cmsg->rm_direction);
-			if (cmsg->rm_direction != CALL) {
-				return (FALSE);
-			}
-			IXDR_PUT_LONG(buf, cmsg->rm_call.cb_rpcvers);
-			if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
-				return (FALSE);
-			}
-			IXDR_PUT_LONG(buf, cmsg->rm_call.cb_prog);
-			IXDR_PUT_LONG(buf, cmsg->rm_call.cb_vers);
-			IXDR_PUT_LONG(buf, cmsg->rm_call.cb_proc);
-			oa = &cmsg->rm_call.cb_cred;
-			IXDR_PUT_ENUM(buf, oa->oa_flavor);
-			IXDR_PUT_LONG(buf, oa->oa_length);
-			if (oa->oa_length) {
-				bcopy(oa->oa_base, (caddr_t) buf, oa->oa_length);
-				buf += RNDUP(oa->oa_length) / sizeof(long);
-			}
-			oa = &cmsg->rm_call.cb_verf;
-			IXDR_PUT_ENUM(buf, oa->oa_flavor);
-			IXDR_PUT_LONG(buf, oa->oa_length);
-			if (oa->oa_length) {
-				bcopy(oa->oa_base, (caddr_t) buf, oa->oa_length);
-				/* no real need....
-				   buf += RNDUP(oa->oa_length) / sizeof (long);
-				 */
-			}
-			return (TRUE);
+	      else
+		{
+		  memcpy (oa->oa_base, (caddr_t) buf, oa->oa_length);
+		  /* no real need....
+		     buf = (long *) ((char *) buf
+		     + RNDUP(oa->oa_length));
+		   */
 		}
-	}
-	if (xdrs->x_op == XDR_DECODE) {
-		buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT);
-		if (buf != NULL) {
-			cmsg->rm_xid = IXDR_GET_LONG(buf);
-			cmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type);
-
-			if (cmsg->rm_direction != CALL) {
-				return (FALSE);
-			}
-			cmsg->rm_call.cb_rpcvers = IXDR_GET_LONG(buf);
-			if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
-				return (FALSE);
-			}
-			cmsg->rm_call.cb_prog = IXDR_GET_LONG(buf);
-			cmsg->rm_call.cb_vers = IXDR_GET_LONG(buf);
-			cmsg->rm_call.cb_proc = IXDR_GET_LONG(buf);
-			oa = &cmsg->rm_call.cb_cred;
-			oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
-			oa->oa_length = IXDR_GET_LONG(buf);
-			if (oa->oa_length) {
-				if (oa->oa_length > MAX_AUTH_BYTES) {
-					return (FALSE);
-				}
-				if (oa->oa_base == NULL) {
-					oa->oa_base = (caddr_t)
-						mem_alloc(oa->oa_length);
-				}
-				buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
-				if (buf == NULL) {
-					if (xdr_opaque(xdrs, oa->oa_base,
-								   oa->oa_length) == FALSE) {
-						return (FALSE);
-					}
-				} else {
-					bcopy((caddr_t) buf, oa->oa_base, oa->oa_length);
-					/* no real need....
-					   buf += RNDUP(oa->oa_length) /
-					   sizeof (long);
-					 */
-				}
-			}
-			oa = &cmsg->rm_call.cb_verf;
-			buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
-			if (buf == NULL) {
-				if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE ||
-					xdr_u_int(xdrs, &oa->oa_length) == FALSE) {
-					return (FALSE);
-				}
-			} else {
-				oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
-				oa->oa_length = IXDR_GET_LONG(buf);
-			}
-			if (oa->oa_length) {
-				if (oa->oa_length > MAX_AUTH_BYTES) {
-					return (FALSE);
-				}
-				if (oa->oa_base == NULL) {
-					oa->oa_base = (caddr_t)
-						mem_alloc(oa->oa_length);
-				}
-				buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
-				if (buf == NULL) {
-					if (xdr_opaque(xdrs, oa->oa_base,
-								   oa->oa_length) == FALSE) {
-						return (FALSE);
-					}
-				} else {
-					bcopy((caddr_t) buf, oa->oa_base, oa->oa_length);
-					/* no real need...
-					   buf += RNDUP(oa->oa_length) /
-					   sizeof (long);
-					 */
-				}
-			}
-			return (TRUE);
+	    }
+	  oa = &cmsg->rm_call.cb_verf;
+	  buf = XDR_INLINE (xdrs, 2 * BYTES_PER_XDR_UNIT);
+	  if (buf == NULL)
+	    {
+	      if (xdr_enum (xdrs, &oa->oa_flavor) == FALSE ||
+		  xdr_u_int (xdrs, &oa->oa_length) == FALSE)
+		{
+		  return FALSE;
+		}
+	    }
+	  else
+	    {
+	      oa->oa_flavor = IXDR_GET_ENUM (buf, enum_t);
+	      oa->oa_length = IXDR_GET_INT32 (buf);
+	    }
+	  if (oa->oa_length)
+	    {
+	      if (oa->oa_length > MAX_AUTH_BYTES)
+		return FALSE;
+	      if (oa->oa_base == NULL)
+		{
+		  oa->oa_base = (caddr_t)
+		    mem_alloc (oa->oa_length);
+		}
+	      buf = XDR_INLINE (xdrs, RNDUP (oa->oa_length));
+	      if (buf == NULL)
+		{
+		  if (xdr_opaque (xdrs, oa->oa_base,
+				  oa->oa_length) == FALSE)
+		    return FALSE;
+		}
+	      else
+		{
+		  memcpy (oa->oa_base, (caddr_t) buf, oa->oa_length);
+		  /* no real need...
+		     buf = (long *) ((char *) buf
+		     + RNDUP(oa->oa_length));
+		   */
 		}
+	    }
+	  return TRUE;
 	}
-	if (xdr_u_long(xdrs, &(cmsg->rm_xid)) &&
-		xdr_enum(xdrs, (enum_t *) & (cmsg->rm_direction)) &&
-		(cmsg->rm_direction == CALL) &&
-		xdr_u_long(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
-		(cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) &&
-		xdr_u_long(xdrs, &(cmsg->rm_call.cb_prog)) &&
-		xdr_u_long(xdrs, &(cmsg->rm_call.cb_vers)) &&
-		xdr_u_long(xdrs, &(cmsg->rm_call.cb_proc)) &&
-		xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_cred)))
-			return (xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_verf)));
-	return (FALSE);
+    }
+  if (
+       xdr_u_long (xdrs, &(cmsg->rm_xid)) &&
+       xdr_enum (xdrs, (enum_t *) & (cmsg->rm_direction)) &&
+       (cmsg->rm_direction == CALL) &&
+       xdr_u_long (xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
+       (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) &&
+       xdr_u_long (xdrs, &(cmsg->rm_call.cb_prog)) &&
+       xdr_u_long (xdrs, &(cmsg->rm_call.cb_vers)) &&
+       xdr_u_long (xdrs, &(cmsg->rm_call.cb_proc)) &&
+       xdr_opaque_auth (xdrs, &(cmsg->rm_call.cb_cred)))
+    return xdr_opaque_auth (xdrs, &(cmsg->rm_call.cb_verf));
+  return FALSE;
 }

+ 16 - 14
libc/inet/rpc/rpc_commondata.c

@@ -1,4 +1,3 @@
-/* @(#)rpc_commondata.c	2.1 88/07/29 4.0 RPCSRC */
 /*
  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  * unrestricted use provided that this legend is included on all tape
@@ -6,39 +5,42 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
 #include <rpc/rpc.h>
+
+#ifdef _RPC_THREAD_SAFE_
+#undef svc_fdset
+#undef rpc_createerr
+#undef svc_pollfd
+#undef svc_max_pollfd
+#endif /* _RPC_THREAD_SAFE_ */
+
 /*
  * This file should only contain common data (global data) that is exported
- * by public interfaces 
+ * by public interfaces
  */
 struct opaque_auth _null_auth;
-
-#ifdef FD_SETSIZE
 fd_set svc_fdset;
-#else
-int svc_fds;
-#endif							/* def FD_SETSIZE */
 struct rpc_createerr rpc_createerr;
+struct pollfd *svc_pollfd;
+int svc_max_pollfd;

+ 19 - 12
libc/inet/rpc/rpc_dtablesize.c

@@ -6,42 +6,49 @@
  * 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
  */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro";
+#endif
+
 #define __FORCE_GLIBC
+#define __USE_BSD
 #include <features.h>
 
-#include <rpc/clnt.h>
 #include <unistd.h>
+#include <rpc/clnt.h>
+
 /*
  * Cache the result of getdtablesize(), so we don't have to do an
  * expensive system call every time.
  */
-int _rpc_dtablesize(void)
+int
+_rpc_dtablesize (void)
 {
-	static int size;
+  static int size;
+
+  if (size == 0)
+    size = getdtablesize ();
 
-	if (size == 0) {
-		size = getdtablesize();
-	}
-	return (size);
+  return size;
 }

+ 180 - 184
libc/inet/rpc/rpc_prot.c

@@ -6,29 +6,30 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";
+#endif
 
 /*
  * rpc_prot.c
@@ -43,6 +44,9 @@
  * routines are also in this program.
  */
 
+#define __FORCE_GLIBC
+#include <features.h>
+
 #include <sys/param.h>
 
 #include <rpc/rpc.h>
@@ -53,25 +57,23 @@
  * XDR an opaque authentication struct
  * (see auth.h)
  */
-bool_t xdr_opaque_auth(xdrs, ap)
-register XDR *xdrs;
-register struct opaque_auth *ap;
+bool_t
+xdr_opaque_auth (XDR *xdrs, struct opaque_auth *ap)
 {
 
-	if (xdr_enum(xdrs, &(ap->oa_flavor)))
-		return (xdr_bytes(xdrs, &ap->oa_base,
-						  &ap->oa_length, MAX_AUTH_BYTES));
-	return (FALSE);
+  if (xdr_enum (xdrs, &(ap->oa_flavor)))
+    return xdr_bytes (xdrs, &ap->oa_base,
+		      &ap->oa_length, MAX_AUTH_BYTES);
+  return FALSE;
 }
 
 /*
  * XDR a DES block
  */
-bool_t xdr_des_block(xdrs, blkp)
-register XDR *xdrs;
-register des_block *blkp;
+bool_t
+xdr_des_block (XDR *xdrs, des_block *blkp)
 {
-	return (xdr_opaque(xdrs, (caddr_t) blkp, sizeof(des_block)));
+  return xdr_opaque (xdrs, (caddr_t) blkp, sizeof (des_block));
 }
 
 /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
@@ -79,75 +81,71 @@ register des_block *blkp;
 /*
  * XDR the MSG_ACCEPTED part of a reply message union
  */
-bool_t xdr_accepted_reply(xdrs, ar)
-register XDR *xdrs;
-register struct accepted_reply *ar;
+bool_t
+xdr_accepted_reply (XDR *xdrs, struct accepted_reply *ar)
 {
-
-	/* personalized union, rather than calling xdr_union */
-	if (!xdr_opaque_auth(xdrs, &(ar->ar_verf)))
-		return (FALSE);
-	if (!xdr_enum(xdrs, (enum_t *) & (ar->ar_stat)))
-		return (FALSE);
-	switch (ar->ar_stat) {
-
-	case SUCCESS:
-		return ((*(ar->ar_results.proc)) (xdrs, ar->ar_results.where));
-
-	case PROG_MISMATCH:
-		if (!xdr_u_long(xdrs, &(ar->ar_vers.low)))
-			return (FALSE);
-		return (xdr_u_long(xdrs, &(ar->ar_vers.high)));
-	default:					/* silence the warnings */
-	}
-	return (TRUE);				/* TRUE => open ended set of problems */
+  /* personalized union, rather than calling xdr_union */
+  if (!xdr_opaque_auth (xdrs, &(ar->ar_verf)))
+    return FALSE;
+  if (!xdr_enum (xdrs, (enum_t *) & (ar->ar_stat)))
+    return FALSE;
+  switch (ar->ar_stat)
+    {
+    case SUCCESS:
+      return ((*(ar->ar_results.proc)) (xdrs, ar->ar_results.where));
+    case PROG_MISMATCH:
+      if (!xdr_u_long (xdrs, &(ar->ar_vers.low)))
+	return FALSE;
+      return (xdr_u_long (xdrs, &(ar->ar_vers.high)));
+    default:
+      return TRUE;
+    }
+  return TRUE;		/* TRUE => open ended set of problems */
 }
 
 /*
  * XDR the MSG_DENIED part of a reply message union
  */
-bool_t xdr_rejected_reply(xdrs, rr)
-register XDR *xdrs;
-register struct rejected_reply *rr;
+bool_t
+xdr_rejected_reply (XDR *xdrs, struct rejected_reply *rr)
 {
-
-	/* personalized union, rather than calling xdr_union */
-	if (!xdr_enum(xdrs, (enum_t *) & (rr->rj_stat)))
-		return (FALSE);
-	switch (rr->rj_stat) {
-
-	case RPC_MISMATCH:
-		if (!xdr_u_long(xdrs, &(rr->rj_vers.low)))
-			return (FALSE);
-		return (xdr_u_long(xdrs, &(rr->rj_vers.high)));
-
-	case AUTH_ERROR:
-		return (xdr_enum(xdrs, (enum_t *) & (rr->rj_why)));
-	default:					/* silence the warnings */
-	}
-	return (FALSE);
+  /* personalized union, rather than calling xdr_union */
+  if (!xdr_enum (xdrs, (enum_t *) & (rr->rj_stat)))
+    return FALSE;
+  switch (rr->rj_stat)
+    {
+    case RPC_MISMATCH:
+      if (!xdr_u_long (xdrs, &(rr->rj_vers.low)))
+	return FALSE;
+      return xdr_u_long (xdrs, &(rr->rj_vers.high));
+
+    case AUTH_ERROR:
+      return xdr_enum (xdrs, (enum_t *) & (rr->rj_why));
+    }
+  return FALSE;
 }
 
-static struct xdr_discrim reply_dscrm[3] = {
-	{(int) MSG_ACCEPTED, (xdrproc_t) xdr_accepted_reply},
-	{(int) MSG_DENIED, (xdrproc_t) xdr_rejected_reply},
-	{__dontcare__, NULL_xdrproc_t}
-};
+static const struct xdr_discrim reply_dscrm[3] =
+{
+  {(int) MSG_ACCEPTED, (xdrproc_t) xdr_accepted_reply},
+  {(int) MSG_DENIED, (xdrproc_t) xdr_rejected_reply},
+  {__dontcare__, NULL_xdrproc_t}};
 
 /*
  * XDR a reply message
  */
-bool_t xdr_replymsg(xdrs, rmsg)
-register XDR *xdrs;
-register struct rpc_msg *rmsg;
+bool_t
+xdr_replymsg (xdrs, rmsg)
+     XDR *xdrs;
+     struct rpc_msg *rmsg;
 {
-	if (xdr_u_long(xdrs, &(rmsg->rm_xid)) &&
-		xdr_enum(xdrs, (enum_t *) & (rmsg->rm_direction)) &&
-		(rmsg->rm_direction == REPLY))
-		return (xdr_union(xdrs, (enum_t *) & (rmsg->rm_reply.rp_stat),
-						  (caddr_t) & (rmsg->rm_reply.ru), reply_dscrm,
-						  NULL_xdrproc_t));
-	return (FALSE);
+  if (xdr_u_long (xdrs, &(rmsg->rm_xid)) &&
+      xdr_enum (xdrs, (enum_t *) & (rmsg->rm_direction)) &&
+      (rmsg->rm_direction == REPLY))
+    return xdr_union (xdrs, (enum_t *) & (rmsg->rm_reply.rp_stat),
+		      (caddr_t) & (rmsg->rm_reply.ru), reply_dscrm,
+		      NULL_xdrproc_t);
+  return FALSE;
 }
 
 
@@ -156,131 +154,129 @@ register struct rpc_msg *rmsg;
  * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
  * The rm_xid is not really static, but the user can easily munge on the fly.
  */
-bool_t xdr_callhdr(xdrs, cmsg)
-register XDR *xdrs;
-register struct rpc_msg *cmsg;
+bool_t
+xdr_callhdr (xdrs, cmsg)
+     XDR *xdrs;
+     struct rpc_msg *cmsg;
 {
 
-	cmsg->rm_direction = CALL;
-	cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
-	if (
-		(xdrs->x_op == XDR_ENCODE) &&
-		xdr_u_long(xdrs, &(cmsg->rm_xid)) &&
-		xdr_enum(xdrs, (enum_t *) & (cmsg->rm_direction)) &&
-		xdr_u_long(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
-		xdr_u_long(xdrs, &(cmsg->rm_call.cb_prog)))
-			return (xdr_u_long(xdrs, &(cmsg->rm_call.cb_vers)));
-	return (FALSE);
+  cmsg->rm_direction = CALL;
+  cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
+  if (
+       (xdrs->x_op == XDR_ENCODE) &&
+       xdr_u_long (xdrs, &(cmsg->rm_xid)) &&
+       xdr_enum (xdrs, (enum_t *) & (cmsg->rm_direction)) &&
+       xdr_u_long (xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
+       xdr_u_long (xdrs, &(cmsg->rm_call.cb_prog)))
+    return xdr_u_long (xdrs, &(cmsg->rm_call.cb_vers));
+  return FALSE;
 }
 
 /* ************************** Client utility routine ************* */
 
-static void accepted(acpt_stat, error)
-register enum accept_stat acpt_stat;
-register struct rpc_err *error;
+static void
+accepted (enum accept_stat acpt_stat,
+	  struct rpc_err *error)
 {
-
-	switch (acpt_stat) {
-
-	case PROG_UNAVAIL:
-		error->re_status = RPC_PROGUNAVAIL;
-		return;
-
-	case PROG_MISMATCH:
-		error->re_status = RPC_PROGVERSMISMATCH;
-		return;
-
-	case PROC_UNAVAIL:
-		error->re_status = RPC_PROCUNAVAIL;
-		return;
-
-	case GARBAGE_ARGS:
-		error->re_status = RPC_CANTDECODEARGS;
-		return;
-
-	case SYSTEM_ERR:
-		error->re_status = RPC_SYSTEMERROR;
-		return;
-
-	case SUCCESS:
-		error->re_status = RPC_SUCCESS;
-		return;
-
-	default:					/* silence the warnings */
-	}
-	/* something's wrong, but we don't know what ... */
-	error->re_status = RPC_FAILED;
-	error->re_lb.s1 = (long) MSG_ACCEPTED;
-	error->re_lb.s2 = (long) acpt_stat;
+  switch (acpt_stat)
+    {
+
+    case PROG_UNAVAIL:
+      error->re_status = RPC_PROGUNAVAIL;
+      return;
+
+    case PROG_MISMATCH:
+      error->re_status = RPC_PROGVERSMISMATCH;
+      return;
+
+    case PROC_UNAVAIL:
+      error->re_status = RPC_PROCUNAVAIL;
+      return;
+
+    case GARBAGE_ARGS:
+      error->re_status = RPC_CANTDECODEARGS;
+      return;
+
+    case SYSTEM_ERR:
+      error->re_status = RPC_SYSTEMERROR;
+      return;
+
+    case SUCCESS:
+      error->re_status = RPC_SUCCESS;
+      return;
+    }
+  /* something's wrong, but we don't know what ... */
+  error->re_status = RPC_FAILED;
+  error->re_lb.s1 = (long) MSG_ACCEPTED;
+  error->re_lb.s2 = (long) acpt_stat;
 }
 
-static void rejected(rjct_stat, error)
-register enum reject_stat rjct_stat;
-register struct rpc_err *error;
+static void
+rejected (enum reject_stat rjct_stat,
+	  struct rpc_err *error)
 {
-
-	switch (rjct_stat) {
-
-	case RPC_VERSMISMATCH:
-		error->re_status = RPC_VERSMISMATCH;
-		return;
-
-	case AUTH_ERROR:
-		error->re_status = RPC_AUTHERROR;
-		return;
-
-	default:					/* silence the warnings */
-	}
-	/* something's wrong, but we don't know what ... */
-	error->re_status = RPC_FAILED;
-	error->re_lb.s1 = (long) MSG_DENIED;
-	error->re_lb.s2 = (long) rjct_stat;
+  switch (rjct_stat)
+    {
+    case RPC_VERSMISMATCH:
+      error->re_status = RPC_VERSMISMATCH;
+      return;
+    case AUTH_ERROR:
+      error->re_status = RPC_AUTHERROR;
+      return;
+    default:
+      /* something's wrong, but we don't know what ... */
+      error->re_status = RPC_FAILED;
+      error->re_lb.s1 = (long) MSG_DENIED;
+      error->re_lb.s2 = (long) rjct_stat;
+      return;
+    }
 }
 
 /*
  * given a reply message, fills in the error
  */
-void _seterr_reply(msg, error)
-register struct rpc_msg *msg;
-register struct rpc_err *error;
+void
+_seterr_reply (struct rpc_msg *msg,
+	       struct rpc_err *error)
 {
-
-	/* optimized for normal, SUCCESSful case */
-	switch (msg->rm_reply.rp_stat) {
-
-	case MSG_ACCEPTED:
-		if (msg->acpted_rply.ar_stat == SUCCESS) {
-			error->re_status = RPC_SUCCESS;
-			return;
-		};
-		accepted(msg->acpted_rply.ar_stat, error);
-		break;
-
-	case MSG_DENIED:
-		rejected(msg->rjcted_rply.rj_stat, error);
-		break;
-
-	default:
-		error->re_status = RPC_FAILED;
-		error->re_lb.s1 = (long) (msg->rm_reply.rp_stat);
-		break;
-	}
-	switch (error->re_status) {
-
-	case RPC_VERSMISMATCH:
-		error->re_vers.low = msg->rjcted_rply.rj_vers.low;
-		error->re_vers.high = msg->rjcted_rply.rj_vers.high;
-		break;
-
-	case RPC_AUTHERROR:
-		error->re_why = msg->rjcted_rply.rj_why;
-		break;
-
-	case RPC_PROGVERSMISMATCH:
-		error->re_vers.low = msg->acpted_rply.ar_vers.low;
-		error->re_vers.high = msg->acpted_rply.ar_vers.high;
-		break;
-
-	default:					/* silence the warnings */
-	}
+  /* optimized for normal, SUCCESSful case */
+  switch (msg->rm_reply.rp_stat)
+    {
+    case MSG_ACCEPTED:
+      if (msg->acpted_rply.ar_stat == SUCCESS)
+	{
+	  error->re_status = RPC_SUCCESS;
+	  return;
+	};
+      accepted (msg->acpted_rply.ar_stat, error);
+      break;
+
+    case MSG_DENIED:
+      rejected (msg->rjcted_rply.rj_stat, error);
+      break;
+
+    default:
+      error->re_status = RPC_FAILED;
+      error->re_lb.s1 = (long) (msg->rm_reply.rp_stat);
+      break;
+    }
+  switch (error->re_status)
+    {
+
+    case RPC_VERSMISMATCH:
+      error->re_vers.low = msg->rjcted_rply.rj_vers.low;
+      error->re_vers.high = msg->rjcted_rply.rj_vers.high;
+      break;
+
+    case RPC_AUTHERROR:
+      error->re_why = msg->rjcted_rply.rj_why;
+      break;
+
+    case RPC_PROGVERSMISMATCH:
+      error->re_vers.low = msg->acpted_rply.ar_vers.low;
+      error->re_vers.high = msg->acpted_rply.ar_vers.high;
+      break;
+    default:
+      break;
+    }
 }

+ 152 - 0
libc/inet/rpc/rpc_thread.c

@@ -0,0 +1,152 @@
+#define __FORCE_GLIBC
+#include <features.h>
+
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <assert.h>
+
+#ifdef _RPC_THREAD_SAFE_
+
+#include <bits/libc-lock.h>
+#include <bits/libc-tsd.h>
+
+
+/* Variable used in non-threaded applications or for the first thread.  */
+static struct rpc_thread_variables __libc_tsd_RPC_VARS_mem;
+static struct rpc_thread_variables *__libc_tsd_RPC_VARS_data =
+     &__libc_tsd_RPC_VARS_mem;
+
+/*
+ * Task-variable destructor
+ */
+void
+__rpc_thread_destroy (void)
+{
+	struct rpc_thread_variables *tvp = __rpc_thread_variables();
+
+	if (tvp != NULL && tvp != &__libc_tsd_RPC_VARS_mem) {
+		__rpc_thread_svc_cleanup ();
+		__rpc_thread_clnt_cleanup ();
+		__rpc_thread_key_cleanup ();
+		free (tvp->authnone_private_s);
+		free (tvp->clnt_perr_buf_s);
+		free (tvp->clntraw_private_s);
+		free (tvp->svcraw_private_s);
+		free (tvp->authdes_cache_s);
+		free (tvp->authdes_lru_s);
+		free (tvp);
+	}
+}
+
+
+/*
+ * Initialize RPC multi-threaded operation
+ */
+static void
+rpc_thread_multi (void)
+{
+  __libc_tsd_set (RPC_VARS, &__libc_tsd_RPC_VARS_mem);
+}
+
+
+struct rpc_thread_variables *
+__rpc_thread_variables (void)
+{
+	__libc_once_define (static, once);
+	struct rpc_thread_variables *tvp;
+
+	tvp = __libc_tsd_get (RPC_VARS);
+	if (tvp == NULL) {
+		__libc_once (once, rpc_thread_multi);
+		tvp = __libc_tsd_get (RPC_VARS);
+		if (tvp == NULL) {
+			tvp = calloc (1, sizeof *tvp);
+			if (tvp != NULL)
+				__libc_tsd_set (RPC_VARS, tvp);
+			else
+				tvp = __libc_tsd_RPC_VARS_data;
+		}
+	}
+	return tvp;
+}
+
+
+/* Global variables If we're single-threaded, or if this is the first
+   thread using the variable, use the existing global variable.  This
+   provides backwards compatability for existing applications which
+   dynamically link against this code.  */
+#undef svc_fdset
+#undef rpc_createerr
+#undef svc_pollfd
+#undef svc_max_pollfd
+
+fd_set *
+__rpc_thread_svc_fdset (void)
+{
+	struct rpc_thread_variables *tvp;
+
+	tvp = __rpc_thread_variables ();
+	if (tvp == &__libc_tsd_RPC_VARS_mem)
+		return &svc_fdset;
+	return &tvp->svc_fdset_s;
+}
+
+struct rpc_createerr *
+__rpc_thread_createerr (void)
+{
+	struct rpc_thread_variables *tvp;
+
+	tvp = __rpc_thread_variables ();
+	if (tvp == &__libc_tsd_RPC_VARS_mem)
+		return &rpc_createerr;
+	return &tvp->rpc_createerr_s;
+}
+
+struct pollfd **
+__rpc_thread_svc_pollfd (void)
+{
+	struct rpc_thread_variables *tvp;
+
+	tvp = __rpc_thread_variables ();
+	if (tvp == &__libc_tsd_RPC_VARS_mem)
+		return &svc_pollfd;
+	return &tvp->svc_pollfd_s;
+}
+
+int *
+__rpc_thread_svc_max_pollfd (void)
+{
+	struct rpc_thread_variables *tvp;
+
+	tvp = __rpc_thread_variables ();
+	if (tvp == &__libc_tsd_RPC_VARS_mem)
+		return &svc_max_pollfd;
+	return &tvp->svc_max_pollfd_s;
+}
+#else
+
+fd_set * __rpc_thread_svc_fdset (void)
+{
+    extern fd_set svc_fdset;
+    return &(svc_fdset);
+}
+
+struct rpc_createerr * __rpc_thread_createerr (void)
+{
+    extern struct rpc_createerr rpc_createerr;
+    return &(rpc_createerr);
+}
+
+struct pollfd ** __rpc_thread_svc_pollfd (void)
+{
+    extern struct pollfd *svc_pollfd;
+    return &(svc_pollfd);
+}
+
+int * __rpc_thread_svc_max_pollfd (void)
+{
+    extern int svc_max_pollfd;
+    return &(svc_max_pollfd);
+}
+
+#endif /* _RPC_THREAD_SAFE_ */

+ 149 - 0
libc/inet/rpc/rtime.c

@@ -0,0 +1,149 @@
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rtime.c	2.2 88/08/10 4.0 RPCSRC; from 1.8 88/02/08 SMI";
+#endif
+/*
+ * 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
+ */
+
+/*
+ * Copyright (c) 1988 by Sun Microsystems, Inc.
+ */
+/*
+ * rtime - get time from remote machine
+ *
+ * gets time, obtaining value from host
+ * on the udp/time socket.  Since timeserver returns
+ * with time of day in seconds since Jan 1, 1900,  must
+ * subtract seconds before Jan 1, 1970 to get
+ * what unix uses.
+ */
+#define __FORCE_GLIBC
+#include <features.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <rpc/rpc.h>
+#include <rpc/clnt.h>
+#include <sys/types.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <rpc/auth_des.h>
+#include <errno.h>
+#include <netinet/in.h>
+
+#define NYEARS	(u_long)(1970 - 1900)
+#define TOFFSET (u_long)(60*60*24*(365*NYEARS + (NYEARS/4)))
+
+static void do_close (int);
+
+static void
+do_close (int s)
+{
+  int save;
+
+  save = errno;
+  close (s);
+  __set_errno (save);
+}
+
+int
+rtime (struct sockaddr_in *addrp, struct rpc_timeval *timep,
+       struct rpc_timeval *timeout)
+{
+  int s;
+  struct pollfd fd;
+  int milliseconds;
+  int res;
+  unsigned long thetime;
+  struct sockaddr_in from;
+  int fromlen;
+  int type;
+
+  if (timeout == NULL)
+    type = SOCK_STREAM;
+  else
+    type = SOCK_DGRAM;
+
+  s = socket (AF_INET, type, 0);
+  if (s < 0)
+    return (-1);
+
+  addrp->sin_family = AF_INET;
+  addrp->sin_port = htons (IPPORT_TIMESERVER);
+  if (type == SOCK_DGRAM)
+    {
+      res = sendto (s, (char *) &thetime, sizeof (thetime), 0,
+		    (struct sockaddr *) addrp, sizeof (*addrp));
+      if (res < 0)
+	{
+	  do_close (s);
+	  return -1;
+	}
+      milliseconds = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000);
+      fd.fd = s;
+      fd.events = POLLIN;
+      do
+	res = poll (&fd, 1, milliseconds);
+      while (res < 0 && errno == EINTR);
+      if (res <= 0)
+	{
+	  if (res == 0)
+	    __set_errno (ETIMEDOUT);
+	  do_close (s);
+	  return (-1);
+	}
+      fromlen = sizeof (from);
+      res = recvfrom (s, (char *) &thetime, sizeof (thetime), 0,
+		      (struct sockaddr *) &from, &fromlen);
+      do_close (s);
+      if (res < 0)
+	return -1;
+    }
+  else
+    {
+      if (connect (s, (struct sockaddr *) addrp, sizeof (*addrp)) < 0)
+	{
+	  do_close (s);
+	  return -1;
+	}
+      res = read (s, (char *) &thetime, sizeof (thetime));
+      do_close (s);
+      if (res < 0)
+	return (-1);
+    }
+  if (res != sizeof (thetime))
+    {
+      __set_errno (EIO);
+      return -1;
+    }
+  thetime = ntohl (thetime);
+  timep->tv_sec = thetime - TOFFSET;
+  timep->tv_usec = 0;
+  return 0;
+}

+ 373 - 357
libc/inet/rpc/svc.c

@@ -1,4 +1,3 @@
-/* @(#)svc.c	2.4 88/08/11 4.0 RPCSRC; from 1.44 88/02/08 SMI */
 /*
  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  * unrestricted use provided that this legend is included on all tape
@@ -6,30 +5,27 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
-
 /*
  * svc.c, Server-side remote procedure call interface.
  *
@@ -40,299 +36,288 @@
  * Copyright (C) 1984, Sun Microsystems, Inc.
  */
 
-#define __USE_XOPEN
-#include <sys/errno.h>
+#define __FORCE_GLIBC
+#define _GNU_SOURCE
+#include <features.h>
+
+#include <errno.h>
+#include <unistd.h>
 #include <rpc/rpc.h>
+#include <rpc/svc.h>
 #include <rpc/pmap_clnt.h>
-#ifdef __linux__
-#include <sys/types.h>
-#include <sys/select.h>
-#endif
+#include <sys/poll.h>
 
-extern int errno;
-
-#ifdef FD_SETSIZE
-static SVCXPRT **xports;
+#ifdef _RPC_THREAD_SAFE_
+#define xports ((SVCXPRT **)RPC_THREAD_VARIABLE(svc_xports_s))
 #else
-#define NOFILE 32
-
-static SVCXPRT *xports[NOFILE];
-#endif							/* def FD_SETSIZE */
+static SVCXPRT **xports;
+#endif
 
 #define NULL_SVC ((struct svc_callout *)0)
-#define	RQCRED_SIZE	400			/* this size is excessive */
-
-/*
- * The services list
- * Each entry represents a set of procedures (an rpc program).
- * The dispatch routine takes request structs and runs the
- * apropriate procedure.
- */
-static struct svc_callout {
-	struct svc_callout *sc_next;
-	u_long sc_prog;
-	u_long sc_vers;
-	void (*sc_dispatch) ();
-} *svc_head;
-
-static struct svc_callout *svc_find();
+#define	RQCRED_SIZE	400	/* this size is excessive */
+
+/* The services list
+   Each entry represents a set of procedures (an rpc program).
+   The dispatch routine takes request structs and runs the
+   appropriate procedure. */
+struct svc_callout {
+  struct svc_callout *sc_next;
+  rpcprog_t sc_prog;
+  rpcvers_t sc_vers;
+  void (*sc_dispatch) (struct svc_req *, SVCXPRT *);
+};
+#ifdef _RPC_THREAD_SAFE_
+#define svc_head ((struct svc_callout *)RPC_THREAD_VARIABLE(svc_head_s))
+#else
+static struct svc_callout *svc_head;
+#endif
 
 /* ***************  SVCXPRT related stuff **************** */
 
-/*
- * Activate a transport handle.
- */
-void xprt_register(xprt)
-SVCXPRT *xprt;
+/* Activate a transport handle. */
+void
+xprt_register (SVCXPRT *xprt)
 {
-	register int sock = xprt->xp_sock;
-
-#ifdef FD_SETSIZE
-	if (xports == NULL) {
-		xports = (SVCXPRT **)
-			mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *));
-	}
-	if (sock < _rpc_dtablesize()) {
-		xports[sock] = xprt;
-		FD_SET(sock, &svc_fdset);
-	}
-#else
-	if (sock < NOFILE) {
-		xports[sock] = xprt;
-		svc_fds |= (1 << sock);
-	}
-#endif							/* def FD_SETSIZE */
-
+  register int sock = xprt->xp_sock;
+  register int i;
+
+  if (xports == NULL)
+    {
+      xports = (SVCXPRT **) malloc (_rpc_dtablesize () * sizeof (SVCXPRT *));
+      if (xports == NULL) /* Don´t add handle */
+	return;
+    }
+
+  if (sock < _rpc_dtablesize ())
+    {
+      xports[sock] = xprt;
+      if (sock < FD_SETSIZE)
+	FD_SET (sock, &svc_fdset);
+
+      /* Check if we have an empty slot */
+      for (i = 0; i < svc_max_pollfd; ++i)
+	if (svc_pollfd[i].fd == -1)
+	  {
+	    svc_pollfd[i].fd = sock;
+	    svc_pollfd[i].events = (POLLIN | POLLPRI |
+				    POLLRDNORM | POLLRDBAND);
+	    return;
+	  }
+
+      ++svc_max_pollfd;
+      svc_pollfd = realloc (svc_pollfd,
+			    sizeof (struct pollfd) * svc_max_pollfd);
+      if (svc_pollfd == NULL) /* Out of memory */
+	return;
+
+      svc_pollfd[svc_max_pollfd - 1].fd = sock;
+      svc_pollfd[svc_max_pollfd - 1].events = (POLLIN | POLLPRI |
+					       POLLRDNORM | POLLRDBAND);
+    }
 }
 
-/*
- * De-activate a transport handle. 
- */
-void xprt_unregister(xprt)
-SVCXPRT *xprt;
+/* De-activate a transport handle. */
+void
+xprt_unregister (SVCXPRT *xprt)
 {
-	register int sock = xprt->xp_sock;
+  register int sock = xprt->xp_sock;
+  register int i;
 
-#ifdef FD_SETSIZE
-	if ((sock < _rpc_dtablesize()) && (xports[sock] == xprt)) {
-		xports[sock] = (SVCXPRT *) 0;
-		FD_CLR(sock, &svc_fdset);
-	}
-#else
-	if ((sock < NOFILE) && (xports[sock] == xprt)) {
-		xports[sock] = (SVCXPRT *) 0;
-		svc_fds &= ~(1 << sock);
-	}
-#endif							/* def FD_SETSIZE */
+  if ((sock < _rpc_dtablesize ()) && (xports[sock] == xprt))
+    {
+      xports[sock] = (SVCXPRT *) 0;
+
+      if (sock < FD_SETSIZE)
+	FD_CLR (sock, &svc_fdset);
+
+      for (i = 0; i < svc_max_pollfd; ++i)
+	if (svc_pollfd[i].fd == sock)
+	  svc_pollfd[i].fd = -1;
+    }
 }
 
 
 /* ********************** CALLOUT list related stuff ************* */
 
-/*
- * Add a service program to the callout list.
- * The dispatch routine will be called when a rpc request for this
- * program number comes in.
- */
-bool_t svc_register (SVCXPRT *xprt, u_long prog, 
-	u_long vers, __dispatch_fn_t dispatch, u_long protocol)
+/* Search the callout list for a program number, return the callout
+   struct. */
+static struct svc_callout *
+svc_find (rpcprog_t prog, rpcvers_t vers, struct svc_callout **prev)
 {
-	struct svc_callout *prev;
-	register struct svc_callout *s;
-
-	if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) {
-		if (s->sc_dispatch == dispatch)
-			goto pmap_it;		/* he is registering another xptr */
-		return (FALSE);
-	}
-	s = (struct svc_callout *) mem_alloc(sizeof(struct svc_callout));
-
-	if (s == (struct svc_callout *) 0) {
-		return (FALSE);
-	}
-	s->sc_prog = prog;
-	s->sc_vers = vers;
-	s->sc_dispatch = dispatch;
-	s->sc_next = svc_head;
-	svc_head = s;
-  pmap_it:
-	/* now register the information with the local binder service */
-	if (protocol) {
-		return (pmap_set(prog, vers, protocol, xprt->xp_port));
-	}
-	return (TRUE);
+  register struct svc_callout *s, *p;
+
+  p = NULL_SVC;
+  for (s = svc_head; s != NULL_SVC; s = s->sc_next)
+    {
+      if ((s->sc_prog == prog) && (s->sc_vers == vers))
+	goto done;
+      p = s;
+    }
+done:
+  *prev = p;
+  return s;
 }
 
-/*
- * Remove a service program from the callout list.
- */
-void svc_unregister(prog, vers)
-u_long prog;
-u_long vers;
+/* Add a service program to the callout list.
+   The dispatch routine will be called when a rpc request for this
+   program number comes in. */
+bool_t
+svc_register (SVCXPRT * xprt, rpcprog_t prog, rpcvers_t vers,
+	      void (*dispatch) (struct svc_req *, SVCXPRT *),
+	      rpcproc_t protocol)
 {
-	struct svc_callout *prev;
-	register struct svc_callout *s;
-
-	if ((s = svc_find(prog, vers, &prev)) == NULL_SVC)
-		return;
-	if (prev == NULL_SVC) {
-		svc_head = s->sc_next;
-	} else {
-		prev->sc_next = s->sc_next;
-	}
-	s->sc_next = NULL_SVC;
-	mem_free((char *) s, (u_int) sizeof(struct svc_callout));
-
-	/* now unregister the information with the local binder service */
-	(void) pmap_unset(prog, vers);
+  struct svc_callout *prev;
+  register struct svc_callout *s;
+
+  if ((s = svc_find (prog, vers, &prev)) != NULL_SVC)
+    {
+      if (s->sc_dispatch == dispatch)
+	goto pmap_it;		/* he is registering another xptr */
+      return FALSE;
+    }
+  s = (struct svc_callout *) mem_alloc (sizeof (struct svc_callout));
+  if (s == (struct svc_callout *) 0)
+    return FALSE;
+
+  s->sc_prog = prog;
+  s->sc_vers = vers;
+  s->sc_dispatch = dispatch;
+  s->sc_next = svc_head;
+  svc_head = s;
+
+pmap_it:
+  /* now register the information with the local binder service */
+  if (protocol)
+    return pmap_set (prog, vers, protocol, xprt->xp_port);
+
+  return TRUE;
 }
 
-/*
- * Search the callout list for a program number, return the callout
- * struct.
- */
-static struct svc_callout *svc_find(prog, vers, prev)
-u_long prog;
-u_long vers;
-struct svc_callout **prev;
+/* Remove a service program from the callout list. */
+void
+svc_unregister (rpcprog_t prog, rpcvers_t vers)
 {
-	register struct svc_callout *s, *p;
+  struct svc_callout *prev;
+  register struct svc_callout *s;
 
-	p = NULL_SVC;
-	for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
-		if ((s->sc_prog == prog) && (s->sc_vers == vers))
-			goto done;
-		p = s;
-	}
-  done:
-	*prev = p;
-	return (s);
+  if ((s = svc_find (prog, vers, &prev)) == NULL_SVC)
+    return;
+
+  if (prev == NULL_SVC)
+    svc_head = s->sc_next;
+  else
+    prev->sc_next = s->sc_next;
+
+  s->sc_next = NULL_SVC;
+  mem_free ((char *) s, (u_int) sizeof (struct svc_callout));
+  /* now unregister the information with the local binder service */
+  pmap_unset (prog, vers);
 }
 
 /* ******************* REPLY GENERATION ROUTINES  ************ */
 
-/*
- * Send a reply to an rpc request
- */
-bool_t svc_sendreply(xprt, xdr_results, xdr_location)
-register SVCXPRT *xprt;
-xdrproc_t xdr_results;
-caddr_t xdr_location;
+/* Send a reply to an rpc request */
+bool_t
+svc_sendreply (register SVCXPRT *xprt, xdrproc_t xdr_results,
+	       caddr_t xdr_location)
 {
-	struct rpc_msg rply;
-
-	rply.rm_direction = REPLY;
-	rply.rm_reply.rp_stat = MSG_ACCEPTED;
-	rply.acpted_rply.ar_verf = xprt->xp_verf;
-	rply.acpted_rply.ar_stat = SUCCESS;
-	rply.acpted_rply.ar_results.where = xdr_location;
-	rply.acpted_rply.ar_results.proc = xdr_results;
-	return (SVC_REPLY(xprt, &rply));
+  struct rpc_msg rply;
+
+  rply.rm_direction = REPLY;
+  rply.rm_reply.rp_stat = MSG_ACCEPTED;
+  rply.acpted_rply.ar_verf = xprt->xp_verf;
+  rply.acpted_rply.ar_stat = SUCCESS;
+  rply.acpted_rply.ar_results.where = xdr_location;
+  rply.acpted_rply.ar_results.proc = xdr_results;
+  return SVC_REPLY (xprt, &rply);
 }
 
-/*
- * No procedure error reply
- */
-void svcerr_noproc(xprt)
-register SVCXPRT *xprt;
+/* No procedure error reply */
+void
+svcerr_noproc (register SVCXPRT *xprt)
 {
-	struct rpc_msg rply;
+  struct rpc_msg rply;
 
-	rply.rm_direction = REPLY;
-	rply.rm_reply.rp_stat = MSG_ACCEPTED;
-	rply.acpted_rply.ar_verf = xprt->xp_verf;
-	rply.acpted_rply.ar_stat = PROC_UNAVAIL;
-	SVC_REPLY(xprt, &rply);
+  rply.rm_direction = REPLY;
+  rply.rm_reply.rp_stat = MSG_ACCEPTED;
+  rply.acpted_rply.ar_verf = xprt->xp_verf;
+  rply.acpted_rply.ar_stat = PROC_UNAVAIL;
+  SVC_REPLY (xprt, &rply);
 }
 
-/*
- * Can't decode args error reply
- */
-void svcerr_decode(xprt)
-register SVCXPRT *xprt;
+/* Can't decode args error reply */
+void
+svcerr_decode (register SVCXPRT *xprt)
 {
-	struct rpc_msg rply;
+  struct rpc_msg rply;
 
-	rply.rm_direction = REPLY;
-	rply.rm_reply.rp_stat = MSG_ACCEPTED;
-	rply.acpted_rply.ar_verf = xprt->xp_verf;
-	rply.acpted_rply.ar_stat = GARBAGE_ARGS;
-	SVC_REPLY(xprt, &rply);
+  rply.rm_direction = REPLY;
+  rply.rm_reply.rp_stat = MSG_ACCEPTED;
+  rply.acpted_rply.ar_verf = xprt->xp_verf;
+  rply.acpted_rply.ar_stat = GARBAGE_ARGS;
+  SVC_REPLY (xprt, &rply);
 }
 
-/*
- * Some system error
- */
-void svcerr_systemerr(xprt)
-register SVCXPRT *xprt;
+/* Some system error */
+void
+svcerr_systemerr (register SVCXPRT *xprt)
 {
-	struct rpc_msg rply;
+  struct rpc_msg rply;
 
-	rply.rm_direction = REPLY;
-	rply.rm_reply.rp_stat = MSG_ACCEPTED;
-	rply.acpted_rply.ar_verf = xprt->xp_verf;
-	rply.acpted_rply.ar_stat = SYSTEM_ERR;
-	SVC_REPLY(xprt, &rply);
+  rply.rm_direction = REPLY;
+  rply.rm_reply.rp_stat = MSG_ACCEPTED;
+  rply.acpted_rply.ar_verf = xprt->xp_verf;
+  rply.acpted_rply.ar_stat = SYSTEM_ERR;
+  SVC_REPLY (xprt, &rply);
 }
 
-/*
- * Authentication error reply
- */
-void svcerr_auth(xprt, why)
-SVCXPRT *xprt;
-enum auth_stat why;
+/* Authentication error reply */
+void
+svcerr_auth (SVCXPRT *xprt, enum auth_stat why)
 {
-	struct rpc_msg rply;
+  struct rpc_msg rply;
 
-	rply.rm_direction = REPLY;
-	rply.rm_reply.rp_stat = MSG_DENIED;
-	rply.rjcted_rply.rj_stat = AUTH_ERROR;
-	rply.rjcted_rply.rj_why = why;
-	SVC_REPLY(xprt, &rply);
+  rply.rm_direction = REPLY;
+  rply.rm_reply.rp_stat = MSG_DENIED;
+  rply.rjcted_rply.rj_stat = AUTH_ERROR;
+  rply.rjcted_rply.rj_why = why;
+  SVC_REPLY (xprt, &rply);
 }
 
-/*
- * Auth too weak error reply
- */
-void svcerr_weakauth(xprt)
-SVCXPRT *xprt;
+/* Auth too weak error reply */
+void
+svcerr_weakauth (SVCXPRT *xprt)
 {
-
-	svcerr_auth(xprt, AUTH_TOOWEAK);
+  svcerr_auth (xprt, AUTH_TOOWEAK);
 }
 
-/*
- * Program unavailable error reply
- */
-void svcerr_noprog(xprt)
-register SVCXPRT *xprt;
+/* Program unavailable error reply */
+void
+svcerr_noprog (register SVCXPRT *xprt)
 {
-	struct rpc_msg rply;
+  struct rpc_msg rply;
 
-	rply.rm_direction = REPLY;
-	rply.rm_reply.rp_stat = MSG_ACCEPTED;
-	rply.acpted_rply.ar_verf = xprt->xp_verf;
-	rply.acpted_rply.ar_stat = PROG_UNAVAIL;
-	SVC_REPLY(xprt, &rply);
+  rply.rm_direction = REPLY;
+  rply.rm_reply.rp_stat = MSG_ACCEPTED;
+  rply.acpted_rply.ar_verf = xprt->xp_verf;
+  rply.acpted_rply.ar_stat = PROG_UNAVAIL;
+  SVC_REPLY (xprt, &rply);
 }
 
-/*
- * Program version mismatch error reply
- */
-void svcerr_progvers(xprt, low_vers, high_vers)
-register SVCXPRT *xprt;
-u_long low_vers;
-u_long high_vers;
+/* Program version mismatch error reply */
+void
+svcerr_progvers (register SVCXPRT *xprt, rpcvers_t low_vers,
+		 rpcvers_t high_vers)
 {
-	struct rpc_msg rply;
-
-	rply.rm_direction = REPLY;
-	rply.rm_reply.rp_stat = MSG_ACCEPTED;
-	rply.acpted_rply.ar_verf = xprt->xp_verf;
-	rply.acpted_rply.ar_stat = PROG_MISMATCH;
-	rply.acpted_rply.ar_vers.low = low_vers;
-	rply.acpted_rply.ar_vers.high = high_vers;
-	SVC_REPLY(xprt, &rply);
+  struct rpc_msg rply;
+
+  rply.rm_direction = REPLY;
+  rply.rm_reply.rp_stat = MSG_ACCEPTED;
+  rply.acpted_rply.ar_verf = xprt->xp_verf;
+  rply.acpted_rply.ar_stat = PROG_MISMATCH;
+  rply.acpted_rply.ar_vers.low = low_vers;
+  rply.acpted_rply.ar_vers.high = high_vers;
+  SVC_REPLY (xprt, &rply);
 }
 
 /* ******************* SERVER INPUT STUFF ******************* */
@@ -345,132 +330,163 @@ u_long high_vers;
  * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
  * the "cooked" credentials (rqst->rq_clntcred).
  * However, this function does not know the structure of the cooked
- * credentials, so it make the following assumptions: 
+ * credentials, so it make the following assumptions:
  *   a) the structure is contiguous (no pointers), and
- *   b) the cred structure size does not exceed RQCRED_SIZE bytes. 
+ *   b) the cred structure size does not exceed RQCRED_SIZE bytes.
  * In all events, all three parameters are freed upon exit from this routine.
  * The storage is trivially management on the call stack in user land, but
  * is mallocated in kernel land.
  */
 
-void svc_getreq(rdfds)
-int rdfds;
+void
+svc_getreq (int rdfds)
 {
-#ifdef FD_SETSIZE
-	fd_set readfds;
+  fd_set readfds;
 
-	FD_ZERO(&readfds);
-/*#ifdef __linux__*/
-#if 0
-	readfds = rdfds;
-#else
-	readfds.fds_bits[0] = rdfds;
-#endif
-	svc_getreqset(&readfds);
-#else
-	int readfds = rdfds & svc_fds;
+  FD_ZERO (&readfds);
+  readfds.fds_bits[0] = rdfds;
+  svc_getreqset (&readfds);
+}
 
-	svc_getreqset(&readfds);
-#endif							/* def FD_SETSIZE */
+void
+svc_getreqset (fd_set *readfds)
+{
+  register u_int32_t mask;
+  register u_int32_t *maskp;
+  register int setsize;
+  register int sock;
+  register int bit;
+
+  setsize = _rpc_dtablesize ();
+  maskp = (u_int32_t *) readfds->fds_bits;
+  for (sock = 0; sock < setsize; sock += 32)
+    for (mask = *maskp++; (bit = ffs (mask)); mask ^= (1 << (bit - 1)))
+      svc_getreq_common (sock + bit - 1);
 }
 
-void svc_getreqset(readfds)
-#ifdef FD_SETSIZE
-fd_set *readfds;
+void
+svc_getreq_poll (struct pollfd *pfdp, int pollretval)
 {
-#else
-int *readfds;
+  register int i;
+  register int fds_found;
+
+  for (i = fds_found = 0; i < svc_max_pollfd && fds_found < pollretval; ++i)
+    {
+      register struct pollfd *p = &pfdp[i];
+
+      if (p->fd != -1 && p->revents)
+	{
+	  /* fd has input waiting */
+	  ++fds_found;
+
+	  if (p->revents & POLLNVAL)
+	    xprt_unregister (xports[p->fd]);
+	  else
+	    svc_getreq_common (p->fd);
+	}
+    }
+}
+
+
+void
+svc_getreq_common (const int fd)
 {
-	int readfds_local = *readfds;
-#endif							/* def FD_SETSIZE */
-	enum xprt_stat stat;
-	struct rpc_msg msg;
-	int prog_found;
-	u_long low_vers;
-	u_long high_vers;
-	struct svc_req r;
-	register SVCXPRT *xprt;
-	register u_long mask;
-	register int bit;
-	register u_long *maskp;
-	register int setsize;
-	register int sock;
-	char cred_area[2 * MAX_AUTH_BYTES + RQCRED_SIZE];
-
-	msg.rm_call.cb_cred.oa_base = cred_area;
-	msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
-	r.rq_clntcred = &(cred_area[2 * MAX_AUTH_BYTES]);
-
-
-#ifdef FD_SETSIZE
-	setsize = _rpc_dtablesize();
-#ifdef __linux__
-/*#define NFDBITS	32*/
-	maskp = (u_long *) readfds;
-#else
-	maskp = (u_long *) readfds->fds_bits;
-#endif
-	for (sock = 0; sock < setsize; sock += NFDBITS) {
-		for (mask = *maskp++; (bit = ffs(mask)); mask ^= (1 << (bit - 1))) {
-			/* sock has input waiting */
-			xprt = xports[sock + bit - 1];
-#else
-	for (sock = 0; readfds_local != 0; sock++, readfds_local >>= 1) {
-		if ((readfds_local & 1) != 0) {
-			/* sock has input waiting */
-			xprt = xports[sock];
-#endif							/* def FD_SETSIZE */
-			/* now receive msgs from xprtprt (support batch calls) */
-			do {
-				if (SVC_RECV(xprt, &msg)) {
-
-					/* now find the exported program and call it */
-					register struct svc_callout *s;
-					enum auth_stat why;
-
-					r.rq_xprt = xprt;
-					r.rq_prog = msg.rm_call.cb_prog;
-					r.rq_vers = msg.rm_call.cb_vers;
-					r.rq_proc = msg.rm_call.cb_proc;
-					r.rq_cred = msg.rm_call.cb_cred;
-					/* first authenticate the message */
-					if ((why = _authenticate(&r, &msg)) != AUTH_OK) {
-						svcerr_auth(xprt, why);
-						goto call_done;
-					}
-					/* now match message with a registered service */
-					prog_found = FALSE;
-					low_vers = 0 - 1;
-					high_vers = 0;
-					for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
-						if (s->sc_prog == r.rq_prog) {
-							if (s->sc_vers == r.rq_vers) {
-								(*s->sc_dispatch) (&r, xprt);
-								goto call_done;
-							}	/* found correct version */
-							prog_found = TRUE;
-							if (s->sc_vers < low_vers)
-								low_vers = s->sc_vers;
-							if (s->sc_vers > high_vers)
-								high_vers = s->sc_vers;
-						}		/* found correct program */
-					}
-					/*
-					 * if we got here, the program or version
-					 * is not served ...
-					 */
-					if (prog_found)
-						svcerr_progvers(xprt, low_vers, high_vers);
-					else
-						svcerr_noprog(xprt);
-					/* Fall through to ... */
-				}
-			  call_done:
-				if ((stat = SVC_STAT(xprt)) == XPRT_DIED) {
-					SVC_DESTROY(xprt);
-					break;
-				}
-			} while (stat == XPRT_MOREREQS);
+  enum xprt_stat stat;
+  struct rpc_msg msg;
+  register SVCXPRT *xprt;
+  char cred_area[2 * MAX_AUTH_BYTES + RQCRED_SIZE];
+  msg.rm_call.cb_cred.oa_base = cred_area;
+  msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
+
+  xprt = xports[fd];
+  /* Do we control fd? */
+  if (xprt == NULL)
+     return;
+
+  /* now receive msgs from xprtprt (support batch calls) */
+  do
+    {
+      if (SVC_RECV (xprt, &msg))
+	{
+	  /* now find the exported program and call it */
+	  struct svc_callout *s;
+	  struct svc_req r;
+	  enum auth_stat why;
+	  rpcvers_t low_vers;
+	  rpcvers_t high_vers;
+	  int prog_found;
+
+	  r.rq_clntcred = &(cred_area[2 * MAX_AUTH_BYTES]);
+	  r.rq_xprt = xprt;
+	  r.rq_prog = msg.rm_call.cb_prog;
+	  r.rq_vers = msg.rm_call.cb_vers;
+	  r.rq_proc = msg.rm_call.cb_proc;
+	  r.rq_cred = msg.rm_call.cb_cred;
+
+	  /* first authenticate the message */
+	  /* Check for null flavor and bypass these calls if possible */
+
+	  if (msg.rm_call.cb_cred.oa_flavor == AUTH_NULL)
+	    {
+	      r.rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
+	      r.rq_xprt->xp_verf.oa_length = 0;
+	    }
+	  else if ((why = _authenticate (&r, &msg)) != AUTH_OK)
+	    {
+	      svcerr_auth (xprt, why);
+	      goto call_done;
+	    }
+
+	  /* now match message with a registered service */
+	  prog_found = FALSE;
+	  low_vers = 0 - 1;
+	  high_vers = 0;
+
+	  for (s = svc_head; s != NULL_SVC; s = s->sc_next)
+	    {
+	      if (s->sc_prog == r.rq_prog)
+		{
+		  if (s->sc_vers == r.rq_vers)
+		    {
+		      (*s->sc_dispatch) (&r, xprt);
+		      goto call_done;
+		    }
+		  /* found correct version */
+		  prog_found = TRUE;
+		  if (s->sc_vers < low_vers)
+		    low_vers = s->sc_vers;
+		  if (s->sc_vers > high_vers)
+		    high_vers = s->sc_vers;
 		}
+	      /* found correct program */
+	    }
+	  /* if we got here, the program or version
+	     is not served ... */
+	  if (prog_found)
+	    svcerr_progvers (xprt, low_vers, high_vers);
+	  else
+	    svcerr_noprog (xprt);
+	  /* Fall through to ... */
+	}
+    call_done:
+      if ((stat = SVC_STAT (xprt)) == XPRT_DIED)
+	{
+	  SVC_DESTROY (xprt);
+	  break;
 	}
+    }
+  while (stat == XPRT_MOREREQS);
 }
+
+#ifdef _RPC_THREAD_SAFE_
+
+void
+__rpc_thread_svc_cleanup (void)
+{
+  struct svc_callout *svcp;
+
+  while ((svcp = svc_head) != NULL)
+    svc_unregister (svcp->sc_prog, svcp->sc_vers);
+}
+
+#endif /* _RPC_THREAD_SAFE_ */

+ 55 - 44
libc/inet/rpc/svc_auth.c

@@ -1,5 +1,4 @@
-#define __FORCE_GLIBC
-#include <features.h>
+/* @(#)svc_auth.c       2.4 88/08/15 4.0 RPCSRC */
 /*
  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  * unrestricted use provided that this legend is included on all tape
@@ -7,11 +6,11 @@
  * 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.
@@ -28,44 +27,60 @@
  * 2550 Garcia Avenue
  * Mountain View, California  94043
  */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_auth.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+#endif
 
 /*
- * svc_auth_nodes.c, Server-side rpc authenticator interface,
- * *WITHOUT* DES authentication.
+ * svc_auth.c, Server-side rpc authenticator interface.
  *
  * Copyright (C) 1984, Sun Microsystems, Inc.
  */
 
 #include <rpc/rpc.h>
+#include <rpc/svc.h>
+#include <rpc/svc_auth.h>
 
 /*
- * svcauthsw is the bdevsw of server side authentication. 
- * 
+ * svcauthsw is the bdevsw of server side authentication.
+ *
  * Server side authenticators are called from authenticate by
  * using the client auth struct flavor field to index into svcauthsw.
- * The server auth flavors must implement a routine that looks  
- * like: 
- * 
- *	enum auth_stat
- *	flavorx_auth(rqst, msg)
- *		register struct svc_req *rqst; 
- *		register struct rpc_msg *msg;
+ * The server auth flavors must implement a routine that looks
+ * like:
+ *
+ *      enum auth_stat
+ *      flavorx_auth(rqst, msg)
+ *              register struct svc_req *rqst;
+ *              register struct rpc_msg *msg;
  *
  */
 
-enum auth_stat _svcauth_null();	/* no authentication */
-enum auth_stat _svcauth_unix();	/* unix style (uid, gids) */
-enum auth_stat _svcauth_short();	/* short hand unix style */
+static enum auth_stat _svcauth_null (struct svc_req *, struct rpc_msg *);
+				/* no authentication */
+extern enum auth_stat _svcauth_unix (struct svc_req *, struct rpc_msg *);
+				/* unix style (uid, gids) */
+extern enum auth_stat _svcauth_short (struct svc_req *, struct rpc_msg *);
+				/* short hand unix style */
+#ifdef CONFIG_AUTH_DES
+extern enum auth_stat _svcauth_des (struct svc_req *, struct rpc_msg *);
+				/* des style */
+#endif
 
-static struct {
-	enum auth_stat (*authenticator) ();
-} svcauthsw[] = {
-	{_svcauth_null},				/* AUTH_NULL */
-	{_svcauth_unix},				/* AUTH_UNIX */
-	{_svcauth_short},				/* AUTH_SHORT */
+static const struct
+  {
+    enum auth_stat (*authenticator) (struct svc_req *, struct rpc_msg *);
+  }
+svcauthsw[] =
+{
+  { _svcauth_null },		/* AUTH_NULL */
+  { _svcauth_unix },		/* AUTH_UNIX */
+  { _svcauth_short },		/* AUTH_SHORT */
+#ifdef CONFIG_AUTH_DES
+  { _svcauth_des }		/* AUTH_DES */
+#endif
 };
-
-#define	AUTH_MAX	2			/* HIGHEST AUTH NUMBER */
+#define	AUTH_MAX	3	/* HIGHEST AUTH NUMBER */
 
 
 /*
@@ -76,7 +91,7 @@ static struct {
  * set rqst->rq_xprt->verf to the appropriate response verifier;
  * sets rqst->rq_client_cred to the "cooked" form of the credentials.
  *
- * NB: rqst->rq_cxprt->verf must be pre-alloctaed;
+ * NB: rqst->rq_cxprt->verf must be pre-allocated;
  * its length is set appropriately.
  *
  * The caller still owns and is responsible for msg->u.cmb.cred and
@@ -86,27 +101,23 @@ static struct {
  * There is an assumption that any flavour less than AUTH_NULL is
  * invalid.
  */
-enum auth_stat _authenticate(rqst, msg)
-register struct svc_req *rqst;
-struct rpc_msg *msg;
+enum auth_stat
+_authenticate (register struct svc_req *rqst, struct rpc_msg *msg)
 {
-	register int cred_flavor;
+  register int cred_flavor;
 
-	rqst->rq_cred = msg->rm_call.cb_cred;
-	rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
-	rqst->rq_xprt->xp_verf.oa_length = 0;
-	cred_flavor = rqst->rq_cred.oa_flavor;
-	if ((cred_flavor <= AUTH_MAX) && (cred_flavor >= AUTH_NULL)) {
-		return ((*(svcauthsw[cred_flavor].authenticator)) (rqst, msg));
-	}
+  rqst->rq_cred = msg->rm_call.cb_cred;
+  rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
+  rqst->rq_xprt->xp_verf.oa_length = 0;
+  cred_flavor = rqst->rq_cred.oa_flavor;
+  if ((cred_flavor <= AUTH_MAX) && (cred_flavor >= AUTH_NULL))
+    return (*(svcauthsw[cred_flavor].authenticator)) (rqst, msg);
 
-	return (AUTH_REJECTEDCRED);
+  return AUTH_REJECTEDCRED;
 }
 
-enum auth_stat _svcauth_null( /*rqst, msg */ )
-	/*struct svc_req *rqst;
-	   struct rpc_msg *msg; */
+static enum auth_stat
+_svcauth_null (struct svc_req *rqst, struct rpc_msg *msg)
 {
-
-	return (AUTH_OK);
+  return AUTH_OK;
 }

+ 102 - 79
libc/inet/rpc/svc_auth_unix.c

@@ -1,4 +1,3 @@
-/* @(#)svc_auth_unix.c	2.3 88/08/01 4.0 RPCSRC; from 1.28 88/02/08 SMI */
 /*
  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  * unrestricted use provided that this legend is included on all tape
@@ -6,29 +5,27 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
 
 /*
  * svc_auth_unix.c
@@ -41,82 +38,108 @@
  * Copyright (C) 1984, Sun Microsystems, Inc.
  */
 
+#define __FORCE_GLIBC
+#define _GNU_SOURCE
+#include <features.h>
+
 #include <stdio.h>
+#include <string.h>
 #include <rpc/rpc.h>
+#include <rpc/svc.h>
 
 /*
  * Unix longhand authenticator
  */
-enum auth_stat _svcauth_unix(rqst, msg)
-register struct svc_req *rqst;
-register struct rpc_msg *msg;
+enum auth_stat
+_svcauth_unix (struct svc_req *rqst, struct rpc_msg *msg)
 {
-	register enum auth_stat stat;
-	XDR xdrs;
-	register struct authunix_parms *aup;
-	register long *buf;
-	struct area {
-		struct authunix_parms area_aup;
-		char area_machname[MAX_MACHINE_NAME + 1];
-		int area_gids[NGRPS];
-	} *area;
-	u_int auth_len;
-	int str_len, gid_len;
-	register int i;
+  enum auth_stat stat;
+  XDR xdrs;
+  struct authunix_parms *aup;
+  int32_t *buf;
+  struct area
+    {
+      struct authunix_parms area_aup;
+      char area_machname[MAX_MACHINE_NAME + 1];
+      gid_t area_gids[NGRPS];
+    }
+   *area;
+  u_int auth_len;
+  u_int str_len, gid_len;
+  u_int i;
 
-	area = (struct area *) rqst->rq_clntcred;
-	aup = &area->area_aup;
-	aup->aup_machname = area->area_machname;
-	aup->aup_gids = area->area_gids;
-	auth_len = (u_int) msg->rm_call.cb_cred.oa_length;
-	xdrmem_create(&xdrs, msg->rm_call.cb_cred.oa_base, auth_len,
-				  XDR_DECODE);
-	buf = (long *)XDR_INLINE(&xdrs, auth_len);
-	if (buf != NULL) {
-		aup->aup_time = IXDR_GET_LONG(buf);
-		str_len = IXDR_GET_U_LONG(buf);
-		if (str_len > MAX_MACHINE_NAME) {
-			stat = AUTH_BADCRED;
-			goto done;
-		}
-		bcopy((caddr_t) buf, aup->aup_machname, (u_int) str_len);
-		aup->aup_machname[str_len] = 0;
-		str_len = RNDUP(str_len);
-		buf += str_len / sizeof(long);
-
-		aup->aup_uid = IXDR_GET_LONG(buf);
-		aup->aup_gid = IXDR_GET_LONG(buf);
-		gid_len = IXDR_GET_U_LONG(buf);
-		if (gid_len > NGRPS) {
-			stat = AUTH_BADCRED;
-			goto done;
-		}
-		aup->aup_len = gid_len;
-		for (i = 0; i < gid_len; i++) {
-			aup->aup_gids[i] = IXDR_GET_LONG(buf);
-		}
-		/*
-		 * five is the smallest unix credentials structure -
-		 * timestamp, hostname len (0), uid, gid, and gids len (0).
-		 */
-		if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) {
-			(void) printf("bad auth_len gid %d str %d auth %d\n",
-						  gid_len, str_len, auth_len);
-			stat = AUTH_BADCRED;
-			goto done;
-		}
-	} else if (!xdr_authunix_parms(&xdrs, aup)) {
-		xdrs.x_op = XDR_FREE;
-		(void) xdr_authunix_parms(&xdrs, aup);
-		stat = AUTH_BADCRED;
-		goto done;
+  area = (struct area *) rqst->rq_clntcred;
+  aup = &area->area_aup;
+  aup->aup_machname = area->area_machname;
+  aup->aup_gids = area->area_gids;
+  auth_len = (u_int) msg->rm_call.cb_cred.oa_length;
+  xdrmem_create (&xdrs, msg->rm_call.cb_cred.oa_base, auth_len, XDR_DECODE);
+  buf = XDR_INLINE (&xdrs, auth_len);
+  if (buf != NULL)
+    {
+      aup->aup_time = IXDR_GET_LONG (buf);
+      str_len = IXDR_GET_U_INT32 (buf);
+      if (str_len > MAX_MACHINE_NAME)
+	{
+	  stat = AUTH_BADCRED;
+	  goto done;
+	}
+      memcpy (aup->aup_machname, (caddr_t) buf, (u_int) str_len);
+      aup->aup_machname[str_len] = 0;
+      str_len = RNDUP (str_len);
+      buf = (int32_t *) ((char *) buf + str_len);
+      aup->aup_uid = IXDR_GET_LONG (buf);
+      aup->aup_gid = IXDR_GET_LONG (buf);
+      gid_len = IXDR_GET_U_INT32 (buf);
+      if (gid_len > NGRPS)
+	{
+	  stat = AUTH_BADCRED;
+	  goto done;
 	}
-	rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL;
-	rqst->rq_xprt->xp_verf.oa_length = 0;
-	stat = AUTH_OK;
-  done:
-	XDR_DESTROY(&xdrs);
-	return (stat);
+      aup->aup_len = gid_len;
+      for (i = 0; i < gid_len; i++)
+	{
+	  aup->aup_gids[i] = IXDR_GET_LONG (buf);
+	}
+      /*
+       * five is the smallest unix credentials structure -
+       * timestamp, hostname len (0), uid, gid, and gids len (0).
+       */
+      if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len)
+	{
+	  (void) printf ("bad auth_len gid %d str %d auth %d\n",
+			 gid_len, str_len, auth_len);
+	  stat = AUTH_BADCRED;
+	  goto done;
+	}
+    }
+  else if (!xdr_authunix_parms (&xdrs, aup))
+    {
+      xdrs.x_op = XDR_FREE;
+      (void) xdr_authunix_parms (&xdrs, aup);
+      stat = AUTH_BADCRED;
+      goto done;
+    }
+
+  /* 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);
+  return stat;
 }
 
 
@@ -124,9 +147,9 @@ register struct rpc_msg *msg;
  * Shorthand unix authenticator
  * Looks up longhand in a cache.
  */
- /*ARGSUSED*/ enum auth_stat _svcauth_short(rqst, msg)
-struct svc_req *rqst;
-struct rpc_msg *msg;
+/*ARGSUSED */
+enum auth_stat
+_svcauth_short (struct svc_req *rqst, struct rpc_msg *msg)
 {
-	return (AUTH_REJECTEDCRED);
+  return AUTH_REJECTEDCRED;
 }

+ 105 - 98
libc/inet/rpc/svc_raw.c

@@ -6,153 +6,160 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_raw.c 1.15 87/08/11 Copyr 1984 Sun Micro";
+#endif
 
 /*
  * svc_raw.c,   This a toy for simple testing and timing.
  * Interface to create an rpc client and server in the same UNIX process.
- * This lets us similate rpc and get rpc (round trip) overhead, without
- * any interference from the kernal.
+ * This lets us simulate rpc and get rpc (round trip) overhead, without
+ * any interference from the kernel.
  *
  * Copyright (C) 1984, Sun Microsystems, Inc.
  */
 
 #include <rpc/rpc.h>
-
+#include <rpc/svc.h>
 
 /*
  * This is the "network" that we will be moving data over
  */
-static struct svcraw_private {
-	char _raw_buf[UDPMSGSIZE];
-	SVCXPRT server;
-	XDR xdr_stream;
-	char verf_body[MAX_AUTH_BYTES];
-} *svcraw_private;
-
-static bool_t svcraw_recv();
-static enum xprt_stat svcraw_stat();
-static bool_t svcraw_getargs();
-static bool_t svcraw_reply();
-static bool_t svcraw_freeargs();
-static void svcraw_destroy();
-
-static struct xp_ops server_ops = {
-	svcraw_recv,
-	svcraw_stat,
-	svcraw_getargs,
-	svcraw_reply,
-	svcraw_freeargs,
-	svcraw_destroy
+struct svcraw_private_s
+  {
+    char _raw_buf[UDPMSGSIZE];
+    SVCXPRT server;
+    XDR xdr_stream;
+    char verf_body[MAX_AUTH_BYTES];
+  };
+#ifdef _RPC_THREAD_SAFE_
+#define svcraw_private ((struct svcraw_private_s *)RPC_THREAD_VARIABLE(svcraw_private_s))
+#else
+static struct svcraw_private_s *svcraw_private;
+#endif
+
+static bool_t svcraw_recv (SVCXPRT *, struct rpc_msg *);
+static enum xprt_stat svcraw_stat (SVCXPRT *);
+static bool_t svcraw_getargs (SVCXPRT *, xdrproc_t, caddr_t);
+static bool_t svcraw_reply (SVCXPRT *, struct rpc_msg *);
+static bool_t svcraw_freeargs (SVCXPRT *, xdrproc_t, caddr_t);
+static void svcraw_destroy (SVCXPRT *);
+
+static struct xp_ops server_ops =
+{
+  svcraw_recv,
+  svcraw_stat,
+  svcraw_getargs,
+  svcraw_reply,
+  svcraw_freeargs,
+  svcraw_destroy
 };
 
-SVCXPRT *svcraw_create()
+SVCXPRT *
+svcraw_create (void)
 {
-	register struct svcraw_private *srp = svcraw_private;
-
-	if (srp == 0) {
-		srp = (struct svcraw_private *) calloc(1, sizeof(*srp));
-		if (srp == 0)
-			return (0);
-	}
-	srp->server.xp_sock = 0;
-	srp->server.xp_port = 0;
-	srp->server.xp_ops = &server_ops;
-	srp->server.xp_verf.oa_base = srp->verf_body;
-	xdrmem_create(&srp->xdr_stream, srp->_raw_buf, UDPMSGSIZE, XDR_FREE);
-	return (&srp->server);
+  struct svcraw_private_s *srp = svcraw_private;
+
+  if (srp == 0)
+    {
+      srp = (struct svcraw_private_s *) calloc (1, sizeof (*srp));
+      if (srp == 0)
+	return NULL;
+    }
+  srp->server.xp_sock = 0;
+  srp->server.xp_port = 0;
+  srp->server.xp_ops = &server_ops;
+  srp->server.xp_verf.oa_base = srp->verf_body;
+  xdrmem_create (&srp->xdr_stream, srp->_raw_buf, UDPMSGSIZE, XDR_FREE);
+  return &srp->server;
 }
 
-static enum xprt_stat svcraw_stat()
+static enum xprt_stat
+svcraw_stat (SVCXPRT *xprt)
 {
-
-	return (XPRT_IDLE);
+  return XPRT_IDLE;
 }
 
-static bool_t svcraw_recv(xprt, msg)
-SVCXPRT *xprt;
-struct rpc_msg *msg;
+static bool_t
+svcraw_recv (xprt, msg)
+     SVCXPRT *xprt;
+     struct rpc_msg *msg;
 {
-	register struct svcraw_private *srp = svcraw_private;
-	register XDR *xdrs;
-
-	if (srp == 0)
-		return (0);
-	xdrs = &srp->xdr_stream;
-	xdrs->x_op = XDR_DECODE;
-	XDR_SETPOS(xdrs, 0);
-	if (!xdr_callmsg(xdrs, msg))
-		return (FALSE);
-	return (TRUE);
+  struct svcraw_private_s *srp = svcraw_private;
+  XDR *xdrs;
+
+  if (srp == 0)
+    return FALSE;
+  xdrs = &srp->xdr_stream;
+  xdrs->x_op = XDR_DECODE;
+  XDR_SETPOS (xdrs, 0);
+  if (!xdr_callmsg (xdrs, msg))
+    return FALSE;
+  return TRUE;
 }
 
-static bool_t svcraw_reply(xprt, msg)
-SVCXPRT *xprt;
-struct rpc_msg *msg;
+static bool_t
+svcraw_reply (SVCXPRT *xprt, struct rpc_msg *msg)
 {
-	register struct svcraw_private *srp = svcraw_private;
-	register XDR *xdrs;
-
-	if (srp == 0)
-		return (FALSE);
-	xdrs = &srp->xdr_stream;
-	xdrs->x_op = XDR_ENCODE;
-	XDR_SETPOS(xdrs, 0);
-	if (!xdr_replymsg(xdrs, msg))
-		return (FALSE);
-	(void) XDR_GETPOS(xdrs);	/* called just for overhead */
-	return (TRUE);
+  struct svcraw_private_s *srp = svcraw_private;
+  XDR *xdrs;
+
+  if (srp == 0)
+    return FALSE;
+  xdrs = &srp->xdr_stream;
+  xdrs->x_op = XDR_ENCODE;
+  XDR_SETPOS (xdrs, 0);
+  if (!xdr_replymsg (xdrs, msg))
+    return FALSE;
+  (void) XDR_GETPOS (xdrs);	/* called just for overhead */
+  return TRUE;
 }
 
-static bool_t svcraw_getargs(xprt, xdr_args, args_ptr)
-SVCXPRT *xprt;
-xdrproc_t xdr_args;
-caddr_t args_ptr;
+static bool_t
+svcraw_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
 {
-	register struct svcraw_private *srp = svcraw_private;
+  struct svcraw_private_s *srp = svcraw_private;
 
-	if (srp == 0)
-		return (FALSE);
-	return ((*xdr_args) (&srp->xdr_stream, args_ptr));
+  if (srp == 0)
+    return FALSE;
+  return (*xdr_args) (&srp->xdr_stream, args_ptr);
 }
 
-static bool_t svcraw_freeargs(xprt, xdr_args, args_ptr)
-SVCXPRT *xprt;
-xdrproc_t xdr_args;
-caddr_t args_ptr;
+static bool_t
+svcraw_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
 {
-	register struct svcraw_private *srp = svcraw_private;
-	register XDR *xdrs;
-
-	if (srp == 0)
-		return (FALSE);
-	xdrs = &srp->xdr_stream;
-	xdrs->x_op = XDR_FREE;
-	return ((*xdr_args) (xdrs, args_ptr));
+  struct svcraw_private_s *srp = svcraw_private;
+  XDR *xdrs;
+
+  if (srp == 0)
+    return FALSE;
+  xdrs = &srp->xdr_stream;
+  xdrs->x_op = XDR_FREE;
+  return (*xdr_args) (xdrs, args_ptr);
 }
 
-static void svcraw_destroy()
+static void
+svcraw_destroy (SVCXPRT *xprt)
 {
 }

+ 56 - 37
libc/inet/rpc/svc_run.c

@@ -1,7 +1,3 @@
-/* @(#)svc_run.c	2.1 88/07/29 4.0 RPCSRC */
-#define __FORCE_GLIBC
-#include <features.h>
-
 /*
  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  * unrestricted use provided that this legend is included on all tape
@@ -9,62 +5,85 @@
  * 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
  */
-
 /*
  * This is the rpc server side idle loop
  * Wait for input, call server program.
  */
+
+#define __FORCE_GLIBC
+#define _GNU_SOURCE
+#include <features.h>
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/poll.h>
 #include <rpc/rpc.h>
-#include <sys/errno.h>
 
-void svc_run()
+/* This function can be used as a signal handler to terminate the
+   server loop.  */
+void
+svc_exit (void)
 {
-#ifdef FD_SETSIZE
-	fd_set readfds;
-#else
-	int readfds;
-#endif							/* def FD_SETSIZE */
-	extern int errno;
+  free (svc_pollfd);
+  svc_pollfd = NULL;
+  svc_max_pollfd = 0;
+}
+
+void
+svc_run (void)
+{
+  int i;
+
+  for (;;)
+    {
+      struct pollfd *my_pollfd;
+
+      if (svc_max_pollfd == 0 && svc_pollfd == NULL)
+	return;
+
+      my_pollfd = malloc (sizeof (struct pollfd) * svc_max_pollfd);
+      for (i = 0; i < svc_max_pollfd; ++i)
+	{
+	  my_pollfd[i].fd = svc_pollfd[i].fd;
+	  my_pollfd[i].events = svc_pollfd[i].events;
+	  my_pollfd[i].revents = 0;
+	}
 
-	for (;;) {
-#ifdef FD_SETSIZE
-		readfds = svc_fdset;
-#else
-		readfds = svc_fds;
-#endif							/* def FD_SETSIZE */
-		switch (select(_rpc_dtablesize(), &readfds, NULL, NULL,
-					   (struct timeval *) 0)) {
-		case -1:
-			if (errno == EINTR) {
-				continue;
-			}
-			perror("svc_run: - select failed");
-			return;
-		case 0:
-			continue;
-		default:
-			svc_getreqset(&readfds);
-		}
+      switch (i = poll (my_pollfd, svc_max_pollfd, -1))
+	{
+	case -1:
+	  free (my_pollfd);
+	  if (errno == EINTR)
+	    continue;
+	  perror (_("svc_run: - poll failed"));
+	  return;
+	case 0:
+	  free (my_pollfd);
+	  continue;
+	default:
+	  svc_getreq_poll (my_pollfd, i);
+	  free (my_pollfd);
 	}
+    }
 }

+ 146 - 95
libc/inet/rpc/svc_simple.c

@@ -6,138 +6,189 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro";
+#endif
 
-/* 
+/*
  * svc_simple.c
  * Simplified front end to rpc.
  *
  * Copyright (C) 1984, Sun Microsystems, Inc.
  */
+#define __FORCE_GLIBC
+#define _GNU_SOURCE
+#include <features.h>
 
 #include <stdio.h>
+#include <string.h>
+#include <unistd.h>
 #include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
 #include <sys/socket.h>
 #include <netdb.h>
 
-static struct proglst {
-	char *(*p_progname) ();
-	int p_prognum;
-	int p_procnum;
-	xdrproc_t p_inproc, p_outproc;
-	struct proglst *p_nxt;
-} *proglst;
-static void universal();
-static SVCXPRT *transp;
-struct proglst *pl;
+#ifdef USE_IN_LIBIO
+# include <wchar.h>
+# include <libio/iolibio.h>
+# define fputs(s, f) _IO_fputs (s, f)
+#endif
+
+struct proglst_
+  {
+    char *(*p_progname) (char *);
+    int p_prognum;
+    int p_procnum;
+    xdrproc_t p_inproc, p_outproc;
+    struct proglst_ *p_nxt;
+  };
+#ifdef _RPC_THREAD_SAFE_
+#define proglst ((struct proglst_ *)RPC_THREAD_VARIABLE(svcsimple_proglst_s))
+#else
+static struct proglst_ *proglst;
+#endif
 
-extern bool_t pmap_unset(u_long program, u_long version);
 
-int registerrpc(prognum, versnum, procnum, progname, inproc, outproc)
-char *(*progname) ();
-xdrproc_t inproc, outproc;
+static void universal (struct svc_req *rqstp, SVCXPRT *transp_s);
+#ifdef _RPC_THREAD_SAFE_
+#define transp ((SVCXPRT *)RPC_THREAD_VARIABLE(svcsimple_transp_s))
+#else
+static SVCXPRT *transp;
+#endif
+
+int
+registerrpc (u_long prognum, u_long versnum, u_long procnum,
+	     char *(*progname) (char *), xdrproc_t inproc, xdrproc_t outproc)
 {
+  struct proglst_ *pl;
+  char *buf;
 
-	if (procnum == NULLPROC) {
-		(void) fprintf(stderr,
-					   "can't reassign procedure number %lu\n", NULLPROC);
-		return (-1);
-	}
-	if (transp == 0) {
-		transp = svcudp_create(RPC_ANYSOCK);
-		if (transp == NULL) {
-			(void) fprintf(stderr, "couldn't create an rpc server\n");
-			return (-1);
-		}
-	}
-	(void) pmap_unset((u_long) prognum, (u_long) versnum);
-	if (!svc_register(transp, (u_long) prognum, (u_long) versnum,
-					  universal, IPPROTO_UDP)) {
-		(void) fprintf(stderr, "couldn't register prog %d vers %d\n",
-					   prognum, versnum);
-		return (-1);
-	}
-	pl = (struct proglst *) malloc(sizeof(struct proglst));
+  if (procnum == NULLPROC)
+    {
 
-	if (pl == NULL) {
-		(void) fprintf(stderr, "registerrpc: out of memory\n");
-		return (-1);
+      (void) asprintf (&buf, _("can't reassign procedure number %ld\n"),
+			 NULLPROC);
+      goto err_out;
+    }
+  if (transp == 0)
+    {
+      transp = svcudp_create (RPC_ANYSOCK);
+      if (transp == NULL)
+	{
+	  buf = strdup (_("couldn't create an rpc server\n"));
+	  goto err_out;
 	}
-	pl->p_progname = progname;
-	pl->p_prognum = prognum;
-	pl->p_procnum = procnum;
-	pl->p_inproc = inproc;
-	pl->p_outproc = outproc;
-	pl->p_nxt = proglst;
-	proglst = pl;
-	return (0);
+    }
+  (void) pmap_unset ((u_long) prognum, (u_long) versnum);
+  if (!svc_register (transp, (u_long) prognum, (u_long) versnum,
+		     universal, IPPROTO_UDP))
+    {
+      (void) asprintf (&buf, _("couldn't register prog %ld vers %ld\n"),
+			 prognum, versnum);
+      goto err_out;
+    }
+  pl = (struct proglst_ *) malloc (sizeof (struct proglst_));
+  if (pl == NULL)
+    {
+      buf = strdup (_("registerrpc: out of memory\n"));
+      goto err_out;
+    }
+  pl->p_progname = progname;
+  pl->p_prognum = prognum;
+  pl->p_procnum = procnum;
+  pl->p_inproc = inproc;
+  pl->p_outproc = outproc;
+  pl->p_nxt = proglst;
+  proglst = pl;
+  return 0;
+
+ err_out:
+#ifdef USE_IN_LIBIO
+  if (_IO_fwide (stderr, 0) > 0)
+    (void) __fwprintf (stderr, L"%s", buf);
+  else
+#endif
+    (void) fputs (buf, stderr);
+  free (buf);
+  return -1;
 }
 
-static void universal(rqstp, transp)
-struct svc_req *rqstp;
-SVCXPRT *transp;
+static void
+universal (struct svc_req *rqstp, SVCXPRT *transp_l)
 {
-	int prog, proc;
-	char *outdata;
-	char xdrbuf[UDPMSGSIZE];
-	struct proglst *pl;
+  int prog, proc;
+  char *outdata;
+  char xdrbuf[UDPMSGSIZE];
+  struct proglst_ *pl;
+  char *buf = NULL;
 
-	/* 
-	 * enforce "procnum 0 is echo" convention
-	 */
-	if (rqstp->rq_proc == NULLPROC) {
-		if (svc_sendreply(transp, (xdrproc_t) xdr_void, (char *) NULL) == FALSE) {
-			(void) fprintf(stderr, "xxx\n");
-			exit(1);
-		}
-		return;
+  /*
+   * enforce "procnum 0 is echo" convention
+   */
+  if (rqstp->rq_proc == NULLPROC)
+    {
+      if (svc_sendreply (transp_l, (xdrproc_t)xdr_void, (char *) NULL) == FALSE)
+	{
+	  write (STDERR_FILENO, "xxx\n", 4);
+	  exit (1);
 	}
-	prog = rqstp->rq_prog;
-	proc = rqstp->rq_proc;
-	for (pl = proglst; pl != NULL; pl = pl->p_nxt)
-		if (pl->p_prognum == prog && pl->p_procnum == proc) {
-			/* decode arguments into a CLEAN buffer */
-			bzero(xdrbuf, sizeof(xdrbuf));	/* required ! */
-			if (!svc_getargs(transp, pl->p_inproc, xdrbuf)) {
-				svcerr_decode(transp);
-				return;
-			}
-			outdata = (*(pl->p_progname)) (xdrbuf);
-			if (outdata == NULL && pl->p_outproc != (xdrproc_t) xdr_void)
-				/* there was an error */
-				return;
-			if (!svc_sendreply(transp, pl->p_outproc, outdata)) {
-				(void) fprintf(stderr,
-							   "trouble replying to prog %d\n",
-							   pl->p_prognum);
-				exit(1);
-			}
-			/* free the decoded arguments */
-			(void) svc_freeargs(transp, pl->p_inproc, xdrbuf);
-			return;
-		}
-	(void) fprintf(stderr, "never registered prog %d\n", prog);
-	exit(1);
+      return;
+    }
+  prog = rqstp->rq_prog;
+  proc = rqstp->rq_proc;
+  for (pl = proglst; pl != NULL; pl = pl->p_nxt)
+    if (pl->p_prognum == prog && pl->p_procnum == proc)
+      {
+	/* decode arguments into a CLEAN buffer */
+	bzero (xdrbuf, sizeof (xdrbuf));	/* required ! */
+	if (!svc_getargs (transp_l, pl->p_inproc, xdrbuf))
+	  {
+	    svcerr_decode (transp_l);
+	    return;
+	  }
+	outdata = (*(pl->p_progname)) (xdrbuf);
+	if (outdata == NULL && pl->p_outproc != (xdrproc_t)xdr_void)
+	  /* there was an error */
+	  return;
+	if (!svc_sendreply (transp_l, pl->p_outproc, outdata))
+	  {
+	    (void) asprintf (&buf,
+			       _("trouble replying to prog %d\n"),
+			       pl->p_prognum);
+	    exit (1);
+	  }
+	/* free the decoded arguments */
+	(void) svc_freeargs (transp_l, pl->p_inproc, xdrbuf);
+	return;
+      }
+  (void) asprintf (&buf, _("never registered prog %d\n"), prog);
+#ifdef USE_IN_LIBIO
+  if (_IO_fwide (stderr, 0) > 0)
+    __fwprintf (stderr, L"%s", buf);
+  else
+#endif
+    fputs (buf, stderr);
+  free (buf);
+  exit (1);
 }

+ 301 - 281
libc/inet/rpc/svc_tcp.c

@@ -6,100 +6,126 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";
+#endif
 
 /*
- * svc_tcp.c, Server side for TCP/IP based RPC. 
+ * svc_tcp.c, Server side for TCP/IP based RPC.
  *
  * Copyright (C) 1984, Sun Microsystems, Inc.
  *
  * Actually implements two flavors of transporter -
- * a tcp rendezvouser (a listner and connection establisher)
+ * a tcp rendezvouser (a listener and connection establisher)
  * and a record/tcp stream.
  */
 
-#include <stdlib.h>
+#define __FORCE_GLIBC
+#define _GNU_SOURCE
+#include <features.h>
+
 #include <stdio.h>
+#include <unistd.h>
+#include <string.h>
 #include <rpc/rpc.h>
 #include <sys/socket.h>
+#include <sys/poll.h>
 #include <errno.h>
-#include <unistd.h>
+#include <stdlib.h>
+
+#ifdef USE_IN_LIBIO
+# include <wchar.h>
+# include <libio/iolibio.h>
+# define fputs(s, f) _IO_fputs (s, f)
+#endif
 
 /*
  * Ops vector for TCP/IP based rpc service handle
  */
-static bool_t svctcp_recv();
-static enum xprt_stat svctcp_stat();
-static bool_t svctcp_getargs();
-static bool_t svctcp_reply();
-static bool_t svctcp_freeargs();
-static void svctcp_destroy();
-
-static struct xp_ops svctcp_op = {
-	svctcp_recv,
-	svctcp_stat,
-	svctcp_getargs,
-	svctcp_reply,
-	svctcp_freeargs,
-	svctcp_destroy
+static bool_t svctcp_recv (SVCXPRT *, struct rpc_msg *);
+static enum xprt_stat svctcp_stat (SVCXPRT *);
+static bool_t svctcp_getargs (SVCXPRT *, xdrproc_t, caddr_t);
+static bool_t svctcp_reply (SVCXPRT *, struct rpc_msg *);
+static bool_t svctcp_freeargs (SVCXPRT *, xdrproc_t, caddr_t);
+static void svctcp_destroy (SVCXPRT *);
+
+static const struct xp_ops svctcp_op =
+{
+  svctcp_recv,
+  svctcp_stat,
+  svctcp_getargs,
+  svctcp_reply,
+  svctcp_freeargs,
+  svctcp_destroy
 };
 
 /*
  * Ops vector for TCP/IP rendezvous handler
  */
-static bool_t rendezvous_request();
-static enum xprt_stat rendezvous_stat();
-
-#warning Expect 3 warnings for initialization from incompatible pointer type
-static struct xp_ops svctcp_rendezvous_op = {
-	rendezvous_request,
-	rendezvous_stat,
-	abort,
-	abort,
-	abort,
-	svctcp_destroy
+static bool_t rendezvous_request (SVCXPRT *, struct rpc_msg *);
+static enum xprt_stat rendezvous_stat (SVCXPRT *);
+static void svctcp_rendezvous_abort (void);
+
+/* This function makes sure abort() relocation goes through PLT
+   and thus can be lazy bound.  */
+static void
+svctcp_rendezvous_abort (void)
+{
+  abort ();
 };
 
-static int readtcp(), writetcp();
-static SVCXPRT *makefd_xprt();
-
-struct tcp_rendezvous {			/* kept in xprt->xp_p1 */
-	u_int sendsize;
-	u_int recvsize;
+static const struct xp_ops svctcp_rendezvous_op =
+{
+  rendezvous_request,
+  rendezvous_stat,
+  (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svctcp_rendezvous_abort,
+  (bool_t (*) (SVCXPRT *, struct rpc_msg *)) svctcp_rendezvous_abort,
+  (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svctcp_rendezvous_abort,
+  svctcp_destroy
 };
 
-struct tcp_conn {				/* kept in xprt->xp_p1 */
-	enum xprt_stat strm_stat;
-	u_long x_id;
-	XDR xdrs;
-	char verf_body[MAX_AUTH_BYTES];
-};
+static int readtcp (char*, char *, int);
+static int writetcp (char *, char *, int);
+static SVCXPRT *makefd_xprt (int, u_int, u_int) internal_function;
+
+struct tcp_rendezvous
+  {				/* kept in xprt->xp_p1 */
+    u_int sendsize;
+    u_int recvsize;
+  };
+
+struct tcp_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 = svctcp_create(sock, send_buf_size, recv_buf_size);
+ *      xprt = svctcp_create(sock, send_buf_size, recv_buf_size);
  *
  * Creates, registers, and returns a (rpc) tcp based transporter.
  * Once *xprt is initialized, it is registered as a transporter
@@ -117,290 +143,284 @@ struct tcp_conn {				/* kept in xprt->xp_p1 */
  * how big the send and receive buffers are via the second and third parms;
  * 0 => use the system default.
  */
-SVCXPRT *svctcp_create(sock, sendsize, recvsize)
-register int sock;
-u_int sendsize;
-u_int recvsize;
+SVCXPRT *
+svctcp_create (int sock, u_int sendsize, u_int recvsize)
 {
-	bool_t madesock = FALSE;
-	register SVCXPRT *xprt;
-	register struct tcp_rendezvous *r;
-	struct sockaddr_in addr;
-	int len = sizeof(struct sockaddr_in);
-
-	if (sock == RPC_ANYSOCK) {
-		if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
-			perror("svc_tcp.c - tcp socket creation problem");
-			return ((SVCXPRT *) NULL);
-		}
-		madesock = TRUE;
+  bool_t madesock = FALSE;
+  SVCXPRT *xprt;
+  struct tcp_rendezvous *r;
+  struct sockaddr_in addr;
+  socklen_t len = sizeof (struct sockaddr_in);
+
+  if (sock == RPC_ANYSOCK)
+    {
+      if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+	{
+	  perror (_("svc_tcp.c - tcp socket creation problem"));
+	  return (SVCXPRT *) NULL;
 	}
-	bzero((char *) &addr, sizeof(addr));
-	addr.sin_family = AF_INET;
-	if (bindresvport(sock, &addr)) {
-		addr.sin_port = 0;
-		(void) bind(sock, (struct sockaddr *) &addr, len);
-	}
-	if ((getsockname(sock, (struct sockaddr *) &addr, &len) != 0) ||
-		(listen(sock, 2) != 0)) {
-		perror("svctcp_.c - cannot getsockname or listen");
-		if (madesock)
-			(void) close(sock);
-		return ((SVCXPRT *) NULL);
-	}
-	r = (struct tcp_rendezvous *) mem_alloc(sizeof(*r));
-	if (r == NULL) {
-		(void) fprintf(stderr, "svctcp_create: out of memory\n");
-		return (NULL);
-	}
-	r->sendsize = sendsize;
-	r->recvsize = recvsize;
-	xprt = (SVCXPRT *) mem_alloc(sizeof(SVCXPRT));
-	if (xprt == NULL) {
-		(void) fprintf(stderr, "svctcp_create: out of memory\n");
-		return (NULL);
-	}
-	xprt->xp_p2 = NULL;
-	xprt->xp_p1 = (caddr_t) r;
-	xprt->xp_verf = _null_auth;
-	xprt->xp_ops = &svctcp_rendezvous_op;
-	xprt->xp_port = ntohs(addr.sin_port);
-	xprt->xp_sock = sock;
-	xprt_register(xprt);
-	return (xprt);
+      madesock = TRUE;
+    }
+  bzero ((char *) &addr, sizeof (addr));
+  addr.sin_family = AF_INET;
+  if (bindresvport (sock, &addr))
+    {
+      addr.sin_port = 0;
+      (void) bind (sock, (struct sockaddr *) &addr, len);
+    }
+  if ((getsockname (sock, (struct sockaddr *) &addr, &len) != 0) ||
+      (listen (sock, 2) != 0))
+    {
+      perror (_("svc_tcp.c - cannot getsockname or listen"));
+      if (madesock)
+	(void) close (sock);
+      return (SVCXPRT *) NULL;
+    }
+  r = (struct tcp_rendezvous *) mem_alloc (sizeof (*r));
+  xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
+  if (r == NULL || xprt == NULL)
+    {
+#ifdef USE_IN_LIBIO
+      if (_IO_fwide (stderr, 0) > 0)
+	(void) __fwprintf (stderr, L"%s", _("svctcp_create: out of memory\n"));
+      else
+#endif
+	(void) fputs (_("svctcp_create: out of memory\n"), stderr);
+      mem_free (r, sizeof (*r));
+      mem_free (xprt, sizeof (SVCXPRT));
+      return NULL;
+    }
+  r->sendsize = sendsize;
+  r->recvsize = recvsize;
+  xprt->xp_p2 = NULL;
+  xprt->xp_p1 = (caddr_t) r;
+  xprt->xp_verf = _null_auth;
+  xprt->xp_ops = &svctcp_rendezvous_op;
+  xprt->xp_port = ntohs (addr.sin_port);
+  xprt->xp_sock = sock;
+  xprt_register (xprt);
+  return xprt;
 }
 
 /*
  * Like svtcp_create(), except the routine takes any *open* UNIX file
  * descriptor as its first input.
  */
-SVCXPRT *svcfd_create(fd, sendsize, recvsize)
-int fd;
-u_int sendsize;
-u_int recvsize;
+SVCXPRT *
+svcfd_create (int fd, u_int sendsize, u_int recvsize)
 {
-
-	return (makefd_xprt(fd, sendsize, recvsize));
+  return makefd_xprt (fd, sendsize, recvsize);
 }
 
-static SVCXPRT *makefd_xprt(fd, sendsize, recvsize)
-int fd;
-u_int sendsize;
-u_int recvsize;
+static SVCXPRT *
+internal_function
+makefd_xprt (int fd, u_int sendsize, u_int recvsize)
 {
-	register SVCXPRT *xprt;
-	register struct tcp_conn *cd;
-
-	xprt = (SVCXPRT *) mem_alloc(sizeof(SVCXPRT));
-	if (xprt == (SVCXPRT *) NULL) {
-		(void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n");
-		goto done;
-	}
-	cd = (struct tcp_conn *) mem_alloc(sizeof(struct tcp_conn));
-
-	if (cd == (struct tcp_conn *) NULL) {
-		(void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n");
-		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, readtcp, writetcp);
-	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 = &svctcp_op;	/* truely deals with calls */
-	xprt->xp_port = 0;			/* this is a connection, not a rendezvouser */
-	xprt->xp_sock = fd;
-	xprt_register(xprt);
-  done:
-	return (xprt);
+  SVCXPRT *xprt;
+  struct tcp_conn *cd;
+
+  xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
+  cd = (struct tcp_conn *) mem_alloc (sizeof (struct tcp_conn));
+  if (xprt == (SVCXPRT *) NULL || cd == NULL)
+    {
+#ifdef USE_IN_LIBIO
+      if (_IO_fwide (stderr, 0) > 0)
+	(void) __fwprintf (stderr, L"%s",
+			   _("svc_tcp: makefd_xprt: out of memory\n"));
+      else
+#endif
+	(void) fputs (_("svc_tcp: makefd_xprt: out of memory\n"), stderr);
+      mem_free (xprt, sizeof (SVCXPRT));
+      mem_free (cd, sizeof (struct tcp_conn));
+      return NULL;
+    }
+  cd->strm_stat = XPRT_IDLE;
+  xdrrec_create (&(cd->xdrs), sendsize, recvsize,
+		 (caddr_t) xprt, readtcp, writetcp);
+  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 = &svctcp_op;	/* truly deals with calls */
+  xprt->xp_port = 0;		/* this is a connection, not a rendezvouser */
+  xprt->xp_sock = fd;
+  xprt_register (xprt);
+  return xprt;
 }
 
-static bool_t rendezvous_request(xprt)
-register SVCXPRT *xprt;
+static bool_t
+rendezvous_request (SVCXPRT *xprt, struct rpc_msg *errmsg)
 {
-	int sock;
-	struct tcp_rendezvous *r;
-	struct sockaddr_in addr;
-	int len;
-
-	r = (struct tcp_rendezvous *) xprt->xp_p1;
-  again:
-	len = sizeof(struct sockaddr_in);
-
-	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)
-	 */
-	xprt = makefd_xprt(sock, r->sendsize, r->recvsize);
-	xprt->xp_raddr = addr;
-	xprt->xp_addrlen = len;
-	return (FALSE);				/* there is never an rpc msg to be processed */
+  int sock;
+  struct tcp_rendezvous *r;
+  struct sockaddr_in addr;
+  socklen_t len;
+
+  r = (struct tcp_rendezvous *) xprt->xp_p1;
+again:
+  len = sizeof (struct sockaddr_in);
+  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)
+   */
+  xprt = makefd_xprt (sock, r->sendsize, r->recvsize);
+  memcpy (&xprt->xp_raddr, &addr, sizeof (addr));
+  xprt->xp_addrlen = len;
+  return FALSE;		/* there is never an rpc msg to be processed */
 }
 
-static enum xprt_stat rendezvous_stat()
+static enum xprt_stat
+rendezvous_stat (SVCXPRT *xprt)
 {
-
-	return (XPRT_IDLE);
+  return XPRT_IDLE;
 }
 
-static void svctcp_destroy(xprt)
-register SVCXPRT *xprt;
+static void
+svctcp_destroy (SVCXPRT *xprt)
 {
-	register struct tcp_conn *cd = (struct tcp_conn *) xprt->xp_p1;
-
-	xprt_unregister(xprt);
-	(void) 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 tcp_conn));
-
-	mem_free((caddr_t) xprt, sizeof(SVCXPRT));
+  struct tcp_conn *cd = (struct tcp_conn *) xprt->xp_p1;
+
+  xprt_unregister (xprt);
+  (void) 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 tcp_conn));
+  mem_free ((caddr_t) xprt, sizeof (SVCXPRT));
 }
 
-/*
- * 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 tcp conection.
+ * reads data from the tcp connection.
  * any error is fatal and the connection is closed.
  * (And a read of zero bytes is a half closed stream => error.)
  */
-static int readtcp(xprt, buf, len)
-register SVCXPRT *xprt;
-caddr_t buf;
-register int len;
+static int
+readtcp (char *xprtptr, char *buf, int len)
 {
-	register int sock = xprt->xp_sock;
-
-#ifdef FD_SETSIZE
-	fd_set mask;
-	fd_set readfds;
-
-	FD_ZERO(&mask);
-	FD_SET(sock, &mask);
-#else
-	register int mask = 1 << sock;
-	int readfds;
-#endif							/* def FD_SETSIZE */
-	do {
-		readfds = mask;
-		if (select(_rpc_dtablesize(), &readfds, NULL, NULL,
-				   &wait_per_try) <= 0) {
-			if (errno == EINTR) {
-				continue;
-			}
-			goto fatal_err;
-		}
-#ifdef FD_SETSIZE
-	} while (!FD_ISSET(sock, &readfds));
-#else
-	} while (readfds != mask);
-#endif							/* def FD_SETSIZE */
-	if ((len = read(sock, buf, len)) > 0) {
-		return (len);
+  SVCXPRT *xprt = (SVCXPRT *)xprtptr;
+  int sock = xprt->xp_sock;
+  int milliseconds = 35 * 1000;
+  struct pollfd pollfd;
+
+  do
+    {
+      pollfd.fd = sock;
+      pollfd.events = POLLIN;
+      switch (poll (&pollfd, 1, milliseconds))
+	{
+	case -1:
+	  if (errno == EINTR)
+	    continue;
+	  /*FALLTHROUGH*/
+	case 0:
+	  goto fatal_err;
+	default:
+          if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP)
+              || (pollfd.revents & POLLNVAL))
+            goto fatal_err;
+	  break;
 	}
-  fatal_err:
-	((struct tcp_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
-	return (-1);
+    }
+  while ((pollfd.revents & POLLIN) == 0);
+
+  if ((len = read (sock, buf, len)) > 0)
+    return len;
+
+ fatal_err:
+  ((struct tcp_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
+  return -1;
 }
 
 /*
  * writes data to the tcp connection.
  * Any error is fatal and the connection is closed.
  */
-static int writetcp(xprt, buf, len)
-register SVCXPRT *xprt;
-caddr_t buf;
-int len;
+static int
+writetcp (char *xprtptr, char * buf, int len)
 {
-	register int i, cnt;
-
-	for (cnt = len; cnt > 0; cnt -= i, buf += i) {
-		if ((i = write(xprt->xp_sock, buf, cnt)) < 0) {
-			((struct tcp_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
-			return (-1);
-		}
+  SVCXPRT *xprt = (SVCXPRT *)xprtptr;
+  int i, cnt;
+
+  for (cnt = len; cnt > 0; cnt -= i, buf += i)
+    {
+      if ((i = write (xprt->xp_sock, buf, cnt)) < 0)
+	{
+	  ((struct tcp_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
+	  return -1;
 	}
-	return (len);
+    }
+  return len;
 }
 
-static enum xprt_stat svctcp_stat(xprt)
-SVCXPRT *xprt;
+static enum xprt_stat
+svctcp_stat (SVCXPRT *xprt)
 {
-	register struct tcp_conn *cd = (struct tcp_conn *) (xprt->xp_p1);
-
-	if (cd->strm_stat == XPRT_DIED)
-		return (XPRT_DIED);
-	if (!xdrrec_eof(&(cd->xdrs)))
-		return (XPRT_MOREREQS);
-	return (XPRT_IDLE);
+  struct tcp_conn *cd =
+  (struct tcp_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 svctcp_recv(xprt, msg)
-SVCXPRT *xprt;
-register struct rpc_msg *msg;
+static bool_t
+svctcp_recv (SVCXPRT *xprt, struct rpc_msg *msg)
 {
-	register struct tcp_conn *cd = (struct tcp_conn *) (xprt->xp_p1);
-	register XDR *xdrs = &(cd->xdrs);
-
-	xdrs->x_op = XDR_DECODE;
-	(void) xdrrec_skiprecord(xdrs);
-	if (xdr_callmsg(xdrs, msg)) {
-		cd->x_id = msg->rm_xid;
-		return (TRUE);
-	}
-	return (FALSE);
+  struct tcp_conn *cd = (struct tcp_conn *) (xprt->xp_p1);
+  XDR *xdrs = &(cd->xdrs);
+
+  xdrs->x_op = XDR_DECODE;
+  (void) xdrrec_skiprecord (xdrs);
+  if (xdr_callmsg (xdrs, msg))
+    {
+      cd->x_id = msg->rm_xid;
+      return TRUE;
+    }
+  cd->strm_stat = XPRT_DIED;	/* XXXX */
+  return FALSE;
 }
 
-static bool_t svctcp_getargs(xprt, xdr_args, args_ptr)
-SVCXPRT *xprt;
-xdrproc_t xdr_args;
-caddr_t args_ptr;
+static bool_t
+svctcp_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
 {
-
-	return ((*xdr_args)
-			(&(((struct tcp_conn *) (xprt->xp_p1))->xdrs), args_ptr));
+  return ((*xdr_args) (&(((struct tcp_conn *)
+			  (xprt->xp_p1))->xdrs), args_ptr));
 }
 
-static bool_t svctcp_freeargs(xprt, xdr_args, args_ptr)
-SVCXPRT *xprt;
-xdrproc_t xdr_args;
-caddr_t args_ptr;
+static bool_t
+svctcp_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
 {
-	register XDR *xdrs = &(((struct tcp_conn *) (xprt->xp_p1))->xdrs);
+  XDR *xdrs = &(((struct tcp_conn *) (xprt->xp_p1))->xdrs);
 
-	xdrs->x_op = XDR_FREE;
-	return ((*xdr_args) (xdrs, args_ptr));
+  xdrs->x_op = XDR_FREE;
+  return ((*xdr_args) (xdrs, args_ptr));
 }
 
-static bool_t svctcp_reply(xprt, msg)
-SVCXPRT *xprt;
-register struct rpc_msg *msg;
+static bool_t
+svctcp_reply (SVCXPRT *xprt, struct rpc_msg *msg)
 {
-	register struct tcp_conn *cd = (struct tcp_conn *) (xprt->xp_p1);
-	register XDR *xdrs = &(cd->xdrs);
-	register 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);
+  struct tcp_conn *cd = (struct tcp_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;
 }

+ 460 - 322
libc/inet/rpc/svc_udp.c

@@ -6,29 +6,30 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro";
+#endif
 
 /*
  * svc_udp.c,
@@ -38,54 +39,69 @@
  * Copyright (C) 1984, Sun Microsystems, Inc.
  */
 
+#define __FORCE_GLIBC
+#define _GNU_SOURCE
+#include <features.h>
+
 #include <stdio.h>
+#include <unistd.h>
+#include <string.h>
 #include <rpc/rpc.h>
 #include <sys/socket.h>
 #include <errno.h>
-#include <unistd.h>
 
+#ifdef IP_PKTINFO
+#include <sys/uio.h>
+#endif
+
+#ifdef USE_IN_LIBIO
+# include <wchar.h>
+# include <libio/iolibio.h>
+# define fputs(s, f) _IO_fputs (s, f)
+#endif
 
 #define rpc_buffer(xprt) ((xprt)->xp_p1)
 #ifndef MAX
 #define MAX(a, b)     ((a > b) ? a : b)
 #endif
 
-static bool_t svcudp_recv();
-static bool_t svcudp_reply();
-static enum xprt_stat svcudp_stat();
-static bool_t svcudp_getargs();
-static bool_t svcudp_freeargs();
-static void svcudp_destroy();
-
-static void cache_set(SVCXPRT *xprt, u_long replylen);
-static int cache_get(SVCXPRT *xprt, struct rpc_msg *msg, 
-					 char **replyp, u_long *replylenp);
-
-static struct xp_ops svcudp_op = {
-	svcudp_recv,
-	svcudp_stat,
-	svcudp_getargs,
-	svcudp_reply,
-	svcudp_freeargs,
-	svcudp_destroy
+static bool_t svcudp_recv (SVCXPRT *, struct rpc_msg *);
+static bool_t svcudp_reply (SVCXPRT *, struct rpc_msg *);
+static enum xprt_stat svcudp_stat (SVCXPRT *);
+static bool_t svcudp_getargs (SVCXPRT *, xdrproc_t, caddr_t);
+static bool_t svcudp_freeargs (SVCXPRT *, xdrproc_t, caddr_t);
+static void svcudp_destroy (SVCXPRT *);
+
+static const struct xp_ops svcudp_op =
+{
+  svcudp_recv,
+  svcudp_stat,
+  svcudp_getargs,
+  svcudp_reply,
+  svcudp_freeargs,
+  svcudp_destroy
 };
 
+static int cache_get (SVCXPRT *, struct rpc_msg *, char **replyp,
+		      u_long *replylenp);
+static void cache_set (SVCXPRT *xprt, u_long replylen);
+
 /*
  * kept in xprt->xp_p2
  */
-struct svcudp_data {
-	u_int su_iosz;				/* byte size of send.recv buffer */
-	u_long su_xid;				/* transaction id */
-	XDR su_xdrs;				/* XDR handle */
-	char su_verfbody[MAX_AUTH_BYTES];	/* verifier body */
-	char *su_cache;				/* cached data, NULL if no cache */
-};
-
+struct svcudp_data
+  {
+    u_int su_iosz;		/* byte size of send.recv buffer */
+    u_long su_xid;		/* transaction id */
+    XDR su_xdrs;		/* XDR handle */
+    char su_verfbody[MAX_AUTH_BYTES];	/* verifier body */
+    char *su_cache;		/* cached data, NULL if no cache */
+  };
 #define	su_data(xprt)	((struct svcudp_data *)(xprt->xp_p2))
 
 /*
  * Usage:
- *	xprt = svcudp_create(sock);
+ *      xprt = svcudp_create(sock);
  *
  * If sock<0 then a socket is created, else sock is used.
  * If the socket, sock is not bound to a port then svcudp_create
@@ -96,170 +112,272 @@ struct svcudp_data {
  * see (svc.h, xprt_register).
  * The routines returns NULL if a problem occurred.
  */
-SVCXPRT *svcudp_bufcreate(sock, sendsz, recvsz)
-register int sock;
-u_int sendsz, recvsz;
+SVCXPRT *
+svcudp_bufcreate (sock, sendsz, recvsz)
+     int sock;
+     u_int sendsz, recvsz;
 {
-	bool_t madesock = FALSE;
-	register SVCXPRT *xprt;
-	register struct svcudp_data *su;
-	struct sockaddr_in addr;
-	int len = sizeof(struct sockaddr_in);
-
-	if (sock == RPC_ANYSOCK) {
-		if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
-			perror("svcudp_create: socket creation problem");
-			return ((SVCXPRT *) NULL);
-		}
-		madesock = TRUE;
-	}
-	bzero((char *) &addr, sizeof(addr));
-	addr.sin_family = AF_INET;
-	if (bindresvport(sock, &addr)) {
-		addr.sin_port = 0;
-		(void) bind(sock, (struct sockaddr *) &addr, len);
-	}
-	if (getsockname(sock, (struct sockaddr *) &addr, &len) != 0) {
-		perror("svcudp_create - cannot getsockname");
-		if (madesock)
-			(void) close(sock);
-		return ((SVCXPRT *) NULL);
-	}
-	xprt = (SVCXPRT *) mem_alloc(sizeof(SVCXPRT));
-	if (xprt == NULL) {
-		(void) fprintf(stderr, "svcudp_create: out of memory\n");
-		return (NULL);
-	}
-	su = (struct svcudp_data *) mem_alloc(sizeof(*su));
-	if (su == NULL) {
-		(void) fprintf(stderr, "svcudp_create: out of memory\n");
-		return (NULL);
+  bool_t madesock = FALSE;
+  SVCXPRT *xprt;
+  struct svcudp_data *su;
+  struct sockaddr_in addr;
+  socklen_t len = sizeof (struct sockaddr_in);
+  int pad;
+  void *buf;
+
+  if (sock == RPC_ANYSOCK)
+    {
+      if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+	{
+	  perror (_("svcudp_create: socket creation problem"));
+	  return (SVCXPRT *) NULL;
 	}
-	su->su_iosz = ((MAX(sendsz, recvsz) + 3) / 4) * 4;
-	if ((rpc_buffer(xprt) = mem_alloc(su->su_iosz)) == NULL) {
-		(void) fprintf(stderr, "svcudp_create: out of memory\n");
-		return (NULL);
-	}
-	xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz,
-				  XDR_DECODE);
-	su->su_cache = NULL;
-	xprt->xp_p2 = (caddr_t) su;
-	xprt->xp_verf.oa_base = su->su_verfbody;
-	xprt->xp_ops = &svcudp_op;
-	xprt->xp_port = ntohs(addr.sin_port);
-	xprt->xp_sock = sock;
-	xprt_register(xprt);
-	return (xprt);
+      madesock = TRUE;
+    }
+  bzero ((char *) &addr, sizeof (addr));
+  addr.sin_family = AF_INET;
+  if (bindresvport (sock, &addr))
+    {
+      addr.sin_port = 0;
+      (void) bind (sock, (struct sockaddr *) &addr, len);
+    }
+  if (getsockname (sock, (struct sockaddr *) &addr, &len) != 0)
+    {
+      perror (_("svcudp_create - cannot getsockname"));
+      if (madesock)
+	(void) close (sock);
+      return (SVCXPRT *) NULL;
+    }
+  xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
+  su = (struct svcudp_data *) mem_alloc (sizeof (*su));
+  buf = mem_alloc (((MAX (sendsz, recvsz) + 3) / 4) * 4);
+  if (xprt == NULL || su == NULL || buf == NULL)
+    {
+#ifdef USE_IN_LIBIO
+      if (_IO_fwide (stderr, 0) > 0)
+	(void) __fwprintf (stderr, L"%s", _("svcudp_create: out of memory\n"));
+      else
+#endif
+	(void) fputs (_("svcudp_create: out of memory\n"), stderr);
+      mem_free (xprt, sizeof (SVCXPRT));
+      mem_free (su, sizeof (*su));
+      mem_free (buf, ((MAX (sendsz, recvsz) + 3) / 4) * 4);
+      return NULL;
+    }
+  su->su_iosz = ((MAX (sendsz, recvsz) + 3) / 4) * 4;
+  rpc_buffer (xprt) = buf;
+  xdrmem_create (&(su->su_xdrs), rpc_buffer (xprt), su->su_iosz, XDR_DECODE);
+  su->su_cache = NULL;
+  xprt->xp_p2 = (caddr_t) su;
+  xprt->xp_verf.oa_base = su->su_verfbody;
+  xprt->xp_ops = &svcudp_op;
+  xprt->xp_port = ntohs (addr.sin_port);
+  xprt->xp_sock = sock;
+
+#ifdef IP_PKTINFO
+  if ((sizeof (struct iovec) + sizeof (struct msghdr)
+       + sizeof(struct cmsghdr) + sizeof (struct in_pktinfo))
+      > sizeof (xprt->xp_pad))
+    {
+# ifdef USE_IN_LIBIO
+      if (_IO_fwide (stderr, 0) > 0)
+	(void) __fwprintf (stderr, L"%s",
+			   _("svcudp_create: xp_pad is too small for IP_PKTINFO\n"));
+      else
+# endif
+	(void) fputs (_("svcudp_create: xp_pad is too small for IP_PKTINFO\n"),
+		      stderr);
+      return NULL;
+    }
+  pad = 1;
+  if (setsockopt (sock, SOL_IP, IP_PKTINFO, (void *) &pad,
+		  sizeof (pad)) == 0)
+    /* Set the padding to all 1s. */
+    pad = 0xff;
+  else
+#endif
+    /* Clear the padding. */
+    pad = 0;
+  memset (&xprt->xp_pad [0], pad, sizeof (xprt->xp_pad));
+
+  xprt_register (xprt);
+  return xprt;
 }
 
-SVCXPRT *svcudp_create(sock)
-int sock;
+SVCXPRT *
+svcudp_create (sock)
+     int sock;
 {
 
-	return (svcudp_bufcreate(sock, UDPMSGSIZE, UDPMSGSIZE));
+  return svcudp_bufcreate (sock, UDPMSGSIZE, UDPMSGSIZE);
 }
 
-static enum xprt_stat svcudp_stat(xprt)
-SVCXPRT *xprt;
+static enum xprt_stat
+svcudp_stat (xprt)
+     SVCXPRT *xprt;
 {
 
-	return (XPRT_IDLE);
+  return XPRT_IDLE;
 }
 
-static bool_t svcudp_recv(xprt, msg)
-register SVCXPRT *xprt;
-struct rpc_msg *msg;
+static bool_t
+svcudp_recv (xprt, msg)
+     SVCXPRT *xprt;
+     struct rpc_msg *msg;
 {
-	register struct svcudp_data *su = su_data(xprt);
-	register XDR *xdrs = &(su->su_xdrs);
-	register int rlen;
-	char *reply;
-	u_long replylen;
-
-  again:
-	xprt->xp_addrlen = sizeof(struct sockaddr_in);
-
-	rlen = recvfrom(xprt->xp_sock, rpc_buffer(xprt), (int) su->su_iosz,
-					0, (struct sockaddr *) &(xprt->xp_raddr),
-					&(xprt->xp_addrlen));
-	if (rlen == -1 && errno == EINTR)
-		goto again;
-	if (rlen < 4 * sizeof(u_long))
-		return (FALSE);
-	xdrs->x_op = XDR_DECODE;
-	XDR_SETPOS(xdrs, 0);
-	if (!xdr_callmsg(xdrs, msg))
-		return (FALSE);
-	su->su_xid = msg->rm_xid;
-	if (su->su_cache != NULL) {
-		if (cache_get(xprt, msg, &reply, &replylen)) {
-			(void) sendto(xprt->xp_sock, reply, (int) replylen, 0,
-						  (struct sockaddr *) &xprt->xp_raddr,
-						  xprt->xp_addrlen);
-			return (TRUE);
-		}
+  struct svcudp_data *su = su_data (xprt);
+  XDR *xdrs = &(su->su_xdrs);
+  int rlen;
+  char *reply;
+  u_long replylen;
+  socklen_t len;
+
+  /* It is very tricky when you have IP aliases. We want to make sure
+     that we are sending the packet from the IP address where the
+     incoming packet is addressed to. H.J. */
+#ifdef IP_PKTINFO
+  struct iovec *iovp;
+  struct msghdr *mesgp;
+#endif
+
+again:
+  /* FIXME -- should xp_addrlen be a size_t?  */
+  len = (socklen_t) sizeof(struct sockaddr_in);
+#ifdef IP_PKTINFO
+  iovp = (struct iovec *) &xprt->xp_pad [0];
+  mesgp = (struct msghdr *) &xprt->xp_pad [sizeof (struct iovec)];
+  if (mesgp->msg_iovlen)
+    {
+      iovp->iov_base = rpc_buffer (xprt);
+      iovp->iov_len = su->su_iosz;
+      mesgp->msg_iov = iovp;
+      mesgp->msg_iovlen = 1;
+      mesgp->msg_name = &(xprt->xp_raddr);
+      mesgp->msg_namelen = len;
+      mesgp->msg_control = &xprt->xp_pad [sizeof (struct iovec)
+					  + sizeof (struct msghdr)];
+      mesgp->msg_controllen = sizeof(xprt->xp_pad)
+			      - sizeof (struct iovec) - sizeof (struct msghdr);
+      rlen = recvmsg (xprt->xp_sock, mesgp, 0);
+      if (rlen >= 0)
+	len = mesgp->msg_namelen;
+    }
+  else
+#endif
+    rlen = recvfrom (xprt->xp_sock, rpc_buffer (xprt),
+		     (int) su->su_iosz, 0,
+		     (struct sockaddr *) &(xprt->xp_raddr), &len);
+  xprt->xp_addrlen = len;
+  if (rlen == -1 && errno == EINTR)
+    goto again;
+  if (rlen < 16)		/* < 4 32-bit ints? */
+    return FALSE;
+  xdrs->x_op = XDR_DECODE;
+  XDR_SETPOS (xdrs, 0);
+  if (!xdr_callmsg (xdrs, msg))
+    return FALSE;
+  su->su_xid = msg->rm_xid;
+  if (su->su_cache != NULL)
+    {
+      if (cache_get (xprt, msg, &reply, &replylen))
+	{
+#ifdef IP_PKTINFO
+	  if (mesgp->msg_iovlen)
+	    {
+	      iovp->iov_base = reply;
+	      iovp->iov_len = replylen;
+	      (void) sendmsg (xprt->xp_sock, mesgp, 0);
+	    }
+	  else
+#endif
+	    (void) sendto (xprt->xp_sock, reply, (int) replylen, 0,
+			   (struct sockaddr *) &xprt->xp_raddr, len);
+	  return TRUE;
 	}
-	return (TRUE);
+    }
+  return TRUE;
 }
 
-static bool_t svcudp_reply(xprt, msg)
-register SVCXPRT *xprt;
-struct rpc_msg *msg;
+static bool_t
+svcudp_reply (xprt, msg)
+     SVCXPRT *xprt;
+     struct rpc_msg *msg;
 {
-	register struct svcudp_data *su = su_data(xprt);
-	register XDR *xdrs = &(su->su_xdrs);
-	register int slen;
-	register bool_t stat = FALSE;
-
-	xdrs->x_op = XDR_ENCODE;
-	XDR_SETPOS(xdrs, 0);
-	msg->rm_xid = su->su_xid;
-	if (xdr_replymsg(xdrs, msg)) {
-		slen = (int) XDR_GETPOS(xdrs);
-		if (sendto(xprt->xp_sock, rpc_buffer(xprt), slen, 0,
-				   (struct sockaddr *) &(xprt->xp_raddr), xprt->xp_addrlen)
-			== slen) {
-			stat = TRUE;
-			if (su->su_cache && slen >= 0) {
-				cache_set(xprt, (u_long) slen);
-			}
-		}
+  struct svcudp_data *su = su_data (xprt);
+  XDR *xdrs = &(su->su_xdrs);
+  int slen, sent;
+  bool_t stat = FALSE;
+#ifdef IP_PKTINFO
+  struct iovec *iovp;
+  struct msghdr *mesgp;
+#endif
+
+  xdrs->x_op = XDR_ENCODE;
+  XDR_SETPOS (xdrs, 0);
+  msg->rm_xid = su->su_xid;
+  if (xdr_replymsg (xdrs, msg))
+    {
+      slen = (int) XDR_GETPOS (xdrs);
+#ifdef IP_PKTINFO
+      mesgp = (struct msghdr *) &xprt->xp_pad [sizeof (struct iovec)];
+      if (mesgp->msg_iovlen)
+	{
+	  iovp = (struct iovec *) &xprt->xp_pad [0];
+	  iovp->iov_base = rpc_buffer (xprt);
+	  iovp->iov_len = slen;
+	  sent = sendmsg (xprt->xp_sock, mesgp, 0);
 	}
-	return (stat);
+      else
+#endif
+	sent = sendto (xprt->xp_sock, rpc_buffer (xprt), slen, 0,
+		       (struct sockaddr *) &(xprt->xp_raddr),
+		       xprt->xp_addrlen);
+      if (sent == slen)
+	{
+	  stat = TRUE;
+	  if (su->su_cache && slen >= 0)
+	    {
+	      cache_set (xprt, (u_long) slen);
+	    }
+	}
+    }
+  return stat;
 }
 
-static bool_t svcudp_getargs(xprt, xdr_args, args_ptr)
-SVCXPRT *xprt;
-xdrproc_t xdr_args;
-caddr_t args_ptr;
+static bool_t
+svcudp_getargs (xprt, xdr_args, args_ptr)
+     SVCXPRT *xprt;
+     xdrproc_t xdr_args;
+     caddr_t args_ptr;
 {
 
-	return ((*xdr_args) (&(su_data(xprt)->su_xdrs), args_ptr));
+  return (*xdr_args) (&(su_data (xprt)->su_xdrs), args_ptr);
 }
 
-static bool_t svcudp_freeargs(xprt, xdr_args, args_ptr)
-SVCXPRT *xprt;
-xdrproc_t xdr_args;
-caddr_t args_ptr;
+static bool_t
+svcudp_freeargs (xprt, xdr_args, args_ptr)
+     SVCXPRT *xprt;
+     xdrproc_t xdr_args;
+     caddr_t args_ptr;
 {
-	register XDR *xdrs = &(su_data(xprt)->su_xdrs);
+  XDR *xdrs = &(su_data (xprt)->su_xdrs);
 
-	xdrs->x_op = XDR_FREE;
-	return ((*xdr_args) (xdrs, args_ptr));
+  xdrs->x_op = XDR_FREE;
+  return (*xdr_args) (xdrs, args_ptr);
 }
 
-static void svcudp_destroy(xprt)
-register SVCXPRT *xprt;
+static void
+svcudp_destroy (xprt)
+     SVCXPRT *xprt;
 {
-	register struct svcudp_data *su = su_data(xprt);
-
-	xprt_unregister(xprt);
-	(void) close(xprt->xp_sock);
-	XDR_DESTROY(&(su->su_xdrs));
-	mem_free(rpc_buffer(xprt), su->su_iosz);
-	mem_free((caddr_t) su, sizeof(struct svcudp_data));
-
-	mem_free((caddr_t) xprt, sizeof(SVCXPRT));
+  struct svcudp_data *su = su_data (xprt);
+
+  xprt_unregister (xprt);
+  (void) close (xprt->xp_sock);
+  XDR_DESTROY (&(su->su_xdrs));
+  mem_free (rpc_buffer (xprt), su->su_iosz);
+  mem_free ((caddr_t) su, sizeof (struct svcudp_data));
+  mem_free ((caddr_t) xprt, sizeof (SVCXPRT));
 }
 
 
@@ -271,10 +389,18 @@ register SVCXPRT *xprt;
  * Buffers are sent again if retransmissions are detected.
  */
 
-#define SPARSENESS 4			/* 75% sparse */
+#define SPARSENESS 4		/* 75% sparse */
 
-#define CACHE_PERROR(msg)	\
+#ifdef USE_IN_LIBIO
+# define CACHE_PERROR(msg)	\
+	if (_IO_fwide (stderr, 0) > 0)					      \
+		(void) __fwprintf(stderr, L"%s\n", msg);		      \
+	else								      \
+		(void) fprintf(stderr, "%s\n", msg)
+#else
+# define CACHE_PERROR(msg)	\
 	(void) fprintf(stderr,"%s\n", msg)
+#endif
 
 #define ALLOC(type, size)	\
 	(type *) mem_alloc((unsigned) (sizeof(type) * (size)))
@@ -286,41 +412,43 @@ register SVCXPRT *xprt;
  * An entry in the cache
  */
 typedef struct cache_node *cache_ptr;
-struct cache_node {
-	/*
-	 * Index into cache is xid, proc, vers, prog and address
-	 */
-	u_long cache_xid;
-	u_long cache_proc;
-	u_long cache_vers;
-	u_long cache_prog;
-	struct sockaddr_in cache_addr;
-	/*
-	 * The cached reply and length
-	 */
-	char *cache_reply;
-	u_long cache_replylen;
-	/*
-	 * Next node on the list, if there is a collision
-	 */
-	cache_ptr cache_next;
-};
+struct cache_node
+  {
+    /*
+     * Index into cache is xid, proc, vers, prog and address
+     */
+    u_long cache_xid;
+    u_long cache_proc;
+    u_long cache_vers;
+    u_long cache_prog;
+    struct sockaddr_in cache_addr;
+    /*
+     * The cached reply and length
+     */
+    char *cache_reply;
+    u_long cache_replylen;
+    /*
+     * Next node on the list, if there is a collision
+     */
+    cache_ptr cache_next;
+  };
 
 
 
 /*
  * The entire cache
  */
-struct udp_cache {
-	u_long uc_size;				/* size of cache */
-	cache_ptr *uc_entries;		/* hash table of entries in cache */
-	cache_ptr *uc_fifo;			/* fifo list of entries in cache */
-	u_long uc_nextvictim;		/* points to next victim in fifo list */
-	u_long uc_prog;				/* saved program number */
-	u_long uc_vers;				/* saved version number */
-	u_long uc_proc;				/* saved procedure number */
-	struct sockaddr_in uc_addr;	/* saved caller's address */
-};
+struct udp_cache
+  {
+    u_long uc_size;		/* size of cache */
+    cache_ptr *uc_entries;	/* hash table of entries in cache */
+    cache_ptr *uc_fifo;		/* fifo list of entries in cache */
+    u_long uc_nextvictim;	/* points to next victim in fifo list */
+    u_long uc_prog;		/* saved program number */
+    u_long uc_vers;		/* saved version number */
+    u_long uc_proc;		/* saved procedure number */
+    struct sockaddr_in uc_addr;	/* saved caller's address */
+  };
 
 
 /*
@@ -331,144 +459,154 @@ struct udp_cache {
 
 
 /*
- * Enable use of the cache. 
+ * Enable use of the cache.
  * Note: there is no disable.
  */
-int svcudp_enablecache(transp, size)
-SVCXPRT *transp;
-u_long size;
+int
+svcudp_enablecache (SVCXPRT *transp, u_long size)
 {
-	struct svcudp_data *su = su_data(transp);
-	struct udp_cache *uc;
-
-	if (su->su_cache != NULL) {
-		CACHE_PERROR("enablecache: cache already enabled");
-		return (0);
-	}
-	uc = ALLOC(struct udp_cache, 1);
-	if (uc == NULL) {
-		CACHE_PERROR("enablecache: could not allocate cache");
-		return (0);
-	}
-	uc->uc_size = size;
-	uc->uc_nextvictim = 0;
-	uc->uc_entries = ALLOC(cache_ptr, size * SPARSENESS);
-	if (uc->uc_entries == NULL) {
-		CACHE_PERROR("enablecache: could not allocate cache data");
-		return (0);
-	}
-	BZERO(uc->uc_entries, cache_ptr, size * SPARSENESS);
-	uc->uc_fifo = ALLOC(cache_ptr, size);
-	if (uc->uc_fifo == NULL) {
-		CACHE_PERROR("enablecache: could not allocate cache fifo");
-		return (0);
-	}
-	BZERO(uc->uc_fifo, cache_ptr, size);
-	su->su_cache = (char *) uc;
-	return (1);
+  struct svcudp_data *su = su_data (transp);
+  struct udp_cache *uc;
+
+  if (su->su_cache != NULL)
+    {
+      CACHE_PERROR (_("enablecache: cache already enabled"));
+      return 0;
+    }
+  uc = ALLOC (struct udp_cache, 1);
+  if (uc == NULL)
+    {
+      CACHE_PERROR (_("enablecache: could not allocate cache"));
+      return 0;
+    }
+  uc->uc_size = size;
+  uc->uc_nextvictim = 0;
+  uc->uc_entries = ALLOC (cache_ptr, size * SPARSENESS);
+  if (uc->uc_entries == NULL)
+    {
+      CACHE_PERROR (_("enablecache: could not allocate cache data"));
+      return 0;
+    }
+  BZERO (uc->uc_entries, cache_ptr, size * SPARSENESS);
+  uc->uc_fifo = ALLOC (cache_ptr, size);
+  if (uc->uc_fifo == NULL)
+    {
+      CACHE_PERROR (_("enablecache: could not allocate cache fifo"));
+      return 0;
+    }
+  BZERO (uc->uc_fifo, cache_ptr, size);
+  su->su_cache = (char *) uc;
+  return 1;
 }
 
 
 /*
  * Set an entry in the cache
  */
-static void cache_set(xprt, replylen)
-SVCXPRT *xprt;
-u_long replylen;
+static void
+cache_set (SVCXPRT *xprt, u_long replylen)
 {
-	register cache_ptr victim;
-	register cache_ptr *vicp;
-	register struct svcudp_data *su = su_data(xprt);
-	struct udp_cache *uc = (struct udp_cache *) su->su_cache;
-	u_int loc;
-	char *newbuf;
-
-	/*
-	 * Find space for the new entry, either by
-	 * reusing an old entry, or by mallocing a new one
-	 */
-	victim = uc->uc_fifo[uc->uc_nextvictim];
-	if (victim != NULL) {
-		loc = CACHE_LOC(xprt, victim->cache_xid);
-		for (vicp = &uc->uc_entries[loc];
-			 *vicp != NULL && *vicp != victim;
-			 vicp = &(*vicp)->cache_next);
-		if (*vicp == NULL) {
-			CACHE_PERROR("cache_set: victim not found");
-			return;
-		}
-		*vicp = victim->cache_next;	/* remote from cache */
-		newbuf = victim->cache_reply;
-	} else {
-		victim = ALLOC(struct cache_node, 1);
-
-		if (victim == NULL) {
-			CACHE_PERROR("cache_set: victim alloc failed");
-			return;
-		}
-		newbuf = mem_alloc(su->su_iosz);
-		if (newbuf == NULL) {
-			CACHE_PERROR("cache_set: could not allocate new rpc_buffer");
-			return;
-		}
+  cache_ptr victim;
+  cache_ptr *vicp;
+  struct svcudp_data *su = su_data (xprt);
+  struct udp_cache *uc = (struct udp_cache *) su->su_cache;
+  u_int loc;
+  char *newbuf;
+
+  /*
+   * Find space for the new entry, either by
+   * reusing an old entry, or by mallocing a new one
+   */
+  victim = uc->uc_fifo[uc->uc_nextvictim];
+  if (victim != NULL)
+    {
+      loc = CACHE_LOC (xprt, victim->cache_xid);
+      for (vicp = &uc->uc_entries[loc];
+	   *vicp != NULL && *vicp != victim;
+	   vicp = &(*vicp)->cache_next)
+	;
+      if (*vicp == NULL)
+	{
+	  CACHE_PERROR (_("cache_set: victim not found"));
+	  return;
 	}
-
-	/*
-	 * Store it away
-	 */
-	victim->cache_replylen = replylen;
-	victim->cache_reply = rpc_buffer(xprt);
-	rpc_buffer(xprt) = newbuf;
-	xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz,
-				  XDR_ENCODE);
-	victim->cache_xid = su->su_xid;
-	victim->cache_proc = uc->uc_proc;
-	victim->cache_vers = uc->uc_vers;
-	victim->cache_prog = uc->uc_prog;
-	victim->cache_addr = uc->uc_addr;
-	loc = CACHE_LOC(xprt, victim->cache_xid);
-	victim->cache_next = uc->uc_entries[loc];
-	uc->uc_entries[loc] = victim;
-	uc->uc_fifo[uc->uc_nextvictim++] = victim;
-	uc->uc_nextvictim %= uc->uc_size;
+      *vicp = victim->cache_next;	/* remote from cache */
+      newbuf = victim->cache_reply;
+    }
+  else
+    {
+      victim = ALLOC (struct cache_node, 1);
+      if (victim == NULL)
+	{
+	  CACHE_PERROR (_("cache_set: victim alloc failed"));
+	  return;
+	}
+      newbuf = mem_alloc (su->su_iosz);
+      if (newbuf == NULL)
+	{
+	  CACHE_PERROR (_("cache_set: could not allocate new rpc_buffer"));
+	  return;
+	}
+    }
+
+  /*
+   * Store it away
+   */
+  victim->cache_replylen = replylen;
+  victim->cache_reply = rpc_buffer (xprt);
+  rpc_buffer (xprt) = newbuf;
+  xdrmem_create (&(su->su_xdrs), rpc_buffer (xprt), su->su_iosz, XDR_ENCODE);
+  victim->cache_xid = su->su_xid;
+  victim->cache_proc = uc->uc_proc;
+  victim->cache_vers = uc->uc_vers;
+  victim->cache_prog = uc->uc_prog;
+  victim->cache_addr = uc->uc_addr;
+  loc = CACHE_LOC (xprt, victim->cache_xid);
+  victim->cache_next = uc->uc_entries[loc];
+  uc->uc_entries[loc] = victim;
+  uc->uc_fifo[uc->uc_nextvictim++] = victim;
+  uc->uc_nextvictim %= uc->uc_size;
 }
 
 /*
  * Try to get an entry from the cache
  * return 1 if found, 0 if not found
  */
-static int cache_get(xprt, msg, replyp, replylenp)
-SVCXPRT *xprt;
-struct rpc_msg *msg;
-char **replyp;
-u_long *replylenp;
+static int
+cache_get (xprt, msg, replyp, replylenp)
+     SVCXPRT *xprt;
+     struct rpc_msg *msg;
+     char **replyp;
+     u_long *replylenp;
 {
-	u_int loc;
-	register cache_ptr ent;
-	register struct svcudp_data *su = su_data(xprt);
-	register struct udp_cache *uc = (struct udp_cache *) su->su_cache;
-
-#	define EQADDR(a1, a2)	(bcmp((char*)&a1, (char*)&a2, sizeof(a1)) == 0)
-
-	loc = CACHE_LOC(xprt, su->su_xid);
-	for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next) {
-		if (ent->cache_xid == su->su_xid &&
-			ent->cache_proc == uc->uc_proc &&
-			ent->cache_vers == uc->uc_vers &&
-			ent->cache_prog == uc->uc_prog &&
-			EQADDR(ent->cache_addr, uc->uc_addr)) {
-			*replyp = ent->cache_reply;
-			*replylenp = ent->cache_replylen;
-			return (1);
-		}
+  u_int loc;
+  cache_ptr ent;
+  struct svcudp_data *su = su_data (xprt);
+  struct udp_cache *uc = (struct udp_cache *) su->su_cache;
+
+#define EQADDR(a1, a2)	(memcmp((char*)&a1, (char*)&a2, sizeof(a1)) == 0)
+
+  loc = CACHE_LOC (xprt, su->su_xid);
+  for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next)
+    {
+      if (ent->cache_xid == su->su_xid &&
+	  ent->cache_proc == uc->uc_proc &&
+	  ent->cache_vers == uc->uc_vers &&
+	  ent->cache_prog == uc->uc_prog &&
+	  EQADDR (ent->cache_addr, uc->uc_addr))
+	{
+	  *replyp = ent->cache_reply;
+	  *replylenp = ent->cache_replylen;
+	  return 1;
 	}
-	/*
-	 * Failed to find entry
-	 * Remember a few things so we can do a set later
-	 */
-	uc->uc_proc = msg->rm_call.cb_proc;
-	uc->uc_vers = msg->rm_call.cb_vers;
-	uc->uc_prog = msg->rm_call.cb_prog;
-	uc->uc_addr = xprt->xp_raddr;
-	return (0);
+    }
+  /*
+   * Failed to find entry
+   * Remember a few things so we can do a set later
+   */
+  uc->uc_proc = msg->rm_call.cb_proc;
+  uc->uc_vers = msg->rm_call.cb_vers;
+  uc->uc_prog = msg->rm_call.cb_prog;
+  memcpy (&uc->uc_addr, &xprt->xp_raddr, sizeof (uc->uc_addr));
+  return 0;
 }

+ 533 - 0
libc/inet/rpc/svc_unix.c

@@ -0,0 +1,533 @@
+/*
+ * 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.
+ */
+
+#define __FORCE_GLIBC
+#include <features.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpc/svc.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/poll.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#ifdef USE_IN_LIBIO
+# include <wchar.h>
+#endif
+
+/*
+ * 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 void svcunix_rendezvous_abort (void);
+
+/* This function makes sure abort() relocation goes through PLT
+   and thus can be lazy bound.  */
+static void
+svcunix_rendezvous_abort (void)
+{
+  abort ();
+};
+
+static const struct xp_ops svcunix_rendezvous_op =
+{
+  rendezvous_request,
+  rendezvous_stat,
+  (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svcunix_rendezvous_abort,
+  (bool_t (*) (SVCXPRT *, struct rpc_msg *)) svcunix_rendezvous_abort,
+  (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svcunix_rendezvous_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 (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));
+  xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
+  if (r == NULL || xprt == NULL)
+    {
+#ifdef USE_IN_LIBIO
+      if (_IO_fwide (stderr, 0) > 0)
+	__fwprintf (stderr, L"%s", _("svcunix_create: out of memory\n"));
+      else
+#endif
+	fputs (_("svcunix_create: out of memory\n"), stderr);
+      mem_free (r, sizeof (*r));
+      mem_free (xprt, sizeof (SVCXPRT));
+      return NULL;
+    }
+  r->sendsize = sendsize;
+  r->recvsize = recvsize;
+  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));
+  cd = (struct unix_conn *) mem_alloc (sizeof (struct unix_conn));
+  if (xprt == (SVCXPRT *) NULL || cd == (struct unix_conn *) NULL)
+    {
+#ifdef USE_IN_LIBIO
+      if (_IO_fwide (stderr, 0) > 0)
+	(void) __fwprintf (stderr, L"%s",
+			   _("svc_unix: makefd_xprt: out of memory\n"));
+      else
+#endif
+	(void) fputs (_("svc_unix: makefd_xprt: out of memory\n"), stderr);
+      mem_free (xprt, sizeof (SVCXPRT));
+      mem_free (cd, sizeof (struct unix_conn));
+      return NULL;
+    }
+  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);
+  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);
+  memcpy (&xprt->xp_raddr, &in_addr, sizeof (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));
+}
+
+#ifdef SCM_CREDENTIALS
+struct cmessage {
+  struct cmsghdr cmsg;
+  struct ucred cmcred;
+  /* hack to make sure we have enough memory */
+  char dummy[(CMSG_ALIGN (sizeof (struct ucred)) - sizeof (struct ucred) + sizeof (long))];
+};
+
+/* 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;
+#endif
+
+static int
+__msgread (int sock, void *data, size_t cnt)
+{
+  struct iovec iov;
+  struct msghdr msg;
+  int len;
+
+  iov.iov_base = data;
+  iov.iov_len = cnt;
+
+  msg.msg_iov = &iov;
+  msg.msg_iovlen = 1;
+  msg.msg_name = NULL;
+  msg.msg_namelen = 0;
+#ifdef SCM_CREDENTIALS
+  msg.msg_control = (caddr_t) &cm;
+  msg.msg_controllen = sizeof (struct cmessage);
+#endif
+  msg.msg_flags = 0;
+
+#ifdef SO_PASSCRED
+  {
+    int on = 1;
+    if (setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)))
+      return -1;
+  }
+#endif
+
+ restart:
+  len = recvmsg (sock, &msg, 0);
+  if (len >= 0)
+    {
+      if (msg.msg_flags & MSG_CTRUNC || len == 0)
+        return 0;
+      else
+        return len;
+    }
+  if (errno == EINTR)
+    goto restart;
+  return -1;
+}
+
+static int
+__msgwrite (int sock, void *data, size_t cnt)
+{
+#ifndef SCM_CREDENTIALS
+  /* We cannot implement this reliably.  */
+  __set_errno (ENOSYS);
+  return -1;
+#else
+  struct iovec iov;
+  struct msghdr msg;
+  struct cmsghdr *cmsg = &cm.cmsg;
+  struct ucred cred;
+  int len;
+
+  /* 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. */
+  cred.pid = getpid ();
+  cred.uid = geteuid ();
+  cred.gid = getegid ();
+
+  memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred));
+  cmsg->cmsg_level = SOL_SOCKET;
+  cmsg->cmsg_type = SCM_CREDENTIALS;
+  cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred);
+
+  iov.iov_base = data;
+  iov.iov_len = cnt;
+
+  msg.msg_iov = &iov;
+  msg.msg_iovlen = 1;
+  msg.msg_name = NULL;
+  msg.msg_namelen = 0;
+  msg.msg_control = cmsg;
+  msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
+  msg.msg_flags = 0;
+
+ restart:
+  len = sendmsg (sock, &msg, 0);
+  if (len >= 0)
+    return len;
+  if (errno == EINTR)
+    goto restart;
+  return -1;
+
+#endif
+}
+
+/*
+ * 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;
+  int milliseconds = 35 * 1000;
+  struct pollfd pollfd;
+
+  do
+    {
+      pollfd.fd = sock;
+      pollfd.events = POLLIN;
+      switch (poll (&pollfd, 1, milliseconds))
+	{
+	case -1:
+	  if (errno == EINTR)
+	    continue;
+	  /*FALLTHROUGH*/
+	case 0:
+	  goto fatal_err;
+	default:
+	  if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP)
+	      || (pollfd.revents & POLLNVAL))
+	    goto fatal_err;
+	  break;
+	}
+    }
+  while ((pollfd.revents & POLLIN) == 0);
+
+  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 */
+#ifdef SCM_CREDENTIALS
+      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);
+#endif
+      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 (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 (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;
+}

+ 535 - 345
libc/inet/rpc/xdr.c

@@ -6,29 +6,30 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
+#endif
 
 /*
  * xdr.c, Generic XDR routines implementation.
@@ -40,12 +41,21 @@
  * xdr.
  */
 
+#define __FORCE_GLIBC
+#define _GNU_SOURCE
+#include <features.h>
+
 #include <stdio.h>
+#include <limits.h>
 #include <string.h>
-#include <stdlib.h>
+
 #include <rpc/types.h>
 #include <rpc/xdr.h>
 
+#ifdef USE_IN_LIBIO
+# include <wchar.h>
+#endif
+
 /*
  * constants specific to the xdr "protocol"
  */
@@ -56,253 +66,400 @@
 /*
  * for unit alignment
  */
-static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
+static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
 
 /*
  * Free a data structure using XDR
  * Not a filter, but a convenient utility nonetheless
  */
-void xdr_free(proc, objp)
-xdrproc_t proc;
-char *objp;
+void
+xdr_free (xdrproc_t proc, char *objp)
 {
-	XDR x;
+  XDR x;
 
-	x.x_op = XDR_FREE;
-	(*proc) (&x, objp);
+  x.x_op = XDR_FREE;
+  (*proc) (&x, objp);
 }
 
 /*
  * XDR nothing
  */
-bool_t xdr_void( /* xdrs, addr */ )
-	/* XDR *xdrs; */
-	/* caddr_t addr; */
+bool_t
+xdr_void (void)
 {
-
-	return (TRUE);
+  return TRUE;
 }
 
 /*
  * XDR integers
  */
-bool_t xdr_int(xdrs, ip)
-XDR *xdrs;
-int *ip;
+bool_t
+xdr_int (XDR *xdrs, int *ip)
 {
 
-#ifdef lint
-	(void) (xdr_short(xdrs, (short *) ip));
-	return (xdr_long(xdrs, (long *) ip));
-#else
-	if (sizeof(int) == sizeof(long)) {
-		return (xdr_long(xdrs, (long *) ip));
-	} else {
-		return (xdr_short(xdrs, (short *) ip));
+#if INT_MAX < LONG_MAX
+  long l;
+
+  switch (xdrs->x_op)
+    {
+    case XDR_ENCODE:
+      l = (long) *ip;
+      return XDR_PUTLONG (xdrs, &l);
+
+    case XDR_DECODE:
+      if (!XDR_GETLONG (xdrs, &l))
+	{
+	  return FALSE;
 	}
+      *ip = (int) l;
+    case XDR_FREE:
+      return TRUE;
+    }
+  return FALSE;
+#elif INT_MAX == LONG_MAX
+  return xdr_long (xdrs, (long *) ip);
+#elif INT_MAX == SHRT_MAX
+  return xdr_short (xdrs, (short *) ip);
+#else
+#error unexpected integer sizes in_xdr_int()
 #endif
 }
 
 /*
  * XDR unsigned integers
  */
-bool_t xdr_u_int(xdrs, up)
-XDR *xdrs;
-u_int *up;
+bool_t
+xdr_u_int (XDR *xdrs, u_int *up)
 {
-
-#ifdef lint
-	(void) (xdr_short(xdrs, (short *) up));
-	return (xdr_u_long(xdrs, (u_long *) up));
-#else
-	if (sizeof(u_int) == sizeof(u_long)) {
-		return (xdr_u_long(xdrs, (u_long *) up));
-	} else {
-		return (xdr_short(xdrs, (short *) up));
+#if UINT_MAX < ULONG_MAX
+  u_long l;
+
+  switch (xdrs->x_op)
+    {
+    case XDR_ENCODE:
+      l = (u_long) * up;
+      return XDR_PUTLONG (xdrs, &l);
+
+    case XDR_DECODE:
+      if (!XDR_GETLONG (xdrs, &l))
+	{
+	  return FALSE;
 	}
+      *up = (u_int) l;
+    case XDR_FREE:
+      return TRUE;
+    }
+  return FALSE;
+#elif UINT_MAX == ULONG_MAX
+  return xdr_u_long (xdrs, (u_long *) up);
+#elif UINT_MAX == USHRT_MAX
+  return xdr_short (xdrs, (short *) up);
+#else
+#error unexpected integer sizes in_xdr_u_int()
 #endif
 }
 
 /*
  * XDR long integers
- * same as xdr_u_long - open coded to save a proc call!
+ * The definition of xdr_long() is kept for backward
+ * compatibility. Instead xdr_int() should be used.
  */
-bool_t xdr_long(xdrs, lp)
-register XDR *xdrs;
-long *lp;
+bool_t
+xdr_long (XDR *xdrs, long *lp)
 {
 
-	if (xdrs->x_op == XDR_ENCODE)
-		return (XDR_PUTLONG(xdrs, lp));
+  if (xdrs->x_op == XDR_ENCODE
+      && (sizeof (int32_t) == sizeof (long)
+	  || (int32_t) *lp == *lp))
+    return XDR_PUTLONG (xdrs, lp);
 
-	if (xdrs->x_op == XDR_DECODE)
-		return (XDR_GETLONG(xdrs, lp));
+  if (xdrs->x_op == XDR_DECODE)
+    return XDR_GETLONG (xdrs, lp);
 
-	if (xdrs->x_op == XDR_FREE)
-		return (TRUE);
+  if (xdrs->x_op == XDR_FREE)
+    return TRUE;
 
-	return (FALSE);
+  return FALSE;
 }
 
 /*
  * XDR unsigned long integers
- * same as xdr_long - open coded to save a proc call!
+ * The definition of xdr_u_long() is kept for backward
+ * compatibility. Instead xdr_u_int() should be used.
  */
-bool_t xdr_u_long(xdrs, ulp)
-register XDR *xdrs;
-u_long *ulp;
+bool_t
+xdr_u_long (XDR *xdrs, u_long *ulp)
 {
-
-	if (xdrs->x_op == XDR_DECODE)
-		return (XDR_GETLONG(xdrs, (long *) ulp));
-	if (xdrs->x_op == XDR_ENCODE)
-		return (XDR_PUTLONG(xdrs, (long *) ulp));
-	if (xdrs->x_op == XDR_FREE)
-		return (TRUE);
-	return (FALSE);
+  switch (xdrs->x_op)
+    {
+    case XDR_DECODE:
+      {
+	long int tmp;
+
+	if (XDR_GETLONG (xdrs, &tmp) == FALSE)
+	  return FALSE;
+
+	*ulp = (uint32_t) tmp;
+	return TRUE;
+      }
+
+    case XDR_ENCODE:
+      if (sizeof (uint32_t) != sizeof (u_long)
+	  && (uint32_t) *ulp != *ulp)
+	return FALSE;
+
+      return XDR_PUTLONG (xdrs, (long *) ulp);
+
+    case XDR_FREE:
+      return TRUE;
+    }
+  return FALSE;
 }
 
 /*
- * XDR short integers
+ * XDR hyper integers
+ * same as xdr_u_hyper - open coded to save a proc call!
  */
-bool_t xdr_short(xdrs, sp)
-register XDR *xdrs;
-short *sp;
+bool_t
+xdr_hyper (XDR *xdrs, quad_t *llp)
 {
-	long l;
+  long t1;
+  unsigned long int t2;
+
+  if (xdrs->x_op == XDR_ENCODE)
+    {
+      t1 = (long) ((*llp) >> 32);
+      t2 = (long) (*llp);
+      return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
+    }
+
+  if (xdrs->x_op == XDR_DECODE)
+    {
+      if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
+	return FALSE;
+      *llp = ((quad_t) t1) << 32;
+      *llp |= t2;
+      return TRUE;
+    }
+
+  if (xdrs->x_op == XDR_FREE)
+    return TRUE;
+
+  return FALSE;
+}
 
-	switch (xdrs->x_op) {
 
-	case XDR_ENCODE:
-		l = (long) *sp;
-		return (XDR_PUTLONG(xdrs, &l));
+/*
+ * XDR hyper integers
+ * same as xdr_hyper - open coded to save a proc call!
+ */
+bool_t
+xdr_u_hyper (XDR *xdrs, u_quad_t *ullp)
+{
+  unsigned long t1;
+  unsigned long t2;
+
+  if (xdrs->x_op == XDR_ENCODE)
+    {
+      t1 = (unsigned long) ((*ullp) >> 32);
+      t2 = (unsigned long) (*ullp);
+      return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
+    }
+
+  if (xdrs->x_op == XDR_DECODE)
+    {
+      if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
+	return FALSE;
+      *ullp = ((u_quad_t) t1) << 32;
+      *ullp |= t2;
+      return TRUE;
+    }
+
+  if (xdrs->x_op == XDR_FREE)
+    return TRUE;
+
+  return FALSE;
+}
 
-	case XDR_DECODE:
-		if (!XDR_GETLONG(xdrs, &l)) {
-			return (FALSE);
-		}
-		*sp = (short) l;
-		return (TRUE);
+bool_t
+xdr_longlong_t (XDR *xdrs, quad_t *llp)
+{
+  return xdr_hyper (xdrs, llp);
+}
 
-	case XDR_FREE:
-		return (TRUE);
-	}
-	return (FALSE);
+bool_t
+xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp)
+{
+  return xdr_u_hyper (xdrs, ullp);
 }
 
 /*
- * XDR unsigned short integers
+ * XDR short integers
  */
-bool_t xdr_u_short(xdrs, usp)
-register XDR *xdrs;
-u_short *usp;
+bool_t
+xdr_short (XDR *xdrs, short *sp)
 {
-	u_long l;
-
-	switch (xdrs->x_op) {
-
-	case XDR_ENCODE:
-		l = (u_long) * usp;
-		return (XDR_PUTLONG(xdrs, &l));
+  long l;
+
+  switch (xdrs->x_op)
+    {
+    case XDR_ENCODE:
+      l = (long) *sp;
+      return XDR_PUTLONG (xdrs, &l);
+
+    case XDR_DECODE:
+      if (!XDR_GETLONG (xdrs, &l))
+	{
+	  return FALSE;
+	}
+      *sp = (short) l;
+      return TRUE;
 
-	case XDR_DECODE:
-		if (!XDR_GETLONG(xdrs, &l)) {
-			return (FALSE);
-		}
-		*usp = (u_short) l;
-		return (TRUE);
+    case XDR_FREE:
+      return TRUE;
+    }
+  return FALSE;
+}
 
-	case XDR_FREE:
-		return (TRUE);
+/*
+ * XDR unsigned short integers
+ */
+bool_t
+xdr_u_short (XDR *xdrs, u_short *usp)
+{
+  u_long l;
+
+  switch (xdrs->x_op)
+    {
+    case XDR_ENCODE:
+      l = (u_long) * usp;
+      return XDR_PUTLONG (xdrs, &l);
+
+    case XDR_DECODE:
+      if (!XDR_GETLONG (xdrs, &l))
+	{
+	  return FALSE;
 	}
-	return (FALSE);
+      *usp = (u_short) l;
+      return TRUE;
+
+    case XDR_FREE:
+      return TRUE;
+    }
+  return FALSE;
 }
 
 
 /*
  * XDR a char
  */
-bool_t xdr_char(xdrs, cp)
-XDR *xdrs;
-char *cp;
+bool_t
+xdr_char (XDR *xdrs, char *cp)
 {
-	int i;
-
-	i = (*cp);
-	if (!xdr_int(xdrs, &i)) {
-		return (FALSE);
-	}
-	*cp = i;
-	return (TRUE);
+  int i;
+
+  i = (*cp);
+  if (!xdr_int (xdrs, &i))
+    {
+      return FALSE;
+    }
+  *cp = i;
+  return TRUE;
 }
 
 /*
  * XDR an unsigned char
  */
-bool_t xdr_u_char (XDR *xdrs, u_char *cp)
+bool_t
+xdr_u_char (XDR *xdrs, u_char *cp)
 {
-	u_int u;
-
-	u = (*cp);
-	if (!xdr_u_int(xdrs, &u)) {
-		return (FALSE);
-	}
-	*cp = u;
-	return (TRUE);
+  u_int u;
+
+  u = (*cp);
+  if (!xdr_u_int (xdrs, &u))
+    {
+      return FALSE;
+    }
+  *cp = u;
+  return TRUE;
 }
 
 /*
  * XDR booleans
  */
-bool_t xdr_bool(xdrs, bp)
-register XDR *xdrs;
-bool_t *bp;
+bool_t
+xdr_bool (XDR *xdrs, bool_t *bp)
 {
-	long lb;
-
-	switch (xdrs->x_op) {
-
-	case XDR_ENCODE:
-		lb = *bp ? XDR_TRUE : XDR_FALSE;
-		return (XDR_PUTLONG(xdrs, &lb));
-
-	case XDR_DECODE:
-		if (!XDR_GETLONG(xdrs, &lb)) {
-			return (FALSE);
-		}
-		*bp = (lb == XDR_FALSE) ? FALSE : TRUE;
-		return (TRUE);
-
-	case XDR_FREE:
-		return (TRUE);
+  long lb;
+
+  switch (xdrs->x_op)
+    {
+    case XDR_ENCODE:
+      lb = *bp ? XDR_TRUE : XDR_FALSE;
+      return XDR_PUTLONG (xdrs, &lb);
+
+    case XDR_DECODE:
+      if (!XDR_GETLONG (xdrs, &lb))
+	{
+	  return FALSE;
 	}
-	return (FALSE);
+      *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
+      return TRUE;
+
+    case XDR_FREE:
+      return TRUE;
+    }
+  return FALSE;
 }
 
 /*
  * XDR enumerations
  */
-bool_t xdr_enum(xdrs, ep)
-XDR *xdrs;
-enum_t *ep;
+bool_t
+xdr_enum (XDR *xdrs, enum_t *ep)
 {
-#ifndef lint
-	enum sizecheck { SIZEVAL };	/* used to find the size of an enum */
-
-	/*
-	 * enums are treated as ints
-	 */
-	if (sizeof(enum sizecheck) == sizeof(long)) {
-		return (xdr_long(xdrs, (long *) ep));
-	} else if (sizeof(enum sizecheck) == sizeof(short)) {
-		return (xdr_short(xdrs, (short *) ep));
-	} else {
-		return (FALSE);
+  enum sizecheck
+    {
+      SIZEVAL
+    };				/* used to find the size of an enum */
+
+  /*
+   * enums are treated as ints
+   */
+  if (sizeof (enum sizecheck) == 4)
+    {
+#if INT_MAX < LONG_MAX
+      long l;
+
+      switch (xdrs->x_op)
+	{
+	case XDR_ENCODE:
+	  l = *ep;
+	  return XDR_PUTLONG (xdrs, &l);
+
+	case XDR_DECODE:
+	  if (!XDR_GETLONG (xdrs, &l))
+	    {
+	      return FALSE;
+	    }
+	  *ep = l;
+	case XDR_FREE:
+	  return TRUE;
+
 	}
+      return FALSE;
 #else
-	(void) (xdr_short(xdrs, (short *) ep));
-	return (xdr_long(xdrs, (long *) ep));
+      return xdr_long (xdrs, (long *) ep);
 #endif
+    }
+  else if (sizeof (enum sizecheck) == sizeof (short))
+    {
+      return xdr_short (xdrs, (short *) ep);
+    }
+  else
+    {
+      return FALSE;
+    }
 }
 
 /*
@@ -310,50 +467,49 @@ enum_t *ep;
  * Allows the specification of a fixed size sequence of opaque bytes.
  * cp points to the opaque object and cnt gives the byte length.
  */
-bool_t xdr_opaque(xdrs, cp, cnt)
-register XDR *xdrs;
-caddr_t cp;
-register u_int cnt;
+bool_t
+xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt)
 {
-	register u_int rndup;
-	static u_long crud[BYTES_PER_XDR_UNIT];
-
-	/*
-	 * if no data we are done
-	 */
-	if (cnt == 0)
-		return (TRUE);
-
-	/*
-	 * round byte count to full xdr units
-	 */
-	rndup = cnt % BYTES_PER_XDR_UNIT;
-	if (rndup > 0)
-		rndup = BYTES_PER_XDR_UNIT - rndup;
-
-	if (xdrs->x_op == XDR_DECODE) {
-		if (!XDR_GETBYTES(xdrs, cp, cnt)) {
-			return (FALSE);
-		}
-		if (rndup == 0)
-			return (TRUE);
-		return (XDR_GETBYTES(xdrs, (caddr_t) crud, rndup));
-	}
-
-	if (xdrs->x_op == XDR_ENCODE) {
-		if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
-			return (FALSE);
-		}
-		if (rndup == 0)
-			return (TRUE);
-		return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
+  u_int rndup;
+  static char crud[BYTES_PER_XDR_UNIT];
+
+  /*
+   * if no data we are done
+   */
+  if (cnt == 0)
+    return TRUE;
+
+  /*
+   * round byte count to full xdr units
+   */
+  rndup = cnt % BYTES_PER_XDR_UNIT;
+  if (rndup > 0)
+    rndup = BYTES_PER_XDR_UNIT - rndup;
+
+  switch (xdrs->x_op)
+    {
+    case XDR_DECODE:
+      if (!XDR_GETBYTES (xdrs, cp, cnt))
+	{
+	  return FALSE;
 	}
-
-	if (xdrs->x_op == XDR_FREE) {
-		return (TRUE);
+      if (rndup == 0)
+	return TRUE;
+      return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup);
+
+    case XDR_ENCODE:
+      if (!XDR_PUTBYTES (xdrs, cp, cnt))
+	{
+	  return FALSE;
 	}
-
-	return (FALSE);
+      if (rndup == 0)
+	return TRUE;
+      return XDR_PUTBYTES (xdrs, xdr_zero, rndup);
+
+    case XDR_FREE:
+      return TRUE;
+    }
+  return FALSE;
 }
 
 /*
@@ -361,70 +517,83 @@ register u_int cnt;
  * *cpp is a pointer to the bytes, *sizep is the count.
  * If *cpp is NULL maxsize bytes are allocated
  */
-bool_t xdr_bytes(xdrs, cpp, sizep, maxsize)
-register XDR *xdrs;
-char **cpp;
-register u_int *sizep;
-u_int maxsize;
+bool_t
+xdr_bytes (xdrs, cpp, sizep, maxsize)
+     XDR *xdrs;
+     char **cpp;
+     u_int *sizep;
+     u_int maxsize;
 {
-	register char *sp = *cpp;	/* sp is the actual string pointer */
-	register u_int nodesize;
-
-	/*
-	 * first deal with the length since xdr bytes are counted
-	 */
-	if (!xdr_u_int(xdrs, sizep)) {
-		return (FALSE);
+  char *sp = *cpp;	/* sp is the actual string pointer */
+  u_int nodesize;
+
+  /*
+   * first deal with the length since xdr bytes are counted
+   */
+  if (!xdr_u_int (xdrs, sizep))
+    {
+      return FALSE;
+    }
+  nodesize = *sizep;
+  if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE))
+    {
+      return FALSE;
+    }
+
+  /*
+   * now deal with the actual bytes
+   */
+  switch (xdrs->x_op)
+    {
+    case XDR_DECODE:
+      if (nodesize == 0)
+	{
+	  return TRUE;
 	}
-	nodesize = *sizep;
-	if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
-		return (FALSE);
+      if (sp == NULL)
+	{
+	  *cpp = sp = (char *) mem_alloc (nodesize);
 	}
+      if (sp == NULL)
+	{
+#ifdef USE_IN_LIBIO
+	  if (_IO_fwide (stderr, 0) > 0)
+	    (void) __fwprintf (stderr, L"%s", _("xdr_bytes: out of memory\n"));
+	  else
+#endif
+	    (void) fputs (_("xdr_bytes: out of memory\n"), stderr);
+	  return FALSE;
+	}
+      /* fall into ... */
 
-	/*
-	 * now deal with the actual bytes
-	 */
-	switch (xdrs->x_op) {
-
-	case XDR_DECODE:
-		if (nodesize == 0) {
-			return (TRUE);
-		}
-		if (sp == NULL) {
-			*cpp = sp = (char *) mem_alloc(nodesize);
-		}
-		if (sp == NULL) {
-			(void) fprintf(stderr, "xdr_bytes: out of memory\n");
-			return (FALSE);
-		}
-		/* fall into ... */
-
-	case XDR_ENCODE:
-		return (xdr_opaque(xdrs, sp, nodesize));
+    case XDR_ENCODE:
+      return xdr_opaque (xdrs, sp, nodesize);
 
-	case XDR_FREE:
-		if (sp != NULL) {
-			mem_free(sp, nodesize);
-			*cpp = NULL;
-		}
-		return (TRUE);
+    case XDR_FREE:
+      if (sp != NULL)
+	{
+	  mem_free (sp, nodesize);
+	  *cpp = NULL;
 	}
-	return (FALSE);
+      return TRUE;
+    }
+  return FALSE;
 }
 
 /*
  * Implemented here due to commonality of the object.
  */
-bool_t xdr_netobj(xdrs, np)
-XDR *xdrs;
-struct netobj *np;
+bool_t
+xdr_netobj (xdrs, np)
+     XDR *xdrs;
+     struct netobj *np;
 {
 
-	return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
+  return xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ);
 }
 
 /*
- * XDR a descriminated union
+ * XDR a discriminated union
  * Support routine for discriminated unions.
  * You create an array of xdrdiscrim structures, terminated with
  * an entry with a null procedure pointer.  The routine gets
@@ -434,37 +603,40 @@ struct netobj *np;
  * routine may be called.
  * If there is no specific or default routine an error is returned.
  */
-bool_t xdr_union(xdrs, dscmp, unp, choices, dfault)
-register XDR *xdrs;
-enum_t *dscmp;					/* enum to decide which arm to work on */
-char *unp;						/* the union itself */
-const struct xdr_discrim *choices;	/* [value, xdr proc] for each arm */
-xdrproc_t dfault;				/* default xdr routine */
+bool_t
+xdr_union (xdrs, dscmp, unp, choices, dfault)
+     XDR *xdrs;
+     enum_t *dscmp;		/* enum to decide which arm to work on */
+     char *unp;			/* the union itself */
+     const struct xdr_discrim *choices;	/* [value, xdr proc] for each arm */
+     xdrproc_t dfault;		/* default xdr routine */
 {
-	register enum_t dscm;
-
-	/*
-	 * we deal with the discriminator;  it's an enum
-	 */
-	if (!xdr_enum(xdrs, dscmp)) {
-		return (FALSE);
-	}
-	dscm = *dscmp;
-
-	/*
-	 * search choices for a value that matches the discriminator.
-	 * if we find one, execute the xdr routine for that value.
-	 */
-	for (; choices->proc != NULL_xdrproc_t; choices++) {
-		if (choices->value == dscm)
-			return ((*(choices->proc)) (xdrs, unp, LASTUNSIGNED));
-	}
-
-	/*
-	 * no match - execute the default xdr routine if there is one
-	 */
-	return ((dfault == NULL_xdrproc_t) ? FALSE :
-			(*dfault) (xdrs, unp, LASTUNSIGNED));
+  enum_t dscm;
+
+  /*
+   * we deal with the discriminator;  it's an enum
+   */
+  if (!xdr_enum (xdrs, dscmp))
+    {
+      return FALSE;
+    }
+  dscm = *dscmp;
+
+  /*
+   * search choices for a value that matches the discriminator.
+   * if we find one, execute the xdr routine for that value.
+   */
+  for (; choices->proc != NULL_xdrproc_t; choices++)
+    {
+      if (choices->value == dscm)
+	return (*(choices->proc)) (xdrs, unp, LASTUNSIGNED);
+    }
+
+  /*
+   * no match - execute the default xdr routine if there is one
+   */
+  return ((dfault == NULL_xdrproc_t) ? FALSE :
+	  (*dfault) (xdrs, unp, LASTUNSIGNED));
 }
 
 
@@ -482,76 +654,94 @@ xdrproc_t dfault;				/* default xdr routine */
  * storage is allocated.  The last parameter is the max allowed length
  * of the string as specified by a protocol.
  */
-bool_t xdr_string(xdrs, cpp, maxsize)
-register XDR *xdrs;
-char **cpp;
-u_int maxsize;
+bool_t
+xdr_string (xdrs, cpp, maxsize)
+     XDR *xdrs;
+     char **cpp;
+     u_int maxsize;
 {
-	register char *sp = *cpp;	/* sp is the actual string pointer */
-	u_int size;
-	u_int nodesize;
-
-	/*
-	 * first deal with the length since xdr strings are counted-strings
-	 */
-	switch (xdrs->x_op) {
-	case XDR_FREE:
-		if (sp == NULL) {
-			return (TRUE);		/* already free */
-		}
-		/* fall through... */
-	case XDR_ENCODE:
-		size = strlen(sp);
-		break;
-	default:					/* silence the warnings */
+  char *sp = *cpp;	/* sp is the actual string pointer */
+  u_int size;
+  u_int nodesize;
+
+  /*
+   * first deal with the length since xdr strings are counted-strings
+   */
+  switch (xdrs->x_op)
+    {
+    case XDR_FREE:
+      if (sp == NULL)
+	{
+	  return TRUE;		/* already free */
 	}
-	if (!xdr_u_int(xdrs, &size)) {
-		return (FALSE);
+      /* fall through... */
+    case XDR_ENCODE:
+      if (sp == NULL)
+	return FALSE;
+      size = strlen (sp);
+      break;
+    case XDR_DECODE:
+      break;
+    }
+  if (!xdr_u_int (xdrs, &size))
+    {
+      return FALSE;
+    }
+  if (size > maxsize)
+    {
+      return FALSE;
+    }
+  nodesize = size + 1;
+
+  /*
+   * now deal with the actual bytes
+   */
+  switch (xdrs->x_op)
+    {
+    case XDR_DECODE:
+      if (nodesize == 0)
+	{
+	  return TRUE;
 	}
-	if (size > maxsize) {
-		return (FALSE);
-	}
-	nodesize = size + 1;
-
-	/*
-	 * now deal with the actual bytes
-	 */
-	switch (xdrs->x_op) {
-
-	case XDR_DECODE:
-		if (nodesize == 0) {
-			return (TRUE);
-		}
-		if (sp == NULL)
-			*cpp = sp = (char *) mem_alloc(nodesize);
-		if (sp == NULL) {
-			(void) fprintf(stderr, "xdr_string: out of memory\n");
-			return (FALSE);
-		}
-		sp[size] = 0;
-		/* fall into ... */
-
-	case XDR_ENCODE:
-		return (xdr_opaque(xdrs, sp, size));
-
-	case XDR_FREE:
-		mem_free(sp, nodesize);
-		*cpp = NULL;
-		return (TRUE);
+      if (sp == NULL)
+	*cpp = sp = (char *) mem_alloc (nodesize);
+      if (sp == NULL)
+	{
+#ifdef USE_IN_LIBIO
+	  if (_IO_fwide (stderr, 0) > 0)
+	    (void) __fwprintf (stderr, L"%s",
+			       _("xdr_string: out of memory\n"));
+	  else
+#endif
+	    (void) fputs (_("xdr_string: out of memory\n"), stderr);
+	  return FALSE;
 	}
-	return (FALSE);
+      sp[size] = 0;
+      /* fall into ... */
+
+    case XDR_ENCODE:
+      return xdr_opaque (xdrs, sp, size);
+
+    case XDR_FREE:
+      mem_free (sp, nodesize);
+      *cpp = NULL;
+      return TRUE;
+    }
+  return FALSE;
 }
 
-/* 
- * Wrapper for xdr_string that can be called directly from 
+/*
+ * Wrapper for xdr_string that can be called directly from
  * routines like clnt_call
  */
-bool_t xdr_wrapstring(xdrs, cpp)
-XDR *xdrs;
-char **cpp;
+bool_t
+xdr_wrapstring (xdrs, cpp)
+     XDR *xdrs;
+     char **cpp;
 {
-	if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
-		return (TRUE);
-	}
-	return (FALSE);
+  if (xdr_string (xdrs, cpp, LASTUNSIGNED))
+    {
+      return TRUE;
+    }
+  return FALSE;
 }

+ 104 - 79
libc/inet/rpc/xdr_array.c

@@ -6,32 +6,33 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro";
+#endif
 
 /*
- * xdr_array.c, Generic XDR routines impelmentation.
+ * xdr_array.c, Generic XDR routines implementation.
  *
  * Copyright (C) 1984, Sun Microsystems, Inc.
  *
@@ -39,12 +40,19 @@
  * arrays.  See xdr.h for more info on the interface to xdr.
  */
 
+#define __FORCE_GLIBC
+#define _GNU_SOURCE
+#include <features.h>
+
 #include <stdio.h>
 #include <string.h>
-
 #include <rpc/types.h>
 #include <rpc/xdr.h>
 
+#ifdef USE_IN_LIBIO
+# include <wchar.h>
+#endif
+
 #define LASTUNSIGNED	((u_int)0-1)
 
 
@@ -55,68 +63,82 @@
  * elsize is the size (in bytes) of each element, and elproc is the
  * xdr procedure to call to handle each element of the array.
  */
-bool_t xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc)
-register XDR *xdrs;
-caddr_t *addrp;					/* array pointer */
-u_int *sizep;					/* number of elements */
-u_int maxsize;					/* max numberof elements */
-u_int elsize;					/* size in bytes of each element */
-xdrproc_t elproc;				/* xdr routine to handle each element */
+bool_t
+xdr_array (xdrs, addrp, sizep, maxsize, elsize, elproc)
+     XDR *xdrs;
+     caddr_t *addrp;		/* array pointer */
+     u_int *sizep;		/* number of elements */
+     u_int maxsize;		/* max numberof elements */
+     u_int elsize;		/* size in bytes of each element */
+     xdrproc_t elproc;		/* xdr routine to handle each element */
 {
-	register u_int i;
-	register caddr_t target = *addrp;
-	register u_int c;			/* the actual element count */
-	register bool_t stat = TRUE;
-	register u_int nodesize;
+  u_int i;
+  caddr_t target = *addrp;
+  u_int c;		/* the actual element count */
+  bool_t stat = TRUE;
+  u_int nodesize;
 
-	/* like strings, arrays are really counted arrays */
-	if (!xdr_u_int(xdrs, sizep)) {
-		return (FALSE);
-	}
-	c = *sizep;
-	if ((c > maxsize) && (xdrs->x_op != XDR_FREE)) {
-		return (FALSE);
-	}
-	nodesize = c * elsize;
+  /* like strings, arrays are really counted arrays */
+  if (!xdr_u_int (xdrs, sizep))
+    {
+      return FALSE;
+    }
+  c = *sizep;
+  if ((c > maxsize) && (xdrs->x_op != XDR_FREE))
+    {
+      return FALSE;
+    }
+  nodesize = c * elsize;
 
-	/*
-	 * if we are deserializing, we may need to allocate an array.
-	 * We also save time by checking for a null array if we are freeing.
-	 */
+  /*
+   * if we are deserializing, we may need to allocate an array.
+   * We also save time by checking for a null array if we are freeing.
+   */
+  if (target == NULL)
+    switch (xdrs->x_op)
+      {
+      case XDR_DECODE:
+	if (c == 0)
+	  return TRUE;
+	*addrp = target = mem_alloc (nodesize);
 	if (target == NULL)
-		switch (xdrs->x_op) {
-		case XDR_DECODE:
-			if (c == 0)
-				return (TRUE);
-			*addrp = target = mem_alloc(nodesize);
-			if (target == NULL) {
-				(void) fprintf(stderr, "xdr_array: out of memory\n");
-				return (FALSE);
-			}
-			bzero(target, nodesize);
-			break;
+	  {
+#ifdef USE_IN_LIBIO
+	    if (_IO_fwide (stderr, 0) > 0)
+	      (void) __fwprintf (stderr, L"%s",
+				 _("xdr_array: out of memory\n"));
+	    else
+#endif
+	      (void) fputs (_("xdr_array: out of memory\n"), stderr);
+	    return FALSE;
+	  }
+	bzero (target, nodesize);
+	break;
 
-		case XDR_FREE:
-			return (TRUE);
-		default:				/* silence the warnings */
-		}
+      case XDR_FREE:
+	return TRUE;
+      default:
+	break;
+      }
 
-	/*
-	 * now we xdr each element of array
-	 */
-	for (i = 0; (i < c) && stat; i++) {
-		stat = (*elproc) (xdrs, target, LASTUNSIGNED);
-		target += elsize;
-	}
+  /*
+   * now we xdr each element of array
+   */
+  for (i = 0; (i < c) && stat; i++)
+    {
+      stat = (*elproc) (xdrs, target, LASTUNSIGNED);
+      target += elsize;
+    }
 
-	/*
-	 * the array may need freeing
-	 */
-	if (xdrs->x_op == XDR_FREE) {
-		mem_free(*addrp, nodesize);
-		*addrp = NULL;
-	}
-	return (stat);
+  /*
+   * the array may need freeing
+   */
+  if (xdrs->x_op == XDR_FREE)
+    {
+      mem_free (*addrp, nodesize);
+      *addrp = NULL;
+    }
+  return stat;
 }
 
 /*
@@ -129,22 +151,25 @@ xdrproc_t elproc;				/* xdr routine to handle each element */
  * > elemsize: size of each element
  * > xdr_elem: routine to XDR each element
  */
-bool_t xdr_vector(xdrs, basep, nelem, elemsize, xdr_elem)
-register XDR *xdrs;
-register char *basep;
-register u_int nelem;
-register u_int elemsize;
-register xdrproc_t xdr_elem;
+bool_t
+xdr_vector (xdrs, basep, nelem, elemsize, xdr_elem)
+     XDR *xdrs;
+     char *basep;
+     u_int nelem;
+     u_int elemsize;
+     xdrproc_t xdr_elem;
 {
-	register u_int i;
-	register char *elptr;
+  u_int i;
+  char *elptr;
 
-	elptr = basep;
-	for (i = 0; i < nelem; i++) {
-		if (!(*xdr_elem) (xdrs, elptr, LASTUNSIGNED)) {
-			return (FALSE);
-		}
-		elptr += elemsize;
+  elptr = basep;
+  for (i = 0; i < nelem; i++)
+    {
+      if (!(*xdr_elem) (xdrs, elptr, LASTUNSIGNED))
+	{
+	  return FALSE;
 	}
-	return (TRUE);
+      elptr += elemsize;
+    }
+  return TRUE;
 }

+ 135 - 105
libc/inet/rpc/xdr_float.c

@@ -6,32 +6,33 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";
+#endif
 
 /*
- * xdr_float.c, Generic XDR routines impelmentation.
+ * xdr_float.c, Generic XDR routines implementation.
  *
  * Copyright (C) 1984, Sun Microsystems, Inc.
  *
@@ -40,7 +41,12 @@
  * xdr.
  */
 
+#define __FORCE_GLIBC
+#define _GNU_SOURCE
+#include <features.h>
+
 #include <stdio.h>
+#include <endian.h>
 
 #include <rpc/types.h>
 #include <rpc/xdr.h>
@@ -50,26 +56,23 @@
  * This routine works on Suns (Sky / 68000's) and Vaxen.
  */
 
-#ifdef __linux__
-/* cheat big time */
-#define sparc
-#endif
+#define LSW	(__FLOAT_WORD_ORDER == __BIG_ENDIAN)
 
 #ifdef vax
 
 /* What IEEE single precision floating point looks like on a Vax */
-struct ieee_single {
-	unsigned int mantissa:23;
-	unsigned int exp:8;
-	unsigned int sign:1;
+struct	ieee_single {
+	unsigned int	mantissa: 23;
+	unsigned int	exp     : 8;
+	unsigned int	sign    : 1;
 };
 
 /* Vax single precision floating point */
-struct vax_single {
-	unsigned int mantissa1:7;
-	unsigned int exp:8;
-	unsigned int sign:1;
-	unsigned int mantissa2:16;
+struct	vax_single {
+	unsigned int	mantissa1 : 7;
+	unsigned int	exp       : 8;
+	unsigned int	sign      : 1;
+	unsigned int	mantissa2 : 16;
 };
 
 #define VAX_SNG_BIAS	0x81
@@ -79,22 +82,19 @@ static struct sgl_limits {
 	struct vax_single s;
 	struct ieee_single ieee;
 } sgl_limits[2] = {
-	{ {
-	0x7f, 0xff, 0x0, 0xffff},	/* Max Vax */
-	{
-	0x0, 0xff, 0x0}},			/* Max IEEE */
-	{ {
-	0x0, 0x0, 0x0, 0x0},		/* Min Vax */
-	{
-	0x0, 0x0, 0x0}}				/* Min IEEE */
+	{{ 0x7f, 0xff, 0x0, 0xffff },	/* Max Vax */
+	{ 0x0, 0xff, 0x0 }},		/* Max IEEE */
+	{{ 0x0, 0x0, 0x0, 0x0 },	/* Min Vax */
+	{ 0x0, 0x0, 0x0 }}		/* Min IEEE */
 };
-#endif							/* vax */
+#endif /* vax */
 
-bool_t xdr_float(xdrs, fp)
-register XDR *xdrs;
-register float *fp;
+bool_t
+xdr_float(xdrs, fp)
+     XDR *xdrs;
+     float *fp;
 {
-#if !defined(mc68000) && !defined(sparc)
+#ifdef vax
 	struct ieee_single is;
 	struct vax_single vs, *vsp;
 	struct sgl_limits *lim;
@@ -103,14 +103,11 @@ register float *fp;
 	switch (xdrs->x_op) {
 
 	case XDR_ENCODE:
-#if defined(mc68000) || defined(sparc)
-		return (XDR_PUTLONG(xdrs, (long *) fp));
-#else
-		vs = *((struct vax_single *) fp);
+#ifdef vax
+		vs = *((struct vax_single *)fp);
 		for (i = 0, lim = sgl_limits;
-
-			 i < sizeof(sgl_limits) / sizeof(struct sgl_limits);
-			 i++, lim++) {
+			i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
+			i++, lim++) {
 			if ((vs.mantissa2 == lim->s.mantissa2) &&
 				(vs.exp == lim->s.exp) &&
 				(vs.mantissa1 == lim->s.mantissa1)) {
@@ -120,22 +117,27 @@ register float *fp;
 		}
 		is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
 		is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
-	  shipit:
+	shipit:
 		is.sign = vs.sign;
-		return (XDR_PUTLONG(xdrs, (long *) &is));
+		return (XDR_PUTLONG(xdrs, (long *)&is));
+#else
+		if (sizeof(float) == sizeof(long))
+			return (XDR_PUTLONG(xdrs, (long *)fp));
+		else if (sizeof(float) == sizeof(int)) {
+			long tmp = *(int *)fp;
+			return (XDR_PUTLONG(xdrs, &tmp));
+		}
+		break;
 #endif
 
 	case XDR_DECODE:
-#if defined(mc68000) || defined(sparc)
-		return (XDR_GETLONG(xdrs, (long *) fp));
-#else
-		vsp = (struct vax_single *) fp;
-		if (!XDR_GETLONG(xdrs, (long *) &is))
+#ifdef vax
+		vsp = (struct vax_single *)fp;
+		if (!XDR_GETLONG(xdrs, (long *)&is))
 			return (FALSE);
 		for (i = 0, lim = sgl_limits;
-
-			 i < sizeof(sgl_limits) / sizeof(struct sgl_limits);
-			 i++, lim++) {
+			i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
+			i++, lim++) {
 			if ((is.exp == lim->ieee.exp) &&
 				(is.mantissa == lim->ieee.mantissa)) {
 				*vsp = lim->s;
@@ -145,9 +147,20 @@ register float *fp;
 		vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
 		vsp->mantissa2 = is.mantissa;
 		vsp->mantissa1 = (is.mantissa >> 16);
-	  doneit:
+	doneit:
 		vsp->sign = is.sign;
 		return (TRUE);
+#else
+		if (sizeof(float) == sizeof(long))
+			return (XDR_GETLONG(xdrs, (long *)fp));
+		else if (sizeof(float) == sizeof(int)) {
+			long tmp;
+			if (XDR_GETLONG(xdrs, &tmp)) {
+				*(int *)fp = tmp;
+				return (TRUE);
+			}
+		}
+		break;
 #endif
 
 	case XDR_FREE:
@@ -162,21 +175,21 @@ register float *fp;
 
 #ifdef vax
 /* What IEEE double precision floating point looks like on a Vax */
-struct ieee_double {
-	unsigned int mantissa1:20;
-	unsigned int exp:11;
-	unsigned int sign:1;
-	unsigned int mantissa2:32;
+struct	ieee_double {
+	unsigned int	mantissa1 : 20;
+	unsigned int	exp       : 11;
+	unsigned int	sign      : 1;
+	unsigned int	mantissa2 : 32;
 };
 
 /* Vax double precision floating point */
-struct vax_double {
-	unsigned int mantissa1:7;
-	unsigned int exp:8;
-	unsigned int sign:1;
-	unsigned int mantissa2:16;
-	unsigned int mantissa3:16;
-	unsigned int mantissa4:16;
+struct  vax_double {
+	unsigned int	mantissa1 : 7;
+	unsigned int	exp       : 8;
+	unsigned int	sign      : 1;
+	unsigned int	mantissa2 : 16;
+	unsigned int	mantissa3 : 16;
+	unsigned int	mantissa4 : 16;
 };
 
 #define VAX_DBL_BIAS	0x81
@@ -184,31 +197,26 @@ struct vax_double {
 #define MASK(nbits)	((1 << nbits) - 1)
 
 static struct dbl_limits {
-	struct vax_double d;
-	struct ieee_double ieee;
+	struct	vax_double d;
+	struct	ieee_double ieee;
 } dbl_limits[2] = {
-	{ {
-	0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff},	/* Max Vax */
-	{
-	0x0, 0x7ff, 0x0, 0x0}},		/* Max IEEE */
-	{ {
-	0x0, 0x0, 0x0, 0x0, 0x0, 0x0},	/* Min Vax */
-	{
-	0x0, 0x0, 0x0, 0x0}}		/* Min IEEE */
+	{{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff },	/* Max Vax */
+	{ 0x0, 0x7ff, 0x0, 0x0 }},			/* Max IEEE */
+	{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},		/* Min Vax */
+	{ 0x0, 0x0, 0x0, 0x0 }}				/* Min IEEE */
 };
 
-#endif							/* vax */
+#endif /* vax */
 
 
-bool_t xdr_double(xdrs, dp)
-register XDR *xdrs;
-double *dp;
+bool_t
+xdr_double(xdrs, dp)
+     XDR *xdrs;
+     double *dp;
 {
-	register long *lp;
-
-#if !defined(mc68000) && !defined(sparc)
-	struct ieee_double id;
-	struct vax_double vd;
+#ifdef vax
+	struct	ieee_double id;
+	struct	vax_double vd;
 	register struct dbl_limits *lim;
 	int i;
 #endif
@@ -216,14 +224,11 @@ double *dp;
 	switch (xdrs->x_op) {
 
 	case XDR_ENCODE:
-#if defined(mc68000) || defined(sparc)
-		lp = (long *) dp;
-#else
-		vd = *((struct vax_double *) dp);
+#ifdef vax
+		vd = *((struct vax_double *)dp);
 		for (i = 0, lim = dbl_limits;
-
-			 i < sizeof(dbl_limits) / sizeof(struct dbl_limits);
-			 i++, lim++) {
+			i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
+			i++, lim++) {
 			if ((vd.mantissa4 == lim->d.mantissa4) &&
 				(vd.mantissa3 == lim->d.mantissa3) &&
 				(vd.mantissa2 == lim->d.mantissa2) &&
@@ -236,25 +241,34 @@ double *dp;
 		id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
 		id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
 		id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
-			(vd.mantissa3 << 13) | ((vd.mantissa4 >> 3) & MASK(13));
-	  shipit:
+				(vd.mantissa3 << 13) |
+				((vd.mantissa4 >> 3) & MASK(13));
+	shipit:
 		id.sign = vd.sign;
-		lp = (long *) &id;
+		dp = (double *)&id;
 #endif
-		return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp));
+		if (2*sizeof(long) == sizeof(double)) {
+			long *lp = (long *)dp;
+			return (XDR_PUTLONG(xdrs, lp+!LSW) &&
+				XDR_PUTLONG(xdrs, lp+LSW));
+		} else if (2*sizeof(int) == sizeof(double)) {
+			int *ip = (int *)dp;
+			long tmp[2];
+			tmp[0] = ip[!LSW];
+			tmp[1] = ip[LSW];
+			return (XDR_PUTLONG(xdrs, tmp) &&
+				XDR_PUTLONG(xdrs, tmp+1));
+		}
+		break;
 
 	case XDR_DECODE:
-#if defined(mc68000) || defined(sparc)
-		lp = (long *) dp;
-		return (XDR_GETLONG(xdrs, lp++) && XDR_GETLONG(xdrs, lp));
-#else
-		lp = (long *) &id;
+#ifdef vax
+		lp = (long *)&id;
 		if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp))
 			return (FALSE);
 		for (i = 0, lim = dbl_limits;
-
-			 i < sizeof(dbl_limits) / sizeof(struct dbl_limits);
-			 i++, lim++) {
+			i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
+			i++, lim++) {
 			if ((id.mantissa2 == lim->ieee.mantissa2) &&
 				(id.mantissa1 == lim->ieee.mantissa1) &&
 				(id.exp == lim->ieee.exp)) {
@@ -265,13 +279,29 @@ double *dp;
 		vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
 		vd.mantissa1 = (id.mantissa1 >> 13);
 		vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
-			(id.mantissa2 >> 29);
+				(id.mantissa2 >> 29);
 		vd.mantissa3 = (id.mantissa2 >> 13);
 		vd.mantissa4 = (id.mantissa2 << 3);
-	  doneit:
+	doneit:
 		vd.sign = id.sign;
-		*dp = *((double *) &vd);
+		*dp = *((double *)&vd);
 		return (TRUE);
+#else
+		if (2*sizeof(long) == sizeof(double)) {
+			long *lp = (long *)dp;
+			return (XDR_GETLONG(xdrs, lp+!LSW) &&
+				XDR_GETLONG(xdrs, lp+LSW));
+		} else if (2*sizeof(int) == sizeof(double)) {
+			int *ip = (int *)dp;
+			long tmp[2];
+			if (XDR_GETLONG(xdrs, tmp+!LSW) &&
+			    XDR_GETLONG(xdrs, tmp+LSW)) {
+				ip[0] = tmp[0];
+				ip[1] = tmp[1];
+				return (TRUE);
+			}
+		}
+		break;
 #endif
 
 	case XDR_FREE:

+ 203 - 0
libc/inet/rpc/xdr_intXX_t.c

@@ -0,0 +1,203 @@
+/* Copyright (c) 1998, 1999, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1998.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+/* XDR 64bit integers */
+bool_t
+xdr_int64_t (XDR *xdrs, int64_t *ip)
+{
+  int32_t t1;
+  /* This must be unsigned, otherwise we get problems with sign
+     extension in the DECODE case.  */
+  uint32_t t2;
+
+  switch (xdrs->x_op)
+    {
+    case XDR_ENCODE:
+      t1 = (int32_t) ((*ip) >> 32);
+      t2 = (int32_t) (*ip);
+      return (XDR_PUTINT32(xdrs, &t1) && XDR_PUTINT32(xdrs, &t2));
+    case XDR_DECODE:
+      if (!XDR_GETINT32(xdrs, &t1) || !XDR_GETINT32(xdrs, &t2))
+        return FALSE;
+      *ip = ((int64_t) t1) << 32;
+      *ip |= t2;
+      return TRUE;
+    case XDR_FREE:
+      return TRUE;
+    default:
+      return FALSE;
+    }
+}
+
+/* XDR 64bit unsigned integers */
+bool_t
+xdr_uint64_t (XDR *xdrs, uint64_t *uip)
+{
+  uint32_t t1;
+  uint32_t t2;
+
+  switch (xdrs->x_op)
+    {
+    case XDR_ENCODE:
+      t1 = (uint32_t) ((*uip) >> 32);
+      t2 = (uint32_t) (*uip);
+      return (XDR_PUTINT32 (xdrs, (int32_t *) &t1) &&
+	      XDR_PUTINT32(xdrs, (int32_t *) &t2));
+    case XDR_DECODE:
+      if (!XDR_GETINT32(xdrs, (int32_t *) &t1) ||
+	  !XDR_GETINT32(xdrs, (int32_t *) &t2))
+        return FALSE;
+      *uip = ((uint64_t) t1) << 32;
+      *uip |= t2;
+      return TRUE;
+    case XDR_FREE:
+      return TRUE;
+    default:
+      return FALSE;
+    }
+}
+
+/* XDR 32bit integers */
+bool_t
+xdr_int32_t (XDR *xdrs, int32_t *lp)
+{
+  switch (xdrs->x_op)
+    {
+    case XDR_ENCODE:
+      return XDR_PUTINT32 (xdrs, lp);
+    case XDR_DECODE:
+      return XDR_GETINT32 (xdrs, lp);
+    case XDR_FREE:
+      return TRUE;
+    default:
+      return FALSE;
+    }
+}
+
+/* XDR 32bit unsigned integers */
+bool_t
+xdr_uint32_t (XDR *xdrs, uint32_t *ulp)
+{
+  switch (xdrs->x_op)
+    {
+    case XDR_ENCODE:
+      return XDR_PUTINT32 (xdrs, (int32_t *) ulp);
+    case XDR_DECODE:
+      return XDR_GETINT32 (xdrs, (int32_t *) ulp);
+    case XDR_FREE:
+      return TRUE;
+    default:
+      return FALSE;
+    }
+}
+
+/* XDR 16bit integers */
+bool_t
+xdr_int16_t (XDR *xdrs, int16_t *ip)
+{
+  int32_t t;
+
+  switch (xdrs->x_op)
+    {
+    case XDR_ENCODE:
+      t = (int32_t) *ip;
+      return XDR_PUTINT32 (xdrs, &t);
+    case XDR_DECODE:
+      if (!XDR_GETINT32 (xdrs, &t))
+	return FALSE;
+      *ip = (int16_t) t;
+      return TRUE;
+    case XDR_FREE:
+      return TRUE;
+    default:
+      return FALSE;
+    }
+}
+
+/* XDR 16bit unsigned integers */
+bool_t
+xdr_uint16_t (XDR *xdrs, uint16_t *uip)
+{
+  uint32_t ut;
+
+  switch (xdrs->x_op)
+    {
+    case XDR_ENCODE:
+      ut = (uint32_t) *uip;
+      return XDR_PUTINT32 (xdrs, (int32_t *) &ut);
+    case XDR_DECODE:
+      if (!XDR_GETINT32 (xdrs, (int32_t *) &ut))
+	return FALSE;
+      *uip = (uint16_t) ut;
+      return TRUE;
+    case XDR_FREE:
+      return TRUE;
+    default:
+      return FALSE;
+    }
+}
+
+/* XDR 8bit integers */
+bool_t
+xdr_int8_t (XDR *xdrs, int8_t *ip)
+{
+  int32_t t;
+
+  switch (xdrs->x_op)
+    {
+    case XDR_ENCODE:
+      t = (int32_t) *ip;
+      return XDR_PUTINT32 (xdrs, &t);
+    case XDR_DECODE:
+      if (!XDR_GETINT32 (xdrs, &t))
+	return FALSE;
+      *ip = (int8_t) t;
+      return TRUE;
+    case XDR_FREE:
+      return TRUE;
+    default:
+      return FALSE;
+    }
+}
+
+/* XDR 8bit unsigned integers */
+bool_t
+xdr_uint8_t (XDR *xdrs, uint8_t *uip)
+{
+  uint32_t ut;
+
+  switch (xdrs->x_op)
+    {
+    case XDR_ENCODE:
+      ut = (uint32_t) *uip;
+      return XDR_PUTINT32 (xdrs, (int32_t *) &ut);
+    case XDR_DECODE:
+      if (!XDR_GETINT32 (xdrs, (int32_t *) &ut))
+	return FALSE;
+      *uip = (uint8_t) ut;
+      return TRUE;
+    case XDR_FREE:
+      return TRUE;
+    default:
+      return FALSE;
+    }
+}

+ 163 - 109
libc/inet/rpc/xdr_mem.c

@@ -1,4 +1,3 @@
-/* @(#)xdr_mem.c	2.1 88/07/29 4.0 RPCSRC */
 /*
  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  * unrestricted use provided that this legend is included on all tape
@@ -6,29 +5,27 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
 
 /*
  * xdr_mem.h, XDR implementation using memory buffers.
@@ -41,138 +38,195 @@
  *
  */
 
+#define __FORCE_GLIBC
+#define _GNU_SOURCE
+#include <features.h>
+
+
 #include <string.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
-#include <netinet/in.h>
-
-static bool_t xdrmem_getlong();
-static bool_t xdrmem_putlong();
-static bool_t xdrmem_getbytes();
-static bool_t xdrmem_putbytes();
-static u_int xdrmem_getpos();
-static bool_t xdrmem_setpos();
-static int32_t *xdrmem_inline();
-static void xdrmem_destroy();
-
-static struct xdr_ops xdrmem_ops = {
-	xdrmem_getlong,
-	xdrmem_putlong,
-	xdrmem_getbytes,
-	xdrmem_putbytes,
-	xdrmem_getpos,
-	xdrmem_setpos,
-	xdrmem_inline,
-	xdrmem_destroy
+#include <rpc/rpc.h>
+
+static bool_t xdrmem_getlong (XDR *, long *);
+static bool_t xdrmem_putlong (XDR *, const long *);
+static bool_t xdrmem_getbytes (XDR *, caddr_t, u_int);
+static bool_t xdrmem_putbytes (XDR *, const char *, u_int);
+static u_int xdrmem_getpos (const XDR *);
+static bool_t xdrmem_setpos (XDR *, u_int);
+static int32_t *xdrmem_inline (XDR *, int);
+static void xdrmem_destroy (XDR *);
+static bool_t xdrmem_getint32 (XDR *, int32_t *);
+static bool_t xdrmem_putint32 (XDR *, const int32_t *);
+
+static const struct xdr_ops xdrmem_ops =
+{
+  xdrmem_getlong,
+  xdrmem_putlong,
+  xdrmem_getbytes,
+  xdrmem_putbytes,
+  xdrmem_getpos,
+  xdrmem_setpos,
+  xdrmem_inline,
+  xdrmem_destroy,
+  xdrmem_getint32,
+  xdrmem_putint32
 };
 
 /*
  * The procedure xdrmem_create initializes a stream descriptor for a
- * memory buffer.  
+ * memory buffer.
  */
-void xdrmem_create(xdrs, addr, size, op)
-register XDR *xdrs;
-caddr_t addr;
-u_int size;
-enum xdr_op op;
+void
+xdrmem_create (XDR *xdrs, const caddr_t addr, u_int size, enum xdr_op op)
 {
-
-	xdrs->x_op = op;
-	xdrs->x_ops = &xdrmem_ops;
-	xdrs->x_private = xdrs->x_base = addr;
-	xdrs->x_handy = size;
+  xdrs->x_op = op;
+  /* We have to add the const since the `struct xdr_ops' in `struct XDR'
+     is not `const'.  */
+  xdrs->x_ops = (struct xdr_ops *) &xdrmem_ops;
+  xdrs->x_private = xdrs->x_base = addr;
+  xdrs->x_handy = size;
 }
 
-static void xdrmem_destroy( /*xdrs */ )
-	/*XDR *xdrs; */
+/*
+ * Nothing needs to be done for the memory case.  The argument is clearly
+ * const.
+ */
+
+static void
+xdrmem_destroy (XDR *xdrs)
 {
 }
 
-static bool_t xdrmem_getlong(xdrs, lp)
-register XDR *xdrs;
-long *lp;
+/*
+ * Gets the next word from the memory referenced by xdrs and places it
+ * in the long pointed to by lp.  It then increments the private word to
+ * point at the next element.  Neither object pointed to is const
+ */
+static bool_t
+xdrmem_getlong (XDR *xdrs, long *lp)
 {
-
-	if ((xdrs->x_handy -= sizeof(long)) < 0)
-		return (FALSE);
-
-	*lp = (long) ntohl((u_long) (*((long *) (xdrs->x_private))));
-	xdrs->x_private += sizeof(long);
-
-	return (TRUE);
+  if ((xdrs->x_handy -= 4) < 0)
+    return FALSE;
+  *lp = (int32_t) ntohl ((*((int32_t *) (xdrs->x_private))));
+  xdrs->x_private += 4;
+  return TRUE;
 }
 
-static bool_t xdrmem_putlong(xdrs, lp)
-register XDR *xdrs;
-long *lp;
+/*
+ * Puts the long pointed to by lp in the memory referenced by xdrs.  It
+ * then increments the private word to point at the next element.  The
+ * long pointed at is const
+ */
+static bool_t
+xdrmem_putlong (XDR *xdrs, const long *lp)
 {
-
-	if ((xdrs->x_handy -= sizeof(long)) < 0)
-		return (FALSE);
-
-	*(long *) xdrs->x_private = (long) htonl((u_long) (*lp));
-	xdrs->x_private += sizeof(long);
-
-	return (TRUE);
+  if ((xdrs->x_handy -= 4) < 0)
+    return FALSE;
+  *(int32_t *) xdrs->x_private = htonl (*lp);
+  xdrs->x_private += 4;
+  return TRUE;
 }
 
-static bool_t xdrmem_getbytes(xdrs, addr, len)
-register XDR *xdrs;
-caddr_t addr;
-register u_int len;
+/*
+ * Gets an unaligned number of bytes from the xdrs structure and writes them
+ * to the address passed in addr.  Be very careful when calling this routine
+ * as it could leave the xdrs pointing to an unaligned structure which is not
+ * a good idea.  None of the things pointed to are const.
+ */
+static bool_t
+xdrmem_getbytes (XDR *xdrs, caddr_t addr, u_int len)
 {
-
-	if ((xdrs->x_handy -= len) < 0)
-		return (FALSE);
-	bcopy(xdrs->x_private, addr, len);
-	xdrs->x_private += len;
-	return (TRUE);
+  if ((xdrs->x_handy -= len) < 0)
+    return FALSE;
+  memcpy (addr, xdrs->x_private, len);
+  xdrs->x_private += len;
+  return TRUE;
 }
 
-static bool_t xdrmem_putbytes(xdrs, addr, len)
-register XDR *xdrs;
-caddr_t addr;
-register u_int len;
+/*
+ * The complementary function to the above.  The same warnings apply about
+ * unaligned data.  The source address is const.
+ */
+static bool_t
+xdrmem_putbytes (XDR *xdrs, const char *addr, u_int len)
 {
+  if ((xdrs->x_handy -= len) < 0)
+    return FALSE;
+  memcpy (xdrs->x_private, addr, len);
+  xdrs->x_private += len;
+  return TRUE;
+}
 
-	if ((xdrs->x_handy -= len) < 0)
-		return (FALSE);
-	bcopy(addr, xdrs->x_private, len);
-	xdrs->x_private += len;
-	return (TRUE);
+/*
+ * Not sure what this one does.  But it clearly doesn't modify the contents
+ * of xdrs.  **FIXME** does this not assume u_int == u_long?
+ */
+static u_int
+xdrmem_getpos (const XDR *xdrs)
+{
+  return (u_long) xdrs->x_private - (u_long) xdrs->x_base;
 }
 
-static u_int xdrmem_getpos(xdrs)
-register XDR *xdrs;
+/*
+ * xdrs modified
+ */
+static bool_t
+xdrmem_setpos (xdrs, pos)
+     XDR *xdrs;
+     u_int pos;
 {
+  caddr_t newaddr = xdrs->x_base + pos;
+  caddr_t lastaddr = xdrs->x_private + xdrs->x_handy;
+
+  if ((long) newaddr > (long) lastaddr)
+    return FALSE;
+  xdrs->x_private = newaddr;
+  xdrs->x_handy = (long) lastaddr - (long) newaddr;
+  return TRUE;
+}
 
-	return ((u_int) xdrs->x_private - (u_int) xdrs->x_base);
+/*
+ * xdrs modified
+ */
+static int32_t *
+xdrmem_inline (XDR *xdrs, int len)
+{
+  int32_t *buf = 0;
+
+  if (xdrs->x_handy >= len)
+    {
+      xdrs->x_handy -= len;
+      buf = (int32_t *) xdrs->x_private;
+      xdrs->x_private += len;
+    }
+  return buf;
 }
 
-static bool_t xdrmem_setpos(xdrs, pos)
-register XDR *xdrs;
-u_int pos;
+/*
+ * Gets the next word from the memory referenced by xdrs and places it
+ * in the int pointed to by ip.  It then increments the private word to
+ * point at the next element.  Neither object pointed to is const
+ */
+static bool_t
+xdrmem_getint32 (XDR *xdrs, int32_t *ip)
 {
-	register caddr_t newaddr = xdrs->x_base + pos;
-	register caddr_t lastaddr = xdrs->x_private + xdrs->x_handy;
-
-	if ((long) newaddr > (long) lastaddr)
-		return (FALSE);
-	xdrs->x_private = newaddr;
-	xdrs->x_handy = (int) lastaddr - (int) newaddr;
-	return (TRUE);
+  if ((xdrs->x_handy -= 4) < 0)
+    return FALSE;
+  *ip = ntohl ((*((int32_t *) (xdrs->x_private))));
+  xdrs->x_private += 4;
+  return TRUE;
 }
 
-static int32_t *xdrmem_inline(xdrs, len)
-register XDR *xdrs;
-int len;
+/*
+ * Puts the long pointed to by lp in the memory referenced by xdrs.  It
+ * then increments the private word to point at the next element.  The
+ * long pointed at is const
+ */
+static bool_t
+xdrmem_putint32 (XDR *xdrs, const int32_t *ip)
 {
-	int32_t *buf = 0;
-
-	if (xdrs->x_handy >= len) {
-		xdrs->x_handy -= len;
-		buf = (int32_t *) xdrs->x_private;
-		xdrs->x_private += len;
-	}
-	return (buf);
+  if ((xdrs->x_handy -= 4) < 0)
+    return FALSE;
+  *(int32_t *) xdrs->x_private = htonl (*ip);
+  xdrs->x_private += 4;
+  return TRUE;
 }

+ 515 - 432
libc/inet/rpc/xdr_rec.c

@@ -1,4 +1,3 @@
-/* @(#)xdr_rec.c	2.2 88/08/01 4.0 RPCSRC */
 /*
  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  * unrestricted use provided that this legend is included on all tape
@@ -6,29 +5,27 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
 
 /*
  * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking"
@@ -41,40 +38,50 @@
  * and the tcp transport level.  A record is composed on one or more
  * record fragments.  A record fragment is a thirty-two bit header followed
  * by n bytes of data, where n is contained in the header.  The header
- * is represented as a htonl(u_long).  Thegh order bit encodes
+ * is represented as a htonl(u_long).  The high order bit encodes
  * whether or not the fragment is the last fragment of the record
- * (1 => fragment is last, 0 => more fragments to follow. 
+ * (1 => fragment is last, 0 => more fragments to follow.
  * The other 31 bits encode the byte length of the fragment.
  */
 
+#define __FORCE_GLIBC
+#define _GNU_SOURCE
+#include <features.h>
+
+
 #include <stdio.h>
 #include <string.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
-#include <netinet/in.h>
-
-extern long lseek();
-
-static u_int fix_buf_size();
-
-static bool_t xdrrec_getlong();
-static bool_t xdrrec_putlong();
-static bool_t xdrrec_getbytes();
-static bool_t xdrrec_putbytes();
-static u_int xdrrec_getpos();
-static bool_t xdrrec_setpos();
-static int32_t *xdrrec_inline();
-static void xdrrec_destroy();
-
-static struct xdr_ops xdrrec_ops = {
-	xdrrec_getlong,
-	xdrrec_putlong,
-	xdrrec_getbytes,
-	xdrrec_putbytes,
-	xdrrec_getpos,
-	xdrrec_setpos,
-	xdrrec_inline,
-	xdrrec_destroy
+#include <unistd.h>
+#include <rpc/rpc.h>
+
+#ifdef USE_IN_LIBIO
+# include <wchar.h>
+# include <libio/iolibio.h>
+# define fputs(s, f) _IO_fputs (s, f)
+#endif
+
+static bool_t xdrrec_getlong (XDR *, long *);
+static bool_t xdrrec_putlong (XDR *, const long *);
+static bool_t xdrrec_getbytes (XDR *, caddr_t, u_int);
+static bool_t xdrrec_putbytes (XDR *, const char *, u_int);
+static u_int xdrrec_getpos (const XDR *);
+static bool_t xdrrec_setpos (XDR *, u_int);
+static int32_t *xdrrec_inline (XDR *, int);
+static void xdrrec_destroy (XDR *);
+static bool_t xdrrec_getint32 (XDR *, int32_t *);
+static bool_t xdrrec_putint32 (XDR *, const int32_t *);
+
+static const struct xdr_ops xdrrec_ops = {
+  xdrrec_getlong,
+  xdrrec_putlong,
+  xdrrec_getbytes,
+  xdrrec_putbytes,
+  xdrrec_getpos,
+  xdrrec_setpos,
+  xdrrec_inline,
+  xdrrec_destroy,
+  xdrrec_getint32,
+  xdrrec_putint32
 };
 
 /*
@@ -90,39 +97,41 @@ static struct xdr_ops xdrrec_ops = {
  * meet the needs of xdr and rpc based on tcp.
  */
 
-#define LAST_FRAG ((u_long)(1 << 31))
-
-typedef struct rec_strm {
-	caddr_t tcp_handle;
-	caddr_t the_buffer;
-	/*
-	 * out-goung bits
-	 */
-	int (*writeit) ();
-	caddr_t out_base;			/* output buffer (points to frag header) */
-	caddr_t out_finger;			/* next output position */
-	caddr_t out_boundry;		/* data cannot up to this address */
-	u_long *frag_header;		/* beginning of curren fragment */
-	bool_t frag_sent;			/* true if buffer sent in middle of record */
-	/*
-	 * in-coming bits
-	 */
-	int (*readit) ();
-	u_long in_size;				/* fixed size of the input buffer */
-	caddr_t in_base;
-	caddr_t in_finger;			/* location of next byte to be had */
-	caddr_t in_boundry;			/* can read up to this location */
-	long fbtbc;					/* fragment bytes to be consumed */
-	bool_t last_frag;
-	u_int sendsize;
-	u_int recvsize;
-} RECSTREAM;
-
-static bool_t flush_out(register RECSTREAM *rstrm, bool_t eor);
-static bool_t set_input_fragment(register RECSTREAM *rstrm);
-static bool_t get_input_bytes(register RECSTREAM *rstrm,
-							  register caddr_t addr, register int len);
-static bool_t skip_input_bytes(register RECSTREAM *rstrm, long cnt);
+#define LAST_FRAG (1UL << 31)
+
+typedef struct rec_strm
+  {
+    caddr_t tcp_handle;
+    caddr_t the_buffer;
+    /*
+     * out-going bits
+     */
+    int (*writeit) (char *, char *, int);
+    caddr_t out_base;		/* output buffer (points to frag header) */
+    caddr_t out_finger;		/* next output position */
+    caddr_t out_boundry;	/* data cannot up to this address */
+    u_int32_t *frag_header;	/* beginning of curren fragment */
+    bool_t frag_sent;		/* true if buffer sent in middle of record */
+    /*
+     * in-coming bits
+     */
+    int (*readit) (char *, char *, int);
+    u_long in_size;		/* fixed size of the input buffer */
+    caddr_t in_base;
+    caddr_t in_finger;		/* location of next byte to be had */
+    caddr_t in_boundry;		/* can read up to this location */
+    long fbtbc;			/* fragment bytes to be consumed */
+    bool_t last_frag;
+    u_int sendsize;
+    u_int recvsize;
+  }
+RECSTREAM;
+
+static u_int fix_buf_size (u_int) internal_function;
+static bool_t skip_input_bytes (RECSTREAM *, long) internal_function;
+static bool_t flush_out (RECSTREAM *, bool_t) internal_function;
+static bool_t set_input_fragment (RECSTREAM *) internal_function;
+static bool_t get_input_bytes (RECSTREAM *, caddr_t, int) internal_function;
 
 /*
  * Create an xdr handle for xdrrec
@@ -133,265 +142,330 @@ static bool_t skip_input_bytes(register RECSTREAM *rstrm, long cnt);
  * write respectively.   They are like the system
  * calls expect that they take an opaque handle rather than an fd.
  */
-void xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit)
-register XDR *xdrs;
-register u_int sendsize;
-register u_int recvsize;
-caddr_t tcp_handle;
-int (*readit) ();				/* like read, but pass it a tcp_handle, not sock */
-int (*writeit) ();				/* like write, but pass it a tcp_handle, not sock */
+void
+xdrrec_create (XDR *xdrs, u_int sendsize,
+	       u_int recvsize, caddr_t tcp_handle,
+	       int (*readit) (char *, char *, int),
+	       int (*writeit) (char *, char *, int))
 {
-	register RECSTREAM *rstrm = (RECSTREAM *) mem_alloc(sizeof(RECSTREAM));
-
-	if (rstrm == NULL) {
-		(void) fprintf(stderr, "xdrrec_create: out of memory\n");
-		/* 
-		 *  This is bad.  Should rework xdrrec_create to 
-		 *  return a handle, and in this case return NULL
-		 */
-		return;
-	}
-	/*
-	 * adjust sizes and allocate buffer quad byte aligned
-	 */
-	rstrm->sendsize = sendsize = fix_buf_size(sendsize);
-	rstrm->recvsize = recvsize = fix_buf_size(recvsize);
-	rstrm->the_buffer =
-		mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT);
-	if (rstrm->the_buffer == NULL) {
-		(void) fprintf(stderr, "xdrrec_create: out of memory\n");
-		return;
-	}
-	for (rstrm->out_base = rstrm->the_buffer;
-		 (u_int) rstrm->out_base % BYTES_PER_XDR_UNIT != 0;
-		 rstrm->out_base++);
-	rstrm->in_base = rstrm->out_base + sendsize;
-	/*
-	 * now the rest ...
-	 */
-	xdrs->x_ops = &xdrrec_ops;
-	xdrs->x_private = (caddr_t) rstrm;
-	rstrm->tcp_handle = tcp_handle;
-	rstrm->readit = readit;
-	rstrm->writeit = writeit;
-	rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
-	rstrm->frag_header = (u_long *) rstrm->out_base;
-	rstrm->out_finger += sizeof(u_long);
-	rstrm->out_boundry += sendsize;
-	rstrm->frag_sent = FALSE;
-	rstrm->in_size = recvsize;
-	rstrm->in_boundry = rstrm->in_base;
-	rstrm->in_finger = (rstrm->in_boundry += recvsize);
-	rstrm->fbtbc = 0;
-	rstrm->last_frag = TRUE;
+  RECSTREAM *rstrm = (RECSTREAM *) mem_alloc (sizeof (RECSTREAM));
+  caddr_t tmp;
+  char *buf;
+
+  sendsize = fix_buf_size (sendsize);
+  recvsize = fix_buf_size (recvsize);
+  buf = mem_alloc (sendsize + recvsize + BYTES_PER_XDR_UNIT);
+
+  if (rstrm == NULL || buf == NULL)
+    {
+#ifdef USE_IN_LIBIO
+      if (_IO_fwide (stderr, 0) > 0)
+	(void) __fwprintf (stderr, L"%s", _("xdrrec_create: out of memory\n"));
+      else
+#endif
+	(void) fputs (_("xdrrec_create: out of memory\n"), stderr);
+      mem_free (rstrm, sizeof (RECSTREAM));
+      mem_free (buf, sendsize + recvsize + BYTES_PER_XDR_UNIT);
+      /*
+       *  This is bad.  Should rework xdrrec_create to
+       *  return a handle, and in this case return NULL
+       */
+      return;
+    }
+  /*
+   * adjust sizes and allocate buffer quad byte aligned
+   */
+  rstrm->sendsize = sendsize;
+  rstrm->recvsize = recvsize;
+  rstrm->the_buffer = buf;
+  tmp = rstrm->the_buffer;
+  if ((size_t)tmp % BYTES_PER_XDR_UNIT)
+    tmp += BYTES_PER_XDR_UNIT - (size_t)tmp % BYTES_PER_XDR_UNIT;
+  rstrm->out_base = tmp;
+  rstrm->in_base = tmp + sendsize;
+  /*
+   * now the rest ...
+   */
+  /* We have to add the const since the `struct xdr_ops' in `struct XDR'
+     is not `const'.  */
+  xdrs->x_ops = (struct xdr_ops *) &xdrrec_ops;
+  xdrs->x_private = (caddr_t) rstrm;
+  rstrm->tcp_handle = tcp_handle;
+  rstrm->readit = readit;
+  rstrm->writeit = writeit;
+  rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
+  rstrm->frag_header = (u_int32_t *) rstrm->out_base;
+  rstrm->out_finger += 4;
+  rstrm->out_boundry += sendsize;
+  rstrm->frag_sent = FALSE;
+  rstrm->in_size = recvsize;
+  rstrm->in_boundry = rstrm->in_base;
+  rstrm->in_finger = (rstrm->in_boundry += recvsize);
+  rstrm->fbtbc = 0;
+  rstrm->last_frag = TRUE;
 }
 
 
 /*
- * The reoutines defined below are the xdr ops which will go into the
+ * The routines defined below are the xdr ops which will go into the
  * xdr handle filled in by xdrrec_create.
  */
 
-static bool_t xdrrec_getlong(xdrs, lp)
-XDR *xdrs;
-long *lp;
+static bool_t
+xdrrec_getlong (XDR *xdrs, long *lp)
 {
-	register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
-	register long *buflp = (long *) (rstrm->in_finger);
-	long mylong;
-
-	/* first try the inline, fast case */
-	if ((rstrm->fbtbc >= sizeof(long)) &&
-		(((int) rstrm->in_boundry - (int) buflp) >= sizeof(long))) {
-		*lp = (long) ntohl((u_long) (*buflp));
-		rstrm->fbtbc -= sizeof(long);
-		rstrm->in_finger += sizeof(long);
-	} else {
-		if (!xdrrec_getbytes(xdrs, (caddr_t) & mylong, sizeof(long)))
-			return (FALSE);
-
-		*lp = (long) ntohl((u_long) mylong);
-	}
-	return (TRUE);
+  RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
+  int32_t *buflp = (int32_t *) rstrm->in_finger;
+  int32_t mylong;
+
+  /* first try the inline, fast case */
+  if (rstrm->fbtbc >= BYTES_PER_XDR_UNIT &&
+      rstrm->in_boundry - (char *) buflp >= BYTES_PER_XDR_UNIT)
+    {
+      *lp = (int32_t) ntohl (*buflp);
+      rstrm->fbtbc -= BYTES_PER_XDR_UNIT;
+      rstrm->in_finger += BYTES_PER_XDR_UNIT;
+    }
+  else
+    {
+      if (!xdrrec_getbytes (xdrs, (caddr_t) & mylong,
+			    BYTES_PER_XDR_UNIT))
+	return FALSE;
+      *lp = (int32_t) ntohl (mylong);
+    }
+  return TRUE;
 }
 
-static bool_t xdrrec_putlong(xdrs, lp)
-XDR *xdrs;
-long *lp;
+static bool_t
+xdrrec_putlong (XDR *xdrs, const long *lp)
 {
-	register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
-	register long *dest_lp = ((long *) (rstrm->out_finger));
-
-	if ((rstrm->out_finger += sizeof(long)) > rstrm->out_boundry) {
-		/*
-		 * this case should almost never happen so the code is
-		 * inefficient
-		 */
-		rstrm->out_finger -= sizeof(long);
-
-		rstrm->frag_sent = TRUE;
-		if (!flush_out(rstrm, FALSE))
-			return (FALSE);
-		dest_lp = ((long *) (rstrm->out_finger));
-		rstrm->out_finger += sizeof(long);
-	}
-	*dest_lp = (long) htonl((u_long) (*lp));
-	return (TRUE);
+  RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
+  int32_t *dest_lp = (int32_t *) rstrm->out_finger;
+
+  if ((rstrm->out_finger += BYTES_PER_XDR_UNIT) > rstrm->out_boundry)
+    {
+      /*
+       * this case should almost never happen so the code is
+       * inefficient
+       */
+      rstrm->out_finger -= BYTES_PER_XDR_UNIT;
+      rstrm->frag_sent = TRUE;
+      if (!flush_out (rstrm, FALSE))
+	return FALSE;
+      dest_lp = (int32_t *) rstrm->out_finger;
+      rstrm->out_finger += BYTES_PER_XDR_UNIT;
+    }
+  *dest_lp = htonl (*lp);
+  return TRUE;
 }
 
-static bool_t
-/* must manage buffers, fragments, and records */
-xdrrec_getbytes(xdrs, addr, len)
-XDR *xdrs;
-register caddr_t addr;
-register u_int len;
+static bool_t	   /* must manage buffers, fragments, and records */
+xdrrec_getbytes (XDR *xdrs, caddr_t addr, u_int len)
 {
-	register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
-	register int current;
-
-	while (len > 0) {
-		current = rstrm->fbtbc;
-		if (current == 0) {
-			if (rstrm->last_frag)
-				return (FALSE);
-			if (!set_input_fragment(rstrm))
-				return (FALSE);
-			continue;
-		}
-		current = (len < current) ? len : current;
-		if (!get_input_bytes(rstrm, addr, current))
-			return (FALSE);
-		addr += current;
-		rstrm->fbtbc -= current;
-		len -= current;
+  RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
+  u_int current;
+
+  while (len > 0)
+    {
+      current = rstrm->fbtbc;
+      if (current == 0)
+	{
+	  if (rstrm->last_frag)
+	    return FALSE;
+	  if (!set_input_fragment (rstrm))
+	    return FALSE;
+	  continue;
 	}
-	return (TRUE);
+      current = (len < current) ? len : current;
+      if (!get_input_bytes (rstrm, addr, current))
+	return FALSE;
+      addr += current;
+      rstrm->fbtbc -= current;
+      len -= current;
+    }
+  return TRUE;
 }
 
-static bool_t xdrrec_putbytes(xdrs, addr, len)
-XDR *xdrs;
-register caddr_t addr;
-register u_int len;
+static bool_t
+xdrrec_putbytes (XDR *xdrs, const char *addr, u_int len)
 {
-	register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
-	register int current;
-
-	while (len > 0) {
-		current = (u_int) rstrm->out_boundry - (u_int) rstrm->out_finger;
-		current = (len < current) ? len : current;
-		bcopy(addr, rstrm->out_finger, current);
-		rstrm->out_finger += current;
-		addr += current;
-		len -= current;
-		if (rstrm->out_finger == rstrm->out_boundry) {
-			rstrm->frag_sent = TRUE;
-			if (!flush_out(rstrm, FALSE))
-				return (FALSE);
-		}
+  RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
+  u_int current;
+
+  while (len > 0)
+    {
+      current = rstrm->out_boundry - rstrm->out_finger;
+      current = (len < current) ? len : current;
+      memcpy (rstrm->out_finger, addr, current);
+      rstrm->out_finger += current;
+      addr += current;
+      len -= current;
+      if (rstrm->out_finger == rstrm->out_boundry && len > 0)
+	{
+	  rstrm->frag_sent = TRUE;
+	  if (!flush_out (rstrm, FALSE))
+	    return FALSE;
 	}
-	return (TRUE);
+    }
+  return TRUE;
 }
 
-static u_int xdrrec_getpos(xdrs)
-register XDR *xdrs;
+static u_int
+xdrrec_getpos (const XDR *xdrs)
 {
-	register RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
-	register long pos;
-
-	pos = lseek((int) rstrm->tcp_handle, (long) 0, 1);
-	if (pos != -1)
-		switch (xdrs->x_op) {
-
-		case XDR_ENCODE:
-			pos += rstrm->out_finger - rstrm->out_base;
-			break;
-
-		case XDR_DECODE:
-			pos -= rstrm->in_boundry - rstrm->in_finger;
-			break;
-
-		default:
-			pos = (u_int) - 1;
-			break;
-		}
-	return ((u_int) pos);
+  RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
+  long pos;
+
+  pos = lseek ((int) (long) rstrm->tcp_handle, (long) 0, 1);
+  if (pos != -1)
+    switch (xdrs->x_op)
+      {
+
+      case XDR_ENCODE:
+	pos += rstrm->out_finger - rstrm->out_base;
+	break;
+
+      case XDR_DECODE:
+	pos -= rstrm->in_boundry - rstrm->in_finger;
+	break;
+
+      default:
+	pos = (u_int) - 1;
+	break;
+      }
+  return (u_int) pos;
 }
 
-static bool_t xdrrec_setpos(xdrs, pos)
-register XDR *xdrs;
-u_int pos;
+static bool_t
+xdrrec_setpos (XDR *xdrs, u_int pos)
 {
-	register RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
-	u_int currpos = xdrrec_getpos(xdrs);
-	int delta = currpos - pos;
-	caddr_t newpos;
-
-	if ((int) currpos != -1)
-		switch (xdrs->x_op) {
-
-		case XDR_ENCODE:
-			newpos = rstrm->out_finger - delta;
-			if ((newpos > (caddr_t) (rstrm->frag_header)) &&
-				(newpos < rstrm->out_boundry)) {
-				rstrm->out_finger = newpos;
-				return (TRUE);
-			}
-			break;
-
-		case XDR_DECODE:
-			newpos = rstrm->in_finger - delta;
-			if ((delta < (int) (rstrm->fbtbc)) &&
-				(newpos <= rstrm->in_boundry) &&
-				(newpos >= rstrm->in_base)) {
-				rstrm->in_finger = newpos;
-				rstrm->fbtbc -= delta;
-				return (TRUE);
-			}
-			break;
-		default:				/* silence the warnings */
-		}
-	return (FALSE);
+  RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
+  u_int currpos = xdrrec_getpos (xdrs);
+  int delta = currpos - pos;
+  caddr_t newpos;
+
+  if ((int) currpos != -1)
+    switch (xdrs->x_op)
+      {
+
+      case XDR_ENCODE:
+	newpos = rstrm->out_finger - delta;
+	if (newpos > (caddr_t) rstrm->frag_header &&
+	    newpos < rstrm->out_boundry)
+	  {
+	    rstrm->out_finger = newpos;
+	    return TRUE;
+	  }
+	break;
+
+      case XDR_DECODE:
+	newpos = rstrm->in_finger - delta;
+	if ((delta < (int) (rstrm->fbtbc)) &&
+	    (newpos <= rstrm->in_boundry) &&
+	    (newpos >= rstrm->in_base))
+	  {
+	    rstrm->in_finger = newpos;
+	    rstrm->fbtbc -= delta;
+	    return TRUE;
+	  }
+	break;
+
+      default:
+	break;
+      }
+  return FALSE;
 }
 
-static int32_t *xdrrec_inline(xdrs, len)
-register XDR *xdrs;
-int len;
+static int32_t *
+xdrrec_inline (XDR *xdrs, int len)
 {
-	register RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
-	int32_t *buf = NULL;
-
-	switch (xdrs->x_op) {
-
-	case XDR_ENCODE:
-		if ((rstrm->out_finger + len) <= rstrm->out_boundry) {
-			buf = (int32_t *) rstrm->out_finger;
-			rstrm->out_finger += len;
-		}
-		break;
-
-	case XDR_DECODE:
-		if ((len <= rstrm->fbtbc) &&
-			((rstrm->in_finger + len) <= rstrm->in_boundry)) {
-			buf = (int32_t *) rstrm->in_finger;
-			rstrm->fbtbc -= len;
-			rstrm->in_finger += len;
-		}
-		break;
-	default:					/* silence the warnings */
+  RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
+  int32_t *buf = NULL;
+
+  switch (xdrs->x_op)
+    {
+
+    case XDR_ENCODE:
+      if ((rstrm->out_finger + len) <= rstrm->out_boundry)
+	{
+	  buf = (int32_t *) rstrm->out_finger;
+	  rstrm->out_finger += len;
+	}
+      break;
+
+    case XDR_DECODE:
+      if ((len <= rstrm->fbtbc) &&
+	  ((rstrm->in_finger + len) <= rstrm->in_boundry))
+	{
+	  buf = (int32_t *) rstrm->in_finger;
+	  rstrm->fbtbc -= len;
+	  rstrm->in_finger += len;
 	}
-	return (buf);
+      break;
+
+    default:
+      break;
+    }
+  return buf;
 }
 
-static void xdrrec_destroy(xdrs)
-register XDR *xdrs;
+static void
+xdrrec_destroy (XDR *xdrs)
 {
-	register RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
+  RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
+
+  mem_free (rstrm->the_buffer,
+	    rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT);
+  mem_free ((caddr_t) rstrm, sizeof (RECSTREAM));
+}
 
-	mem_free(rstrm->the_buffer,
-			 rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT);
-	mem_free((caddr_t) rstrm, sizeof(RECSTREAM));
+static bool_t
+xdrrec_getint32 (XDR *xdrs, int32_t *ip)
+{
+  RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
+  int32_t *bufip = (int32_t *) rstrm->in_finger;
+  int32_t mylong;
+
+  /* first try the inline, fast case */
+  if (rstrm->fbtbc >= BYTES_PER_XDR_UNIT &&
+      rstrm->in_boundry - (char *) bufip >= BYTES_PER_XDR_UNIT)
+    {
+      *ip = ntohl (*bufip);
+      rstrm->fbtbc -= BYTES_PER_XDR_UNIT;
+      rstrm->in_finger += BYTES_PER_XDR_UNIT;
+    }
+  else
+    {
+      if (!xdrrec_getbytes (xdrs, (caddr_t) &mylong,
+			    BYTES_PER_XDR_UNIT))
+	return FALSE;
+      *ip = ntohl (mylong);
+    }
+  return TRUE;
 }
 
+static bool_t
+xdrrec_putint32 (XDR *xdrs, const int32_t *ip)
+{
+  RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
+  int32_t *dest_ip = (int32_t *) rstrm->out_finger;
+
+  if ((rstrm->out_finger += BYTES_PER_XDR_UNIT) > rstrm->out_boundry)
+    {
+      /*
+       * this case should almost never happen so the code is
+       * inefficient
+       */
+      rstrm->out_finger -= BYTES_PER_XDR_UNIT;
+      rstrm->frag_sent = TRUE;
+      if (!flush_out (rstrm, FALSE))
+	return FALSE;
+      dest_ip = (int32_t *) rstrm->out_finger;
+      rstrm->out_finger += BYTES_PER_XDR_UNIT;
+    }
+  *dest_ip = htonl (*ip);
+  return TRUE;
+}
 
 /*
  * Exported routines to manage xdr records
@@ -401,181 +475,190 @@ register XDR *xdrs;
  * Before reading (deserializing from the stream, one should always call
  * this procedure to guarantee proper record alignment.
  */
-bool_t xdrrec_skiprecord(xdrs)
-XDR *xdrs;
+bool_t
+xdrrec_skiprecord (XDR *xdrs)
 {
-	register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
-
-	while (rstrm->fbtbc > 0 || (!rstrm->last_frag)) {
-		if (!skip_input_bytes(rstrm, rstrm->fbtbc))
-			return (FALSE);
-		rstrm->fbtbc = 0;
-		if ((!rstrm->last_frag) && (!set_input_fragment(rstrm)))
-			return (FALSE);
-	}
-	rstrm->last_frag = FALSE;
-	return (TRUE);
+  RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
+
+  while (rstrm->fbtbc > 0 || (!rstrm->last_frag))
+    {
+      if (!skip_input_bytes (rstrm, rstrm->fbtbc))
+	return FALSE;
+      rstrm->fbtbc = 0;
+      if ((!rstrm->last_frag) && (!set_input_fragment (rstrm)))
+	return FALSE;
+    }
+  rstrm->last_frag = FALSE;
+  return TRUE;
 }
 
 /*
- * Look ahead fuction.
- * Returns TRUE iff there is no more input in the buffer 
+ * Lookahead function.
+ * Returns TRUE iff there is no more input in the buffer
  * after consuming the rest of the current record.
  */
-bool_t xdrrec_eof(xdrs)
-XDR *xdrs;
+bool_t
+xdrrec_eof (XDR *xdrs)
 {
-	register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
-
-	while (rstrm->fbtbc > 0 || (!rstrm->last_frag)) {
-		if (!skip_input_bytes(rstrm, rstrm->fbtbc))
-			return (TRUE);
-		rstrm->fbtbc = 0;
-		if ((!rstrm->last_frag) && (!set_input_fragment(rstrm)))
-			return (TRUE);
-	}
-	if (rstrm->in_finger == rstrm->in_boundry)
-		return (TRUE);
-	return (FALSE);
+  RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
+
+  while (rstrm->fbtbc > 0 || (!rstrm->last_frag))
+    {
+      if (!skip_input_bytes (rstrm, rstrm->fbtbc))
+	return TRUE;
+      rstrm->fbtbc = 0;
+      if ((!rstrm->last_frag) && (!set_input_fragment (rstrm)))
+	return TRUE;
+    }
+  if (rstrm->in_finger == rstrm->in_boundry)
+    return TRUE;
+  return FALSE;
 }
 
 /*
  * The client must tell the package when an end-of-record has occurred.
- * The second paraemters tells whether the record should be flushed to the
- * (output) tcp stream.  (This let's the package support batched or
- * pipelined procedure calls.)  TRUE => immmediate flush to tcp connection.
+ * The second parameter tells whether the record should be flushed to the
+ * (output) tcp stream.  (This lets the package support batched or
+ * pipelined procedure calls.)  TRUE => immediate flush to tcp connection.
  */
-bool_t xdrrec_endofrecord(xdrs, sendnow)
-XDR *xdrs;
-bool_t sendnow;
+bool_t
+xdrrec_endofrecord (XDR *xdrs, bool_t sendnow)
 {
-	register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
-	register u_long len;		/* fragment length */
-
-	if (sendnow || rstrm->frag_sent ||
-		((u_long) rstrm->out_finger + sizeof(u_long) >=
-		 (u_long) rstrm->out_boundry)) {
-		rstrm->frag_sent = FALSE;
-		return (flush_out(rstrm, TRUE));
-	}
-	len = (u_long) (rstrm->out_finger) - (u_long) (rstrm->frag_header) -
-		sizeof(u_long);
-	*(rstrm->frag_header) = htonl((u_long) len | LAST_FRAG);
-	rstrm->frag_header = (u_long *) rstrm->out_finger;
-	rstrm->out_finger += sizeof(u_long);
-	return (TRUE);
+  RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
+  u_long len;		/* fragment length */
+
+  if (sendnow || rstrm->frag_sent
+      || rstrm->out_finger + BYTES_PER_XDR_UNIT >= rstrm->out_boundry)
+    {
+      rstrm->frag_sent = FALSE;
+      return flush_out (rstrm, TRUE);
+    }
+  len = (rstrm->out_finger - (char *) rstrm->frag_header
+	 - BYTES_PER_XDR_UNIT);
+  *rstrm->frag_header = htonl ((u_long) len | LAST_FRAG);
+  rstrm->frag_header = (u_int32_t *) rstrm->out_finger;
+  rstrm->out_finger += BYTES_PER_XDR_UNIT;
+  return TRUE;
 }
 
 
 /*
  * Internal useful routines
  */
-static bool_t flush_out(rstrm, eor)
-register RECSTREAM *rstrm;
-bool_t eor;
+static bool_t
+internal_function
+flush_out (RECSTREAM *rstrm, bool_t eor)
 {
-	register u_long eormask = (eor == TRUE) ? LAST_FRAG : 0;
-	register u_long len = (u_long) (rstrm->out_finger) -
-		(u_long) (rstrm->frag_header) - sizeof(u_long);
-
-	*(rstrm->frag_header) = htonl(len | eormask);
-	len = (u_long) (rstrm->out_finger) - (u_long) (rstrm->out_base);
-	if ((*(rstrm->writeit)) (rstrm->tcp_handle, rstrm->out_base, (int) len)
-		!= (int) len)
-		return (FALSE);
-	rstrm->frag_header = (u_long *) rstrm->out_base;
-	rstrm->out_finger = (caddr_t) rstrm->out_base + sizeof(u_long);
-	return (TRUE);
+  u_long eormask = (eor == TRUE) ? LAST_FRAG : 0;
+  u_long len = (rstrm->out_finger - (char *) rstrm->frag_header
+		- BYTES_PER_XDR_UNIT);
+
+  *rstrm->frag_header = htonl (len | eormask);
+  len = rstrm->out_finger - rstrm->out_base;
+  if ((*(rstrm->writeit)) (rstrm->tcp_handle, rstrm->out_base, (int) len)
+      != (int) len)
+    return FALSE;
+  rstrm->frag_header = (u_int32_t *) rstrm->out_base;
+  rstrm->out_finger = (caddr_t) rstrm->out_base + BYTES_PER_XDR_UNIT;
+  return TRUE;
 }
 
-static bool_t
-/* knows nothing about records!  Only about input buffers */
-fill_input_buf(rstrm)
-register RECSTREAM *rstrm;
+static bool_t	/* knows nothing about records!  Only about input buffers */
+fill_input_buf (RECSTREAM *rstrm)
 {
-	register caddr_t where;
-	u_int i;
-	register int len;
-
-	where = rstrm->in_base;
-	i = (u_int) rstrm->in_boundry % BYTES_PER_XDR_UNIT;
-	where += i;
-	len = rstrm->in_size - i;
-	if ((len = (*(rstrm->readit)) (rstrm->tcp_handle, where, len)) == -1)
-		return (FALSE);
-	rstrm->in_finger = where;
-	where += len;
-	rstrm->in_boundry = where;
-	return (TRUE);
+  caddr_t where;
+  size_t i;
+  int len;
+
+  where = rstrm->in_base;
+  i = (size_t) rstrm->in_boundry % BYTES_PER_XDR_UNIT;
+  where += i;
+  len = rstrm->in_size - i;
+  if ((len = (*(rstrm->readit)) (rstrm->tcp_handle, where, len)) == -1)
+    return FALSE;
+  rstrm->in_finger = where;
+  where += len;
+  rstrm->in_boundry = where;
+  return TRUE;
 }
 
-static bool_t
-/* knows nothing about records!  Only about input buffers */
-get_input_bytes(rstrm, addr, len)
-register RECSTREAM *rstrm;
-register caddr_t addr;
-register int len;
+static bool_t	/* knows nothing about records!  Only about input buffers */
+internal_function
+get_input_bytes (RECSTREAM *rstrm, caddr_t addr, int len)
 {
-	register int current;
-
-	while (len > 0) {
-		current = (int) rstrm->in_boundry - (int) rstrm->in_finger;
-		if (current == 0) {
-			if (!fill_input_buf(rstrm))
-				return (FALSE);
-			continue;
-		}
-		current = (len < current) ? len : current;
-		bcopy(rstrm->in_finger, addr, current);
-		rstrm->in_finger += current;
-		addr += current;
-		len -= current;
+  int current;
+
+  while (len > 0)
+    {
+      current = rstrm->in_boundry - rstrm->in_finger;
+      if (current == 0)
+	{
+	  if (!fill_input_buf (rstrm))
+	    return FALSE;
+	  continue;
 	}
-	return (TRUE);
+      current = (len < current) ? len : current;
+      memcpy (addr, rstrm->in_finger, current);
+      rstrm->in_finger += current;
+      addr += current;
+      len -= current;
+    }
+  return TRUE;
 }
 
-static bool_t
-/* next two bytes of the input stream are treated as a header */
-set_input_fragment(rstrm)
-register RECSTREAM *rstrm;
+static bool_t /* next two bytes of the input stream are treated as a header */
+internal_function
+set_input_fragment (RECSTREAM *rstrm)
 {
-	u_long header;
-
-	if (!get_input_bytes(rstrm, (caddr_t) & header, sizeof(header)))
-		return (FALSE);
-	header = (long) ntohl(header);
-	rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
-	rstrm->fbtbc = header & (~LAST_FRAG);
-	return (TRUE);
+  uint32_t header;
+
+  if (! get_input_bytes (rstrm, (caddr_t)&header, BYTES_PER_XDR_UNIT))
+    return FALSE;
+  header = ntohl (header);
+  rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
+  /*
+   * Sanity check. Try not to accept wildly incorrect fragment
+   * sizes. Unfortunately, only a size of zero can be identified as
+   * 'wildely incorrect', and this only, if it is not the last
+   * fragment of a message. Ridiculously large fragment sizes may look
+   * wrong, but we don't have any way to be certain that they aren't
+   * what the client actually intended to send us. Many existing RPC
+   * implementations may sent a fragment of size zero as the last
+   * fragment of a message.
+   */
+  if (header == 0)
+    return FALSE;
+  rstrm->fbtbc = header & ~LAST_FRAG;
+  return TRUE;
 }
 
-static bool_t
-/* consumes input bytes; knows nothing about records! */
-skip_input_bytes(rstrm, cnt)
-register RECSTREAM *rstrm;
-long cnt;
+static bool_t	/* consumes input bytes; knows nothing about records! */
+internal_function
+skip_input_bytes (RECSTREAM *rstrm, long cnt)
 {
-	register int current;
-
-	while (cnt > 0) {
-		current = (int) rstrm->in_boundry - (int) rstrm->in_finger;
-		if (current == 0) {
-			if (!fill_input_buf(rstrm))
-				return (FALSE);
-			continue;
-		}
-		current = (cnt < current) ? cnt : current;
-		rstrm->in_finger += current;
-		cnt -= current;
+  int current;
+
+  while (cnt > 0)
+    {
+      current = rstrm->in_boundry - rstrm->in_finger;
+      if (current == 0)
+	{
+	  if (!fill_input_buf (rstrm))
+	    return FALSE;
+	  continue;
 	}
-	return (TRUE);
+      current = (cnt < current) ? cnt : current;
+      rstrm->in_finger += current;
+      cnt -= current;
+    }
+  return TRUE;
 }
 
-static u_int fix_buf_size(s)
-register u_int s;
+static u_int
+internal_function
+fix_buf_size (u_int s)
 {
-
-	if (s < 100)
-		s = 4000;
-	return (RNDUP(s));
+  if (s < 100)
+    s = 4000;
+  return RNDUP (s);
 }

+ 77 - 52
libc/inet/rpc/xdr_reference.c

@@ -6,32 +6,33 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_reference.c 1.11 87/08/11 SMI";
+#endif
 
 /*
- * xdr_reference.c, Generic XDR routines impelmentation.
+ * xdr_reference.c, Generic XDR routines implementation.
  *
  * Copyright (C) 1987, Sun Microsystems, Inc.
  *
@@ -39,11 +40,21 @@
  * "pointers".  See xdr.h for more info on the interface to xdr.
  */
 
+#define __FORCE_GLIBC
+#define _GNU_SOURCE
+#include <features.h>
+
 #include <stdio.h>
 #include <string.h>
 #include <rpc/types.h>
 #include <rpc/xdr.h>
 
+#ifdef USE_IN_LIBIO
+# include <wchar.h>
+# include <libio/iolibio.h>
+# define fputs(s, f) _IO_fputs (s, f)
+#endif
+
 #define LASTUNSIGNED	((u_int)0-1)
 
 /*
@@ -52,41 +63,52 @@
  * referenced by a pointer inside the structure that is currently being
  * translated.  pp references a pointer to storage. If *pp is null
  * the  necessary storage is allocated.
- * size is the sizeof the referneced structure.
+ * size is the size of the referneced structure.
  * proc is the routine to handle the referenced structure.
  */
-bool_t xdr_reference(xdrs, pp, size, proc)
-register XDR *xdrs;
-caddr_t *pp;					/* the pointer to work on */
-u_int size;						/* size of the object pointed to */
-xdrproc_t proc;					/* xdr routine to handle the object */
+bool_t
+xdr_reference (xdrs, pp, size, proc)
+     XDR *xdrs;
+     caddr_t *pp;		/* the pointer to work on */
+     u_int size;		/* size of the object pointed to */
+     xdrproc_t proc;		/* xdr routine to handle the object */
 {
-	register caddr_t loc = *pp;
-	register bool_t stat;
+  caddr_t loc = *pp;
+  bool_t stat;
 
-	if (loc == NULL)
-		switch (xdrs->x_op) {
-		case XDR_FREE:
-			return (TRUE);
+  if (loc == NULL)
+    switch (xdrs->x_op)
+      {
+      case XDR_FREE:
+	return TRUE;
 
-		case XDR_DECODE:
-			*pp = loc = (caddr_t) mem_alloc(size);
-			if (loc == NULL) {
-				(void) fprintf(stderr, "xdr_reference: out of memory\n");
-				return (FALSE);
-			}
-			bzero(loc, (int) size);
-			break;
-		default:				/* silence the warnings */
-		}
+      case XDR_DECODE:
+	*pp = loc = (caddr_t) mem_alloc (size);
+	if (loc == NULL)
+	  {
+#ifdef USE_IN_LIBIO
+	    if (_IO_fwide (stderr, 0) > 0)
+	      (void) __fwprintf (stderr, L"%s",
+				 _("xdr_reference: out of memory\n"));
+	    else
+#endif
+	      (void) fputs (_("xdr_reference: out of memory\n"), stderr);
+	    return FALSE;
+	  }
+	bzero (loc, (int) size);
+	break;
+      default:
+	break;
+      }
 
-	stat = (*proc) (xdrs, loc, LASTUNSIGNED);
+  stat = (*proc) (xdrs, loc, LASTUNSIGNED);
 
-	if (xdrs->x_op == XDR_FREE) {
-		mem_free(loc, size);
-		*pp = NULL;
-	}
-	return (stat);
+  if (xdrs->x_op == XDR_FREE)
+    {
+      mem_free (loc, size);
+      *pp = NULL;
+    }
+  return stat;
 }
 
 
@@ -94,7 +116,7 @@ xdrproc_t proc;					/* xdr routine to handle the object */
  * xdr_pointer():
  *
  * XDR a pointer to a possibly recursive data structure. This
- * differs with xdr_reference in that it can serialize/deserialiaze
+ * differs with xdr_reference in that it can serialize/deserialize
  * trees correctly.
  *
  *  What's sent is actually a union:
@@ -109,22 +131,25 @@ xdrproc_t proc;					/* xdr routine to handle the object */
  * > xdr_obj: routine to XDR an object.
  *
  */
-bool_t xdr_pointer(xdrs, objpp, obj_size, xdr_obj)
-register XDR *xdrs;
-char **objpp;
-u_int obj_size;
-xdrproc_t xdr_obj;
+bool_t
+xdr_pointer (xdrs, objpp, obj_size, xdr_obj)
+     XDR *xdrs;
+     char **objpp;
+     u_int obj_size;
+     xdrproc_t xdr_obj;
 {
 
-	bool_t more_data;
+  bool_t more_data;
 
-	more_data = (*objpp != NULL);
-	if (!xdr_bool(xdrs, &more_data)) {
-		return (FALSE);
-	}
-	if (!more_data) {
-		*objpp = NULL;
-		return (TRUE);
-	}
-	return (xdr_reference(xdrs, objpp, obj_size, xdr_obj));
+  more_data = (*objpp != NULL);
+  if (!xdr_bool (xdrs, &more_data))
+    {
+      return FALSE;
+    }
+  if (!more_data)
+    {
+      *objpp = NULL;
+      return TRUE;
+    }
+  return xdr_reference (xdrs, objpp, obj_size, xdr_obj);
 }

+ 110 - 100
libc/inet/rpc/xdr_stdio.c

@@ -1,4 +1,3 @@
-/* @(#)xdr_stdio.c	2.1 88/07/29 4.0 RPCSRC */
 /*
  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  * unrestricted use provided that this legend is included on all tape
@@ -6,29 +5,27 @@
  * 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
  */
-#define __FORCE_GLIBC
-#include <features.h>
 
 /*
  * xdr_stdio.c, XDR implementation on standard i/o file.
@@ -44,27 +41,40 @@
 #include <stdio.h>
 #include <rpc/xdr.h>
 
-static bool_t xdrstdio_getlong();
-static bool_t xdrstdio_putlong();
-static bool_t xdrstdio_getbytes();
-static bool_t xdrstdio_putbytes();
-static u_int xdrstdio_getpos();
-static bool_t xdrstdio_setpos();
-static int32_t *xdrstdio_inline();
-static void xdrstdio_destroy();
+#ifdef USE_IN_LIBIO
+# include <libio/iolibio.h>
+# define fflush(s) _IO_fflush (s)
+# define fread(p, m, n, s) _IO_fread (p, m, n, s)
+# define ftell(s) _IO_ftell (s)
+# define fwrite(p, m, n, s) _IO_fwrite (p, m, n, s)
+#endif
+
+static bool_t xdrstdio_getlong (XDR *, long *);
+static bool_t xdrstdio_putlong (XDR *, const long *);
+static bool_t xdrstdio_getbytes (XDR *, caddr_t, u_int);
+static bool_t xdrstdio_putbytes (XDR *, const char *, u_int);
+static u_int xdrstdio_getpos (const XDR *);
+static bool_t xdrstdio_setpos (XDR *, u_int);
+static int32_t *xdrstdio_inline (XDR *, int);
+static void xdrstdio_destroy (XDR *);
+static bool_t xdrstdio_getint32 (XDR *, int32_t *);
+static bool_t xdrstdio_putint32 (XDR *, const int32_t *);
 
 /*
  * Ops vector for stdio type XDR
  */
-static struct xdr_ops xdrstdio_ops = {
-	xdrstdio_getlong,			/* deseraialize a long int */
-	xdrstdio_putlong,			/* seraialize a long int */
-	xdrstdio_getbytes,			/* deserialize counted bytes */
-	xdrstdio_putbytes,			/* serialize counted bytes */
-	xdrstdio_getpos,			/* get offset in the stream */
-	xdrstdio_setpos,			/* set offset in the stream */
-	xdrstdio_inline,			/* prime stream for inline macros */
-	xdrstdio_destroy			/* destroy stream */
+static const struct xdr_ops xdrstdio_ops =
+{
+  xdrstdio_getlong,		/* deserialize a long int */
+  xdrstdio_putlong,		/* serialize a long int */
+  xdrstdio_getbytes,		/* deserialize counted bytes */
+  xdrstdio_putbytes,		/* serialize counted bytes */
+  xdrstdio_getpos,		/* get offset in the stream */
+  xdrstdio_setpos,		/* set offset in the stream */
+  xdrstdio_inline,		/* prime stream for inline macros */
+  xdrstdio_destroy,		/* destroy stream */
+  xdrstdio_getint32,		/* deserialize a int */
+  xdrstdio_putint32		/* serialize a int */
 };
 
 /*
@@ -72,113 +82,113 @@ static struct xdr_ops xdrstdio_ops = {
  * Sets the xdr stream handle xdrs for use on the stream file.
  * Operation flag is set to op.
  */
-void xdrstdio_create(xdrs, file, op)
-register XDR *xdrs;
-FILE *file;
-enum xdr_op op;
+void
+xdrstdio_create (XDR *xdrs, FILE *file, enum xdr_op op)
 {
-
-	xdrs->x_op = op;
-	xdrs->x_ops = &xdrstdio_ops;
-	xdrs->x_private = (caddr_t) file;
-	xdrs->x_handy = 0;
-	xdrs->x_base = 0;
+  xdrs->x_op = op;
+  /* We have to add the const since the `struct xdr_ops' in `struct XDR'
+     is not `const'.  */
+  xdrs->x_ops = (struct xdr_ops *) &xdrstdio_ops;
+  xdrs->x_private = (caddr_t) file;
+  xdrs->x_handy = 0;
+  xdrs->x_base = 0;
 }
 
 /*
  * Destroy a stdio xdr stream.
  * Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create.
  */
-static void xdrstdio_destroy(xdrs)
-register XDR *xdrs;
+static void
+xdrstdio_destroy (XDR *xdrs)
 {
-	(void) fflush((FILE *) xdrs->x_private);
-	/* xx should we close the file ?? */
+  (void) fflush ((FILE *) xdrs->x_private);
+  /* xx should we close the file ?? */
 };
 
-static bool_t xdrstdio_getlong(xdrs, lp)
-XDR *xdrs;
-register long *lp;
+static bool_t
+xdrstdio_getlong (XDR *xdrs, long *lp)
 {
+  int32_t mycopy;
 
-	if (fread((caddr_t) lp, sizeof(long), 1, (FILE *) xdrs->x_private) !=
-		1) return (FALSE);
-
-#ifndef mc68000
-	*lp = ntohl(*lp);
-#endif
-	return (TRUE);
+  if (fread ((caddr_t) & mycopy, 4, 1, (FILE *) xdrs->x_private) != 1)
+    return FALSE;
+  *lp = (int32_t) ntohl (mycopy);
+  return TRUE;
 }
 
-static bool_t xdrstdio_putlong(xdrs, lp)
-XDR *xdrs;
-long *lp;
+static bool_t
+xdrstdio_putlong (XDR *xdrs, const long *lp)
 {
-
-#ifndef mc68000
-	long mycopy = htonl(*lp);
-
-	lp = &mycopy;
-#endif
-	if (fwrite((caddr_t) lp, sizeof(long), 1, (FILE *) xdrs->x_private) !=
-		1) return (FALSE);
-
-	return (TRUE);
+  long mycopy = htonl (*lp);
+  lp = &mycopy;
+  if (fwrite ((caddr_t) lp, 4, 1, (FILE *) xdrs->x_private) != 1)
+    return FALSE;
+  return TRUE;
 }
 
-static bool_t xdrstdio_getbytes(xdrs, addr, len)
-XDR *xdrs;
-caddr_t addr;
-u_int len;
+static bool_t
+xdrstdio_getbytes (XDR *xdrs, const caddr_t addr, u_int len)
 {
-
-	if ((len != 0)
-		&& (fread(addr, (int) len, 1, (FILE *) xdrs->x_private) != 1))
-		return (FALSE);
-	return (TRUE);
+  if ((len != 0) && (fread (addr, (int) len, 1,
+			    (FILE *) xdrs->x_private) != 1))
+    return FALSE;
+  return TRUE;
 }
 
-static bool_t xdrstdio_putbytes(xdrs, addr, len)
-XDR *xdrs;
-caddr_t addr;
-u_int len;
+static bool_t
+xdrstdio_putbytes (XDR *xdrs, const char *addr, u_int len)
 {
+  if ((len != 0) && (fwrite (addr, (int) len, 1,
+			     (FILE *) xdrs->x_private) != 1))
+    return FALSE;
+  return TRUE;
+}
 
-	if ((len != 0)
-		&& (fwrite(addr, (int) len, 1, (FILE *) xdrs->x_private) != 1))
-		return (FALSE);
-	return (TRUE);
+static u_int
+xdrstdio_getpos (const XDR *xdrs)
+{
+  return (u_int) ftell ((FILE *) xdrs->x_private);
 }
 
-static u_int xdrstdio_getpos(xdrs)
-XDR *xdrs;
+static bool_t
+xdrstdio_setpos (XDR *xdrs, u_int pos)
 {
+  return fseek ((FILE *) xdrs->x_private, (long) pos, 0) < 0 ? FALSE : TRUE;
+}
 
-	return ((u_int) ftell((FILE *) xdrs->x_private));
+static int32_t *
+xdrstdio_inline (XDR *xdrs, int len)
+{
+  /*
+   * Must do some work to implement this: must insure
+   * enough data in the underlying stdio buffer,
+   * that the buffer is aligned so that we can indirect through a
+   * long *, and stuff this pointer in xdrs->x_buf.  Doing
+   * a fread or fwrite to a scratch buffer would defeat
+   * most of the gains to be had here and require storage
+   * management on this buffer, so we don't do this.
+   */
+  return NULL;
 }
 
-static bool_t xdrstdio_setpos(xdrs, pos)
-XDR *xdrs;
-u_int pos;
+static bool_t
+xdrstdio_getint32 (XDR *xdrs, int32_t *ip)
 {
+  int32_t mycopy;
 
-	return ((fseek((FILE *) xdrs->x_private, (long) pos, 0) < 0) ?
-			FALSE : TRUE);
+  if (fread ((caddr_t) &mycopy, 4, 1, (FILE *) xdrs->x_private) != 1)
+    return FALSE;
+  *ip = ntohl (mycopy);
+  return TRUE;
 }
 
-static int32_t *xdrstdio_inline(xdrs, len)
-XDR *xdrs;
-u_int len;
+static bool_t
+xdrstdio_putint32 (XDR *xdrs, const int32_t *ip)
 {
+  int32_t mycopy = htonl (*ip);
 
-	/*
-	 * Must do some work to implement this: must insure
-	 * enough data in the underlying stdio buffer,
-	 * that the buffer is aligned so that we can indirect through a
-	 * long *, and stuff this pointer in xdrs->x_buf.  Doing
-	 * a fread or fwrite to a scratch buffer would defeat
-	 * most of the gains to be had here and require storage
-	 * management on this buffer, so we don't do this.
-	 */
-	return (NULL);
+  ip = &mycopy;
+  if (fwrite ((caddr_t) ip, 4, 1, (FILE *) xdrs->x_private) != 1)
+    return FALSE;
+  return TRUE;
 }