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>
7 * $Id: notice.c,v 1.12 1999/01/22 23:20:28 ghudson Exp $
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: notice.c,v 1.12 1999/01/22 23:20:28 ghudson Exp $";
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]
41 int count_nulls(data, length)
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)
69 string get_next_field(data_p, length_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(data, length, num)
107 * While num>1 and there are fields left, skip a field & decrement num:
109 while (length && num>1) {
117 * If any more fields left, the first field is the one we want.
118 * Otherwise, there is no such field as num -- return "".
121 return(get_next_field(&data, &length));
123 return(string_Copy(""));
127 * string convert_nulls_to_newlines(data, length)
128 * Requires: length>=0, malloc never returns NULL
129 * Effects: Takes data[0]..data[length-1], converts all nulls to
130 * newlines ('\n') and returns the result as a null-terminated
131 * string on the heap. The returned string must eventually
135 string convert_nulls_to_newlines(data, length)
142 result = (char *) malloc(length+1);
143 result[length] = '\0';
145 for (ptr=result; length; data++, ptr++, length--)
146 *ptr = (c = *data) ? c : '\n';
155 * string z_kind_to_ascii(ZNotice_Kind_t z_kind)
156 * Effects: Returns an ascii representation for z_kind.
157 * The string returned is on the heap and must be freed
161 static string z_kind_to_ascii(z_kind)
162 ZNotice_Kind_t z_kind;
196 result = "clientack";
204 result = "<unknown kind>";
208 return(string_Copy(result));
214 * string z_auth_to_ascii(int z_auth)
215 * Effects: Returns an ascii representation for z_auth.
216 * The string returned is on the heap and must be freed
220 static string z_auth_to_ascii(z_auth)
243 return(string_Copy(result));
247 * char *decode_notice(ZNotice_t *notice)
248 * Modifies: various description language variables
252 char *decode_notice(notice, hostname)
257 string time, notyear, year, date_string, time_string;
260 * Convert useful notice fields to ascii and store away in
261 * description language variables for later use by the
262 * the user's program:
264 var_set_variable("zephyr_version", notice->z_version);
265 var_set_variable("class", notice->z_class);
266 var_set_variable("instance", notice->z_class_inst);
267 var_set_variable("opcode", notice->z_opcode);
268 var_set_variable("default", notice->z_default_format);
269 var_set_variable("recipient",
270 (notice->z_recipient[0] ? notice->z_recipient : "*"));
271 var_set_variable("fullsender", notice->z_sender);
272 var_set_variable_to_number("port", (int)notice->z_port);
273 var_set_variable_then_free_value("kind", z_kind_to_ascii(notice->z_kind));
274 var_set_variable_then_free_value("auth", z_auth_to_ascii(notice->z_auth));
277 * Set $sender to the name of the notice sender except first strip off the
278 * realm name if it is the local realm:
280 if ( (temp=strchr(notice->z_sender,'@')) && string_Eq(temp+1, ZGetRealm()) )
281 var_set_variable_then_free_value("sender",
282 string_CreateFromData(notice->z_sender,
283 temp-notice->z_sender));
285 var_set_variable("sender", notice->z_sender);
288 * Convert time & date notice was sent to ascii. The $time
289 * has the format "01:03:52" while $date has the format
293 /* the fields of struct timeval might not be the right type to pass
294 to ctime, so use a temporary */
295 time_t sec = notice->z_time.tv_sec;
298 time_string = string_CreateFromData(time+11,8);
299 var_set_variable_then_free_value("time", time_string);
300 date_string = string_Concat(notyear=string_CreateFromData(time,11),
301 year=string_CreateFromData(time+20,4));
302 var_set_variable_then_free_value("date", date_string);
307 * Convert host notice sent from to ascii:
309 var_set_variable("fromhost", hostname ? hostname :
310 inet_ntoa(notice->z_sender_addr));
313 * Set $message to the message field of the notice with nulls changed
316 var_set_variable_then_free_value("message",
317 convert_nulls_to_newlines(notice->z_message,
318 notice->z_message_len));
321 * Decide if its a control notice. If so, return the notice's
322 * opcode. Otherwise, return NULL:
324 if ((strcasecmp(notice->z_class, WG_CTL_CLASS)==0) && /* <<<>>> */
325 (strcasecmp(notice->z_class_inst, WG_CTL_USER)==0))
326 return(notice->z_opcode);