RPCGEN(1) COMMAND REFERENCE RPCGEN(1) NAME rpcgen - an RPC (Remote Procedure Call) protocol compiler SYNOPSIS rpcgen -h [-o outfile] [inputfile] rpcgen -c [-o outfile] [infile] rpcgen infile rpcgen [-s transport]* [-o outfile] [infile] DESCRIPTION As a tool that generates C code to implement an RPC protocol, the input to rpcgen is a language with striking similarity to C, known as RPCL (Remote Procedure Call Language). The protocol compiler rpcgen operates in four modes: the first mode converts RPCL definitions into C definitions for use as a header file; the second mode compiles the XDR (External Data Representation) routines required to serialize the protocol described by RPCL; the third mode compiles both, leaving the header file in a file named infile.h retaining the XDR routines in infile.c; the fourth mode compiles an RPC server skeleton, so that you need only write local procedures that know nothing about RPC in order to implement an RPC server. The input may contain C-style comments and preprocessor directives. Comments are ignored, while the directives are simply stuffed uninterpreted in the output header file. You can customize some of your XDR routines by leaving those data types undefined. For every data type that is undefined, rpcgen assumes there exists a routine with the name xdr_ prepended to the name of the undefined type. OPTIONS -c Compile XDR routines. -h Compile C data-definitions (a header file). -ooutfile Specify the name of the output file; if none is specified, standard output is used (-c, -h, and -s modes only). -stransport Compile a server, using the given transport; supported transports are udp and tcp; this option may be invoked more than once so as to compile a server that serves multiple transports. Usage: RPCL Syntax Summary This summary of RPCL syntax, which is used for rpcgen input, is intended more for aiding comprehension than as an exact Printed 4/6/89 1
RPCGEN(1) COMMAND REFERENCE RPCGEN(1) statement of the language. Primitive Data Types [ unsigned ] char [ unsigned ] short [ unsigned ] int [ unsigned ] long unsigned float double void bool Except for the added boolean data-type bool, RPCL is identical to C; rpcgen converts bool declarations to int declarations in the output header file (literally it is converted to a boolt, which has been #define'd to be an int). Also, void declarations may appear only inside union and program definitions. For those averse to typing the prefix unsigned, the abbreviations uchar, ushort, uint and ulong are available. Declarations RPCL allows only three kinds of declarations: simple-declaration type-name object-ident pointer-declaration type-name *object-ident vector-declaration type-name object-ident[size] (size can be either an integer or a symbolic constant). RPCL declarations contain both limitations and extensions with respect to C. The limitations are that you cannot declare multidimensional arrays or pointers-to-pointers in- line (you can still declare them though, using typedef). There are two extensions. Opaque data is declared as a vector: opaque object-ident [ size ] In the protocol, this results in an object of size bytes. Note that this is not the same as a declaration of size characters, since XDR characters are 32 bits. Opaque Printed 4/6/89 2
RPCGEN(1) COMMAND REFERENCE RPCGEN(1) declarations are compiled in the output header file into character array declarations of size bytes. Strings are special and are declared as a vector declaration: string object-ident [ max-size ] If max-size is unspecified there is essentially no limit to the maximum length of the string. String declarations get compiled into the following: char *object-ident The object-ident part of declaration is the name of the new type, whereas the type-name part is the name of the type from which it is derived. Type Definitions The only way to generate an XDR routine is to define a type. For every type zetype you define, there is a corresponding XDR routine named xdr_zetype. There are six ways to define a type: type-definition: typedef enumeration-def structure-def variable-length-array-def discriminated-union-def program-def The first three are very similar to their C namesakes. C does not have a formal type mechanism to define variable- length arrays, and XDR unions are quite different from their C counterparts. Program definitions are not really type definitions, but they are useful nonetheless. You may not nest XDR definitions, for example, the following causes rpcgen to choke: struct dontdoit { struct ididit { int oops; } sorry; enum ididitagain { OOPS, WHOOPS } iapologize; }; Typedefs Printed 4/6/89 3
RPCGEN(1) COMMAND REFERENCE RPCGEN(1) The syntax is: typedef: typedef declaration ; Enumeration Types The syntax is: enumeration-def: enum enum-ident { enum-list }; enum-list: enum-symbol-ident [ = assignment ] enum-symbol-ident [ = assignment ] , enum-list (assignment may be either an integer or a symbolic constant) If there is no explicit assignment, then the implicit assignment is the value of the previous enumeration plus 1. If not explicitly assigned, the first enumeration receives the value 0. Structures The syntax is: structure-def: struct struct-ident { declaration-list }; declaration-list: declaration ; declaration ; declaration-list Variable-Length Arrays The syntax is: variable-length-array-def: array array-ident { unsigned length-identifier ; vector-declaration ; }; A variable length array definition looks much like a structure definition. Here's an example: Printed 4/6/89 4
RPCGEN(1) COMMAND REFERENCE RPCGEN(1) array mp_int { unsigned len; short val[MAX_MP_LENGTH]; }; This is compiled into: struct mp_int { unsigned len; short *val; }; typedef struct mp_int mp_int; Discriminated Unions The syntax is: discriminated-union-def: union union-ident switch ( discriminant-declaration ) { case-list [ default : declaration ; ] }; case-list: case case-ident : declaration ; case case-ident : declaration ; case-list discriminant-declaration: declaration The union definition looks like a cross between a C-union and a C-switch. An example: union net_object switch (net_kind kind) { case MACHINE: struct sockaddr_in sin; case USER: int uid; default: string whatisit; }; Compiles into: struct net_object { net_kind kind; union { struct sockaddr_in sin; int uid; char *whatisit; } net_object; }; Printed 4/6/89 5
RPCGEN(1) COMMAND REFERENCE RPCGEN(1) typedef struct net_object net_object; Note that the name of the union component of the output struct is the same as the name of the type itself. Program Definitions The syntax is: program-def: program program-ident { version-list } = program-number ; version-list: version version version-list version: version version-ident { procedure-list } = version-number ; procedure-list: procedure-declaration procedure-declaration procedure-list procedure-declaration: type-name procedure-ident ( type-name ) = procedure- number ; EXAMPLES Suppose you wanted to create a server that could get or set the date; its declaration might look like this: program DATE_PROG { version DATE_VERS { date DATE_GET(timezone) = 1; void DATE_SET(date) = 2; /* Greenwich mean time */ } = 1; } = 100; In the header file, this compiles into the following: #define DATE_PROG 100 #define DATE_VERS 1 #define DATE_GET 1 #define DATE_SET 2 These defines are intended for use by the client program to reference the remote procedures. If you are using rpcgen to compile your server, there are some important things for you to know: the server interfaces to your local procedures by expecting a C Printed 4/6/89 6
RPCGEN(1) COMMAND REFERENCE RPCGEN(1) function with the same name as that in the program definition, but in all lowercase letters and followed by the version number. Here is the local procedure that implements DATE_GET: date * /* always returns a pointer to the results */ date_get_1(tz) timezone *tz; /* always takes a a pointer to the arguments */ { static date d; /* must be static! */ /* * figure out the date * and store it in d */ return(&d); } The name of the routine is the same as the #define'd name, but should be in all lowercase letters and should be followed by the version number. XDR recursively frees the argument after getting the results from your local procedure, so you should copy from the argument any data you need between calls, however, XDR neither allocates nor frees your results; you must take care of their storage yourself. Make Inference Rules For Compiling XDR Headers It is possible to set up suffix transformation rules in make(1) for compiling XDR routines and header files. The convention is that RPCL protocol files have the extension .x. Follow these make rules: .SUFFIXES: .x .x.c: rpcgen -c $< -o $@ .x.h: rpcgen -h $< -o $@ CAVEATS Name clashes can occur when using program definitions, since the apparent scoping does not really apply. Give unique names for programs, versions, procedures, and types. SEE ALSO See the sections RPC Programming Guide, Introduction to RPC and XDR, and External Data Representation Protocol in the manual The Network File System, Tektronix part number 070- 6628-00. Printed 4/6/89 7
%%index%% na:288,109; sy:397,780; de:1177,1558; op:2735,1234;4329,3823;8512,2339;11211,2646;14217,2129;16706,1682; ex:18388,1019;19767,1929; ca:21696,265; se:21961,478; %%index%%000000000192