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);