[mod.sources] v06i094: Sun RPC Source

sources-request@mirror.UUCP (08/06/86)

Submitted by: cca!SUN.COM!marks (Mark Stein)
Mod.sources: Volume 6, Issue 94
Archive-name: rpc2/Part06


Sun RPC source (part 6 of 11).  This software package contains code
and documentation for Revision 3.0 of the Sun Remote Procedure Call
library.  In addition, a beta version of the XDR/RPC protocol compiler
is included.  Comments about this latest release may be mailed to
sun!rpc or rpc@sun.com.

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.

- - - - - - - - - C U T - H E R E - - - - - - - - - - - - - - - - - -
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	rpc/rpclib/auth_none.c
#	rpc/rpclib/auth_unix.c
#	rpc/rpclib/authunix_prot.c
#	rpc/rpclib/clnt_perror.c
#	rpc/rpclib/clnt_raw.c
#	rpc/rpclib/clnt_simple.c
#	rpc/rpclib/clnt_tcp.c
#	rpc/rpclib/clnt_udp.c
# This archive created: Mon Jul 14 16:55:20 1986
export PATH; PATH=/bin:/usr/bin:$PATH
for d in rpc rpc/doc rpc/rpclib rpc/tools rpc/toys rpc/rpclib/profiled rpc/rpcgen rpc/rpcgen/test
do
	if test ! -d $d
	then
		echo "shar: Making directory $d"
		mkdir $d
		chmod 755 $d
	fi
done
echo shar: "extracting 'rpc/rpclib/auth_none.c'" '(2876 characters)'
if test -f 'rpc/rpclib/auth_none.c'
then
	echo shar: "will not over-write existing file 'rpc/rpclib/auth_none.c'"
else
sed 's/^X//' << \SHAR_EOF > 'rpc/rpclib/auth_none.c'
X/*
X * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
X * unrestricted use provided that this legend is included on all tape
X * media and as a part of the software program in whole or part.  Users
X * may copy or modify Sun RPC without charge, but are not authorized
X * to license or distribute it to anyone else except as part of a product or
X * program developed by the user.
X * 
X * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
X * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
X * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
X * 
X * Sun RPC is provided with no support and without any obligation on the
X * part of Sun Microsystems, Inc. to assist in its use, correction,
X * modification or enhancement.
X * 
X * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
X * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
X * OR ANY PART THEREOF.
X * 
X * In no event will Sun Microsystems, Inc. be liable for any lost revenue
X * or profits or other special, indirect and consequential damages, even if
X * Sun has been advised of the possibility of such damages.
X * 
X * Sun Microsystems, Inc.
X * 2550 Garcia Avenue
X * Mountain View, California  94043
X */
X#ifndef lint
Xstatic char sccsid[] = "@(#)auth_none.c 1.1 86/02/03 Copyr 1984 Sun Micro";
X#endif
X
X/*
X * auth_none.c
X * Creates a client authentication handle for passing "null" 
X * credentials and verifiers to remote systems. 
X * 
X * Copyright (C) 1984, Sun Microsystems, Inc. 
X */
X
X#include "types.h"
X#include "xdr.h"
X#include "auth.h"
X#define NULL ((caddr_t)0)
X#define MAX_MARSHEL_SIZE 20
X
X/*
X * Authenticator operations routines
X */
Xstatic void	authnone_verf();
Xstatic void	authnone_destroy();
Xstatic bool_t	authnone_marshal();
Xstatic bool_t	authnone_validate();
Xstatic bool_t	authnone_refresh();
X
Xstatic struct auth_ops ops = {
X	authnone_verf,
X	authnone_marshal,
X	authnone_validate,
X	authnone_refresh,
X	authnone_destroy
X};
X
Xstatic AUTH	no_client;
Xstatic char	marshalled_client[MAX_MARSHEL_SIZE];
Xstatic u_int	mcnt;
X
XAUTH *
Xauthnone_create()
X{
X	XDR xdr_stream;
X	register XDR *xdrs;
X
X	if (! mcnt) {
X		no_client.ah_cred = no_client.ah_verf = _null_auth;
X		no_client.ah_ops = &ops;
X		xdrs = &xdr_stream;
X		xdrmem_create(xdrs, marshalled_client, (u_int)MAX_MARSHEL_SIZE,
X		    XDR_ENCODE);
X		(void)xdr_opaque_auth(xdrs, &no_client.ah_cred);
X		(void)xdr_opaque_auth(xdrs, &no_client.ah_verf);
X		mcnt = XDR_GETPOS(xdrs);
X		XDR_DESTROY(xdrs);
X	}
X	return (&no_client);
X}
X
X/*ARGSUSED*/
Xstatic bool_t
Xauthnone_marshal(client, xdrs)
X	AUTH *client;
X	XDR *xdrs;
X{
X
X	return ((*xdrs->x_ops->x_putbytes)(xdrs, marshalled_client, mcnt));
X}
X
Xstatic void 
Xauthnone_verf()
X{
X}
X
Xstatic bool_t
Xauthnone_validate()
X{
X
X	return (TRUE);
X}
X
Xstatic bool_t
Xauthnone_refresh()
X{
X
X	return (FALSE);
X}
X
Xstatic void
Xauthnone_destroy()
X{
X}
SHAR_EOF
if test 2876 -ne "`wc -c < 'rpc/rpclib/auth_none.c'`"
then
	echo shar: "error transmitting 'rpc/rpclib/auth_none.c'" '(should have been 2876 characters)'
fi
chmod 444 'rpc/rpclib/auth_none.c'
fi
echo shar: "extracting 'rpc/rpclib/auth_unix.c'" '(8022 characters)'
if test -f 'rpc/rpclib/auth_unix.c'
then
	echo shar: "will not over-write existing file 'rpc/rpclib/auth_unix.c'"
