Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ rpcgen(NC) — OpenDesktop Software Development System 1.0.0d

Media Vault

Software Library

Restoration Projects

Artifacts Sought


     RPCGEN(NC)                                 UNIX System V



     Name
          rpcgen - An RPC protocol compiler


     Syntax
          rpcgen -h [-o outfile] [inputfile]
          rpcgen -c [-o outfile] [infile]
          rpcgen infile
          rpcgen [-s transport]* [-o outfile] [infile]


     Description
          rpcgen is 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).  rpcgen operates in four modes:

           ⊕   The first mode is used to convert RPCL definitions into
               C definitions for use as a header file.

           ⊕   The second mode compiles the XDR routines  required  to
               serialize the protocol described by RPCL.

           ⊕   The third mode compiles both, leaving the  header  file
               in a file named infile with an .h extension and the XDR
               routines in infile with an xdr.c extension.

           ⊕   The fourth mode  is  used  to  compile  an  RPC  server
               skeleton,  so  that  all  you have to do is 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 will assume that there  exists  a  routine
          with  the  name  xdr prepended to the name of the undefined
          type.

          It is highly recommended that you read the chapters  on  RPC
          and  XDR in the SCO NFS Programmer's Guide before using this
          utility.


     Options
          -c   Compile XDR routines.

          -h   Compile C data-definitions (a header file)

          -o outfile
               Specify the name  of  the  output  file.   If  none  is
               specified, standard output is used (-c, -h and -s modes
               only).

          -s transport
               Compile a  server,  using  the  given  transport.   The
               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
          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  of
          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

               For example,
               long a;

          ⊕   pointer-declaration

               type-name *object-ident

               For example,
               char *b;

          ⊕   vector-declaration

               type-name object-ident[size]

               (size can be either an integer or a symbolic constant)

               For example,
               opaque c[10];

          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 as follows:

                    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
          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, then  there  is  essentially  no
          limit   to   the   maximum  length  of  the  string.  String
          declarations get compiled into the following:

               char *object-ident

        Type Definitions
          You need to use rpcgen to generate  an  XDR  routine  and/or
          header file that defines a type in an input file.  For every
          zetype  you  define,  rpcgen  creates  a  corresponding  XDR
          routine  named xdr_zetype that is mandatory for creating RPC
          programs.

          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 will cause rpcgen to choke:

          struct dontdoit {
               struct ididit {
                    int oops;
               } sorry;
               enum ididitagain { OOPS, WHOOPS } iapologize;
          };



        Typedefs
          An XDR typedef looks as follows:

          typedef:
               typedef type-name object-ident ;

          The object-ident is the name of the new  type,  whereas  the
          type-name  part  is  the  name  of the type from which it is
          derived.  For example,
          typedef longa;

        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
          structure-def:
               struct struct-ident {
                    declaration-list
               };

          declaration-list:
               declaration ;
               declaration ; declaration-list

        Variable-Length Arrays
          variable-length-array-def:
               array array-ident {
                    unsigned length-identifer ;
                    vector-declaration ;
               };

          A  variable  length  array  definition  looks  much  like  a
          structure definition. Here's an example:

          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
          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.  For 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;
          };

          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
          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 ;

          Program definitions  look  like  nothing  you've  ever  seen
          before,  so  we turn to an example to explain them.  Suppose
          you wanted to create 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 define's are intended for use by the client program to
          reference the remote procedures.

          If you are using rpcgen to compile your server,  then  there
          are  some  important  things  for  you  to  know. The server
          interfaces  to  your  local  procedures  by  expecting  a  C
          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 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  in  all  lowercase  letters and followed by the version
          number.   XDR  will  recursively  free  the  argument  after
          getting the results from your local procedure, so you should
          copy from the argument any data that you will  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(C)  for  compiling  XDR routines and header files.  The
          convention is that RPCL protocol files  have  the  extension
          .x.  The make rules to do this are:

               .SUFFIXES: .x
               .x.c:
                    rpcgen -c $< -o $@

               .x.h:
                    rpcgen -h $< -o $@


     Example
          Consider the following  program,  example  ,  which  defines
          three data types:

          const NFS_PORT = 2059;
          enum nfsstat {
               NFS_OK=0
          };

          struct gnumbers {
               long g_assets;
               long g_liabilities;
          };

          When you run rpcgen with no arguments, it generates a header
          file, example.h and an XDR file, examplexdr.c.


          example.h

          #define NFS_PORT 2059

          enum nfsstat {
               NFS_OK = 0,
          };

          typedef enum nfsstat nfsstat;
          bool_t xdr_nfsstat();


          struct gnumbers {
               long g_assets;
               long g_liabilities;
          };

          typedef struct gnumbers gnumbers;
          bool_t xdr_gnumbers();


          examplexdr.c

          #include <rpc/rpc.h>
          #include "infile.h"


          bool_t
          xdr_nfsstat(xdrs, objp)
               XDR *xdrs;
               nfsstat *objp;
          {
               if (!xdr_enum(xdrs, (enum_t *)objp)) {
                    return (FALSE);
               }
               return (TRUE);
          }


          bool_t
          xdr_gnumbers(xdrs, objp)
               XDR *xdrs;
               gnumbers *objp;
          {
               if (!xdr_long(xdrs, &objp->g_assets)) {
                    return (FALSE);
               }
               if (!xdr_long(xdrs, &objp->g_liabilities)) {
                    return (FALSE);
               }
               return (TRUE);
          }


     SEE ALSO
          SCO NFS Programmer's Guide


     Notes
          Name clashes can occur when using program definitions, since
          the  apparent  scoping  does not really apply. Most of these
          can  be  avoided  by  giving  unique  names  for   programs,
          versions, procedures and types.


     (printed 8/17/89)                                  RPCGEN(NC)

Typewritten Software • bear@typewritten.org • Edmonds, WA 98026