1. Introduction to ONC+ Technologies
4. Programmer's Interface to RPC
5. Advanced RPC Programming Techniques
6. Porting From TS-RPC to TI-RPC
7. Multithreaded RPC Programming
8. Extensions to the Sun RPC Library
B. RPC Protocol and Language Specification
Add Two Numbers Program (rpcgen)
Spray Packets Program (rpcgen)
Print Message Program With Remote Version
F. Writing a Port Monitor With the Service Access Facility (SAF)
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);