]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/zwgc/notice.c
new upstream tarball
[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: notice.c 2295 2009-03-15 22:13:16Z kcr $
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: notice.c 2295 2009-03-15 22:13:16Z kcr $";
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 #ifdef CMU_ZWGCPLUS
35 #include <pwd.h>
36 #include "plus.h"
37 #endif
38
39 /*
40  *    int count_nulls(char *data, int length)
41  *        Requires: length>=0
42  *        Effects: Returns the # of nulls in data[0]..data[length-1]
43  */
44
45 int
46 count_nulls(char *data,
47             int length)
48 {
49     int count = 0;
50
51     for (; length; data++, length--)
52       if (!*data)
53         count++;
54
55     return(count);
56 }
57
58 /*
59  *    string get_next_field(char **data_p, int *length_p)
60  *        Requires: *length_p >= 0
61  *        Modifies: *data_p, *length_p
62  *        Effects: Treats (*data_p)[0], (*data_p)[1], ... (*data_p)[length-1]
63  *                 as a series of null-seperated fields.  This function
64  *                 returns a copy of the first field on the heap.  This
65  *                 string must eventually be freed.  Also, *data_p is
66  *                 advanced and *length_p decreased so that another
67  *                 call to this procedure with the same arguments will
68  *                 return the second field.  The next call will return
69  *                 the third field, etc.  "" is returned if 0 fields
70  *                 remain.  (this is the case when *length_p == 0)
71  */
72
73 string
74 get_next_field(char **data_p,
75                int *length_p)
76 {
77     char *data = *data_p;
78     int length = *length_p;
79     char *ptr;
80
81     for (ptr=data; length; ptr++, length--)
82       if (!*ptr) {
83           *data_p = ptr+1;
84           *length_p = length-1;
85           return(string_Copy(data));
86       }
87
88     length = *length_p;
89     *data_p = ptr;
90     *length_p = 0;
91     return(string_CreateFromData(data, length));
92 }
93
94 /*
95  *    string get_field(char *data, int length, int num)
96  *        Requires: length>=0, num>0
97  *        Effects: Treats data[0]..data[length-1] as a series of
98  *                 null-seperated fields.  This function returns a copy of
99  *                 the num'th field (numbered from 1 in this case) on the
100  *                 heap.  This string must eventually be freed.  If there
101  *                 is no num'th field (because num<1 or num># of fields),
102  *                 "" is returned.
103  */
104
105 string get_field(char *data,
106                  int length,
107                  int num)
108 {
109     /*
110      * While num>1 and there are fields left, skip a field & decrement num:
111      */
112     while (length && num>1) {
113         if (!*data)
114           num--;
115         length--;
116         data++;
117     }
118
119     /*
120      * If any more fields left, the first field is the one we want.
121      * Otherwise, there is no such field as num -- return "".
122      */
123     if (length)
124       return(get_next_field(&data, &length));
125     else
126       return(string_Copy(""));
127 }
128
129 /*
130  *    string convert_nulls_to_newlines(data, length)
131  *       Requires: length>=0, malloc never returns NULL
132  *       Effects: Takes data[0]..data[length-1], converts all nulls to
133  *                newlines ('\n') and returns the result as a null-terminated
134  *                string on the heap.  The returned string must eventually
135  *                be freed.
136  */
137
138 string
139 convert_nulls_to_newlines(char *data,
140                           int length)
141 {
142     char *result, *ptr;
143     char c;
144
145     result = (char *) malloc(length+1);
146     result[length] = '\0';
147     
148     for (ptr=result; length; data++, ptr++, length--)
149       *ptr = (c = *data) ? c : '\n';
150
151     return(result);
152 }
153
154
155 /*
156  *  Internal Routine:
157  *
158  *    string z_kind_to_ascii(ZNotice_Kind_t z_kind)
159  *        Effects: Returns an ascii representation for z_kind.
160  *                 The string returned is on the heap and must be freed
161  *                 eventually.
162  */
163
164 static string
165 z_kind_to_ascii(ZNotice_Kind_t z_kind)
166 {
167     string result;
168
169     switch (z_kind) {
170       case UNSAFE:
171         result = "unsafe";
172         break;
173
174       case UNACKED:
175         result = "unacked";
176         break;
177
178       case ACKED:
179         result = "acked";
180         break;
181
182       case HMACK:
183         result = "hmack";
184         break;
185
186       case HMCTL:
187         result = "hmctl";
188         break;
189
190       case SERVACK:
191         result = "servack";
192         break;
193
194       case SERVNAK:
195         result = "servnak";
196         break;
197
198       case CLIENTACK:
199         result = "clientack";
200         break;
201
202       case STAT:
203         result = "stat";
204         break;
205
206       default:
207         result = "<unknown kind>";
208         break;
209     }
210     
211     return(string_Copy(result));
212 }
213
214 /*
215  *  Internal Routine:
216  *
217  *    string z_auth_to_ascii(int z_auth)
218  *        Effects: Returns an ascii representation for z_auth.
219  *                 The string returned is on the heap and must be freed
220  *                 eventually.
221  */
222
223 static string
224 z_auth_to_ascii(int z_auth)
225 {
226     string result;
227
228     switch (z_auth) {
229       case ZAUTH_FAILED:
230         result = "forged";
231         break;
232
233       case ZAUTH_NO:
234         result = "no";
235         break;
236         
237       case ZAUTH_YES:
238         result = "yes";
239         break;
240
241       default:
242         result = "unknown";
243         break;
244     }
245     
246     return(string_Copy(result));
247 }
248
249 /*
250  *    char *decode_notice(ZNotice_t *notice)
251  *        Modifies: various description language variables
252  *        Effects:
253  */
254
255 char *
256 decode_notice(ZNotice_t *notice,
257               char *hostname)
258 {
259     char *temp;
260     string time, notyear, year, date_string, time_string;
261 #ifdef CMU_ZWGCPLUS
262     extern char *getSelectedText();
263 #endif
264
265     /*
266      * Convert useful notice fields to ascii and store away in
267      * description language variables for later use by the
268      * the user's program:
269      */
270     var_set_variable("zephyr_version", notice->z_version);
271     var_set_variable("class", notice->z_class);
272     var_set_variable("instance", notice->z_class_inst);
273     var_set_variable("opcode", notice->z_opcode);
274     var_set_variable("default", notice->z_default_format);
275     var_set_variable("charset", (char *)ZCharsetToString(notice->z_charset)); /*XXX const*/
276     var_set_variable("recipient",
277                      (notice->z_recipient[0] ? notice->z_recipient : "*"));
278     var_set_variable("fullsender", notice->z_sender);
279     var_set_variable_to_number("port", (int)ntohs(notice->z_port));
280     var_set_variable_then_free_value("kind", z_kind_to_ascii(notice->z_kind));
281     var_set_variable_then_free_value("auth", z_auth_to_ascii(notice->z_auth));
282
283 #ifdef CMU_ZWGCPLUS
284     if ((temp=getSelectedText()) != 0)
285         var_set_variable("selection", temp);
286     
287     var_set_variable("delete_window", "none");
288     var_set_variable("event_time", "none");
289     var_set_variable("event_name", "event");
290 #endif
291     /*
292      * Set $sender to the name of the notice sender except first strip off the
293      * realm name if it is the local realm:
294      */
295     if ( (temp=strchr(notice->z_sender,'@')) && string_Eq(temp+1, ZGetRealm()) )
296       var_set_variable_then_free_value("sender",
297                                 string_CreateFromData(notice->z_sender,
298                                                       temp-notice->z_sender));
299     else
300       var_set_variable("sender", notice->z_sender);
301 #ifdef CMU_ZWGCPLUS
302     if (get_full_names) {
303       struct passwd *pwnam = getpwnam(var_get_variable("sender"));
304       if (pwnam) {
305         temp = string_Copy(pwnam->pw_gecos);
306         var_set_variable_then_free_value("sendername", temp);
307       } else {
308         var_set_variable("sendername", "unknown");
309       }
310     }
311 #endif
312     
313     /*
314      * Convert time & date notice was sent to ascii.  The $time
315      * has the format "01:03:52" while $date has the format
316      * "Sun Sep 16 1973".
317      */
318     {
319       /* the fields of struct timeval might not be the right type to pass
320          to ctime, so use a temporary */
321       time_t sec = notice->z_time.tv_sec;
322       time = ctime(&sec);
323     }
324     time_string = string_CreateFromData(time+11,8);
325     var_set_variable_then_free_value("time", time_string);
326     date_string = string_Concat(notyear=string_CreateFromData(time,11),
327                                 year=string_CreateFromData(time+20,4));
328     var_set_variable_then_free_value("date", date_string);
329     free(notyear);
330     free(year);
331
332     /*
333      * Convert host notice sent from to ascii:
334      */
335     var_set_variable("fromhost", hostname ? hostname :
336                      inet_ntoa(notice->z_sender_addr));
337
338     /*
339      * Set $message to the message field of the notice with nulls changed
340      * to newlines:
341      */
342     var_set_variable_then_free_value("message",
343                      convert_nulls_to_newlines(notice->z_message,
344                                                notice->z_message_len));
345
346     /*
347      * Decide if its a control notice.  If so, return the notice's
348      * opcode.  Otherwise, return NULL:
349      */
350     if ((strcasecmp(notice->z_class, WG_CTL_CLASS)==0) && /* <<<>>> */
351         (strcasecmp(notice->z_class_inst, WG_CTL_USER)==0))
352       return(notice->z_opcode);
353     return(0);
354 }