123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573 |
- #define __FORCE_GLIBC__
- #include <features.h>
- #include <stdio.h>
- #include <rpc/types.h>
- #include <rpc/xdr.h>
- #include <netinet/in.h>
- extern long lseek();
- static u_int fix_buf_size();
- static bool_t xdrrec_getlong();
- static bool_t xdrrec_putlong();
- static bool_t xdrrec_getbytes();
- static bool_t xdrrec_putbytes();
- static u_int xdrrec_getpos();
- static bool_t xdrrec_setpos();
- static long *xdrrec_inline();
- static void xdrrec_destroy();
- static struct xdr_ops xdrrec_ops = {
- xdrrec_getlong,
- xdrrec_putlong,
- xdrrec_getbytes,
- xdrrec_putbytes,
- xdrrec_getpos,
- xdrrec_setpos,
- xdrrec_inline,
- xdrrec_destroy
- };
- #define LAST_FRAG ((u_long)(1 << 31))
- typedef struct rec_strm {
- caddr_t tcp_handle;
- caddr_t the_buffer;
-
- int (*writeit) ();
- caddr_t out_base;
- caddr_t out_finger;
- caddr_t out_boundry;
- u_long *frag_header;
- bool_t frag_sent;
-
- int (*readit) ();
- u_long in_size;
- caddr_t in_base;
- caddr_t in_finger;
- caddr_t in_boundry;
- long fbtbc;
- bool_t last_frag;
- u_int sendsize;
- u_int recvsize;
- } RECSTREAM;
- void xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit)
- register XDR *xdrs;
- register u_int sendsize;
- register u_int recvsize;
- caddr_t tcp_handle;
- int (*readit) ();
- int (*writeit) ();
- {
- register RECSTREAM *rstrm = (RECSTREAM *) mem_alloc(sizeof(RECSTREAM));
- if (rstrm == NULL) {
- (void) fprintf(stderr, "xdrrec_create: out of memory\n");
-
- return;
- }
-
- rstrm->sendsize = sendsize = fix_buf_size(sendsize);
- rstrm->recvsize = recvsize = fix_buf_size(recvsize);
- rstrm->the_buffer =
- mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT);
- if (rstrm->the_buffer == NULL) {
- (void) fprintf(stderr, "xdrrec_create: out of memory\n");
- return;
- }
- for (rstrm->out_base = rstrm->the_buffer;
- (u_int) rstrm->out_base % BYTES_PER_XDR_UNIT != 0;
- rstrm->out_base++);
- rstrm->in_base = rstrm->out_base + sendsize;
-
- xdrs->x_ops = &xdrrec_ops;
- xdrs->x_private = (caddr_t) rstrm;
- rstrm->tcp_handle = tcp_handle;
- rstrm->readit = readit;
- rstrm->writeit = writeit;
- rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
- rstrm->frag_header = (u_long *) rstrm->out_base;
- rstrm->out_finger += sizeof(u_long);
- rstrm->out_boundry += sendsize;
- rstrm->frag_sent = FALSE;
- rstrm->in_size = recvsize;
- rstrm->in_boundry = rstrm->in_base;
- rstrm->in_finger = (rstrm->in_boundry += recvsize);
- rstrm->fbtbc = 0;
- rstrm->last_frag = TRUE;
- }
- static bool_t xdrrec_getlong(xdrs, lp)
- XDR *xdrs;
- long *lp;
- {
- register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
- register long *buflp = (long *) (rstrm->in_finger);
- long mylong;
-
- if ((rstrm->fbtbc >= sizeof(long)) &&
- (((int) rstrm->in_boundry - (int) buflp) >= sizeof(long))) {
- *lp = (long) ntohl((u_long) (*buflp));
- rstrm->fbtbc -= sizeof(long);
- rstrm->in_finger += sizeof(long);
- } else {
- if (!xdrrec_getbytes(xdrs, (caddr_t) & mylong, sizeof(long)))
- return (FALSE);
- *lp = (long) ntohl((u_long) mylong);
- }
- return (TRUE);
- }
- static bool_t xdrrec_putlong(xdrs, lp)
- XDR *xdrs;
- long *lp;
- {
- register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
- register long *dest_lp = ((long *) (rstrm->out_finger));
- if ((rstrm->out_finger += sizeof(long)) > rstrm->out_boundry) {
-
- rstrm->out_finger -= sizeof(long);
- rstrm->frag_sent = TRUE;
- if (!flush_out(rstrm, FALSE))
- return (FALSE);
- dest_lp = ((long *) (rstrm->out_finger));
- rstrm->out_finger += sizeof(long);
- }
- *dest_lp = (long) htonl((u_long) (*lp));
- return (TRUE);
- }
- static bool_t
- xdrrec_getbytes(xdrs, addr, len)
- XDR *xdrs;
- register caddr_t addr;
- register u_int len;
- {
- register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
- register int current;
- while (len > 0) {
- current = rstrm->fbtbc;
- if (current == 0) {
- if (rstrm->last_frag)
- return (FALSE);
- if (!set_input_fragment(rstrm))
- return (FALSE);
- continue;
- }
- current = (len < current) ? len : current;
- if (!get_input_bytes(rstrm, addr, current))
- return (FALSE);
- addr += current;
- rstrm->fbtbc -= current;
- len -= current;
- }
- return (TRUE);
- }
- static bool_t xdrrec_putbytes(xdrs, addr, len)
- XDR *xdrs;
- register caddr_t addr;
- register u_int len;
- {
- register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
- register int current;
- while (len > 0) {
- current = (u_int) rstrm->out_boundry - (u_int) rstrm->out_finger;
- current = (len < current) ? len : current;
- bcopy(addr, rstrm->out_finger, current);
- rstrm->out_finger += current;
- addr += current;
- len -= current;
- if (rstrm->out_finger == rstrm->out_boundry) {
- rstrm->frag_sent = TRUE;
- if (!flush_out(rstrm, FALSE))
- return (FALSE);
- }
- }
- return (TRUE);
- }
- static u_int xdrrec_getpos(xdrs)
- register XDR *xdrs;
- {
- register RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
- register long pos;
- pos = lseek((int) rstrm->tcp_handle, (long) 0, 1);
- if (pos != -1)
- switch (xdrs->x_op) {
- case XDR_ENCODE:
- pos += rstrm->out_finger - rstrm->out_base;
- break;
- case XDR_DECODE:
- pos -= rstrm->in_boundry - rstrm->in_finger;
- break;
- default:
- pos = (u_int) - 1;
- break;
- }
- return ((u_int) pos);
- }
- static bool_t xdrrec_setpos(xdrs, pos)
- register XDR *xdrs;
- u_int pos;
- {
- register RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
- u_int currpos = xdrrec_getpos(xdrs);
- int delta = currpos - pos;
- caddr_t newpos;
- if ((int) currpos != -1)
- switch (xdrs->x_op) {
- case XDR_ENCODE:
- newpos = rstrm->out_finger - delta;
- if ((newpos > (caddr_t) (rstrm->frag_header)) &&
- (newpos < rstrm->out_boundry)) {
- rstrm->out_finger = newpos;
- return (TRUE);
- }
- break;
- case XDR_DECODE:
- newpos = rstrm->in_finger - delta;
- if ((delta < (int) (rstrm->fbtbc)) &&
- (newpos <= rstrm->in_boundry) &&
- (newpos >= rstrm->in_base)) {
- rstrm->in_finger = newpos;
- rstrm->fbtbc -= delta;
- return (TRUE);
- }
- break;
- }
- return (FALSE);
- }
- static long *xdrrec_inline(xdrs, len)
- register XDR *xdrs;
- int len;
- {
- register RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
- long *buf = NULL;
- switch (xdrs->x_op) {
- case XDR_ENCODE:
- if ((rstrm->out_finger + len) <= rstrm->out_boundry) {
- buf = (long *) rstrm->out_finger;
- rstrm->out_finger += len;
- }
- break;
- case XDR_DECODE:
- if ((len <= rstrm->fbtbc) &&
- ((rstrm->in_finger + len) <= rstrm->in_boundry)) {
- buf = (long *) rstrm->in_finger;
- rstrm->fbtbc -= len;
- rstrm->in_finger += len;
- }
- break;
- }
- return (buf);
- }
- static void xdrrec_destroy(xdrs)
- register XDR *xdrs;
- {
- register RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
- mem_free(rstrm->the_buffer,
- rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT);
- mem_free((caddr_t) rstrm, sizeof(RECSTREAM));
- }
- bool_t xdrrec_skiprecord(xdrs)
- XDR *xdrs;
- {
- register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
- while (rstrm->fbtbc > 0 || (!rstrm->last_frag)) {
- if (!skip_input_bytes(rstrm, rstrm->fbtbc))
- return (FALSE);
- rstrm->fbtbc = 0;
- if ((!rstrm->last_frag) && (!set_input_fragment(rstrm)))
- return (FALSE);
- }
- rstrm->last_frag = FALSE;
- return (TRUE);
- }
- bool_t xdrrec_eof(xdrs)
- XDR *xdrs;
- {
- register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
- while (rstrm->fbtbc > 0 || (!rstrm->last_frag)) {
- if (!skip_input_bytes(rstrm, rstrm->fbtbc))
- return (TRUE);
- rstrm->fbtbc = 0;
- if ((!rstrm->last_frag) && (!set_input_fragment(rstrm)))
- return (TRUE);
- }
- if (rstrm->in_finger == rstrm->in_boundry)
- return (TRUE);
- return (FALSE);
- }
- bool_t xdrrec_endofrecord(xdrs, sendnow)
- XDR *xdrs;
- bool_t sendnow;
- {
- register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
- register u_long len;
- if (sendnow || rstrm->frag_sent ||
- ((u_long) rstrm->out_finger + sizeof(u_long) >=
- (u_long) rstrm->out_boundry)) {
- rstrm->frag_sent = FALSE;
- return (flush_out(rstrm, TRUE));
- }
- len = (u_long) (rstrm->out_finger) - (u_long) (rstrm->frag_header) -
- sizeof(u_long);
- *(rstrm->frag_header) = htonl((u_long) len | LAST_FRAG);
- rstrm->frag_header = (u_long *) rstrm->out_finger;
- rstrm->out_finger += sizeof(u_long);
- return (TRUE);
- }
- static bool_t flush_out(rstrm, eor)
- register RECSTREAM *rstrm;
- bool_t eor;
- {
- register u_long eormask = (eor == TRUE) ? LAST_FRAG : 0;
- register u_long len = (u_long) (rstrm->out_finger) -
- (u_long) (rstrm->frag_header) - sizeof(u_long);
- *(rstrm->frag_header) = htonl(len | eormask);
- len = (u_long) (rstrm->out_finger) - (u_long) (rstrm->out_base);
- if ((*(rstrm->writeit)) (rstrm->tcp_handle, rstrm->out_base, (int) len)
- != (int) len)
- return (FALSE);
- rstrm->frag_header = (u_long *) rstrm->out_base;
- rstrm->out_finger = (caddr_t) rstrm->out_base + sizeof(u_long);
- return (TRUE);
- }
- static bool_t
- fill_input_buf(rstrm)
- register RECSTREAM *rstrm;
- {
- register caddr_t where;
- u_int i;
- register int len;
- where = rstrm->in_base;
- i = (u_int) rstrm->in_boundry % BYTES_PER_XDR_UNIT;
- where += i;
- len = rstrm->in_size - i;
- if ((len = (*(rstrm->readit)) (rstrm->tcp_handle, where, len)) == -1)
- return (FALSE);
- rstrm->in_finger = where;
- where += len;
- rstrm->in_boundry = where;
- return (TRUE);
- }
- static bool_t
- get_input_bytes(rstrm, addr, len)
- register RECSTREAM *rstrm;
- register caddr_t addr;
- register int len;
- {
- register int current;
- while (len > 0) {
- current = (int) rstrm->in_boundry - (int) rstrm->in_finger;
- if (current == 0) {
- if (!fill_input_buf(rstrm))
- return (FALSE);
- continue;
- }
- current = (len < current) ? len : current;
- bcopy(rstrm->in_finger, addr, current);
- rstrm->in_finger += current;
- addr += current;
- len -= current;
- }
- return (TRUE);
- }
- static bool_t
- set_input_fragment(rstrm)
- register RECSTREAM *rstrm;
- {
- u_long header;
- if (!get_input_bytes(rstrm, (caddr_t) & header, sizeof(header)))
- return (FALSE);
- header = (long) ntohl(header);
- rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
- rstrm->fbtbc = header & (~LAST_FRAG);
- return (TRUE);
- }
- static bool_t
- skip_input_bytes(rstrm, cnt)
- register RECSTREAM *rstrm;
- long cnt;
- {
- register int current;
- while (cnt > 0) {
- current = (int) rstrm->in_boundry - (int) rstrm->in_finger;
- if (current == 0) {
- if (!fill_input_buf(rstrm))
- return (FALSE);
- continue;
- }
- current = (cnt < current) ? cnt : current;
- rstrm->in_finger += current;
- cnt -= current;
- }
- return (TRUE);
- }
- static u_int fix_buf_size(s)
- register u_int s;
- {
- if (s < 100)
- s = 4000;
- return (RNDUP(s));
- }
|