Go to main content

ONC+ RPC Developer's Guide

Exit Print View

Updated: March 2019
 
 

RPC Code Examples

This appendix contains copies of the complete live code modules used in the rpcgen and RPC chapters of this book. They are compilable as they are written and will run, unless otherwise noted to be pseudo-code or the like. These examples are provided for informational purposes only. Oracle assumes no liability from their use.

Directory Listing Program and Support Routines (rpcgen)

Example 99  rpcgen Program: dir.x
/*
 * dir.x: Remote directory listing
 * protocol
 *
 * This source module is a rpcgen source module
 * used to demonstrate the functions of the rpcgen
 * tool.
 *
 * It is compiled with the rpcgen -h -T switches to
 * generate both the header (.h) file and the
 * accompanying data structures.
 */
const MAXNAMELEN = 255; /*maxlengthofadirectoryentry*/
typedef string nametype<MAXNAMELEN>; /* directory entry */
typedef struct namenode *namelist; /* linkinthelisting*/

/* A node in the directory listing */
struct namenode {
    nametype name; /* name of directory entry */
    namelist next; /* next entry */
};

/*
 * The result of a READDIR operation:
 * a truly portable application would use an agreed upon list of
 * error codes rather than, as this sample program does, rely upon
 * passing UNIX errno's back. In this example the union is used to
 * discriminate between successful and unsuccessful remote calls.
 */
union readdir_res switch (int errno) {
    case 0:
        namelist list; /*no error: return directory listing*/
    default:
        void; /*error occurred: nothing else to return*/
};

/* The directory program definition */
program DIRPROG {
    version DIRVERS {
        readdir_res
        READDIR(nametype) = 1;
    } = 1;
} = 0x20000076;
Example 100  Remote dir_proc.c
/*
 * dir_proc.c: remote readdir implementation
 */
#include <rpc/rpc.h>      /* Always needed */
#include <dirent.h>
#include "dir.h"          /* Created by rpcgen */

extern int errno;
extern char *malloc();
extern char *strdup();

/* ARGSUSED1*/
readdir_res *
readdir_1(dirname,req)
 	nametype *dirname;
 	struct svc_req *req;
{
 	DIR *dirp;
 	struct dirent *d;
 	namelist nl;
 	namelist *nlp;
 	static readdir_res res; /* must be static! */

	/*
	 * Open directory
	 */
	dirp = opendir(*dirname);
	if (dirp == (DIR *)NULL) {
 		res.errno = errno;
 		return (&res);
 	}
	/*
	 * Free previous result
	 */
	xdr_free(xdr_readdir_res, &res);
	/*
	 * Collect directory entries. Memory allocated here is freed
	 * by xdr_free the next time readdir_1 is called.
	 */

 	nlp = &res.readdir_res_u.list;
 	while (d = readdir(dirp)) {
 		nl = *nlp = (namenode *) malloc(sizeof(namenode));
 		if (nl == (namenode *) NULL) {
 			res.errno = EAGAIN;
 			closedir(dirp);
 			return(&res);
 		}
 		nl->name = strdup(d->d_name);
 		nlp = &nl->next;
 	}
 	*nlp = (namelist)NULL;
 	/* Return the result */
 	res.errno = 0;
 	closedir(dirp);
 	return (&res);
}
Example 101  rls.c Client
/*
 * rls.c: Remote directory listing client
 */

#include <stdio.h>
#include <rpc/rpc.h>	/* always need this */
#include "dir.h"	    /* generated by rpcgen */

extern int errno;

main(argc, argv)
 	int argc;
 	char *argv[];
{
 	CLIENT *cl;
 	char *server;
 	char *dir;
 	readdir_res *result;
 	namelist nl;

	if (argc != 3) {
		fprintf(stderr, "usage: %s host directory\n",
		argv[0]);
		exit(1);
	}
	server = argv[1];
	 dir = argv[2];
/*
 * Create client "handle" used for calling MESSAGEPROG on the
 * server designated on the command line.
 */
	cl = clnt_create(server, DIRPROG, DIRVERS, "visible");
 	if (cl == (CLIENT *)NULL) {
 		clnt_pcreateerror(server);
 		exit(1);
 	}

 	result = readdir_1(&dir, cl);
 	if (result == (readdir_res *)NULL) {
 		clnt_perror(cl, server);
 		exit(1);
 	}

/* Okay, we successfully called the remote procedure. */
	if (result->errno != 0) {
	/*
	 * A remote system error occurred. Print error message and die.
	 */
	}
	if (result->errno < sys_nerr)
 		fprintf (stderr, "%s : %s\n", dir,
 		sys_enlist[result->errno]);
 		errno = result->errno;
 		perror(dir);
 		exit(1);
 	}

/* Successfully got a directory listing. Print it out. */
	for(nl = result->readdir_res_u.list; nl != NULL;
                        nl = nl->next) {
		printf("%s\n", nl->name);
	}
exit(0);