< ccc7 /cs/cs4513/public/RPC-Linux/Date >ls date.x dateproc.c rdate.c < ccc7 /cs/cs4513/public/RPC-Linux/Date >rpcgen date.x < ccc7 /cs/cs4513/public/RPC-Linux/Date >ls date.h date_clnt.c dateproc.c date.x date_svc.c rdate.c < ccc7 /cs/cs4513/public/RPC-Linux/Date >cc -o rdate rdate.c date_clnt.c < ccc7 /cs/cs4513/public/RPC-Linux/Date >cc -o dateproc dateproc.c date_svc.c < ccc7 /cs/cs4513/public/RPC-Linux/Date >./dateproc& [1] 15663 < ccc7 /cs/cs4513/public/RPC-Linux/Date >./rdate ccc7 time on host ccc7 = 1081360462 time on host ccc7 = Wed Apr 7 13:54:22 2004 < ccc7 /cs/cs4513/public/example/Date 8 >exit
README by Jae Chung (goos@cs.wpi.edu) Date: April 4, 2004 The RPC examples under ./ex-linux work on Linux machines (ccc, fossil server and clients, and etc.) The RPC examples under ./ex-unix work on Digital Unix machines (cpu). The difference is due to that "rpcgen" in Linux and Digital Unix generate slightly different server side rpc definition. For example, assuming the following date.x: program DATE_PROG { version DATE_VERS { long BIN_DATE(void) = 1; /* procedure number = 1 */ string STR_DATE(long) = 2; /* procedure number = 2 */ } = 1; /* version number = 1 */ } = 0x31234567; The server side rpc definitions (in date.h) generated by Linux are: extern long * bin_date_1_svc(void *, struct svc_req *); extern char ** str_date_1_svc(long *, struct svc_req *); while Digital Unix generates: extern long *bin_date_1(); extern char **str_date_1(); The Linux generated rpc definitions always have two arguements of which the second one can be ignored for general purpose rpc implementations.
/* * date.x Specification of the remote date and time server */ /* * Define two procedures * bin_date_1() returns the binary date and time (no arguments) * str_date_1() takes a binary time and returns a string * */ program DATE_PROG { version DATE_VERS { long BIN_DATE(void) = 1; /* procedure number = 1 */ string STR_DATE(long) = 2; /* procedure number = 2 */ } = 1; /* version number = 1 */ } = 0x31234567; /* program number = 0x31234567 */
/* * Please do not edit this file. * It was generated using rpcgen. */ #ifndef _DATE_H_RPCGEN #define _DATE_H_RPCGEN #include#ifdef __cplusplus extern "C" { #endif #define DATE_PROG 0x31234567 #define DATE_VERS 1 #if defined(__STDC__) || defined(__cplusplus) #define BIN_DATE 1 extern long * bin_date_1(void *, CLIENT *); extern long * bin_date_1_svc(void *, struct svc_req *); #define STR_DATE 2 extern char ** str_date_1(long *, CLIENT *); extern char ** str_date_1_svc(long *, struct svc_req *); extern int date_prog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t); #else /* K&R C */ #define BIN_DATE 1 extern long * bin_date_1(); extern long * bin_date_1_svc(); #define STR_DATE 2 extern char ** str_date_1(); extern char ** str_date_1_svc(); extern int date_prog_1_freeresult (); #endif /* K&R C */ #ifdef __cplusplus } #endif #endif /* !_DATE_H_RPCGEN */
/* * Please do not edit this file. * It was generated using rpcgen. */ #include "date.h" #include#include #include #include #include #include #include #ifndef SIG_PF #define SIG_PF void(*)(int) #endif static void date_prog_1(struct svc_req *rqstp, register SVCXPRT *transp) { union { long str_date_1_arg; } argument; char *result; xdrproc_t _xdr_argument, _xdr_result; char *(*local)(char *, struct svc_req *); switch (rqstp->rq_proc) { case NULLPROC: (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); return; case BIN_DATE: _xdr_argument = (xdrproc_t) xdr_void; _xdr_result = (xdrproc_t) xdr_long; local = (char *(*)(char *, struct svc_req *)) bin_date_1_svc; break; case STR_DATE: _xdr_argument = (xdrproc_t) xdr_long; _xdr_result = (xdrproc_t) xdr_wrapstring; local = (char *(*)(char *, struct svc_req *)) str_date_1_svc; break; default: svcerr_noproc (transp); return; } memset ((char *)&argument, 0, sizeof (argument)); if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { svcerr_decode (transp); return; } result = (*local)((char *)&argument, rqstp); if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) { svcerr_systemerr (transp); } if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { fprintf (stderr, "%s", "unable to free arguments"); exit (1); } return; } int main (int argc, char **argv) { register SVCXPRT *transp; pmap_unset (DATE_PROG, DATE_VERS); transp = svcudp_create(RPC_ANYSOCK); if (transp == NULL) { fprintf (stderr, "%s", "cannot create udp service."); exit(1); } if (!svc_register(transp, DATE_PROG, DATE_VERS, date_prog_1, IPPROTO_UDP)) { fprintf (stderr, "%s", "unable to register (DATE_PROG, DATE_VERS, udp)."); exit(1); } transp = svctcp_create(RPC_ANYSOCK, 0, 0); if (transp == NULL) { fprintf (stderr, "%s", "cannot create tcp service."); exit(1); } if (!svc_register(transp, DATE_PROG, DATE_VERS, date_prog_1, IPPROTO_TCP)) { fprintf (stderr, "%s", "unable to register (DATE_PROG, DATE_VERS, tcp)."); exit(1); } svc_run (); fprintf (stderr, "%s", "svc_run returned"); exit (1); /* NOTREACHED */ }
/* * Please do not edit this file. * It was generated using rpcgen. */ #include/* for memset */ #include "date.h" /* Default timeout can be changed using clnt_control() */ static struct timeval TIMEOUT = { 25, 0 }; long * bin_date_1(void *argp, CLIENT *clnt) { static long clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call (clnt, BIN_DATE, (xdrproc_t) xdr_void, (caddr_t) argp, (xdrproc_t) xdr_long, (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); } char ** str_date_1(long *argp, CLIENT *clnt) { static char *clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call (clnt, STR_DATE, (xdrproc_t) xdr_long, (caddr_t) argp, (xdrproc_t) xdr_wrapstring, (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); }
/* * dateproc.c remote procedures; called by server stub */ #include#include /* standard RPC include file */ #include "date.h" /* this file is generated by rpcgen */ /* * Return the binary date and time */ long *bin_date_1_svc(void *arg1, struct svc_req *arg2) { static long timeval; /* must be static */ timeval = time((long *) 0); return(&timeval); } /* * Convert a binary time and return a human readable string */ char **str_date_1_svc(long *bintime, struct svc_req *arg2) { static char *ptr; /* must be static */ ptr = ctime(bintime); /* convert to local time */ return(&ptr); }
/* * rdate.c client program for remote date program */ #include#include /* standard RPC include file */ #include "date.h" /* this file is generated by rpcgen */ main(int argc, char *argv[]) { CLIENT *cl; /* RPC handle */ char *server; long *lresult; /* return value from bin_date_1() */ char **sresult; /* return value from str_date_1() */ if (argc != 2) { fprintf(stderr, "usage: %s hostname\n", argv[0]); exit(1); } server = argv[1]; /* * Create client handle */ if ((cl = clnt_create(server, DATE_PROG, DATE_VERS, "udp")) == NULL) { /* * can't establish connection with server */ clnt_pcreateerror(server); exit(2); } /* * First call the remote procedure "bin_date". */ if ( (lresult = bin_date_1(NULL, cl)) == NULL) { clnt_perror(cl, server); exit(3); } printf("time on host %s = %ld\n",server, *lresult); /* * Now call the remote procedure str_date */ if ( (sresult = str_date_1(lresult, cl)) == NULL) { clnt_perror(cl, server); exit(4); } printf("time on host %s = %s", server, *sresult); clnt_destroy(cl); /* done with the handle */ exit(0); }