else
sed 's/^X//' << \SHAR_EOF > 'rpc/rpclib/auth_unix.c'
X/*
X * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
X * unrestricted use provided that this legend is included on all tape
X * media and as a part of the software program in whole or part.  Users
X * may copy or modify Sun RPC without charge, but are not authorized
X * to license or distribute it to anyone else except as part of a product or
X * program developed by the user.
X * 
X * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
X * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
X * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
X * 
X * Sun RPC is provided with no support and without any obligation on the
X * part of Sun Microsystems, Inc. to assist in its use, correction,
X * modification or enhancement.
X * 
X * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
X * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
X * OR ANY PART THEREOF.
X * 
X * In no event will Sun Microsystems, Inc. be liable for any lost revenue
X * or profits or other special, indirect and consequential damages, even if
X * Sun has been advised of the possibility of such damages.
X * 
X * Sun Microsystems, Inc.
X * 2550 Garcia Avenue
X * Mountain View, California  94043
X */
X#ifndef lint
Xstatic char sccsid[] = "@(#)auth_unix.c 1.1 86/02/03 Copyr 1984 Sun Micro";
X#endif
X
X/*
X * auth_unix.c, Implements UNIX style authentication parameters. 
X *  
X * Copyright (C) 1984, Sun Microsystems, Inc. 
X *
X * The system is very weak.  The client uses no encryption for it's
X * credentials and only sends null verifiers.  The server sends backs
X * null verifiers or optionally a verifier that suggests a new short hand
X * for the credentials.
X *
X */
X
X#include <stdio.h>
X#include "types.h"
X#include <sys/time.h>
X#include "xdr.h"
X#include "auth.h"
X#include "auth_unix.h"
Xchar *malloc();
X
X/*
X * Unix authenticator operations vector
X */
Xstatic void	authunix_nextverf();
Xstatic bool_t	authunix_marshal();
Xstatic bool_t	authunix_validate();
Xstatic bool_t	authunix_refresh();
Xstatic void	authunix_destroy();
X
Xstatic struct auth_ops auth_unix_ops = {
X	authunix_nextverf,
X	authunix_marshal,
X	authunix_validate,
X	authunix_refresh,
X	authunix_destroy
X};
X
X/*
X * This struct is pointed to by the ah_private field of an auth_handle.
X */
Xstruct audata {
X	struct opaque_auth	au_origcred;	/* original credentials */
X	struct opaque_auth	au_shcred;	/* short hand cred */
X	u_long			au_shfaults;	/* short hand cache faults */
X	char			au_marshed[MAX_AUTH_BYTES];
X	u_int			au_mpos;	/* xdr pos at end of marshed */
X};
X#define	AUTH_PRIVATE(auth)	((struct audata *)auth->ah_private)
X
Xstatic bool_t marshal_new_auth();
X
X
X/*
X * Create a unix style authenticator.
X * Returns an auth handle with the given stuff in it.
X */
XAUTH *
Xauthunix_create(machname, uid, gid, len, aup_gids)
X	char *machname;
X	int uid;
X	int gid;
X	register int len;
X	int *aup_gids;
X{
X	struct authunix_parms aup;
X	char mymem[MAX_AUTH_BYTES];
X	struct timeval now;
X	XDR xdrs;
X	register AUTH *auth;
X	register struct audata *au;
X
X	/*
X	 * Allocate and set up auth handle
X	 */
X	auth = (AUTH *)mem_alloc(sizeof(*auth));
X#ifndef KERNEL
X	if (auth == NULL) {
X		fprintf(stderr, "authunix_create: out of memory\n");
X		return (NULL);
X	}
X#endif
X	au = (struct audata *)mem_alloc(sizeof(*au));
X#ifndef KERNEL
X	if (au == NULL) {
X		fprintf(stderr, "authunix_create: out of memory\n");
X		return (NULL);
X	}
X#endif
X	auth->ah_ops = &auth_unix_ops;
X	auth->ah_private = (caddr_t)au;
X	auth->ah_verf = au->au_shcred = _null_auth;
X	au->au_shfaults = 0;
X
X	/*
X	 * fill in param struct from the given params
X	 */
X	(void)gettimeofday(&now,  (struct timezone *)0);
X	aup.aup_time = now.tv_sec;
X	aup.aup_machname = machname;
X	aup.aup_uid = uid;
X	aup.aup_gid = gid;
X	aup.aup_len = (u_int)len;
X	aup.aup_gids = aup_gids;
X
X	/*
X	 * Serialize the parameters into origcred
X	 */
X	xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
X	if (! xdr_authunix_parms(&xdrs, &aup)) 
X		abort();
X	au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
X	au->au_origcred.oa_flavor = AUTH_UNIX;
X#ifdef KERNEL
X	au->au_origcred.oa_base = mem_alloc(len);
X#else
X	if ((au->au_origcred.oa_base = mem_alloc(len)) == NULL) {
X		fprintf(stderr, "authunix_create: out of memory\n");
X		return (NULL);
X	}
X#endif
X	bcopy(mymem, au->au_origcred.oa_base, (u_int)len);
X
X	/*
X	 * set auth handle to reflect new cred.
X	 */
X	auth->ah_cred = au->au_origcred;
X	marshal_new_auth(auth);
X	return (auth);
X}
X
X/*
X * Returns an auth handle with parameters determined by doing lots of
X * syscalls.
X */
XAUTH *
Xauthunix_create_default()
X{
X	register int len;
X	char machname[MAX_MACHINE_NAME + 1];
X	register int uid;
X	register int gid;
X	int gids[NGRPS];
X
X	if (gethostname(machname, MAX_MACHINE_NAME) == -1)
X		abort();
X	machname[MAX_MACHINE_NAME] = 0;
X	uid = geteuid();
X	gid = getegid();
X	if ((len = getgroups(NGRPS, gids)) < 0)
X		abort();
X	return (authunix_create(machname, uid, gid, len, gids));
X}
X
X/*
X * authunix operations
X */
X
Xstatic void
Xauthunix_nextverf(auth)
X	AUTH *auth;
X{
X	/* no action necessary */
X}
X
Xstatic bool_t
Xauthunix_marshal(auth, xdrs)
X	AUTH *auth;
X	XDR *xdrs;
X{
X	register struct audata *au = AUTH_PRIVATE(auth);
X
X	return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
X}
X
Xstatic bool_t
Xauthunix_validate(auth, verf)
X	register AUTH *auth;
X	struct opaque_auth verf;
X{
X	register struct audata *au;
X	XDR xdrs;
X
X	if (verf.oa_flavor == AUTH_SHORT) {
X		au = AUTH_PRIVATE(auth);
X		xdrmem_create(&xdrs, verf.oa_base, verf.oa_length, XDR_DECODE);
X
X		if (au->au_shcred.oa_base != NULL) {
X			mem_free(au->au_shcred.oa_base,
X			    au->au_shcred.oa_length);
X			au->au_shcred.oa_base = NULL;
X		}
X		if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
X			auth->ah_cred = au->au_shcred;
X		} else {
X			xdrs.x_op = XDR_FREE;
X			(void)xdr_opaque_auth(&xdrs, &au->au_shcred);
X			au->au_shcred.oa_base = NULL;
X			auth->ah_cred = au->au_origcred;
X		}
X		marshal_new_auth(auth);
X	}
X	return (TRUE);
X}
X
Xstatic bool_t
Xauthunix_refresh(auth)
X	register AUTH *auth;
X{
X	register struct audata *au = AUTH_PRIVATE(auth);
X	struct authunix_parms aup;
X	struct timeval now;
X	XDR xdrs;
X	register int stat;
X
X	if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
X		/* there is no hope.  Punt */
X		return (FALSE);
X	}
X	au->au_shfaults ++;
X
X	/* first deserialize the creds back into a struct authunix_parms */
X	aup.aup_machname = NULL;
X	aup.aup_gids = (int *)NULL;
X	xdrmem_create(&xdrs, au->au_origcred.oa_base,
X	    au->au_origcred.oa_length, XDR_DECODE);
X	stat = xdr_authunix_parms(&xdrs, &aup);
X	if (! stat) 
X		goto done;
X
X	/* update the time and serialize in place */
X	(void)gettimeofday(&now, (struct timezone *)0);
X	aup.aup_time = now.tv_sec;
X	xdrs.x_op = XDR_ENCODE;
X	XDR_SETPOS(&xdrs, 0);
X	stat = xdr_authunix_parms(&xdrs, &aup);
X	if (! stat)
X		goto done;
X	auth->ah_cred = au->au_origcred;
X	marshal_new_auth(auth);
Xdone:
X	/* free the struct authunix_parms created by deserializing */
X	xdrs.x_op = XDR_FREE;
X	(void)xdr_authunix_parms(&xdrs, &aup);
X	XDR_DESTROY(&xdrs);
X	return (stat);
X}
X
Xstatic void
Xauthunix_destroy(auth)
X	register AUTH *auth;
X{
X	register struct audata *au = AUTH_PRIVATE(auth);
X
X	mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
X
X	if (au->au_shcred.oa_base != NULL)
X		mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
X
X	mem_free(auth->ah_private, sizeof(struct audata));
X
X	if (auth->ah_verf.oa_base != NULL)
X		mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
X
X	mem_free((caddr_t)auth, sizeof(*auth));
X}
X
X/*
X * Marshals (pre-serializes) an auth struct.
X * sets private data, au_marshed and au_mpos
X */
Xstatic bool_t
Xmarshal_new_auth(auth)
X	register AUTH *auth;
X{
X	XDR		xdr_stream;
X	register XDR	*xdrs = &xdr_stream;
X	register struct audata *au = AUTH_PRIVATE(auth);
X
X	xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
X	if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
X	    (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) {
X		perror("auth_none.c - Fatal marshalling problem");
X	} else {
X		au->au_mpos = XDR_GETPOS(xdrs);
X	}
X	XDR_DESTROY(xdrs);
X}
SHAR_EOF
if test 8022 -ne "`wc -c < 'rpc/rpclib/auth_unix.c'`"
then
	echo shar: "error transmitting 'rpc/rpclib/auth_unix.c'" '(should have been 8022 characters)'
fi
chmod 444 'rpc/rpclib/auth_unix.c'
fi
echo shar: "extracting 'rpc/rpclib/authunix_prot.c'" '(2045 characters)'
if test -f 'rpc/rpclib/authunix_prot.c'
then
	echo shar: "will not over-write existing file 'rpc/rpclib/authunix_prot.c'"
