home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume1 / rpc / part10 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  54.6 KB

  1. Date: Wed, 3 Apr 85 00:21:21 pst
  2. From: decvax!sun!pumpkinseed!blyon (Bob Lyon)
  3. Subject: Sun RPC part 10 of 10
  4.  
  5. echo x - xdr.c
  6. sed 's/^X//' >xdr.c <<'!Funky!Stuff!'
  7. /*
  8.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  9.  * unrestricted use provided that this legend is included on all tape
  10.  * media and as a part of the software program in whole or part.  Users
  11.  * may copy or modify Sun RPC without charge, but are not authorized
  12.  * to license or distribute it to anyone else except as part of a product or
  13.  * program developed by the user.
  14.  * 
  15.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  16.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  17.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  18.  * 
  19.  * Sun RPC is provided with no support and without any obligation on the
  20.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  21.  * modification or enhancement.
  22.  * 
  23.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  24.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  25.  * OR ANY PART THEREOF.
  26.  * 
  27.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  28.  * or profits or other special, indirect and consequential damages, even if
  29.  * Sun has been advised of the possibility of such damages.
  30.  * 
  31.  * Sun Microsystems, Inc.
  32.  * 2550 Garcia Avenue
  33.  * Mountain View, California  94043
  34.  */
  35. #ifndef lint
  36. static char sccsid[] = "@(#)xdr.c 1.3 85/02/26 Copyr 1984 Sun Micro";
  37. #endif
  38.  
  39. /*
  40.  * xdr.c, Generic XDR routines impelmentation.
  41.  *
  42.  * Copyright (C) 1984, Sun Microsystems, Inc.
  43.  *
  44.  * These are the "generic" xdr routines used to serialize and de-serialize
  45.  * most common data items.  See xdr.h for more info on the interface to
  46.  * xdr.
  47.  */
  48.  
  49. #include "types.h"
  50. #include "xdr.h"
  51. #include <stdio.h>
  52.  
  53. char *mem_alloc();
  54.  
  55. /*
  56.  * constants specific to the xdr "protocol"
  57.  */
  58. #define XDR_FALSE    ((long) 0)
  59. #define XDR_TRUE    ((long) 1)
  60. #define LASTUNSIGNED    ((u_int) 0-1)
  61.  
  62. /*
  63.  * for unit alignment
  64.  */
  65. static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
  66.  
  67.  
  68. /*
  69.  * XDR nothing
  70.  */
  71. bool_t
  72. xdr_void(/* xdrs, addr */)
  73.     /* XDR *xdrs; */
  74.     /* caddr_t addr; */
  75. {
  76.  
  77.     return (TRUE);
  78. }
  79.  
  80. /*
  81.  * XDR integers
  82.  */
  83. bool_t
  84. xdr_int(xdrs, ip)
  85.     XDR *xdrs;
  86.     int *ip;
  87. {
  88.  
  89.     if (sizeof(int) == sizeof(long)) {
  90.         return (xdr_long(xdrs, (long *)ip));
  91.     } else {
  92.         return (xdr_short(xdrs, (short *)ip));
  93.     }
  94. }
  95.  
  96. /*
  97.  * XDR unsigned integers
  98.  */
  99. bool_t
  100. xdr_u_int(xdrs, up)
  101.     XDR *xdrs;
  102.     u_int *up;
  103. {
  104.  
  105.     if (sizeof(u_int) == sizeof(u_long)) {
  106.         return (xdr_u_long(xdrs, (u_long *)up));
  107.     } else {
  108.         return (xdr_short(xdrs, (short *)up));
  109.     }
  110. }
  111.  
  112. /*
  113.  * XDR long integers
  114.  * same as xdr_u_long - open coded to save a proc call!
  115.  */
  116. bool_t
  117. xdr_long(xdrs, lp)
  118.     register XDR *xdrs;
  119.     long *lp;
  120. {
  121.  
  122.     if (xdrs->x_op == XDR_ENCODE)
  123.         return (XDR_PUTLONG(xdrs, lp));
  124.  
  125.     if (xdrs->x_op == XDR_DECODE)
  126.         return (XDR_GETLONG(xdrs, lp));
  127.  
  128.     if (xdrs->x_op == XDR_FREE)
  129.         return (TRUE);
  130.  
  131.     return (FALSE);
  132. }
  133.  
  134. /*
  135.  * XDR unsigned long integers
  136.  * same as xdr_long - open coded to save a proc call!
  137.  */
  138. bool_t
  139. xdr_u_long(xdrs, ulp)
  140.     register XDR *xdrs;
  141.     u_long *ulp;
  142. {
  143.  
  144.     if (xdrs->x_op == XDR_DECODE)
  145.         return (XDR_GETLONG(xdrs, (long *)ulp));
  146.     if (xdrs->x_op == XDR_ENCODE)
  147.         return (XDR_PUTLONG(xdrs, (long *)ulp));
  148.     if (xdrs->x_op == XDR_FREE)
  149.         return (TRUE);
  150.     return (FALSE);
  151. }
  152.  
  153. /*
  154.  * XDR short integers
  155.  */
  156. bool_t
  157. xdr_short(xdrs, sp)
  158.     register XDR *xdrs;
  159.     short *sp;
  160. {
  161.     long l;
  162.  
  163.     switch (xdrs->x_op) {
  164.  
  165.     case XDR_ENCODE:
  166.         l = (long) *sp;
  167.         return (XDR_PUTLONG(xdrs, &l));
  168.  
  169.     case XDR_DECODE:
  170.         if (!XDR_GETLONG(xdrs, &l)) {
  171.             return (FALSE);
  172.         }
  173.         *sp = (short) l;
  174.         return (TRUE);
  175.  
  176.     case XDR_FREE:
  177.         return (TRUE);
  178.     }
  179.     return (FALSE);
  180. }
  181.  
  182. /*
  183.  * XDR unsigned short integers
  184.  */
  185. bool_t
  186. xdr_u_short(xdrs, usp)
  187.     register XDR *xdrs;
  188.     u_short *usp;
  189. {
  190.     u_long l;
  191.  
  192.     switch (xdrs->x_op) {
  193.  
  194.     case XDR_ENCODE:
  195.         l = (u_long) *usp;
  196.         return (XDR_PUTLONG(xdrs, &l));
  197.  
  198.     case XDR_DECODE:
  199.         if (!XDR_GETLONG(xdrs, &l)) {
  200.             return (FALSE);
  201.         }
  202.         *usp = (u_short) l;
  203.         return (TRUE);
  204.  
  205.     case XDR_FREE:
  206.         return (TRUE);
  207.     }
  208.     return (FALSE);
  209. }
  210.  
  211.  
  212. /*
  213.  * XDR booleans
  214.  */
  215. bool_t
  216. xdr_bool(xdrs, bp)
  217.     register XDR *xdrs;
  218.     bool_t *bp;
  219. {
  220.     long lb;
  221.  
  222.     switch (xdrs->x_op) {
  223.  
  224.     case XDR_ENCODE:
  225.         lb = *bp ? XDR_TRUE : XDR_FALSE;
  226.         return (XDR_PUTLONG(xdrs, &lb));
  227.  
  228.     case XDR_DECODE:
  229.         if (!XDR_GETLONG(xdrs, &lb)) {
  230.             return (FALSE);
  231.         }
  232.         *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
  233.         return (TRUE);
  234.  
  235.     case XDR_FREE:
  236.         return (TRUE);
  237.     }
  238.     return (FALSE);
  239. }
  240.  
  241. /*
  242.  * XDR enumerations
  243.  */
  244. bool_t
  245. xdr_enum(xdrs, ep)
  246.     XDR *xdrs;
  247.     enum_t *ep;
  248. {
  249.  
  250.     /*
  251.      * enums are treated as ints
  252.      */
  253.     if (sizeof(enum_t) == sizeof(long)) {
  254.         return (xdr_long(xdrs, (long *)ep));
  255.     } else {
  256.         return (xdr_short(xdrs, (short *)ep));
  257.     }
  258. }
  259.  
  260. /*
  261.  * XDR opaque data
  262.  * Allows the specification of a fixed size sequence of opaque bytes.
  263.  * cp points to the opaque object and cnt gives the byte length.
  264.  */
  265. bool_t
  266. xdr_opaque(xdrs, cp, cnt)
  267.     register XDR *xdrs;
  268.     caddr_t cp;
  269.     register u_int cnt;
  270. {
  271.     register u_int rndup;
  272.     static crud[BYTES_PER_XDR_UNIT];
  273.  
  274.     /*
  275.      * if no data we are done
  276.      */
  277.     if (cnt == 0)
  278.         return (TRUE);
  279.  
  280.     /*
  281.      * round byte count to full xdr units
  282.      */
  283.     rndup = cnt % BYTES_PER_XDR_UNIT;
  284.     if (rndup > 0)
  285.         rndup = BYTES_PER_XDR_UNIT - rndup;
  286.  
  287.     if (xdrs->x_op == XDR_DECODE) {
  288.         if (!XDR_GETBYTES(xdrs, cp, cnt)) {
  289.             return (FALSE);
  290.         }
  291.         if (rndup == 0)
  292.             return (TRUE);
  293.         return (XDR_GETBYTES(xdrs, crud, rndup));
  294.     }
  295.  
  296.     if (xdrs->x_op == XDR_ENCODE) {
  297.         if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
  298.             return (FALSE);
  299.         }
  300.         if (rndup == 0)
  301.             return (TRUE);
  302.         return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
  303.     }
  304.  
  305.     if (xdrs->x_op == XDR_FREE) {
  306.         return (TRUE);
  307.     }
  308.  
  309.     return (FALSE);
  310. }
  311.  
  312. /*
  313.  * XDR counted bytes
  314.  * *cpp is a pointer to the bytes, *sizep is the count.
  315.  * If *cpp is NULL maxsize bytes are allocated
  316.  */
  317. bool_t
  318. xdr_bytes(xdrs, cpp, sizep, maxsize)
  319.     register XDR *xdrs;
  320.     char **cpp;
  321.     register u_int *sizep;
  322.     u_int maxsize;
  323. {
  324.     register char *sp = *cpp;  /* sp is the actual string pointer */
  325.     register u_int nodesize;
  326.  
  327.     /*
  328.      * first deal with the length since xdr bytes are counted
  329.      */
  330.     if (! xdr_u_int(xdrs, sizep)) {
  331.         return (FALSE);
  332.     }
  333.     nodesize = *sizep;
  334.     if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
  335.         return (FALSE);
  336.     }
  337.  
  338.     /*
  339.      * now deal with the actual bytes
  340.      */
  341.     switch (xdrs->x_op) {
  342.  
  343.     case XDR_DECODE:
  344.         if (sp == NULL) {
  345.             *cpp = sp = mem_alloc(nodesize);
  346.         }
  347.         if (sp == NULL) {
  348.             fprintf(stderr, "xdr_bytes: out of memory\n");
  349.             return (FALSE);
  350.         }
  351.         /* fall into ... */
  352.  
  353.     case XDR_ENCODE:
  354.         return (xdr_opaque(xdrs, sp, nodesize));
  355.  
  356.     case XDR_FREE:
  357.         if (sp != NULL) {
  358.             mem_free(sp, nodesize);
  359.             *cpp = NULL;
  360.         }
  361.         return (TRUE);
  362.     }
  363.     return (FALSE);
  364. }
  365.  
  366. /*
  367.  * XDR a descriminated union
  368.  * Support routine for discriminated unions.
  369.  * You create an array of xdrdiscrim structures, terminated with
  370.  * an entry with a null procedure pointer.  The routine gets
  371.  * the discriminant value and then searches the array of xdrdiscrims
  372.  * looking for that value.  It calls the procedure given in the xdrdiscrim
  373.  * to handle the discriminant.  If there is no specific routine a default
  374.  * routine may be called.
  375.  * If there is no specific or default routine an error is returned.
  376.  */
  377. bool_t
  378. xdr_union(xdrs, dscmp, unp, choices, dfault)
  379.     register XDR *xdrs;
  380.     enum_t *dscmp;        /* enum to decide which arm to work on */
  381.     caddr_t unp;        /* the union itself */
  382.     struct xdr_discrim *choices;    /* [value, xdr proc] for each arm */
  383.     xdrproc_t dfault;    /* default xdr routine */
  384. {
  385.     register enum_t dscm;
  386.  
  387.     /*
  388.      * we deal with the discriminator;  it's an enum
  389.      */
  390.     if (! xdr_enum(xdrs, dscmp)) {
  391.         return (FALSE);
  392.     }
  393.     dscm = *dscmp;
  394.  
  395.     /*
  396.      * search choices for a value that matches the discriminator.
  397.      * if we find one, execute the xdr routine for that value.
  398.      */
  399.     for (; choices->proc != NULL_xdrproc_t; choices++) {
  400.         if (choices->value == dscm)
  401.             return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
  402.     }
  403.  
  404.     /*
  405.      * no match - execute the default xdr routine if there is one
  406.      */
  407.     return ((dfault == NULL_xdrproc_t) ? FALSE :
  408.         (*dfault)(xdrs, unp, LASTUNSIGNED));
  409. }
  410.  
  411.  
  412. /*
  413.  * Non-portable xdr primitives.
  414.  * Care should be taken when moving these routines to new architectures.
  415.  */
  416.  
  417.  
  418. /*
  419.  * XDR null terminated ASCII strings
  420.  * xdr_string deals with "C strings" - arrays of bytes that are
  421.  * terminated by a NULL character.  The parameter cpp references a
  422.  * pointer to storage; If the pointer is null, then the necessary
  423.  * storage is allocated.  The last parameter is the max allowed length
  424.  * of the string as specified by a protocol.
  425.  */
  426. bool_t
  427. xdr_string(xdrs, cpp, maxsize)
  428.     register XDR *xdrs;
  429.     char **cpp;
  430.     u_int maxsize;
  431. {
  432.     register char *sp = *cpp;  /* sp is the actual string pointer */
  433.     u_int size;
  434.     u_int nodesize;
  435.  
  436.     /*
  437.      * first deal with the length since xdr strings are counted-strings
  438.      */
  439.     if ((xdrs->x_op) != XDR_DECODE)
  440.         size = strlen(sp);
  441.     if (! xdr_u_int(xdrs, &size)) {
  442.         return (FALSE);
  443.     }
  444.     if (size > maxsize) {
  445.         return (FALSE);
  446.     }
  447.     nodesize = size + 1;
  448.  
  449.     /*
  450.      * now deal with the actual bytes
  451.      */
  452.     switch (xdrs->x_op) {
  453.  
  454.     case XDR_DECODE:
  455.         if (sp == NULL)
  456.             *cpp = sp = mem_alloc(nodesize);
  457.         if (sp == NULL) {
  458.             fprintf(stderr, "xdr_string: out of memory\n");
  459.             return (FALSE);
  460.         }
  461.         sp[size] = 0;
  462.         /* fall into ... */
  463.  
  464.     case XDR_ENCODE:
  465.         return (xdr_opaque(xdrs, sp, size));
  466.  
  467.     case XDR_FREE:
  468.         if (sp != NULL) {
  469.             mem_free(sp, nodesize);
  470.             *cpp = NULL;
  471.         }
  472.         return (TRUE);
  473.     }
  474.     return (FALSE);
  475. }
  476.  
  477. /* 
  478.  * Wrapper for xdr_string that can be called directly from 
  479.  * routines like clnt_call
  480.  */
  481.  
  482. bool_t
  483. xdr_wrapstring(xdrs, cpp)
  484.     XDR *xdrs;
  485.     char **cpp;
  486. {
  487.     if (xdr_string(xdrs, cpp, BUFSIZ)) {
  488.         return(TRUE);
  489.     }
  490.     return(FALSE);
  491. }
  492. !Funky!Stuff!
  493. echo x - xdr.h
  494. sed 's/^X//' >xdr.h <<'!Funky!Stuff!'
  495. /*
  496.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  497.  * unrestricted use provided that this legend is included on all tape
  498.  * media and as a part of the software program in whole or part.  Users
  499.  * may copy or modify Sun RPC without charge, but are not authorized
  500.  * to license or distribute it to anyone else except as part of a product or
  501.  * program developed by the user.
  502.  * 
  503.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  504.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  505.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  506.  * 
  507.  * Sun RPC is provided with no support and without any obligation on the
  508.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  509.  * modification or enhancement.
  510.  * 
  511.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  512.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  513.  * OR ANY PART THEREOF.
  514.  * 
  515.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  516.  * or profits or other special, indirect and consequential damages, even if
  517.  * Sun has been advised of the possibility of such damages.
  518.  * 
  519.  * Sun Microsystems, Inc.
  520.  * 2550 Garcia Avenue
  521.  * Mountain View, California  94043
  522.  */
  523. /*      @(#)xdr.h 1.4 85/02/08 SMI      */
  524.  
  525. /*
  526.  * xdr.h, External Data Representation Serialization Routines.
  527.  *
  528.  * Copyright (C) 1984, Sun Microsystems, Inc.
  529.  */
  530.  
  531. /*
  532.  * XDR provides a conventional way for converting between C data
  533.  * types and an external bit-string representation.  Library supplied
  534.  * routines provide for the conversion on built-in C data types.  These
  535.  * routines and utility routines defined here are used to help implement
  536.  * a type encode/decode routine for each user-defined type.
  537.  *
  538.  * Each data type provides a single procedure which takes two arguments:
  539.  *
  540.  *    bool_t
  541.  *    xdrproc(xdrs, argresp)
  542.  *        XDR *xdrs;
  543.  *        <type> *argresp;
  544.  *
  545.  * xdrs is an instance of a XDR handle, to which or from which the data
  546.  * type is to be converted.  argresp is a pointer to the structure to be
  547.  * converted.  The XDR handle contains an operation field which indicates
  548.  * which of the operations (ENCODE, DECODE * or FREE) is to be performed.
  549.  *
  550.  * XDR_DECODE may allocate space if the pointer argresp is null.  This
  551.  * data can be freed with the XDR_FREE operation.
  552.  *
  553.  * We write only one procedure per data type to make it easy
  554.  * to keep the encode and decode procedures for a data type consistent.
  555.  * In many cases the same code performs all operations on a user defined type,
  556.  * because all the hard work is done in the component type routines.
  557.  * decode as a series of calls on the nested data types.
  558.  */
  559.  
  560. /*
  561.  * Xdr operations.  XDR_ENCODE causes the type to be encoded into the
  562.  * stream.  XDR_DECODE causes the type to be extracted from the stream.
  563.  * XDR_FREE can be used to release the space allocated by an XDR_DECODE
  564.  * request.
  565.  */
  566. enum xdr_op {
  567.     XDR_ENCODE=0,
  568.     XDR_DECODE=1,
  569.     XDR_FREE=2
  570. };
  571.  
  572. /*
  573.  * This is the number of bytes per unit of external data.
  574.  */
  575. #define BYTES_PER_XDR_UNIT    (4)
  576.  
  577. /*
  578.  * A xdrproc_t exists for each data type which is to be encoded or decoded.
  579.  *
  580.  * The second argument to the xdrproc_t is a pointer to an opaque pointer.
  581.  * The opaque pointer generally points to a structure of the data type
  582.  * to be decoded.  If this pointer is 0, then the type routines should
  583.  * allocate dynamic storage of the appropriate size and return it.
  584.  * bool_t    (*xdrproc_t)(XDR *, caddr_t *);
  585.  */
  586. typedef    bool_t (*xdrproc_t)();
  587.  
  588. /*
  589.  * The XDR handle.
  590.  * Contains operation which is being applied to the stream,
  591.  * an operations vector for the paticular implementation (e.g. see xdr_mem.c),
  592.  * and two private fields for the use of the particular impelementation.
  593.  */
  594. typedef struct {
  595.     enum xdr_op    x_op;        /* operation; fast additional param */
  596.     struct xdr_ops {
  597.         bool_t    (*x_getlong)();    /* get a long from underlying stream */
  598.         bool_t    (*x_putlong)();    /* put a long to " */
  599.         bool_t    (*x_getbytes)();/* get some bytes from " */
  600.         bool_t    (*x_putbytes)();/* put some bytes to " */
  601.         u_int    (*x_getpostn)();/* returns bytes off from beginning */
  602.         bool_t  (*x_setpostn)();/* lets you reposition the stream */
  603.         long *    (*x_inline)();    /* buf quick ptr to buffered data */
  604.         void    (*x_destroy)();    /* free privates of this xdr_stream */
  605.     } *x_ops;
  606.     caddr_t     x_public;    /* users' data */
  607.     caddr_t        x_private;    /* pointer to private data */
  608.     caddr_t     x_base;        /* private used for position info */
  609.     int        x_handy;    /* extra private word */
  610. } XDR;
  611.  
  612. /*
  613.  * Operations defined on a XDR handle
  614.  *
  615.  * XDR        *xdrs;
  616.  * long        *longp;
  617.  * caddr_t     addr;
  618.  * u_int     len;
  619.  * u_int     pos;
  620.  */
  621. #define XDR_GETLONG(xdrs, longp)            \
  622.     (*(xdrs)->x_ops->x_getlong)(xdrs, longp)
  623. #define xdr_getlong(xdrs, longp)            \
  624.     (*(xdrs)->x_ops->x_getlong)(xdrs, longp)
  625.  
  626. #define XDR_PUTLONG(xdrs, longp)            \
  627.     (*(xdrs)->x_ops->x_putlong)(xdrs, longp)
  628. #define xdr_putlong(xdrs, longp)            \
  629.     (*(xdrs)->x_ops->x_putlong)(xdrs, longp)
  630.  
  631. #define XDR_GETBYTES(xdrs, addr, len)            \
  632.     (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
  633. #define xdr_getbytes(xdrs, addr, len)            \
  634.     (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
  635.  
  636. #define XDR_PUTBYTES(xdrs, addr, len)            \
  637.     (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
  638. #define xdr_putbytes(xdrs, addr, len)            \
  639.     (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
  640.  
  641. #define XDR_GETPOS(xdrs)                \
  642.     (*(xdrs)->x_ops->x_getpostn)(xdrs)
  643. #define xdr_getpos(xdrs)                \
  644.     (*(xdrs)->x_ops->x_getpostn)(xdrs)
  645.  
  646. #define XDR_SETPOS(xdrs, pos)                \
  647.     (*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
  648. #define xdr_setpos(xdrs, pos)                \
  649.     (*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
  650.  
  651. #define    XDR_INLINE(xdrs, len)                \
  652.     (*(xdrs)->x_ops->x_inline)(xdrs, len)
  653. #define    xdr_inline(xdrs, len)                \
  654.     (*(xdrs)->x_ops->x_inline)(xdrs, len)
  655.  
  656. #define    XDR_DESTROY(xdrs)                \
  657.     if ((xdrs)->x_ops->x_destroy)             \
  658.         (*(xdrs)->x_ops->x_destroy)(xdrs)
  659. #define    xdr_destroy(xdrs)                \
  660.     if ((xdrs)->x_ops->x_destroy)             \
  661.         (*(xdrs)->x_ops->x_destroy)(xdrs)
  662.  
  663. /*
  664.  * Support struct for discriminated unions.
  665.  * You create an array of xdrdiscrim structures, terminated with
  666.  * a entry with a null procedure pointer.  The xdr_union routine gets
  667.  * the discriminant value and then searches the array of structures
  668.  * for a matching value.  If a match is found the associated xdr routine
  669.  * is called to handle that part of the union.  If there is
  670.  * no match, then a default routine may be called.
  671.  * If there is no match and no default routine it is an error.
  672.  */
  673. #define NULL_xdrproc_t ((xdrproc_t)0)
  674. struct xdr_discrim {
  675.     int    value;
  676.     xdrproc_t proc;
  677. };
  678.  
  679. /*
  680.  * In-line routines for fast encode/decode of primitve data types.
  681.  * Caveat emptor: these use single memory cycles to get the
  682.  * data from the underlying buffer, and will fail to operate
  683.  * properly if the data is not aligned.  The standard way to use these
  684.  * is to say:
  685.  *    if ((buf = XDR_INLINE(xdrs, count)) == NULL)
  686.  *        return (FALSE);
  687.  *    <<< macro calls >>>
  688.  * where ``count'' is the number of bytes of data occupied
  689.  * by the primitive data types.
  690.  *
  691.  * N.B. and frozen for all time: each data type here uses 4 bytes
  692.  * of external representation.
  693.  */
  694. #define IXDR_GET_LONG(buf)        ntohl(*buf++)
  695. #define IXDR_PUT_LONG(buf, v)        (*buf++ = htonl(v))
  696.  
  697. #define IXDR_GET_BOOL(buf)        ((bool_t)IXDR_GET_LONG(buf))
  698. #define IXDR_GET_ENUM(buf, t)        ((t)IXDR_GET_LONG(buf))
  699. #define IXDR_GET_U_LONG(buf)        ((u_long)IXDR_GET_LONG(buf))
  700. #define IXDR_GET_SHORT(buf)        ((short)IXDR_GET_LONG(buf))
  701. #define IXDR_GET_U_SHORT(buf)        ((u_short)IXDR_GET_LONG(buf))
  702.  
  703. #define IXDR_PUT_BOOL(buf, v)        IXDR_PUT_LONG((buf), ((long)(v)))
  704. #define IXDR_PUT_ENUM(buf, v)        IXDR_PUT_LONG((buf), ((long)(v)))
  705. #define IXDR_PUT_U_LONG(buf, v)        IXDR_PUT_LONG((buf), ((long)(v)))
  706. #define IXDR_PUT_SHORT(buf, v)        IXDR_PUT_LONG((buf), ((long)(v)))
  707. #define IXDR_PUT_U_SHORT(buf, v)    IXDR_PUT_LONG((buf), ((long)(v)))
  708.  
  709. /*
  710.  * These are the "generic" xdr routines.
  711.  */
  712. extern bool_t    xdr_void();
  713. extern bool_t    xdr_int();
  714. extern bool_t    xdr_u_int();
  715. extern bool_t    xdr_long();
  716. extern bool_t    xdr_u_long();
  717. extern bool_t    xdr_short();
  718. extern bool_t    xdr_u_short();
  719. extern bool_t    xdr_float();
  720. extern bool_t    xdr_double();
  721. extern bool_t    xdr_bool();
  722. extern bool_t    xdr_enum();
  723. extern bool_t    xdr_array();
  724. extern bool_t    xdr_bytes();
  725. extern bool_t    xdr_opaque();
  726. extern bool_t    xdr_string();
  727. extern bool_t    xdr_wrapstring();
  728. extern bool_t    xdr_union();
  729. extern bool_t    xdr_reference();
  730.  
  731. /*
  732.  * These are the public routines for the various implementations of
  733.  * xdr streams.
  734.  */
  735.  
  736. extern void   xdrmem_create();        /* XDR using memory buffers */
  737. extern void   xdrstdio_create();    /* XDR using stdio library */
  738. extern void   xdrrec_create();        /* XDR pseudo records for tcp */
  739. extern bool_t xdrrec_endofrecord();    /* make end of xdr record */
  740. extern bool_t xdrrec_skiprecord();    /* move to begining of next record */
  741. extern bool_t xdrrec_eof();        /* true iff no more input */
  742. !Funky!Stuff!
  743. echo x - xdr_array.c
  744. sed 's/^X//' >xdr_array.c <<'!Funky!Stuff!'
  745. /*
  746.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  747.  * unrestricted use provided that this legend is included on all tape
  748.  * media and as a part of the software program in whole or part.  Users
  749.  * may copy or modify Sun RPC without charge, but are not authorized
  750.  * to license or distribute it to anyone else except as part of a product or
  751.  * program developed by the user.
  752.  * 
  753.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  754.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  755.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  756.  * 
  757.  * Sun RPC is provided with no support and without any obligation on the
  758.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  759.  * modification or enhancement.
  760.  * 
  761.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  762.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  763.  * OR ANY PART THEREOF.
  764.  * 
  765.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  766.  * or profits or other special, indirect and consequential damages, even if
  767.  * Sun has been advised of the possibility of such damages.
  768.  * 
  769.  * Sun Microsystems, Inc.
  770.  * 2550 Garcia Avenue
  771.  * Mountain View, California  94043
  772.  */
  773. #ifndef lint
  774. static char sccsid[] = "@(#)xdr_array.c 1.2 85/02/26 Copyr 1984 Sun Micro";
  775. #endif
  776.  
  777. /*
  778.  * xdr_array.c, Generic XDR routines impelmentation.
  779.  *
  780.  * Copyright (C) 1984, Sun Microsystems, Inc.
  781.  *
  782.  * These are the "non-trivial" xdr primitives used to serialize and de-serialize
  783.  * arrays.  See xdr.h for more info on the interface to xdr.
  784.  */
  785.  
  786. #include "types.h"
  787. #include "xdr.h"
  788. #include <stdio.h>
  789. #define LASTUNSIGNED    ((u_int)0-1)
  790.  
  791. char *mem_alloc();
  792.  
  793. /*
  794.  * XDR an array of arbitrary elements
  795.  * *addrp is a pointer to the array, *sizep is the number of elements.
  796.  * If addrp is NULL (*sizep * elsize) bytes are allocated.
  797.  * elsize is the size (in bytes) of each element, and elproc is the
  798.  * xdr procedure to call to handle each element of the array.
  799.  */
  800. bool_t
  801. xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc)
  802.     register XDR *xdrs;
  803.     caddr_t *addrp;        /* array pointer */
  804.     u_int *sizep;        /* number of elements */
  805.     u_int maxsize;        /* max numberof elements */
  806.     u_int elsize;        /* size in bytes of each element */
  807.     xdrproc_t elproc;    /* xdr routine to handle each element */
  808. {
  809.     register u_int i;
  810.     register caddr_t target = *addrp;
  811.     register u_int c;  /* the actual element count */
  812.     register bool_t stat = TRUE;
  813.     register int nodesize;
  814.  
  815.     /* like strings, arrays are really counted arrays */
  816.     if (! xdr_u_int(xdrs, sizep)) {
  817.         return (FALSE);
  818.     }
  819.     c = *sizep;
  820.     if ((c > maxsize) && (xdrs->x_op != XDR_FREE)) {
  821.         return (FALSE);
  822.     }
  823.     nodesize = c * elsize;
  824.  
  825.     /*
  826.      * if we are deserializing, we may need to allocate an array.
  827.      * We also save time by checking for a null array if we are freeing.
  828.      */
  829.     if (target == NULL)
  830.         switch (xdrs->x_op) {
  831.         case XDR_DECODE:
  832.             if (c == 0)
  833.                 return (TRUE);
  834.             *addrp = target = mem_alloc(nodesize);
  835.             if (target == NULL) {
  836.                 fprintf(stderr, "xdr_array: out of memory\n");
  837.                 return (FALSE);
  838.             }
  839.             bzero(target, nodesize);
  840.             break;
  841.  
  842.         case XDR_FREE:
  843.             return (TRUE);
  844.     }
  845.     
  846.     /*
  847.      * now we xdr each element of array
  848.      */
  849.     for (i = 0; (i < c) && stat; i++) {
  850.         stat = (*elproc)(xdrs, target, LASTUNSIGNED);
  851.         target += elsize;
  852.     }
  853.  
  854.     /*
  855.      * the array may need freeing
  856.      */
  857.     if (xdrs->x_op == XDR_FREE) {
  858.         mem_free(*addrp, nodesize);
  859.         *addrp = NULL;
  860.     }
  861.     return (stat);
  862. }
  863. !Funky!Stuff!
  864. echo x - xdr_float.c
  865. sed 's/^X//' >xdr_float.c <<'!Funky!Stuff!'
  866. /*
  867.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  868.  * unrestricted use provided that this legend is included on all tape
  869.  * media and as a part of the software program in whole or part.  Users
  870.  * may copy or modify Sun RPC without charge, but are not authorized
  871.  * to license or distribute it to anyone else except as part of a product or
  872.  * program developed by the user.
  873.  * 
  874.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  875.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  876.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  877.  * 
  878.  * Sun RPC is provided with no support and without any obligation on the
  879.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  880.  * modification or enhancement.
  881.  * 
  882.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  883.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  884.  * OR ANY PART THEREOF.
  885.  * 
  886.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  887.  * or profits or other special, indirect and consequential damages, even if
  888.  * Sun has been advised of the possibility of such damages.
  889.  * 
  890.  * Sun Microsystems, Inc.
  891.  * 2550 Garcia Avenue
  892.  * Mountain View, California  94043
  893.  */
  894. #ifndef lint
  895. static char sccsid[] = "@(#)xdr_float.c 1.2 85/03/14 Copyr 1984 Sun Micro";
  896. #endif
  897.  
  898. /*
  899.  * xdr_float.c, Generic XDR routines impelmentation.
  900.  *
  901.  * Copyright (C) 1984, Sun Microsystems, Inc.
  902.  *
  903.  * These are the "floating point" xdr routines used to (de)serialize
  904.  * most common data items.  See xdr.h for more info on the interface to
  905.  * xdr.
  906.  */
  907.  
  908. #include "types.h"
  909. #include "xdr.h"
  910. #include <stdio.h>
  911.  
  912. /*
  913.  * NB: Not portable.
  914.  * This routine works on Suns (Sky / 68000's) and Vaxen.
  915.  */
  916.    
  917. /* What IEEE single precision floating point looks like on a Vax */
  918. struct  ieee_single {
  919.     unsigned int    mantissa: 23;
  920.     unsigned int    exp     : 8;
  921.     unsigned int    sign    : 1;
  922. };
  923.  
  924. /* Vax single precision floating point */
  925. struct  vax_single {
  926.     unsigned int    mantissa1 : 7;
  927.     unsigned int    exp       : 8;
  928.     unsigned int    sign      : 1;
  929.     unsigned int    mantissa2 : 16;
  930.         
  931. };
  932.  
  933. #define VAX_SNG_BIAS    0x81
  934. #define IEEE_SNG_BIAS   0x7f
  935.  
  936. static struct sgl_limits {
  937.     struct vax_single s;
  938.     struct ieee_single ieee;
  939. } sgl_limits[2] = {
  940.     {{ 0x3f, 0xff, 0x0, 0xffff },    /* Max Vax */
  941.     { 0x0, 0xff, 0x0 }},        /* Max IEEE */
  942.     {{ 0x0, 0x0, 0x0, 0x0 },    /* Min Vax */
  943.     { 0x0, 0x0, 0x0 }}        /* Min IEEE */
  944. };
  945.  
  946. bool_t 
  947. xdr_float(xdrs, fp)
  948.     register XDR *xdrs;
  949.     register float *fp;
  950. {
  951.     struct ieee_single is;
  952.     struct vax_single vs, *vsp;
  953.     struct sgl_limits *lim;
  954.     int i;
  955.  
  956.     switch (xdrs->x_op) {
  957.  
  958.     case XDR_ENCODE:
  959. #ifdef mc68000
  960.         return (XDR_PUTLONG(xdrs, (long *)fp));
  961. #else
  962.         vs = *((struct vax_single *)fp);
  963.         for (i = 0, lim = sgl_limits;
  964.             i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
  965.             i++, lim++) {
  966.             if ((vs.mantissa2 == lim->s.mantissa2) &&
  967.                 (vs.exp == lim->s.exp) &&
  968.                 (vs.mantissa1 == lim->s.mantissa1)) {
  969.                 is = lim->ieee;
  970.                 goto shipit;
  971.             }
  972.         }
  973.         is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
  974.         is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
  975.     shipit:
  976.         is.sign = vs.sign;
  977.         return (XDR_PUTLONG(xdrs, (long *)&is));
  978. #endif
  979.  
  980.     case XDR_DECODE:
  981. #ifdef mc68000
  982.         return (XDR_GETLONG(xdrs, (long *)fp));
  983. #else
  984.         vsp = (struct vax_single *)fp;
  985.         if (!XDR_GETLONG(xdrs, (long *)&is))
  986.             return (FALSE);
  987.         for (i = 0, lim = sgl_limits;
  988.             i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
  989.             i++, lim++) {
  990.             if ((is.exp == lim->ieee.exp) &&
  991.                 (is.mantissa = lim->ieee.mantissa)) {
  992.                 *vsp = lim->s;
  993.                 goto doneit;
  994.             }
  995.         }
  996.         vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
  997.         vsp->mantissa2 = is.mantissa;
  998.         vsp->mantissa1 = (is.mantissa >> 16);
  999.     doneit:
  1000.         vsp->sign = is.sign;
  1001.         return (TRUE);
  1002. #endif
  1003.  
  1004.     case XDR_FREE:
  1005.         return (TRUE);
  1006.     }
  1007.     return (FALSE);
  1008. }
  1009.  
  1010. /*
  1011.  * This routine works on Suns (Sky / 68000's) and Vaxen.
  1012.  */
  1013.  
  1014. /* What IEEE double precision floating point looks like on a Vax */
  1015. struct  ieee_double {
  1016.     unsigned int    mantissa1 : 20;
  1017.     unsigned int    exp      : 11;
  1018.     unsigned int    sign      : 1;
  1019.     unsigned int    mantissa2 : 32;
  1020. };
  1021.  
  1022. /* Vax double precision floating point */
  1023. struct  vax_double {
  1024.     unsigned int    mantissa1 : 7;
  1025.     unsigned int    exp       : 8;
  1026.     unsigned int    sign      : 1;
  1027.     unsigned int    mantissa2 : 16;
  1028.     unsigned int    mantissa3 : 16;
  1029.     unsigned int    mantissa4 : 16;
  1030. };
  1031.  
  1032. #define VAX_DBL_BIAS    0x81
  1033. #define IEEE_DBL_BIAS   0x3ff
  1034. #define MASK(nbits)     ((1 << nbits) - 1)
  1035.  
  1036. static struct dbl_limits {
  1037.     struct  vax_double d;
  1038.     struct  ieee_double ieee;
  1039. } dbl_limits[2] = {
  1040.     {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff },    /* Max Vax */
  1041.     { 0x0, 0x7ff, 0x0, 0x0 }},            /* Max IEEE */
  1042.     {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},        /* Min Vax */
  1043.     { 0x0, 0x0, 0x0, 0x0 }}                /* Min IEEE */
  1044. };
  1045.  
  1046. bool_t           
  1047. xdr_double(xdrs, dp)
  1048.     register XDR *xdrs;
  1049.     double *dp;
  1050. {
  1051.     register long *lp;
  1052.     struct  ieee_double id;
  1053.     struct  vax_double vd;
  1054.     register struct dbl_limits *lim;
  1055.     int i;
  1056.  
  1057.     switch (xdrs->x_op) {
  1058.  
  1059.     case XDR_ENCODE:
  1060. #ifdef mc68000
  1061.         lp = (long *)dp;
  1062. #else
  1063.         vd = *((struct  vax_double *)dp);
  1064.         for (i = 0, lim = dbl_limits;
  1065.             i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
  1066.             i++, lim++) {
  1067.             if ((vd.mantissa4 == lim->d.mantissa4) &&
  1068.                 (vd.mantissa3 == lim->d.mantissa3) &&
  1069.                 (vd.mantissa2 == lim->d.mantissa2) &&
  1070.                 (vd.mantissa1 == lim->d.mantissa1) &&
  1071.                 (vd.exp == lim->d.exp)) {
  1072.                 id = lim->ieee;
  1073.                 goto shipit;
  1074.             }
  1075.         }
  1076.         id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
  1077.         id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
  1078.         id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
  1079.                 (vd.mantissa3 << 13) |
  1080.                 ((vd.mantissa4 >> 3) & MASK(13));
  1081.     shipit:
  1082.         id.sign = vd.sign;
  1083.         lp = (long *)&id;
  1084. #endif
  1085.         return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp));
  1086.  
  1087.     case XDR_DECODE:
  1088. #ifdef mc68000
  1089.         lp = (long *)dp;
  1090.         return (XDR_GETLONG(xdrs, lp++) && XDR_GETLONG(xdrs, lp));
  1091. #else
  1092.         lp = (long *)&id;
  1093.         if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp))
  1094.             return (FALSE);
  1095.         for (i = 0, lim = dbl_limits;
  1096.             i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
  1097.             i++, lim++) {
  1098.             if ((id.mantissa2 == lim->ieee.mantissa2) &&
  1099.                 (id.mantissa1 == lim->ieee.mantissa1) &&
  1100.                 (id.exp == lim->ieee.exp)) {
  1101.                 vd = lim->d;
  1102.                 goto doneit;
  1103.             }
  1104.         }
  1105.         vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
  1106.         vd.mantissa1 = (id.mantissa1 >> 13);
  1107.         vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
  1108.                 (id.mantissa2 >> 29);
  1109.         vd.mantissa3 = (id.mantissa2 >> 13);
  1110.         vd.mantissa4 = (id.mantissa2 << 3);
  1111.     doneit:
  1112.         vd.sign = id.sign;
  1113.         *dp = *((double *)&vd);
  1114.         return (TRUE);
  1115. #endif
  1116.  
  1117.     case XDR_FREE:
  1118.         return (TRUE);
  1119.     }
  1120.     return (FALSE);
  1121. }
  1122. !Funky!Stuff!
  1123. echo x - xdr_mem.c
  1124. sed 's/^X//' >xdr_mem.c <<'!Funky!Stuff!'
  1125. /*
  1126.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  1127.  * unrestricted use provided that this legend is included on all tape
  1128.  * media and as a part of the software program in whole or part.  Users
  1129.  * may copy or modify Sun RPC without charge, but are not authorized
  1130.  * to license or distribute it to anyone else except as part of a product or
  1131.  * program developed by the user.
  1132.  * 
  1133.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  1134.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  1135.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  1136.  * 
  1137.  * Sun RPC is provided with no support and without any obligation on the
  1138.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  1139.  * modification or enhancement.
  1140.  * 
  1141.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  1142.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  1143.  * OR ANY PART THEREOF.
  1144.  * 
  1145.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  1146.  * or profits or other special, indirect and consequential damages, even if
  1147.  * Sun has been advised of the possibility of such damages.
  1148.  * 
  1149.  * Sun Microsystems, Inc.
  1150.  * 2550 Garcia Avenue
  1151.  * Mountain View, California  94043
  1152.  */
  1153. #ifndef lint
  1154. static char sccsid[] = "@(#)xdr_mem.c 1.4 85/03/14 Copyr 1984 Sun Micro";
  1155. #endif
  1156.  
  1157. /*
  1158.  * xdr_mem.h, XDR implementation using memory buffers.
  1159.  *
  1160.  * Copyright (C) 1984, Sun Microsystems, Inc.
  1161.  *
  1162.  * If you have some data to be interpreted as external data representation
  1163.  * or to be converted to external data representation in a memory buffer,
  1164.  * then this is the package for you.
  1165.  *
  1166.  */
  1167.  
  1168. #include "types.h"
  1169. #include "xdr.h"
  1170. #include <netinet/in.h>
  1171.  
  1172. static bool_t    xdrmem_getlong();
  1173. static bool_t    xdrmem_putlong();
  1174. static bool_t    xdrmem_getbytes();
  1175. static bool_t    xdrmem_putbytes();
  1176. static u_int    xdrmem_getpos();
  1177. static bool_t    xdrmem_setpos();
  1178. static long *    xdrmem_inline();
  1179. static void    xdrmem_destroy();
  1180.  
  1181. static struct    xdr_ops xdrmem_ops = {
  1182.     xdrmem_getlong,
  1183.     xdrmem_putlong,
  1184.     xdrmem_getbytes,
  1185.     xdrmem_putbytes,
  1186.     xdrmem_getpos,
  1187.     xdrmem_setpos,
  1188.     xdrmem_inline,
  1189.     xdrmem_destroy
  1190. };
  1191.  
  1192. /*
  1193.  * The procedure xdrmem_create initializes a stream descriptor for a
  1194.  * memory buffer.  
  1195.  */
  1196. void
  1197. xdrmem_create(xdrs, addr, size, op)
  1198.     register XDR *xdrs;
  1199.     caddr_t addr;
  1200.     u_int size;
  1201.     enum xdr_op op;
  1202. {
  1203.  
  1204.     xdrs->x_op = op;
  1205.     xdrs->x_ops = &xdrmem_ops;
  1206.     xdrs->x_private = xdrs->x_base = addr;
  1207.     xdrs->x_handy = size;
  1208. }
  1209.  
  1210. static void
  1211. xdrmem_destroy(/*xdrs*/)
  1212.     /*XDR *xdrs;*/
  1213. {
  1214. }
  1215.  
  1216. static bool_t
  1217. xdrmem_getlong(xdrs, lp)
  1218.     register XDR *xdrs;
  1219.     long *lp;
  1220. {
  1221.  
  1222.     if ((xdrs->x_handy -= sizeof(long)) < 0)
  1223.         return (FALSE);
  1224.     *lp = ntohl(*((long *)(xdrs->x_private)));
  1225.     xdrs->x_private += sizeof(long);
  1226.     return (TRUE);
  1227. }
  1228.  
  1229. static bool_t
  1230. xdrmem_putlong(xdrs, lp)
  1231.     register XDR *xdrs;
  1232.     long *lp;
  1233. {
  1234.  
  1235.     if ((xdrs->x_handy -= sizeof(long)) < 0)
  1236.         return (FALSE);
  1237.     *(long *)xdrs->x_private = htonl(*lp);
  1238.     xdrs->x_private += sizeof(long);
  1239.     return (TRUE);
  1240. }
  1241.  
  1242. static bool_t
  1243. xdrmem_getbytes(xdrs, addr, len)
  1244.     register XDR *xdrs;
  1245.     caddr_t addr;
  1246.     register u_int len;
  1247. {
  1248.  
  1249.     if ((xdrs->x_handy -= len) < 0)
  1250.         return (FALSE);
  1251.     bcopy(xdrs->x_private, addr, len);
  1252.     xdrs->x_private += len;
  1253.     return (TRUE);
  1254. }
  1255.  
  1256. static bool_t
  1257. xdrmem_putbytes(xdrs, addr, len)
  1258.     register XDR *xdrs;
  1259.     caddr_t addr;
  1260.     register u_int len;
  1261. {
  1262.  
  1263.     if ((xdrs->x_handy -= len) < 0)
  1264.         return (FALSE);
  1265.     bcopy(addr, xdrs->x_private, len);
  1266.     xdrs->x_private += len;
  1267.     return (TRUE);
  1268. }
  1269.  
  1270. static u_int
  1271. xdrmem_getpos(xdrs)
  1272.     register XDR *xdrs;
  1273. {
  1274.  
  1275.     return ((u_int)xdrs->x_private - (u_int)xdrs->x_base);
  1276. }
  1277.  
  1278. static bool_t
  1279. xdrmem_setpos(xdrs, pos)
  1280.     register XDR *xdrs;
  1281.     u_int pos;
  1282. {
  1283.     register caddr_t newaddr = xdrs->x_base + pos;
  1284.     register caddr_t lastaddr = xdrs->x_private + xdrs->x_handy;
  1285.  
  1286.     if ((long)newaddr > (long)lastaddr)
  1287.         return (FALSE);
  1288.     xdrs->x_private = newaddr;
  1289.     xdrs->x_handy = (int)lastaddr - (int)newaddr;
  1290.     return (TRUE);
  1291. }
  1292.  
  1293. static long *
  1294. xdrmem_inline(xdrs, len)
  1295.     register XDR *xdrs;
  1296.     int len;
  1297. {
  1298.     long *buf = 0;
  1299.  
  1300.     if (xdrs->x_handy >= len) {
  1301.         xdrs->x_handy -= len;
  1302.         buf = (long *) xdrs->x_private;
  1303.         xdrs->x_private += len;
  1304.     }
  1305.     return (buf);
  1306. }
  1307. !Funky!Stuff!
  1308. echo x - xdr_rec.c
  1309. sed 's/^X//' >xdr_rec.c <<'!Funky!Stuff!'
  1310. /*
  1311.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  1312.  * unrestricted use provided that this legend is included on all tape
  1313.  * media and as a part of the software program in whole or part.  Users
  1314.  * may copy or modify Sun RPC without charge, but are not authorized
  1315.  * to license or distribute it to anyone else except as part of a product or
  1316.  * program developed by the user.
  1317.  * 
  1318.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  1319.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  1320.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  1321.  * 
  1322.  * Sun RPC is provided with no support and without any obligation on the
  1323.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  1324.  * modification or enhancement.
  1325.  * 
  1326.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  1327.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  1328.  * OR ANY PART THEREOF.
  1329.  * 
  1330.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  1331.  * or profits or other special, indirect and consequential damages, even if
  1332.  * Sun has been advised of the possibility of such damages.
  1333.  * 
  1334.  * Sun Microsystems, Inc.
  1335.  * 2550 Garcia Avenue
  1336.  * Mountain View, California  94043
  1337.  */
  1338. #ifndef lint
  1339. static char sccsid[] = "@(#)xdr_rec.c 1.5 85/03/14 Copyr 1984 Sun Micro";
  1340. #endif
  1341.  
  1342. /*
  1343.  * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking"
  1344.  * layer above tcp (for rpc's use).
  1345.  *
  1346.  * Copyright (C) 1984, Sun Microsystems, Inc.
  1347.  *
  1348.  * These routines interface XDRSTREAMS to a tcp/ip connection.
  1349.  * There is a record marking layer between the xdr stream
  1350.  * and the tcp transport level.  A record is composed on one or more
  1351.  * record fragments.  A record fragment is a thirty-two bit header followed
  1352.  * by n bytes of data, where n is contained in the header.  The header
  1353.  * is represented as a htonl(u_long).  Thegh order bit encodes
  1354.  * whether or not the fragment is the last fragment of the record
  1355.  * (1 => fragment is last, 0 => more fragments to follow. 
  1356.  * The other 31 bits encode the byte length of the fragment.
  1357.  */
  1358.  
  1359. #include <stdio.h>
  1360. #include "types.h"
  1361. #include "xdr.h"
  1362. #include <sys/time.h>
  1363. #include <netinet/in.h>
  1364.  
  1365. char *mem_alloc();
  1366.  
  1367. static u_int    fix_buf_size();
  1368.  
  1369. static bool_t    xdrrec_getlong();
  1370. static bool_t    xdrrec_putlong();
  1371. static bool_t    xdrrec_getbytes();
  1372. static bool_t    xdrrec_putbytes();
  1373. static u_int    xdrrec_getpos();
  1374. static bool_t    xdrrec_setpos();
  1375. static long *    xdrrec_inline();
  1376. static void    xdrrec_destroy();
  1377.  
  1378. static struct  xdr_ops xdrrec_ops = {
  1379.     xdrrec_getlong,
  1380.     xdrrec_putlong,
  1381.     xdrrec_getbytes,
  1382.     xdrrec_putbytes,
  1383.     xdrrec_getpos,
  1384.     xdrrec_setpos,
  1385.     xdrrec_inline,
  1386.     xdrrec_destroy
  1387. };
  1388.  
  1389. /*
  1390.  * A record is composed of one or more record fragments.
  1391.  * A record fragment is a two-byte header followed by zero to
  1392.  * 2**32-1 bytes.  The header is treated as a long unsigned and is
  1393.  * encode/decoded to the network via htonl/ntohl.  The low order 31 bits
  1394.  * are a byte count of the fragment.  The highest order bit is a boolean:
  1395.  * 1 => this fragment is the last fragment of the record,
  1396.  * 0 => this fragment is followed by more fragment(s).
  1397.  *
  1398.  * The fragment/record machinery is not general;  it is constructed to
  1399.  * meet the needs of xdr and rpc based on tcp.
  1400.  */
  1401.  
  1402. #define LAST_FRAG ((u_long)(1 << 31))
  1403.  
  1404. typedef struct rec_strm {
  1405.     caddr_t tcp_handle;
  1406.     /*
  1407.      * out-goung bits
  1408.      */
  1409.     int (*writeit)();
  1410.     caddr_t out_base;    /* output buffer (points to frag header) */
  1411.     caddr_t out_finger;    /* next output position */
  1412.     caddr_t out_boundry;    /* data cannot up to this address */
  1413.     u_long *frag_header;    /* beginning of curren fragment */
  1414.     bool_t frag_sent;    /* true if buffer sent in middle of record */
  1415.     /*
  1416.      * in-coming bits
  1417.      */
  1418.     int (*readit)();
  1419.     u_long in_size;    /* fixed size of the input buffer */
  1420.     caddr_t in_base;
  1421.     caddr_t in_finger;    /* location of next byte to be had */
  1422.     caddr_t in_boundry;    /* can read up to this location */
  1423.     long fbtbc;        /* fragment bytes to be consumed */
  1424.     bool_t last_frag;
  1425.     u_int sendsize;
  1426.     u_int recvsize;
  1427. } RECSTREAM;
  1428.  
  1429.  
  1430. /*
  1431.  * Create an xdr handle for xdrrec
  1432.  * xdrrec_create fills in xdrs.  Sendsize and recvsize are
  1433.  * send and recv buffer sizes (0 => use default).
  1434.  * tcp_handle is an opaque handle that is passed as the first parameter to
  1435.  * the procedures readit and writeit.  Readit and writeit are read and
  1436.  * write respectively.   They are like the system
  1437.  * calls expect that they take an opaque handle rather than an fd.
  1438.  */
  1439. void
  1440. xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit)
  1441.     register XDR *xdrs;
  1442.     u_int sendsize;
  1443.     u_int recvsize;
  1444.     caddr_t tcp_handle;
  1445.     int (*readit)();  /* like read, but pass it a tcp_handle, not sock */
  1446.     int (*writeit)();  /* like write, but pass it a tcp_handle, not sock */
  1447. {
  1448.     register RECSTREAM *rstrm =
  1449.         (RECSTREAM *)mem_alloc(sizeof(RECSTREAM));
  1450.  
  1451.     if (rstrm == NULL) {
  1452.         fprintf(stderr, "xdrrec_create: out of memory\n");
  1453.         /* 
  1454.          *  This is bad.  Should rework xdrrec_create to 
  1455.          *  return a handle, and in this case return NULL
  1456.          */
  1457.         return;
  1458.     }
  1459.     xdrs->x_ops = &xdrrec_ops;
  1460.     xdrs->x_private = (caddr_t)rstrm;
  1461.     rstrm->tcp_handle = tcp_handle;
  1462.     rstrm->readit = readit;
  1463.     rstrm->writeit = writeit;
  1464.     sendsize = fix_buf_size(sendsize);
  1465.     if ((rstrm->out_base = rstrm->out_finger = rstrm->out_boundry =
  1466.         mem_alloc(sendsize)) == NULL) {
  1467.         fprintf(stderr, "xdrrec_create: out of memory\n");
  1468.         return;
  1469.     }
  1470.     rstrm->frag_header = (u_long *)rstrm->out_base;
  1471.     rstrm->out_finger += sizeof(u_long);
  1472.     rstrm->out_boundry += sendsize;
  1473.     rstrm->frag_sent = FALSE;
  1474.     rstrm->in_size = recvsize = fix_buf_size(recvsize);
  1475.     if ((rstrm->in_base = rstrm->in_boundry=mem_alloc(recvsize)) == NULL) {
  1476.         fprintf(stderr, "xdrrec_create: out of memory\n");
  1477.         return;
  1478.     }
  1479.     rstrm->in_finger = (rstrm->in_boundry += recvsize);
  1480.     rstrm->fbtbc = 0;
  1481.     rstrm->last_frag = TRUE;
  1482.     rstrm->sendsize = sendsize;
  1483.     rstrm->recvsize = recvsize;
  1484. }
  1485.  
  1486.  
  1487. /*
  1488.  * The reoutines defined below are the xdr ops which will go into the
  1489.  * xdr handle filled in by xdrrec_create.
  1490.  */
  1491.  
  1492. static bool_t
  1493. xdrrec_getlong(xdrs, lp)
  1494.     XDR *xdrs;
  1495.     long *lp;
  1496. {
  1497.     register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
  1498.     register long *buflp = (long *)(rstrm->in_finger);
  1499.     long mylong;
  1500.  
  1501.     /* first try the inline, fast case */
  1502.     if ((rstrm->fbtbc >= sizeof(long)) &&
  1503.         (((int)rstrm->in_boundry - (int)buflp) >= sizeof(long))) {
  1504.         *lp = ntohl(*buflp);
  1505.         rstrm->fbtbc -= sizeof(long);
  1506.         rstrm->in_finger += sizeof(long);
  1507.     } else {
  1508.         if (! xdrrec_getbytes(xdrs, (caddr_t)&mylong, sizeof(long)))
  1509.             return (FALSE);
  1510.         *lp = ntohl(mylong);
  1511.     }
  1512.     return (TRUE);
  1513. }
  1514.  
  1515. static bool_t
  1516. xdrrec_putlong(xdrs, lp)
  1517.     XDR *xdrs;
  1518.     long *lp;
  1519. {
  1520.     register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
  1521.     register long *dest_lp = ((long *)(rstrm->out_finger));
  1522.  
  1523.     if ((rstrm->out_finger += sizeof(long)) > rstrm->out_boundry) {
  1524.         /*
  1525.          * this case should almost never happen so the code is
  1526.          * inefficient
  1527.          */
  1528.         rstrm->out_finger -= sizeof(long);
  1529.         rstrm->frag_sent = TRUE;
  1530.         if (! flush_out(rstrm, FALSE))
  1531.             return (FALSE);
  1532.         dest_lp = ((long *)(rstrm->out_finger));
  1533.         rstrm->out_finger += sizeof(long);
  1534.     }
  1535.     *dest_lp = htonl(*lp);
  1536.     return (TRUE);
  1537. }
  1538.  
  1539. static bool_t  /* must manage buffers, fragments, and records */
  1540. xdrrec_getbytes(xdrs, addr, len)
  1541.     XDR *xdrs;
  1542.     register caddr_t addr;
  1543.     register u_int len;
  1544. {
  1545.     register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
  1546.     register int current;
  1547.  
  1548.     while (len > 0) {
  1549.         current = rstrm->fbtbc;
  1550.         if (current == 0) {
  1551.             if (rstrm->last_frag)
  1552.                 return (FALSE);
  1553.             if (! set_input_fragment(rstrm))
  1554.                 return (FALSE);
  1555.             continue;
  1556.         }
  1557.         current = (len < current) ? len : current;
  1558.         if (! get_input_bytes(rstrm, addr, current))
  1559.             return (FALSE);
  1560.         addr += current; 
  1561.         rstrm->fbtbc -= current;
  1562.         len -= current;
  1563.     }
  1564.     return (TRUE);
  1565. }
  1566.  
  1567. static bool_t
  1568. xdrrec_putbytes(xdrs, addr, len)
  1569.     XDR *xdrs;
  1570.     register caddr_t addr;
  1571.     register u_int len;
  1572. {
  1573.     register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
  1574.     register int current;
  1575.  
  1576.     while (len > 0) {
  1577.         current = (u_int)rstrm->out_boundry - (u_int)rstrm->out_finger;
  1578.         current = (len < current) ? len : current;
  1579.         bcopy(addr, rstrm->out_finger, current);
  1580.         rstrm->out_finger += current;
  1581.         addr += current;
  1582.         len -= current;
  1583.         if (rstrm->out_finger == rstrm->out_boundry) {
  1584.             rstrm->frag_sent = TRUE;
  1585.             if (! flush_out(rstrm, FALSE))
  1586.                 return (FALSE);
  1587.         }
  1588.     }
  1589.     return (TRUE);
  1590. }
  1591.  
  1592. static u_int
  1593. xdrrec_getpos(xdrs)
  1594.     register XDR *xdrs;
  1595. {
  1596.     register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
  1597.     register u_int pos;
  1598.  
  1599.     pos = lseek((int)rstrm->tcp_handle, 0, 1);
  1600.     if ((int)pos != -1)
  1601.         switch (xdrs->x_op) {
  1602.  
  1603.         case XDR_ENCODE:
  1604.             pos += rstrm->out_finger - rstrm->out_base;
  1605.             break;
  1606.  
  1607.         case XDR_DECODE:
  1608.             pos -= rstrm->in_boundry - rstrm->in_finger;
  1609.             break;
  1610.  
  1611.         default:
  1612.             pos = (u_int) -1;
  1613.             break;
  1614.         }
  1615.     return (pos);
  1616. }
  1617.  
  1618. static bool_t
  1619. xdrrec_setpos(xdrs, pos)
  1620.     register XDR *xdrs;
  1621.     u_int pos;
  1622. {
  1623.     register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
  1624.     u_int currpos = xdrrec_getpos(xdrs);
  1625.     int delta = currpos - pos;
  1626.     caddr_t newpos;
  1627.  
  1628.     if ((int)currpos != -1)
  1629.         switch (xdrs->x_op) {
  1630.  
  1631.         case XDR_ENCODE:
  1632.             newpos = rstrm->out_finger - delta;
  1633.             if ((newpos > (caddr_t)(rstrm->frag_header)) &&
  1634.                 (newpos < rstrm->out_boundry)) {
  1635.                 rstrm->out_finger = newpos;
  1636.                 return (TRUE);
  1637.             }
  1638.             break;
  1639.  
  1640.         case XDR_DECODE:
  1641.             newpos = rstrm->in_finger - delta;
  1642.             if ((delta < (int)(rstrm->fbtbc)) &&
  1643.                 (newpos <= rstrm->in_boundry) &&
  1644.                 (newpos >= rstrm->in_base)) {
  1645.                 rstrm->in_finger = newpos;
  1646.                 rstrm->fbtbc -= delta;
  1647.                 return (TRUE);
  1648.             }
  1649.             break;
  1650.         }
  1651.     return (FALSE);
  1652. }
  1653.  
  1654. static long *
  1655. xdrrec_inline(xdrs, len)
  1656.     register XDR *xdrs;
  1657.     int len;
  1658. {
  1659.     register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
  1660.     long * buf = NULL;
  1661.  
  1662.     switch (xdrs->x_op) {
  1663.  
  1664.     case XDR_ENCODE:
  1665.         if ((rstrm->out_finger + len) <= rstrm->out_boundry) {
  1666.             buf = (long *) rstrm->out_finger;
  1667.             rstrm->out_finger += len;
  1668.         }
  1669.         break;
  1670.  
  1671.     case XDR_DECODE:
  1672.         if ((len <= rstrm->fbtbc) &&
  1673.             ((rstrm->in_finger + len) <= rstrm->in_boundry)) {
  1674.             buf = (long *) rstrm->in_finger;
  1675.             rstrm->fbtbc -= len;
  1676.             rstrm->in_finger += len;
  1677.         }
  1678.         break;
  1679.     }
  1680.     return (buf);
  1681. }
  1682.  
  1683. static void
  1684. xdrrec_destroy(xdrs)
  1685.     register XDR *xdrs;
  1686. {
  1687.     register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
  1688.  
  1689.     mem_free(rstrm->out_base, rstrm->sendsize);
  1690.     mem_free(rstrm->in_base, rstrm->recvsize);
  1691.     mem_free((caddr_t)rstrm, sizeof(RECSTREAM));
  1692. }
  1693.  
  1694.  
  1695. /*
  1696.  * Exported routines to manage xdr records
  1697.  */
  1698.  
  1699. /*
  1700.  * Before reading (deserializing from the stream, one should always call
  1701.  * this procedure to guarantee proper record alignment.
  1702.  */
  1703. bool_t
  1704. xdrrec_skiprecord(xdrs)
  1705.     XDR *xdrs;
  1706. {
  1707.     register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
  1708.  
  1709.     while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
  1710.         if (! skip_input_bytes(rstrm, rstrm->fbtbc))
  1711.             return (FALSE);
  1712.         rstrm->fbtbc = 0;
  1713.         if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
  1714.             return (FALSE);
  1715.     }
  1716.     rstrm->last_frag = FALSE;
  1717.     return (TRUE);
  1718. }
  1719.  
  1720. /*
  1721.  * Look ahead fuction.
  1722.  * Returns TRUE iff there is no more input in the buffer 
  1723.  * after consuming the rest of the current record.
  1724.  */
  1725. bool_t
  1726. xdrrec_eof(xdrs)
  1727.     XDR *xdrs;
  1728. {
  1729.     register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
  1730.  
  1731.     while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
  1732.         if (! skip_input_bytes(rstrm, rstrm->fbtbc))
  1733.             return (TRUE);
  1734.         rstrm->fbtbc = 0;
  1735.         if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
  1736.             return (TRUE);
  1737.     }
  1738.     if (rstrm->in_finger == rstrm->in_boundry)
  1739.         return (TRUE);
  1740.     return (FALSE);
  1741. }
  1742.  
  1743. /*
  1744.  * The client must tell the package when an end-of-record has occurred.
  1745.  * The second paraemters tells whether the record should be flushed to the
  1746.  * (output) tcp stream.  (This let's the package support batched or
  1747.  * pipelined procedure calls.)  TRUE => immmediate flush to tcp connection.
  1748.  */
  1749. bool_t
  1750. xdrrec_endofrecord(xdrs, sendnow)
  1751.     XDR *xdrs;
  1752.     bool_t sendnow;
  1753. {
  1754.     register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
  1755.     register u_long len;  /* fragment length */
  1756.  
  1757.     if (sendnow || rstrm->frag_sent ||
  1758.         ((u_long)rstrm->out_finger + sizeof(u_long) >=
  1759.         (u_long)rstrm->out_boundry)) {
  1760.         rstrm->frag_sent = FALSE;
  1761.         return (flush_out(rstrm, TRUE));
  1762.     }
  1763.     len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) -
  1764.        sizeof(u_long);
  1765.     *(rstrm->frag_header) = htonl(len | LAST_FRAG);
  1766.     rstrm->frag_header = (u_long *)rstrm->out_finger;
  1767.     rstrm->out_finger += sizeof(u_long);
  1768.     return (TRUE);
  1769. }
  1770.  
  1771.  
  1772. /*
  1773.  * Internal useful routines
  1774.  */
  1775. static bool_t
  1776. flush_out(rstrm, eor)
  1777.     register RECSTREAM *rstrm;
  1778.     bool_t eor;
  1779. {
  1780.     register u_long eormask = (eor == TRUE) ? LAST_FRAG : 0;
  1781.     register u_long len = (u_long)(rstrm->out_finger) - 
  1782.         (u_long)(rstrm->frag_header) - sizeof(u_long);
  1783.  
  1784.     *(rstrm->frag_header) = htonl(len | eormask);
  1785.     len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->out_base);
  1786.     if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len)
  1787.         != (int)len)
  1788.         return (FALSE);
  1789.     rstrm->frag_header = (u_long *)rstrm->out_base;
  1790.     rstrm->out_finger = (caddr_t)rstrm->out_base + sizeof(u_long);
  1791.     return (TRUE);
  1792. }
  1793.  
  1794. static bool_t  /* knows nothing about records!  Only about input buffers */
  1795. fill_input_buf(rstrm)
  1796.     register RECSTREAM *rstrm;
  1797. {
  1798.     register caddr_t where = rstrm->in_base;
  1799.     register int len = rstrm->in_size;
  1800.  
  1801.     if (((int)rstrm->in_boundry % 2) != 0) {
  1802.         /* keep stream odd bytes aligned with memory odd bytes */
  1803.         where++;
  1804.         len--;
  1805.     }
  1806.     if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1)
  1807.         return (FALSE);
  1808.     rstrm->in_finger = where;
  1809.     where += len;
  1810.     rstrm->in_boundry = where;
  1811.     return (TRUE);
  1812. }
  1813.  
  1814. static bool_t  /* knows nothing about records!  Only about input buffers */
  1815. get_input_bytes(rstrm, addr, len)
  1816.     register RECSTREAM *rstrm;
  1817.     register caddr_t addr;
  1818.     register int len;
  1819. {
  1820.     register int current;
  1821.  
  1822.     while (len > 0) {
  1823.         current = (int)rstrm->in_boundry - (int)rstrm->in_finger;
  1824.         if (current == 0) {
  1825.             if (! fill_input_buf(rstrm))
  1826.                 return (FALSE);
  1827.             continue;
  1828.         }
  1829.         current = (len < current) ? len : current;
  1830.         bcopy(rstrm->in_finger, addr, current);
  1831.         rstrm->in_finger += current;
  1832.         addr += current;
  1833.         len -= current;
  1834.     }
  1835.     return (TRUE);
  1836. }
  1837.  
  1838. static bool_t  /* next two bytes of the input stream are treated as a header */
  1839. set_input_fragment(rstrm)
  1840.     register RECSTREAM *rstrm;
  1841. {
  1842.     u_long header;
  1843.  
  1844.     if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header)))
  1845.         return (FALSE);
  1846.     header = ntohl(header);
  1847.     rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
  1848.     rstrm->fbtbc = header & (~LAST_FRAG);
  1849.     return (TRUE);
  1850. }
  1851.  
  1852. static bool_t  /* consumes input bytes; knows nothing about records! */
  1853. skip_input_bytes(rstrm, cnt)
  1854.     register RECSTREAM *rstrm;
  1855.     int cnt;
  1856. {
  1857.     register int current;
  1858.  
  1859.     while (cnt > 0) {
  1860.         current = (int)rstrm->in_boundry - (int)rstrm->in_finger;
  1861.         if (current == 0) {
  1862.             if (! fill_input_buf(rstrm))
  1863.                 return (FALSE);
  1864.             continue;
  1865.         }
  1866.         current = (cnt < current) ? cnt : current;
  1867.         rstrm->in_finger += current;
  1868.         cnt -= current;
  1869.     }
  1870.     return (TRUE);
  1871. }
  1872.  
  1873. static u_int
  1874. fix_buf_size(s)
  1875.     register u_int s;
  1876. {
  1877.  
  1878.     if (s < 100)
  1879.         return (3998);
  1880.     for (; (s % 4) != 2; --s);
  1881.     return (s);
  1882. }
  1883. !Funky!Stuff!
  1884. echo x - xdr_reference.c
  1885. sed 's/^X//' >xdr_reference.c <<'!Funky!Stuff!'
  1886. /*
  1887.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  1888.  * unrestricted use provided that this legend is included on all tape
  1889.  * media and as a part of the software program in whole or part.  Users
  1890.  * may copy or modify Sun RPC without charge, but are not authorized
  1891.  * to license or distribute it to anyone else except as part of a product or
  1892.  * program developed by the user.
  1893.  * 
  1894.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  1895.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  1896.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  1897.  * 
  1898.  * Sun RPC is provided with no support and without any obligation on the
  1899.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  1900.  * modification or enhancement.
  1901.  * 
  1902.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  1903.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  1904.  * OR ANY PART THEREOF.
  1905.  * 
  1906.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  1907.  * or profits or other special, indirect and consequential damages, even if
  1908.  * Sun has been advised of the possibility of such damages.
  1909.  * 
  1910.  * Sun Microsystems, Inc.
  1911.  * 2550 Garcia Avenue
  1912.  * Mountain View, California  94043
  1913.  */
  1914. #ifndef lint
  1915. static char sccsid[] = "@(#)xdr_reference.c 1.2 85/02/26 Copyr 1984 Sun Micro";
  1916. #endif
  1917.  
  1918. /*
  1919.  * xdr_reference.c, Generic XDR routines impelmentation.
  1920.  *
  1921.  * Copyright (C) 1984, Sun Microsystems, Inc.
  1922.  *
  1923.  * These are the "non-trivial" xdr primitives used to serialize and de-serialize
  1924.  * "pointers".  See xdr.h for more info on the interface to xdr.
  1925.  */
  1926.  
  1927. #include "types.h"
  1928. #include "xdr.h"
  1929. #include <stdio.h>
  1930. #define LASTUNSIGNED    ((u_int)0-1)
  1931.  
  1932. char *mem_alloc();
  1933.  
  1934. /*
  1935.  * XDR an indirect pointer
  1936.  * xdr_reference is for recursively translating a structure that is
  1937.  * referenced by a pointer inside the structure that is currently being
  1938.  * translated.  pp references a pointer to storage. If *pp is null
  1939.  * the  necessary storage is allocated.
  1940.  * size is the sizeof the referneced structure.
  1941.  * proc is the routine to handle the referenced structure.
  1942.  */
  1943. bool_t
  1944. xdr_reference(xdrs, pp, size, proc)
  1945.     register XDR *xdrs;
  1946.     caddr_t *pp;        /* the pointer to work on */
  1947.     u_int size;        /* size of the object pointed to */
  1948.     xdrproc_t proc;        /* xdr routine to handle the object */
  1949. {
  1950.     register caddr_t loc = *pp;
  1951.     register bool_t stat;
  1952.  
  1953.     if (loc == NULL)
  1954.         switch (xdrs->x_op) {
  1955.         case XDR_FREE:
  1956.             return (TRUE);
  1957.  
  1958.         case XDR_DECODE:
  1959.             *pp = loc = mem_alloc(size);
  1960.             if (loc == NULL) {
  1961.                 fprintf(stderr,
  1962.                     "xdr_reference: out of memory\n");
  1963.                 return (FALSE);
  1964.             }
  1965.             bzero(loc, (int)size);
  1966.             break;
  1967.     }
  1968.  
  1969.     stat = (*proc)(xdrs, loc, LASTUNSIGNED);
  1970.  
  1971.     if (xdrs->x_op == XDR_FREE) {
  1972.         mem_free(loc, size);
  1973.         *pp = NULL;
  1974.     }
  1975.     return (stat);
  1976. }
  1977. !Funky!Stuff!
  1978. echo x - xdr_stdio.c
  1979. sed 's/^X//' >xdr_stdio.c <<'!Funky!Stuff!'
  1980. /*
  1981.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  1982.  * unrestricted use provided that this legend is included on all tape
  1983.  * media and as a part of the software program in whole or part.  Users
  1984.  * may copy or modify Sun RPC without charge, but are not authorized
  1985.  * to license or distribute it to anyone else except as part of a product or
  1986.  * program developed by the user.
  1987.  * 
  1988.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  1989.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  1990.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  1991.  * 
  1992.  * Sun RPC is provided with no support and without any obligation on the
  1993.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  1994.  * modification or enhancement.
  1995.  * 
  1996.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  1997.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  1998.  * OR ANY PART THEREOF.
  1999.  * 
  2000.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  2001.  * or profits or other special, indirect and consequential damages, even if
  2002.  * Sun has been advised of the possibility of such damages.
  2003.  * 
  2004.  * Sun Microsystems, Inc.
  2005.  * 2550 Garcia Avenue
  2006.  * Mountain View, California  94043
  2007.  */
  2008. #ifndef lint
  2009. static char sccsid[] = "@(#)xdr_stdio.c 1.4 85/03/14 Copyr 1984 Sun Micro";
  2010. #endif
  2011.  
  2012. /*
  2013.  * xdr_stdio.c, XDR implementation on standard i/o file.
  2014.  *
  2015.  * Copyright (C) 1984, Sun Microsystems, Inc.
  2016.  *
  2017.  * This set of routines implements a XDR on a stdio stream.
  2018.  * XDR_ENCODE serializes onto the stream, XDR_DECODE de-serializes
  2019.  * from the stream.
  2020.  */
  2021.  
  2022. #include "types.h"
  2023. #include <stdio.h>
  2024. #include "xdr.h"
  2025.  
  2026. static bool_t    xdrstdio_getlong();
  2027. static bool_t    xdrstdio_putlong();
  2028. static bool_t    xdrstdio_getbytes();
  2029. static bool_t    xdrstdio_putbytes();
  2030. static u_int    xdrstdio_getpos();
  2031. static bool_t    xdrstdio_setpos();
  2032. static long *    xdrstdio_inline();
  2033. static void    xdrstdio_destroy();
  2034.  
  2035. /*
  2036.  * Ops vector for stdio type XDR
  2037.  */
  2038. static struct xdr_ops    xdrstdio_ops = {
  2039.     xdrstdio_getlong,    /* deseraialize a long int */
  2040.     xdrstdio_putlong,    /* seraialize a long int */
  2041.     xdrstdio_getbytes,    /* deserialize counted bytes */
  2042.     xdrstdio_putbytes,    /* serialize counted bytes */
  2043.     xdrstdio_getpos,    /* get offset in the stream */
  2044.     xdrstdio_setpos,    /* set offset in the stream */
  2045.     xdrstdio_inline,    /* prime stream for inline macros */
  2046.     xdrstdio_destroy    /* destroy stream */
  2047. };
  2048.  
  2049. /*
  2050.  * Initialize a stdio xdr stream.
  2051.  * Sets the xdr stream handle xdrs for use on the stream file.
  2052.  * Operation flag is set to op.
  2053.  */
  2054. void
  2055. xdrstdio_create(xdrs, file, op)
  2056.     register XDR *xdrs;
  2057.     FILE *file;
  2058.     enum xdr_op op;
  2059. {
  2060.  
  2061.     xdrs->x_op = op;
  2062.     xdrs->x_ops = &xdrstdio_ops;
  2063.     xdrs->x_private = (caddr_t)file;
  2064.     xdrs->x_handy = 0;
  2065.     xdrs->x_base = 0;
  2066. }
  2067.  
  2068. /*
  2069.  * Destroy a stdio xdr stream.
  2070.  * Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create.
  2071.  */
  2072. static void
  2073. xdrstdio_destroy(xdrs)
  2074.     register XDR *xdrs;
  2075. {
  2076.     (void)fflush((FILE *)xdrs->x_private);
  2077.     /* xx should we close the file ?? */
  2078. };
  2079.  
  2080. static bool_t
  2081. xdrstdio_getlong(xdrs, lp)
  2082.     XDR *xdrs;
  2083.     register long *lp;
  2084. {
  2085.  
  2086.     if (fread((caddr_t)lp, sizeof(long), 1, (FILE *)xdrs->x_private) != 1)
  2087.         return (FALSE);
  2088. #ifndef mc68000
  2089.     *lp = ntohl(*lp);
  2090. #endif
  2091.     return (TRUE);
  2092. }
  2093.  
  2094. static bool_t
  2095. xdrstdio_putlong(xdrs, lp)
  2096.     XDR *xdrs;
  2097.     long *lp;
  2098. {
  2099.  
  2100. #ifndef mc68000
  2101.     long mycopy = htonl(*lp);
  2102.     lp = &mycopy;
  2103. #endif
  2104.     if (fwrite((caddr_t)lp, sizeof(long), 1, (FILE *)xdrs->x_private) != 1)
  2105.         return (FALSE);
  2106.     return (TRUE);
  2107. }
  2108.  
  2109. static bool_t
  2110. xdrstdio_getbytes(xdrs, addr, len)
  2111.     XDR *xdrs;
  2112.     caddr_t addr;
  2113.     u_int len;
  2114. {
  2115.  
  2116.     if ((len != 0) && (fread(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1))
  2117.         return (FALSE);
  2118.     return (TRUE);
  2119. }
  2120.  
  2121. static bool_t
  2122. xdrstdio_putbytes(xdrs, addr, len)
  2123.     XDR *xdrs;
  2124.     caddr_t addr;
  2125.     u_int len;
  2126. {
  2127.  
  2128.     if ((len != 0) && (fwrite(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1))
  2129.         return (FALSE);
  2130.     return (TRUE);
  2131. }
  2132.  
  2133. static u_int
  2134. xdrstdio_getpos(xdrs)
  2135.     XDR *xdrs;
  2136. {
  2137.  
  2138.     return ((u_int) ftell((FILE *)xdrs->x_private));
  2139. }
  2140.  
  2141. static bool_t
  2142. xdrstdio_setpos(xdrs, pos) 
  2143.     XDR *xdrs;
  2144.     u_int pos;
  2145.  
  2146.     return ((fseek((FILE *)xdrs->x_private, (long)pos, 0) < 0) ?
  2147.         FALSE : TRUE);
  2148. }
  2149.  
  2150. static long *
  2151. xdrstdio_inline(xdrs, len)
  2152.     XDR *xdrs;
  2153.     u_int len;
  2154. {
  2155.  
  2156.     /*
  2157.      * Must do some work to implement this: must insure
  2158.      * enough data in the underlying stdio buffer,
  2159.      * that the buffer is aligned so that we can indirect through a
  2160.      * long *, and stuff this pointer in xdrs->x_buf.  Doing
  2161.      * a fread or fwrite to a scratch buffer would defeat
  2162.      * most of the gains to be had here and require storage
  2163.      * management on this buffer, so we don't do this.
  2164.      */
  2165.     return (NULL);
  2166. }
  2167. !Funky!Stuff!
  2168.  
  2169. exit
  2170.