1 /* This file is part of the Project Athena Zephyr Notification System.
2 * It is one of the source files comprising zwgc, the Zephyr WindowGram
5 * Created by: Marc Horowitz <marc@athena.mit.edu>
9 * Copyright (c) 1989 by the Massachusetts Institute of Technology.
10 * For copying and distribution information, see the file
16 #if (!defined(lint) && !defined(SABER))
17 static const char rcsid_notice_c[] = "$Id$";
20 #include <zephyr/mit-copyright.h>
22 /****************************************************************************/
24 /* Module containing code to extract a notice's fields: */
26 /****************************************************************************/
28 #include <zephyr/zephyr.h>
29 #include <arpa/inet.h>
30 #include "new_memory.h"
32 #include "variables.h"
36 * int count_nulls(char *data, int length)
38 * Effects: Returns the # of nulls in data[0]..data[length-1]
42 count_nulls(char *data,
47 for (; length; data++, length--)
55 * string get_next_field(char **data_p, int *length_p)
56 * Requires: *length_p >= 0
57 * Modifies: *data_p, *length_p
58 * Effects: Treats (*data_p)[0], (*data_p)[1], ... (*data_p)[length-1]
59 * as a series of null-seperated fields. This function
60 * returns a copy of the first field on the heap. This
61 * string must eventually be freed. Also, *data_p is
62 * advanced and *length_p decreased so that another
63 * call to this procedure with the same arguments will
64 * return the second field. The next call will return
65 * the third field, etc. "" is returned if 0 fields
66 * remain. (this is the case when *length_p == 0)
70 get_next_field(char **data_p,
74 int length = *length_p;
77 for (ptr=data; length; ptr++, length--)
81 return(string_Copy(data));
87 return(string_CreateFromData(data, length));
91 * string get_field(char *data, int length, int num)
92 * Requires: length>=0, num>0
93 * Effects: Treats data[0]..data[length-1] as a series of
94 * null-seperated fields. This function returns a copy of
95 * the num'th field (numbered from 1 in this case) on the
96 * heap. This string must eventually be freed. If there
97 * is no num'th field (because num<1 or num># of fields),
101 string get_field(char *data,
106 * While num>1 and there are fields left, skip a field & decrement num:
108 while (length && num>1) {
116 * If any more fields left, the first field is the one we want.
117 * Otherwise, there is no such field as num -- return "".
120 return(get_next_field(&data, &length));
122 return(string_Copy(""));
126 * string convert_nulls_to_newlines(data, length)
127 * Requires: length>=0, malloc never returns NULL
128 * Effects: Takes data[0]..data[length-1], converts all nulls to
129 * newlines ('\n') and returns the result as a null-terminated
130 * string on the heap. The returned string must eventually
135 convert_nulls_to_newlines(char *data,
141 result = (char *) malloc(length+1);
142 result[length] = '\0';
144 for (ptr=result; length; data++, ptr++, length--)
145 *ptr = (c = *data) ? c : '\n';
154 * string z_kind_to_ascii(ZNotice_Kind_t z_kind)
155 * Effects: Returns an ascii representation for z_kind.
156 * The string returned is on the heap and must be freed
161 z_kind_to_ascii(ZNotice_Kind_t z_kind)
195 result = "clientack";
203 result = "<unknown kind>";
207 return(string_Copy(result));
213 * string z_auth_to_ascii(int z_auth)
214 * Effects: Returns an ascii representation for z_auth.
215 * The string returned is on the heap and must be freed
220 z_auth_to_ascii(int z_auth)
242 return(string_Copy(result));
246 * char *decode_notice(ZNotice_t *notice)
247 * Modifies: various description language variables
252 decode_notice(ZNotice_t *notice,
256 string time, notyear, year, date_string, time_string;
259 * Convert useful notice fields to ascii and store away in
260 * description language variables for later use by the
261 * the user's program:
263 var_set_variable("zephyr_version", notice->z_version);
264 var_set_variable("class", notice->z_class);
265 var_set_variable("instance", notice->z_class_inst);
266 var_set_variable("opcode", notice->z_opcode);
267 var_set_variable("default", notice->z_default_format);
268 var_set_variable("recipient",
269 (notice->z_recipient[0] ? notice->z_recipient : "*"));
270 var_set_variable("fullsender", notice->z_sender);
271 var_set_variable_to_number("port", (int)ntohs(notice->z_port));
272 var_set_variable_then_free_value("kind", z_kind_to_ascii(notice->z_kind));
273 var_set_variable_then_free_value("auth", z_auth_to_ascii(notice->z_auth));
276 * Set $sender to the name of the notice sender except first strip off the
277 * realm name if it is the local realm:
279 if ( (temp=strchr(notice->z_sender,'@')) && string_Eq(temp+1, ZGetRealm()) )
280 var_set_variable_then_free_value("sender",
281 string_CreateFromData(notice->z_sender,
282 temp-notice->z_sender));
284 var_set_variable("sender", notice->z_sender);
287 * Convert time & date notice was sent to ascii. The $time
288 * has the format "01:03:52" while $date has the format
292 /* the fields of struct timeval might not be the right type to pass
293 to ctime, so use a temporary */
294 time_t sec = notice->z_time.tv_sec;
297 time_string = string_CreateFromData(time+11,8);
298 var_set_variable_then_free_value("time", time_string);
299 date_string = string_Concat(notyear=string_CreateFromData(time,11),
300 year=string_CreateFromData(time+20,4));
301 var_set_variable_then_free_value("date", date_string);
306 * Convert host notice sent from to ascii:
308 var_set_variable("fromhost", hostname ? hostname :
309 inet_ntoa(notice->z_sender_addr));
312 * Set $message to the message field of the notice with nulls changed
315 var_set_variable_then_free_value("message",
316 convert_nulls_to_newlines(notice->z_message,
317 notice->z_message_len));
320 * Decide if its a control notice. If so, return the notice's
321 * opcode. Otherwise, return NULL:
323 if ((strcasecmp(notice->z_class, WG_CTL_CLASS)==0) && /* <<<>>> */
324 (strcasecmp(notice->z_class_inst, WG_CTL_USER)==0))
325 return(notice->z_opcode);