00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #if !defined(lint) && defined(SCCSIDS)
00031 static char sccsid[] = "@(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";
00032 #endif
00033
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #include <stdio.h>
00056 #include <rpc/types.h>
00057 #include <rpc/xdr.h>
00058 #include <netinet/in.h>
00059 #include <string.h>
00060
00061 extern long lseek ();
00062
00063 static u_int fix_buf_size ();
00064
00065 static bool_t xdrrec_getlong ();
00066 static bool_t xdrrec_putlong ();
00067 static bool_t xdrrec_getbytes ();
00068 static bool_t xdrrec_putbytes ();
00069 static u_int xdrrec_getpos ();
00070 static bool_t xdrrec_setpos ();
00071 static long *xdrrec_inline ();
00072 static void xdrrec_destroy ();
00073
00074 static struct xdr_ops xdrrec_ops =
00075 {
00076 xdrrec_getlong,
00077 xdrrec_putlong,
00078 xdrrec_getbytes,
00079 xdrrec_putbytes,
00080 xdrrec_getpos,
00081 xdrrec_setpos,
00082 xdrrec_inline,
00083 xdrrec_destroy
00084 };
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 #define LAST_FRAG ((u_long)(1 << 31))
00100
00101 typedef struct rec_strm {
00102 caddr_t tcp_handle;
00103 caddr_t the_buffer;
00104
00105
00106
00107 int (*writeit) ();
00108 caddr_t out_base;
00109 caddr_t out_finger;
00110 caddr_t out_boundry;
00111 u_long *frag_header;
00112 bool_t frag_sent;
00113
00114
00115
00116 int (*readit) ();
00117 u_long in_size;
00118 caddr_t in_base;
00119 caddr_t in_finger;
00120 caddr_t in_boundry;
00121 long fbtbc;
00122 bool_t last_frag;
00123 u_int sendsize;
00124 u_int recvsize;
00125 } RECSTREAM;
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 void xdrrec_create (xdrs, sendsize, recvsize, tcp_handle, readit, writeit)
00138 register XDR *xdrs;
00139 register u_int sendsize;
00140 register u_int recvsize;
00141 caddr_t tcp_handle;
00142 int (*readit) ();
00143 int (*writeit) ();
00144 {
00145 register RECSTREAM *rstrm =
00146 (RECSTREAM *) mem_alloc (sizeof (RECSTREAM));
00147
00148 if (rstrm == NULL) {
00149 (void) fprintf (stderr, "xdrrec_create: out of memory\n");
00150
00151
00152
00153
00154 return;
00155 }
00156
00157
00158
00159 rstrm->sendsize = sendsize = fix_buf_size (sendsize);
00160 rstrm->recvsize = recvsize = fix_buf_size (recvsize);
00161 rstrm->the_buffer = mem_alloc (sendsize + recvsize + BYTES_PER_XDR_UNIT);
00162 if (rstrm->the_buffer == NULL) {
00163 (void) fprintf (stderr, "xdrrec_create: out of memory\n");
00164 return;
00165 }
00166 for (rstrm->out_base = rstrm->the_buffer;
00167 (u_int) rstrm->out_base % BYTES_PER_XDR_UNIT != 0;
00168 rstrm->out_base++);
00169 rstrm->in_base = rstrm->out_base + sendsize;
00170
00171
00172
00173 xdrs->x_ops = &xdrrec_ops;
00174 xdrs->x_private = (caddr_t) rstrm;
00175 rstrm->tcp_handle = tcp_handle;
00176 rstrm->readit = readit;
00177 rstrm->writeit = writeit;
00178 rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
00179 rstrm->frag_header = (u_long *) rstrm->out_base;
00180 rstrm->out_finger += sizeof (u_long);
00181 rstrm->out_boundry += sendsize;
00182 rstrm->frag_sent = FALSE;
00183 rstrm->in_size = recvsize;
00184 rstrm->in_boundry = rstrm->in_base;
00185 rstrm->in_finger = (rstrm->in_boundry += recvsize);
00186 rstrm->fbtbc = 0;
00187 rstrm->last_frag = TRUE;
00188 }
00189
00190
00191
00192
00193
00194
00195
00196 static bool_t
00197 xdrrec_getlong (xdrs, lp)
00198 XDR *xdrs;
00199 long *lp;
00200 {
00201 register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
00202 register long *buflp = (long *) (rstrm->in_finger);
00203 long mylong;
00204
00205
00206 if ((rstrm->fbtbc >= sizeof (long)) &&
00207 (((int) rstrm->in_boundry - (int) buflp) >= sizeof (long))) {
00208 *lp = (long) ntohl ((u_long) (*buflp));
00209 rstrm->fbtbc -= sizeof (long);
00210 rstrm->in_finger += sizeof (long);
00211 } else {
00212 if (!xdrrec_getbytes (xdrs, (caddr_t) & mylong, sizeof (long)))
00213 return (FALSE);
00214 *lp = (long) ntohl ((u_long) mylong);
00215 }
00216 return (TRUE);
00217 }
00218
00219 static bool_t
00220 xdrrec_putlong (xdrs, lp)
00221 XDR *xdrs;
00222 long *lp;
00223 {
00224 register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
00225 register long *dest_lp = ((long *) (rstrm->out_finger));
00226
00227 if ((rstrm->out_finger += sizeof (long)) > rstrm->out_boundry) {
00228
00229
00230
00231
00232 rstrm->out_finger -= sizeof (long);
00233 rstrm->frag_sent = TRUE;
00234 if (!flush_out (rstrm, FALSE))
00235 return (FALSE);
00236 dest_lp = ((long *) (rstrm->out_finger));
00237 rstrm->out_finger += sizeof (long);
00238 }
00239 *dest_lp = (long) htonl ((u_long) (*lp));
00240 return (TRUE);
00241 }
00242
00243 static bool_t
00244 xdrrec_getbytes (xdrs, addr, len)
00245 XDR *xdrs;
00246 register caddr_t addr;
00247 register u_int len;
00248 {
00249 register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
00250 register int current;
00251
00252 while (len > 0) {
00253 current = rstrm->fbtbc;
00254 if (current == 0) {
00255 if (rstrm->last_frag)
00256 return (FALSE);
00257 if (!set_input_fragment (rstrm))
00258 return (FALSE);
00259 continue;
00260 }
00261 current = (len < current) ? len : current;
00262 if (!get_input_bytes (rstrm, addr, current))
00263 return (FALSE);
00264 addr += current;
00265 rstrm->fbtbc -= current;
00266 len -= current;
00267 }
00268 return (TRUE);
00269 }
00270
00271 static bool_t
00272 xdrrec_putbytes (xdrs, addr, len)
00273 XDR *xdrs;
00274 register caddr_t addr;
00275 register u_int len;
00276 {
00277 register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
00278 register int current;
00279
00280 while (len > 0) {
00281 current = (u_int) rstrm->out_boundry - (u_int) rstrm->out_finger;
00282 current = (len < current) ? len : current;
00283 bcopy (addr, rstrm->out_finger, current);
00284 rstrm->out_finger += current;
00285 addr += current;
00286 len -= current;
00287 if (rstrm->out_finger == rstrm->out_boundry) {
00288 rstrm->frag_sent = TRUE;
00289 if (!flush_out (rstrm, FALSE))
00290 return (FALSE);
00291 }
00292 }
00293 return (TRUE);
00294 }
00295
00296 static u_int
00297 xdrrec_getpos (xdrs)
00298 register XDR *xdrs;
00299 {
00300 register RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
00301 register long pos;
00302
00303 pos = lseek ((int) rstrm->tcp_handle, (long) 0, 1);
00304 if (pos != -1)
00305 switch (xdrs->x_op) {
00306
00307 case XDR_ENCODE:
00308 pos += rstrm->out_finger - rstrm->out_base;
00309 break;
00310
00311 case XDR_DECODE:
00312 pos -= rstrm->in_boundry - rstrm->in_finger;
00313 break;
00314
00315 default:
00316 pos = (u_int) - 1;
00317 break;
00318 }
00319 return ((u_int) pos);
00320 }
00321
00322 static bool_t
00323 xdrrec_setpos (xdrs, pos)
00324 register XDR *xdrs;
00325 u_int pos;
00326 {
00327 register RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
00328 u_int currpos = xdrrec_getpos (xdrs);
00329 int delta = currpos - pos;
00330 caddr_t newpos;
00331
00332 if ((int) currpos != -1)
00333 switch (xdrs->x_op) {
00334
00335 case XDR_ENCODE:
00336 newpos = rstrm->out_finger - delta;
00337 if ((newpos > (caddr_t) (rstrm->frag_header)) &&
00338 (newpos < rstrm->out_boundry)) {
00339 rstrm->out_finger = newpos;
00340 return (TRUE);
00341 }
00342 break;
00343
00344 case XDR_DECODE:
00345 newpos = rstrm->in_finger - delta;
00346 if ((delta < (int) (rstrm->fbtbc)) &&
00347 (newpos <= rstrm->in_boundry) &&
00348 (newpos >= rstrm->in_base)) {
00349 rstrm->in_finger = newpos;
00350 rstrm->fbtbc -= delta;
00351 return (TRUE);
00352 }
00353 break;
00354 }
00355 return (FALSE);
00356 }
00357
00358 static long *
00359 xdrrec_inline (xdrs, len)
00360 register XDR *xdrs;
00361 int len;
00362 {
00363 register RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
00364 long *buf = NULL;
00365
00366 switch (xdrs->x_op) {
00367
00368 case XDR_ENCODE:
00369 if ((rstrm->out_finger + len) <= rstrm->out_boundry) {
00370 buf = (long *) rstrm->out_finger;
00371 rstrm->out_finger += len;
00372 }
00373 break;
00374
00375 case XDR_DECODE:
00376 if ((len <= rstrm->fbtbc) &&
00377 ((rstrm->in_finger + len) <= rstrm->in_boundry)) {
00378 buf = (long *) rstrm->in_finger;
00379 rstrm->fbtbc -= len;
00380 rstrm->in_finger += len;
00381 }
00382 break;
00383 }
00384 return (buf);
00385 }
00386
00387 static void xdrrec_destroy (xdrs)
00388 register XDR *xdrs;
00389 {
00390 register RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
00391
00392 mem_free (rstrm->the_buffer,
00393 rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT);
00394 mem_free ((caddr_t) rstrm, sizeof (RECSTREAM));
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406 bool_t
00407 xdrrec_skiprecord (xdrs)
00408 XDR *xdrs;
00409 {
00410 register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
00411
00412 while (rstrm->fbtbc > 0 || (!rstrm->last_frag)) {
00413 if (!skip_input_bytes (rstrm, rstrm->fbtbc))
00414 return (FALSE);
00415 rstrm->fbtbc = 0;
00416 if ((!rstrm->last_frag) && (!set_input_fragment (rstrm)))
00417 return (FALSE);
00418 }
00419 rstrm->last_frag = FALSE;
00420 return (TRUE);
00421 }
00422
00423
00424
00425
00426
00427
00428 bool_t
00429 xdrrec_eof (xdrs)
00430 XDR *xdrs;
00431 {
00432 register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
00433
00434 while (rstrm->fbtbc > 0 || (!rstrm->last_frag)) {
00435 if (!skip_input_bytes (rstrm, rstrm->fbtbc))
00436 return (TRUE);
00437 rstrm->fbtbc = 0;
00438 if ((!rstrm->last_frag) && (!set_input_fragment (rstrm)))
00439 return (TRUE);
00440 }
00441 if (rstrm->in_finger == rstrm->in_boundry)
00442 return (TRUE);
00443 return (FALSE);
00444 }
00445
00446
00447
00448
00449
00450
00451
00452 bool_t
00453 xdrrec_endofrecord (xdrs, sendnow)
00454 XDR *xdrs;
00455 bool_t sendnow;
00456 {
00457 register RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private);
00458 register u_long len;
00459
00460 if (sendnow || rstrm->frag_sent ||
00461 ((u_long) rstrm->out_finger + sizeof (u_long) >=
00462 (u_long) rstrm->out_boundry)) {
00463 rstrm->frag_sent = FALSE;
00464 return (flush_out (rstrm, TRUE));
00465 }
00466 len = (u_long) (rstrm->out_finger) - (u_long) (rstrm->frag_header) -
00467 sizeof (u_long);
00468 *(rstrm->frag_header) = htonl ((u_long) len | LAST_FRAG);
00469 rstrm->frag_header = (u_long *) rstrm->out_finger;
00470 rstrm->out_finger += sizeof (u_long);
00471 return (TRUE);
00472 }
00473
00474
00475
00476
00477
00478 static bool_t
00479 flush_out (rstrm, eor)
00480 register RECSTREAM *rstrm;
00481 bool_t eor;
00482 {
00483 register u_long eormask = (eor == TRUE) ? LAST_FRAG : 0;
00484 register u_long len = (u_long) (rstrm->out_finger) -
00485 (u_long) (rstrm->frag_header) - sizeof (u_long);
00486
00487 *(rstrm->frag_header) = htonl (len | eormask);
00488 len = (u_long) (rstrm->out_finger) - (u_long) (rstrm->out_base);
00489 if ((*(rstrm->writeit)) (rstrm->tcp_handle, rstrm->out_base, (int) len)
00490 != (int) len)
00491 return (FALSE);
00492 rstrm->frag_header = (u_long *) rstrm->out_base;
00493 rstrm->out_finger = (caddr_t) rstrm->out_base + sizeof (u_long);
00494 return (TRUE);
00495 }
00496
00497 static bool_t
00498 fill_input_buf (rstrm)
00499 register RECSTREAM *rstrm;
00500 {
00501 register caddr_t where;
00502 u_int i;
00503 register int len;
00504
00505 where = rstrm->in_base;
00506 i = (u_int) rstrm->in_boundry % BYTES_PER_XDR_UNIT;
00507 where += i;
00508 len = rstrm->in_size - i;
00509 if ((len = (*(rstrm->readit)) (rstrm->tcp_handle, where, len)) == -1)
00510 return (FALSE);
00511 rstrm->in_finger = where;
00512 where += len;
00513 rstrm->in_boundry = where;
00514 return (TRUE);
00515 }
00516
00517 static bool_t
00518 get_input_bytes (rstrm, addr, len)
00519 register RECSTREAM *rstrm;
00520 register caddr_t addr;
00521 register int len;
00522 {
00523 register int current;
00524
00525 while (len > 0) {
00526 current = (int) rstrm->in_boundry - (int) rstrm->in_finger;
00527 if (current == 0) {
00528 if (!fill_input_buf (rstrm))
00529 return (FALSE);
00530 continue;
00531 }
00532 current = (len < current) ? len : current;
00533 bcopy (rstrm->in_finger, addr, current);
00534 rstrm->in_finger += current;
00535 addr += current;
00536 len -= current;
00537 }
00538 return (TRUE);
00539 }
00540
00541 static bool_t
00542 set_input_fragment (rstrm)
00543 register RECSTREAM *rstrm;
00544 {
00545 u_long header;
00546
00547 if (!get_input_bytes (rstrm, (caddr_t) & header, sizeof (header)))
00548 return (FALSE);
00549 header = (long) ntohl (header);
00550 rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
00551 rstrm->fbtbc = header & (~LAST_FRAG);
00552 return (TRUE);
00553 }
00554
00555 static bool_t
00556 skip_input_bytes (rstrm, cnt)
00557 register RECSTREAM *rstrm;
00558 long cnt;
00559 {
00560 register int current;
00561
00562 while (cnt > 0) {
00563 current = (int) rstrm->in_boundry - (int) rstrm->in_finger;
00564 if (current == 0) {
00565 if (!fill_input_buf (rstrm))
00566 return (FALSE);
00567 continue;
00568 }
00569 current = (cnt < current) ? cnt : current;
00570 rstrm->in_finger += current;
00571 cnt -= current;
00572 }
00573 return (TRUE);
00574 }
00575
00576 static u_int
00577 fix_buf_size (s)
00578 register u_int s;
00579 {
00580
00581 if (s < 100)
00582 s = 4000;
00583 return (RNDUP (s));
00584 }