home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / lib / librpc / rpc / xdr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-10-30  |  10.8 KB  |  577 lines

  1. /* @(#)xdr.c    2.1 88/07/29 4.0 RPCSRC */
  2. /*
  3.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  4.  * unrestricted use provided that this legend is included on all tape
  5.  * media and as a part of the software program in whole or part.  Users
  6.  * may copy or modify Sun RPC without charge, but are not authorized
  7.  * to license or distribute it to anyone else except as part of a product or
  8.  * program developed by the user.
  9.  * 
  10.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  11.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  12.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  13.  * 
  14.  * Sun RPC is provided with no support and without any obligation on the
  15.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  16.  * modification or enhancement.
  17.  * 
  18.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  19.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  20.  * OR ANY PART THEREOF.
  21.  * 
  22.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  23.  * or profits or other special, indirect and consequential damages, even if
  24.  * Sun has been advised of the possibility of such damages.
  25.  * 
  26.  * Sun Microsystems, Inc.
  27.  * 2550 Garcia Avenue
  28.  * Mountain View, California  94043
  29.  */
  30. #if !defined(lint) && defined(SCCSIDS)
  31. static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
  32. #endif
  33.  
  34. /*
  35.  * xdr.c, Generic XDR routines implementation.
  36.  *
  37.  * Copyright (C) 1986, Sun Microsystems, Inc.
  38.  *
  39.  * These are the "generic" xdr routines used to serialize and de-serialize
  40.  * most common data items.  See xdr.h for more info on the interface to
  41.  * xdr.
  42.  */
  43.  
  44. #include <stdio.h>
  45.  
  46. #include <rpc/types.h>
  47. #include <rpc/xdr.h>
  48.  
  49. /*
  50.  * constants specific to the xdr "protocol"
  51.  */
  52. #define XDR_FALSE    ((long) 0)
  53. #define XDR_TRUE    ((long) 1)
  54. #define LASTUNSIGNED    ((u_int) 0-1)
  55.  
  56. /*
  57.  * for unit alignment
  58.  */
  59. static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
  60.  
  61. /*
  62.  * Free a data structure using XDR
  63.  * Not a filter, but a convenient utility nonetheless
  64.  */
  65. void
  66. xdr_free(proc, objp)
  67.     xdrproc_t proc;
  68.     char *objp;
  69. {
  70.     XDR x;
  71.     
  72.     x.x_op = XDR_FREE;
  73.     (*proc)(&x, objp);
  74. }
  75.  
  76. /*
  77.  * XDR nothing
  78.  */
  79. bool_t
  80. xdr_void(/* xdrs, addr */)
  81.     /* XDR *xdrs; */
  82.     /* caddr_t addr; */
  83. {
  84.  
  85.     return (TRUE);
  86. }
  87.  
  88. /*
  89.  * XDR integers
  90.  */
  91. bool_t
  92. xdr_int(xdrs, ip)
  93.     XDR *xdrs;
  94.     int *ip;
  95. {
  96.  
  97. #ifdef lint
  98.     (void) (xdr_short(xdrs, (short *)ip));
  99.     return (xdr_long(xdrs, (long *)ip));
  100. #else
  101.     if (sizeof (int) == sizeof (long)) {
  102.         return (xdr_long(xdrs, (long *)ip));
  103.     } else {
  104.         return (xdr_short(xdrs, (short *)ip));
  105.     }
  106. #endif
  107. }
  108.  
  109. /*
  110.  * XDR unsigned integers
  111.  */
  112. bool_t
  113. xdr_u_int(xdrs, up)
  114.     XDR *xdrs;
  115.     u_int *up;
  116. {
  117.  
  118. #ifdef lint
  119.     (void) (xdr_short(xdrs, (short *)up));
  120.     return (xdr_u_long(xdrs, (u_long *)up));
  121. #else
  122.     if (sizeof (u_int) == sizeof (u_long)) {
  123.         return (xdr_u_long(xdrs, (u_long *)up));
  124.     } else {
  125.         return (xdr_short(xdrs, (short *)up));
  126.     }
  127. #endif
  128. }
  129.  
  130. /*
  131.  * XDR long integers
  132.  * same as xdr_u_long - open coded to save a proc call!
  133.  */
  134. bool_t
  135. xdr_long(xdrs, lp)
  136.     register XDR *xdrs;
  137.     long *lp;
  138. {
  139.  
  140.     if (xdrs->x_op == XDR_ENCODE)
  141.         return (XDR_PUTLONG(xdrs, lp));
  142.  
  143.     if (xdrs->x_op == XDR_DECODE)
  144.         return (XDR_GETLONG(xdrs, lp));
  145.  
  146.     if (xdrs->x_op == XDR_FREE)
  147.         return (TRUE);
  148.  
  149.     return (FALSE);
  150. }
  151.  
  152. /*
  153.  * XDR unsigned long integers
  154.  * same as xdr_long - open coded to save a proc call!
  155.  */
  156. bool_t
  157. xdr_u_long(xdrs, ulp)
  158.     register XDR *xdrs;
  159.     u_long *ulp;
  160. {
  161.  
  162.     if (xdrs->x_op == XDR_DECODE)
  163.         return (XDR_GETLONG(xdrs, (long *)ulp));
  164.     if (xdrs->x_op == XDR_ENCODE)
  165.         return (XDR_PUTLONG(xdrs, (long *)ulp));
  166.     if (xdrs->x_op == XDR_FREE)
  167.         return (TRUE);
  168.     return (FALSE);
  169. }
  170.  
  171. /*
  172.  * XDR short integers
  173.  */
  174. bool_t
  175. xdr_short(xdrs, sp)
  176.     register XDR *xdrs;
  177.     short *sp;
  178. {
  179.     long l;
  180.  
  181.     switch (xdrs->x_op) {
  182.  
  183.     case XDR_ENCODE:
  184.         l = (long) *sp;
  185.         return (XDR_PUTLONG(xdrs, &l));
  186.  
  187.     case XDR_DECODE:
  188.         if (!XDR_GETLONG(xdrs, &l)) {
  189.             return (FALSE);
  190.         }
  191.         *sp = (short) l;
  192.         return (TRUE);
  193.  
  194.     case XDR_FREE:
  195.         return (TRUE);
  196.     }
  197.     return (FALSE);
  198. }
  199.  
  200. /*
  201.  * XDR unsigned short integers
  202.  */
  203. bool_t
  204. xdr_u_short(xdrs, usp)
  205.     register XDR *xdrs;
  206.     u_short *usp;
  207. {
  208.     u_long l;
  209.  
  210.     switch (xdrs->x_op) {
  211.  
  212.     case XDR_ENCODE:
  213.         l = (u_long) *usp;
  214.         return (XDR_PUTLONG(xdrs, &l));
  215.  
  216.     case XDR_DECODE:
  217.         if (!XDR_GETLONG(xdrs, &l)) {
  218.             return (FALSE);
  219.         }
  220.         *usp = (u_short) l;
  221.         return (TRUE);
  222.  
  223.     case XDR_FREE:
  224.         return (TRUE);
  225.     }
  226.     return (FALSE);
  227. }
  228.  
  229.  
  230. /*
  231.  * XDR a char
  232.  */
  233. bool_t
  234. xdr_char(xdrs, cp)
  235.     XDR *xdrs;
  236.     char *cp;
  237. {
  238.     int i;
  239.  
  240.     i = (*cp);
  241.     if (!xdr_int(xdrs, &i)) {
  242.         return (FALSE);
  243.     }
  244.     *cp = i;
  245.     return (TRUE);
  246. }
  247.  
  248. /*
  249.  * XDR an unsigned char
  250.  */
  251. bool_t
  252. xdr_u_char(xdrs, cp)
  253.     XDR *xdrs;
  254.     char *cp;
  255. {
  256.     u_int u;
  257.  
  258.     u = (*cp);
  259.     if (!xdr_u_int(xdrs, &u)) {
  260.         return (FALSE);
  261.     }
  262.     *cp = u;
  263.     return (TRUE);
  264. }
  265.  
  266. /*
  267.  * XDR booleans
  268.  */
  269. bool_t
  270. xdr_bool(xdrs, bp)
  271.     register XDR *xdrs;
  272.     bool_t *bp;
  273. {
  274.     long lb;
  275.  
  276.     switch (xdrs->x_op) {
  277.  
  278.     case XDR_ENCODE:
  279.         lb = *bp ? XDR_TRUE : XDR_FALSE;
  280.         return (XDR_PUTLONG(xdrs, &lb));
  281.  
  282.     case XDR_DECODE:
  283.         if (!XDR_GETLONG(xdrs, &lb)) {
  284.             return (FALSE);
  285.         }
  286.         *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
  287.         return (TRUE);
  288.  
  289.     case XDR_FREE:
  290.         return (TRUE);
  291.     }
  292.     return (FALSE);
  293. }
  294.  
  295. /*
  296.  * XDR enumerations
  297.  */
  298. bool_t
  299. xdr_enum(xdrs, ep)
  300.     XDR *xdrs;
  301.     enum_t *ep;
  302. {
  303. #ifndef lint
  304.     enum sizecheck { SIZEVAL };    /* used to find the size of an enum */
  305.  
  306.     /*
  307.      * enums are treated as ints
  308.      */
  309.     if (sizeof (enum sizecheck) == sizeof (long)) {
  310.         return (xdr_long(xdrs, (long *)ep));
  311.     } else if (sizeof (enum sizecheck) == sizeof (short)) {
  312.         return (xdr_short(xdrs, (short *)ep));
  313.     } else {
  314.         return (FALSE);
  315.     }
  316. #else
  317.     (void) (xdr_short(xdrs, (short *)ep));
  318.     return (xdr_long(xdrs, (long *)ep));
  319. #endif
  320. }
  321.  
  322. /*
  323.  * XDR opaque data
  324.  * Allows the specification of a fixed size sequence of opaque bytes.
  325.  * cp points to the opaque object and cnt gives the byte length.
  326.  */
  327. bool_t
  328. xdr_opaque(xdrs, cp, cnt)
  329.     register XDR *xdrs;
  330.     caddr_t cp;
  331.     register u_int cnt;
  332. {
  333.     register u_int rndup;
  334.     static crud[BYTES_PER_XDR_UNIT];
  335.  
  336.     /*
  337.      * if no data we are done
  338.      */
  339.     if (cnt == 0)
  340.         return (TRUE);
  341.  
  342.     /*
  343.      * round byte count to full xdr units
  344.      */
  345.     rndup = cnt % BYTES_PER_XDR_UNIT;
  346.     if (rndup > 0)
  347.         rndup = BYTES_PER_XDR_UNIT - rndup;
  348.  
  349.     if (xdrs->x_op == XDR_DECODE) {
  350.         if (!XDR_GETBYTES(xdrs, cp, cnt)) {
  351.             return (FALSE);
  352.         }
  353.         if (rndup == 0)
  354.             return (TRUE);
  355.         return (XDR_GETBYTES(xdrs, crud, rndup));
  356.     }
  357.  
  358.     if (xdrs->x_op == XDR_ENCODE) {
  359.         if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
  360.             return (FALSE);
  361.         }
  362.         if (rndup == 0)
  363.             return (TRUE);
  364.         return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
  365.     }
  366.  
  367.     if (xdrs->x_op == XDR_FREE) {
  368.         return (TRUE);
  369.     }
  370.  
  371.     return (FALSE);
  372. }
  373.  
  374. /*
  375.  * XDR counted bytes
  376.  * *cpp is a pointer to the bytes, *sizep is the count.
  377.  * If *cpp is NULL maxsize bytes are allocated
  378.  */
  379. bool_t
  380. xdr_bytes(xdrs, cpp, sizep, maxsize)
  381.     register XDR *xdrs;
  382.     char **cpp;
  383.     register u_int *sizep;
  384.     u_int maxsize;
  385. {
  386.     register char *sp = *cpp;  /* sp is the actual string pointer */
  387.     register u_int nodesize;
  388.  
  389.     /*
  390.      * first deal with the length since xdr bytes are counted
  391.      */
  392.     if (! xdr_u_int(xdrs, sizep)) {
  393.         return (FALSE);
  394.     }
  395.     nodesize = *sizep;
  396.     if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
  397.         return (FALSE);
  398.     }
  399.  
  400.     /*
  401.      * now deal with the actual bytes
  402.      */
  403.     switch (xdrs->x_op) {
  404.  
  405.     case XDR_DECODE:
  406.         if (nodesize == 0) {
  407.             return (TRUE);
  408.         }
  409.         if (sp == NULL) {
  410.             *cpp = sp = (char *)mem_alloc(nodesize);
  411.         }
  412.         if (sp == NULL) {
  413.             (void) fprintf(stderr, "xdr_bytes: out of memory\n");
  414.             return (FALSE);
  415.         }
  416.         /* fall into ... */
  417.  
  418.     case XDR_ENCODE:
  419.         return (xdr_opaque(xdrs, sp, nodesize));
  420.  
  421.     case XDR_FREE:
  422.         if (sp != NULL) {
  423.             mem_free(sp, nodesize);
  424.             *cpp = NULL;
  425.         }
  426.         return (TRUE);
  427.     }
  428.     return (FALSE);
  429. }
  430.  
  431. /*
  432.  * Implemented here due to commonality of the object.
  433.  */
  434. bool_t
  435. xdr_netobj(xdrs, np)
  436.     XDR *xdrs;
  437.     struct netobj *np;
  438. {
  439.  
  440.     return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
  441. }
  442.  
  443. /*
  444.  * XDR a descriminated union
  445.  * Support routine for discriminated unions.
  446.  * You create an array of xdrdiscrim structures, terminated with
  447.  * an entry with a null procedure pointer.  The routine gets
  448.  * the discriminant value and then searches the array of xdrdiscrims
  449.  * looking for that value.  It calls the procedure given in the xdrdiscrim
  450.  * to handle the discriminant.  If there is no specific routine a default
  451.  * routine may be called.
  452.  * If there is no specific or default routine an error is returned.
  453.  */
  454. bool_t
  455. xdr_union(xdrs, dscmp, unp, choices, dfault)
  456.     register XDR *xdrs;
  457.     enum_t *dscmp;        /* enum to decide which arm to work on */
  458.     char *unp;        /* the union itself */
  459.     struct xdr_discrim *choices;    /* [value, xdr proc] for each arm */
  460.     xdrproc_t dfault;    /* default xdr routine */
  461. {
  462.     register enum_t dscm;
  463.  
  464.     /*
  465.      * we deal with the discriminator;  it's an enum
  466.      */
  467.     if (! xdr_enum(xdrs, dscmp)) {
  468.         return (FALSE);
  469.     }
  470.     dscm = *dscmp;
  471.  
  472.     /*
  473.      * search choices for a value that matches the discriminator.
  474.      * if we find one, execute the xdr routine for that value.
  475.      */
  476.     for (; choices->proc != NULL_xdrproc_t; choices++) {
  477.         if (choices->value == dscm)
  478.             return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
  479.     }
  480.  
  481.     /*
  482.      * no match - execute the default xdr routine if there is one
  483.      */
  484.     return ((dfault == NULL_xdrproc_t) ? FALSE :
  485.         (*dfault)(xdrs, unp, LASTUNSIGNED));
  486. }
  487.  
  488.  
  489. /*
  490.  * Non-portable xdr primitives.
  491.  * Care should be taken when moving these routines to new architectures.
  492.  */
  493.  
  494.  
  495. /*
  496.  * XDR null terminated ASCII strings
  497.  * xdr_string deals with "C strings" - arrays of bytes that are
  498.  * terminated by a NULL character.  The parameter cpp references a
  499.  * pointer to storage; If the pointer is null, then the necessary
  500.  * storage is allocated.  The last parameter is the max allowed length
  501.  * of the string as specified by a protocol.
  502.  */
  503. bool_t
  504. xdr_string(xdrs, cpp, maxsize)
  505.     register XDR *xdrs;
  506.     char **cpp;
  507.     u_int maxsize;
  508. {
  509.     register char *sp = *cpp;  /* sp is the actual string pointer */
  510.     u_int size;
  511.     u_int nodesize;
  512.  
  513.     /*
  514.      * first deal with the length since xdr strings are counted-strings
  515.      */
  516.     switch (xdrs->x_op) {
  517.     case XDR_FREE:
  518.         if (sp == NULL) {
  519.             return(TRUE);    /* already free */
  520.         }
  521.         /* fall through... */
  522.     case XDR_ENCODE:
  523.         size = strlen(sp);
  524.         break;
  525.     }
  526.     if (! xdr_u_int(xdrs, &size)) {
  527.         return (FALSE);
  528.     }
  529.     if (size > maxsize) {
  530.         return (FALSE);
  531.     }
  532.     nodesize = size + 1;
  533.  
  534.     /*
  535.      * now deal with the actual bytes
  536.      */
  537.     switch (xdrs->x_op) {
  538.  
  539.     case XDR_DECODE:
  540.         if (nodesize == 0) {
  541.             return (TRUE);
  542.         }
  543.         if (sp == NULL)
  544.             *cpp = sp = (char *)mem_alloc(nodesize);
  545.         if (sp == NULL) {
  546.             (void) fprintf(stderr, "xdr_string: out of memory\n");
  547.             return (FALSE);
  548.         }
  549.         sp[size] = 0;
  550.         /* fall into ... */
  551.  
  552.     case XDR_ENCODE:
  553.         return (xdr_opaque(xdrs, sp, size));
  554.  
  555.     case XDR_FREE:
  556.         mem_free(sp, nodesize);
  557.         *cpp = NULL;
  558.         return (TRUE);
  559.     }
  560.     return (FALSE);
  561. }
  562.  
  563. /* 
  564.  * Wrapper for xdr_string that can be called directly from 
  565.  * routines like clnt_call
  566.  */
  567. bool_t
  568. xdr_wrapstring(xdrs, cpp)
  569.     XDR *xdrs;
  570.     char **cpp;
  571. {
  572.     if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
  573.         return (TRUE);
  574.     }
  575.     return (FALSE);
  576. }
  577.