1 /* $Id: nhextxdr.c,v 1.7 2003/10/25 18:06:01 j_ali Exp $ */
2 /* Copyright (c) Slash'EM Development Team 2001-2003 */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 #include <stdlib.h>
6 #include <string.h>
7 #include "nhxdr.h"
8 
9 /*
10  * This module implements the NhExt version of XDR according to RFC 1014.
11  * It is backwards compatible with the code produced by rpcgen, and can
12  * be replaced by that for testing purposes on systems which support it.
13  * NetHack uses the extra facilities implemented here and is not therefore
14  * itself compatible with rpcgen.
15  * Rpcgen is included in the freely available RPCSRC 4.0 from Sun
16  * Microsystems, which can be downloaded in 17 shar files from
17  * ftp://bcm.tmc.edu/nfs/
18  */
19 
20 /*
21  * Note: Although this routine is called _long and takes a pointer to a
22  * long datum, it always reads and writes 32-bit values, regardless of
23  * the size of the long type. This might cause problems on a platform
24  * where long is smaller than 32 bits (but then NetHack doesn't support
25  * such platforms anyway). On platforms with longs larger than 32 bits,
26  * NetHack only needs the least significant 32 bits, and this function
27  * will correctly encode and decode this quantity.
28  */
29 
30 nhext_xdr_bool_t
nhext_xdr_long(xdrs,datum)31 nhext_xdr_long(xdrs, datum)
32 NhExtXdr *xdrs;
33 long *datum;
34 {
35     int retval = TRUE;
36     unsigned char buf[4];
37     if (xdrs->x_op == NHEXT_XDR_ENCODE) {
38 	buf[0] = *datum >> 24 & 0xff;
39 	buf[1] = *datum >> 16 & 0xff;
40 	buf[2] = *datum >> 8 & 0xff;
41 	buf[3] = *datum & 0xff;
42 	retval = xdrs->x_write(xdrs, buf, 4);
43     } else if (xdrs->x_op == NHEXT_XDR_DECODE) {
44 	retval = xdrs->x_read(xdrs, buf, 4);
45 	*datum =
46 	  (long)buf[0] << 24 | (long)buf[1] << 16 | (long)buf[2] << 8 | buf[3];
47     } else if (xdrs->x_op == NHEXT_XDR_COUNT)
48 	xdrs->x_pos += 4;
49     return retval;
50 }
51 
52 nhext_xdr_bool_t
nhext_xdr_u_long(xdrs,datum)53 nhext_xdr_u_long(xdrs, datum)
54 NhExtXdr *xdrs;
55 unsigned long *datum;
56 {
57     int retval;
58     long l;
59     l = *datum;
60     retval = nhext_xdr_long(xdrs, &l);
61     *datum = (unsigned long)l;
62     return retval;
63 }
64 
65 nhext_xdr_bool_t
nhext_xdr_short(xdrs,datum)66 nhext_xdr_short(xdrs, datum)
67 NhExtXdr *xdrs;
68 short *datum;
69 {
70     int retval;
71     long l;
72     l = *datum;
73     retval = nhext_xdr_long(xdrs, &l);
74     *datum = (short)l;
75     return retval;
76 }
77 
78 nhext_xdr_bool_t
nhext_xdr_u_short(xdrs,datum)79 nhext_xdr_u_short(xdrs, datum)
80 NhExtXdr *xdrs;
81 unsigned short *datum;
82 {
83     int retval;
84     long l;
85     l = *datum;
86     retval = nhext_xdr_long(xdrs, &l);
87     *datum = (unsigned short)l;
88     return retval;
89 }
90 
91 nhext_xdr_bool_t
nhext_xdr_int(xdrs,datum)92 nhext_xdr_int(xdrs, datum)
93 NhExtXdr *xdrs;
94 int *datum;
95 {
96     int retval;
97     long l;
98     l = *datum;
99     retval = nhext_xdr_long(xdrs, &l);
100     *datum = (int)l;
101     return retval;
102 }
103 
104 nhext_xdr_bool_t
nhext_xdr_u_int(xdrs,datum)105 nhext_xdr_u_int(xdrs, datum)
106 NhExtXdr *xdrs;
107 unsigned int *datum;
108 {
109     int retval;
110     long l;
111     l = *datum;
112     retval = nhext_xdr_long(xdrs, &l);
113     *datum = (unsigned int)l;
114     return retval;
115 }
116 
117 nhext_xdr_bool_t
nhext_xdr_char(xdrs,datum)118 nhext_xdr_char(xdrs, datum)
119 NhExtXdr *xdrs;
120 char *datum;
121 {
122     int retval;
123     long l;
124     l = *datum;
125     retval = nhext_xdr_long(xdrs, &l);
126     *datum = (char)l;
127     return retval;
128 }
129 
130 nhext_xdr_bool_t
nhext_xdr_u_char(xdrs,datum)131 nhext_xdr_u_char(xdrs, datum)
132 NhExtXdr *xdrs;
133 unsigned char *datum;
134 {
135     int retval;
136     long l;
137     l = *datum;
138     retval = nhext_xdr_long(xdrs, &l);
139     *datum = (unsigned char)l;
140     return retval;
141 }
142 
143 nhext_xdr_bool_t
nhext_xdr_enum(xdrs,datum)144 nhext_xdr_enum(xdrs, datum)
145 NhExtXdr *xdrs;
146 int *datum;
147 {
148     int retval;
149     long l;
150     l = *datum;
151     retval = nhext_xdr_long(xdrs, &l);
152     *datum = (int)l;
153     return retval;
154 }
155 
156 nhext_xdr_bool_t
nhext_xdr_bool(xdrs,datum)157 nhext_xdr_bool(xdrs, datum)
158 NhExtXdr *xdrs;
159 nhext_xdr_bool_t *datum;
160 {
161     int retval;
162     long l;
163     l = !!*datum;
164     retval = nhext_xdr_long(xdrs, &l);
165     *datum = (nhext_xdr_bool_t)l;
166     return retval;
167 }
168 
169 /*
170  * A common routine for nhext_xdr_string() and nhext_xdr_bytes()
171  */
172 
173 static nhext_xdr_bool_t
nhext_xdr_bytestring(xdrs,datum,len,maxlen,ext)174 nhext_xdr_bytestring(xdrs, datum, len, maxlen, ext)
175 NhExtXdr *xdrs;
176 char **datum;
177 unsigned int *len;
178 unsigned int maxlen, ext;
179 {
180     int retval;
181     long zero = 0;
182     if (xdrs->x_op == NHEXT_XDR_ENCODE) {
183 	if (*len > maxlen)
184 	    return FALSE;
185 	retval = nhext_xdr_u_int(xdrs, len);
186 	retval &= xdrs->x_write(xdrs, *datum, *len);
187 	if (*len & 3)
188 	    retval &= xdrs->x_write(xdrs, &zero, 4 - (*len & 3));
189     } else if (xdrs->x_op == NHEXT_XDR_DECODE) {
190 	retval = nhext_xdr_u_int(xdrs, len);
191 	if (retval) {
192 	    if (*len > maxlen)
193 		return FALSE;
194 	    if (!*datum) {
195 		*datum = malloc(MAX(NHEXT_XDR_RNDUP(*len), *len + ext));
196 		if (!*datum)
197 		    return FALSE;
198 	    }
199 	    retval &= xdrs->x_read(xdrs, *datum, NHEXT_XDR_RNDUP(*len));
200 	}
201     } else if (xdrs->x_op == NHEXT_XDR_FREE) {
202 	free(*datum);
203 	*datum = NULL;
204 	retval = TRUE;
205     } else if (xdrs->x_op == NHEXT_XDR_COUNT) {
206 	xdrs->x_pos += 4 + NHEXT_XDR_RNDUP(*len);
207 	retval = TRUE;
208     }
209     return retval;
210 }
211 
212 nhext_xdr_bool_t
nhext_xdr_string(xdrs,datum,maxsize)213 nhext_xdr_string(xdrs, datum, maxsize)
214 NhExtXdr *xdrs;
215 char **datum;
216 unsigned int maxsize;
217 {
218     int retval;
219     unsigned int slen;
220     if (xdrs->x_op == NHEXT_XDR_ENCODE || xdrs->x_op == NHEXT_XDR_COUNT)
221 	slen = strlen(*datum);
222     retval = nhext_xdr_bytestring(xdrs, datum, &slen, maxsize, 1);
223     if (retval && xdrs->x_op == NHEXT_XDR_DECODE)
224 	(*datum)[slen] = '\0';
225     return retval;
226 }
227 
228 nhext_xdr_bool_t
nhext_xdr_bytes(xdrs,datum,len,maxlen)229 nhext_xdr_bytes(xdrs, datum, len, maxlen)
230 NhExtXdr *xdrs;
231 char **datum;
232 unsigned int *len;
233 unsigned int maxlen;
234 {
235     return nhext_xdr_bytestring(xdrs, datum, len, maxlen, 0);
236 }
237 
238 nhext_xdr_bool_t
nhext_xdr_wrapstring(xdrs,datum)239 nhext_xdr_wrapstring(xdrs, datum)
240 NhExtXdr *xdrs;
241 char **datum;
242 {
243     return nhext_xdr_string(xdrs, datum, (unsigned int)-1);
244 }
245 
246 nhext_xdr_bool_t
nhext_xdr_vector(xdrs,addr,len,size,codec)247 nhext_xdr_vector(xdrs, addr, len, size, codec)
248 NhExtXdr *xdrs;
249 char *addr;
250 unsigned int len;
251 unsigned int size;
252 nhext_xdr_bool_t (*codec)(NhExtXdr *, void *);
253 {
254     for(; len > 0; len--) {
255 	if (!(*codec)(xdrs, addr))
256 	    return FALSE;
257 	addr += size;
258     }
259     return TRUE;
260 }
261 
262 nhext_xdr_bool_t
nhext_xdr_array(xdrs,addr,len,maxlen,size,codec)263 nhext_xdr_array(xdrs, addr, len, maxlen, size, codec)
264 NhExtXdr *xdrs;
265 char **addr;
266 unsigned int *len;
267 unsigned int maxlen;
268 unsigned int size;
269 nhext_xdr_bool_t (*codec)(NhExtXdr *, void *);
270 {
271     int retval;
272     long slen;
273     if (!nhext_xdr_u_int(xdrs, len))
274 	return FALSE;
275     slen = *len;
276     if (xdrs->x_op != NHEXT_XDR_FREE && slen > maxlen)
277 	return FALSE;
278     if (xdrs->x_op == NHEXT_XDR_DECODE && !*addr && slen) {
279 	*addr = calloc(slen, size);
280 	if (!*addr)
281 	    return FALSE;
282     }
283     retval = nhext_xdr_vector(xdrs, *addr, slen, size, codec);
284     if (xdrs->x_op == NHEXT_XDR_FREE) {
285 	free(*addr);
286 	*addr = NULL;
287     }
288     return retval;
289 }
290