xref: /csrg-svn/lib/librpc/rpc/xdr.c (revision 45438)
1*45095Smckusick /* @(#)xdr.c	2.1 88/07/29 4.0 RPCSRC */
2*45095Smckusick /*
3*45095Smckusick  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
4*45095Smckusick  * unrestricted use provided that this legend is included on all tape
5*45095Smckusick  * media and as a part of the software program in whole or part.  Users
6*45095Smckusick  * may copy or modify Sun RPC without charge, but are not authorized
7*45095Smckusick  * to license or distribute it to anyone else except as part of a product or
8*45095Smckusick  * program developed by the user.
9*45095Smckusick  *
10*45095Smckusick  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
11*45095Smckusick  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
12*45095Smckusick  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
13*45095Smckusick  *
14*45095Smckusick  * Sun RPC is provided with no support and without any obligation on the
15*45095Smckusick  * part of Sun Microsystems, Inc. to assist in its use, correction,
16*45095Smckusick  * modification or enhancement.
17*45095Smckusick  *
18*45095Smckusick  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
19*45095Smckusick  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
20*45095Smckusick  * OR ANY PART THEREOF.
21*45095Smckusick  *
22*45095Smckusick  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
23*45095Smckusick  * or profits or other special, indirect and consequential damages, even if
24*45095Smckusick  * Sun has been advised of the possibility of such damages.
25*45095Smckusick  *
26*45095Smckusick  * Sun Microsystems, Inc.
27*45095Smckusick  * 2550 Garcia Avenue
28*45095Smckusick  * Mountain View, California  94043
29*45095Smckusick  */
30*45095Smckusick #if !defined(lint) && defined(SCCSIDS)
31*45095Smckusick static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
32*45095Smckusick #endif
33*45095Smckusick 
34*45095Smckusick /*
35*45095Smckusick  * xdr.c, Generic XDR routines implementation.
36*45095Smckusick  *
37*45095Smckusick  * Copyright (C) 1986, Sun Microsystems, Inc.
38*45095Smckusick  *
39*45095Smckusick  * These are the "generic" xdr routines used to serialize and de-serialize
40*45095Smckusick  * most common data items.  See xdr.h for more info on the interface to
41*45095Smckusick  * xdr.
42*45095Smckusick  */
43*45095Smckusick 
44*45095Smckusick #include <stdio.h>
45*45095Smckusick 
46*45095Smckusick #include <rpc/types.h>
47*45095Smckusick #include <rpc/xdr.h>
48*45095Smckusick 
49*45095Smckusick /*
50*45095Smckusick  * constants specific to the xdr "protocol"
51*45095Smckusick  */
52*45095Smckusick #define XDR_FALSE	((long) 0)
53*45095Smckusick #define XDR_TRUE	((long) 1)
54*45095Smckusick #define LASTUNSIGNED	((u_int) 0-1)
55*45095Smckusick 
56*45095Smckusick /*
57*45095Smckusick  * for unit alignment
58*45095Smckusick  */
59*45095Smckusick static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
60*45095Smckusick 
61*45095Smckusick /*
62*45095Smckusick  * Free a data structure using XDR
63*45095Smckusick  * Not a filter, but a convenient utility nonetheless
64*45095Smckusick  */
65*45095Smckusick void
xdr_free(proc,objp)66*45095Smckusick xdr_free(proc, objp)
67*45095Smckusick 	xdrproc_t proc;
68*45095Smckusick 	char *objp;
69*45095Smckusick {
70*45095Smckusick 	XDR x;
71*45095Smckusick 
72*45095Smckusick 	x.x_op = XDR_FREE;
73*45095Smckusick 	(*proc)(&x, objp);
74*45095Smckusick }
75*45095Smckusick 
76*45095Smckusick /*
77*45095Smckusick  * XDR nothing
78*45095Smckusick  */
79*45095Smckusick bool_t
xdr_void()80*45095Smckusick xdr_void(/* xdrs, addr */)
81*45095Smckusick 	/* XDR *xdrs; */
82*45095Smckusick 	/* caddr_t addr; */
83*45095Smckusick {
84*45095Smckusick 
85*45095Smckusick 	return (TRUE);
86*45095Smckusick }
87*45095Smckusick 
88*45095Smckusick /*
89*45095Smckusick  * XDR integers
90*45095Smckusick  */
91*45095Smckusick bool_t
xdr_int(xdrs,ip)92*45095Smckusick xdr_int(xdrs, ip)
93*45095Smckusick 	XDR *xdrs;
94*45095Smckusick 	int *ip;
95*45095Smckusick {
96*45095Smckusick 
97*45095Smckusick #ifdef lint
98*45095Smckusick 	(void) (xdr_short(xdrs, (short *)ip));
99*45095Smckusick 	return (xdr_long(xdrs, (long *)ip));
100*45095Smckusick #else
101*45095Smckusick 	if (sizeof (int) == sizeof (long)) {
102*45095Smckusick 		return (xdr_long(xdrs, (long *)ip));
103*45095Smckusick 	} else {
104*45095Smckusick 		return (xdr_short(xdrs, (short *)ip));
105*45095Smckusick 	}
106*45095Smckusick #endif
107*45095Smckusick }
108*45095Smckusick 
109*45095Smckusick /*
110*45095Smckusick  * XDR unsigned integers
111*45095Smckusick  */
112*45095Smckusick bool_t
xdr_u_int(xdrs,up)113*45095Smckusick xdr_u_int(xdrs, up)
114*45095Smckusick 	XDR *xdrs;
115*45095Smckusick 	u_int *up;
116*45095Smckusick {
117*45095Smckusick 
118*45095Smckusick #ifdef lint
119*45095Smckusick 	(void) (xdr_short(xdrs, (short *)up));
120*45095Smckusick 	return (xdr_u_long(xdrs, (u_long *)up));
121*45095Smckusick #else
122*45095Smckusick 	if (sizeof (u_int) == sizeof (u_long)) {
123*45095Smckusick 		return (xdr_u_long(xdrs, (u_long *)up));
124*45095Smckusick 	} else {
125*45095Smckusick 		return (xdr_short(xdrs, (short *)up));
126*45095Smckusick 	}
127*45095Smckusick #endif
128*45095Smckusick }
129*45095Smckusick 
130*45095Smckusick /*
131*45095Smckusick  * XDR long integers
132*45095Smckusick  * same as xdr_u_long - open coded to save a proc call!
133*45095Smckusick  */
134*45095Smckusick bool_t
xdr_long(xdrs,lp)135*45095Smckusick xdr_long(xdrs, lp)
136*45095Smckusick 	register XDR *xdrs;
137*45095Smckusick 	long *lp;
138*45095Smckusick {
139*45095Smckusick 
140*45095Smckusick 	if (xdrs->x_op == XDR_ENCODE)
141*45095Smckusick 		return (XDR_PUTLONG(xdrs, lp));
142*45095Smckusick 
143*45095Smckusick 	if (xdrs->x_op == XDR_DECODE)
144*45095Smckusick 		return (XDR_GETLONG(xdrs, lp));
145*45095Smckusick 
146*45095Smckusick 	if (xdrs->x_op == XDR_FREE)
147*45095Smckusick 		return (TRUE);
148*45095Smckusick 
149*45095Smckusick 	return (FALSE);
150*45095Smckusick }
151*45095Smckusick 
152*45095Smckusick /*
153*45095Smckusick  * XDR unsigned long integers
154*45095Smckusick  * same as xdr_long - open coded to save a proc call!
155*45095Smckusick  */
156*45095Smckusick bool_t
xdr_u_long(xdrs,ulp)157*45095Smckusick xdr_u_long(xdrs, ulp)
158*45095Smckusick 	register XDR *xdrs;
159*45095Smckusick 	u_long *ulp;
160*45095Smckusick {
161*45095Smckusick 
162*45095Smckusick 	if (xdrs->x_op == XDR_DECODE)
163*45095Smckusick 		return (XDR_GETLONG(xdrs, (long *)ulp));
164*45095Smckusick 	if (xdrs->x_op == XDR_ENCODE)
165*45095Smckusick 		return (XDR_PUTLONG(xdrs, (long *)ulp));
166*45095Smckusick 	if (xdrs->x_op == XDR_FREE)
167*45095Smckusick 		return (TRUE);
168*45095Smckusick 	return (FALSE);
169*45095Smckusick }
170*45095Smckusick 
171*45095Smckusick /*
172*45095Smckusick  * XDR short integers
173*45095Smckusick  */
174*45095Smckusick bool_t
xdr_short(xdrs,sp)175*45095Smckusick xdr_short(xdrs, sp)
176*45095Smckusick 	register XDR *xdrs;
177*45095Smckusick 	short *sp;
178*45095Smckusick {
179*45095Smckusick 	long l;
180*45095Smckusick 
181*45095Smckusick 	switch (xdrs->x_op) {
182*45095Smckusick 
183*45095Smckusick 	case XDR_ENCODE:
184*45095Smckusick 		l = (long) *sp;
185*45095Smckusick 		return (XDR_PUTLONG(xdrs, &l));
186*45095Smckusick 
187*45095Smckusick 	case XDR_DECODE:
188*45095Smckusick 		if (!XDR_GETLONG(xdrs, &l)) {
189*45095Smckusick 			return (FALSE);
190*45095Smckusick 		}
191*45095Smckusick 		*sp = (short) l;
192*45095Smckusick 		return (TRUE);
193*45095Smckusick 
194*45095Smckusick 	case XDR_FREE:
195*45095Smckusick 		return (TRUE);
196*45095Smckusick 	}
197*45095Smckusick 	return (FALSE);
198*45095Smckusick }
199*45095Smckusick 
200*45095Smckusick /*
201*45095Smckusick  * XDR unsigned short integers
202*45095Smckusick  */
203*45095Smckusick bool_t
xdr_u_short(xdrs,usp)204*45095Smckusick xdr_u_short(xdrs, usp)
205*45095Smckusick 	register XDR *xdrs;
206*45095Smckusick 	u_short *usp;
207*45095Smckusick {
208*45095Smckusick 	u_long l;
209*45095Smckusick 
210*45095Smckusick 	switch (xdrs->x_op) {
211*45095Smckusick 
212*45095Smckusick 	case XDR_ENCODE:
213*45095Smckusick 		l = (u_long) *usp;
214*45095Smckusick 		return (XDR_PUTLONG(xdrs, &l));
215*45095Smckusick 
216*45095Smckusick 	case XDR_DECODE:
217*45095Smckusick 		if (!XDR_GETLONG(xdrs, &l)) {
218*45095Smckusick 			return (FALSE);
219*45095Smckusick 		}
220*45095Smckusick 		*usp = (u_short) l;
221*45095Smckusick 		return (TRUE);
222*45095Smckusick 
223*45095Smckusick 	case XDR_FREE:
224*45095Smckusick 		return (TRUE);
225*45095Smckusick 	}
226*45095Smckusick 	return (FALSE);
227*45095Smckusick }
228*45095Smckusick 
229*45095Smckusick 
230*45095Smckusick /*
231*45095Smckusick  * XDR a char
232*45095Smckusick  */
233*45095Smckusick bool_t
xdr_char(xdrs,cp)234*45095Smckusick xdr_char(xdrs, cp)
235*45095Smckusick 	XDR *xdrs;
236*45095Smckusick 	char *cp;
237*45095Smckusick {
238*45095Smckusick 	int i;
239*45095Smckusick 
240*45095Smckusick 	i = (*cp);
241*45095Smckusick 	if (!xdr_int(xdrs, &i)) {
242*45095Smckusick 		return (FALSE);
243*45095Smckusick 	}
244*45095Smckusick 	*cp = i;
245*45095Smckusick 	return (TRUE);
246*45095Smckusick }
247*45095Smckusick 
248*45095Smckusick /*
249*45095Smckusick  * XDR an unsigned char
250*45095Smckusick  */
251*45095Smckusick bool_t
xdr_u_char(xdrs,cp)252*45095Smckusick xdr_u_char(xdrs, cp)
253*45095Smckusick 	XDR *xdrs;
254*45095Smckusick 	char *cp;
255*45095Smckusick {
256*45095Smckusick 	u_int u;
257*45095Smckusick 
258*45095Smckusick 	u = (*cp);
259*45095Smckusick 	if (!xdr_u_int(xdrs, &u)) {
260*45095Smckusick 		return (FALSE);
261*45095Smckusick 	}
262*45095Smckusick 	*cp = u;
263*45095Smckusick 	return (TRUE);
264*45095Smckusick }
265*45095Smckusick 
266*45095Smckusick /*
267*45095Smckusick  * XDR booleans
268*45095Smckusick  */
269*45095Smckusick bool_t
xdr_bool(xdrs,bp)270*45095Smckusick xdr_bool(xdrs, bp)
271*45095Smckusick 	register XDR *xdrs;
272*45095Smckusick 	bool_t *bp;
273*45095Smckusick {
274*45095Smckusick 	long lb;
275*45095Smckusick 
276*45095Smckusick 	switch (xdrs->x_op) {
277*45095Smckusick 
278*45095Smckusick 	case XDR_ENCODE:
279*45095Smckusick 		lb = *bp ? XDR_TRUE : XDR_FALSE;
280*45095Smckusick 		return (XDR_PUTLONG(xdrs, &lb));
281*45095Smckusick 
282*45095Smckusick 	case XDR_DECODE:
283*45095Smckusick 		if (!XDR_GETLONG(xdrs, &lb)) {
284*45095Smckusick 			return (FALSE);
285*45095Smckusick 		}
286*45095Smckusick 		*bp = (lb == XDR_FALSE) ? FALSE : TRUE;
287*45095Smckusick 		return (TRUE);
288*45095Smckusick 
289*45095Smckusick 	case XDR_FREE:
290*45095Smckusick 		return (TRUE);
291*45095Smckusick 	}
292*45095Smckusick 	return (FALSE);
293*45095Smckusick }
294*45095Smckusick 
295*45095Smckusick /*
296*45095Smckusick  * XDR enumerations
297*45095Smckusick  */
298*45095Smckusick bool_t
xdr_enum(xdrs,ep)299*45095Smckusick xdr_enum(xdrs, ep)
300*45095Smckusick 	XDR *xdrs;
301*45095Smckusick 	enum_t *ep;
302*45095Smckusick {
303*45095Smckusick #ifndef lint
304*45095Smckusick 	enum sizecheck { SIZEVAL };	/* used to find the size of an enum */
305*45095Smckusick 
306*45095Smckusick 	/*
307*45095Smckusick 	 * enums are treated as ints
308*45095Smckusick 	 */
309*45095Smckusick 	if (sizeof (enum sizecheck) == sizeof (long)) {
310*45095Smckusick 		return (xdr_long(xdrs, (long *)ep));
311*45095Smckusick 	} else if (sizeof (enum sizecheck) == sizeof (short)) {
312*45095Smckusick 		return (xdr_short(xdrs, (short *)ep));
313*45095Smckusick 	} else {
314*45095Smckusick 		return (FALSE);
315*45095Smckusick 	}
316*45095Smckusick #else
317*45095Smckusick 	(void) (xdr_short(xdrs, (short *)ep));
318*45095Smckusick 	return (xdr_long(xdrs, (long *)ep));
319*45095Smckusick #endif
320*45095Smckusick }
321*45095Smckusick 
322*45095Smckusick /*
323*45095Smckusick  * XDR opaque data
324*45095Smckusick  * Allows the specification of a fixed size sequence of opaque bytes.
325*45095Smckusick  * cp points to the opaque object and cnt gives the byte length.
326*45095Smckusick  */
327*45095Smckusick bool_t
xdr_opaque(xdrs,cp,cnt)328*45095Smckusick xdr_opaque(xdrs, cp, cnt)
329*45095Smckusick 	register XDR *xdrs;
330*45095Smckusick 	caddr_t cp;
331*45095Smckusick 	register u_int cnt;
332*45095Smckusick {
333*45095Smckusick 	register u_int rndup;
334*45095Smckusick 	static crud[BYTES_PER_XDR_UNIT];
335*45095Smckusick 
336*45095Smckusick 	/*
337*45095Smckusick 	 * if no data we are done
338*45095Smckusick 	 */
339*45095Smckusick 	if (cnt == 0)
340*45095Smckusick 		return (TRUE);
341*45095Smckusick 
342*45095Smckusick 	/*
343*45095Smckusick 	 * round byte count to full xdr units
344*45095Smckusick 	 */
345*45095Smckusick 	rndup = cnt % BYTES_PER_XDR_UNIT;
346*45095Smckusick 	if (rndup > 0)
347*45095Smckusick 		rndup = BYTES_PER_XDR_UNIT - rndup;
348*45095Smckusick 
349*45095Smckusick 	if (xdrs->x_op == XDR_DECODE) {
350*45095Smckusick 		if (!XDR_GETBYTES(xdrs, cp, cnt)) {
351*45095Smckusick 			return (FALSE);
352*45095Smckusick 		}
353*45095Smckusick 		if (rndup == 0)
354*45095Smckusick 			return (TRUE);
355*45095Smckusick 		return (XDR_GETBYTES(xdrs, crud, rndup));
356*45095Smckusick 	}
357*45095Smckusick 
358*45095Smckusick 	if (xdrs->x_op == XDR_ENCODE) {
359*45095Smckusick 		if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
360*45095Smckusick 			return (FALSE);
361*45095Smckusick 		}
362*45095Smckusick 		if (rndup == 0)
363*45095Smckusick 			return (TRUE);
364*45095Smckusick 		return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
365*45095Smckusick 	}
366*45095Smckusick 
367*45095Smckusick 	if (xdrs->x_op == XDR_FREE) {
368*45095Smckusick 		return (TRUE);
369*45095Smckusick 	}
370*45095Smckusick 
371*45095Smckusick 	return (FALSE);
372*45095Smckusick }
373*45095Smckusick 
374*45095Smckusick /*
375*45095Smckusick  * XDR counted bytes
376*45095Smckusick  * *cpp is a pointer to the bytes, *sizep is the count.
377*45095Smckusick  * If *cpp is NULL maxsize bytes are allocated
378*45095Smckusick  */
379*45095Smckusick bool_t
xdr_bytes(xdrs,cpp,sizep,maxsize)380*45095Smckusick xdr_bytes(xdrs, cpp, sizep, maxsize)
381*45095Smckusick 	register XDR *xdrs;
382*45095Smckusick 	char **cpp;
383*45095Smckusick 	register u_int *sizep;
384*45095Smckusick 	u_int maxsize;
385*45095Smckusick {
386*45095Smckusick 	register char *sp = *cpp;  /* sp is the actual string pointer */
387*45095Smckusick 	register u_int nodesize;
388*45095Smckusick 
389*45095Smckusick 	/*
390*45095Smckusick 	 * first deal with the length since xdr bytes are counted
391*45095Smckusick 	 */
392*45095Smckusick 	if (! xdr_u_int(xdrs, sizep)) {
393*45095Smckusick 		return (FALSE);
394*45095Smckusick 	}
395*45095Smckusick 	nodesize = *sizep;
396*45095Smckusick 	if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
397*45095Smckusick 		return (FALSE);
398*45095Smckusick 	}
399*45095Smckusick 
400*45095Smckusick 	/*
401*45095Smckusick 	 * now deal with the actual bytes
402*45095Smckusick 	 */
403*45095Smckusick 	switch (xdrs->x_op) {
404*45095Smckusick 
405*45095Smckusick 	case XDR_DECODE:
406*45095Smckusick 		if (nodesize == 0) {
407*45095Smckusick 			return (TRUE);
408*45095Smckusick 		}
409*45095Smckusick 		if (sp == NULL) {
410*45095Smckusick 			*cpp = sp = (char *)mem_alloc(nodesize);
411*45095Smckusick 		}
412*45095Smckusick 		if (sp == NULL) {
413*45095Smckusick 			(void) fprintf(stderr, "xdr_bytes: out of memory\n");
414*45095Smckusick 			return (FALSE);
415*45095Smckusick 		}
416*45095Smckusick 		/* fall into ... */
417*45095Smckusick 
418*45095Smckusick 	case XDR_ENCODE:
419*45095Smckusick 		return (xdr_opaque(xdrs, sp, nodesize));
420*45095Smckusick 
421*45095Smckusick 	case XDR_FREE:
422*45095Smckusick 		if (sp != NULL) {
423*45095Smckusick 			mem_free(sp, nodesize);
424*45095Smckusick 			*cpp = NULL;
425*45095Smckusick 		}
426*45095Smckusick 		return (TRUE);
427*45095Smckusick 	}
428*45095Smckusick 	return (FALSE);
429*45095Smckusick }
430*45095Smckusick 
431*45095Smckusick /*
432*45095Smckusick  * Implemented here due to commonality of the object.
433*45095Smckusick  */
434*45095Smckusick bool_t
xdr_netobj(xdrs,np)435*45095Smckusick xdr_netobj(xdrs, np)
436*45095Smckusick 	XDR *xdrs;
437*45095Smckusick 	struct netobj *np;
438*45095Smckusick {
439*45095Smckusick 
440*45095Smckusick 	return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
441*45095Smckusick }
442*45095Smckusick 
443*45095Smckusick /*
444*45095Smckusick  * XDR a descriminated union
445*45095Smckusick  * Support routine for discriminated unions.
446*45095Smckusick  * You create an array of xdrdiscrim structures, terminated with
447*45095Smckusick  * an entry with a null procedure pointer.  The routine gets
448*45095Smckusick  * the discriminant value and then searches the array of xdrdiscrims
449*45095Smckusick  * looking for that value.  It calls the procedure given in the xdrdiscrim
450*45095Smckusick  * to handle the discriminant.  If there is no specific routine a default
451*45095Smckusick  * routine may be called.
452*45095Smckusick  * If there is no specific or default routine an error is returned.
453*45095Smckusick  */
454*45095Smckusick bool_t
xdr_union(xdrs,dscmp,unp,choices,dfault)455*45095Smckusick xdr_union(xdrs, dscmp, unp, choices, dfault)
456*45095Smckusick 	register XDR *xdrs;
457*45095Smckusick 	enum_t *dscmp;		/* enum to decide which arm to work on */
458*45095Smckusick 	char *unp;		/* the union itself */
459*45095Smckusick 	struct xdr_discrim *choices;	/* [value, xdr proc] for each arm */
460*45095Smckusick 	xdrproc_t dfault;	/* default xdr routine */
461*45095Smckusick {
462*45095Smckusick 	register enum_t dscm;
463*45095Smckusick 
464*45095Smckusick 	/*
465*45095Smckusick 	 * we deal with the discriminator;  it's an enum
466*45095Smckusick 	 */
467*45095Smckusick 	if (! xdr_enum(xdrs, dscmp)) {
468*45095Smckusick 		return (FALSE);
469*45095Smckusick 	}
470*45095Smckusick 	dscm = *dscmp;
471*45095Smckusick 
472*45095Smckusick 	/*
473*45095Smckusick 	 * search choices for a value that matches the discriminator.
474*45095Smckusick 	 * if we find one, execute the xdr routine for that value.
475*45095Smckusick 	 */
476*45095Smckusick 	for (; choices->proc != NULL_xdrproc_t; choices++) {
477*45095Smckusick 		if (choices->value == dscm)
478*45095Smckusick 			return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
479*45095Smckusick 	}
480*45095Smckusick 
481*45095Smckusick 	/*
482*45095Smckusick 	 * no match - execute the default xdr routine if there is one
483*45095Smckusick 	 */
484*45095Smckusick 	return ((dfault == NULL_xdrproc_t) ? FALSE :
485*45095Smckusick 	    (*dfault)(xdrs, unp, LASTUNSIGNED));
486*45095Smckusick }
487*45095Smckusick 
488*45095Smckusick 
489*45095Smckusick /*
490*45095Smckusick  * Non-portable xdr primitives.
491*45095Smckusick  * Care should be taken when moving these routines to new architectures.
492*45095Smckusick  */
493*45095Smckusick 
494*45095Smckusick 
495*45095Smckusick /*
496*45095Smckusick  * XDR null terminated ASCII strings
497*45095Smckusick  * xdr_string deals with "C strings" - arrays of bytes that are
498*45095Smckusick  * terminated by a NULL character.  The parameter cpp references a
499*45095Smckusick  * pointer to storage; If the pointer is null, then the necessary
500*45095Smckusick  * storage is allocated.  The last parameter is the max allowed length
501*45095Smckusick  * of the string as specified by a protocol.
502*45095Smckusick  */
503*45095Smckusick bool_t
xdr_string(xdrs,cpp,maxsize)504*45095Smckusick xdr_string(xdrs, cpp, maxsize)
505*45095Smckusick 	register XDR *xdrs;
506*45095Smckusick 	char **cpp;
507*45095Smckusick 	u_int maxsize;
508*45095Smckusick {
509*45095Smckusick 	register char *sp = *cpp;  /* sp is the actual string pointer */
510*45095Smckusick 	u_int size;
511*45095Smckusick 	u_int nodesize;
512*45095Smckusick 
513*45095Smckusick 	/*
514*45095Smckusick 	 * first deal with the length since xdr strings are counted-strings
515*45095Smckusick 	 */
516*45095Smckusick 	switch (xdrs->x_op) {
517*45095Smckusick 	case XDR_FREE:
518*45095Smckusick 		if (sp == NULL) {
519*45095Smckusick 			return(TRUE);	/* already free */
520*45095Smckusick 		}
521*45095Smckusick 		/* fall through... */
522*45095Smckusick 	case XDR_ENCODE:
523*45095Smckusick 		size = strlen(sp);
524*45095Smckusick 		break;
525*45095Smckusick 	}
526*45095Smckusick 	if (! xdr_u_int(xdrs, &size)) {
527*45095Smckusick 		return (FALSE);
528*45095Smckusick 	}
529*45095Smckusick 	if (size > maxsize) {
530*45095Smckusick 		return (FALSE);
531*45095Smckusick 	}
532*45095Smckusick 	nodesize = size + 1;
533*45095Smckusick 
534*45095Smckusick 	/*
535*45095Smckusick 	 * now deal with the actual bytes
536*45095Smckusick 	 */
537*45095Smckusick 	switch (xdrs->x_op) {
538*45095Smckusick 
539*45095Smckusick 	case XDR_DECODE:
540*45095Smckusick 		if (nodesize == 0) {
541*45095Smckusick 			return (TRUE);
542*45095Smckusick 		}
543*45095Smckusick 		if (sp == NULL)
544*45095Smckusick 			*cpp = sp = (char *)mem_alloc(nodesize);
545*45095Smckusick 		if (sp == NULL) {
546*45095Smckusick 			(void) fprintf(stderr, "xdr_string: out of memory\n");
547*45095Smckusick 			return (FALSE);
548*45095Smckusick 		}
549*45095Smckusick 		sp[size] = 0;
550*45095Smckusick 		/* fall into ... */
551*45095Smckusick 
552*45095Smckusick 	case XDR_ENCODE:
553*45095Smckusick 		return (xdr_opaque(xdrs, sp, size));
554*45095Smckusick 
555*45095Smckusick 	case XDR_FREE:
556*45095Smckusick 		mem_free(sp, nodesize);
557*45095Smckusick 		*cpp = NULL;
558*45095Smckusick 		return (TRUE);
559*45095Smckusick 	}
560*45095Smckusick 	return (FALSE);
561*45095Smckusick }
562*45095Smckusick 
563*45095Smckusick /*
564*45095Smckusick  * Wrapper for xdr_string that can be called directly from
565*45095Smckusick  * routines like clnt_call
566*45095Smckusick  */
567*45095Smckusick bool_t
xdr_wrapstring(xdrs,cpp)568*45095Smckusick xdr_wrapstring(xdrs, cpp)
569*45095Smckusick 	XDR *xdrs;
570*45095Smckusick 	char **cpp;
571*45095Smckusick {
572*45095Smckusick 	if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
573*45095Smckusick 		return (TRUE);
574*45095Smckusick 	}
575*45095Smckusick 	return (FALSE);
576*45095Smckusick }
577