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