Skip Navigation Links | |
Exit Print View | |
ONC+ Developer's Guide Oracle Solaris 11.1 Information Library |
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 Oracle Solaris RPC Library
B. RPC Protocol and Language Specification
Add Two Numbers Program (rpcgen)
Spray Packets Program (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);