home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Libraries / GUSI-RPC 4.0 / xdr.c < prev   
Encoding:
C/C++ Source or Header  |  1993-02-17  |  11.1 KB  |  584 lines  |  [TEXT/MPS ]

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