else
sed 's/^X//' << \SHAR_EOF > 'rpc/rpclib/authunix_prot.c'
X/*
X * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
X * unrestricted use provided that this legend is included on all tape
X * media and as a part of the software program in whole or part.  Users
X * may copy or modify Sun RPC without charge, but are not authorized
X * to license or distribute it to anyone else except as part of a product or
X * program developed by the user.
X * 
X * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
X * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
X * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
X * 
X * Sun RPC is provided with no support and without any obligation on the
X * part of Sun Microsystems, Inc. to assist in its use, correction,
X * modification or enhancement.
X * 
X * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
X * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
X * OR ANY PART THEREOF.
X * 
X * In no event will Sun Microsystems, Inc. be liable for any lost revenue
X * or profits or other special, indirect and consequential damages, even if
X * Sun has been advised of the possibility of such damages.
X * 
X * Sun Microsystems, Inc.
X * 2550 Garcia Avenue
X * Mountain View, California  94043
X */
X#ifndef lint
Xstatic char sccsid[] = "@(#)authunix_prot.c 1.1 86/02/03 Copyr 1984 Sun Micro";
X#endif
X
X/*
X * authunix_prot.c
X * XDR for UNIX style authentication parameters for RPC
X *
X * Copyright (C) 1984, Sun Microsystems, Inc.
X */
X
X#include "types.h"
X#include "xdr.h"
X#include "auth.h"
X#include "auth_unix.h"
X
X/*
X * XDR for unix authentication parameters.
X */
Xbool_t
Xxdr_authunix_parms(xdrs, p)
X	register XDR *xdrs;
X	register struct authunix_parms *p;
X{
X
X	if (xdr_u_long(xdrs, &(p->aup_time))
X	    && xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME)
X	    && xdr_int(xdrs, &(p->aup_uid))
X	    && xdr_int(xdrs, &(p->aup_gid))
X	    && xdr_array(xdrs, (caddr_t *)&(p->aup_gids),
X		    &(p->aup_len), NGRPS, sizeof(int), xdr_int) ) {
X		return (TRUE);
X	}
X	return (FALSE);
X}
X
SHAR_EOF
if test 2045 -ne "`wc -c < 'rpc/rpclib/authunix_prot.c'`"
then
	echo shar: "error transmitting 'rpc/rpclib/authunix_prot.c'" '(should have been 2045 characters)'
fi
chmod 444 'rpc/rpclib/authunix_prot.c'
fi
echo shar: "extracting 'rpc/rpclib/clnt_perror.c'" '(5331 characters)'
if test -f 'rpc/rpclib/clnt_perror.c'
then
	echo shar: "will not over-write existing file 'rpc/rpclib/clnt_perror.c'"
else
sed 's/^X//' << \SHAR_EOF > 'rpc/rpclib/clnt_perror.c'
X/*
X * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
X * unrestricted use provided that this legend is included on all tape
X * media and as a part of the software program in whole or part.  Users
X * may copy or modify Sun RPC without charge, but are not authorized
X * to license or distribute it to anyone else except as part of a product or
X * program developed by the user.
X * 
X * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
X * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
X * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
X * 
X * Sun RPC is provided with no support and without any obligation on the
X * part of Sun Microsystems, Inc. to assist in its use, correction,
X * modification or enhancement.
X * 
X * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
X * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
X * OR ANY PART THEREOF.
X * 
X * In no event will Sun Microsystems, Inc. be liable for any lost revenue
X * or profits or other special, indirect and consequential damages, even if
X * Sun has been advised of the possibility of such damages.
X * 
X * Sun Microsystems, Inc.
X * 2550 Garcia Avenue
X * Mountain View, California  94043
X */
X#ifndef lint
Xstatic char sccsid[] = "@(#)clnt_perror.c 1.1 86/02/03 Copyr 1984 Sun Micro";
X#endif
X
X/*
X * clnt_perror.c
X *
X * Copyright (C) 1984, Sun Microsystems, Inc.
X *
X */
X#include "types.h"
X#include "xdr.h"
X#include "auth.h"
X#include "clnt.h"
X#include "rpc_msg.h"
X#include <stdio.h>
Xextern char *sys_errlist[];
X
X/*
X * Print reply error info
X */
Xvoid
Xclnt_perror(rpch, s)
X	CLIENT *rpch;
X	char *s;
X{
X	struct rpc_err e;
X	void clnt_perrno();
X
X	CLNT_GETERR(rpch, &e);
X	fprintf(stderr, "%s: ", s);
X	switch (e.re_status) {
X		case RPC_SUCCESS:
X		case RPC_CANTENCODEARGS:
X		case RPC_CANTDECODERES:
X		case RPC_TIMEDOUT:
X		case RPC_PROGUNAVAIL:
X		case RPC_PROCUNAVAIL:
X		case RPC_CANTDECODEARGS:
X			clnt_perrno(e.re_status);
X			break;
X		case RPC_CANTSEND:
X			clnt_perrno(e.re_status);
X			fprintf(stderr, "; errno = %s",
X			    sys_errlist[e.re_errno]);
X			break;
X	
X		case RPC_CANTRECV:
X			clnt_perrno(e.re_status);
X			fprintf(stderr, "; errno = %s",
X			    sys_errlist[e.re_errno]);
X			break;
X	
X		case RPC_VERSMISMATCH:
X			clnt_perrno(e.re_status);
X			fprintf(stderr, "; low version = %lu, high version = %lu", e.re_vers.low, e.re_vers.high);
X			break;
X	
X		case RPC_AUTHERROR:
X			clnt_perrno(e.re_status);
X			fprintf(stderr, "; why = ");
X			switch (e.re_why) {
X			case AUTH_OK:
X				fprintf(stderr, "AUTH_OK");
X				break;
X	
X			case AUTH_BADCRED:
X				fprintf(stderr, "AUTH_BOGUS_CREDENTIAL");
X				break;
X	
X			case AUTH_REJECTEDCRED:
X				fprintf(stderr, "AUTH_REJECTED_CREDENTIAL");
X				break;
X	
X			case AUTH_BADVERF:
X				fprintf(stderr, "AUTH_BOGUS_VERIFIER");
X				break;
X	
X			case AUTH_REJECTEDVERF:
X				fprintf(stderr, "AUTH_REJECTED_VERIFIER");
X				break;
X	
X			case AUTH_TOOWEAK:
X				fprintf(stderr, "AUTH_TOO_WEAK (remote error)");
X				break;
X	
X			case AUTH_INVALIDRESP:
X				fprintf(stderr, "AUTH_INVALID_RESPONSE");
X				break;
X	
X			default:
X				fprintf(stderr, "AUTH_UNKNOWN_FAILURE");
X				break;
X			}
X			break;
X	
X		case RPC_PROGVERSMISMATCH:
X			clnt_perrno(e.re_status);
X			fprintf(stderr, "; low version = %lu, high version = %lu", e.re_vers.low, e.re_vers.high);
X			break;
X	
X		default:
X			fprintf(stderr, "RPC_UNKNOWN_FAILURE; s1 = %lu, s2 = %lu", e.re_lb.s1, e.re_lb.s2);
X			break;
X	}
X	fprintf(stderr, "\n");
X}
X
X/*
X * This interface for use by clntrpc
X */
Xvoid
Xclnt_perrno(num)
X	enum clnt_stat num;
X{
X	switch (num) {
X		case RPC_SUCCESS:
X			fprintf(stderr, "RPC_SUCCESS");
X			break;
X	
X		case RPC_CANTENCODEARGS:
X			fprintf(stderr, "RPC_CANT_ENCODE_ARGS");
X			break;
X	
X		case RPC_CANTDECODERES:
X			fprintf(stderr, "RPC_CANT_DECODE_RESULTS");
X			break;
X	
X		case RPC_CANTSEND:
X			fprintf(stderr, "RPC_CANT_SEND");
X			break;
X	
X		case RPC_CANTRECV:
X			fprintf(stderr, "RPC_CANT_RECV");
X			break;
X	
X		case RPC_TIMEDOUT:
X			fprintf(stderr, "RPC_TIMED_OUT");
X			break;
X	
X		case RPC_VERSMISMATCH:
X			fprintf(stderr, "RPC_VERSION_MISMATCH");
X			break;
X	
X		case RPC_AUTHERROR:
X			fprintf(stderr, "RPC_AUTH_ERROR");
X			break;
X	
X		case RPC_PROGUNAVAIL:
X			fprintf(stderr, "RPC_REMOTE_PROGRAM_UNAVAILABLE");
X			break;
X	
X		case RPC_PROGVERSMISMATCH:
X			fprintf(stderr, "RPC_PROGRAM_MISMATCH");
X			break;
X	
X		case RPC_PROCUNAVAIL:
X			fprintf(stderr, "RPC_UNKNOWN_PROCEDURE");
X			break;
X	
X		case RPC_CANTDECODEARGS:
X			fprintf(stderr, "RPC_CANT_DECODE_ARGS");
X			break;
X		case RPC_UNKNOWNHOST:
X			fprintf(stderr, "RPC_UNKNOWNHOST");
X			break;
X		case RPC_PMAPFAILURE:
X			fprintf(stderr, "RPC_PMAP_FAILURE");
X			break;
X		case RPC_PROGNOTREGISTERED:
X			fprintf(stderr, "RPC_PROG_NOT_REGISTERED");
X			break;
X		case RPC_SYSTEMERROR:
X			fprintf(stderr, "RPC_SYSTEM_ERROR");
X			break;
X	}
X}
X
X/*
X * A handle on why an rpc creation routine failed (returned NULL.)
X */
Xstruct rpc_createerr rpc_createerr;
X
Xclnt_pcreateerror(s)
X	char *s;
X{
X
X	fprintf(stderr, "%s: ", s);
X	clnt_perrno(rpc_createerr.cf_stat);
X	switch (rpc_createerr.cf_stat) {
X		case RPC_PMAPFAILURE:
X			fprintf(stderr, " - ");
X			clnt_perrno(rpc_createerr.cf_error.re_status);
X			break;
X
X		case RPC_SYSTEMERROR:
X			fprintf(stderr, " - %s", sys_errlist[rpc_createerr.cf_error.re_errno]);
X			break;
X
X	}
X	fprintf(stderr, "\n");
X}
SHAR_EOF
if test 5331 -ne "`wc -c < 'rpc/rpclib/clnt_perror.c'`"
then
	echo shar: "error transmitting 'rpc/rpclib/clnt_perror.c'" '(should have been 5331 characters)'
