145098Smckusick /* @(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC */
245098Smckusick /*
345098Smckusick * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
445098Smckusick * unrestricted use provided that this legend is included on all tape
545098Smckusick * media and as a part of the software program in whole or part. Users
645098Smckusick * may copy or modify Sun RPC without charge, but are not authorized
745098Smckusick * to license or distribute it to anyone else except as part of a product or
845098Smckusick * program developed by the user.
945098Smckusick *
1045098Smckusick * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
1145098Smckusick * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
1245098Smckusick * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
1345098Smckusick *
1445098Smckusick * Sun RPC is provided with no support and without any obligation on the
1545098Smckusick * part of Sun Microsystems, Inc. to assist in its use, correction,
1645098Smckusick * modification or enhancement.
1745098Smckusick *
1845098Smckusick * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
1945098Smckusick * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
2045098Smckusick * OR ANY PART THEREOF.
2145098Smckusick *
2245098Smckusick * In no event will Sun Microsystems, Inc. be liable for any lost revenue
2345098Smckusick * or profits or other special, indirect and consequential damages, even if
2445098Smckusick * Sun has been advised of the possibility of such damages.
2545098Smckusick *
2645098Smckusick * Sun Microsystems, Inc.
2745098Smckusick * 2550 Garcia Avenue
2845098Smckusick * Mountain View, California 94043
2945098Smckusick */
3045098Smckusick #if !defined(lint) && defined(SCCSIDS)
3145098Smckusick static char sccsid[] = "@(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";
3245098Smckusick #endif
3345098Smckusick
3445098Smckusick /*
3545098Smckusick * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking"
3645098Smckusick * layer above tcp (for rpc's use).
3745098Smckusick *
3845098Smckusick * Copyright (C) 1984, Sun Microsystems, Inc.
3945098Smckusick *
4045098Smckusick * These routines interface XDRSTREAMS to a tcp/ip connection.
4145098Smckusick * There is a record marking layer between the xdr stream
4245098Smckusick * and the tcp transport level. A record is composed on one or more
4345098Smckusick * record fragments. A record fragment is a thirty-two bit header followed
4445098Smckusick * by n bytes of data, where n is contained in the header. The header
4545098Smckusick * is represented as a htonl(u_long). Thegh order bit encodes
4645098Smckusick * whether or not the fragment is the last fragment of the record
4745098Smckusick * (1 => fragment is last, 0 => more fragments to follow.
4845098Smckusick * The other 31 bits encode the byte length of the fragment.
4945098Smckusick */
5045098Smckusick
5145098Smckusick #include <stdio.h>
5245098Smckusick #include <rpc/types.h>
5345098Smckusick #include <rpc/xdr.h>
5445098Smckusick #include <netinet/in.h>
55*59711Storek #include <unistd.h>
5645098Smckusick
5745098Smckusick static u_int fix_buf_size();
5846639Sbostic static bool_t flush_out();
5946639Sbostic static bool_t get_input_bytes();
6046639Sbostic static bool_t set_input_fragment();
6146639Sbostic static bool_t skip_input_bytes();
6245098Smckusick
6345098Smckusick static bool_t xdrrec_getlong();
6445098Smckusick static bool_t xdrrec_putlong();
6545098Smckusick static bool_t xdrrec_getbytes();
6645098Smckusick static bool_t xdrrec_putbytes();
6745098Smckusick static u_int xdrrec_getpos();
6845098Smckusick static bool_t xdrrec_setpos();
6945098Smckusick static long * xdrrec_inline();
7045098Smckusick static void xdrrec_destroy();
7145098Smckusick
7245098Smckusick static struct xdr_ops xdrrec_ops = {
7345098Smckusick xdrrec_getlong,
7445098Smckusick xdrrec_putlong,
7545098Smckusick xdrrec_getbytes,
7645098Smckusick xdrrec_putbytes,
7745098Smckusick xdrrec_getpos,
7845098Smckusick xdrrec_setpos,
7945098Smckusick xdrrec_inline,
8045098Smckusick xdrrec_destroy
8145098Smckusick };
8245098Smckusick
8345098Smckusick /*
8445098Smckusick * A record is composed of one or more record fragments.
8545098Smckusick * A record fragment is a two-byte header followed by zero to
8645098Smckusick * 2**32-1 bytes. The header is treated as a long unsigned and is
8745098Smckusick * encode/decoded to the network via htonl/ntohl. The low order 31 bits
8845098Smckusick * are a byte count of the fragment. The highest order bit is a boolean:
8945098Smckusick * 1 => this fragment is the last fragment of the record,
9045098Smckusick * 0 => this fragment is followed by more fragment(s).
9145098Smckusick *
9245098Smckusick * The fragment/record machinery is not general; it is constructed to
9345098Smckusick * meet the needs of xdr and rpc based on tcp.
9445098Smckusick */
9545098Smckusick
9645098Smckusick #define LAST_FRAG ((u_long)(1 << 31))
9745098Smckusick
9845098Smckusick typedef struct rec_strm {
9945098Smckusick caddr_t tcp_handle;
10045098Smckusick caddr_t the_buffer;
10145098Smckusick /*
10245098Smckusick * out-goung bits
10345098Smckusick */
10445098Smckusick int (*writeit)();
10545098Smckusick caddr_t out_base; /* output buffer (points to frag header) */
10645098Smckusick caddr_t out_finger; /* next output position */
10745098Smckusick caddr_t out_boundry; /* data cannot up to this address */
10845098Smckusick u_long *frag_header; /* beginning of curren fragment */
10945098Smckusick bool_t frag_sent; /* true if buffer sent in middle of record */
11045098Smckusick /*
11145098Smckusick * in-coming bits
11245098Smckusick */
11345098Smckusick int (*readit)();
11445098Smckusick u_long in_size; /* fixed size of the input buffer */
11545098Smckusick caddr_t in_base;
11645098Smckusick caddr_t in_finger; /* location of next byte to be had */
11745098Smckusick caddr_t in_boundry; /* can read up to this location */
11845098Smckusick long fbtbc; /* fragment bytes to be consumed */
11945098Smckusick bool_t last_frag;
12045098Smckusick u_int sendsize;
12145098Smckusick u_int recvsize;
12245098Smckusick } RECSTREAM;
12345098Smckusick
12445098Smckusick
12545098Smckusick /*
12645098Smckusick * Create an xdr handle for xdrrec
12745098Smckusick * xdrrec_create fills in xdrs. Sendsize and recvsize are
12845098Smckusick * send and recv buffer sizes (0 => use default).
12945098Smckusick * tcp_handle is an opaque handle that is passed as the first parameter to
13045098Smckusick * the procedures readit and writeit. Readit and writeit are read and
13145098Smckusick * write respectively. They are like the system
13245098Smckusick * calls expect that they take an opaque handle rather than an fd.
13345098Smckusick */
13445098Smckusick void
xdrrec_create(xdrs,sendsize,recvsize,tcp_handle,readit,writeit)13545098Smckusick xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit)
13645098Smckusick register XDR *xdrs;
13745098Smckusick register u_int sendsize;
13845098Smckusick register u_int recvsize;
13945098Smckusick caddr_t tcp_handle;
14045098Smckusick int (*readit)(); /* like read, but pass it a tcp_handle, not sock */
14145098Smckusick int (*writeit)(); /* like write, but pass it a tcp_handle, not sock */
14245098Smckusick {
14345098Smckusick register RECSTREAM *rstrm =
14445098Smckusick (RECSTREAM *)mem_alloc(sizeof(RECSTREAM));
14545098Smckusick
14645098Smckusick if (rstrm == NULL) {
14745098Smckusick (void)fprintf(stderr, "xdrrec_create: out of memory\n");
14845098Smckusick /*
14945098Smckusick * This is bad. Should rework xdrrec_create to
15045098Smckusick * return a handle, and in this case return NULL
15145098Smckusick */
15245098Smckusick return;
15345098Smckusick }
15445098Smckusick /*
15545098Smckusick * adjust sizes and allocate buffer quad byte aligned
15645098Smckusick */
15745098Smckusick rstrm->sendsize = sendsize = fix_buf_size(sendsize);
15845098Smckusick rstrm->recvsize = recvsize = fix_buf_size(recvsize);
15945098Smckusick rstrm->the_buffer = mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT);
16045098Smckusick if (rstrm->the_buffer == NULL) {
16145098Smckusick (void)fprintf(stderr, "xdrrec_create: out of memory\n");
16245098Smckusick return;
16345098Smckusick }
16445098Smckusick for (rstrm->out_base = rstrm->the_buffer;
16545098Smckusick (u_int)rstrm->out_base % BYTES_PER_XDR_UNIT != 0;
16645098Smckusick rstrm->out_base++);
16745098Smckusick rstrm->in_base = rstrm->out_base + sendsize;
16845098Smckusick /*
16945098Smckusick * now the rest ...
17045098Smckusick */
17145098Smckusick xdrs->x_ops = &xdrrec_ops;
17245098Smckusick xdrs->x_private = (caddr_t)rstrm;
17345098Smckusick rstrm->tcp_handle = tcp_handle;
17445098Smckusick rstrm->readit = readit;
17545098Smckusick rstrm->writeit = writeit;
17645098Smckusick rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
17745098Smckusick rstrm->frag_header = (u_long *)rstrm->out_base;
17845098Smckusick rstrm->out_finger += sizeof(u_long);
17945098Smckusick rstrm->out_boundry += sendsize;
18045098Smckusick rstrm->frag_sent = FALSE;
18145098Smckusick rstrm->in_size = recvsize;
18245098Smckusick rstrm->in_boundry = rstrm->in_base;
18345098Smckusick rstrm->in_finger = (rstrm->in_boundry += recvsize);
18445098Smckusick rstrm->fbtbc = 0;
18545098Smckusick rstrm->last_frag = TRUE;
18645098Smckusick }
18745098Smckusick
18845098Smckusick
18945098Smckusick /*
19045098Smckusick * The reoutines defined below are the xdr ops which will go into the
19145098Smckusick * xdr handle filled in by xdrrec_create.
19245098Smckusick */
19345098Smckusick
19445098Smckusick static bool_t
xdrrec_getlong(xdrs,lp)19545098Smckusick xdrrec_getlong(xdrs, lp)
19645098Smckusick XDR *xdrs;
19745098Smckusick long *lp;
19845098Smckusick {
19945098Smckusick register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
20045098Smckusick register long *buflp = (long *)(rstrm->in_finger);
20145098Smckusick long mylong;
20245098Smckusick
20345098Smckusick /* first try the inline, fast case */
20445098Smckusick if ((rstrm->fbtbc >= sizeof(long)) &&
20545098Smckusick (((int)rstrm->in_boundry - (int)buflp) >= sizeof(long))) {
20645098Smckusick *lp = (long)ntohl((u_long)(*buflp));
20745098Smckusick rstrm->fbtbc -= sizeof(long);
20845098Smckusick rstrm->in_finger += sizeof(long);
20945098Smckusick } else {
21045098Smckusick if (! xdrrec_getbytes(xdrs, (caddr_t)&mylong, sizeof(long)))
21145098Smckusick return (FALSE);
21245098Smckusick *lp = (long)ntohl((u_long)mylong);
21345098Smckusick }
21445098Smckusick return (TRUE);
21545098Smckusick }
21645098Smckusick
21745098Smckusick static bool_t
xdrrec_putlong(xdrs,lp)21845098Smckusick xdrrec_putlong(xdrs, lp)
21945098Smckusick XDR *xdrs;
22045098Smckusick long *lp;
22145098Smckusick {
22245098Smckusick register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
22345098Smckusick register long *dest_lp = ((long *)(rstrm->out_finger));
22445098Smckusick
22545098Smckusick if ((rstrm->out_finger += sizeof(long)) > rstrm->out_boundry) {
22645098Smckusick /*
22745098Smckusick * this case should almost never happen so the code is
22845098Smckusick * inefficient
22945098Smckusick */
23045098Smckusick rstrm->out_finger -= sizeof(long);
23145098Smckusick rstrm->frag_sent = TRUE;
23245098Smckusick if (! flush_out(rstrm, FALSE))
23345098Smckusick return (FALSE);
23445098Smckusick dest_lp = ((long *)(rstrm->out_finger));
23545098Smckusick rstrm->out_finger += sizeof(long);
23645098Smckusick }
23745098Smckusick *dest_lp = (long)htonl((u_long)(*lp));
23845098Smckusick return (TRUE);
23945098Smckusick }
24045098Smckusick
24145098Smckusick static bool_t /* must manage buffers, fragments, and records */
xdrrec_getbytes(xdrs,addr,len)24245098Smckusick xdrrec_getbytes(xdrs, addr, len)
24345098Smckusick XDR *xdrs;
24445098Smckusick register caddr_t addr;
24545098Smckusick register u_int len;
24645098Smckusick {
24745098Smckusick register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
24845098Smckusick register int current;
24945098Smckusick
25045098Smckusick while (len > 0) {
25145098Smckusick current = rstrm->fbtbc;
25245098Smckusick if (current == 0) {
25345098Smckusick if (rstrm->last_frag)
25445098Smckusick return (FALSE);
25545098Smckusick if (! set_input_fragment(rstrm))
25645098Smckusick return (FALSE);
25745098Smckusick continue;
25845098Smckusick }
25945098Smckusick current = (len < current) ? len : current;
26045098Smckusick if (! get_input_bytes(rstrm, addr, current))
26145098Smckusick return (FALSE);
26245098Smckusick addr += current;
26345098Smckusick rstrm->fbtbc -= current;
26445098Smckusick len -= current;
26545098Smckusick }
26645098Smckusick return (TRUE);
26745098Smckusick }
26845098Smckusick
26945098Smckusick static bool_t
xdrrec_putbytes(xdrs,addr,len)27045098Smckusick xdrrec_putbytes(xdrs, addr, len)
27145098Smckusick XDR *xdrs;
27245098Smckusick register caddr_t addr;
27345098Smckusick register u_int len;
27445098Smckusick {
27545098Smckusick register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
27645098Smckusick register int current;
27745098Smckusick
27845098Smckusick while (len > 0) {
27945098Smckusick current = (u_int)rstrm->out_boundry - (u_int)rstrm->out_finger;
28045098Smckusick current = (len < current) ? len : current;
28145098Smckusick bcopy(addr, rstrm->out_finger, current);
28245098Smckusick rstrm->out_finger += current;
28345098Smckusick addr += current;
28445098Smckusick len -= current;
28545098Smckusick if (rstrm->out_finger == rstrm->out_boundry) {
28645098Smckusick rstrm->frag_sent = TRUE;
28745098Smckusick if (! flush_out(rstrm, FALSE))
28845098Smckusick return (FALSE);
28945098Smckusick }
29045098Smckusick }
29145098Smckusick return (TRUE);
29245098Smckusick }
29345098Smckusick
29445098Smckusick static u_int
xdrrec_getpos(xdrs)29545098Smckusick xdrrec_getpos(xdrs)
29645098Smckusick register XDR *xdrs;
29745098Smckusick {
29845098Smckusick register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
29945098Smckusick register long pos;
30045098Smckusick
30145098Smckusick pos = lseek((int)rstrm->tcp_handle, (long) 0, 1);
30245098Smckusick if (pos != -1)
30345098Smckusick switch (xdrs->x_op) {
30445098Smckusick
30545098Smckusick case XDR_ENCODE:
30645098Smckusick pos += rstrm->out_finger - rstrm->out_base;
30745098Smckusick break;
30845098Smckusick
30945098Smckusick case XDR_DECODE:
31045098Smckusick pos -= rstrm->in_boundry - rstrm->in_finger;
31145098Smckusick break;
31245098Smckusick
31345098Smckusick default:
31445098Smckusick pos = (u_int) -1;
31545098Smckusick break;
31645098Smckusick }
31745098Smckusick return ((u_int) pos);
31845098Smckusick }
31945098Smckusick
32045098Smckusick static bool_t
xdrrec_setpos(xdrs,pos)32145098Smckusick xdrrec_setpos(xdrs, pos)
32245098Smckusick register XDR *xdrs;
32345098Smckusick u_int pos;
32445098Smckusick {
32545098Smckusick register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
32645098Smckusick u_int currpos = xdrrec_getpos(xdrs);
32745098Smckusick int delta = currpos - pos;
32845098Smckusick caddr_t newpos;
32945098Smckusick
33045098Smckusick if ((int)currpos != -1)
33145098Smckusick switch (xdrs->x_op) {
33245098Smckusick
33345098Smckusick case XDR_ENCODE:
33445098Smckusick newpos = rstrm->out_finger - delta;
33545098Smckusick if ((newpos > (caddr_t)(rstrm->frag_header)) &&
33645098Smckusick (newpos < rstrm->out_boundry)) {
33745098Smckusick rstrm->out_finger = newpos;
33845098Smckusick return (TRUE);
33945098Smckusick }
34045098Smckusick break;
34145098Smckusick
34245098Smckusick case XDR_DECODE:
34345098Smckusick newpos = rstrm->in_finger - delta;
34445098Smckusick if ((delta < (int)(rstrm->fbtbc)) &&
34545098Smckusick (newpos <= rstrm->in_boundry) &&
34645098Smckusick (newpos >= rstrm->in_base)) {
34745098Smckusick rstrm->in_finger = newpos;
34845098Smckusick rstrm->fbtbc -= delta;
34945098Smckusick return (TRUE);
35045098Smckusick }
35145098Smckusick break;
35245098Smckusick }
35345098Smckusick return (FALSE);
35445098Smckusick }
35545098Smckusick
35645098Smckusick static long *
xdrrec_inline(xdrs,len)35745098Smckusick xdrrec_inline(xdrs, len)
35845098Smckusick register XDR *xdrs;
35945098Smckusick int len;
36045098Smckusick {
36145098Smckusick register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
36245098Smckusick long * buf = NULL;
36345098Smckusick
36445098Smckusick switch (xdrs->x_op) {
36545098Smckusick
36645098Smckusick case XDR_ENCODE:
36745098Smckusick if ((rstrm->out_finger + len) <= rstrm->out_boundry) {
36845098Smckusick buf = (long *) rstrm->out_finger;
36945098Smckusick rstrm->out_finger += len;
37045098Smckusick }
37145098Smckusick break;
37245098Smckusick
37345098Smckusick case XDR_DECODE:
37445098Smckusick if ((len <= rstrm->fbtbc) &&
37545098Smckusick ((rstrm->in_finger + len) <= rstrm->in_boundry)) {
37645098Smckusick buf = (long *) rstrm->in_finger;
37745098Smckusick rstrm->fbtbc -= len;
37845098Smckusick rstrm->in_finger += len;
37945098Smckusick }
38045098Smckusick break;
38145098Smckusick }
38245098Smckusick return (buf);
38345098Smckusick }
38445098Smckusick
38545098Smckusick static void
xdrrec_destroy(xdrs)38645098Smckusick xdrrec_destroy(xdrs)
38745098Smckusick register XDR *xdrs;
38845098Smckusick {
38945098Smckusick register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
39045098Smckusick
39145098Smckusick mem_free(rstrm->the_buffer,
39245098Smckusick rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT);
39345098Smckusick mem_free((caddr_t)rstrm, sizeof(RECSTREAM));
39445098Smckusick }
39545098Smckusick
39645098Smckusick
39745098Smckusick /*
39845098Smckusick * Exported routines to manage xdr records
39945098Smckusick */
40045098Smckusick
40145098Smckusick /*
40245098Smckusick * Before reading (deserializing from the stream, one should always call
40345098Smckusick * this procedure to guarantee proper record alignment.
40445098Smckusick */
40545098Smckusick bool_t
xdrrec_skiprecord(xdrs)40645098Smckusick xdrrec_skiprecord(xdrs)
40745098Smckusick XDR *xdrs;
40845098Smckusick {
40945098Smckusick register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
41045098Smckusick
41145098Smckusick while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
41245098Smckusick if (! skip_input_bytes(rstrm, rstrm->fbtbc))
41345098Smckusick return (FALSE);
41445098Smckusick rstrm->fbtbc = 0;
41545098Smckusick if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
41645098Smckusick return (FALSE);
41745098Smckusick }
41845098Smckusick rstrm->last_frag = FALSE;
41945098Smckusick return (TRUE);
42045098Smckusick }
42145098Smckusick
42245098Smckusick /*
42345098Smckusick * Look ahead fuction.
42445098Smckusick * Returns TRUE iff there is no more input in the buffer
42545098Smckusick * after consuming the rest of the current record.
42645098Smckusick */
42745098Smckusick bool_t
xdrrec_eof(xdrs)42845098Smckusick xdrrec_eof(xdrs)
42945098Smckusick XDR *xdrs;
43045098Smckusick {
43145098Smckusick register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
43245098Smckusick
43345098Smckusick while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
43445098Smckusick if (! skip_input_bytes(rstrm, rstrm->fbtbc))
43545098Smckusick return (TRUE);
43645098Smckusick rstrm->fbtbc = 0;
43745098Smckusick if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
43845098Smckusick return (TRUE);
43945098Smckusick }
44045098Smckusick if (rstrm->in_finger == rstrm->in_boundry)
44145098Smckusick return (TRUE);
44245098Smckusick return (FALSE);
44345098Smckusick }
44445098Smckusick
44545098Smckusick /*
44645098Smckusick * The client must tell the package when an end-of-record has occurred.
44745098Smckusick * The second paraemters tells whether the record should be flushed to the
44845098Smckusick * (output) tcp stream. (This let's the package support batched or
44945098Smckusick * pipelined procedure calls.) TRUE => immmediate flush to tcp connection.
45045098Smckusick */
45145098Smckusick bool_t
xdrrec_endofrecord(xdrs,sendnow)45245098Smckusick xdrrec_endofrecord(xdrs, sendnow)
45345098Smckusick XDR *xdrs;
45445098Smckusick bool_t sendnow;
45545098Smckusick {
45645098Smckusick register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
45745098Smckusick register u_long len; /* fragment length */
45845098Smckusick
45945098Smckusick if (sendnow || rstrm->frag_sent ||
46045098Smckusick ((u_long)rstrm->out_finger + sizeof(u_long) >=
46145098Smckusick (u_long)rstrm->out_boundry)) {
46245098Smckusick rstrm->frag_sent = FALSE;
46345098Smckusick return (flush_out(rstrm, TRUE));
46445098Smckusick }
46545098Smckusick len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) -
46645098Smckusick sizeof(u_long);
46745098Smckusick *(rstrm->frag_header) = htonl((u_long)len | LAST_FRAG);
46845098Smckusick rstrm->frag_header = (u_long *)rstrm->out_finger;
46945098Smckusick rstrm->out_finger += sizeof(u_long);
47045098Smckusick return (TRUE);
47145098Smckusick }
47245098Smckusick
47345098Smckusick
47445098Smckusick /*
47545098Smckusick * Internal useful routines
47645098Smckusick */
47745098Smckusick static bool_t
flush_out(rstrm,eor)47845098Smckusick flush_out(rstrm, eor)
47945098Smckusick register RECSTREAM *rstrm;
48045098Smckusick bool_t eor;
48145098Smckusick {
48245098Smckusick register u_long eormask = (eor == TRUE) ? LAST_FRAG : 0;
48345098Smckusick register u_long len = (u_long)(rstrm->out_finger) -
48445098Smckusick (u_long)(rstrm->frag_header) - sizeof(u_long);
48545098Smckusick
48645098Smckusick *(rstrm->frag_header) = htonl(len | eormask);
48745098Smckusick len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->out_base);
48845098Smckusick if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len)
48945098Smckusick != (int)len)
49045098Smckusick return (FALSE);
49145098Smckusick rstrm->frag_header = (u_long *)rstrm->out_base;
49245098Smckusick rstrm->out_finger = (caddr_t)rstrm->out_base + sizeof(u_long);
49345098Smckusick return (TRUE);
49445098Smckusick }
49545098Smckusick
49645098Smckusick static bool_t /* knows nothing about records! Only about input buffers */
fill_input_buf(rstrm)49745098Smckusick fill_input_buf(rstrm)
49845098Smckusick register RECSTREAM *rstrm;
49945098Smckusick {
50045098Smckusick register caddr_t where;
50145098Smckusick u_int i;
50245098Smckusick register int len;
50345098Smckusick
50445098Smckusick where = rstrm->in_base;
50545098Smckusick i = (u_int)rstrm->in_boundry % BYTES_PER_XDR_UNIT;
50645098Smckusick where += i;
50745098Smckusick len = rstrm->in_size - i;
50845098Smckusick if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1)
50945098Smckusick return (FALSE);
51045098Smckusick rstrm->in_finger = where;
51145098Smckusick where += len;
51245098Smckusick rstrm->in_boundry = where;
51345098Smckusick return (TRUE);
51445098Smckusick }
51545098Smckusick
51645098Smckusick static bool_t /* knows nothing about records! Only about input buffers */
get_input_bytes(rstrm,addr,len)51745098Smckusick get_input_bytes(rstrm, addr, len)
51845098Smckusick register RECSTREAM *rstrm;
51945098Smckusick register caddr_t addr;
52045098Smckusick register int len;
52145098Smckusick {
52245098Smckusick register int current;
52345098Smckusick
52445098Smckusick while (len > 0) {
52545098Smckusick current = (int)rstrm->in_boundry - (int)rstrm->in_finger;
52645098Smckusick if (current == 0) {
52745098Smckusick if (! fill_input_buf(rstrm))
52845098Smckusick return (FALSE);
52945098Smckusick continue;
53045098Smckusick }
53145098Smckusick current = (len < current) ? len : current;
53245098Smckusick bcopy(rstrm->in_finger, addr, current);
53345098Smckusick rstrm->in_finger += current;
53445098Smckusick addr += current;
53545098Smckusick len -= current;
53645098Smckusick }
53745098Smckusick return (TRUE);
53845098Smckusick }
53945098Smckusick
54045098Smckusick static bool_t /* next two bytes of the input stream are treated as a header */
set_input_fragment(rstrm)54145098Smckusick set_input_fragment(rstrm)
54245098Smckusick register RECSTREAM *rstrm;
54345098Smckusick {
54445098Smckusick u_long header;
54545098Smckusick
54645098Smckusick if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header)))
54745098Smckusick return (FALSE);
54845098Smckusick header = (long)ntohl(header);
54945098Smckusick rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
55045098Smckusick rstrm->fbtbc = header & (~LAST_FRAG);
55145098Smckusick return (TRUE);
55245098Smckusick }
55345098Smckusick
55445098Smckusick static bool_t /* consumes input bytes; knows nothing about records! */
skip_input_bytes(rstrm,cnt)55545098Smckusick skip_input_bytes(rstrm, cnt)
55645098Smckusick register RECSTREAM *rstrm;
55745098Smckusick long cnt;
55845098Smckusick {
55945098Smckusick register int current;
56045098Smckusick
56145098Smckusick while (cnt > 0) {
56245098Smckusick current = (int)rstrm->in_boundry - (int)rstrm->in_finger;
56345098Smckusick if (current == 0) {
56445098Smckusick if (! fill_input_buf(rstrm))
56545098Smckusick return (FALSE);
56645098Smckusick continue;
56745098Smckusick }
56845098Smckusick current = (cnt < current) ? cnt : current;
56945098Smckusick rstrm->in_finger += current;
57045098Smckusick cnt -= current;
57145098Smckusick }
57245098Smckusick return (TRUE);
57345098Smckusick }
57445098Smckusick
57545098Smckusick static u_int
fix_buf_size(s)57645098Smckusick fix_buf_size(s)
57745098Smckusick register u_int s;
57845098Smckusick {
57945098Smckusick
58045098Smckusick if (s < 100)
58145098Smckusick s = 4000;
58245098Smckusick return (RNDUP(s));
58345098Smckusick }
584