source: zephyr.c @ c73a22d

release-1.10release-1.8release-1.9
Last change on this file since c73a22d was c73a22d, checked in by Karl Ramm <kcr@1ts.org>, 13 years ago
when something goes wrong, give more information about what happened These various utility functions, instead of just saying "there was an error", should report to the user what the library thinks went wrong so they user has some small chance of debugging the problem. Reviewed-By: Nelson Elhage <nelhage@nelhage.com>
  • Property mode set to 100644
File size: 36.7 KB
Line 
1#include <stdlib.h>
2#include <unistd.h>
3#include <sys/types.h>
4#include <sys/wait.h>
5#include <sys/stat.h>
6#include <string.h>
7#include "owl.h"
8
9#ifdef HAVE_LIBZEPHYR
10static GList *deferred_subs = NULL;
11
12typedef struct _owl_sub_list {                            /* noproto */
13  ZSubscription_t *subs;
14  int nsubs;
15} owl_sub_list;
16
17Code_t ZResetAuthentication(void);
18#endif
19
20#define HM_SVC_FALLBACK         htons((unsigned short) 2104)
21
22static char *owl_zephyr_dotfile(const char *name, const char *input)
23{
24  if (input != NULL)
25    return g_strdup(input);
26  else
27    return g_strdup_printf("%s/%s", owl_global_get_homedir(&g), name);
28}
29
30#ifdef HAVE_LIBZEPHYR
31void owl_zephyr_initialize(void)
32{
33  Code_t ret;
34  struct servent *sp;
35  struct sockaddr_in sin;
36  ZNotice_t req;
37
38  /*
39   * Code modified from libzephyr's ZhmStat.c
40   *
41   * Modified to add the fd to our select loop, rather than hanging
42   * until we get an ack.
43   */
44
45  if ((ret = ZOpenPort(NULL)) != ZERR_NONE) {
46    owl_function_error("Error opening Zephyr port: %s", error_message(ret));
47    return;
48  }
49
50  (void) memset(&sin, 0, sizeof(struct sockaddr_in));
51
52  sp = getservbyname(HM_SVCNAME, "udp");
53
54  sin.sin_port = (sp) ? sp->s_port : HM_SVC_FALLBACK;
55  sin.sin_family = AF_INET;
56
57  sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
58
59  (void) memset(&req, 0, sizeof(req));
60  req.z_kind = STAT;
61  req.z_port = 0;
62  req.z_class = zstr(HM_STAT_CLASS);
63  req.z_class_inst = zstr(HM_STAT_CLIENT);
64  req.z_opcode = zstr(HM_GIMMESTATS);
65  req.z_sender = zstr("");
66  req.z_recipient = zstr("");
67  req.z_default_format = zstr("");
68  req.z_message_len = 0;
69
70  if ((ret = ZSetDestAddr(&sin)) != ZERR_NONE) {
71    owl_function_error("Initializing Zephyr: %s", error_message(ret));
72    return;
73  }
74
75  if ((ret = ZSendNotice(&req, ZNOAUTH)) != ZERR_NONE) {
76    owl_function_error("Initializing Zephyr: %s", error_message(ret));
77    return;
78  }
79
80  owl_select_add_io_dispatch(ZGetFD(), OWL_IO_READ|OWL_IO_EXCEPT, &owl_zephyr_finish_initialization, NULL, NULL);
81}
82
83void owl_zephyr_finish_initialization(const owl_io_dispatch *d, void *data) {
84  Code_t code;
85  char *perl;
86
87  owl_select_remove_io_dispatch(d);
88
89  ZClosePort();
90
91  if ((code = ZInitialize()) != ZERR_NONE) {
92    owl_function_error("Initializing Zephyr: %s", error_message(code));
93    return;
94  }
95
96  if ((code = ZOpenPort(NULL)) != ZERR_NONE) {
97    owl_function_error("Initializing Zephyr: %s", error_message(code));
98    return;
99  }
100
101  owl_select_add_io_dispatch(ZGetFD(), OWL_IO_READ|OWL_IO_EXCEPT, &owl_zephyr_process_events, NULL, NULL);
102
103  owl_global_set_havezephyr(&g);
104
105  if(g.load_initial_subs) {
106    owl_zephyr_load_initial_subs();
107  }
108  while(deferred_subs != NULL) {
109    owl_sub_list *subs = deferred_subs->data;
110    owl_function_debugmsg("Loading %d deferred subs.", subs->nsubs);
111    owl_zephyr_loadsubs_helper(subs->subs, subs->nsubs);
112    deferred_subs = g_list_delete_link(deferred_subs, deferred_subs);
113    g_free(subs);
114  }
115
116  /* zlog in if we need to */
117  if (owl_global_is_startuplogin(&g)) {
118    owl_function_debugmsg("startup: doing zlog in");
119    owl_zephyr_zlog_in();
120  }
121  /* check pseudo-logins if we need to */
122  if (owl_global_is_pseudologins(&g)) {
123    owl_function_debugmsg("startup: checking pseudo-logins");
124    owl_function_zephyr_buddy_check(0);
125  }
126
127  perl = owl_perlconfig_execute("BarnOwl::Zephyr::_zephyr_startup()");
128  g_free(perl);
129
130  owl_select_add_pre_select_action(owl_zephyr_pre_select_action, NULL, NULL);
131}
132
133void owl_zephyr_load_initial_subs(void) {
134  int ret_sd, ret_bd, ret_u;
135
136  owl_function_debugmsg("startup: loading initial zephyr subs");
137
138  /* load default subscriptions */
139  ret_sd = owl_zephyr_loaddefaultsubs();
140
141  /* load Barnowl default subscriptions */
142  ret_bd = owl_zephyr_loadbarnowldefaultsubs();
143
144  /* load subscriptions from subs file */
145  ret_u = owl_zephyr_loadsubs(NULL, 0);
146
147  if (ret_sd || ret_bd || ret_u) {
148    owl_function_error("Error loading zephyr subscriptions");
149  }
150
151  /* load login subscriptions */
152  if (owl_global_is_loginsubs(&g)) {
153    owl_function_debugmsg("startup: loading login subs");
154    owl_function_loadloginsubs(NULL);
155  }
156}
157#else
158void owl_zephyr_initialize(void)
159{
160}
161#endif
162
163
164int owl_zephyr_shutdown(void)
165{
166#ifdef HAVE_LIBZEPHYR
167  if(owl_global_is_havezephyr(&g)) {
168    unsuball();
169    ZClosePort();
170  }
171#endif
172  return 0;
173}
174
175int owl_zephyr_zpending(void)
176{
177#ifdef HAVE_LIBZEPHYR
178  Code_t code;
179  if(owl_global_is_havezephyr(&g)) {
180    if((code = ZPending()) < 0) {
181      owl_function_debugmsg("Error (%s) in ZPending()\n",
182                            error_message(code));
183      return 0;
184    }
185    return code;
186  }
187#endif
188  return 0;
189}
190
191const char *owl_zephyr_get_realm(void)
192{
193#ifdef HAVE_LIBZEPHYR
194  if (owl_global_is_havezephyr(&g))
195    return(ZGetRealm());
196#endif
197  return "";
198}
199
200const char *owl_zephyr_get_sender(void)
201{
202#ifdef HAVE_LIBZEPHYR
203  if (owl_global_is_havezephyr(&g))
204    return(ZGetSender());
205#endif
206  return "";
207}
208
209#ifdef HAVE_LIBZEPHYR
210int owl_zephyr_loadsubs_helper(ZSubscription_t subs[], int count)
211{
212  int ret = 0;
213  Code_t code;
214
215  if (owl_global_is_havezephyr(&g)) {
216    int i;
217    /* sub without defaults */
218    code = ZSubscribeToSansDefaults(subs, count, 0);
219    if (code != ZERR_NONE) {
220      owl_function_error("Error subscribing to zephyr notifications: %s",
221                         error_message(code));
222      ret=-2;
223    }
224
225    /* free stuff */
226    for (i=0; i<count; i++) {
227      g_free(subs[i].zsub_class);
228      g_free(subs[i].zsub_classinst);
229      g_free(subs[i].zsub_recipient);
230    }
231
232    g_free(subs);
233  } else {
234    owl_sub_list *s = g_new(owl_sub_list, 1);
235    s->subs = subs;
236    s->nsubs = count;
237    deferred_subs = g_list_append(deferred_subs, s);
238  }
239
240  return ret;
241}
242#endif
243
244/* Load zephyr subscriptions from 'filename'.  If 'filename' is NULL,
245 * the default file $HOME/.zephyr.subs will be used.
246 *
247 * Returns 0 on success.  If the file does not exist, return -1 if
248 * 'error_on_nofile' is 1, otherwise return 0.  Return -1 if the file
249 * exists but can not be read.  Return -2 if there is a failure from
250 * zephyr to load the subscriptions.
251 */
252int owl_zephyr_loadsubs(const char *filename, int error_on_nofile)
253{
254#ifdef HAVE_LIBZEPHYR
255  FILE *file;
256  char *tmp, *start;
257  char *buffer = NULL;
258  char *subsfile;
259  ZSubscription_t *subs;
260  int subSize = 1024;
261  int count;
262  struct stat statbuff;
263
264  subs = g_new(ZSubscription_t, subSize);
265  subsfile = owl_zephyr_dotfile(".zephyr.subs", filename);
266
267  if (stat(subsfile, &statbuff) != 0) {
268    g_free(subsfile);
269    if (error_on_nofile == 1)
270      return -1;
271    return 0;
272  }
273
274  ZResetAuthentication();
275  count = 0;
276  file = fopen(subsfile, "r");
277  g_free(subsfile);
278  if (!file)
279    return -1;
280  while (owl_getline(&buffer, file)) {
281    if (buffer[0] == '#' || buffer[0] == '\n')
282        continue;
283
284    if (buffer[0] == '-')
285      start = buffer + 1;
286    else
287      start = buffer;
288
289    if (count >= subSize) {
290      subSize *= 2;
291      subs = g_renew(ZSubscription_t, subs, subSize);
292    }
293   
294    /* add it to the list of subs */
295    if ((tmp = strtok(start, ",\n\r")) == NULL)
296      continue;
297    subs[count].zsub_class = g_strdup(tmp);
298    if ((tmp=strtok(NULL, ",\n\r")) == NULL)
299      continue;
300    subs[count].zsub_classinst = g_strdup(tmp);
301    if ((tmp = strtok(NULL, " \t\n\r")) == NULL)
302      continue;
303    subs[count].zsub_recipient = g_strdup(tmp);
304
305    /* if it started with '-' then add it to the global punt list, and
306     * remove it from the list of subs. */
307    if (buffer[0] == '-') {
308      owl_function_zpunt(subs[count].zsub_class, subs[count].zsub_classinst, subs[count].zsub_recipient, 0);
309      g_free(subs[count].zsub_class);
310      g_free(subs[count].zsub_classinst);
311      g_free(subs[count].zsub_recipient);
312    } else {
313      count++;
314    }
315  }
316  fclose(file);
317  if (buffer)
318    g_free(buffer);
319
320  return owl_zephyr_loadsubs_helper(subs, count);
321#else
322  return 0;
323#endif
324}
325
326/* Load default Barnowl subscriptions
327 *
328 * Returns 0 on success.
329 * Return -2 if there is a failure from zephyr to load the subscriptions.
330 */
331int owl_zephyr_loadbarnowldefaultsubs(void)
332{
333#ifdef HAVE_LIBZEPHYR
334  ZSubscription_t *subs;
335  int subSize = 10; /* Max Barnowl default subs we allow */
336  int count, ret;
337
338  subs = g_new(ZSubscription_t, subSize);
339  ZResetAuthentication();
340  count=0;
341
342  subs[count].zsub_class=g_strdup("message");
343  subs[count].zsub_classinst=g_strdup("*");
344  subs[count].zsub_recipient=g_strdup("%me%");
345  count++;
346
347  ret = owl_zephyr_loadsubs_helper(subs, count);
348  return(ret);
349#else
350  return(0);
351#endif
352}
353
354int owl_zephyr_loaddefaultsubs(void)
355{
356#ifdef HAVE_LIBZEPHYR
357  Code_t ret;
358
359  if (owl_global_is_havezephyr(&g)) {
360    ZSubscription_t subs[10];
361
362    ret = ZSubscribeTo(subs, 0, 0);
363    if (ret != ZERR_NONE) {
364      owl_function_error("Error subscribing to default zephyr notifications: %s.",
365                           error_message(ret));
366      return(-1);
367    }
368  }
369  return(0);
370#else
371  return(0);
372#endif
373}
374
375int owl_zephyr_loadloginsubs(const char *filename)
376{
377#ifdef HAVE_LIBZEPHYR
378  FILE *file;
379  ZSubscription_t *subs;
380  int numSubs = 100;
381  char *subsfile;
382  char *buffer = NULL;
383  int count;
384  struct stat statbuff;
385
386  subs = g_new(ZSubscription_t, numSubs);
387  subsfile = owl_zephyr_dotfile(".anyone", filename);
388
389  if (stat(subsfile, &statbuff) == -1) {
390    g_free(subs);
391    g_free(subsfile);
392    return 0;
393  }
394
395  ZResetAuthentication();
396  count = 0;
397  file = fopen(subsfile, "r");
398  g_free(subsfile);
399  if (file) {
400    while (owl_getline_chomp(&buffer, file)) {
401      if (buffer[0] == '\0' || buffer[0] == '#')
402        continue;
403
404      if (count == numSubs) {
405        numSubs *= 2;
406        subs = g_renew(ZSubscription_t, subs, numSubs);
407      }
408
409      subs[count].zsub_class = g_strdup("login");
410      subs[count].zsub_recipient = g_strdup("*");
411      subs[count].zsub_classinst = long_zuser(buffer);
412
413      count++;
414    }
415    fclose(file);
416  } else {
417    return 0;
418  }
419  if (buffer)
420    g_free(buffer);
421
422  return owl_zephyr_loadsubs_helper(subs, count);
423#else
424  return 0;
425#endif
426}
427
428void unsuball(void)
429{
430#if HAVE_LIBZEPHYR
431  int ret;
432
433  ZResetAuthentication();
434  ret=ZCancelSubscriptions(0);
435  if (ret != ZERR_NONE) {
436    com_err("owl",ret,"while unsubscribing");
437  }
438#endif
439}
440
441int owl_zephyr_sub(const char *class, const char *inst, const char *recip)
442{
443#ifdef HAVE_LIBZEPHYR
444  ZSubscription_t subs[5];
445  Code_t ret;
446
447  subs[0].zsub_class=zstr(class);
448  subs[0].zsub_classinst=zstr(inst);
449  subs[0].zsub_recipient=zstr(recip);
450
451  ZResetAuthentication();
452  ret = ZSubscribeTo(subs, 1, 0);
453  if (ret != ZERR_NONE) {
454    owl_function_error("Error subbing to <%s,%s,%s>: %s",
455                       class, inst, recip,
456                       error_message(ret));
457    return(-2);
458  }
459  return(0);
460#else
461  return(0);
462#endif
463}
464
465
466int owl_zephyr_unsub(const char *class, const char *inst, const char *recip)
467{
468#ifdef HAVE_LIBZEPHYR
469  ZSubscription_t subs[5];
470  Code_t ret;
471
472  subs[0].zsub_class=zstr(class);
473  subs[0].zsub_classinst=zstr(inst);
474  subs[0].zsub_recipient=zstr(recip);
475
476  ZResetAuthentication();
477  ret = ZUnsubscribeTo(subs, 1, 0);
478  if (ret != ZERR_NONE) {
479    owl_function_error("Error unsubbing from <%s,%s,%s>: %s",
480                       class, inst, recip,
481                       error_message(ret));
482    return(-2);
483  }
484  return(0);
485#else
486  return(0);
487#endif
488}
489
490/* return a pointer to the data in the Jth field, (NULL terminated by
491 * definition).  Caller must free the return.
492 */
493#ifdef HAVE_LIBZEPHYR
494char *owl_zephyr_get_field(const ZNotice_t *n, int j)
495{
496  int i, count, save;
497
498  /* If there's no message here, just run along now */
499  if (n->z_message_len == 0)
500    return(g_strdup(""));
501
502  count=save=0;
503  for (i=0; i<n->z_message_len; i++) {
504    if (n->z_message[i]=='\0') {
505      count++;
506      if (count==j) {
507        /* just found the end of the field we're looking for */
508        return(g_strdup(n->z_message+save));
509      } else {
510        save=i+1;
511      }
512    }
513  }
514  /* catch the last field, which might not be null terminated */
515  if (count==j-1) {
516    return g_strndup(n->z_message + save, n->z_message_len - save);
517  }
518
519  return(g_strdup(""));
520}
521
522char *owl_zephyr_get_field_as_utf8(const ZNotice_t *n, int j)
523{
524  int i, count, save;
525
526  /* If there's no message here, just run along now */
527  if (n->z_message_len == 0)
528    return(g_strdup(""));
529
530  count=save=0;
531  for (i = 0; i < n->z_message_len; i++) {
532    if (n->z_message[i]=='\0') {
533      count++;
534      if (count == j) {
535        /* just found the end of the field we're looking for */
536        return(owl_validate_or_convert(n->z_message + save));
537      } else {
538        save = i + 1;
539      }
540    }
541  }
542  /* catch the last field, which might not be null terminated */
543  if (count == j - 1) {
544    char *tmp, *out;
545    tmp = g_strndup(n->z_message + save, n->z_message_len - save);
546    out = owl_validate_or_convert(tmp);
547    g_free(tmp);
548    return out;
549  }
550
551  return(g_strdup(""));
552}
553#else
554char *owl_zephyr_get_field(void *n, int j)
555{
556  return(g_strdup(""));
557}
558char *owl_zephyr_get_field_as_utf8(void *n, int j)
559{
560  return owl_zephyr_get_field(n, j);
561}
562#endif
563
564
565#ifdef HAVE_LIBZEPHYR
566int owl_zephyr_get_num_fields(const ZNotice_t *n)
567{
568  int i, fields;
569
570  if(n->z_message_len == 0)
571    return 0;
572
573  fields=1;
574  for (i=0; i<n->z_message_len; i++) {
575    if (n->z_message[i]=='\0') fields++;
576  }
577 
578  return(fields);
579}
580#else
581int owl_zephyr_get_num_fields(const void *n)
582{
583  return(0);
584}
585#endif
586
587#ifdef HAVE_LIBZEPHYR
588/* return a pointer to the message, place the message length in k
589 * caller must free the return
590 */
591char *owl_zephyr_get_message(const ZNotice_t *n, const owl_message *m)
592{
593  /* don't let ping messages have a body */
594  if (!strcasecmp(n->z_opcode, "ping")) {
595    return(g_strdup(""));
596  }
597
598  /* deal with MIT NOC messages */
599  if (!strcasecmp(n->z_default_format, "@center(@bold(NOC Message))\n\n@bold(Sender:) $1 <$sender>\n@bold(Time:  ) $time\n\n@italic($opcode service on $instance $3.) $4\n")) {
600    char *msg, *field3, *field4;
601
602    field3 = owl_zephyr_get_field(n, 3);
603    field4 = owl_zephyr_get_field(n, 4);
604
605    msg = g_strdup_printf("%s service on %s %s\n%s", n->z_opcode, n->z_class_inst, field3, field4);
606    g_free(field3);
607    g_free(field4);
608    if (msg) {
609      return msg;
610    }
611  }
612  /* deal with MIT Discuss messages */
613  else if (!strcasecmp(n->z_default_format, "New transaction [$1] entered in $2\nFrom: $3 ($5)\nSubject: $4") ||
614           !strcasecmp(n->z_default_format, "New transaction [$1] entered in $2\nFrom: $3\nSubject: $4")) {
615    char *msg, *field1, *field2, *field3, *field4, *field5;
616   
617    field1 = owl_zephyr_get_field(n, 1);
618    field2 = owl_zephyr_get_field(n, 2);
619    field3 = owl_zephyr_get_field(n, 3);
620    field4 = owl_zephyr_get_field(n, 4);
621    field5 = owl_zephyr_get_field(n, 5);
622   
623    msg = g_strdup_printf("New transaction [%s] entered in %s\nFrom: %s (%s)\nSubject: %s", field1, field2, field3, field5, field4);
624    g_free(field1);
625    g_free(field2);
626    g_free(field3);
627    g_free(field4);
628    g_free(field5);
629    if (msg) {
630      return msg;
631    }
632  }
633  /* deal with MIT Moira messages */
634  else if (!strcasecmp(n->z_default_format, "MOIRA $instance on $fromhost:\n $message\n")) {
635    char *msg, *field1;
636   
637    field1 = owl_zephyr_get_field(n, 1);
638   
639    msg = g_strdup_printf("MOIRA %s on %s: %s", n->z_class_inst, owl_message_get_hostname(m), field1);
640    g_free(field1);
641    if (msg) {
642      return msg;
643    }
644  }
645
646  if (owl_zephyr_get_num_fields(n) == 1) {
647    return(owl_zephyr_get_field(n, 1));
648  }
649  else {
650    return(owl_zephyr_get_field(n, 2));
651  }
652}
653#endif
654
655#ifdef HAVE_LIBZEPHYR
656const char *owl_zephyr_get_zsig(const ZNotice_t *n, int *k)
657{
658  /* return a pointer to the zsig if there is one */
659
660  /* message length 0? No zsig */
661  if (n->z_message_len==0) {
662    *k=0;
663    return("");
664  }
665
666  /* If there's only one field, no zsig */
667  if (owl_zephyr_get_num_fields(n) == 1) {
668    *k=0;
669    return("");
670  }
671
672  /* Everything else is field 1 */
673  *k=strlen(n->z_message);
674  return(n->z_message);
675}
676#else
677const char *owl_zephyr_get_zsig(const void *n, int *k)
678{
679  return("");
680}
681#endif
682
683int send_zephyr(const char *opcode, const char *zsig, const char *class, const char *instance, const char *recipient, const char *message)
684{
685#ifdef HAVE_LIBZEPHYR
686  Code_t ret;
687  ZNotice_t notice;
688   
689  memset(&notice, 0, sizeof(notice));
690
691  ZResetAuthentication();
692
693  if (!zsig) zsig="";
694 
695  notice.z_kind=ACKED;
696  notice.z_port=0;
697  notice.z_class=zstr(class);
698  notice.z_class_inst=zstr(instance);
699  notice.z_sender=NULL;
700  if (!strcmp(recipient, "*") || !strcmp(recipient, "@")) {
701    notice.z_recipient=zstr("");
702    if (*owl_global_get_zsender(&g))
703        notice.z_sender=zstr(owl_global_get_zsender(&g));
704  } else {
705    notice.z_recipient=zstr(recipient);
706  }
707  notice.z_default_format=zstr("Class $class, Instance $instance:\nTo: @bold($recipient) at $time $date\nFrom: @bold{$1 <$sender>}\n\n$2");
708  if (opcode) notice.z_opcode=zstr(opcode);
709
710  notice.z_message_len=strlen(zsig)+1+strlen(message);
711  notice.z_message=g_new(char, notice.z_message_len+10);
712  strcpy(notice.z_message, zsig);
713  memcpy(notice.z_message+strlen(zsig)+1, message, strlen(message));
714
715  /* ret=ZSendNotice(&notice, ZAUTH); */
716  ret=ZSrvSendNotice(&notice, ZAUTH, send_zephyr_helper);
717 
718  /* free then check the return */
719  g_free(notice.z_message);
720  ZFreeNotice(&notice);
721  if (ret != ZERR_NONE) {
722    owl_function_error("Error sending zephyr: %s", error_message(ret));
723    return(ret);
724  }
725  return(0);
726#else
727  return(0);
728#endif
729}
730
731#ifdef HAVE_LIBZEPHYR
732Code_t send_zephyr_helper(ZNotice_t *notice, char *buf, int len, int wait)
733{
734  return(ZSendPacket(buf, len, 0));
735}
736#endif
737
738void send_ping(const char *to, const char *zclass, const char *zinstance)
739{
740#ifdef HAVE_LIBZEPHYR
741  send_zephyr("PING", "", zclass, zinstance, to, "");
742#endif
743}
744
745#ifdef HAVE_LIBZEPHYR
746void owl_zephyr_handle_ack(const ZNotice_t *retnotice)
747{
748  char *tmp;
749 
750  /* if it's an HMACK ignore it */
751  if (retnotice->z_kind == HMACK) return;
752
753  if (retnotice->z_kind == SERVNAK) {
754    owl_function_error("Authorization failure sending zephyr");
755  } else if ((retnotice->z_kind != SERVACK) || !retnotice->z_message_len) {
756    owl_function_error("Detected server failure while receiving acknowledgement");
757  } else if (!strcmp(retnotice->z_message, ZSRVACK_SENT)) {
758    if (!strcasecmp(retnotice->z_opcode, "ping")) {
759      return;
760    } else {
761      if (strcasecmp(retnotice->z_recipient, ""))
762      { /* personal */
763        tmp=short_zuser(retnotice->z_recipient);
764        if(!strcasecmp(retnotice->z_class, "message") &&
765           !strcasecmp(retnotice->z_class_inst, "personal")) {
766          owl_function_makemsg("Message sent to %s.", tmp);
767        } else if(!strcasecmp(retnotice->z_class, "message")) { /* instanced, but not classed, personal */
768          owl_function_makemsg("Message sent to %s on -i %s\n", tmp, retnotice->z_class_inst);
769        } else { /* classed personal */
770          owl_function_makemsg("Message sent to %s on -c %s -i %s\n", tmp, retnotice->z_class, retnotice->z_class_inst);
771        }
772        g_free(tmp);
773      } else {
774        /* class / instance message */
775          owl_function_makemsg("Message sent to -c %s -i %s\n", retnotice->z_class, retnotice->z_class_inst);
776      }
777    }
778  } else if (!strcmp(retnotice->z_message, ZSRVACK_NOTSENT)) {
779    if (retnotice->z_recipient == NULL
780        || *retnotice->z_recipient == 0
781        || *retnotice->z_recipient == '@') {
782      char *buff;
783      owl_function_error("No one subscribed to class %s", retnotice->z_class);
784      buff = g_strdup_printf("Could not send message to class %s: no one subscribed.\n", retnotice->z_class);
785      owl_function_adminmsg("", buff);
786      g_free(buff);
787    } else {
788      char *buff;
789      owl_zwrite zw;
790      char *realm;
791
792      tmp = short_zuser(retnotice->z_recipient);
793      owl_function_error("%s: Not logged in or subscribing.", tmp);
794      /*
795       * These error messages are often over 80 chars, but users who want to
796       * see the whole thing can scroll to the side, and for those with wide
797       * terminals or who don't care, not splitting saves a line in the UI
798       */
799      if(strcasecmp(retnotice->z_class, "message")) {
800        buff = g_strdup_printf(
801                 "Could not send message to %s: "
802                 "not logged in or subscribing to class %s, instance %s.\n",
803                 tmp,
804                 retnotice->z_class,
805                 retnotice->z_class_inst);
806      } else if(strcasecmp(retnotice->z_class_inst, "personal")) {
807        buff = g_strdup_printf(
808                 "Could not send message to %s: "
809                 "not logged in or subscribing to instance %s.\n",
810                 tmp,
811                 retnotice->z_class_inst);
812      } else {
813        buff = g_strdup_printf(
814                 "Could not send message to %s: "
815                 "not logged in or subscribing to messages.\n",
816                 tmp);
817      }
818      owl_function_adminmsg("", buff);
819
820      memset(&zw, 0, sizeof(zw));
821      zw.class = g_strdup(retnotice->z_class);
822      zw.inst  = g_strdup(retnotice->z_class_inst);
823      realm = strchr(retnotice->z_recipient, '@');
824      if(realm) {
825        zw.realm = g_strdup(realm + 1);
826      } else {
827        zw.realm = g_strdup(owl_zephyr_get_realm());
828      }
829      zw.opcode = g_strdup(retnotice->z_opcode);
830      zw.zsig   = g_strdup("");
831      owl_list_create(&(zw.recips));
832      owl_list_append_element(&(zw.recips), g_strdup(tmp));
833
834      owl_log_outgoing_zephyr_error(&zw, buff);
835
836      owl_zwrite_cleanup(&zw);
837      g_free(buff);
838      g_free(tmp);
839    }
840  } else {
841    owl_function_error("Internal error on ack (%s)", retnotice->z_message);
842  }
843}
844#else
845void owl_zephyr_handle_ack(const void *retnotice)
846{
847}
848#endif
849
850#ifdef HAVE_LIBZEPHYR
851int owl_zephyr_notice_is_ack(const ZNotice_t *n)
852{
853  if (n->z_kind == SERVNAK || n->z_kind == SERVACK || n->z_kind == HMACK) {
854    if (!strcasecmp(n->z_class, LOGIN_CLASS)) return(0);
855    return(1);
856  }
857  return(0);
858}
859#else
860int owl_zephyr_notice_is_ack(const void *n)
861{
862  return(0);
863}
864#endif
865 
866void owl_zephyr_zaway(const owl_message *m)
867{
868#ifdef HAVE_LIBZEPHYR
869  char *tmpbuff, *myuser, *to;
870  owl_message *mout;
871  owl_zwrite *z;
872 
873  /* bail if it doesn't look like a message we should reply to.  Some
874   * of this defined by the way zaway(1) works
875   */
876  if (strcasecmp(owl_message_get_class(m), "message")) return;
877  if (strcasecmp(owl_message_get_recipient(m), ZGetSender())) return;
878  if (!strcasecmp(owl_message_get_sender(m), "")) return;
879  if (!strcasecmp(owl_message_get_opcode(m), "ping")) return;
880  if (!strcasecmp(owl_message_get_opcode(m), "auto")) return;
881  if (!strcasecmp(owl_message_get_zsig(m), "Automated reply:")) return;
882  if (!strcasecmp(owl_message_get_sender(m), ZGetSender())) return;
883  if (owl_message_get_attribute_value(m, "isauto")) return;
884
885  if (owl_global_is_smartstrip(&g)) {
886    to=owl_zephyr_smartstripped_user(owl_message_get_sender(m));
887  } else {
888    to=g_strdup(owl_message_get_sender(m));
889  }
890
891  send_zephyr("",
892              "Automated reply:",
893              owl_message_get_class(m),
894              owl_message_get_instance(m),
895              to,
896              owl_global_get_zaway_msg(&g));
897
898  myuser=short_zuser(to);
899  if (!strcasecmp(owl_message_get_instance(m), "personal")) {
900    tmpbuff = owl_string_build_quoted("zwrite %q", myuser);
901  } else {
902    tmpbuff = owl_string_build_quoted("zwrite -i %q %q", owl_message_get_instance(m), myuser);
903  }
904  g_free(myuser);
905  g_free(to);
906
907  z = owl_zwrite_new(tmpbuff);
908  g_free(tmpbuff);
909  if (z == NULL) {
910    owl_function_error("Error creating outgoing zephyr.");
911    return;
912  }
913  owl_zwrite_set_message(z, owl_global_get_zaway_msg(&g));
914  owl_zwrite_set_zsig(z, "Automated reply:");
915
916  /* display the message as an admin message in the receive window */
917  mout=owl_function_make_outgoing_zephyr(z);
918  owl_global_messagequeue_addmsg(&g, mout);
919  owl_zwrite_delete(z);
920#endif
921}
922
923#ifdef HAVE_LIBZEPHYR
924void owl_zephyr_hackaway_cr(ZNotice_t *n)
925{
926  /* replace \r's with ' '.  Gross-ish */
927  int i;
928
929  for (i=0; i<n->z_message_len; i++) {
930    if (n->z_message[i]=='\r') {
931      n->z_message[i]=' ';
932    }
933  }
934}
935#endif
936
937char *owl_zephyr_zlocate(const char *user, int auth)
938{
939#ifdef HAVE_LIBZEPHYR
940  int ret, numlocs;
941  int one = 1;
942  ZLocations_t locations;
943  char *myuser;
944  char *p, *result;
945
946  ZResetAuthentication();
947  ret = ZLocateUser(zstr(user), &numlocs, auth ? ZAUTH : ZNOAUTH);
948  if (ret != ZERR_NONE)
949    return g_strdup_printf("Error locating user %s: %s\n",
950                           user, error_message(ret));
951
952  myuser = short_zuser(user);
953  if (numlocs == 0) {
954    result = g_strdup_printf("%s: Hidden or not logged in\n", myuser);
955  } else {
956    result = g_strdup("");
957    for (; numlocs; numlocs--) {
958      ZGetLocations(&locations, &one);
959      p = g_strdup_printf("%s%s: %s\t%s\t%s\n",
960                          result, myuser,
961                          locations.host ? locations.host : "?",
962                          locations.tty ? locations.tty : "?",
963                          locations.time ? locations.time : "?");
964      g_free(result);
965      result = p;
966    }
967  }
968  g_free(myuser);
969
970  return result;
971#else
972  return g_strdup("");
973#endif
974}
975
976void owl_zephyr_addsub(const char *filename, const char *class, const char *inst, const char *recip)
977{
978#ifdef HAVE_LIBZEPHYR
979  char *line, *subsfile, *s = NULL;
980  FILE *file;
981  int duplicate = 0;
982
983  line = owl_zephyr_makesubline(class, inst, recip);
984  subsfile = owl_zephyr_dotfile(".zephyr.subs", filename);
985
986  /* if the file already exists, check to see if the sub is already there */
987  file = fopen(subsfile, "r");
988  if (file) {
989    while (owl_getline(&s, file)) {
990      if (strcasecmp(s, line) == 0) {
991        owl_function_error("Subscription already present in %s", subsfile);
992        duplicate++;
993      }
994    }
995    fclose(file);
996    g_free(s);
997  }
998
999  if (!duplicate) {
1000    file = fopen(subsfile, "a");
1001    if (file) {
1002      fputs(line, file);
1003      fclose(file);
1004      owl_function_makemsg("Subscription added");
1005    } else {
1006      owl_function_error("Error opening file %s for writing", subsfile);
1007    }
1008  }
1009
1010  g_free(line);
1011#endif
1012}
1013
1014void owl_zephyr_delsub(const char *filename, const char *class, const char *inst, const char *recip)
1015{
1016#ifdef HAVE_LIBZEPHYR
1017  char *line, *subsfile;
1018  int linesdeleted;
1019 
1020  line=owl_zephyr_makesubline(class, inst, recip);
1021  line[strlen(line)-1]='\0';
1022
1023  subsfile = owl_zephyr_dotfile(".zephyr.subs", filename);
1024 
1025  linesdeleted = owl_util_file_deleteline(subsfile, line, 1);
1026  if (linesdeleted > 0) {
1027    owl_function_makemsg("Subscription removed");
1028  } else if (linesdeleted == 0) {
1029    owl_function_error("No subscription present in %s", subsfile);
1030  }
1031  g_free(subsfile);
1032  g_free(line);
1033#endif
1034}
1035
1036/* caller must free the return */
1037char *owl_zephyr_makesubline(const char *class, const char *inst, const char *recip)
1038{
1039  return g_strdup_printf("%s,%s,%s\n", class, inst, !strcmp(recip, "") ? "*" : recip);
1040}
1041
1042
1043void owl_zephyr_zlog_in(void)
1044{
1045#ifdef HAVE_LIBZEPHYR
1046  const char *exposure, *eset;
1047  int ret;
1048
1049  ZResetAuthentication();
1050   
1051  eset=EXPOSE_REALMVIS;
1052  exposure=ZGetVariable(zstr("exposure"));
1053  if (exposure==NULL) {
1054    eset=EXPOSE_REALMVIS;
1055  } else if (!strcasecmp(exposure,EXPOSE_NONE)) {
1056    eset = EXPOSE_NONE;
1057  } else if (!strcasecmp(exposure,EXPOSE_OPSTAFF)) {
1058    eset = EXPOSE_OPSTAFF;
1059  } else if (!strcasecmp(exposure,EXPOSE_REALMVIS)) {
1060    eset = EXPOSE_REALMVIS;
1061  } else if (!strcasecmp(exposure,EXPOSE_REALMANN)) {
1062    eset = EXPOSE_REALMANN;
1063  } else if (!strcasecmp(exposure,EXPOSE_NETVIS)) {
1064    eset = EXPOSE_NETVIS;
1065  } else if (!strcasecmp(exposure,EXPOSE_NETANN)) {
1066    eset = EXPOSE_NETANN;
1067  }
1068   
1069  ret=ZSetLocation(zstr(eset));
1070  if (ret != ZERR_NONE) {
1071    /*
1072      owl_function_makemsg("Error setting location: %s", error_message(ret));
1073    */
1074  }
1075#endif
1076}
1077
1078void owl_zephyr_zlog_out(void)
1079{
1080#ifdef HAVE_LIBZEPHYR
1081  int ret;
1082
1083  ZResetAuthentication();
1084  ret=ZUnsetLocation();
1085  if (ret != ZERR_NONE) {
1086    /*
1087      owl_function_makemsg("Error unsetting location: %s", error_message(ret));
1088    */
1089  }
1090#endif
1091}
1092
1093void owl_zephyr_addbuddy(const char *name)
1094{
1095  char *filename;
1096  FILE *file;
1097 
1098  filename = owl_zephyr_dotfile(".anyone", NULL);
1099  file = fopen(filename, "a");
1100  g_free(filename);
1101  if (!file) {
1102    owl_function_error("Error opening zephyr buddy file for append");
1103    return;
1104  }
1105  fprintf(file, "%s\n", name);
1106  fclose(file);
1107}
1108
1109void owl_zephyr_delbuddy(const char *name)
1110{
1111  char *filename;
1112
1113  filename = owl_zephyr_dotfile(".anyone", NULL);
1114  owl_util_file_deleteline(filename, name, 0);
1115  g_free(filename);
1116}
1117
1118/* return auth string */
1119#ifdef HAVE_LIBZEPHYR
1120const char *owl_zephyr_get_authstr(const ZNotice_t *n)
1121{
1122
1123  if (!n) return("UNKNOWN");
1124
1125  if (n->z_auth == ZAUTH_FAILED) {
1126    return ("FAILED");
1127  } else if (n->z_auth == ZAUTH_NO) {
1128    return ("NO");
1129  } else if (n->z_auth == ZAUTH_YES) {
1130    return ("YES");
1131  } else {
1132    return ("UNKNOWN");
1133  }           
1134}
1135#else
1136const char *owl_zephyr_get_authstr(const void *n)
1137{
1138  return("");
1139}
1140#endif
1141
1142/* Returns a buffer of subscriptions or an error message.  Caller must
1143 * free the return.
1144 */
1145char *owl_zephyr_getsubs(void)
1146{
1147#ifdef HAVE_LIBZEPHYR
1148  Code_t ret;
1149  int num, i, one;
1150  ZSubscription_t sub;
1151  GString *buf;
1152
1153  ret = ZRetrieveSubscriptions(0, &num);
1154  if (ret != ZERR_NONE)
1155    return g_strdup_printf("Zephyr: Requesting subscriptions: %s\n", error_message(ret));
1156  if (num == 0)
1157    return g_strdup("Zephyr: No subscriptions retrieved\n");
1158
1159  buf = g_string_new("");
1160  for (i=0; i<num; i++) {
1161    one = 1;
1162    if ((ret = ZGetSubscriptions(&sub, &one)) != ZERR_NONE) {
1163      ZFlushSubscriptions();
1164      g_string_free(buf, true);
1165      return g_strdup_printf("Zephyr: Getting subscriptions: %s\n", error_message(ret));
1166    } else {
1167      /* g_string_append_printf would be backwards. */
1168      char *tmp = g_strdup_printf("<%s,%s,%s>\n",
1169                                  sub.zsub_class,
1170                                  sub.zsub_classinst,
1171                                  sub.zsub_recipient);
1172      g_string_prepend(buf, tmp);
1173      g_free(tmp);
1174    }
1175  }
1176
1177  ZFlushSubscriptions();
1178  return g_string_free(buf, false);
1179#else
1180  return(g_strdup("Zephyr not available"));
1181#endif
1182}
1183
1184const char *owl_zephyr_get_variable(const char *var)
1185{
1186#ifdef HAVE_LIBZEPHYR
1187  return(ZGetVariable(zstr(var)));
1188#else
1189  return("");
1190#endif
1191}
1192
1193void owl_zephyr_set_locationinfo(const char *host, const char *val)
1194{
1195#ifdef HAVE_LIBZEPHYR
1196  ZInitLocationInfo(zstr(host), zstr(val));
1197#endif
1198}
1199 
1200/* Strip a local realm fron the zephyr user name.
1201 * The caller must free the return
1202 */
1203char *short_zuser(const char *in)
1204{
1205  char *out, *ptr;
1206
1207  out=g_strdup(in);
1208  ptr=strchr(out, '@');
1209  if (ptr) {
1210    if (!strcasecmp(ptr+1, owl_zephyr_get_realm())) {
1211      *ptr='\0';
1212    }
1213  }
1214  return(out);
1215}
1216
1217/* Append a local realm to the zephyr user name if necessary.
1218 * The caller must free the return.
1219 */
1220char *long_zuser(const char *in)
1221{
1222  if (strchr(in, '@')) {
1223    return(g_strdup(in));
1224  }
1225  return(g_strdup_printf("%s@%s", in, owl_zephyr_get_realm()));
1226}
1227
1228/* strip out the instance from a zsender's principal.  Preserves the
1229 * realm if present.  Leave host/ and daemon/ krb5 principals
1230 * alone. Also leave rcmd. and daemon. krb4 principals alone. The
1231 * caller must free the return.
1232 */
1233char *owl_zephyr_smartstripped_user(const char *in)
1234{
1235  char *slash, *dot, *realm, *out;
1236
1237  out = g_strdup(in);
1238
1239  /* bail immeaditly if we don't have to do any work */
1240  slash = strchr(out, '/');
1241  dot = strchr(out, '.');
1242  if (!slash && !dot) {
1243    return(out);
1244  }
1245
1246  if (!strncasecmp(out, OWL_ZEPHYR_NOSTRIP_HOST, strlen(OWL_ZEPHYR_NOSTRIP_HOST)) ||
1247      !strncasecmp(out, OWL_ZEPHYR_NOSTRIP_RCMD, strlen(OWL_ZEPHYR_NOSTRIP_RCMD)) ||
1248      !strncasecmp(out, OWL_ZEPHYR_NOSTRIP_DAEMON5, strlen(OWL_ZEPHYR_NOSTRIP_DAEMON5)) ||
1249      !strncasecmp(out, OWL_ZEPHYR_NOSTRIP_DAEMON4, strlen(OWL_ZEPHYR_NOSTRIP_DAEMON4))) {
1250    return(out);
1251  }
1252
1253  realm = strchr(out, '@');
1254  if (!slash && dot && realm && (dot > realm)) {
1255    /* There's no '/', and the first '.' is in the realm */
1256    return(out);
1257  }
1258
1259  /* remove the realm from out, but hold on to it */
1260  if (realm) realm[0]='\0';
1261
1262  /* strip */
1263  if (slash) slash[0] = '\0';  /* krb5 style user/instance */
1264  else if (dot) dot[0] = '\0'; /* krb4 style user.instance */
1265
1266  /* reattach the realm if we had one */
1267  if (realm) {
1268    strcat(out, "@");
1269    strcat(out, realm+1);
1270  }
1271
1272  return(out);
1273}
1274
1275/* read the list of users in 'filename' as a .anyone file, and put the
1276 * names of the zephyr users in the list 'in'.  If 'filename' is NULL,
1277 * use the default .anyone file in the users home directory.  Returns
1278 * -1 on failure, 0 on success.
1279 */
1280int owl_zephyr_get_anyone_list(owl_list *in, const char *filename)
1281{
1282#ifdef HAVE_LIBZEPHYR
1283  char *ourfile, *tmp, *s = NULL;
1284  FILE *f;
1285
1286  ourfile = owl_zephyr_dotfile(".anyone", filename);
1287
1288  f = fopen(ourfile, "r");
1289  if (!f) {
1290    owl_function_error("Error opening file %s: %s", ourfile, strerror(errno) ? strerror(errno) : "");
1291    g_free(ourfile);
1292    return -1;
1293  }
1294  g_free(ourfile);
1295
1296  while (owl_getline_chomp(&s, f)) {
1297    /* ignore comments, blank lines etc. */
1298    if (s[0] == '#' || s[0] == '\0')
1299      continue;
1300
1301    /* ignore from # on */
1302    tmp = strchr(s, '#');
1303    if (tmp)
1304      tmp[0] = '\0';
1305
1306    /* ignore from SPC */
1307    tmp = strchr(s, ' ');
1308    if (tmp)
1309      tmp[0] = '\0';
1310
1311    owl_list_append_element(in, long_zuser(s));
1312  }
1313  g_free(s);
1314  fclose(f);
1315  return 0;
1316#else
1317  return -1;
1318#endif
1319}
1320
1321#ifdef HAVE_LIBZEPHYR
1322void owl_zephyr_process_pseudologin(ZNotice_t *n)
1323{
1324  owl_message *m;
1325  owl_zbuddylist *zbl;
1326  GList **zaldlist;
1327  GList *zaldptr;
1328  ZAsyncLocateData_t *zald = NULL;
1329  ZLocations_t location;
1330  int numlocs, ret, notify;
1331
1332  /* Find a ZALD to match this notice. */
1333  zaldlist = owl_global_get_zaldlist(&g);
1334  zaldptr = g_list_first(*zaldlist);
1335  while (zaldptr) {
1336    if (ZCompareALDPred(n, zaldptr->data)) {
1337      zald = zaldptr->data;
1338      *zaldlist = g_list_remove(*zaldlist, zaldptr->data);
1339      break;
1340    }
1341    zaldptr = g_list_next(zaldptr);
1342  }
1343  if (zald) {
1344    /* Deal with notice. */
1345    notify = owl_global_get_pseudologin_notify(&g);
1346    zbl = owl_global_get_zephyr_buddylist(&g);
1347    ret = ZParseLocations(n, zald, &numlocs, NULL);
1348    if (ret == ZERR_NONE) {
1349      if (numlocs > 0 && !owl_zbuddylist_contains_user(zbl, zald->user)) {
1350        if (notify) {
1351          numlocs = 1;
1352          ret = ZGetLocations(&location, &numlocs);
1353          if (ret == ZERR_NONE) {
1354            /* Send a PSEUDO LOGIN! */
1355            m = g_new(owl_message, 1);
1356            owl_message_create_pseudo_zlogin(m, 0, zald->user,
1357                                             location.host,
1358                                             location.time,
1359                                             location.tty);
1360            owl_global_messagequeue_addmsg(&g, m);
1361          }
1362          owl_zbuddylist_adduser(zbl, zald->user);
1363          owl_function_debugmsg("owl_function_zephyr_buddy_check: login for %s ", zald->user);
1364        }
1365      } else if (numlocs == 0 && owl_zbuddylist_contains_user(zbl, zald->user)) {
1366        /* Send a PSEUDO LOGOUT! */
1367        if (notify) {
1368          m = g_new(owl_message, 1);
1369          owl_message_create_pseudo_zlogin(m, 1, zald->user, "", "", "");
1370          owl_global_messagequeue_addmsg(&g, m);
1371        }
1372        owl_zbuddylist_deluser(zbl, zald->user);
1373        owl_function_debugmsg("owl_function_zephyr_buddy_check: logout for %s ", zald->user);
1374      }
1375    }
1376    ZFreeALD(zald);
1377    g_free(zald);
1378  }
1379}
1380#else
1381void owl_zephyr_process_pseudologin(void *n)
1382{
1383}
1384#endif
1385
1386void owl_zephyr_buddycheck_timer(owl_timer *t, void *data)
1387{
1388  if (owl_global_is_pseudologins(&g)) {
1389    owl_function_debugmsg("Doing zephyr buddy check");
1390    owl_function_zephyr_buddy_check(1);
1391  } else {
1392    owl_function_debugmsg("Warning: owl_zephyr_buddycheck_timer call pointless; timer should have been disabled");
1393  }
1394}
1395
1396/*
1397 * Process zephyrgrams from libzephyr's queue. To prevent starvation,
1398 * process a maximum of OWL_MAX_ZEPHYRGRAMS_TO_PROCESS.
1399 *
1400 * Returns the number of zephyrgrams processed.
1401 */
1402
1403#define OWL_MAX_ZEPHYRGRAMS_TO_PROCESS 20
1404
1405static int _owl_zephyr_process_events(void)
1406{
1407  int zpendcount=0;
1408#ifdef HAVE_LIBZEPHYR
1409  ZNotice_t notice;
1410  Code_t code;
1411  owl_message *m=NULL;
1412
1413  while(owl_zephyr_zpending() && zpendcount < OWL_MAX_ZEPHYRGRAMS_TO_PROCESS) {
1414    if (owl_zephyr_zpending()) {
1415      if ((code = ZReceiveNotice(&notice, NULL)) != ZERR_NONE) {
1416        owl_function_debugmsg("Error: %s while calling ZReceiveNotice\n",
1417                              error_message(code));
1418        continue;
1419      }
1420      zpendcount++;
1421
1422      /* is this an ack from a zephyr we sent? */
1423      if (owl_zephyr_notice_is_ack(&notice)) {
1424        owl_zephyr_handle_ack(&notice);
1425        ZFreeNotice(&notice);
1426        continue;
1427      }
1428
1429      /* if it's a ping and we're not viewing pings then skip it */
1430      if (!owl_global_is_rxping(&g) && !strcasecmp(notice.z_opcode, "ping")) {
1431        ZFreeNotice(&notice);
1432        continue;
1433      }
1434
1435      /* if it is a LOCATE message, it's for pseudologins. */
1436      if (strcmp(notice.z_opcode, LOCATE_LOCATE) == 0) {
1437        owl_zephyr_process_pseudologin(&notice);
1438        ZFreeNotice(&notice);
1439        continue;
1440      }
1441
1442      /* create the new message */
1443      m=g_new(owl_message, 1);
1444      owl_message_create_from_znotice(m, &notice);
1445
1446      owl_global_messagequeue_addmsg(&g, m);
1447    }
1448  }
1449#endif
1450  return zpendcount;
1451}
1452
1453void owl_zephyr_process_events(const owl_io_dispatch *d, void *data)
1454{
1455  _owl_zephyr_process_events();
1456}
1457
1458int owl_zephyr_pre_select_action(owl_ps_action *a, void *p)
1459{
1460  return _owl_zephyr_process_events();
1461}
Note: See TracBrowser for help on using the repository browser.