fi
chmod 444 'rpc/rpclib/clnt_perror.c'
fi
echo shar: "extracting 'rpc/rpclib/clnt_raw.c'" '(5285 characters)'
if test -f 'rpc/rpclib/clnt_raw.c'
then
	echo shar: "will not over-write existing file 'rpc/rpclib/clnt_raw.c'"
else
sed 's/^X//' << \SHAR_EOF > 'rpc/rpclib/clnt_raw.c'
X/*
X * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
X * unrestricted use provided that this legend is included on all tape
X * media and as a part of the software program in whole or part.  Users
X * may copy or modify Sun RPC without charge, but are not authorized
X * to license or distribute it to anyone else except as part of a product or
X * program developed by the user.
X * 
X * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
X * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
X * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
X * 
X * Sun RPC is provided with no support and without any obligation on the
X * part of Sun Microsystems, Inc. to assist in its use, correction,
X * modification or enhancement.
X * 
X * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
X * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
X * OR ANY PART THEREOF.
X * 
X * In no event will Sun Microsystems, Inc. be liable for any lost revenue
X * or profits or other special, indirect and consequential damages, even if
X * Sun has been advised of the possibility of such damages.
X * 
X * Sun Microsystems, Inc.
X * 2550 Garcia Avenue
X * Mountain View, California  94043
X */
X#ifndef lint
Xstatic char sccsid[] = "@(#)clnt_raw.c 1.1 86/02/03 Copyr 1984 Sun Micro";
X#endif
X
X/*
X * clnt_raw.c
X *
X * Copyright (C) 1984, Sun Microsystems, Inc.
X *
X * Memory based rpc for simple testing and timing.
X * Interface to create an rpc client and server in the same process.
X * This lets us similate rpc and get round trip overhead, without
X * any interference from the kernal.
X */
X
X#include "types.h"
X#include <sys/time.h>
X#include <netinet/in.h>
X#include "xdr.h"
X#include "auth.h"
X#include "clnt.h"
X#include "rpc_msg.h"
X
X#define NULL ((caddr_t)0)
X#define MCALL_MSG_SIZE 24
X
X/*
X * This is the "network" we will be moving stuff over.
X */
Xchar _raw_buf[UDPMSGSIZE];
X
Xstatic char	mashl_callmsg[MCALL_MSG_SIZE];
Xstatic u_int	mcnt;
X
Xstatic enum clnt_stat	clntraw_call();
Xstatic void		clntraw_abort();
Xstatic void		clntraw_geterr();
Xstatic bool_t		clntraw_freeres();
Xstatic void		clntraw_destroy();
X
Xstatic struct clnt_ops client_ops = {
X	clntraw_call,
X	clntraw_abort,
X	clntraw_geterr,
X	clntraw_freeres,
X	clntraw_destroy
X};
X
Xstatic CLIENT	client_object;
Xstatic XDR	xdr_stream;
X
Xvoid	svc_getreq();
X
X/*
X * Create a client handle for memory based rpc.
X */
XCLIENT *
Xclntraw_create(prog, vers)
X	u_long prog;
X	u_long vers;
X{
X	struct rpc_msg call_msg;
X	XDR *xdrs = &xdr_stream;
X	CLIENT	*client = &client_object;
X
X	/*
X	 * pre-serialize the staic part of the call msg and stash it away
X	 */
X	call_msg.rm_direction = CALL;
X	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
X	call_msg.rm_call.cb_prog = prog;
X	call_msg.rm_call.cb_vers = vers;
X	xdrmem_create(xdrs, mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE); 
X	if (! xdr_callhdr(xdrs, &call_msg)) {
X		perror("clnt_raw.c - Fatal header serialization error.");
X	}
X	mcnt = XDR_GETPOS(xdrs);
X	XDR_DESTROY(xdrs);
X
X	/*
X	 * Set xdrmem for client/server shared buffer
X	 */
X	xdrmem_create(xdrs, _raw_buf, UDPMSGSIZE, XDR_FREE);
X
X	/*
X	 * create client handle
X	 */
X	client->cl_ops = &client_ops;
X	client->cl_auth = authnone_create();
X	return (client);
X}
X
Xstatic enum clnt_stat 
Xclntraw_call(h, proc, xargs, argsp, xresults, resultsp, timeout)
X	CLIENT *h;
X	u_long proc;
X	xdrproc_t xargs;
X	caddr_t argsp;
X	xdrproc_t xresults;
X	caddr_t resultsp;
X	struct timeval timeout;
X{
X	register XDR *xdrs = &xdr_stream;
X	struct rpc_msg msg;
X	enum clnt_stat status;
X	struct rpc_err error;
X
Xcall_again:
X	/*
X	 * send request
X	 */
X	xdrs->x_op = XDR_ENCODE;
X	XDR_SETPOS(xdrs, 0);
X	((struct rpc_msg *)mashl_callmsg)->rm_xid ++ ;
X	if ((! XDR_PUTBYTES(xdrs, mashl_callmsg, mcnt)) ||
X	    (! XDR_PUTLONG(xdrs, (long *)&proc)) ||
X	    (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
X	    (! (*xargs)(xdrs, argsp))) {
X		return (RPC_CANTENCODEARGS);
X	}
X	(void)XDR_GETPOS(xdrs);  /* called just to cause overhead */
X
X	/*
X	 * We have to call server input routine here because this is
X	 * all going on in one process. Yuk.
X	 */
X	svc_getreq(1);
X
X	/*
X	 * get results
X	 */
X	xdrs->x_op = XDR_DECODE;
X	XDR_SETPOS(xdrs, 0);
X	msg.acpted_rply.ar_verf = _null_auth;
X	msg.acpted_rply.ar_results.where = resultsp;
X	msg.acpted_rply.ar_results.proc = xresults;
X	if (! xdr_replymsg(xdrs, &msg))
X		return (RPC_CANTDECODERES);
X	_seterr_reply(&msg, &error);
X	status = error.re_status;
X
X	if (status == RPC_SUCCESS) {
X		if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
X			status = RPC_AUTHERROR;
X		}
X	}  /* end successful completion */
X	else {
X		if (AUTH_REFRESH(h->cl_auth))
X			goto call_again;
X	}  /* end of unsuccessful completion */
X
X	if (status == RPC_SUCCESS) {
X		if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
X			status = RPC_AUTHERROR;
X		}
X		if (msg.acpted_rply.ar_verf.oa_base != NULL) {
X			xdrs->x_op = XDR_FREE;
X			(void)xdr_opaque_auth(xdrs, &(msg.acpted_rply.ar_verf));
X		}
X	}
X
X	return (status);
X}
X
Xstatic void
Xclntraw_geterr()
X{
X}
X
X
Xstatic bool_t
Xclntraw_freeres(cl, xdr_res, res_ptr)
X	CLIENT *cl;
X	xdrproc_t xdr_res;
X	caddr_t res_ptr;
X{
X	register XDR *xdrs = &xdr_stream;
X
X	xdrs->x_op = XDR_FREE;
X	return ((*xdr_res)(xdrs, res_ptr));
X}
X
Xstatic void
Xclntraw_abort()
X{
X}
X
Xstatic void
Xclntraw_destroy()
X{
X}
SHAR_EOF
if test 5285 -ne "`wc -c < 'rpc/rpclib/clnt_raw.c'`"
then
	echo shar: "error transmitting 'rpc/rpclib/clnt_raw.c'" '(should have been 5285 characters)'
