Appendix D
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. Sun Microsystems assumes no liability from their use.
Directory Listing Program and Support Routines (rpcgen)
Example D-1 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 D-2 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 D-3 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);
|