home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / lan / soss.arj / RPC / XDR.C < prev    next >
C/C++ Source or Header  |  1991-02-22  |  11KB  |  502 lines

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