fi
chmod 444 'rpc/rpclib/clnt_raw.c'
fi
echo shar: "extracting 'rpc/rpclib/clnt_simple.c'" '(3016 characters)'
if test -f 'rpc/rpclib/clnt_simple.c'
then
	echo shar: "will not over-write existing file 'rpc/rpclib/clnt_simple.c'"
else
sed 's/^X//' << \SHAR_EOF > 'rpc/rpclib/clnt_simple.c'
X/*
X * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
X * unrestricted use provided that this legend is included on all tape
X * media and as a part of the software program in whole or part.  Users
X * may copy or modify Sun RPC without charge, but are not authorized
X * to license or distribute it to anyone else except as part of a product or
X * program developed by the user.
X * 
X * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
X * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
X * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
X * 
X * Sun RPC is provided with no support and without any obligation on the
X * part of Sun Microsystems, Inc. to assist in its use, correction,
X * modification or enhancement.
X * 
X * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
X * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
X * OR ANY PART THEREOF.
X * 
X * In no event will Sun Microsystems, Inc. be liable for any lost revenue
X * or profits or other special, indirect and consequential damages, even if
X * Sun has been advised of the possibility of such damages.
X * 
X * Sun Microsystems, Inc.
X * 2550 Garcia Avenue
X * Mountain View, California  94043
X */
X#ifndef lint
Xstatic char sccsid[] = "@(#)clnt_simple.c 1.1 86/02/03 Copyr 1984 Sun Micro";
X#endif
X
X/* 
X * clnt_simple.c
X * Simplified front end to rpc.
X *
X * Copyright (C) 1984, Sun Microsystems, Inc.
X */
X
X#include <stdio.h>
X#include <rpc/rpc.h>
X#include <sys/socket.h>
X#include <sys/time.h>
X#include <netdb.h>
X
Xchar *malloc();
Xstatic CLIENT *client;
Xstatic int socket;
Xstatic int oldprognum, oldversnum, valid;
Xstatic char *oldhost;
X
Xcallrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
X	char *host;
X	xdrproc_t inproc, outproc;
X	char *in, *out;
X{
X	struct sockaddr_in server_addr;
X	enum clnt_stat clnt_stat;
X	struct hostent *hp;
X	struct timeval timeout, tottimeout;
X
X	if (oldhost == NULL) {
X		oldhost = malloc(256);
X		oldhost[0] = 0;
X		socket = RPC_ANYSOCK;
X	}
X	if (valid && oldprognum == prognum && oldversnum == versnum
X		&& strcmp(oldhost, host) == 0) {
X		/* reuse old client */		
X	}
X	else {
X		valid = 0;
X		close(socket);
X		socket = RPC_ANYSOCK;
X		if (client) {
X			clnt_destroy(client);
X			client = NULL;
X		}
X		if ((hp = gethostbyname(host)) == NULL)
X			return ((int) RPC_UNKNOWNHOST);
X		timeout.tv_usec = 0;
X		timeout.tv_sec = 5;
X		bcopy(hp->h_addr, &server_addr.sin_addr, hp->h_length);
X		server_addr.sin_family = AF_INET;
X		server_addr.sin_port =  0;
X		if ((client = clntudp_create(&server_addr, prognum,
X		    versnum, timeout, &socket)) == NULL)
X			return ((int) rpc_createerr.cf_stat);
X		valid = 1;
X		oldprognum = prognum;
X		oldversnum = versnum;
X		strcpy(oldhost, host);
X	}
X	tottimeout.tv_sec = 25;
X	tottimeout.tv_usec = 0;
X	clnt_stat = clnt_call(client, procnum, inproc, in,
X	    outproc, out, tottimeout);
X	/* 
X	 * if call failed, empty cache
X	 */
X	if (clnt_stat != RPC_SUCCESS)
X		valid = 0;
X	return ((int) clnt_stat);
X}
SHAR_EOF
if test 3016 -ne "`wc -c < 'rpc/rpclib/clnt_simple.c'`"
then
	echo shar: "error transmitting 'rpc/rpclib/clnt_simple.c'" '(should have been 3016 characters)'
fi
chmod 444 'rpc/rpclib/clnt_simple.c'
fi
echo shar: "extracting 'rpc/rpclib/clnt_tcp.c'" '(10804 characters)'
if test -f 'rpc/rpclib/clnt_tcp.c'
then
	echo shar: "will not over-write existing file 'rpc/rpclib/clnt_tcp.c'"
