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