1 #ifndef lint
2 static char *rcsid = "$Id: imdata.c,v 1.7 1994/06/02 02:20:23 ishisone Exp $";
3 #endif
4 /*
5  * Copyright (c) 1994  Software Research Associates, Inc.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation for any purpose and without fee is hereby granted, provided
9  * that the above copyright notice appear in all copies and that both that
10  * copyright notice and this permission notice appear in supporting
11  * documentation, and that the name of Software Research Associates not be
12  * used in advertising or publicity pertaining to distribution of the
13  * software without specific, written prior permission.  Software Research
14  * Associates makes no representations about the suitability of this software
15  * for any purpose.  It is provided "as is" without express or implied
16  * warranty.
17  *
18  * Author:  Makoto Ishisone, Software Research Associates, Inc., Japan
19  */
20 
21 #include "im.h"
22 
23 #define B_GET16(p)	(((p)[0]<<8) + (p)[1])
24 #define B_GET32(p)	(((p)[0]<<24) + ((p)[1]<<16) + ((p)[2]<<8) + (p)[3])
25 #define L_GET16(p)	((p)[0] + ((p)[1]<<8))
26 #define L_GET32(p)	((p)[0] + ((p)[1]<<8) + ((p)[2]<<16) + ((p)[3] << 24))
27 
28 #define B_PUT16(x, p)	(p)[0] = ((x)>>8) & 0xff; (p)[1] = (x) & 0xff
29 #define B_PUT32(x, p)	(p)[0] = ((x)>>24) & 0xff; (p)[1] = ((x)>>16) & 0xff; \
30 			(p)[2] = ((x)>>8) & 0xff; (p)[3] = (x) & 0xff
31 #define L_PUT16(x, p)	(p)[0] = (x) & 0xff; (p)[1] = ((x)>>8) & 0xff
32 #define L_PUT32(x, p)	(p)[0] = (x) & 0xff; (p)[1] = ((x)>>8) & 0xff; \
33 			(p)[2] = ((x)>>16) & 0xff; (p)[3] = ((x)>>24) & 0xff;
34 
35 int
IMGetC8(conn,offset)36 IMGetC8(conn, offset)
37 IMConnection *conn;
38 int offset;
39 {
40     IMBuffer *ibp = IM_INBUF(conn);
41     int x;
42 
43     x = *((unsigned char *)IMBUFDATA(ibp) + offset);
44     return x;
45 }
46 
47 unsigned int
IMGetC16(conn,offset)48 IMGetC16(conn, offset)
49 IMConnection *conn;
50 int offset;
51 {
52     IMBuffer *ibp = IM_INBUF(conn);
53     unsigned char *p = (unsigned char *)IMBUFDATA(ibp) + offset;
54     unsigned int x;
55 
56     if (conn->byte_order == ORDER_BIG) {
57 	x = B_GET16(p);
58     } else {
59 	x = L_GET16(p);
60     }
61 
62     return x;
63 }
64 
65 int
IMGetI16(conn,offset)66 IMGetI16(conn, offset)
67 IMConnection *conn;
68 int offset;
69 {
70     long x;
71 
72     x = (long)IMGetC16(conn, offset);
73     return (x < 32768) ? (int)x : (int)(x - 65536L);
74 }
75 
76 unsigned long
IMGetC32(conn,offset)77 IMGetC32(conn, offset)
78 IMConnection *conn;
79 int offset;
80 {
81     IMBuffer *ibp = IM_INBUF(conn);
82     unsigned char *p = (unsigned char *)IMBUFDATA(ibp) + offset;
83     unsigned long x;
84 
85     if (conn->byte_order == ORDER_BIG) {
86 	x = B_GET32(p);
87     } else {
88 	x = L_GET32(p);
89     }
90 
91     return x;
92 }
93 
94 void
IMGetString(conn,offset,buf,len)95 IMGetString(conn, offset, buf, len)
96 IMConnection *conn;
97 int offset;
98 char *buf;
99 int len;
100 {
101     IMBuffer *ibp = IM_INBUF(conn);
102     char *p = IMBUFDATA(ibp) + offset;
103 
104     bcopy(p, buf, len);
105     buf[len] = '\0';
106 }
107 
108 void
IMPutC8(conn,x)109 IMPutC8(conn, x)
110 IMConnection *conn;
111 int x;
112 {
113     IMBuffer *ibp = IM_OUTBUF(conn);
114     unsigned char c = (unsigned char)x;
115 
116     IMBufAdd(ibp, (char *)&c, 1);
117 }
118 
119 void
IMPutC16(conn,x)120 IMPutC16(conn, x)
121 IMConnection *conn;
122 unsigned int x;
123 {
124     IMBuffer *ibp = IM_OUTBUF(conn);
125     unsigned char *p = (unsigned char *)IMBufAlloc(ibp, 2);
126 
127     if (conn->byte_order == ORDER_BIG) {
128 	B_PUT16(x, p);
129     } else {
130 	L_PUT16(x, p);
131     }
132 }
133 
134 void
IMPutC32(conn,x)135 IMPutC32(conn, x)
136 IMConnection *conn;
137 unsigned long x;
138 {
139     IMBuffer *ibp = IM_OUTBUF(conn);
140     unsigned char *p = (unsigned char *)IMBufAlloc(ibp, 4);
141 
142     if (conn->byte_order == ORDER_BIG) {
143 	B_PUT32(x, p);
144     } else {
145 	L_PUT32(x, p);
146     }
147 }
148 
149 void
IMPutI16(conn,x)150 IMPutI16(conn, x)
151 IMConnection *conn;
152 int x;
153 {
154     IMBuffer *ibp = IM_OUTBUF(conn);
155     unsigned char *p = (unsigned char *)IMBufAlloc(ibp, 2);
156 
157     if (conn->byte_order == ORDER_BIG) {
158 	B_PUT16(x, p);
159     } else {
160 	L_PUT16(x, p);
161     }
162 }
163 
164 void
IMPutString(conn,s,len)165 IMPutString(conn, s, len)
166 IMConnection *conn;
167 char *s;
168 int len;
169 {
170     if (len < 0) len = strlen(s);
171     IMBufAdd(&conn->out_buf, s, len);
172 }
173 
174 void
IMPutPad(conn)175 IMPutPad(conn)
176 IMConnection *conn;
177 {
178     int remainder;
179     int npad;
180     static char padding[] = { 0, 0, 0, 0 };
181 
182     if ((remainder = IMBUFLEN(&conn->out_buf) % 4) != 0) {
183 	npad = 4 - remainder;
184 	IMBufAdd(IM_OUTBUF(conn), padding, npad);
185     }
186 }
187 
188 void
IMRewriteC16(conn,pos,x)189 IMRewriteC16(conn, pos, x)
190 IMConnection *conn;
191 int pos;
192 unsigned int x;
193 {
194     IMBuffer *ibp = IM_OUTBUF(conn);
195     unsigned char p[2];
196 
197     if (conn->byte_order == ORDER_BIG) {
198 	B_PUT16(x, p);
199     } else {
200 	L_PUT16(x, p);
201     }
202     IMBufOverwrite(ibp, pos, (char *)p, 2);
203 }
204 
205 int
IMWritePos(conn)206 IMWritePos(conn)
207 IMConnection *conn;
208 {
209     IMBuffer *ibp = IM_OUTBUF(conn);
210 
211     return IMBUFLEN(ibp);
212 }
213 
214 int
IMPutHeader(conn,major,minor,arglen)215 IMPutHeader(conn, major, minor, arglen)
216 IMConnection *conn;
217 int major;
218 int minor;
219 int arglen;
220 {
221     int offset;
222 
223     offset = IMBUFLEN(&conn->out_buf);
224     arglen = (arglen + 3) / 4;
225 #ifdef XIM_BC
226     if (conn->has_length_bug) arglen *= 4;
227 #endif
228     IMPutC8(conn, major);
229     IMPutC8(conn, minor);
230     IMPutC16(conn, (unsigned int)arglen);
231     return offset;
232 }
233 
234 void
IMFinishRequest(conn,offset)235 IMFinishRequest(conn, offset)
236 IMConnection *conn;
237 int offset;
238 {
239     IMBuffer *ibp = IM_OUTBUF(conn);
240     unsigned int arglen;
241 
242     /*
243      * Append padding bytes, if needed.
244      */
245     IMPutPad(conn);
246 
247     /*
248      * Offset points the beginning of the request.
249      * Following is a Request header which is 4-byte long.
250      */
251     arglen = (unsigned int)((IMBUFLEN(ibp) - offset - 4) / 4);
252 #ifdef XIM_BC
253     if (conn->has_length_bug) arglen *= 4;
254 #endif
255 
256     /*
257      * rewrite the length field of the request header.
258      */
259     IMRewriteC16(conn, offset + 2, arglen);
260 
261     IMSchedule(conn, SCHED_WRITE);
262 }
263 
264 void
IMCancelRequest(conn,offset)265 IMCancelRequest(conn, offset)
266 IMConnection *conn;
267 int offset;
268 {
269     IMBuffer *ibp = IM_OUTBUF(conn);
270 
271     IMBufDiscard(ibp, offset - IMBUFLEN(ibp));
272 }
273 
274 void
IMSendSimpleRequest(conn,major,minor)275 IMSendSimpleRequest(conn, major, minor)
276 IMConnection *conn;
277 int major;
278 int minor;
279 {
280     IMPutC8(conn, major);
281     IMPutC8(conn, minor);
282     /*
283      * This function (IMSendSimpleRequest) might be called when
284      * client's byte order is yet unknown, so usually it is unwise to
285      * call IMPutC16().  But in this particular case where the value
286      * to be put is zero, it is perfectly ok.
287      */
288     IMPutC16(conn, 0);
289     IMSchedule(conn, SCHED_WRITE);
290 }
291 
292 void
IMSendRequestWithIC(conn,major,minor,icp)293 IMSendRequestWithIC(conn, major, minor, icp)
294 IMConnection *conn;
295 int major;
296 int minor;
297 IMIC *icp;
298 {
299     (void)IMPutHeader(conn, major, minor, 4);
300     IMPutC16(conn, icp->im->id);
301     IMPutC16(conn, icp->id);
302     IMSchedule(conn, SCHED_WRITE);
303 }
304 
305 void
IMSendError(conn,code,imid,icid,msg)306 IMSendError(conn, code, imid, icid, msg)
307 IMConnection *conn;
308 int code;
309 unsigned int imid;
310 unsigned int icid;
311 char *msg;
312 {
313     int offset;
314     int msg_len;
315     unsigned int valid_flag = 0;
316 
317     msg_len = strlen(msg);
318 
319     if (imid != 0) valid_flag |= 1;
320     if (icid != 0) valid_flag |= 2;
321 
322     offset = IMPutHeader(conn, XIM_ERROR, 0, 0);
323     IMPutC16(conn, imid);
324     IMPutC16(conn, icid);
325     IMPutC16(conn, valid_flag);
326     IMPutC16(conn, (unsigned int)code);
327     IMPutC16(conn, (unsigned int)msg_len);
328     IMPutC16(conn, 0);
329     IMPutString(conn, msg, msg_len);
330     IMFinishRequest(conn, offset);
331 }
332 
333 void
IMSendBadProtocol(conn,msg)334 IMSendBadProtocol(conn, msg)
335 IMConnection *conn;
336 char *msg;
337 {
338     IMSendError(conn, IMBadProtocol, 0, 0, msg);
339 }
340 
341 void
IMSendBadLength(conn,imid,icid)342 IMSendBadLength(conn, imid, icid)
343 IMConnection *conn;
344 unsigned int imid;
345 unsigned int icid;
346 {
347     IMSendError(conn, IMBadSomething, imid, icid, "Bad request length");
348 }
349