else
sed 's/^X//' << \SHAR_EOF > 'rpc/rpclib/clnt_tcp.c'
X/*
X * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
X * unrestricted use provided that this legend is included on all tape
X * media and as a part of the software program in whole or part.  Users
X * may copy or modify Sun RPC without charge, but are not authorized
X * to license or distribute it to anyone else except as part of a product or
X * program developed by the user.
X * 
X * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
X * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
X * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
X * 
X * Sun RPC is provided with no support and without any obligation on the
X * part of Sun Microsystems, Inc. to assist in its use, correction,
X * modification or enhancement.
X * 
X * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
X * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
X * OR ANY PART THEREOF.
X * 
X * In no event will Sun Microsystems, Inc. be liable for any lost revenue
X * or profits or other special, indirect and consequential damages, even if
X * Sun has been advised of the possibility of such damages.
X * 
X * Sun Microsystems, Inc.
X * 2550 Garcia Avenue
X * Mountain View, California  94043
X */
X#ifndef lint
Xstatic char sccsid[] = "@(#)clnt_tcp.c 1.1 86/02/03 Copyr 1984 Sun Micro";
X#endif
X 
X/*
X * clnt_tcp.c, Implements a TCP/IP based, client side RPC.
X *
X * Copyright (C) 1984, Sun Microsystems, Inc.
X *
X * TCP based RPC supports 'batched calls'.
X * A sequence of calls may be batched-up in a send buffer.  The rpc call
X * return immediately to the client even though the call was not necessarily
X * sent.  The batching occurs iff the results' xdr routine is NULL (0) AND
X * the rpc timeout value is zero (see clnt.h, rpc).
X *
X * Clients should NOT casually batch calls that in fact return results; that is,
X * the server side should be aware that a call is batched and not produce any
X * return message.  Batched calls that produce many result messages can
X * deadlock (netlock) the client and the server....
X *
X * Now go hang yourself.
X */
X
X#include <stdio.h>
X#include "types.h"
X#include <sys/socket.h>
X#include <sys/time.h>
X#include <netinet/in.h>
X#include <netdb.h>
X#include <errno.h>
X#include "xdr.h"
X#include "auth.h"
X#include "clnt.h"
X#include "rpc_msg.h"
X#include "pmap_clnt.h"
X
X#define MCALL_MSG_SIZE 24
X
Xchar *malloc();
Xextern int errno;
X
Xstatic int	readtcp();
Xstatic int	writetcp();
X
Xstatic enum clnt_stat	clnttcp_call();
Xstatic void		clnttcp_abort();
Xstatic void		clnttcp_geterr();
Xstatic bool_t		clnttcp_freeres();
Xstatic void		clnttcp_destroy();
X
Xstatic struct clnt_ops tcp_ops = {
X	clnttcp_call,
X	clnttcp_abort,
X	clnttcp_geterr,
X	clnttcp_freeres,
X	clnttcp_destroy
X};
X
Xstruct ct_data {
X	int		ct_sock;
X	struct timeval	ct_wait;
X	struct rpc_err	ct_error;
X	char		ct_mcall[MCALL_MSG_SIZE];	/* marshalled callmsg */
X	u_int		ct_mpos;			/* pos after marshal */
X	XDR		ct_xdrs;
X};
X
X/*
X * Create a client handle for a tcp/ip connection.
X * If *sockp<0, *sockp is set to a newly created TCP socket and it is
X * connected to raddr.  If *sockp non-negative then
X * raddr is ignored.  The rpc/tcp package does buffering
X * similar to stdio, so the client must pick send and receive buffer sizes,];
X * 0 => use the default.
X * If raddr->sin_port is 0, then a binder on the remote machine is
X * consulted for the right port number.
X * NB: *sockp is copied into a private area.
X * NB: It is the clients responsibility to close *sockp.
X * NB: The rpch->cl_auth is set null authentication.  Caller may wish to set this
X * something more useful.
X */
XCLIENT *
Xclnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
X	struct sockaddr_in *raddr;
X	u_long prog;
X	u_long vers;
X	register int *sockp;
X	u_int sendsz;
X	u_int recvsz;
X{
X	CLIENT *h;
X	register struct ct_data *ct;
X	struct timeval now;
X	struct rpc_msg call_msg;
X
X	h  = (CLIENT *)mem_alloc(sizeof(*h));
X	if (h == NULL) {
X		fprintf(stderr, "clnttcp_create: out of memory\n");
X		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
X		rpc_createerr.cf_error.re_errno = errno;
X		goto fooy;
X	}
X	ct = (struct ct_data *)mem_alloc(sizeof(*ct));
X	if (ct == NULL) {
X		fprintf(stderr, "clnttcp_create: out of memory\n");
X		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
X		rpc_createerr.cf_error.re_errno = errno;
X		goto fooy;
X	}
X
X	/*
X	 * If no port number given ask the pmap for one
X	 */
X	if (raddr->sin_port == 0) {
X		u_short port;
X		if ((port = pmap_getport(raddr, prog, vers, IPPROTO_TCP)) == 0) {
X			mem_free((caddr_t)ct, sizeof(struct ct_data));
X			mem_free((caddr_t)h, sizeof(CLIENT));
X			return ((CLIENT *)NULL);
X		}
X		raddr->sin_port = htons(port);
X	}
X
X	/*
X	 * If no socket given, open one
X	 */
X	if (*sockp < 0) {
X		if (((*sockp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
X		    || (connect(*sockp, (struct sockaddr *)raddr,
X		    sizeof(*raddr)) < 0)) {
X			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
X			rpc_createerr.cf_error.re_errno = errno;
X			goto fooy;
X		}
X	}
X
X	/*
X	 * Set up private data struct
X	 */
X	ct->ct_sock = *sockp;
X	ct->ct_wait.tv_usec = 0;
X
X	/*
X	 * Initialize call message
X	 */
X	(void)gettimeofday(&now, (struct timezone *)0);
X	call_msg.rm_xid = getpid() ^  now.tv_sec ^ now.tv_usec;
X	call_msg.rm_direction = CALL;
X	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
X	call_msg.rm_call.cb_prog = prog;
X	call_msg.rm_call.cb_vers = vers;
X
X	/*
X	 * pre-serialize the staic part of the call msg and stash it away
X	 */
X	xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
X	    XDR_ENCODE);
X	if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
X		goto fooy;
X	}
X	ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
X	XDR_DESTROY(&(ct->ct_xdrs));
X
X	/*
X	 * Create a client handle which uses xdrrec for serialization
X	 * and authnone for authentication.
X	 */
X	xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
X	    (caddr_t)ct, readtcp, writetcp);
X	h->cl_ops = &tcp_ops;
X	h->cl_private = (caddr_t) ct;
X	h->cl_auth = authnone_create();
X	return (h);
X
Xfooy:
X	/*
X	 * Something goofed, free stuff and barf
X	 */
X	mem_free((caddr_t)ct, sizeof(struct ct_data));
X	mem_free((caddr_t)h, sizeof(CLIENT));
X	(void)close(*sockp);
X	return ((CLIENT *)NULL);
X}
X
Xstatic enum clnt_stat
Xclnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
X	register CLIENT *h;
X	u_long proc;
X	xdrproc_t xdr_args;
X	caddr_t args_ptr;
X	xdrproc_t xdr_results;
X	caddr_t results_ptr;
X	struct timeval timeout;
X{
X	register struct ct_data *ct = (struct ct_data *) h->cl_private;
X	register XDR *xdrs = &(ct->ct_xdrs);
X	struct rpc_msg reply_msg;
X	u_long x_id;
X	u_long *msg_x_id = (u_long *)(ct->ct_mcall);	/* yuk */
X	register bool_t shipnow;
X
X	ct->ct_wait = timeout;
X	shipnow =
X	    (xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0
X	    && timeout.tv_usec == 0) ? FALSE : TRUE;
X
Xcall_again:
X	xdrs->x_op = XDR_ENCODE;
X	ct->ct_error.re_status = RPC_SUCCESS;
X	x_id = ntohl(--(*msg_x_id));
X	if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) ||
X	    (! XDR_PUTLONG(xdrs, (long *)&proc)) ||
X	    (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
X	    (! (*xdr_args)(xdrs, args_ptr))) {
X		if (ct->ct_error.re_status == RPC_SUCCESS)
X			ct->ct_error.re_status = RPC_CANTENCODEARGS;
X		(void)xdrrec_endofrecord(xdrs, TRUE);
X		return (ct->ct_error.re_status);
X	}
X	if (! xdrrec_endofrecord(xdrs, shipnow))
X		return (ct->ct_error.re_status = RPC_CANTSEND);
X	if (! shipnow)
X		return (RPC_SUCCESS);
X	xdrs->x_op = XDR_DECODE;
X
X	/*
X	 * Keep receiving until we get a valid transaction id
X	 */
X	while (TRUE) {
X		reply_msg.acpted_rply.ar_verf = _null_auth;
X		reply_msg.acpted_rply.ar_results.where = NULL;
X		reply_msg.acpted_rply.ar_results.proc = xdr_void;
X		if (! xdrrec_skiprecord(xdrs))
X			return (ct->ct_error.re_status);
X		/* now decode and validate the response header */
X		if (! xdr_replymsg(xdrs, &reply_msg)) {
X			if (ct->ct_error.re_status == RPC_SUCCESS)
X				continue;
X			return (ct->ct_error.re_status);
X		}
X		if (reply_msg.rm_xid == x_id)
X			break;
X	}
X
X	/*
X	 * process header
X	 */
X	_seterr_reply(&reply_msg, &(ct->ct_error));
X	if (ct->ct_error.re_status == RPC_SUCCESS) {
X		if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) {
X			ct->ct_error.re_status = RPC_AUTHERROR;
X			ct->ct_error.re_why = AUTH_INVALIDRESP;
X		} else if (! (*xdr_results)(xdrs, results_ptr)) {
X			if (ct->ct_error.re_status == RPC_SUCCESS)
X				ct->ct_error.re_status = RPC_CANTDECODERES;
X		}
X		/* free verifier ... */
X		if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
X			xdrs->x_op = XDR_FREE;
X			(void)xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf));
X		}
X	}  /* end successful completion */
X	else {
X		/* maybe our credentials need to be refreshed ... */
X		if (AUTH_REFRESH(h->cl_auth))
X			goto call_again;
X	}  /* end of unsuccessful completion */
X	return (ct->ct_error.re_status);
X}
X
Xstatic void
Xclnttcp_geterr(h, errp)
X	CLIENT *h;
X	struct rpc_err *errp;
X{
X	register struct ct_data *ct =
X	    (struct ct_data *) h->cl_private;
X
X	*errp = ct->ct_error;
X}
X
Xstatic bool_t
Xclnttcp_freeres(cl, xdr_res, res_ptr)
X	CLIENT *cl;
X	xdrproc_t xdr_res;
X	caddr_t res_ptr;
X{
X	register struct ct_data *ct = (struct ct_data *)cl->cl_private;
X	register XDR *xdrs = &(ct->ct_xdrs);
X
X	xdrs->x_op = XDR_FREE;
X	return ((*xdr_res)(xdrs, res_ptr));
X}
X
Xstatic void
Xclnttcp_abort()
X{
X}
X
Xstatic void
Xclnttcp_destroy(h)
X	CLIENT *h;
X{
X	register struct ct_data *ct =
X	    (struct ct_data *) h->cl_private;
X
X	XDR_DESTROY(&(ct->ct_xdrs));
X	mem_free((caddr_t)ct, sizeof(struct ct_data));
X	mem_free((caddr_t)h, sizeof(CLIENT));
X}
X
X/*
X * Interface between xdr serializer and tcp connection.
X * Behaves like the system calls, read & write, but keeps some error state
X * around for the rpc level.
X */
Xstatic int
Xreadtcp(ct, buf, len)
X	register struct ct_data *ct;
X	caddr_t buf;
X	register int len;
X{
X	register int mask = 1 << (ct->ct_sock);
X	int readfds;
X
X	if (len == 0)
X		return (0);
X	while (TRUE) {
X		readfds = mask;
X		switch (select(32, &readfds, (int*)NULL, (int*)NULL,
X		    &(ct->ct_wait))) {
X
X		case 0:
X			ct->ct_error.re_status = RPC_TIMEDOUT;
X			return (-1);
X
X		case -1:
X			if (errno == EINTR)
X				continue;
X			ct->ct_error.re_status = RPC_CANTRECV;
X			ct->ct_error.re_errno = errno;
X			return (-1);
X		}
X		if (readfds == mask)
X			break;
X	}
X	switch (len = read(ct->ct_sock, buf, len)) {
X
X	case 0:
X		/* premature eof */
X		ct->ct_error.re_errno = ECONNRESET;
X		ct->ct_error.re_status = RPC_CANTRECV;
X		len = -1;  /* it's really an error */
X		break;
X
X	case -1:
X		ct->ct_error.re_errno = errno;
X		ct->ct_error.re_status = RPC_CANTRECV;
X		break;
X	}
X	return (len);
X}
X
Xstatic int
Xwritetcp(ct, buf, len)
X	struct ct_data *ct;
X	caddr_t buf;
X	int len;
X{
X	register int i, cnt;
X
X	for (cnt = len; cnt > 0; cnt -= i, buf += i) {
X		if ((i = write(ct->ct_sock, buf, cnt)) == -1) {
X			ct->ct_error.re_errno = errno;
X			ct->ct_error.re_status = RPC_CANTSEND;
X			return (-1);
X		}
X	}
X	return (len);
X}
SHAR_EOF
if test 10804 -ne "`wc -c < 'rpc/rpclib/clnt_tcp.c'`"
then
	echo shar: "error transmitting 'rpc/rpclib/clnt_tcp.c'" '(should have been 10804 characters)'
