[mod.sources] v06i095: Sun RPC Source

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

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

[  "Don't blame me, I'm only the messenger."  -r$  ]

Sun RPC source (part 7 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/pmap_clnt.c
#	rpc/rpclib/pmap_getmaps.c
#	rpc/rpclib/pmap_getport.c
#	rpc/rpclib/pmap_prot.c
#	rpc/rpclib/pmap_rmt.c
#	rpc/rpclib/rpc_prot.c
#	rpc/rpclib/svc.c
# This archive created: Mon Jul 14 16:55:27 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/pmap_clnt.c'" '(4441 characters)'
if test -f 'rpc/rpclib/pmap_clnt.c'
then
	echo shar: "will not over-write existing file 'rpc/rpclib/pmap_clnt.c'"
else
sed 's/^X//' << \SHAR_EOF > 'rpc/rpclib/pmap_clnt.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[] = "@(#)pmap_clnt.c 1.1 86/02/03 Copyr 1984 Sun Micro";
X#endif
X
X/*
X * pmap_clnt.c
X * Client interface to pmap rpc service.
X *
X * Copyright (C) 1984, Sun Microsystems, Inc.
X */
X
X#include "types.h"
X#include <netinet/in.h>
X#include "xdr.h"
X#include "auth.h"
X#include "clnt.h"
X#include "rpc_msg.h"
X#include "pmap_prot.h" 
X#include "pmap_clnt.h"
X#include <sys/socket.h>
X#include <sys/time.h>
X#include <stdio.h>
X#include <net/if.h>
X#include <sys/ioctl.h>
X#include <arpa/inet.h>
X#define NAMELEN 255
X
Xstatic struct timeval timeout = { 5, 0 };
Xstatic struct timeval tottimeout = { 60, 0 };
Xstatic struct sockaddr_in myaddress;
X
Xvoid clnt_perror();
X
X
X/*
X * Set a mapping between program,version and port.
X * Calls the pmap service remotely to do the mapping.
X */
Xbool_t
Xpmap_set(program, version, protocol, port)
X	u_long program;
X	u_long version;
X	u_long protocol;
X	u_short port;
X{
X	struct sockaddr_in myaddress;
X	int socket = -1;
X	register CLIENT *client;
X	struct pmap parms;
X	bool_t rslt;
X
X	get_myaddress(&myaddress);
X	client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS,
X	    timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
X	if (client == (CLIENT *)NULL)
X		return (FALSE);
X	parms.pm_prog = program;
X	parms.pm_vers = version;
X	parms.pm_prot = protocol;
X	parms.pm_port = port;
X	if (CLNT_CALL(client, PMAPPROC_SET, xdr_pmap, &parms, xdr_bool, &rslt,
X	    tottimeout) != RPC_SUCCESS) {
X		clnt_perror(client, "Cannot register service");
X		return (FALSE);
X	}
X	CLNT_DESTROY(client);
X	(void)close(socket);
X	return (rslt);
X}
X
X/*
X * Remove the mapping between program,version and port.
X * Calls the pmap service remotely to do the un-mapping.
X */
Xbool_t
Xpmap_unset(program, version)
X	u_long program;
X	u_long version;
X{
X	struct sockaddr_in myaddress;
X	int socket = -1;
X	register CLIENT *client;
X	struct pmap parms;
X	bool_t rslt;
X
X	get_myaddress(&myaddress);
X	client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS,
X	    timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
X	if (client == (CLIENT *)NULL)
X		return (FALSE);
X	parms.pm_prog = program;
X	parms.pm_vers = version;
X	parms.pm_port = parms.pm_prot = 0;
X	CLNT_CALL(client, PMAPPROC_UNSET, xdr_pmap, &parms, xdr_bool, &rslt,
X	    tottimeout);
X	CLNT_DESTROY(client);
X	(void)close(socket);
X	return (rslt);
X}
X
X/* 
X * don't use gethostbyname, which would invoke yellow pages
X */
Xget_myaddress(addr)
X	struct sockaddr_in *addr;
X{
X	int s;
X	char buf[BUFSIZ];
X	struct ifconf ifc;
X	struct ifreq ifreq, *ifr;
X	int len;
X
X	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
X	    perror("get_myaddress: socket");
X	    exit(1);
X	}
X	ifc.ifc_len = sizeof (buf);
X	ifc.ifc_buf = buf;
X	if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
X		perror("get_myaddress: ioctl (get interface configuration)");
X		exit(1);
X	}
X	ifr = ifc.ifc_req;
X	for (len = ifc.ifc_len; len; len -= sizeof ifreq) {
X		ifreq = *ifr;
X		if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
X			perror("get_myaddress: ioctl");
X			exit(1);
X		}
X		if ((ifreq.ifr_flags & IFF_UP) &&
X		    ifr->ifr_addr.sa_family == AF_INET) {
X			*addr = *((struct sockaddr_in *)&ifr->ifr_addr);
X			addr->sin_port = htons(PMAPPORT);
X			break;
X		}
X		ifr++;
X	}
X	close(s);
X}
SHAR_EOF
if test 4441 -ne "`wc -c < 'rpc/rpclib/pmap_clnt.c'`"
then
	echo shar: "error transmitting 'rpc/rpclib/pmap_clnt.c'" '(should have been 4441 characters)'
fi
chmod 444 'rpc/rpclib/pmap_clnt.c'
fi
echo shar: "extracting 'rpc/rpclib/pmap_getmaps.c'" '(2732 characters)'
if test -f 'rpc/rpclib/pmap_getmaps.c'
then
	echo shar: "will not over-write existing file 'rpc/rpclib/pmap_getmaps.c'"
else
sed 's/^X//' << \SHAR_EOF > 'rpc/rpclib/pmap_getmaps.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[] = "@(#)pmap_getmaps.c 1.1 86/02/03 Copyr 1984 Sun Micro";
X#endif
X
X/*
X * pmap_getmap.c
X * Client interface to pmap rpc service.
X * contains pmap_getmaps, which is only tcp service involved
X *
X * Copyright (C) 1984, Sun Microsystems, Inc.
X */
X
X#include "types.h"
X#include <netinet/in.h>
X#include "xdr.h"
X#include "auth.h"
X#include "clnt.h"
X#include "rpc_msg.h"
X#include "pmap_prot.h" 
X#include "pmap_clnt.h"
X#include <sys/socket.h>
X#include <sys/time.h>
X#include <netdb.h>
X#include <stdio.h>
X#include <errno.h>
X#include <net/if.h>
X#include <sys/ioctl.h>
X#define NAMELEN 255
X#define MAX_BROADCAST_SIZE 1400
X
Xextern int errno;
Xstatic struct sockaddr_in myaddress;
X
X/*
X * Get a copy of the current port maps.
X * Calls the pmap service remotely to do get the maps.
X */
Xstruct pmaplist *
Xpmap_getmaps(address)
X	 struct sockaddr_in *address;
X{
X	struct pmaplist *head = (struct pmaplist *)NULL;
X	int socket = -1;
X	struct timeval minutetimeout;
X	register CLIENT *client;
X
X	minutetimeout.tv_sec = 60;
X	minutetimeout.tv_usec = 0;
X	address->sin_port = htons(PMAPPORT);
X	client = clnttcp_create(address, PMAPPROG,
X	    PMAPVERS, &socket, 50, 500);
X	if (client != (CLIENT *)NULL) {
X		if (CLNT_CALL(client, PMAPPROC_DUMP, xdr_void, NULL, xdr_pmaplist,
X		    &head, minutetimeout) != RPC_SUCCESS) {
X			clnt_perror(client, "pmap_getmaps rpc problem");
X		}
X		CLNT_DESTROY(client);
X	}
X	(void)close(socket);
X	address->sin_port = 0;
X	return (head);
X}
SHAR_EOF
if test 2732 -ne "`wc -c < 'rpc/rpclib/pmap_getmaps.c'`"
then
	echo shar: "error transmitting 'rpc/rpclib/pmap_getmaps.c'" '(should have been 2732 characters)'
