source: zephyr.c @ 1c6c4d3

barnowl_perlaimdebianowlrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 1c6c4d3 was 1c6c4d3, checked in by Erik Nygren <nygren@mit.edu>, 22 years ago
Added owl_sprintf which returns the formatted string, or NULL. The caller must free this string. This will allocate enough memory and thus avoid potential some buffer overrun situations. Started fixing some potential buffer overrun situations. Simple implementation of 'zwrite -m' (doesn't yet log an outgoing message as having been sent.) The "Not logged in or subscribing to messages" error now includes the name of the recipient.
  • Property mode set to 100644
File size: 11.1 KB
Line 
1#include <stdlib.h>
2#include <unistd.h>
3#include <sys/types.h>
4#include <sys/wait.h>
5#include <string.h>
6#include <zephyr/zephyr.h>
7#include <com_err.h>
8#include <pwd.h>
9#include "owl.h"
10
11static const char fileIdent[] = "$Id$";
12
13int owl_zephyr_loadsubs(char *filename) {
14  /* return 0  on success
15   *        -1 on file error
16   *        -2 on subscription error
17   */
18  FILE *file;
19  char *tmp, *start;
20  char buffer[1024], subsfile[1024];
21  ZSubscription_t subs[3001];
22  int count, ret, i;
23
24  ret=0;
25 
26  if (filename==NULL) {
27    sprintf(subsfile, "%s/%s", owl_global_get_homedir(&g), ".zephyr.subs");
28  } else {
29    strcpy(subsfile, filename);
30  }
31 
32  /* need to redo this to do chunks, not just bail after 3000 */
33  count=0;
34  file=fopen(subsfile, "r");
35  if (file) {
36    while ( fgets(buffer, 1024, file)!=NULL ) {
37      if (buffer[0]=='#' || buffer[0]=='\n' || buffer[0]=='\n') continue;
38
39      if (buffer[0]=='-') {
40        start=buffer+1;
41      } else {
42        start=buffer;
43      }
44     
45      if (count >= 3000) break; /* also tell the user */
46
47      /* add it to the list of subs */
48      if ((tmp=(char *) strtok(start, ",\n\r"))==NULL) continue;
49      subs[count].zsub_class=owl_strdup(tmp);
50      if ((tmp=(char *) strtok(NULL, ",\n\r"))==NULL) continue;
51      subs[count].zsub_classinst=owl_strdup(tmp);
52      if ((tmp=(char *) strtok(NULL, " \t\n\r"))==NULL) continue;
53      subs[count].zsub_recipient=owl_strdup(tmp);
54
55      /* if it started with '-' then add it to the global punt list */
56      if (buffer[0]=='-') {
57        owl_function_zpunt(subs[count].zsub_class, subs[count].zsub_classinst, subs[count].zsub_recipient, 0);
58      }
59     
60      count++;
61    }
62    fclose(file);
63  } else {
64    count=0;
65    ret=-1;
66  }
67
68  /* sub with defaults */
69  if (ZSubscribeTo(subs,count,0) != ZERR_NONE) {
70    fprintf(stderr, "Error subbing\n");
71    ret=-2;
72  }
73
74  /* free stuff */
75  for (i=0; i<count; i++) {
76    owl_free(subs[i].zsub_class);
77    owl_free(subs[i].zsub_classinst);
78    owl_free(subs[i].zsub_recipient);
79  }
80
81  return(ret);
82}
83
84int loadloginsubs(char *filename) {
85  FILE *file;
86  ZSubscription_t subs[3001];
87  char subsfile[1024], buffer[1024];
88  int count, ret, i;
89
90  ret=0;
91
92  if (filename==NULL) {
93    sprintf(subsfile, "%s/%s", owl_global_get_homedir(&g), ".anyone");
94  } else {
95    strcpy(subsfile, filename);
96  }
97
98  /* need to redo this to do chunks, not just bag out after 3000 */
99  count=0;
100  file=fopen(subsfile, "r");
101  if (file) {
102    while ( fgets(buffer, 1024, file)!=NULL ) {
103      if (buffer[0]=='#' || buffer[0]=='\n' || buffer[0]=='\n') continue;
104     
105      if (count >= 3000) break; /* also tell the user */
106
107      buffer[strlen(buffer)-1]='\0';
108      subs[count].zsub_class="login";
109      subs[count].zsub_recipient="*";
110      if (strchr(buffer, '@')) {
111        subs[count].zsub_classinst=owl_strdup(buffer);
112      } else {
113        subs[count].zsub_classinst=owl_sprintf("%s@%s", buffer, ZGetRealm());
114      }
115
116      count++;
117    }
118    fclose(file);
119  } else {
120    count=0;
121    ret=-1;
122  }
123
124  /* sub with defaults */
125  if (ZSubscribeTo(subs,count,0) != ZERR_NONE) {
126    fprintf(stderr, "Error subbing\n");
127    ret=-2;
128  }
129
130  /* free stuff */
131  for (i=0; i<count; i++) {
132    owl_free(subs[i].zsub_classinst);
133  }
134
135  return(ret);
136}
137
138void unsuball() {
139  int ret;
140 
141  ret=ZCancelSubscriptions(0);
142  if (ret != ZERR_NONE) {
143    com_err("owl",ret,"while unsubscribing");
144  }
145}
146
147int owl_zephyr_sub(char *class, char *inst, char *recip) {
148  ZSubscription_t subs[5];
149  int ret;
150
151  subs[0].zsub_class=class;
152  subs[0].zsub_classinst=inst;
153  subs[0].zsub_recipient=recip;
154
155  if (ZSubscribeTo(subs,1,0) != ZERR_NONE) {
156    fprintf(stderr, "Error subbing\n");
157    ret=-2;
158  }
159  return(0);
160}
161
162
163int owl_zephyr_unsub(char *class, char *inst, char *recip) {
164  ZSubscription_t subs[5];
165  int ret;
166
167  subs[0].zsub_class=class;
168  subs[0].zsub_classinst=inst;
169  subs[0].zsub_recipient=recip;
170
171  if (ZUnsubscribeTo(subs,1,0) != ZERR_NONE) {
172    fprintf(stderr, "Error unsubbing\n");
173    ret=-2;
174  }
175  return(0);
176}
177
178
179void zlog_in() {
180  int ret;
181
182  ret=ZSetLocation(EXPOSE_NETVIS);
183  /* do something on failure */
184}
185
186void zlog_out() {
187  int ret;
188
189  ret=ZUnsetLocation();
190  /* do something on failure */
191}
192
193
194char *owl_zephyr_get_field(ZNotice_t *n, int j, int *k) {
195  /* return a pointer to the Jth field, place the length in k.  If the
196     field doesn't exist return an emtpy string */
197  int i, count, save;
198
199  count=save=0;
200  for (i=0; i<n->z_message_len; i++) {
201    if (n->z_message[i]=='\0') {
202      count++;
203      if (count==j) {
204        /* just found the end of the field we're looking for */
205        *k=i-save;
206        return(n->z_message+save);
207      } else {
208        save=i+1;
209      }
210    }
211  }
212  /* catch the last field */
213  if (count==j-1) {
214    *k=n->z_message_len-save;
215    return(n->z_message+save);
216  }
217 
218  *k=0;
219  return("");
220}
221
222
223int owl_zephyr_get_num_fields(ZNotice_t *n) {
224  int i, fields;
225
226  fields=1;
227  for (i=0; i<n->z_message_len; i++) {
228    if (n->z_message[i]=='\0') fields++;
229  }
230 
231  return(fields);
232}
233
234
235char *owl_zephyr_get_message(ZNotice_t *n, int *k) {
236  /* return a pointer to the message, place the message length in k */
237  if (!strcasecmp(n->z_opcode, "ping")) {
238    *k=0;
239    return("");
240  }
241
242  return(owl_zephyr_get_field(n, 2, k));
243}
244
245
246char *owl_zephyr_get_zsig(ZNotice_t *n, int *k) {
247  /* return a pointer to the zsig if there is one */
248
249  if (n->z_message_len==0) {
250    *k=0;
251    return("");
252  }
253  *k=strlen(n->z_message);
254  return(n->z_message);
255}
256
257
258int send_zephyr(char *opcode, char *zsig, char *class, char *instance, char *recipient, char *message) {
259  int ret;
260  ZNotice_t notice;
261  char *ptr;
262  struct passwd *pw;
263  char zsigtmp[LINE];
264  char *zsigexec, *zsigowlvar, *zsigzvar;
265 
266  zsigexec = owl_global_get_zsig_exec(&g);
267  zsigowlvar = owl_global_get_zsig(&g);
268  zsigzvar = ZGetVariable("zwrite-signature");
269
270  if (zsig) {
271    strcpy(zsigtmp, zsig);
272  } else if (zsigowlvar && *zsigowlvar) {
273    strncpy(zsigtmp, zsigowlvar, LINE);
274  } else if (zsigexec && *zsigexec) {
275    FILE *file;
276    char buff[LINE];
277    strcpy(zsigtmp, "");
278    file=popen(zsigexec, "r");
279    if (!file) {
280      if (zsigzvar && *zsigzvar) {
281        strncpy(zsigtmp, zsigzvar, LINE);
282      }
283    } else {
284      while (fgets(buff, LINE, file)) { /* wrong sizing */
285        strcat(zsigtmp, buff);
286      }
287      pclose(file);
288      if (zsigtmp[strlen(zsigtmp)-1]=='\n') {
289        zsigtmp[strlen(zsigtmp)-1]='\0';
290      }
291    }
292  } else if (zsigzvar) {
293    strncpy(zsigtmp, zsigzvar, LINE);
294  } else if (((pw=getpwuid(getuid()))!=NULL) && (pw->pw_gecos)) {
295    strncpy(zsigtmp, pw->pw_gecos, LINE);
296    ptr=strchr(zsigtmp, ',');
297    if (ptr) {
298      ptr[0]='\0';
299    }
300  } else {
301    strcpy(zsigtmp, "");
302  }
303   
304  memset(&notice, 0, sizeof(notice));
305
306  notice.z_kind=ACKED;
307  notice.z_port=0;
308  notice.z_class=class;
309  notice.z_class_inst=instance;
310  if (!strcmp(recipient, "*") || !strcmp(recipient, "@")) {
311    notice.z_recipient="";
312  } else {
313    notice.z_recipient=recipient;
314  }
315  notice.z_default_format="Class $class, Instance $instance:\nTo: @bold($recipient) at $time $date\nFrom: @bold{$1 <$sender>}\n\n$2";
316  notice.z_sender=NULL;
317  if (opcode) notice.z_opcode=opcode;
318
319  notice.z_message_len=strlen(zsigtmp)+1+strlen(message);
320  notice.z_message=owl_malloc(notice.z_message_len+10);
321  strcpy(notice.z_message, zsigtmp);
322  memcpy(notice.z_message+strlen(zsigtmp)+1, message, strlen(message));
323
324  /* ret=ZSendNotice(&notice, ZAUTH); */
325  ret=ZSrvSendNotice(&notice, ZAUTH, send_zephyr_helper);
326 
327  /* free then check the return */
328  owl_free(notice.z_message);
329  ZFreeNotice(&notice);
330  if (ret!=ZERR_NONE) {
331    owl_function_makemsg("Error sending zephyr");
332    return(ret);
333  }
334
335  return(0);
336}
337
338Code_t send_zephyr_helper(ZNotice_t *notice, char *buf, int len, int wait) {
339  return(ZSendPacket(buf, len, 0));
340}
341
342void send_ping(char *to) {
343  send_zephyr("PING", "", "MESSAGE", "PERSONAL", to, "");
344}
345
346void owl_zephyr_handle_ack(ZNotice_t *retnotice) {
347  char *tmp;
348 
349  /* if it's an HMACK ignore it */
350  if (retnotice->z_kind == HMACK) return;
351 
352  if (retnotice->z_kind == SERVNAK) {
353    owl_function_makemsg("Authorization failure sending zephyr");
354  } else if ((retnotice->z_kind != SERVACK) || !retnotice->z_message_len) {
355    owl_function_makemsg("Detected server failure while receiving acknowledgement");
356  } else if (!strcmp(retnotice->z_message, ZSRVACK_SENT)) {
357    if (!strcasecmp(retnotice->z_opcode, "ping")) {
358      return;
359    } else if (!strcasecmp(retnotice->z_class, "message") &&
360               !strcasecmp(retnotice->z_class_inst, "personal")) {
361      tmp=pretty_sender(retnotice->z_recipient);
362      owl_function_makemsg("Message sent to %s.", tmp);
363      free(tmp);
364    } else {
365      owl_function_makemsg("Message sent to -c %s -i %s\n", retnotice->z_class, retnotice->z_class_inst);
366    }
367  } else if (!strcmp(retnotice->z_message, ZSRVACK_NOTSENT)) {
368    if (strcasecmp(retnotice->z_class, "message")) {
369      owl_function_makemsg("Not logged in or not subscribing to class %s, instance %s",
370              retnotice->z_class, retnotice->z_class_inst);
371    } else {
372      tmp = pretty_sender(retnotice->z_recipient);
373      owl_function_makemsg("%s: Not logged in or subscribing to messages.", 
374                           tmp);
375      owl_free(tmp);
376    }
377  } else {
378    owl_function_makemsg("Internal error on ack (%s)", retnotice->z_message);
379  }
380}
381
382int owl_zephyr_notice_is_ack(ZNotice_t *n) {
383  if (n->z_kind == SERVNAK || n->z_kind == SERVACK || n->z_kind == HMACK) {
384    if (!strcasecmp(n->z_class, LOGIN_CLASS)) return(0);
385    return(1);
386  }
387  return(0);
388}
389 
390void owl_zephyr_zaway(owl_message *m) {
391  char *tmpbuff;
392 
393  /* bail if it doesn't look like a message we should reply to */
394  if (strcasecmp(owl_message_get_class(m), "message")) return;
395  if (strcasecmp(owl_message_get_recipient(m), ZGetSender())) return;
396  if (!strcasecmp(owl_message_get_sender(m), "")) return;
397  if (!strcasecmp(owl_message_get_opcode(m), "ping")) return;
398  if (!strcasecmp(owl_message_get_opcode(m), "auto")) return;
399  if (!strcasecmp(owl_message_get_notice(m)->z_message, "Automated reply:")) return;
400  if (!strcasecmp(owl_message_get_sender(m), ZGetSender())) return;
401  /* add one to not send to ourselves */
402
403  send_zephyr("",
404              "Automated reply:",
405              owl_message_get_class(m),
406              owl_message_get_instance(m),
407              owl_message_get_sender(m),
408              owl_global_get_zaway_msg(&g));
409
410  /* display the message as an admin message in the receive window */
411  tmpbuff = owl_sprintf("Message sent to %s", owl_message_get_sender(m));
412  owl_function_adminmsg(tmpbuff, owl_global_get_zaway_msg(&g));
413  owl_free(tmpbuff);
414}
415
416
417void owl_zephyr_hackaway_cr(ZNotice_t *n) {
418  /* replace \r's with ' '.  Gross-ish */
419  int i;
420
421  for (i=0; i<n->z_message_len; i++) {
422    if (n->z_message[i]=='\r') {
423      n->z_message[i]=' ';
424    }
425  }
426}
427
428void owl_zephyr_zlocate(char *user, char *out, int auth) {
429  int ret, numlocs;
430  int one = 1;
431  ZLocations_t locations;
432  char *myuser;
433 
434  strcpy(out, "");
435
436  ret=ZLocateUser(user,&numlocs,auth?ZAUTH:ZNOAUTH);
437  if (ret != ZERR_NONE) {
438    owl_function_makemsg("Error locating user");
439  }
440
441  if (numlocs==0) {
442    strcpy(out, "Hidden or not logged-in\n");
443    return;
444  }
445   
446  for (;numlocs;numlocs--) {
447    ZGetLocations(&locations,&one);
448    myuser=pretty_sender(user);
449    sprintf(out, "%s%s: %s\t%s\t%s\n", out, myuser, locations.host, locations.tty, locations.time);
450    owl_free(myuser);
451  }
452}
Note: See TracBrowser for help on using the repository browser.