ONC+ Developer's Guide

Client Side of Simplified Interface

Just one function exists on the client side of the simplified interface: rpc_call(). It has nine parameters:

int	0 or error code
rpc_call (  
       char				*host			/* Name of server host */
       rpcprog_t		prognum		/* Server program number */
       rpcvers_t		versnum		/* Server version number */
       rpcproc_t		procnum		/* Server procedure number */
       xdrproc_t		inproc		/* XDR filter to encode arg */
       char				*in			/* Pointer to argument */
       xdr_proc_t	outproc		/* Filter to decode result */
       char				*out			/* Address to store result */
       char		*nettype	 /*For transport selection */

The rpc_call() function calls the procedure specified by prognum, versum, and procnum on the host. The argument to be passed to the remote procedure is pointed to by the in parameter, and inproc is the XDR filter to encode this argument. The out parameter is an address where the result from the remote procedure is to be placed. outproc is an XDR filter that decodes the result and places it at this address.

The client blocks on rpc_call() until it receives a reply from the server. If the server accepts, it returns RPC_SUCCESS with the value of zero. The server returns a non-zero value if the call was unsuccessful. You can cast this value to the type clnt_stat, an enumerated type defined in the RPC include files and interpreted by the clnt_sperrno() function. This function returns a pointer to a standard RPC error message corresponding to the error code.

In the example, all “visible” transports listed in /etc/netconfig are tried. Adjusting the number of retries requires use of the lower levels of the RPC library.

Multiple arguments and results are handled by collecting them in structures.

The following code example changes the code in Example 4–1 to use the simplified interface.

Example 4–2 rusers Program Using Simplified Interface

#include <stdio.h>

#include <utmpx.h>
#include <rpc/rpc.h>

#include <rpcsvc/rusers.h>
/* a program that calls the RUSERSPROG
 * RPC program
main(argc, argv)
	int argc;
	char **argv;
	unsigned int nusers;
	enum clnt_stat cs;
	if (argc != 2) {
		   fprintf(stderr, "usage: rusers hostname\n");
	if( cs = rpc_call(argv[1], RUSERSPROG,
					(char *)0, xdr_u_int, (char *)&nusers,
     "visible")  !=  RPC_SUCCESS )  {
	fprintf(stderr, "%d users on %s\n", nusers,
						argv[1] );

Data types can be represented differently on different machines. Therefore, rpc_call() needs both the type of the RPC argument and a pointer to it. rpc_call() also needs this information for the result. For RUSERSPROC_NUM, the return value is an unsigned int, so the first return parameter of rpc_call() is xdr_u_int, which is for an unsigned int, and the second return parameter is &nusers, which points to unsigned int storage. Because RUSERSPROC_NUM has no argument, the XDR encoding function of rpc_call() is xdr_void() and its argument is NULL.