]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/zwgc/notice.c
r4264@bucket (orig r254): kcr | 2008-01-20 22:11:44 -0500
[1ts-debian.git] / zephyr / zwgc / notice.c
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
3  * client.
4  *
5  *      Created by:     Marc Horowitz <marc@athena.mit.edu>
6  *
7  *      $Id$
8  *
9  *      Copyright (c) 1989 by the Massachusetts Institute of Technology.
10  *      For copying and distribution information, see the file
11  *      "mit-copyright.h".
12  */
13
14 #include <sysdep.h>
15
16 #if (!defined(lint) && !defined(SABER))
17 static const char rcsid_notice_c[] = "$Id$";
18 #endif
19
20 #include <zephyr/mit-copyright.h>
21
22 /****************************************************************************/
23 /*                                                                          */
24 /*         Module containing code to extract a notice's fields:             */
25 /*                                                                          */
26 /****************************************************************************/
27
28 #include <zephyr/zephyr.h>
29 #include <arpa/inet.h>
30 #include "new_memory.h"
31 #include "error.h"
32 #include "variables.h"
33 #include "notice.h"
34
35 /*
36  *    int count_nulls(char *data, int length)
37  *        Requires: length>=0
38  *        Effects: Returns the # of nulls in data[0]..data[length-1]
39  */
40
41 int
42 count_nulls(char *data,
43             int length)
44 {
45     int count = 0;
46
47     for (; length; data++, length--)
48       if (!*data)
49         count++;
50
51     return(count);
52 }
53
54 /*
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)
67  */
68
69 string
70 get_next_field(char **data_p,
71                int *length_p)
72 {
73     char *data = *data_p;
74     int length = *length_p;
75     char *ptr;
76
77     for (ptr=data; length; ptr++, length--)
78       if (!*ptr) {
79           *data_p = ptr+1;
80           *length_p = length-1;
81           return(string_Copy(data));
82       }
83
84     length = *length_p;
85     *data_p = ptr;
86     *length_p = 0;
87     return(string_CreateFromData(data, length));
88 }
89
90 /*
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),
98  *                 "" is returned.
99  */
100
101 string get_field(char *data,
102                  int length,
103                  int num)
104 {
105     /*
106      * While num>1 and there are fields left, skip a field & decrement num:
107      */
108     while (length && num>1) {
109         if (!*data)
110           num--;
111         length--;
112         data++;
113     }
114
115     /*
116      * If any more fields left, the first field is the one we want.
117      * Otherwise, there is no such field as num -- return "".
118      */
119     if (length)
120       return(get_next_field(&data, &length));
121     else
122       return(string_Copy(""));
123 }
124
125 /*
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
131  *                be freed.
132  */
133
134 string
135 convert_nulls_to_newlines(char *data,
136                           int length)
137 {
138     char *result, *ptr;
139     char c;
140
141     result = (char *) malloc(length+1);
142     result[length] = '\0';
143     
144     for (ptr=result; length; data++, ptr++, length--)
145       *ptr = (c = *data) ? c : '\n';
146
147     return(result);
148 }
149
150
151 /*
152  *  Internal Routine:
153  *
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
157  *                 eventually.
158  */
159
160 static string
161 z_kind_to_ascii(ZNotice_Kind_t z_kind)
162 {
163     string result;
164
165     switch (z_kind) {
166       case UNSAFE:
167         result = "unsafe";
168         break;
169
170       case UNACKED:
171         result = "unacked";
172         break;
173
174       case ACKED:
175         result = "acked";
176         break;
177
178       case HMACK:
179         result = "hmack";
180         break;
181
182       case HMCTL:
183         result = "hmctl";
184         break;
185
186       case SERVACK:
187         result = "servack";
188         break;
189
190       case SERVNAK:
191         result = "servnak";
192         break;
193
194       case CLIENTACK:
195         result = "clientack";
196         break;
197
198       case STAT:
199         result = "stat";
200         break;
201
202       default:
203         result = "<unknown kind>";
204         break;
205     }
206     
207     return(string_Copy(result));
208 }
209
210 /*
211  *  Internal Routine:
212  *
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
216  *                 eventually.
217  */
218
219 static string
220 z_auth_to_ascii(int z_auth)
221 {
222     string result;
223
224     switch (z_auth) {
225       case ZAUTH_FAILED:
226         result = "forged";
227         break;
228
229       case ZAUTH_NO:
230         result = "no";
231         break;
232         
233       case ZAUTH_YES:
234         result = "yes";
235         break;
236
237       default:
238         result = "unknown";
239         break;
240     }
241     
242     return(string_Copy(result));
243 }
244
245 /*
246  *    char *decode_notice(ZNotice_t *notice)
247  *        Modifies: various description language variables
248  *        Effects:
249  */
250
251 char *
252 decode_notice(ZNotice_t *notice,
253               char *hostname)
254 {
255     char *temp;
256     string time, notyear, year, date_string, time_string;
257
258     /*
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:
262      */
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));
274
275     /*
276      * Set $sender to the name of the notice sender except first strip off the
277      * realm name if it is the local realm:
278      */
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));
283     else
284       var_set_variable("sender", notice->z_sender);
285     
286     /*
287      * Convert time & date notice was sent to ascii.  The $time
288      * has the format "01:03:52" while $date has the format
289      * "Sun Sep 16 1973".
290      */
291     {
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;
295       time = ctime(&sec);
296     }
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);
302     free(notyear);
303     free(year);
304
305     /*
306      * Convert host notice sent from to ascii:
307      */
308     var_set_variable("fromhost", hostname ? hostname :
309                      inet_ntoa(notice->z_sender_addr));
310
311     /*
312      * Set $message to the message field of the notice with nulls changed
313      * to newlines:
314      */
315     var_set_variable_then_free_value("message",
316                      convert_nulls_to_newlines(notice->z_message,
317                                                notice->z_message_len));
318
319     /*
320      * Decide if its a control notice.  If so, return the notice's
321      * opcode.  Otherwise, return NULL:
322      */
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);
326     return(0);
327 }