[gaim-migrate @ 3063]
[pidgin-git.git] / src / protocols / zephyr / ZParseNot.c
blob2a90114dcabebba59e7cd7cb26ca4811cb6ae385
1 /* This file is part of the Project Athena Zephyr Notification System.
2 * It contains source for the ZParseNotice function.
4 * Created by: Robert French
6 * $Source$
7 * $Author: warmenhoven $
9 * Copyright (c) 1987,1991 by the Massachusetts Institute of Technology.
10 * For copying and distribution information, see the file
11 * "mit-copyright.h".
13 /* $Header$ */
15 #ifndef lint
16 static char rcsid_ZParseNotice_c[] =
17 "$Zephyr: /mit/zephyr/src/lib/RCS/ZParseNotice.c,v 1.22 91/03/29 03:34:46 raeburn Exp $";
18 #endif
20 #include <internal.h>
22 /* Assume that strlen is efficient on this machine... */
23 #define next_field(ptr) ptr += strlen (ptr) + 1
25 #if defined (__GNUC__) && defined (__vax__)
26 #undef next_field
27 static __inline__ char * Istrend (char *str) {
29 * This should be faster on VAX models outside the 2 series. Don't
30 * use it if you are using MicroVAX 2 servers. If you are using a
31 * VS2 server, use something like
32 * #define next_field(ptr) while(*ptr++)
33 * instead of this code.
35 * This requires use of GCC to get the optimized code, but
36 * everybody uses GCC, don't they? :-)
38 register char *str2 asm ("r1");
39 /* Assumes that no field is longer than 64K.... */
40 asm ("locc $0,$65535,(%1)" : "=r" (str2) : "r" (str) : "r0");
41 return str2;
43 #define next_field(ptr) ptr = Istrend (ptr) + 1
44 #endif
46 #ifdef mips
47 #undef next_field
49 * The compiler doesn't optimize this macro as well as it does the
50 * following function.
52 #define next_fieldXXX(ptr) do{register unsigned c1,c2;c1= *ptr; \
53 while((ptr++,c2= *ptr,c1)&&(ptr++,c1= *ptr,c2));}while(0)
54 static char *next_field_1 (s) char *s; {
56 * Calling overhead is still present, but this routine is faster
57 * than strlen, and doesn't bother with some of the other math
58 * that we'd just have to undo later anyways.
60 register unsigned c1 = *s, c2;
61 while (1) {
62 s++; c2 = *s; if (c1 == 0) break;
63 s++; c1 = *s; if (c2 == 0) break;
64 s++; c2 = *s; if (c1 == 0) break;
65 s++; c1 = *s; if (c2 == 0) break;
67 return s;
69 #define next_field(ptr) ptr=next_field_1(ptr)
70 #endif
72 Code_t ZParseNotice(buffer, len, notice)
73 char *buffer;
74 int len;
75 ZNotice_t *notice;
77 char *ptr, *end;
78 unsigned long temp;
79 int maj, numfields, i;
81 #ifdef __LINE__
82 int lineno;
83 /* Note: This definition of BAD eliminates lint and compiler
84 * complains about the "while (0)", but require that the macro not
85 * be used as the "then" part of an "if" statement that also has
86 * an "else" clause.
88 #define BAD_PACKET {lineno=__LINE__;goto badpkt;}
89 /* This one gets lint/compiler complaints. */
90 /*#define BAD do{lineno=__LINE__;goto badpkt;}while(0)*/
91 #else
92 #define BAD_PACKET goto badpkt
93 #endif
95 (void) memset((char *)notice, 0, sizeof(ZNotice_t));
97 ptr = buffer;
98 end = buffer+len;
100 notice->z_packet = buffer;
102 notice->z_version = ptr;
103 if (strncmp(ptr, ZVERSIONHDR, sizeof(ZVERSIONHDR) - 1))
104 return (ZERR_VERS);
105 ptr += sizeof(ZVERSIONHDR) - 1;
106 if (!*ptr) {
107 #ifdef Z_DEBUG
108 Z_debug ("ZParseNotice: null version string");
109 #endif
110 return ZERR_BADPKT;
112 maj = atoi(ptr);
113 if (maj != ZVERSIONMAJOR)
114 return (ZERR_VERS);
115 next_field (ptr);
117 if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
118 BAD_PACKET;
119 numfields = temp;
120 next_field (ptr);
122 /*XXX 3 */
123 numfields -= 2; /* numfields, version, and checksum */
124 if (numfields < 0) {
125 #ifdef __LINE__
126 lineno = __LINE__;
127 badpkt:
128 #ifdef Z_DEBUG
129 Z_debug ("ZParseNotice: bad packet from %s/%d (line %d)",
130 inet_ntoa (notice->z_uid.zuid_addr.s_addr),
131 notice->z_port, lineno);
132 #endif
133 #else
134 badpkt:
135 #ifdef Z_DEBUG
136 Z_debug ("ZParseNotice: bad packet from %s/%d",
137 inet_ntoa (notice->z_uid.zuid_addr.s_addr),
138 notice->z_port);
139 #endif
140 #endif
141 return ZERR_BADPKT;
144 if (numfields) {
145 if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
146 BAD_PACKET;
147 notice->z_kind = temp;
148 numfields--;
149 next_field (ptr);
151 else
152 BAD_PACKET;
154 if (numfields) {
155 if (ZReadAscii(ptr, end-ptr, (unsigned char *)&notice->z_uid,
156 sizeof(ZUnique_Id_t)) == ZERR_BADFIELD)
157 BAD_PACKET;
158 notice->z_time.tv_sec = ntohl((u_long) notice->z_uid.tv.tv_sec);
159 notice->z_time.tv_usec = ntohl((u_long) notice->z_uid.tv.tv_usec);
160 numfields--;
161 next_field (ptr);
163 else
164 BAD_PACKET;
166 if (numfields) {
167 if (ZReadAscii16(ptr, end-ptr, &notice->z_port) == ZERR_BADFIELD)
168 BAD_PACKET;
169 notice->z_port = htons(notice->z_port);
170 numfields--;
171 next_field (ptr);
173 else
174 BAD_PACKET;
176 if (numfields) {
177 if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
178 BAD_PACKET;
179 notice->z_auth = temp;
180 numfields--;
181 next_field (ptr);
183 else
184 BAD_PACKET;
185 notice->z_checked_auth = ZAUTH_UNSET;
187 if (numfields) {
188 if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
189 BAD_PACKET;
190 notice->z_authent_len = temp;
191 numfields--;
192 next_field (ptr);
194 else
195 BAD_PACKET;
197 if (numfields) {
198 notice->z_ascii_authent = ptr;
199 numfields--;
200 next_field (ptr);
202 else
203 BAD_PACKET;
205 if (numfields) {
206 notice->z_class = ptr;
207 numfields--;
208 next_field (ptr);
210 else
211 notice->z_class = "";
213 if (numfields) {
214 notice->z_class_inst = ptr;
215 numfields--;
216 next_field (ptr);
218 else
219 notice->z_class_inst = "";
221 if (numfields) {
222 notice->z_opcode = ptr;
223 numfields--;
224 next_field (ptr);
226 else
227 notice->z_opcode = "";
229 if (numfields) {
230 notice->z_sender = ptr;
231 numfields--;
232 next_field (ptr);
234 else
235 notice->z_sender = "";
237 if (numfields) {
238 notice->z_recipient = ptr;
239 numfields--;
240 next_field (ptr);
242 else
243 notice->z_recipient = "";
245 if (numfields) {
246 notice->z_default_format = ptr;
247 numfields--;
248 next_field (ptr);
250 else
251 notice->z_default_format = "";
253 /*XXX*/
254 if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
255 BAD_PACKET;
256 notice->z_checksum = temp;
257 numfields--;
258 next_field (ptr);
260 if (numfields) {
261 notice->z_multinotice = ptr;
262 numfields--;
263 next_field (ptr);
265 else
266 notice->z_multinotice = "";
268 if (numfields) {
269 if (ZReadAscii(ptr, end-ptr, (unsigned char *)&notice->z_multiuid,
270 sizeof(ZUnique_Id_t)) == ZERR_BADFIELD)
271 BAD_PACKET;
272 notice->z_time.tv_sec = ntohl((u_long) notice->z_multiuid.tv.tv_sec);
273 notice->z_time.tv_usec = ntohl((u_long) notice->z_multiuid.tv.tv_usec);
274 numfields--;
275 next_field (ptr);
277 else
278 notice->z_multiuid = notice->z_uid;
280 for (i=0;i<Z_MAXOTHERFIELDS && numfields;i++,numfields--) {
281 notice->z_other_fields[i] = ptr;
282 next_field (ptr);
284 notice->z_num_other_fields = i;
286 for (i=0;i<numfields;i++)
287 next_field (ptr);
289 notice->z_message = (caddr_t) ptr;
290 notice->z_message_len = len-(ptr-buffer);
292 return (ZERR_NONE);