fi
chmod 444 'rpc/rpclib/clnt_tcp.c'
fi
echo shar: "extracting 'rpc/rpclib/clnt_udp.c'" '(10438 characters)'
if test -f 'rpc/rpclib/clnt_udp.c'
then
	echo shar: "will not over-write existing file 'rpc/rpclib/clnt_udp.c'"
else
sed 's/^X//' << \SHAR_EOF > 'rpc/rpclib/clnt_udp.c'
X/*
X * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
X * unrestricted use provided that this legend is included on all tape
X * media and as a part of the software program in whole or part.  Users
X * may copy or modify Sun RPC without charge, but are not authorized
X * to license or distribute it to anyone else except as part of a product or
X * program developed by the user.
X * 
X * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
X * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
X * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
X * 
X * Sun RPC is provided with no support and without any obligation on the
X * part of Sun Microsystems, Inc. to assist in its use, correction,
X * modification or enhancement.
X * 
X * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
X * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
X * OR ANY PART THEREOF.
X * 
X * In no event will Sun Microsystems, Inc. be liable for any lost revenue
X * or profits or other special, indirect and consequential damages, even if
X * Sun has been advised of the possibility of such damages.
X * 
X * Sun Microsystems, Inc.
X * 2550 Garcia Avenue
X * Mountain View, California  94043
X */
X#ifndef lint
Xstatic char sccsid[] = "@(#)clnt_udp.c 1.1 86/02/03 Copyr 1984 Sun Micro";
X#endif
X
X/*
X * clnt_udp.c, Implements a UPD/IP based, client side RPC.
X *
X * Copyright (C) 1984, Sun Microsystems, Inc.
X */
X
X#include <stdio.h>
X#include "types.h"
X#include <sys/socket.h>
X#include <sys/time.h>
X#include <sys/ioctl.h>
X#include <netinet/in.h>
X#include <netdb.h>
X#include <errno.h>
X#include "xdr.h"
X#include "auth.h"
X#include "clnt.h"
X#include "rpc_msg.h"
X#include "pmap_clnt.h"
X
Xchar *malloc();
Xextern int errno;
X
X/*
X * UDP bases client side rpc operations
X */
Xstatic enum clnt_stat	clntudp_call();
Xstatic void		clntudp_abort();
Xstatic void		clntudp_geterr();
Xstatic bool_t		clntudp_freeres();
Xstatic void		clntudp_destroy();
X
Xstatic struct clnt_ops udp_ops = {
X	clntudp_call,
X	clntudp_abort,
X	clntudp_geterr,
X	clntudp_freeres,
X	clntudp_destroy
X};
X
X/* 
X * Private data kept per client handle
X */
Xstruct cu_data {
X	int		   cu_sock;
X	struct sockaddr_in cu_raddr;
X	int		   cu_rlen;
X	struct timeval	   cu_wait;
X	struct rpc_err	   cu_error;
X	XDR		   cu_outxdrs;
X	u_int		   cu_xdrpos;
X	u_int		   cu_sendsz;
X	char		   *cu_outbuf;
X	u_int		   cu_recvsz;
X	char		   cu_inbuf[1];
X};
X
X/*
X * Create a UDP based client handle.
X * If *sockp<0, *sockp is set to a newly created UPD socket.
X * If raddr->sin_port is 0 a binder on the remote machine
X * is consulted for the correct port number.
X * NB: It is the clients responsibility to close *sockp.
X * NB: The rpch->cl_auth is initialized to null authentication.
X *     Caller may wish to set this something more useful.
X *
X * wait is the amount of time used between retransmitting a call if
X * no response has been heard;  retransmition occurs until the actual
X * rpc call times out.
X *
X * sendsz and recvsz are the maximum allowable packet sizes that can be
X * sent and received.
X */
XCLIENT *
Xclntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
X	struct sockaddr_in *raddr;
X	u_long program;
X	u_long version;
X	struct timeval wait;
X	register int *sockp;
X	u_int sendsz;
X	u_int recvsz;
X{
X	CLIENT *cl;
X	register struct cu_data *cu;
X	struct timeval now;
X	struct rpc_msg call_msg;
X
X	cl = (CLIENT *)mem_alloc(sizeof(CLIENT));
X	if (cl == NULL) {
X		fprintf(stderr, "clntudp_create: out of memory\n");
X		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
X		rpc_createerr.cf_error.re_errno = errno;
X		goto fooy;
X	}
X	sendsz = ((sendsz + 3) / 4) * 4;
X	recvsz = ((recvsz + 3) / 4) * 4;
X	cu = (struct cu_data *)mem_alloc(sizeof(*cu) + sendsz + recvsz);
X	if (cu == NULL) {
X		fprintf(stderr, "clntudp_create: out of memory\n");
X		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
X		rpc_createerr.cf_error.re_errno = errno;
X		goto fooy;
X	}
X	cu->cu_outbuf = &cu->cu_inbuf[recvsz];
X
X	(void)gettimeofday(&now, (struct timezone *)0);
X	if (raddr->sin_port == 0) {
X		u_short port;
X		if ((port =
X		    pmap_getport(raddr, program, version, IPPROTO_UDP)) == 0) {
X			goto fooy;
X		}
X		raddr->sin_port = htons(port);
X	}
X	cl->cl_ops = &udp_ops;
X	cl->cl_private = (caddr_t)cu;
X	cu->cu_raddr = *raddr;
X	cu->cu_rlen = sizeof (cu->cu_raddr);
X	cu->cu_wait = wait;
X	cu->cu_sendsz = sendsz;
X	cu->cu_recvsz = recvsz;
X	call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
X	call_msg.rm_direction = CALL;
X	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
X	call_msg.rm_call.cb_prog = program;
X	call_msg.rm_call.cb_vers = version;
X	xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf,
X	    sendsz, XDR_ENCODE);
X	if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) {
X		goto fooy;
X	}
X	cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
X	if (*sockp < 0) {
X		int dontblock = 1;
X
X		*sockp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
X		if (*sockp < 0) {
X			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
X			rpc_createerr.cf_error.re_errno = errno;
X			goto fooy;
X		}
X		/* the sockets rpc controls are non-blocking */
X		(void)ioctl(*sockp, FIONBIO, &dontblock);
X	}
X	cu->cu_sock = *sockp;
X	cl->cl_auth = authnone_create();
X	return (cl);
Xfooy:
X	if (cu)
X		mem_free((caddr_t)cu, sizeof(*cu) + sendsz + recvsz);
X	if (cl)
X		mem_free((caddr_t)cl, sizeof(CLIENT));
X	return ((CLIENT *)NULL);
X}
X
XCLIENT *
Xclntudp_create(raddr, program, version, wait, sockp)
X	struct sockaddr_in *raddr;
X	u_long program;
X	u_long version;
X	struct timeval wait;
X	register int *sockp;
X{
X
X	return(clntudp_bufcreate(raddr, program, version, wait, sockp,
X	    UDPMSGSIZE, UDPMSGSIZE));
X}
X
Xstatic enum clnt_stat 
Xclntudp_call(cl, proc, xargs, argsp, xresults, resultsp, timeout)
X	register CLIENT	*cl;		/* client handle */
X	u_long		proc;		/* procedure number */
X	xdrproc_t	xargs;		/* xdr routine for args */
X	caddr_t		argsp;		/* pointer to args */
X	xdrproc_t	xresults;	/* xdr routine for results */
X	caddr_t		resultsp;	/* pointer to results */
X	struct timeval	timeout;	/* seconds to wait before giving up */
X{
X	register struct cu_data *cu = (struct cu_data *)cl->cl_private;
X	register XDR *xdrs;
X	register int outlen;
X	register int inlen;
X	int readfds, fromlen;
X	register int mask;
X	struct sockaddr_in from;
X	struct rpc_msg reply_msg;
X	XDR reply_xdrs;
X	struct timeval time_waited;
X	bool_t ok;
X
Xcall_again:
X	time_waited.tv_sec = 0;
X	time_waited.tv_usec = 0;
X	xdrs = &(cu->cu_outxdrs);
X	xdrs->x_op = XDR_ENCODE;
X	XDR_SETPOS(xdrs, cu->cu_xdrpos);
X	/*
X	 * the transaction is the first thing in the out buffer
X	 */
X	(*(u_short *)(cu->cu_outbuf))++;
X	if ((! XDR_PUTLONG(xdrs, (long *)&proc)) ||
X	    (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
X	    (! (*xargs)(xdrs, argsp)))
X		return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
X	outlen = (int)XDR_GETPOS(xdrs);
X	while (TRUE) {
X
X		if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0,
X		    (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen)
X		    != outlen) {
X			cu->cu_error.re_errno = errno;
X			return (cu->cu_error.re_status = RPC_CANTSEND);
X		}
X		/*
X		 * sub-optimal code appears inside the loop because we have
X		 * some clock time to spare while the packets are in flight.
X		 * (We assume that this is actually only executed once.)
X		 */
X		reply_msg.acpted_rply.ar_verf = _null_auth;
X		reply_msg.acpted_rply.ar_results.where = resultsp;
X		reply_msg.acpted_rply.ar_results.proc = xresults;
X		mask = 1 << cu->cu_sock;
Xrcv_again:
X		readfds = mask;
X		switch (select(32, &readfds, (int *)NULL, (int *)NULL,
X		    &(cu->cu_wait))) {
X
X		case 0:
X			time_waited.tv_sec += cu->cu_wait.tv_sec;
X			time_waited.tv_usec += cu->cu_wait.tv_usec;
X			while (time_waited.tv_usec >= 1000000) {
X				time_waited.tv_sec++;
X				time_waited.tv_usec -= 1000000;
X			}
X			if ((time_waited.tv_sec < timeout.tv_sec) ||
X				((time_waited.tv_sec == timeout.tv_sec) &&
X				(time_waited.tv_usec < timeout.tv_usec)))
X				continue;
X			return (cu->cu_error.re_status = RPC_TIMEDOUT);
X
X		case -1:
X			if (errno == EINTR)
X				goto rcv_again;
X			cu->cu_error.re_errno = errno;
X			return (cu->cu_error.re_status = RPC_CANTRECV);
X		}
X		if ((readfds & mask) == 0)
X			goto rcv_again;
Xtryagain:
X		fromlen = sizeof(struct sockaddr);
X		inlen = recvfrom(cu->cu_sock, cu->cu_inbuf, cu->cu_recvsz, 0,
X		    (struct sockaddr *)&from, &fromlen);
X		if (inlen < 0) {
X			if (errno == EINTR)
X				goto tryagain;
X			if (errno == EWOULDBLOCK)
X				goto rcv_again;
X			cu->cu_error.re_errno = errno;
X			return (cu->cu_error.re_status = RPC_CANTRECV);
X		}
X		if (inlen < sizeof(u_long))
X			goto rcv_again;
X		/* see if reply transaction id matches sent id */
X		if (*((u_long *)(cu->cu_inbuf)) != *((u_long *)(cu->cu_outbuf)))
X			goto rcv_again;
X		/* we now assume we have the proper reply */
X		break;
X	}
X
X	/*
X	 * now decode and validate the response
X	 */
X	xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)inlen, XDR_DECODE);
X	ok = xdr_replymsg(&reply_xdrs, &reply_msg);
X	/* XDR_DESTROY(&reply_xdrs);  save a few cycles on noop destroy */
X	if (ok) {
X		_seterr_reply(&reply_msg, &(cu->cu_error));
X		if (cu->cu_error.re_status == RPC_SUCCESS) {
X			if (! AUTH_VALIDATE(cl->cl_auth,
X				&reply_msg.acpted_rply.ar_verf)) {
X				cu->cu_error.re_status = RPC_AUTHERROR;
X				cu->cu_error.re_why = AUTH_INVALIDRESP;
X			}
X			if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
X				xdrs->x_op = XDR_FREE;
X				(void)xdr_opaque_auth(xdrs,
X				    &(reply_msg.acpted_rply.ar_verf));
X			} 
X		}  /* end successful completion */
X		else {
X			/* maybe our credentials need to be refreshed ... */
X			if (AUTH_REFRESH(cl->cl_auth))
X				goto call_again;
X		}  /* end of unsuccessful completion */
X	}  /* end of valid reply message */
X	else {
X		cu->cu_error.re_status = RPC_CANTDECODERES;
X	}
X	return (cu->cu_error.re_status);
X}
X
Xstatic void
Xclntudp_geterr(cl, errp)
X	CLIENT *cl;
X	struct rpc_err *errp;
X{
X	register struct cu_data *cu = (struct cu_data *)cl->cl_private;
X
X	*errp = cu->cu_error;
X}
X
X
Xstatic bool_t
Xclntudp_freeres(cl, xdr_res, res_ptr)
X	CLIENT *cl;
X	xdrproc_t xdr_res;
X	caddr_t res_ptr;
X{
X	register struct cu_data *cu = (struct cu_data *)cl->cl_private;
X	register XDR *xdrs = &(cu->cu_outxdrs);
X
X	xdrs->x_op = XDR_FREE;
X	return ((*xdr_res)(xdrs, res_ptr));
X}
X
Xstatic void 
Xclntudp_abort(/*h*/)
X	/*CLIENT *h;*/
X{
X}
X
Xstatic void
Xclntudp_destroy(cl)
X	CLIENT *cl;
X{
X	register struct cu_data *cu = (struct cu_data *)cl->cl_private;
X
X	XDR_DESTROY(&(cu->cu_outxdrs));
X	mem_free((caddr_t)cu, (sizeof(*cu) + cu->cu_sendsz + cu->cu_recvsz));
X	mem_free((caddr_t)cl, sizeof(CLIENT));
X}
SHAR_EOF
if test 10438 -ne "`wc -c < 'rpc/rpclib/clnt_udp.c'`"
then
	echo shar: "error transmitting 'rpc/rpclib/clnt_udp.c'" '(should have been 10438 characters)'
fi
chmod 444 'rpc/rpclib/clnt_udp.c'
fi
exit 0
#	End of shell archive