fi
chmod 444 'rpc/rpclib/pmap_getmaps.c'
fi
echo shar: "extracting 'rpc/rpclib/pmap_getport.c'" '(2946 characters)'
if test -f 'rpc/rpclib/pmap_getport.c'
then
	echo shar: "will not over-write existing file 'rpc/rpclib/pmap_getport.c'"
else
sed 's/^X//' << \SHAR_EOF > 'rpc/rpclib/pmap_getport.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[] = "@(#)pmap_getport.c 1.1 86/02/03 Copyr 1984 Sun Micro";
X#endif
X
X/*
X * pmap_getport.c
X * Client interface to pmap rpc service.
X *
X * Copyright (C) 1984, Sun Microsystems, Inc.
X */
X
X#include "types.h"
X#include <netinet/in.h>
X#include "xdr.h"
X#include "auth.h"
X#include "clnt.h"
X#include "rpc_msg.h"
X#include "pmap_prot.h" 
X#include "pmap_clnt.h"
X#include <sys/socket.h>
X#include <sys/time.h>
X#include <stdio.h>
X#include <net/if.h>
X#include <sys/ioctl.h>
X#include <arpa/inet.h>
X#define NAMELEN 255
X
Xstatic struct timeval timeout = { 5, 0 };
Xstatic struct timeval tottimeout = { 60, 0 };
X
X/*
X * Find the mapped port for program,version.
X * Calls the pmap service remotely to do the lookup.
X * Returns 0 if no map exists.
X */
Xu_short
Xpmap_getport(address, program, version, protocol)
X	struct sockaddr_in *address;
X	u_long program;
X	u_long version;
X	u_long protocol;
X{
X	u_short port = 0;
X	int socket = -1;
X	register CLIENT *client;
X	struct pmap parms;
X
X	address->sin_port = htons(PMAPPORT);
X	client = clntudp_bufcreate(address, PMAPPROG,
X	    PMAPVERS, timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
X	if (client != (CLIENT *)NULL) {
X		parms.pm_prog = program;
X		parms.pm_vers = version;
X		parms.pm_prot = protocol;
X		parms.pm_port = 0;  /* not needed or used */
X		if (CLNT_CALL(client, PMAPPROC_GETPORT, xdr_pmap, &parms,
X		    xdr_u_short, &port, tottimeout) != RPC_SUCCESS){
X			rpc_createerr.cf_stat = RPC_PMAPFAILURE;
X			clnt_geterr(client, &rpc_createerr.cf_error);
X		} else if (port == 0) {
X			rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
X		}
X		CLNT_DESTROY(client);
X	}
X	(void)close(socket);
X	address->sin_port = 0;
X	return (port);
X}
SHAR_EOF
if test 2946 -ne "`wc -c < 'rpc/rpclib/pmap_getport.c'`"
then
	echo shar: "error transmitting 'rpc/rpclib/pmap_getport.c'" '(should have been 2946 characters)'
fi
chmod 444 'rpc/rpclib/pmap_getport.c'
fi
echo shar: "extracting 'rpc/rpclib/pmap_prot.c'" '(4003 characters)'
if test -f 'rpc/rpclib/pmap_prot.c'
then
	echo shar: "will not over-write existing file 'rpc/rpclib/pmap_prot.c'"
else
sed 's/^X//' << \SHAR_EOF > 'rpc/rpclib/pmap_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[] = "@(#)pmap_prot.c 1.1 86/02/03 Copyr 1984 Sun Micro";
X#endif
X
X/*
X * pmap_prot.c
X * Protocol for the local binder service, or pmap.
X *
X * Copyright (C) 1984, Sun Microsystems, Inc.
X */
X
X#include "types.h"
X#include "xdr.h"
X#include "pmap_prot.h"
X
X#define NULL ((struct pmaplist *)0)
X
Xbool_t
Xxdr_pmap(xdrs, regs)
X	XDR *xdrs;
X	struct pmap *regs;
X{
X
X	if (xdr_u_long(xdrs, &regs->pm_prog) && 
X		xdr_u_long(xdrs, &regs->pm_vers) && 
X		xdr_u_long(xdrs, &regs->pm_prot))
X		return (xdr_u_long(xdrs, &regs->pm_port));
X	return (FALSE);
X}
X
X/* 
X * What is going on with linked lists? (!)
X * First recall the link list declaration from pmap_prot.h:
X *
X * struct pmaplist {
X *	struct pmap pml_map;
X *	struct pmaplist *pml_map;
X * };
X *
X * Compare that declaration with a corresponding xdr declaration that 
X * is (a) pointer-less, and (b) recursive:
X *
X * typedef union switch (bool_t) {
X * 
X *	case TRUE: struct {
X *		struct pmap;
X * 		pmaplist_t foo;
X *	};
X *
X *	case FALSE: struct {};
X * } pmaplist_t;
X *
X * Notice that the xdr declaration has no nxt pointer while
X * the C declaration has no bool_t variable.  The bool_t can be
X * interpreted as ``more data follows me''; if FALSE then nothing
X * follows this bool_t; if TRUE then the bool_t is followed by
X * an actual struct pmap, and then (recursively) by the 
X * xdr union, pamplist_t.  
X *
X * This could be implemented via the xdr_union primitive, though this
X * would cause a one recursive call per element in the list.  Rather than do
X * that we can ``unwind'' the recursion
X * into a while loop and do the union arms in-place.
X *
X * The head of the list is what the C programmer wishes to past around
X * the net, yet is the data that the pointer points to which is interesting;
X * this sounds like a job for xdr_reference!
X */
Xbool_t
Xxdr_pmaplist(xdrs, rp)
X	register XDR *xdrs;
X	register struct pmaplist **rp;
X{
X	/*
X	 * more_elements is pre-computed in case the direction is
X	 * XDR_ENCODE or XDR_FREE.  more_elements is overwritten by
X	 * xdr_bool when the direction is XDR_DECODE.
X	 */
X	bool_t more_elements;
X	register int freeing = (xdrs->x_op == XDR_FREE);
X	register struct pmaplist **next;
X
X	while (TRUE) {
X		more_elements = (bool_t)(*rp != NULL);
X		if (! xdr_bool(xdrs, &more_elements))
X			return (FALSE);
X		if (! more_elements)
X			return (TRUE);  /* we are done */
X		/*
X		 * the unfortunate side effect of non-recursion is that in
X		 * the case of freeing we must remember the next object
X		 * before we free the current object ...
X		 */
X		if (freeing)
X			next = &((*rp)->pml_next); 
X		if (! xdr_reference(xdrs, (caddr_t *)rp,
X		    (u_int)sizeof(struct pmaplist), xdr_pmap))
X			return (FALSE);
X		rp = (freeing) ? next : &((*rp)->pml_next);
X	}
X}
SHAR_EOF
if test 4003 -ne "`wc -c < 'rpc/rpclib/pmap_prot.c'`"
then
	echo shar: "error transmitting 'rpc/rpclib/pmap_prot.c'" '(should have been 4003 characters)'
fi
chmod 444 'rpc/rpclib/pmap_prot.c'
fi
echo shar: "extracting 'rpc/rpclib/pmap_rmt.c'" '(10629 characters)'
if test -f 'rpc/rpclib/pmap_rmt.c'
then
	echo shar: "will not over-write existing file 'rpc/rpclib/pmap_rmt.c'"
else
sed 's/^X//' << \SHAR_EOF > 'rpc/rpclib/pmap_rmt.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[] = "@(#)pmap_rmt.c 1.1 86/02/03 Copyr 1984 Sun Micro";
X#endif
X
X/*
X * pmap_rmt.c
X * Client interface to pmap rpc service.
X * remote call and broadcast service
X *
X * Copyright (C) 1984, Sun Microsystems, Inc.
X */
X
X#include "types.h"
X#include <netinet/in.h>
X#include "xdr.h"
X#include "auth.h"
X#include "clnt.h"
X#include "rpc_msg.h"
X#include "pmap_prot.h" 
X#include "pmap_clnt.h"
X#include <sys/socket.h>
X#include <sys/time.h>
X#include <stdio.h>
X#include <errno.h>
X#include <net/if.h>
X#include <sys/ioctl.h>
X#include <arpa/inet.h>
X#define MAX_BROADCAST_SIZE 1400
X
Xextern int errno;
Xstatic struct timeval timeout = { 3, 0 };
X
X/*
X * Structures and XDR routines for parameters to and replys from
X * the pmapper remote-call-service.
X */
X
Xstruct rmtcallargs {
X	u_long prog, vers, proc, arglen;
X	caddr_t args_ptr;
X	xdrproc_t xdr_args;
X};
Xstatic bool_t xdr_rmtcall_args();
X
Xstruct rmtcallres {
X	u_long *port_ptr;
X	u_long resultslen;
X	caddr_t results_ptr;
X	xdrproc_t xdr_results;
X};
Xstatic bool_t xdr_rmtcallres();
X
X/*
X * pmapper remote-call-service interface.
X * This routine is used to call the pmapper remote call service
X * which will look up a service program in the port maps, and then
X * remotely call that routine with the given parameters.  This allows
X * programs to do a lookup and call in one step.
X*/
Xenum clnt_stat
Xpmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_ptr)
X	struct sockaddr_in *addr;
X	u_long prog, vers, proc;
X	xdrproc_t xdrargs, xdrres;
X	caddr_t argsp, resp;
X	struct timeval tout;
X	u_long *port_ptr;
X{
X	int socket = -1;
X	register CLIENT *client;
X	struct rmtcallargs a;
X	struct rmtcallres r;
X	enum clnt_stat stat;
X
X	addr->sin_port = htons(PMAPPORT);
X	client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &socket);
X	if (client != (CLIENT *)NULL) {
X		a.prog = prog;
X		a.vers = vers;
X		a.proc = proc;
X		a.args_ptr = argsp;
X		a.xdr_args = xdrargs;
X		r.port_ptr = port_ptr;
X		r.results_ptr = resp;
X		r.xdr_results = xdrres;
X		stat = CLNT_CALL(client, PMAPPROC_CALLIT, xdr_rmtcall_args, &a,
X		    xdr_rmtcallres, &r, tout);
X		CLNT_DESTROY(client);
X	} else {
X		stat = RPC_FAILED;
X	}
X	(void)close(socket);
X	addr->sin_port = 0;
X	return (stat);
X}
X
X/*
X * XDR remote call arguments
X * written for XDR_ENCODE direction only
X */
Xstatic bool_t
Xxdr_rmtcall_args(xdrs, cap)
X	register XDR *xdrs;
X	register struct rmtcallargs *cap;
X{
X	u_int lenposition, argposition, position;
X
X	if (xdr_u_long(xdrs, &(cap->prog)) &&
X	    xdr_u_long(xdrs, &(cap->vers)) &&
X	    xdr_u_long(xdrs, &(cap->proc))) {
X		lenposition = XDR_GETPOS(xdrs);
X		if (! xdr_u_long(xdrs, &(cap->arglen)))
X		    return (FALSE);
X		argposition = XDR_GETPOS(xdrs);
X		if (! (*(cap->xdr_args))(xdrs, cap->args_ptr))
X		    return (FALSE);
X		position = XDR_GETPOS(xdrs);
X		cap->arglen = (u_long)position - (u_long)argposition;
X		XDR_SETPOS(xdrs, lenposition);
X		if (! xdr_u_long(xdrs, &(cap->arglen)))
X		    return (FALSE);
X		XDR_SETPOS(xdrs, position);
X		return (TRUE);
X	}
X	return (FALSE);
X}
X
X/*
X * XDR remote call results
X * written for XDR_DECODE direction only
X */
Xstatic bool_t
Xxdr_rmtcallres(xdrs, crp)
X	register XDR *xdrs;
X	register struct rmtcallres *crp;
X{
X
X	if (xdr_reference(xdrs, &crp->port_ptr, sizeof (u_long), xdr_u_long) &&
X		xdr_u_long(xdrs, &crp->resultslen))
X		return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
X	return (FALSE);
X}
X
X/*
X * The following is kludged-up support for simple rpc broadcasts.
X * Someday a large, complicated system will replace these trivial 
X * routines which only support udp/ip .
X */
X
Xstatic int
Xgetbroadcastnets(addrs, sock, buf)
X	struct in_addr *addrs;
X	int sock;  /* any valid socket will do */
X	char *buf;  /* why allocxate more when we can use existing... */
X{
X	struct ifconf ifc;
X        struct ifreq ifreq, *ifr;
X	struct sockaddr_in *sin;
X        int n, i;
X
X	ifc.ifc_len = MAX_BROADCAST_SIZE;
X        ifc.ifc_buf = buf;
X        if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
X                perror("broadcast: ioctl (get interface configuration)");
X                return (0);
X        }
X        ifr = ifc.ifc_req;
X        for (i = 0, n = ifc.ifc_len/sizeof (struct ifreq); n > 0; n--, ifr++) {
X                ifreq = *ifr;
X                if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
X                        perror("broadcast: ioctl (get interface flags)");
X                        continue;
X                }
X                if ((ifreq.ifr_flags & IFF_BROADCAST) &&
X		    (ifreq.ifr_flags & IFF_UP) &&
X		    ifr->ifr_addr.sa_family == AF_INET) {
X                        sin = (struct sockaddr_in *)&ifr->ifr_addr;
X			addrs[i++] = inet_makeaddr(inet_netof
X			    (sin->sin_addr.s_addr), INADDR_ANY);
X                }
X        }
X	return (i);
X}
X
Xtypedef bool_t (*resultproc_t)();
X
Xenum clnt_stat 
Xclnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
X	u_long		prog;		/* program number */
X	u_long		vers;		/* version number */
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	resultproc_t	eachresult;	/* call with each result obtained */
X{
X	enum clnt_stat stat;
X	AUTH *unix_auth = authunix_create_default();
X	XDR xdr_stream;
X	register XDR *xdrs = &xdr_stream;
X	int outlen, inlen, fromlen, readfds, nets;
X	register int sock, mask, i;
X	bool_t done = FALSE;
X	register u_long xid;
X	u_long port;
X	struct in_addr addrs[20];
X	struct sockaddr_in baddr, raddr; /* broadcast and response addresses */
X	struct rmtcallargs a;
X	struct rmtcallres r;
X	struct rpc_msg msg;
X	struct timeval t; 
X	char outbuf[MAX_BROADCAST_SIZE], inbuf[MAX_BROADCAST_SIZE];
X
X	/*
X	 * initialization: create a socket, a broadcast address, and
X	 * preserialize the arguments into a send buffer.
X	 */
X	if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
X		perror("Cannot create socket for broadcast rpc");
X		stat = RPC_CANTSEND;
X		goto done_broad;
X	}
X	mask = (1 << sock);
X	nets = getbroadcastnets(addrs, sock, inbuf);
X	bzero(&baddr, sizeof (baddr));
X	baddr.sin_family = AF_INET;
X	baddr.sin_port = htons(PMAPPORT);
X	baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
X	(void)gettimeofday(&t, (struct timezone *)0);
X	msg.rm_xid = xid = getpid() ^ t.tv_sec ^ t.tv_usec;
X	t.tv_usec = 0;
X	msg.rm_direction = CALL;
X	msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
X	msg.rm_call.cb_prog = PMAPPROG;
X	msg.rm_call.cb_vers = PMAPVERS;
X	msg.rm_call.cb_proc = PMAPPROC_CALLIT;
X	msg.rm_call.cb_cred = unix_auth->ah_cred;
X	msg.rm_call.cb_verf = unix_auth->ah_verf;
X	a.prog = prog;
X	a.vers = vers;
X	a.proc = proc;
X	a.xdr_args = xargs;
X	a.args_ptr = argsp;
X	r.port_ptr = &port;
X	r.xdr_results = xresults;
X	r.results_ptr = resultsp;
X	xdrmem_create(xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE);
X	if ((! xdr_callmsg(xdrs, &msg)) || (! xdr_rmtcall_args(xdrs, &a))) {
X		stat = RPC_CANTENCODEARGS;
X		goto done_broad;
X	}
X	outlen = (int)xdr_getpos(xdrs);
X	xdr_destroy(xdrs);
X	/*
X	 * Basic loop: broadcast a packet and wait a while for response(s).
X	 * The response timeout grows larger per iteration.
X	 */
X	for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) {
X		for (i = 0; i < nets; i++) {
X			baddr.sin_addr = addrs[i];
X			if (sendto(sock, outbuf, outlen, 0,
X				(struct socketaddr *)&baddr,
X				sizeof (struct sockaddr)) != outlen) {
X				perror("Cannot send broadcast packet");
X				stat = RPC_CANTSEND;
X				goto done_broad;
X			}
X		}
X	recv_again:
X		msg.acpted_rply.ar_verf = _null_auth;
X		msg.acpted_rply.ar_results.where = (caddr_t)&r;
X                msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
X		readfds = mask;
X		switch (select(32, &readfds, (int *)NULL, (int *)NULL, &t)) {
X
X		case 0:  /* timed out */
X			stat = RPC_TIMEDOUT;
X			continue;
X
X		case -1:  /* some kind of error */
X			if (errno == EINTR)
X				goto recv_again;
X			perror("Broadcast select problem");
X			stat = RPC_CANTRECV;
X			goto done_broad;
X
X		}  /* end of select results switch */
X		if ((readfds & mask) == 0)
X			goto recv_again;
X	try_again:
X		fromlen = sizeof(struct sockaddr);
X		inlen = recvfrom(sock, inbuf, MAX_BROADCAST_SIZE, 0,
X			(struct sockaddr *)&raddr, &fromlen);
X		if (inlen < 0) {
X			if (errno == EINTR)
X				goto try_again;
X			perror("Cannot receive reply to broadcast");
X			stat = RPC_CANTRECV;
X			goto done_broad;
X		}
X		if (inlen < sizeof(u_long))
X			goto recv_again;
X		/*
X		 * see if reply transaction id matches sent id.
X		 * If so, decode the results.
X		 */
X		xdrmem_create(xdrs, inbuf, inlen, XDR_DECODE);
X		if (xdr_replymsg(xdrs, &msg)) {
X			if ((msg.rm_xid == xid) &&
X				(msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
X				(msg.acpted_rply.ar_stat == SUCCESS)) {
X				raddr.sin_port = htons((u_short)port);
X				done = (*eachresult)(resultsp, &raddr);
X			}
X			/* otherwise, we just ignore the errors ... */
X		} else {
X#ifdef notdef
X			/* some kind of deserialization problem ... */
X			if (msg.rm_xid == xid)
X				fprintf(stderr, "Broadcast deserialization problem");
X			/* otherwise, just random garbage */
X#endif
X		}
X		xdrs->x_op = XDR_FREE;
X		msg.acpted_rply.ar_results.proc = xdr_void;
X		(void)xdr_replymsg(xdrs, &msg);
X		(void)(*xresults)(xdrs, resultsp);
X		xdr_destroy(xdrs);
X		if (done) {
X			stat = RPC_SUCCESS;
X			goto done_broad;
X		} else {
X			goto recv_again;
X		}
X	}
Xdone_broad:
X	(void)close(sock);
X	AUTH_DESTROY(unix_auth);
X	return (stat);
X}
SHAR_EOF
if test 10629 -ne "`wc -c < 'rpc/rpclib/pmap_rmt.c'`"
then
	echo shar: "error transmitting 'rpc/rpclib/pmap_rmt.c'" '(should have been 10629 characters)'
