]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/zwgc/notice.c
4e09167cd7cc46bbdc3ac70f3a73fffaeb6424e6
[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 count_nulls(data, length)
42      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 get_next_field(data_p, length_p)
70      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(data, length, num)
102      char *data;
103      int length;
104      int num;
105 {
106     /*
107      * While num>1 and there are fields left, skip a field & decrement num:
108      */
109     while (length && num>1) {
110         if (!*data)
111           num--;
112         length--;
113         data++;
114     }
115
116     /*
117      * If any more fields left, the first field is the one we want.
118      * Otherwise, there is no such field as num -- return "".
119      */
120     if (length)
121       return(get_next_field(&data, &length));
122     else
123       return(string_Copy(""));
124 }
125
126 /*
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
132  *                be freed.
133  */
134
135 string convert_nulls_to_newlines(data, length)
136      char *data;
137      int length;
138 {
139     char *result, *ptr;
140     char c;
141
142     result = (char *) malloc(length+1);
143     result[length] = '\0';
144     
145     for (ptr=result; length; data++, ptr++, length--)
146       *ptr = (c = *data) ? c : '\n';
147
148     return(result);
149 }
150
151
152 /*
153  *  Internal Routine:
154  *
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
158  *                 eventually.
159  */
160
161 static string z_kind_to_ascii(z_kind)
162      ZNotice_Kind_t z_kind;
163 {
164     string result;
165
166     switch (z_kind) {
167       case UNSAFE:
168         result = "unsafe";
169         break;
170
171       case UNACKED:
172         result = "unacked";
173         break;
174
175       case ACKED:
176         result = "acked";
177         break;
178
179       case HMACK:
180         result = "hmack";
181         break;
182
183       case HMCTL:
184         result = "hmctl";
185         break;
186
187       case SERVACK:
188         result = "servack";
189         break;
190
191       case SERVNAK:
192         result = "servnak";
193         break;
194
195       case CLIENTACK:
196         result = "clientack";
197         break;
198
199       case STAT:
200         result = "stat";
201         break;
202
203       default:
204         result = "<unknown kind>";
205         break;
206     }
207     
208     return(string_Copy(result));
209 }
210
211 /*
212  *  Internal Routine:
213  *
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
217  *                 eventually.
218  */
219
220 static string z_auth_to_ascii(z_auth)
221      int z_auth;
222 {
223     string result;
224
225     switch (z_auth) {
226       case ZAUTH_FAILED:
227         result = "forged";
228         break;
229
230       case ZAUTH_NO:
231         result = "no";
232         break;
233         
234       case ZAUTH_YES:
235         result = "yes";
236         break;
237
238       default:
239         result = "unknown";
240         break;
241     }
242     
243     return(string_Copy(result));
244 }
245
246 /*
247  *    char *decode_notice(ZNotice_t *notice)
248  *        Modifies: various description language variables
249  *        Effects:
250  */
251
252 char *decode_notice(notice, hostname)
253      ZNotice_t *notice;
254      char *hostname;
255 {
256     char *temp;
257     string time, notyear, year, date_string, time_string;
258
259     /*
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:
263      */
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)ntohs(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));
275
276     /*
277      * Set $sender to the name of the notice sender except first strip off the
278      * realm name if it is the local realm:
279      */
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));
284     else
285       var_set_variable("sender", notice->z_sender);
286     
287     /*
288      * Convert time & date notice was sent to ascii.  The $time
289      * has the format "01:03:52" while $date has the format
290      * "Sun Sep 16 1973".
291      */
292     {
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;
296       time = ctime(&sec);
297     }
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);
303     free(notyear);
304     free(year);
305
306     /*
307      * Convert host notice sent from to ascii:
308      */
309     var_set_variable("fromhost", hostname ? hostname :
310                      inet_ntoa(notice->z_sender_addr));
311
312     /*
313      * Set $message to the message field of the notice with nulls changed
314      * to newlines:
315      */
316     var_set_variable_then_free_value("message",
317                      convert_nulls_to_newlines(notice->z_message,
318                                                notice->z_message_len));
319
320     /*
321      * Decide if its a control notice.  If so, return the notice's
322      * opcode.  Otherwise, return NULL:
323      */
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);
327     return(0);
328 }