Subject: v06i099: Sun RPC Source (rpc2), Part11/11 Newsgroups: mod.sources Approved: rs@mirror.UUCP Submitted by: cca!SUN.COM!marks (Mark Stein) Mod.sources: Volume 6, Issue 99 Archive-name: rpc2/Part11 [ I have only verified that this unpacks correctly. --r$ ] Sun RPC source (part 11 of 11). This software package contains code and documentation for Revision 3.0 of the Sun Remote Procedure Call library. In addition, a beta version of the XDR/RPC protocol compiler is included. Comments about this latest release may be mailed to sun!rpc or rpc@sun.com. Sun RPC is a product of Sun Microsystems, Inc. and is provided for unrestricted use provided that this legend is included on all tape media and as a part of the software program in whole or part. Users may copy or modify Sun RPC without charge, but are not authorized to license or distribute it to anyone else except as part of a product or program developed by the user. - - - - - - - - - C U T - H E R E - - - - - - - - - - - - - - - - - - #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # rpc/rpcgen/rpc_util.c # rpc/rpcgen/rpc_util.h # rpc/rpcgen/rpcgen.1 # rpc/rpcgen/xdr_update.c # rpc/rpcgen/test/Makefile # rpc/rpcgen/test/demo_clnt.c # rpc/rpcgen/test/demo_proc.c # rpc/rpcgen/test/demo_xdr.x # This archive created: Mon Jul 14 16:55:53 1986 export PATH; PATH=/bin:/usr/bin:$PATH for d in rpc rpc/doc rpc/rpclib rpc/tools rpc/toys rpc/rpclib/profiled rpc/rpcgen rpc/rpcgen/test do if test ! -d $d then echo "shar: Making directory $d" mkdir $d chmod 755 $d fi done echo shar: "extracting 'rpc/rpcgen/rpc_util.c'" '(4145 characters)' if test -f 'rpc/rpcgen/rpc_util.c' then echo shar: "will not over-write existing file 'rpc/rpcgen/rpc_util.c'" else sed 's/^X//' << \SHAR_EOF > 'rpc/rpcgen/rpc_util.c' X#ifndef lint Xstatic char sccsid[] = "@(#)rpc_util.c 1.1 86/03/26 (C) 1986 SMI"; X#endif X X/* X * rpc_util.c, Utility routines for the RPC protocol compiler X * Copyright (C) 1986, Sun Microsystems, Inc. X */ X#include X#include "rpc_scan.h" X#include "rpc_util.h" X Xchar curline[MAXLINESIZE]; /* current read line */ Xchar *where = curline; /* current point in line */ Xint linenum = 0; /* current line number */ X Xchar *infile; /* input filename */ Xchar *outfile; /* output filename */ Xchar *outfile2; /* possible other output filename */ X XFILE *fout; /* file pointer of current output */ XFILE *fin; /* file pointer of current input */ X Xlist *printed; /* list of printed routines */ Xlist *defined; /* list of defined things */ X X/* X * Reinitialize the world X */ Xreinitialize() X{ X bzero(curline,MAXLINESIZE); X where = curline; X linenum = 0; X printed = NULL; X defined = NULL; X} X X/* X * string equality X */ Xstreq(a,b) X char *a; X char *b; X{ X return(strcmp(a,b) == 0); X} X X/* X * find a value in a list X */ Xchar * Xfindval(lst,val,cmp) X list *lst; X char *val; X int (*cmp)(); X{ X for (; lst != NULL; lst = lst->next) { X if ((*cmp)(lst->val,val)) { X return(lst->val); X } X } X return(NULL); X} X X/* X * store a value in a list X */ Xvoid Xstoreval(lstp,val) X list **lstp; X char *val; X{ X list **l; X list *lst; X X for (l = lstp; *l != NULL; l = (list **) &(*l)->next) X ; X lst = ALLOC(list); X lst->val = val; X lst->next = NULL; X *l = lst; X} X X X/* X * print a useful (?) error message, and then die X */ Xvoid Xerror(msg) X char *msg; X{ X extern char *outfile; X X printwhere(); X fprintf(stderr,"%s, line %d: ",infile ? infile : "", linenum); X fprintf(stderr,"%s\n",msg); X crash(); X} X X/* X * Something went wrong, unlink any files X * that we may have created and then die. X */ Xcrash() X{ X if (outfile) { X unlink(outfile); X } X if (outfile2) { X unlink(outfile2); X } X exit(1); X} X X X Xstatic char expectbuf[100]; Xstatic char *toktostr(); X X/* X * error, token encountered was not the expected one X */ Xvoid Xexpected1(exp1) X tok_kind exp1; X{ X sprintf(expectbuf,"expected '%s'", X toktostr(exp1)); X error(expectbuf); X} X X/* X * error, token encountered was not one of two expected ones X */ Xvoid Xexpected2(exp1,exp2) X tok_kind exp1,exp2; X{ X sprintf(expectbuf,"expected '%s' or '%s'", X toktostr(exp1), X toktostr(exp2)); X error(expectbuf); X} X X/* X * error, token encountered was not one of 3 expected ones X */ Xvoid Xexpected3(exp1,exp2,exp3) X tok_kind exp1,exp2,exp3; X{ X sprintf(expectbuf,"expected '%s', '%s' or '%s'", X toktostr(exp1), X toktostr(exp2), X toktostr(exp3)); X error(expectbuf); X} X X X Xstatic token tokstrings[] = { X { TOK_IDENT, "identifier" }, X { TOK_CONST, "constant" }, X { TOK_RPAREN, ")" }, X { TOK_LPAREN, "(" }, X { TOK_RBRACE, "}" }, X { TOK_LBRACE, "{" }, X { TOK_LBRACKET, "[" }, X { TOK_RBRACKET, "]" }, X { TOK_STAR, "*" }, X { TOK_COMMA, "," }, X { TOK_EQUAL, "=" }, X { TOK_COLON, ":" }, X { TOK_SEMICOLON, ";" }, X { TOK_UNION, "union" }, X { TOK_STRUCT, "struct" }, X { TOK_SWITCH, "switch" }, X { TOK_CASE, "case" }, X { TOK_DEFAULT, "default" }, X { TOK_ENUM, "enum" }, X { TOK_ARRAY, "array" }, X { TOK_TYPEDEF, "typedef" }, X { TOK_INT, "int" }, X { TOK_SHORT, "short" }, X { TOK_LONG, "long" }, X { TOK_UNSIGNED, "unsigned" }, X { TOK_DOUBLE, "double" }, X { TOK_FLOAT, "float" }, X { TOK_CHAR, "char" }, X { TOK_STRING, "string" }, X { TOK_OPAQUE, "opaque" }, X { TOK_BOOL, "bool" }, X { TOK_VOID, "void" }, X { TOK_PROGRAM, "program" }, X { TOK_VERSION, "version" }, X { TOK_EOF, "??????" } X}; X Xstatic char * Xtoktostr(kind) X tok_kind kind; X{ X token *sp; X X for (sp = tokstrings; sp->kind != TOK_EOF && sp->kind != kind; sp++) X ; X return(sp->str); X} X X Xstatic Xprintbuf() X{ X char c; X int i; X int cnt; X X# define TABSIZE 4 X X for (i = 0; c = curline[i]; i++) { X if (c == '\t') { X cnt = 8 - (i % TABSIZE); X c = ' '; X } else { X cnt = 1; X } X while (cnt--) { X putc(c,stderr); X } X } X} X X Xstatic Xprintwhere() X{ X int i; X char c; X int cnt; X X printbuf(); X for (i = 0; i < where - curline; i++) { X c = curline[i]; X if (c == '\t') { X cnt = 8 - (i % TABSIZE); X } else { X cnt = 1; X } X while (cnt--) { X putc('^',stderr); X } X } X putc('\n',stderr); X} SHAR_EOF if test 4145 -ne "`wc -c < 'rpc/rpcgen/rpc_util.c'`" then echo shar: "error transmitting 'rpc/rpcgen/rpc_util.c'" '(should have been 4145 characters)' fi chmod 444 'rpc/rpcgen/rpc_util.c' fi echo shar: "extracting 'rpc/rpcgen/rpc_util.h'" '(1202 characters)' if test -f 'rpc/rpcgen/rpc_util.h' then echo shar: "will not over-write existing file 'rpc/rpcgen/rpc_util.h'" else sed 's/^X//' << \SHAR_EOF > 'rpc/rpcgen/rpc_util.h' X/* @(#)rpc_util.h 1.1 86/03/26 (C) 1986 SMI */ X X/* X * rpc_util.h, Useful definitions for the RPC protocol compiler X * Copyright (C) 1986, Sun Microsystems, Inc. X */ X Xextern char *malloc(); Xextern char *sprintf(); X#define alloc(size) malloc((unsigned)(size)) X#define ALLOC(object) (object *) malloc(sizeof(object)) X X#define OFF 0 X#define ON 1 X Xstruct list { X char *val; X struct list *next; X}; Xtypedef struct list list; X X/* X * Global variables X */ X#define MAXLINESIZE 1024 Xextern char curline[MAXLINESIZE]; Xextern char *where; Xextern int linenum; X Xextern char *outfile; Xextern char *outfile2; Xextern char *infile; Xextern FILE *fout; Xextern FILE *fin; X Xextern list *printed; Xextern list *defined; X X X/* X * rpc_util routines X */ Xvoid storeval(); X#define STOREVAL(list,item) \ X storeval(list,(char *)item) X Xchar *findval(); X#define FINDVAL(list,item,finder) \ X findval(list, (char *) item, finder) X Xint streq(); Xvoid error(); Xvoid expected1(); Xvoid expected2(); Xvoid expected3(); X X/* X * rpc_cout routines X */ Xvoid cprint(); Xvoid emit(); X X/* X * rpc_hout routines X */ Xvoid print_datadef(); Xvoid print_funcdefs(); X X/* X * rpc_svcout routines X */ Xvoid write_most(); Xvoid write_register(); Xvoid write_rest(); X SHAR_EOF if test 1202 -ne "`wc -c < 'rpc/rpcgen/rpc_util.h'`" then echo shar: "error transmitting 'rpc/rpcgen/rpc_util.h'" '(should have been 1202 characters)' fi chmod 444 'rpc/rpcgen/rpc_util.h' fi echo shar: "extracting 'rpc/rpcgen/rpcgen.1'" '(11239 characters)' if test -f 'rpc/rpcgen/rpcgen.1' then echo shar: "will not over-write existing file 'rpc/rpcgen/rpcgen.1'" else sed 's/^X//' << \SHAR_EOF > 'rpc/rpcgen/rpcgen.1' X.\" @(#)rpcgen.1 1.1 86/04/15 SMI X.TH RPCGEN 1 "11 March 1986" X.SH NAME Xrpcgen \- an RPC protocol compiler X.SH SYNOPSIS X\fBrpcgen\fP \fB-h\fP \fB[-o \fIoutfile\fP]\fP \fB[\fIinputfile\fP]\fP X.br X\fBrpcgen\fP \fB-c\fP \fB[-o \fIoutfile\fP]\fP \fB[\fIinfile\fP]\fP X.br X\fBrpcgen\fP \fIinfile\fP X.br X\fBrpcgen\fP \fB[-s \fItransport\fP]*\fP \fB[-o\fP \fIoutfile\fP]\fP \fB[\fIinfile\fP]\fP X.br X.SH DESCRIPTION X\fIrpcgen\fP is a tool that generates X.B C Xcode to implement an X.SM RPC Xprotocol. The input to \fIrpcgen\fP is a language with striking Xsimilarity to X.B C Xknown as RPCL (Remote Procedure Call Language). X.I rpcgen Xoperates in four modes. The first mode is used to convert XRPCL definitions into X.B C Xdefinitions for use as a header file. XThe second mode compiles the XDR routines required to serialize the protocol Xdescribed by RPCL. The third mode compiles both, leaving the Xheader file in a file named \fIinfile\fP with a X.B .h Xextension and the XDR routines in \fIinfile\fP with a X.B .c Xextension. The fourth mode is used to compile an RPC server skeleton, so that Xall you have to do is write local procedures that know nothing about RPC Xin order to implement an RPC server. X.LP XThe input may contain X.BR C -style Xcomments and preprocessor directives. Comments are ignored, while the Xdirectives are simply stuffed uninterpreted in the output header file. X.LP XYou can customize some of your XDR routines by leaving those data Xtypes undefined. For every data type that is undefined, \fIrpcgen\fP Xwill assume that there exists a routine with the name `xdr_' prepended Xto the name of the undefined type. X.SH OPTIONS X.IP \fB-c\fP XCompile XDR routines. X.IP \fB-h\fP XCompile X.B C Xdata-definitions (a header file) X.IP "\fB-o\fP \fIoutfile\fP" XSpecify the name of the output file. If none is specified, standard Xoutput is used (\fB-c\fP, \fB-h\fP and \fB-s\fP modes only). X.IP "\fB-s\fP \fItransport\fP" XCompile a server, using the the given transport. The supported transports Xare \fBudp\fP and \fBtcp\fP. This option may be invoked more than once Xso as to compile a server that serves multiple transports. X.SH USAGE X.SS "RPCL Syntax Summary" XThis summary of RPCL syntax, which is used for X.I rpcgen Xinput, is intended more for aiding Xcomprehension than as an exact statement of the language. X.SS "Primitive Data Types" X.RS X.nf X[ \fBunsigned\fP ] \fBchar\fP X[ \fBunsigned\fP ] \fBshort\fP X[ \fBunsigned\fP ] \fBint\fP X[ \fBunsigned\fP ] \fBlong\fP X\fBunsigned\fP X\fBfloat\fP X\fBdouble\fP X\fBvoid\fP X\fBbool\fP X.fi X.RE XExcept for the added boolean data-type \fBbool\fP, XRPCL is identical to X.BR C . X\fIrpcgen\fP converts \fBbool\fP declarations to \fBint\fP declarations in the Xoutput header file (literally it is converted to a \fBbool_t\fP, which has been X\fB#define\fP'd to be an \fBint\fP). Also, \fBvoid\fP declarations Xmay appear only inside of X.B union Xand X.B program Xdefinitions. For those averse to typing the prefix X\fBunsigned\fP, the abbreviations \fBu_char\fP, \fBu_short\fP, \fBu_int\fP and X\fBu_long\fP are available. X.SS Declarations XRPCL allows only three kinds of declarations: X.LP X\fIdeclaration:\fP X.RS X.nf X\fIsimple-declaration\fP X\fIpointer-declaration\fP X\fIvector-declaration\fP X.fi X.RE X.LP X\fIsimple-declaration:\fP X.RS X\fItype-name\fP \fIobject-ident\fP X.RE X.LP X\fIpointer-declaration:\fP X.RS X\fItype-name\fP \fB*\fP\fIobject-ident\fP X.RE X.LP X\fIvector-declaration:\fP X.RS X\fItype-name\fP \fIobject-ident\fP\fB[\fP\fIsize\fP\fB]\fP X.RE X.LP X(\fIsize\fP can be either an integer or a symbolic constant) X.RE X.LP XRPCL declarations contain both limitations and extensions with Xrespect to X.BR C . XThe limitations are that you cannot declare Xmultidimensional arrays or pointers-to-pointers in-line (You Xcan still declare them though, using \fBtypedef\fP). There Xare two extensions: X.LP X.RS XOpaque data is declared as a vector as follows: X.LP X.RS X\fBopaque\fP \fIobject-ident\fP \fB[\fP \fIsize\fP \fB]\fP X.RE X.LP XIn the protocol, this results in an object of \fIsize\fP bytes. Note that Xthis is \fInot\fP the same as a declaration of \fIsize\fP characters, Xsince XDR characters are 32-bits. Opaque declarations are compiled in the Xoutput header file into character array declarations of \fIsize\fP bytes. X.LP XStrings are special and are declared as a vector declaration: X.LP X.RS X\fBstring\fP \fIobject-ident\fP \fB[\fP \fImax-size\fP \fB]\fP X.RE X.LP XIf \fImax-size\fP is unspecified, then there is essentially no limit to Xthe maximum length of the string. String declarations get compiled into Xthe following: X.LP X.RS Xchar *\fIobject-ident\fP X.RE X.RE X.RE X.SS "Type Definitions" XThe only way to generate an XDR routine is to define a type. For Xevery type \fIzetype\fP you define, there is a corresponding XXDR routine named \fIxdr_zetype\fP. X.LP XThere are six ways to define a type: X.LP X\fItype-definition:\fP X.RS X.nf X\fItypedef\fP X\fIenumeration-def\fP X\fIstructure-def\fP X\fIvariable-length-array-def\fP X\fIdiscriminated-union-def\fP X\fIprogram-def\fP X.fi X.RE X.LP XThe first three are very similar to their X.B C Xnamesakes. X.B C Xdoes not have a formal type mechanism to define variable-length arrays and XXDR unions are quite different from their X.B C Xcounterparts. Program definitions are not really type definitions, Xbut they are useful nonetheless. X.LP XYou may not nest XDR definitions. For example, the following will Xcause \fIrpcgen\fP to choke: X.RS X.nf Xstruct dontdoit { X struct ididit { X int oops; X } sorry; X enum ididitagain { OOPS, WHOOPS } iapologize; X}; X.fi X.RE X.SS \fRTypedefs XAn XDR \fBtypedef\fP looks as follows: X.LP X\fItypedef:\fP X.RS X\fBtypedef\fP \fIdeclaration\fP \fB;\fP X.RE XThe \fIobject-ident\fP part of \fIdeclaration\fP is the name of the new type, Xwhereas the \fItype-name\fP part is the name of the type from which it is Xderived. X.LP X.SS "\fIEnumeration Types" XThe syntax is: X.LP X\fIenumeration-def:\fP X.RS X\fBenum\fP \fIenum-ident\fP \fB{\fP X.RS X\fIenum-list\fP X.RE X\fB};\fP X.RE X.LP X\fIenum-list:\fP X.RS X\fIenum-symbol-ident\fP [ \fB=\fP \fIassignment\fP ] X.br X\fIenum-symbol-ident\fP [ \fB=\fP \fIassignment\fP ] \fB,\fP \fIenum-list\fP X.RE X.LP X(\fIassignment\fP may be either an integer or a symbolic constant) X.LP XIf there is no explicit assignment, then the implicit assignment is the Xvalue of the previous enumeration plus 1. If not explicitly assigned, Xthe first enumeration receives the value 0. X.SS \fIStructures X\fIstructure-def:\fP X.RS X\fBstruct\fP \fIstruct-ident\fP \fB{\fP X.RS X\fIdeclaration-list\fP X.RE X\fB};\fP X.RE X.LP X\fIdeclaration-list:\fP X.RS X\fIdeclaration\fP \fB;\fP X.br X\fIdeclaration\fP \fB;\fP \fIdeclaration-list\fP X.RE X.RE X.LP X.SS "\fIVariable-Length Arrays" X\fIvariable-length-array-def:\fP X.RS X\fBarray\fP \fIarray-ident\fP \fB{\fP X.RS X\fBunsigned\fP \fIlength-identifer\fP \fB;\fP X.br X\fIvector-declaration\fP \fB;\fP X.RE X\fB};\fP X.RE X.LP XA variable length array definition looks much like a structure Xdefinition. Here's an example: X.RS X.nf Xarray mp_int { X unsigned len; X short val[MAX_MP_LENGTH]; X}; X.fi X.RE XThis is compiled into: X.RS X.nf Xstruct mp_int { X unsigned len; X short *val; X}; Xtypedef struct mp_int mp_int; X.fi X.RE X.SS "\fIDisriminated Unions" X\fIdiscriminated-union-def:\fP X.RS X\fBunion\fP \fIunion-ident\fP \fBswitch\fP \fB(\fP \fIdiscriminant-declaration\fP \fB)\fP \fB{\fP X.RS X\fIcase-list\fP X.br X[ \fBdefault\fP \fB:\fP \fIdeclaration\fP \fB;\fP ] X.RE X\fB};\fP X.RE X.LP X\fIcase-list:\fP X.RS X\fBcase\fP \fIcase-ident\fP \fB:\fP \fIdeclaration\fP \fB;\fP X.br X\fBcase\fP \fIcase-ident\fP \fB:\fP \fIdeclaration\fP \fB;\fP \fIcase-list\fP X.RE X.LP X\fIdiscriminant-declaration:\fP X.RS X\fIdeclaration\fP X.RE X.LP XThe union definition looks like a cross between a C-union and a C-switch. XAn example: X.RS X.nf Xunion net_object switch (net_kind kind) { Xcase MACHINE: X struct sockaddr_in sin; Xcase USER: X int uid; Xdefault: X string whatisit; X}; X.fi X.RE XCompiles into: X.RS X.nf Xstruct net_object { X net_kind kind; X union { X struct sockaddr_in sin; X int uid; X char *whatisit; X } net_object; X}; Xtypedef struct net_object net_object; X.fi X.RE XNote that the name of the union component of the output struct is the Xsame as the name of the type itself. X.SS "\fIProgram Definitions" X\fIprogram-def:\fP X.RS X\fBprogram\fP \fIprogram-ident\fP \fB{\fP X.RS X\fIversion-list\fP X.RE X\fB}\fP \fB=\fP \fIprogram-number\fP \fB;\fP X.RE X.LP X\fIversion-list:\fP X.RS X\fIversion\fP X.br X\fIversion\fP \fIversion-list\fP X.RE X\fIversion:\fP X.RS X\fBversion\fP \fIversion-ident\fP \fB{\fP X.RS X\fIprocedure-list\fP X.RE X\fB} =\fP \fIversion-number\fP \fB;\fP X.RE X\fIprocedure-list:\fP X.RS X\fIprocedure-declaration\fP X.br X\fIprocedure-declaration procedure-list\fP X.RE X\fIprocedure-declaration:\fP X.RS X\fItype-name\fP \fIprocedure-ident\fP \fB(\fP \fItype-name\fP \fB)\fP \fB=\fP \fIprocedure-number\fP \fB;\fP X.RE X.LP XProgram definitions look like nothing you've ever seen before, so we Xturn to an example to explain them. Suppose you wanted to create server Xthat could get or set the date. It's declaration might look like this: X.RS X.nf Xprogram DATE_PROG { X version DATE_VERS { X date DATE_GET(timezone) = 1; X void DATE_SET(date) = 2; /* Greenwich mean time */ X } = 1; X} = 100; X.fi X.RE XIn the header file, this compiles into the following: X.RS X.nf X#define DATE_PROG 100 X#define DATE_VERS 1 X#define DATE_GET 1 X#define DATE_SET 2 X.fi X.RE XThese \fBdefine\fP's are intended for use by the client program to Xreference the remote procedures. X.LP XIf you are using \fIrpcgen\fP to compile your server, then there are Xsome important things for you to know. The server interfaces to Xyour local procedures by expecting a X.B C Xfunction with the same name as that in the program definition, but in all Xlower-case letters and followed by the version number. Here is the local Xprocedure that implements DATE_GET: X.RS X.nf Xdate * /* always returns a pointer to the results */ Xdate_get_1(tz) X timezone *tz; /* always takes a a pointer to the arguments */ X{ X static date d; /* must be static! */ X X /* X * figure out the date X * and store it in d X */ X return(&d); X} X.fi X.RE XThe name of the routine is the same as the \fB#define\fP'd name, but in all Xlower case letters and followed by the version number. XDR will recursively Xfree the argument after getting the Xresults from your local procedure, so you should copy from the argument Xany data that you will need between calls. However, XDR neither allocates Xnor frees your results. You must take care of their storage yourself. X.LP X.SS "Make Inference Rules For Compiling XDR Headers" X.LP XIt is possible to set up suffix transformation rules in X.IR make (1) Xfor compiling XDR routines and header files. The Xconvention is that RPCL protocol files have the extension X.BR .x . XThe \fImake\fP rules to do this are: X.nf X .SUFFIXES: .x X .x.c: X rpcgen -c $< -o $@ X X .x.h: X rpcgen -h $< -o $@ X.fi X.SH "SEE ALSO" X\fIRemote Procedure Call: Programming Guide\fP Xand \fIExternal Data Representation: Protocol Specification\fP Xin\fI Networking on the Sun Workstation\fP X.SH BUGS XName clashes can occur when using program definitions, since the apparent Xscoping does not really apply. Most of these can be avoided by giving Xunique names for programs, versions, procedures and types. SHAR_EOF if test 11239 -ne "`wc -c < 'rpc/rpcgen/rpcgen.1'`" then echo shar: "error transmitting 'rpc/rpcgen/rpcgen.1'" '(should have been 11239 characters)' fi chmod 444 'rpc/rpcgen/rpcgen.1' fi echo shar: "extracting 'rpc/rpcgen/xdr_update.c'" '(1993 characters)' if test -f 'rpc/rpcgen/xdr_update.c' then echo shar: "will not over-write existing file 'rpc/rpcgen/xdr_update.c'" else sed 's/^X//' << \SHAR_EOF > 'rpc/rpcgen/xdr_update.c' X/* X * xdr_update.c: Additions to release 3.0 XDR routines required X * for rpcgen. These routines are from release 3.2BETA and X * may be updated before final release. X * X * Copyright (C) 1986, Sun Microsystems, Inc. X * X */ X X#include X#define NULL 0 X#define LASTUNSIGNED ((u_int)0-1) X X/* X * xdr_pointer(): X * X * XDR a pointer to a possibly recursive data structure. This X * differs with xdr_reference in that it can serialize/deserialiaze X * trees correctly. X * X * What's sent is actually a union: X * X * union object_pointer switch (boolean b) { X * case TRUE: object_data data; X * case FALSE: void nothing; X * } X * X * > objpp: Pointer to the pointer to the object. X * > obj_size: size of the object. X * > xdr_obj: routine to XDR an object. X * X */ Xbool_t Xxdr_pointer(xdrs,objpp,obj_size,xdr_obj) X register XDR *xdrs; X char **objpp; X u_int obj_size; X xdrproc_t xdr_obj; X{ X X bool_t more_data; X X more_data = (*objpp != NULL); X if (! xdr_bool(xdrs,&more_data)) { X return(FALSE); X } X if (! more_data) { X *objpp = NULL; X return(TRUE); X } X return(xdr_reference(xdrs,objpp,obj_size,xdr_obj)); X} X X/* X * xdr_vector(): X * X * XDR a fixed length array. Unlike variable-length arrays, X * the storage of fixed length arrays is static and unfreeable. X * > basep: base of the array X * > size: size of the array X * > elemsize: size of each element X * > xdr_elem: routine to XDR each element X */ Xbool_t Xxdr_vector(xdrs, basep, nelem, elemsize, xdr_elem) X register XDR *xdrs; X register char *basep; X register u_int nelem; X register u_int elemsize; X register xdrproc_t xdr_elem; X{ X register u_int i; X register char *elptr; X X elptr = basep; X for (i = 0; i < nelem; i++) { X if (! (*xdr_elem)(xdrs, elptr, LASTUNSIGNED)) { X return(FALSE); X } X elptr += elemsize; X } X return(TRUE); X} SHAR_EOF if test 1993 -ne "`wc -c < 'rpc/rpcgen/xdr_update.c'`" then echo shar: "error transmitting 'rpc/rpcgen/xdr_update.c'" '(should have been 1993 characters)' fi chmod 664 'rpc/rpcgen/xdr_update.c' fi echo shar: "extracting 'rpc/rpcgen/test/Makefile'" '(1274 characters)' if test -f 'rpc/rpcgen/test/Makefile' then echo shar: "will not over-write existing file 'rpc/rpcgen/test/Makefile'" else sed 's/^X//' << \SHAR_EOF > 'rpc/rpcgen/test/Makefile' X# Makefile for the demo rpc service for rpcgen X# X# There are three source files used by this makefile: X# demo_xdr.x Demo protocol specification used as input X# by rpcgen to generate demo_xdr.h (xdr X# defines and data type decarations), X# demo_xdr.c (xdr data type routines), X# and demo.c (server program shell) X# demo_proc.c The actual procedure handlers for the server. X# demo_clnt.c The client program. X X.SUFFIXES: .x .c .h .o XCC = cc X X# REL3_0 should be defined in CFLAGS if using a pre-3.2 rpc library XCFLAGS = -DREL3_0 X XRPCGEN = ../rpcgen XPROTO = udp X XSOBJS = demo.o demo_proc.o demo_xdr.o XCOBJS = demo_clnt.o demo_xdr.o X X# RPCLIB should be the rpc library, or commented out if included in libc. X# xdr_update.o should be included if linking with a pre-3.2 rpc library. X#RPCLIB = -lrpc XRPCLIB = ../xdr_update.o X X.x.c: X $(RPCGEN) -c $< -o $@ X.x.h: X $(RPCGEN) -h $< -o $@ X Xall: demo_svr demo_clnt X Xdemo_svr: $(SOBJS) X $(CC) $(CFLAGS) -o $@ $(SOBJS) $(RPCLIB) X Xdemo_clnt: $(COBJS) X $(CC) $(CFLAGS) -o $@ $(COBJS) $(RPCLIB) X Xdemo.c: demo_xdr.x demo_xdr.h X $(RPCGEN) -s $(PROTO) demo_xdr.x -o $@ X Xdemo_xdr.c: demo_xdr.x Xdemo_xdr.o: demo_xdr.c demo_xdr.h Xdemo_proc.o: demo_xdr.h Xdemo_clnt.o: demo_xdr.h X Xclean: X -rm -f *.o *.h demo_clnt demo_svr demo_xdr.c demo.c SHAR_EOF if test 1274 -ne "`wc -c < 'rpc/rpcgen/test/Makefile'`" then echo shar: "error transmitting 'rpc/rpcgen/test/Makefile'" '(should have been 1274 characters)' fi chmod 664 'rpc/rpcgen/test/Makefile' fi echo shar: "extracting 'rpc/rpcgen/test/demo_clnt.c'" '(3254 characters)' if test -f 'rpc/rpcgen/test/demo_clnt.c' then echo shar: "will not over-write existing file 'rpc/rpcgen/test/demo_clnt.c'" else sed 's/^X//' << \SHAR_EOF > 'rpc/rpcgen/test/demo_clnt.c' X/* X * Client program for rpcgen demo X */ X X#include X#include X#include "demo_xdr.h" X Xchar *Prog, *Host; X Xstruct Calls { X char *name; /* name of call */ X enum ret_status arg_type; /* arg type expected */ X int procno; /* proc number */ X} Calls[] = { X { "ctime", RET_CLOCK, CTIME }, X { "localtime", RET_CLOCK, LOCALTIME }, X { "gmtime", RET_CLOCK, GMTIME }, X { "asctime", RET_TM, ASCTIME }, X { "timezone", RET_TZ, TIMEZONE }, X { "dysize", RET_YEAR, DYSIZE }, X { NULL } X}; X Xchar *Arg; Xdemo_res Res; Xxdrproc_t Xargs, Xres; X Xmain(argc, argv) Xchar **argv; X{ X struct Calls *callp; X int ret; X X Prog = argv[0]; X if (argc < 3) X usage(); X X for (callp = Calls; callp->name; callp++) X if (!strcmp(callp->name, argv[2])) X break; X if (callp->name == NULL) { X fprintf(stderr, "%s: call \"%s\" not recognized.\n", X Prog, argv[2]); X exit(1); X } X Host = argv[1]; X argc -= 3; argv += 3; X getargs(argc, argv, callp); X Xres = xdr_demo_res; X if (ret = callrpc(Host, DEMOPROG, DEMOVERS, callp->procno, X Xargs, Arg, Xres, &Res)) X { X fprintf(stderr, "%s: rpc failed: ", Prog); X clnt_perrno(ret); X fprintf(stderr, "\n"); X exit(1); X } X printres(callp); X} X Xgetargs(argc, argv, callp) Xint argc; Xchar **argv; Xstruct Calls *callp; X{ X static long l_arg; X static timeval tv; X static tzargs tz_arg; X X gettimeofday(&tv, &tz_arg); X switch (callp->arg_type) { X case RET_CLOCK: X l_arg = (long)(argc > 0? atoi(argv[0]) : tv.tv_sec); X Arg = (char *)&l_arg; X Xargs = xdr_clock; X break; X case RET_TM: X l_arg = (long)(argc > 0? atoi(argv[0]) : tv.tv_sec); X Arg = (char *)localtime(&l_arg); X Xargs = xdr_tm; X break; X case RET_TZ: X if (argc == 1) { X fprintf(stderr, "\ X%s: call \"%s\" takes two arguments.\n", Prog, callp->name); X exit(1); X } else if (argc > 1) { X tz_arg.zone = atoi(argv[0]); X tz_arg.dst = atoi(argv[1]); X } X Arg = (char *)&tz_arg; X Xargs = xdr_tzargs; X break; X case RET_YEAR: X l_arg = (argc > 0? atoi(argv[0]) : 1986); X Arg = (char *)&l_arg; X Xargs = xdr_int; X break; X default: X fprintf(stderr, "%s: panic: unknown arg type %d\n", X Prog, callp->arg_type); X exit(1); X } X} X Xprintres(callp) Xstruct Calls *callp; X{ X switch (Res.which) { X case RET_DATE: X printf("date from %s: %s\n", Host, Res.demo_res.date); X break; X case RET_TM: X#define TZP(x) Res.demo_res.tmp->tm_/**/x X printf("\ Xtime info from %s: sec=%d, min=%d, hour=%d, mday=%d, mon=%d,\n\ X year=%d, wday=%d, yday=%d, isdst=%d\n", X Host, TZP(sec), TZP(min), TZP(hour), TZP(mday), X TZP(mon), TZP(year), TZP(wday), TZP(yday), TZP(isdst)); X break; X case RET_STR: X printf("Return string from %s: %s\n", Host, Res.demo_res.str); X break; X case RET_DAYS: X printf("Return from %s: %d days\n", Host, Res.demo_res.days); X break; X case RET_ERROR: X printf("%s returned error %d (%s)\n", Host, X Res.demo_res.err.err_number, X Res.demo_res.err.err_text); X break; X default: X printf("%s returned an unknown return type (%d)\n", X Host, Res.which); X break; X } X} X Xusage() X{ X struct Calls *callp; X X fprintf(stderr, "usage: %s host call [args]\n", Prog); X fprintf(stderr, "valid calls are:\n"); X for (callp = Calls; callp->name; callp++) X fprintf(stderr, "\t%s\n", callp->name); X exit(1); X} SHAR_EOF if test 3254 -ne "`wc -c < 'rpc/rpcgen/test/demo_clnt.c'`" then echo shar: "error transmitting 'rpc/rpcgen/test/demo_clnt.c'" '(should have been 3254 characters)' fi chmod 664 'rpc/rpcgen/test/demo_clnt.c' fi echo shar: "extracting 'rpc/rpcgen/test/demo_proc.c'" '(833 characters)' if test -f 'rpc/rpcgen/test/demo_proc.c' then echo shar: "will not over-write existing file 'rpc/rpcgen/test/demo_proc.c'" else sed 's/^X//' << \SHAR_EOF > 'rpc/rpcgen/test/demo_proc.c' X/* X * Demo procedures X */ X X#include X#include X#include "demo_xdr.h" Xstatic demo_res res; X Xdemo_res * Xctime_5(arg) Xclock *arg; X{ X res.which = RET_DATE; X res.demo_res.date = (date)ctime(arg); X return &res; X} X Xdemo_res * Xlocaltime_5(arg) Xclock *arg; X{ X res.which = RET_TM; X res.demo_res.tmp = (tm *)localtime(arg); X return &res; X} X Xdemo_res * Xgmtime_5(arg) Xclock *arg; X{ X res.which = RET_TM; X res.demo_res.tmp = (tm *)gmtime(arg); X return &res; X} X Xdemo_res * Xasctime_5(arg) Xtm *arg; X{ X res.which = RET_DATE; X res.demo_res.date = (date)asctime(arg); X return &res; X} X Xdemo_res * Xtimezone_5(arg) Xtzargs *arg; X{ X res.which = RET_STR; X res.demo_res.str = (str)timezone(arg->zone, arg->dst); X return &res; X} X Xdemo_res * Xdysize_5(val) Xint *val; X{ X res.which = RET_DAYS; X res.demo_res.days = dysize(*val); X return &res; X} SHAR_EOF if test 833 -ne "`wc -c < 'rpc/rpcgen/test/demo_proc.c'`" then echo shar: "error transmitting 'rpc/rpcgen/test/demo_proc.c'" '(should have been 833 characters)' fi chmod 664 'rpc/rpcgen/test/demo_proc.c' fi echo shar: "extracting 'rpc/rpcgen/test/demo_xdr.x'" '(1834 characters)' if test -f 'rpc/rpcgen/test/demo_xdr.x' then echo shar: "will not over-write existing file 'rpc/rpcgen/test/demo_xdr.x'" else sed 's/^X//' << \SHAR_EOF > 'rpc/rpcgen/test/demo_xdr.x' X/* X * This file defines the protocol to support a demo rpc X * service and is designed to be processed by the `rpcgen' X * protocol compiler. The Sun ctime(3) routines are used X * as examples. See the rpcgen manual page for more detailed X * information. X */ X X#ifdef REL3_0 X#ifndef NULL X# define NULL 0 X#endif X#endif X X X/* X * argument / result data types X */ X X#define DATELEN 26 Xtypedef string date[DATELEN]; X X#define STRLEN 80 Xtypedef string str[STRLEN]; X Xtypedef long clock; X Xstruct tm { X int tm_sec; X int tm_min; X int tm_hour; X int tm_mday; X int tm_mon; X int tm_year; X int tm_wday; X int tm_yday; X int tm_isdst; X}; X Xstruct timeval { X u_long tv_sec; X long tv_usec; X}; X Xstruct timez { X int tz_minuteswest; X int tz_dsttime; X}; X Xstruct tzargs { X int zone; X int dst; X}; X X X/* X * There is one generic data type for the result. This is implemented X * as a union switch. The specific union element returned is specified X * by ret_status. X */ X Xenum ret_status { X RET_DATE, RET_TM, RET_STR, RET_DAYS, RET_CLOCK, RET_TZ, RET_YEAR, X RET_ERROR X}; X Xstruct ret_err { X int err_number; X str err_text; X}; X Xunion demo_res switch (ret_status which) { X case RET_DATE: X date date; X case RET_TM: X tm *tmp; X case RET_STR: X str str; X case RET_DAYS: X int days; X case RET_ERROR: X ret_err err; X}; X X X/* X * This section declares the individual procedures which are supported X * by this protocol. The program number and version numbers are X * arbitrary in this case. Procedures correspond to the ctime(3) X * time routines. X */ X Xprogram DEMOPROG { X version DEMOVERS { X demo_res /* date */ CTIME(clock) = 1; X demo_res /* tm */ LOCALTIME(clock) = 2; X demo_res /* tm */ GMTIME(clock) = 3; X demo_res /* date */ ASCTIME(tm) = 4; X demo_res /* str */ TIMEZONE(tzargs) = 5; X demo_res /* days */ DYSIZE(int) = 6; X } = 5; X} = 123456; SHAR_EOF if test 1834 -ne "`wc -c < 'rpc/rpcgen/test/demo_xdr.x'`" then echo shar: "error transmitting 'rpc/rpcgen/test/demo_xdr.x'" '(should have been 1834 characters)' fi chmod 664 'rpc/rpcgen/test/demo_xdr.x' fi exit 0 # End of shell archive