fi
chmod 444 'rpc/rpclib/pmap_rmt.c'
fi
echo shar: "extracting 'rpc/rpclib/rpc_prot.c'" '(14335 characters)'
if test -f 'rpc/rpclib/rpc_prot.c'
then
	echo shar: "will not over-write existing file 'rpc/rpclib/rpc_prot.c'"
else
sed 's/^X//' << \SHAR_EOF > 'rpc/rpclib/rpc_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[] = "@(#)rpc_prot.c 1.1 86/02/03 Copyr 1984 Sun Micro";
X#endif
X
X/*
X * rpc_prot.c
X *
X * Copyright (C) 1984, Sun Microsystems, Inc.
X *
X * This set of routines implements the rpc message definition,
X * its serializer and some common rpc utility routines.
X * The routines are meant for various implementations of rpc -
X * they are NOT for the rpc client or rpc service implementations!
X * Because authentication stuff is easy and is part of rpc, the opaque
X * routines are also in this program.
X */
X
X#include <sys/param.h>
X#include "types.h"
X#include "xdr.h"
X#include "auth.h"
X#include "clnt.h"
X#include "rpc_msg.h"
X#include <netinet/in.h>
X
X/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
X
Xstruct opaque_auth _null_auth;
X
X/*
X * XDR an opaque authentication struct
X * (see auth.h)
X */
Xbool_t
Xxdr_opaque_auth(xdrs, ap)
X	register XDR *xdrs;
X	register struct opaque_auth *ap;
X{
X
X	if (xdr_enum(xdrs, &(ap->oa_flavor)))
X		return (xdr_bytes(xdrs, &ap->oa_base,
X			&ap->oa_length, MAX_AUTH_BYTES));
X	return (FALSE);
X}
X
X/*
X * XDR a DES key.
X */
Xbool_t
Xxdr_deskey(xdrs, blkp)
X	register XDR *xdrs;
X	register union des_block *blkp;
X{
X
X	if (! xdr_u_long(xdrs, &(blkp->key.high)))
X		return (FALSE);
X	return (xdr_u_long(xdrs, &(blkp->key.low)));
X}
X
X/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
X
X/*
X * XDR the MSG_ACCEPTED part of a reply message union
X */
Xbool_t 
Xxdr_accepted_reply(xdrs, ar)
X	register XDR *xdrs;   
X	register struct accepted_reply *ar;
X{
X
X	/* personalized union, rather than calling xdr_union */
X	if (! xdr_opaque_auth(xdrs, &(ar->ar_verf)))
X		return (FALSE);
X	if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat)))
X		return (FALSE);
X	switch (ar->ar_stat) {
X
X	case SUCCESS:
X		return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where));
X	
X	case PROG_MISMATCH:
X		if (! xdr_u_long(xdrs, &(ar->ar_vers.low)))
X			return (FALSE);
X		return (xdr_u_long(xdrs, &(ar->ar_vers.high)));
X	}
X	return (TRUE);  /* TRUE => open ended set of problems */
X}
X
X/*
X * XDR the MSG_DENIED part of a reply message union
X */
Xbool_t 
Xxdr_rejected_reply(xdrs, rr)
X	register XDR *xdrs;
X	register struct rejected_reply *rr;
X{
X
X	/* personalized union, rather than calling xdr_union */
X	if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat)))
X		return (FALSE);
X	switch (rr->rj_stat) {
X
X	case RPC_MISMATCH:
X		if (! xdr_u_long(xdrs, &(rr->rj_vers.low)))
X			return (FALSE);
X		return (xdr_u_long(xdrs, &(rr->rj_vers.high)));
X
X	case AUTH_ERROR:
X		return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why)));
X	}
X	return (FALSE);
X}
X
X#define	RNDUP(x)  ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \
X		   * BYTES_PER_XDR_UNIT)
X
Xstatic struct xdr_discrim reply_dscrm[3] = {
X	{ (int)MSG_ACCEPTED, xdr_accepted_reply },
X	{ (int)MSG_DENIED, xdr_rejected_reply },
X	{ __dontcare__, NULL_xdrproc_t } };
X
X/*
X * XDR a reply message
X */
Xbool_t
Xxdr_replymsg(xdrs, rmsg)
X	register XDR *xdrs;
X	register struct rpc_msg *rmsg;
X{
X	register long *buf;
X	register struct accepted_reply *ar;
X	register struct opaque_auth *oa;
X
X	if (xdrs->x_op == XDR_ENCODE &&
X	    rmsg->rm_reply.rp_stat == MSG_ACCEPTED &&
X	    rmsg->rm_direction == REPLY &&
X	    (buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT +
X	    rmsg->rm_reply.rp_acpt.ar_verf.oa_length)) != NULL) {
X		IXDR_PUT_LONG(buf, rmsg->rm_xid);
X		IXDR_PUT_ENUM(buf, rmsg->rm_direction);
X		IXDR_PUT_ENUM(buf, rmsg->rm_reply.rp_stat);
X		ar = &rmsg->rm_reply.rp_acpt;
X		oa = &ar->ar_verf;
X		IXDR_PUT_ENUM(buf, oa->oa_flavor);
X		IXDR_PUT_LONG(buf, oa->oa_length);
X		if (oa->oa_length) {
X			bcopy(oa->oa_base, buf, oa->oa_length);
X			buf += (oa->oa_length +
X				BYTES_PER_XDR_UNIT - 1) /
X				sizeof (long);
X		}
X		/*
X		 * stat and rest of reply, copied from xdr_accepted_reply
X		 */
X		IXDR_PUT_ENUM(buf, ar->ar_stat);
X		switch (ar->ar_stat) {
X
X		case SUCCESS:
X			return ((*(ar->ar_results.proc))
X				(xdrs, ar->ar_results.where));
X	
X		case PROG_MISMATCH:
X			if (! xdr_u_long(xdrs, &(ar->ar_vers.low)))
X				return (FALSE);
X			return (xdr_u_long(xdrs, &(ar->ar_vers.high)));
X		}
X		return (TRUE);
X	}
X	if (xdrs->x_op == XDR_DECODE &&
X	    (buf = XDR_INLINE(xdrs, 3 * BYTES_PER_XDR_UNIT)) != NULL) {
X		rmsg->rm_xid = IXDR_GET_LONG(buf);
X		rmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type);
X		if (rmsg->rm_direction != REPLY) {
X			return (FALSE);
X		}
X		rmsg->rm_reply.rp_stat = IXDR_GET_ENUM(buf, enum reply_stat);
X		if (rmsg->rm_reply.rp_stat != MSG_ACCEPTED) {
X			if (rmsg->rm_reply.rp_stat == MSG_DENIED) {
X				return (xdr_rejected_reply(xdrs,
X					&rmsg->rm_reply.rp_rjct));
X			}
X			return (FALSE);
X		}
X		ar = &rmsg->rm_reply.rp_acpt;
X		oa = &ar->ar_verf;
X		buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
X		if (buf != NULL) {
X			oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
X			oa->oa_length = IXDR_GET_LONG(buf);
X		} else {
X			if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE ||
X			    xdr_u_int(xdrs, &oa->oa_length) == FALSE) {
X				return (FALSE);
X			}
X		}
X		if (oa->oa_length) {
X			if (oa->oa_length > MAX_AUTH_BYTES) {
X				return (FALSE);
X			}
X			if (oa->oa_base == NULL) {
X				oa->oa_base = (caddr_t)
X					mem_alloc(oa->oa_length);
X			}
X			buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
X			if (buf == NULL) {
X				if (xdr_opaque(xdrs, oa->oa_base,
X				    oa->oa_length) == FALSE) {
X					return (FALSE);
X				}
X			} else {
X				bcopy(buf, oa->oa_base, oa->oa_length);
X				/* no real need....
X				buf += RNDUP(oa->oa_length) / sizeof (long);
X				*/
X			}
X		}
X		/*
X		 * stat and rest of reply, copied from
X		 * xdr_accepted_reply
X		 */
X		xdr_enum(xdrs, &ar->ar_stat);
X		switch (ar->ar_stat) {
X
X		case SUCCESS:
X			return ((*(ar->ar_results.proc))
X				(xdrs, ar->ar_results.where));
X
X		case PROG_MISMATCH:
X			if (! xdr_u_long(xdrs, &(ar->ar_vers.low)))
X				return (FALSE);
X			return (xdr_u_long(xdrs, &(ar->ar_vers.high)));
X		}
X		return (TRUE);
X	}
X	if (
X	    xdr_u_long(xdrs, &(rmsg->rm_xid)) && 
X	    xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) &&
X	    (rmsg->rm_direction == REPLY) )
X		return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat),
X		    (caddr_t)&(rmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t));
X	return (FALSE);
X}
X
X/*
X * XDR a call message
X */
Xbool_t
Xxdr_callmsg(xdrs, cmsg)
X	register XDR *xdrs;
X	register struct rpc_msg *cmsg;
X{
X	register long *buf;
X	register struct opaque_auth *oa;
X
X	if (xdrs->x_op == XDR_ENCODE) {
X		if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) {
X			return (FALSE);
X		}
X		if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) {
X			return (FALSE);
X		}
X		buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT
X			+ RNDUP(cmsg->rm_call.cb_cred.oa_length)
X			+ 2 * BYTES_PER_XDR_UNIT
X			+ RNDUP(cmsg->rm_call.cb_verf.oa_length));
X		if (buf != NULL) {
X			IXDR_PUT_LONG(buf, cmsg->rm_xid);
X			IXDR_PUT_ENUM(buf, cmsg->rm_direction);
X			if (cmsg->rm_direction != CALL) {
X				return (FALSE);
X			}
X			IXDR_PUT_LONG(buf, cmsg->rm_call.cb_rpcvers);
X			if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
X				return (FALSE);
X			}
X			IXDR_PUT_LONG(buf, cmsg->rm_call.cb_prog);
X			IXDR_PUT_LONG(buf, cmsg->rm_call.cb_vers);
X			IXDR_PUT_LONG(buf, cmsg->rm_call.cb_proc);
X			oa = &cmsg->rm_call.cb_cred;
X			IXDR_PUT_ENUM(buf, oa->oa_flavor);
X			IXDR_PUT_LONG(buf, oa->oa_length);
X			if (oa->oa_length) {
X				bcopy(oa->oa_base, buf, oa->oa_length);
X				buf += RNDUP(oa->oa_length) / sizeof (long);
X			}
X			oa = &cmsg->rm_call.cb_verf;
X			IXDR_PUT_ENUM(buf, oa->oa_flavor);
X			IXDR_PUT_LONG(buf, oa->oa_length);
X			if (oa->oa_length) {
X				bcopy(oa->oa_base, buf, oa->oa_length);
X				/* no real need....
X				buf += RNDUP(oa->oa_length) / sizeof (long);
X				*/
X			}
X			return (TRUE);
X		}
X	}
X	if (xdrs->x_op == XDR_DECODE) {
X		buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT);
X		if (buf != NULL) {
X			cmsg->rm_xid = IXDR_GET_LONG(buf);
X			cmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type);
X			if (cmsg->rm_direction != CALL) {
X				return (FALSE);
X			}
X			cmsg->rm_call.cb_rpcvers = IXDR_GET_LONG(buf);
X			if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
X				return (FALSE);
X			}
X			cmsg->rm_call.cb_prog = IXDR_GET_LONG(buf);
X			cmsg->rm_call.cb_vers = IXDR_GET_LONG(buf);
X			cmsg->rm_call.cb_proc = IXDR_GET_LONG(buf);
X			oa = &cmsg->rm_call.cb_cred;
X			oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
X			oa->oa_length = IXDR_GET_LONG(buf);
X			if (oa->oa_length) {
X				if (oa->oa_length > MAX_AUTH_BYTES) {
X					return (FALSE);
X				}
X				if (oa->oa_base == NULL) {
X					oa->oa_base = (caddr_t)
X						mem_alloc(oa->oa_length);
X				}
X				buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
X				if (buf == NULL) {
X					if (xdr_opaque(xdrs, oa->oa_base,
X					    oa->oa_length) == FALSE) {
X						return (FALSE);
X					}
X				} else {
X					bcopy(buf, oa->oa_base, oa->oa_length);
X					/* no real need....
X					buf += RNDUP(oa->oa_length) /
X						sizeof (long);
X					*/
X				}
X			}
X			oa = &cmsg->rm_call.cb_verf;
X			buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
X			if (buf == NULL) {
X				if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE ||
X				    xdr_u_int(xdrs, &oa->oa_length) == FALSE) {
X					return (FALSE);
X				}
X			} else {
X				oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
X				oa->oa_length = IXDR_GET_LONG(buf);
X			}
X			if (oa->oa_length) {
X				if (oa->oa_length > MAX_AUTH_BYTES) {
X					return (FALSE);
X				}
X				if (oa->oa_base == NULL) {
X					oa->oa_base = (caddr_t)
X						mem_alloc(oa->oa_length);
X				}
X				buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
X				if (buf == NULL) {
X					if (xdr_opaque(xdrs, oa->oa_base,
X					    oa->oa_length) == FALSE) {
X						return (FALSE);
X					}
X				} else {
X					bcopy(buf, oa->oa_base, oa->oa_length);
X					/* no real need...
X					buf += RNDUP(oa->oa_length) /
X						sizeof (long);
X					*/
X				}
X			}
X			return (TRUE);
X		}
X	}
X	if (
X	    xdr_u_long(xdrs, &(cmsg->rm_xid)) &&
X	    xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
X	    (cmsg->rm_direction == CALL) &&
X	    xdr_u_long(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
X	    (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) &&
X	    xdr_u_long(xdrs, &(cmsg->rm_call.cb_prog)) &&
X	    xdr_u_long(xdrs, &(cmsg->rm_call.cb_vers)) &&
X	    xdr_u_long(xdrs, &(cmsg->rm_call.cb_proc)) &&
X	    xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_cred)) )
X	    return (xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_verf)));
X	return (FALSE);
X}
X
X/*
X * Serializes the "static part" of a call message header.
X * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
X * The rm_xid is not really static, but the user can easily munge on the fly.
X */
Xbool_t
Xxdr_callhdr(xdrs, cmsg)
X	register XDR *xdrs;
X	register struct rpc_msg *cmsg;
X{
X
X	cmsg->rm_direction = CALL;
X	cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
X	if (
X	    (xdrs->x_op == XDR_ENCODE) &&
X	    xdr_u_long(xdrs, &(cmsg->rm_xid)) &&
X	    xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
X	    xdr_u_long(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
X	    xdr_u_long(xdrs, &(cmsg->rm_call.cb_prog)) )
X	    return (xdr_u_long(xdrs, &(cmsg->rm_call.cb_vers)));
X	return (FALSE);
X}
X
X/* ************************** Client utility routine ************* */
X
Xstatic void
Xaccepted(acpt_stat, error)
X	register enum accept_stat acpt_stat;
X	register struct rpc_err *error;
X{
X
X	switch (acpt_stat) {
X
X	case PROG_UNAVAIL:
X		error->re_status = RPC_PROGUNAVAIL;
X		return;
X
X	case PROG_MISMATCH:
X		error->re_status = RPC_PROGVERSMISMATCH;
X		return;
X
X	case PROC_UNAVAIL:
X		error->re_status = RPC_PROCUNAVAIL;
X		return;
X
X	case GARBAGE_ARGS:
X		error->re_status = RPC_CANTDECODEARGS;
X		return;
X
X	case SYSTEM_ERR:
X		error->re_status = RPC_SYSTEMERROR;
X		return;
X
X	case SUCCESS:
X		error->re_status = RPC_SUCCESS;
X		return;
X	}
X	/* something's wrong, but we don't know what ... */
X	error->re_status = RPC_FAILED;
X	error->re_lb.s1 = (long)MSG_ACCEPTED;
X	error->re_lb.s2 = (long)acpt_stat;
X}
X
Xstatic void 
Xrejected(rjct_stat, error)
X	register enum reject_stat rjct_stat;
X	register struct rpc_err *error;
X{
X
X	switch (rjct_stat) {
X
X	case RPC_VERSMISMATCH:
X		error->re_status = RPC_VERSMISMATCH;
X		return;
X
X	case AUTH_ERROR:
X		error->re_status = RPC_AUTHERROR;
X		return;
X	}
X	/* something's wrong, but we don't know what ... */
X	error->re_status = RPC_FAILED;
X	error->re_lb.s1 = (long)MSG_DENIED;
X	error->re_lb.s2 = (long)rjct_stat;
X}
X
X/*
X * given a reply message, fills in the error
X */
Xvoid
X_seterr_reply(msg, error)
X	register struct rpc_msg *msg;
X	register struct rpc_err *error;
X{
X
X	/* optimized for normal, SUCCESSful case */
X	switch (msg->rm_reply.rp_stat) {
X
X	case MSG_ACCEPTED:
X		if (msg->acpted_rply.ar_stat == SUCCESS) {
X			error->re_status = RPC_SUCCESS;
X			return;
X		};
X		accepted(msg->acpted_rply.ar_stat, error);
X		break;
X
X	case MSG_DENIED:
X		rejected(msg->rjcted_rply.rj_stat, error);
X		break;
X
X	default:
X		error->re_status = RPC_FAILED;
X		error->re_lb.s1 = (long)(msg->rm_reply.rp_stat);
X		break;
X	}
X	switch (error->re_status) {
X
X	case RPC_VERSMISMATCH:
X		error->re_vers.low = msg->rjcted_rply.rj_vers.low;
X		error->re_vers.high = msg->rjcted_rply.rj_vers.high;
X		break;
X
X	case RPC_AUTHERROR:
X		error->re_why = msg->rjcted_rply.rj_why;
X		break;
X
X	case RPC_PROGVERSMISMATCH:
X		error->re_vers.low = msg->acpted_rply.ar_vers.low;
X		error->re_vers.high = msg->acpted_rply.ar_vers.high;
X		break;
X	}
X}
SHAR_EOF
if test 14335 -ne "`wc -c < 'rpc/rpclib/rpc_prot.c'`"
then
	echo shar: "error transmitting 'rpc/rpclib/rpc_prot.c'" '(should have been 14335 characters)'
fi
chmod 444 'rpc/rpclib/rpc_prot.c'
fi
echo shar: "extracting 'rpc/rpclib/svc.c'" '(10663 characters)'
if test -f 'rpc/rpclib/svc.c'
then
	echo shar: "will not over-write existing file 'rpc/rpclib/svc.c'"
else
sed 's/^X//' << \SHAR_EOF > 'rpc/rpclib/svc.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[] = "@(#)svc.c 1.1 86/02/03 Copyr 1984 Sun Micro";
X#endif
X
X/*
X * svc.c, Server-side remote procedure call interface.
X *
X * There are two sets of procedures here.  The xprt routines are
X * for handling transport handles.  The svc routines handle the
X * list of service routines.
X *
X * Copyright (C) 1984, Sun Microsystems, Inc.
X */
X
X#include "types.h"
X#include <sys/errno.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#include "svc.h"
X#include "svc_auth.h"
X#include "pmap_clnt.h"
X
X#define NOFILE 32
X
Xstatic SVCXPRT *xports[NOFILE];
Xint svc_fds;
Xextern errno;
Xchar *malloc();
X
X#define NULL_SVC ((struct svc_callout *)0)
X#define	RQCRED_SIZE	400
X
X/*
X * The services list
X * Each entry represents a set of procedures (an rpc program).
X * The dispatch routine takes request structs and runs the
X * apropriate procedure.
X */
Xstatic struct svc_callout {
X	struct svc_callout *sc_next;
X	u_long		    sc_prog;
X	u_long		    sc_vers;
X	void		    (*sc_dispatch)();
X} *svc_head;
X
Xstatic struct svc_callout *svc_find();
X
X/* ***************  SVCXPRT related stuff **************** */
X
X/*
X * Activate a transport handle.
X */
Xvoid
Xxprt_register(xprt)
X	SVCXPRT *xprt;
X{
X	register int sock = xprt->xp_sock;
X
X	if (sock < NOFILE) {
X		xports[sock] = xprt;
X		svc_fds |= (1 << sock);
X	}
X}
X
X/*
X * De-activate a transport handle. 
X */
Xvoid
Xxprt_unregister(xprt) 
X	SVCXPRT *xprt;
X{ 
X	register int sock = xprt->xp_sock;
X
X	if ((sock < NOFILE) && (xports[sock] == xprt)) {
X		xports[sock] = (SVCXPRT *)0;
X		svc_fds &= ~(1 << sock);
X	}
X} 
X
X
X/* ********************** CALLOUT list related stuff ************* */
X
X/*
X * Add a service program to the callout list.
X * The dispatch routine will be called when a rpc request for this
X * program number comes in.
X */
Xbool_t
Xsvc_register(xprt, prog, vers, dispatch, protocol)
X	SVCXPRT *xprt;
X	u_long prog;
X	u_long vers;
X	void (*dispatch)();
X	int protocol;
X{
X	struct svc_callout *prev;
X	register struct svc_callout *s;
X
X	if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) {
X		if (s->sc_dispatch == dispatch)
X			goto pmap_it;  /* he is registering another xptr */
X		return (FALSE);
X	}
X	s = (struct svc_callout *)mem_alloc(sizeof(struct svc_callout));
X	if (s == (struct svc_callout *)0) {
X		return (FALSE);
X	}
X	s->sc_prog = prog;
X	s->sc_vers = vers;
X	s->sc_dispatch = dispatch;
X	s->sc_next = svc_head;
X	svc_head = s;
Xpmap_it:
X	/* now register the information with the local binder service */
X	if (protocol) {
X		return (pmap_set(prog, vers, protocol, xprt->xp_port));
X	}
X	return (TRUE);
X}
X
X/*
X * Remove a service program from the callout list.
X */
Xvoid
Xsvc_unregister(prog, vers)
X	u_long prog;
X	u_long vers;
X{
X	struct svc_callout *prev;
X	register struct svc_callout *s;
X
X	if ((s = svc_find(prog, vers, &prev)) == NULL_SVC)
X		return;
X	if (prev == NULL_SVC) {
X		svc_head = s->sc_next;
X	} else {
X		prev->sc_next = s->sc_next;
X	}
X	s->sc_next = NULL_SVC;
X	mem_free((char *) s, (u_int) sizeof(struct svc_callout));
X	/* now unregister the information with the local binder service */
X	(void)pmap_unset(prog, vers);
X}
X
X/*
X * Search the callout list for a program number, return the callout
X * struct.
X */
Xstatic struct svc_callout *
Xsvc_find(prog, vers, prev)
X	u_long prog;
X	u_long vers;
X	struct svc_callout **prev;
X{
X	register struct svc_callout *s, *p;
X
X	p = NULL_SVC;
X	for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
X		if ((s->sc_prog == prog) && (s->sc_vers == vers))
X			goto done;
X		p = s;
X	}
Xdone:
X	*prev = p;
X	return (s);
X}
X
X/* ******************* REPLY GENERATION ROUTINES  ************ */
X
X/*
X * Send a reply to an rpc request
X */
Xbool_t
Xsvc_sendreply(xprt, xdr_results, xdr_location)
X	register SVCXPRT *xprt;
X	xdrproc_t xdr_results;
X	caddr_t xdr_location;
X{
X	struct rpc_msg rply; 
X
X	rply.rm_direction = REPLY;  
X	rply.rm_reply.rp_stat = MSG_ACCEPTED; 
X	rply.acpted_rply.ar_verf = xprt->xp_verf; 
X	rply.acpted_rply.ar_stat = SUCCESS;
X	rply.acpted_rply.ar_results.where = xdr_location;
X	rply.acpted_rply.ar_results.proc = xdr_results;
X	return (SVC_REPLY(xprt, &rply)); 
X}
X
X/*
X * No procedure error reply
X */
Xvoid
Xsvcerr_noproc(xprt)
X	register SVCXPRT *xprt;
X{
X	struct rpc_msg rply;
X
X	rply.rm_direction = REPLY;
X	rply.rm_reply.rp_stat = MSG_ACCEPTED;
X	rply.acpted_rply.ar_verf = xprt->xp_verf;
X	rply.acpted_rply.ar_stat = PROC_UNAVAIL;
X	SVC_REPLY(xprt, &rply);
X}
X
X/*
X * Can't decode args error reply
X */
Xvoid
Xsvcerr_decode(xprt)
X	register SVCXPRT *xprt;
X{
X	struct rpc_msg rply; 
X
X	rply.rm_direction = REPLY; 
X	rply.rm_reply.rp_stat = MSG_ACCEPTED; 
X	rply.acpted_rply.ar_verf = xprt->xp_verf;
X	rply.acpted_rply.ar_stat = GARBAGE_ARGS;
X	SVC_REPLY(xprt, &rply); 
X}
X
X/*
X * Some system error
X */
Xvoid
Xsvcerr_systemerr(xprt)
X	register SVCXPRT *xprt;
X{
X	struct rpc_msg rply; 
X
X	rply.rm_direction = REPLY; 
X	rply.rm_reply.rp_stat = MSG_ACCEPTED; 
X	rply.acpted_rply.ar_verf = xprt->xp_verf;
X	rply.acpted_rply.ar_stat = SYSTEM_ERR;
X	SVC_REPLY(xprt, &rply); 
X}
X
X/*
X * Authentication error reply
X */
Xvoid
Xsvcerr_auth(xprt, why)
X	SVCXPRT *xprt;
X	enum auth_stat why;
X{
X	struct rpc_msg rply;
X
X	rply.rm_direction = REPLY;
X	rply.rm_reply.rp_stat = MSG_DENIED;
X	rply.rjcted_rply.rj_stat = AUTH_ERROR;
X	rply.rjcted_rply.rj_why = why;
X	SVC_REPLY(xprt, &rply);
X}
X
X/*
X * Auth too weak error reply
X */
Xvoid
Xsvcerr_weakauth(xprt)
X	SVCXPRT *xprt;
X{
X
X	svcerr_auth(xprt, AUTH_TOOWEAK);
X}
X
X/*
X * Program unavailable error reply
X */
Xvoid 
Xsvcerr_noprog(xprt)
X	register SVCXPRT *xprt;
X{
X	struct rpc_msg rply;  
X
X	rply.rm_direction = REPLY;   
X	rply.rm_reply.rp_stat = MSG_ACCEPTED;  
X	rply.acpted_rply.ar_verf = xprt->xp_verf;  
X	rply.acpted_rply.ar_stat = PROG_UNAVAIL;
X	SVC_REPLY(xprt, &rply);
X}
X
X/*
X * Program version mismatch error reply
X */
Xvoid  
Xsvcerr_progvers(xprt, low_vers, high_vers)
X	register SVCXPRT *xprt; 
X	u_long low_vers;
X	u_long high_vers;
X{
X	struct rpc_msg rply;
X
X	rply.rm_direction = REPLY;
X	rply.rm_reply.rp_stat = MSG_ACCEPTED;
X	rply.acpted_rply.ar_verf = xprt->xp_verf;
X	rply.acpted_rply.ar_stat = PROG_MISMATCH;
X	rply.acpted_rply.ar_vers.low = low_vers;
X	rply.acpted_rply.ar_vers.high = high_vers;
X	SVC_REPLY(xprt, &rply);
X}
X
X/* ******************* SERVER INPUT STUFF ******************* */
X
X/*
X * Get server side input from some transport.
X *
X * Statement of authentication parameters management:
X * This function owns and manages all authentication parameters, specifically
X * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
X * the "cooked" credentials (rqst->rq_clntcred).  However, this function
X * does not know the structure of the cooked credentials, so it make the
X * following two assumptions: a) the structure is contiguous (no pointers), and
X * b) the structure size does not exceed RQCRED_SIZE bytes. 
X * In all events, all three parameters are freed upon exit from this routine.
X * The storage is trivially management on the call stack in user land, but
X * is mallocated in kernel land.
X */
Xvoid
Xsvc_getreq(rdfds)
X	int rdfds;
X{
X	register enum xprt_stat stat;
X	struct rpc_msg msg;
X	int prog_found;
X	u_long low_vers;
X	u_long high_vers;
X	struct svc_req r;
X	register int sock;
X	register int readfds = rdfds & svc_fds;
X	register SVCXPRT *xprt;
X	char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];
X	msg.rm_call.cb_cred.oa_base = cred_area;
X	msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
X	r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]);
X
X	for (sock = 0; readfds != 0; sock++, readfds >>= 1) {
X	    if ((readfds & 1) != 0) {
X		/* sock has input waiting */
X		xprt = xports[sock];
X		/* now receive msgs from xprtprt (support batch calls) */
X		do {
X			if (SVC_RECV(xprt, &msg)) {
X
X				/* now find the exported program and call it */
X				register struct svc_callout *s;
X				enum auth_stat why;
X
X				r.rq_xprt = xprt;
X				r.rq_prog = msg.rm_call.cb_prog;
X				r.rq_vers = msg.rm_call.cb_vers;
X				r.rq_proc = msg.rm_call.cb_proc;
X				r.rq_cred = msg.rm_call.cb_cred;
X				/* first authenticate the message */
X				if ((why= _authenticate(&r, &msg)) != AUTH_OK) {
X					svcerr_auth(xprt, why);
X					goto call_done;
X				}
X				/* now match message with a registered service*/
X				prog_found = FALSE;
X				low_vers = 0 - 1;
X				high_vers = 0;
X				for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
X					if (s->sc_prog == r.rq_prog) {
X						if (s->sc_vers == r.rq_vers) {
X							(*s->sc_dispatch)(&r, xprt);
X							goto call_done;
X						}  /* found correct version */
X						prog_found = TRUE;
X						if (s->sc_vers < low_vers)
X							low_vers = s->sc_vers;
X						if (s->sc_vers > high_vers)
X							high_vers = s->sc_vers;
X					}   /* found correct program */
X				}
X				/*
X				 * if we got here, the program or version
X				 * is not served ...
X				 */
X				if (prog_found)
X					svcerr_progvers(xprt,
X					low_vers, high_vers);
X				else
X					 svcerr_noprog(xprt);
X				/* Fall through to ... */
X			}
X		call_done:
X			if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
X				SVC_DESTROY(xprt);
X				break;
X			}
X		} while (stat == XPRT_MOREREQS);
X	    }
X	}
X}
X
X
X/*
X * This is the rpc server side idle loop
X * Wait for input, call server program.
X */
Xvoid
Xsvc_run()
X{
X	int readfds;
X
X	while (TRUE) {
X		readfds = svc_fds;
X		switch (select(32, &readfds, (int *)0, (int *)0,
X		    (struct timeval *)0)) {
X
X		case -1:
X			if (errno == EINTR)
X				continue;
X			else {
X				perror("svc.c: - Select failed");
X				return;
X			}
X		case 0:
X			continue;
X		default:
X			svc_getreq(readfds);
X		}
X	}
X}
SHAR_EOF
if test 10663 -ne "`wc -c < 'rpc/rpclib/svc.c'`"
then
	echo shar: "error transmitting 'rpc/rpclib/svc.c'" '(should have been 10663 characters)'
fi
chmod 444 'rpc/rpclib/svc.c'
fi
exit 0
#	End of shell archive