source: zephyr.c @ 18105584

debianrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 18105584 was 18105584, checked in by Nelson Elhage <nelhage@mit.edu>, 15 years ago
zephyr: Don't give bogus error messages when adding subscriptions. We were returning the value of an uninitalized 'ret' if we added subscriptions to the deferred list instead of taking them immediately. This primarily manifests as an occasional (false) error suscribing to login messages at startup.
  • Property mode set to 100644
File size: 30.3 KB
RevLine 
[7d4fbcd]1#include <stdlib.h>
2#include <unistd.h>
3#include <sys/types.h>
4#include <sys/wait.h>
[4357be8]5#include <sys/stat.h>
[7d4fbcd]6#include <string.h>
7#include "owl.h"
8
[1aee7d9]9static const char fileIdent[] = "$Id$";
10
[a5e7ed6]11static GList *deferred_subs = NULL;
12typedef struct _owl_sub_list {                            /* noproto */
13  ZSubscription_t *subs;
14  int nsubs;
15} owl_sub_list;
16
[09489b89]17#ifdef HAVE_LIBZEPHYR
[8262340]18Code_t ZResetAuthentication();
[09489b89]19#endif
[8262340]20
[02f55dc]21#define HM_SVC_FALLBACK         htons((unsigned short) 2104)
22
[52a0f14]23#ifdef HAVE_LIBZEPHYR
24void owl_zephyr_initialize()
25{
26  int ret;
[02f55dc]27  struct servent *sp;
28  struct sockaddr_in sin;
29  ZNotice_t req;
30  Code_t code;
[52a0f14]31  owl_dispatch *dispatch;
32
33  /*
34   * Code modified from libzephyr's ZhmStat.c
35   *
36   * Modified to add the fd to our select loop, rather than hanging
37   * until we get an ack.
38   */
39
40  if ((ret = ZOpenPort(NULL)) != ZERR_NONE) {
41    owl_function_error("Error opening Zephyr port: %s", error_message(ret));
42    return;
43  }
[02f55dc]44
45  (void) memset((char *)&sin, 0, sizeof(struct sockaddr_in));
46
47  sp = getservbyname(HM_SVCNAME, "udp");
48
49  sin.sin_port = (sp) ? sp->s_port : HM_SVC_FALLBACK;
50  sin.sin_family = AF_INET;
51
52  sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
53
54  (void) memset((char *)&req, 0, sizeof(req));
55  req.z_kind = STAT;
56  req.z_port = 0;
57  req.z_class = HM_STAT_CLASS;
58  req.z_class_inst = HM_STAT_CLIENT;
59  req.z_opcode = HM_GIMMESTATS;
60  req.z_sender = "";
61  req.z_recipient = "";
62  req.z_default_format = "";
63  req.z_message_len = 0;
[52a0f14]64
65  if ((code = ZSetDestAddr(&sin)) != ZERR_NONE) {
66    owl_function_error("Initializing Zephyr: %s", error_message(code));
67    return;
68  }
69
70  if ((code = ZSendNotice(&req, ZNOAUTH)) != ZERR_NONE) {
71    owl_function_error("Initializing Zephyr: %s", error_message(code));
72    return;
73  }
74
75  dispatch = owl_malloc(sizeof(*dispatch));
76  dispatch->fd = ZGetFD();
77  dispatch->cfunc = owl_zephyr_finish_initialization;
78  dispatch->destroy = (void(*)(owl_dispatch*))owl_free;
79
80  owl_select_add_dispatch(dispatch);
[02f55dc]81}
82
[52a0f14]83void owl_zephyr_finish_initialization(owl_dispatch *d) {
84  Code_t code;
85
86  owl_select_remove_dispatch(d->fd);
87
88  ZClosePort();
89
90  if ((code = ZInitialize()) != ZERR_NONE) {
91    owl_function_error("Initializing Zephyr: %s", error_message(code));
92    return;
93  }
94
95  if ((code = ZOpenPort(NULL)) != ZERR_NONE) {
96    owl_function_error("Initializing Zephyr: %s", error_message(code));
97    return;
98  }
99
100  d = owl_malloc(sizeof(owl_dispatch));
101  d->fd = ZGetFD();
102  d->cfunc = &owl_zephyr_process_events;
103  d->destroy = NULL;
104  owl_select_add_dispatch(d);
105  owl_global_set_havezephyr(&g);
106
107  if(g.load_initial_subs) {
108    owl_zephyr_load_initial_subs();
109  }
[a5e7ed6]110  while(deferred_subs != NULL) {
111    owl_sub_list *subs = deferred_subs->data;
112    owl_function_debugmsg("Loading %d deferred subs.", subs->nsubs);
113    owl_zephyr_loadsubs_helper(subs->subs, subs->nsubs);
114    deferred_subs = g_list_delete_link(deferred_subs, deferred_subs);
115    owl_free(subs);
116  }
[52a0f14]117}
118
119void owl_zephyr_load_initial_subs() {
120  int ret, ret2;
121
122  owl_function_debugmsg("startup: loading initial zephyr subs");
123
124  /* load default subscriptions */
125  ret = owl_zephyr_loaddefaultsubs();
126
127  /* load subscriptions from subs file */
128  ret2 = owl_zephyr_loadsubs(NULL, 0);
129
130  if (ret || ret2) {
131    owl_function_error("Error loading zephyr subscriptions");
132  } else if (ret2!=-1) {
133    owl_global_add_userclue(&g, OWL_USERCLUE_CLASSES);
134  }
135
136  /* load login subscriptions */
137  if (owl_global_is_loginsubs(&g)) {
138    owl_function_debugmsg("startup: loading login subs");
139    owl_function_loadloginsubs(NULL);
140  }
141}
142#else
143void owl_zephyr_initialize()
144{
145}
[02f55dc]146#endif
147
[52a0f14]148
[09489b89]149int owl_zephyr_shutdown()
150{
151#ifdef HAVE_LIBZEPHYR
[bfbf590]152  if(owl_global_is_havezephyr(&g)) {
153    unsuball();
154    ZClosePort();
155  }
[09489b89]156#endif
[be0a79f]157  return(0);
158}
159
160int owl_zephyr_zpending()
161{
162#ifdef HAVE_LIBZEPHYR
[bfbf590]163  if(owl_global_is_havezephyr(&g))
164    return(ZPending());
165  else
166    return 0;
[be0a79f]167#else
168  return(0);
169#endif
170}
171
[09489b89]172char *owl_zephyr_get_realm()
173{
174#ifdef HAVE_LIBZEPHYR
175  return(ZGetRealm());
176#else
177  return("");
178#endif
179}
180
181char *owl_zephyr_get_sender()
182{
183#ifdef HAVE_LIBZEPHYR
184  return(ZGetSender());
185#else
186  return("");
187#endif
188}
189
[f6050ee]190#ifdef HAVE_LIBZEPHYR
[93e883d]191int owl_zephyr_loadsubs_helper(ZSubscription_t subs[], int count)
192{
[18105584]193  int ret = 0;
[a5e7ed6]194  if (owl_global_is_havezephyr(&g)) {
195    int i;
196    /* sub without defaults */
197    if (ZSubscribeToSansDefaults(subs,count,0) != ZERR_NONE) {
198      owl_function_error("Error subscribing to zephyr notifications.");
199      ret=-2;
200    }
[93e883d]201
[a5e7ed6]202    /* free stuff */
203    for (i=0; i<count; i++) {
204      owl_free(subs[i].zsub_class);
205      owl_free(subs[i].zsub_classinst);
206      owl_free(subs[i].zsub_recipient);
207    }
[bb2c60d]208
[a5e7ed6]209    owl_free(subs);
210  } else {
211    owl_sub_list *s = owl_malloc(sizeof(owl_sub_list));
212    s->subs = subs;
213    s->nsubs = count;
214    deferred_subs = g_list_append(deferred_subs, s);
215  }
[d21efbc]216
[93e883d]217  return ret;
218}
[f6050ee]219#endif
[93e883d]220
[95474d7]221/* Load zephyr subscriptions form 'filename'.  If 'filename' is NULL,
222 * the default file $HOME/.zephyr.subs will be used.
223 *
224 * Returns 0 on success.  If the file does not exist, return -1 if
225 * 'error_on_nofile' is 1, otherwise return 0.  Return -1 if the file
226 * exists but can not be read.  Return -2 if there is a failure from
227 * zephyr to load the subscriptions.
[2de4f20]228 */
[95474d7]229int owl_zephyr_loadsubs(char *filename, int error_on_nofile)
[31e48a3]230{
[be0a79f]231#ifdef HAVE_LIBZEPHYR
[7d4fbcd]232  FILE *file;
233  char *tmp, *start;
234  char buffer[1024], subsfile[1024];
[bb2c60d]235  ZSubscription_t *subs;
236  int subSize = 1024;
[93e883d]237  int count, ret;
[4357be8]238  struct stat statbuff;
[7d4fbcd]239
[bb2c60d]240  subs = owl_malloc(sizeof(ZSubscription_t) * subSize);
[7d4fbcd]241  if (filename==NULL) {
242    sprintf(subsfile, "%s/%s", owl_global_get_homedir(&g), ".zephyr.subs");
243  } else {
244    strcpy(subsfile, filename);
245  }
[8262340]246
[4357be8]247  ret=stat(subsfile, &statbuff);
[95474d7]248  if (ret) {
249    if (error_on_nofile==1) return(-1);
250    return(0);
251  }
[4357be8]252
[8262340]253  ZResetAuthentication();
[7d4fbcd]254  count=0;
255  file=fopen(subsfile, "r");
[95474d7]256  if (!file) return(-1);
257  while ( fgets(buffer, 1024, file)!=NULL ) {
258    if (buffer[0]=='#' || buffer[0]=='\n' || buffer[0]=='\n') continue;
259   
260    if (buffer[0]=='-') {
261      start=buffer+1;
262    } else {
263      start=buffer;
[7d4fbcd]264    }
[95474d7]265   
[bb2c60d]266    if (count >= subSize) {
[d21efbc]267      subSize *= 2;
268      subs = owl_realloc(subs, sizeof(ZSubscription_t) * subSize);
[93e883d]269    }
[95474d7]270   
271    /* add it to the list of subs */
272    if ((tmp=(char *) strtok(start, ",\n\r"))==NULL) continue;
273    subs[count].zsub_class=owl_strdup(tmp);
274    if ((tmp=(char *) strtok(NULL, ",\n\r"))==NULL) continue;
275    subs[count].zsub_classinst=owl_strdup(tmp);
276    if ((tmp=(char *) strtok(NULL, " \t\n\r"))==NULL) continue;
277    subs[count].zsub_recipient=owl_strdup(tmp);
278   
[bb2c60d]279    /* if it started with '-' then add it to the global punt list, and
280     * remove it from the list of subs. */
[95474d7]281    if (buffer[0]=='-') {
282      owl_function_zpunt(subs[count].zsub_class, subs[count].zsub_classinst, subs[count].zsub_recipient, 0);
[bb2c60d]283      owl_free(subs[count].zsub_class);
284      owl_free(subs[count].zsub_classinst);
285      owl_free(subs[count].zsub_recipient);
286    }
287    else {
288      count++;
[95474d7]289    }
[7d4fbcd]290  }
[95474d7]291  fclose(file);
[7d4fbcd]292
[0cff2b4]293  owl_zephyr_loadsubs_helper(subs, count);
[7d4fbcd]294  return(ret);
[be0a79f]295#else
296  return(0);
297#endif
[7d4fbcd]298}
299
[4357be8]300int owl_zephyr_loaddefaultsubs()
301{
[40d834a]302#ifdef HAVE_LIBZEPHYR
[4357be8]303  ZSubscription_t subs[10];
304   
305  if (ZSubscribeTo(subs,0,0) != ZERR_NONE) {
306    owl_function_error("Error subscribing to default zephyr notifications.");
307    return(-1);
308  }
309  return(0);
[40d834a]310#else
311  return(0);
312#endif
[4357be8]313}
314
[31e48a3]315int owl_zephyr_loadloginsubs(char *filename)
316{
[be0a79f]317#ifdef HAVE_LIBZEPHYR
[7d4fbcd]318  FILE *file;
[d21efbc]319  ZSubscription_t *subs;
320  int numSubs = 100;
[7d4fbcd]321  char subsfile[1024], buffer[1024];
[d21efbc]322  int count, ret;
[4357be8]323  struct stat statbuff;
[7d4fbcd]324
[d21efbc]325  subs = owl_malloc(numSubs * sizeof(ZSubscription_t));
326
[7d4fbcd]327  if (filename==NULL) {
328    sprintf(subsfile, "%s/%s", owl_global_get_homedir(&g), ".anyone");
329  } else {
330    strcpy(subsfile, filename);
331  }
[4357be8]332 
333  ret=stat(subsfile, &statbuff);
334  if (ret) return(0);
335
336  ret=0;
[7d4fbcd]337
[8262340]338  ZResetAuthentication();
[7d4fbcd]339  count=0;
340  file=fopen(subsfile, "r");
341  if (file) {
342    while ( fgets(buffer, 1024, file)!=NULL ) {
343      if (buffer[0]=='#' || buffer[0]=='\n' || buffer[0]=='\n') continue;
344     
[d21efbc]345      if (count == numSubs) {
346        numSubs *= 2;
347        subs = owl_realloc(subs, numSubs * sizeof(ZSubscription_t));
348      }
[7d4fbcd]349
350      buffer[strlen(buffer)-1]='\0';
[d21efbc]351      subs[count].zsub_class=owl_strdup("login");
352      subs[count].zsub_recipient=owl_strdup("*");
[7d4fbcd]353      if (strchr(buffer, '@')) {
[d21efbc]354        subs[count].zsub_classinst=owl_strdup(buffer);
[7d4fbcd]355      } else {
[d21efbc]356        subs[count].zsub_classinst=owl_sprintf("%s@%s", buffer, ZGetRealm());
[7d4fbcd]357      }
358
359      count++;
360    }
361    fclose(file);
362  } else {
363    count=0;
364    ret=-1;
365  }
366
[d21efbc]367  ret = owl_zephyr_loadsubs_helper(subs, count);
[7d4fbcd]368  return(ret);
[be0a79f]369#else
370  return(0);
371#endif
[7d4fbcd]372}
373
[31e48a3]374void unsuball()
375{
[be0a79f]376#if HAVE_LIBZEPHYR
[7d4fbcd]377  int ret;
[8262340]378
379  ZResetAuthentication();
[7d4fbcd]380  ret=ZCancelSubscriptions(0);
381  if (ret != ZERR_NONE) {
382    com_err("owl",ret,"while unsubscribing");
383  }
[be0a79f]384#endif
[7d4fbcd]385}
386
[31e48a3]387int owl_zephyr_sub(char *class, char *inst, char *recip)
388{
[be0a79f]389#ifdef HAVE_LIBZEPHYR
[7d4fbcd]390  ZSubscription_t subs[5];
391
392  subs[0].zsub_class=class;
393  subs[0].zsub_classinst=inst;
394  subs[0].zsub_recipient=recip;
395
[8262340]396  ZResetAuthentication();
[7d4fbcd]397  if (ZSubscribeTo(subs,1,0) != ZERR_NONE) {
[97cd00be]398    owl_function_error("Error subbing to <%s,%s,%s>", class, inst, recip);
399    return(-2);
[7d4fbcd]400  }
401  return(0);
[be0a79f]402#else
403  return(0);
404#endif
[7d4fbcd]405}
406
407
[31e48a3]408int owl_zephyr_unsub(char *class, char *inst, char *recip)
409{
[be0a79f]410#ifdef HAVE_LIBZEPHYR
[7d4fbcd]411  ZSubscription_t subs[5];
412
413  subs[0].zsub_class=class;
414  subs[0].zsub_classinst=inst;
415  subs[0].zsub_recipient=recip;
416
[8262340]417  ZResetAuthentication();
[7d4fbcd]418  if (ZUnsubscribeTo(subs,1,0) != ZERR_NONE) {
[97cd00be]419    owl_function_error("Error unsubbing from <%s,%s,%s>", class, inst, recip);
420    return(-2);
[7d4fbcd]421  }
422  return(0);
[be0a79f]423#else
424  return(0);
425#endif
[7d4fbcd]426}
427
[b0430a6]428/* return a pointer to the data in the Jth field, (NULL terminated by
429 * definition).  Caller must free the return.
430 */
[be0a79f]431#ifdef HAVE_LIBZEPHYR
[b0430a6]432char *owl_zephyr_get_field(ZNotice_t *n, int j)
[31e48a3]433{
[7d4fbcd]434  int i, count, save;
[b0430a6]435  char *out;
[7d4fbcd]436
[128171a]437  /* If there's no message here, just run along now */
438  if (n->z_message_len == 0)
439    return(owl_strdup(""));
440
[7d4fbcd]441  count=save=0;
442  for (i=0; i<n->z_message_len; i++) {
443    if (n->z_message[i]=='\0') {
444      count++;
445      if (count==j) {
446        /* just found the end of the field we're looking for */
[b0430a6]447        return(owl_strdup(n->z_message+save));
[7d4fbcd]448      } else {
449        save=i+1;
450      }
451    }
452  }
[b0430a6]453  /* catch the last field, which might not be null terminated */
[7d4fbcd]454  if (count==j-1) {
[b0430a6]455    out=owl_malloc(n->z_message_len-save+5);
456    memcpy(out, n->z_message+save, n->z_message_len-save);
457    out[n->z_message_len-save]='\0';
458    return(out);
[7d4fbcd]459  }
[b0430a6]460
461  return(owl_strdup(""));
[7d4fbcd]462}
[5376a95]463
464char *owl_zephyr_get_field_as_utf8(ZNotice_t *n, int j)
465{
466  int i, count, save;
467
468  /* If there's no message here, just run along now */
469  if (n->z_message_len == 0)
470    return(owl_strdup(""));
471
472  count=save=0;
473  for (i = 0; i < n->z_message_len; i++) {
474    if (n->z_message[i]=='\0') {
475      count++;
476      if (count == j) {
477        /* just found the end of the field we're looking for */
[6201646]478        return(owl_validate_or_convert(n->z_message + save));
[5376a95]479      } else {
480        save = i + 1;
481      }
482    }
483  }
484  /* catch the last field, which might not be null terminated */
485  if (count == j - 1) {
[6201646]486    char *tmp, *out;
487    tmp = owl_malloc(n->z_message_len-save+5);
488    memcpy(tmp, n->z_message+save, n->z_message_len-save);
489    tmp[n->z_message_len-save]='\0';
490    out = owl_validate_or_convert(tmp);
491    owl_free(tmp);
492    return out;
[5376a95]493  }
494
495  return(owl_strdup(""));
496}
[09489b89]497#else
[701a184]498char *owl_zephyr_get_field(void *n, int j)
[09489b89]499{
[b0430a6]500  return(owl_strdup(""));
[09489b89]501}
[5577606]502char *owl_zephyr_get_field_as_utf8(void *n, int j)
[5376a95]503{
504  return owl_zephyr_get_field(n, j);
505}
[be0a79f]506#endif
[7d4fbcd]507
[b0430a6]508
[be0a79f]509#ifdef HAVE_LIBZEPHYR
[31e48a3]510int owl_zephyr_get_num_fields(ZNotice_t *n)
511{
[7d4fbcd]512  int i, fields;
513
[50e29e3]514  if(n->z_message_len == 0)
515    return 0;
516
[7d4fbcd]517  fields=1;
518  for (i=0; i<n->z_message_len; i++) {
519    if (n->z_message[i]=='\0') fields++;
520  }
521 
522  return(fields);
523}
[09489b89]524#else
525int owl_zephyr_get_num_fields(void *n)
526{
527  return(0);
528}
[be0a79f]529#endif
[7d4fbcd]530
[be0a79f]531#ifdef HAVE_LIBZEPHYR
[bf73bdd]532/* return a pointer to the message, place the message length in k
533 * caller must free the return
534 */
[85d1795]535char *owl_zephyr_get_message(ZNotice_t *n, owl_message *m)
[31e48a3]536{
[405d5e6]537  /* don't let ping messages have a body */
[7d4fbcd]538  if (!strcasecmp(n->z_opcode, "ping")) {
[bf73bdd]539    return(owl_strdup(""));
[7d4fbcd]540  }
541
[a1bb198]542  /* deal with MIT NOC messages */
[85d1795]543  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")) {
544    char *msg, *field3, *field4;
[a1bb198]545
546    field3 = owl_zephyr_get_field(n, 3);
547    field4 = owl_zephyr_get_field(n, 4);
548
[85d1795]549    msg = owl_sprintf("%s service on %s %s\n%s", n->z_opcode, n->z_class_inst, field3, field4);
[272a4a0]550    owl_free(field3);
551    owl_free(field4);
[a1bb198]552    if (msg) {
553      return msg;
554    }
555  }
[fba0f96]556  /* deal with MIT Discuss messages */
[e2a620b]557  else if (!strcasecmp(n->z_default_format, "New transaction [$1] entered in $2\nFrom: $3 ($5)\nSubject: $4") ||
558           !strcasecmp(n->z_default_format, "New transaction [$1] entered in $2\nFrom: $3\nSubject: $4")) {
[fba0f96]559    char *msg, *field1, *field2, *field3, *field4, *field5;
560   
561    field1 = owl_zephyr_get_field(n, 1);
562    field2 = owl_zephyr_get_field(n, 2);
563    field3 = owl_zephyr_get_field(n, 3);
564    field4 = owl_zephyr_get_field(n, 4);
565    field5 = owl_zephyr_get_field(n, 5);
566   
567    msg = owl_sprintf("New transaction [%s] entered in %s\nFrom: %s (%s)\nSubject: %s", field1, field2, field3, field5, field4);
568    owl_free(field1);
569    owl_free(field2);
570    owl_free(field3);
571    owl_free(field4);
572    owl_free(field5);
573    if (msg) {
574      return msg;
575    }
576  }
[85d1795]577  /* deal with MIT Moira messages */
578  else if (!strcasecmp(n->z_default_format, "MOIRA $instance on $fromhost:\n $message\n")) {
579    char *msg, *field1;
580   
581    field1 = owl_zephyr_get_field(n, 1);
582   
583    msg = owl_sprintf("MOIRA %s on %s: %s", n->z_class_inst, owl_message_get_hostname(m), field1);
584    owl_free(field1);
585    if (msg) {
586      return msg;
587    }
588  }
[405d5e6]589
[85d1795]590  if (owl_zephyr_get_num_fields(n) == 1) {
591    return(owl_zephyr_get_field(n, 1));
592  }
593  else {
594    return(owl_zephyr_get_field(n, 2));
595  }
[7d4fbcd]596}
[be0a79f]597#endif
[7d4fbcd]598
[be0a79f]599#ifdef HAVE_LIBZEPHYR
[31e48a3]600char *owl_zephyr_get_zsig(ZNotice_t *n, int *k)
601{
[7d4fbcd]602  /* return a pointer to the zsig if there is one */
603
[405d5e6]604  /* message length 0? No zsig */
[7d4fbcd]605  if (n->z_message_len==0) {
606    *k=0;
607    return("");
608  }
[405d5e6]609
[85d1795]610  /* If there's only one field, no zsig */
611  if (owl_zephyr_get_num_fields(n) == 1) {
612    *k=0;
[405d5e6]613    return("");
614  }
615
616  /* Everything else is field 1 */
[7d4fbcd]617  *k=strlen(n->z_message);
618  return(n->z_message);
619}
[09489b89]620#else
621char *owl_zephyr_get_zsig(void *n, int *k)
622{
623  return("");
624}
[be0a79f]625#endif
[7d4fbcd]626
[31e48a3]627int send_zephyr(char *opcode, char *zsig, char *class, char *instance, char *recipient, char *message)
628{
[be0a79f]629#ifdef HAVE_LIBZEPHYR
[7d4fbcd]630  int ret;
631  ZNotice_t notice;
632   
633  memset(&notice, 0, sizeof(notice));
634
[8262340]635  ZResetAuthentication();
[8ba37ec]636
637  if (!zsig) zsig="";
[8262340]638 
[7d4fbcd]639  notice.z_kind=ACKED;
640  notice.z_port=0;
641  notice.z_class=class;
642  notice.z_class_inst=instance;
[21882032]643  notice.z_sender=NULL;
[7d4fbcd]644  if (!strcmp(recipient, "*") || !strcmp(recipient, "@")) {
645    notice.z_recipient="";
[21882032]646    if (*owl_global_get_zsender(&g))
647        notice.z_sender=owl_global_get_zsender(&g);
[7d4fbcd]648  } else {
649    notice.z_recipient=recipient;
650  }
651  notice.z_default_format="Class $class, Instance $instance:\nTo: @bold($recipient) at $time $date\nFrom: @bold{$1 <$sender>}\n\n$2";
652  if (opcode) notice.z_opcode=opcode;
653
[56330ff]654  notice.z_message_len=strlen(zsig)+1+strlen(message);
[7d4fbcd]655  notice.z_message=owl_malloc(notice.z_message_len+10);
[56330ff]656  strcpy(notice.z_message, zsig);
657  memcpy(notice.z_message+strlen(zsig)+1, message, strlen(message));
[7d4fbcd]658
659  /* ret=ZSendNotice(&notice, ZAUTH); */
660  ret=ZSrvSendNotice(&notice, ZAUTH, send_zephyr_helper);
661 
662  /* free then check the return */
663  owl_free(notice.z_message);
664  ZFreeNotice(&notice);
665  if (ret!=ZERR_NONE) {
[ec6ff52]666    owl_function_error("Error sending zephyr");
[7d4fbcd]667    return(ret);
668  }
669  return(0);
[be0a79f]670#else
671  return(0);
672#endif
[7d4fbcd]673}
674
[be0a79f]675#ifdef HAVE_LIBZEPHYR
[31e48a3]676Code_t send_zephyr_helper(ZNotice_t *notice, char *buf, int len, int wait)
677{
[7d4fbcd]678  return(ZSendPacket(buf, len, 0));
679}
[be0a79f]680#endif
[7d4fbcd]681
[31e48a3]682void send_ping(char *to)
683{
[be0a79f]684#ifdef HAVE_LIBZEPHYR
[7d4fbcd]685  send_zephyr("PING", "", "MESSAGE", "PERSONAL", to, "");
[be0a79f]686#endif
[7d4fbcd]687}
688
[be0a79f]689#ifdef HAVE_LIBZEPHYR
[31e48a3]690void owl_zephyr_handle_ack(ZNotice_t *retnotice)
691{
[7d4fbcd]692  char *tmp;
693 
694  /* if it's an HMACK ignore it */
695  if (retnotice->z_kind == HMACK) return;
[aecf3e6]696
[7d4fbcd]697  if (retnotice->z_kind == SERVNAK) {
[ec6ff52]698    owl_function_error("Authorization failure sending zephyr");
[7d4fbcd]699  } else if ((retnotice->z_kind != SERVACK) || !retnotice->z_message_len) {
[ec6ff52]700    owl_function_error("Detected server failure while receiving acknowledgement");
[7d4fbcd]701  } else if (!strcmp(retnotice->z_message, ZSRVACK_SENT)) {
702    if (!strcasecmp(retnotice->z_opcode, "ping")) {
703      return;
704    } else if (!strcasecmp(retnotice->z_class, "message") &&
705               !strcasecmp(retnotice->z_class_inst, "personal")) {
[4b464a4]706      tmp=short_zuser(retnotice->z_recipient);
[b4db911]707      owl_function_makemsg("Message sent to %s.", tmp);
[7d4fbcd]708      free(tmp);
709    } else {
[b4db911]710      owl_function_makemsg("Message sent to -c %s -i %s\n", retnotice->z_class, retnotice->z_class_inst);
[7d4fbcd]711    }
712  } else if (!strcmp(retnotice->z_message, ZSRVACK_NOTSENT)) {
[1151f0b]713    #define BUFFLEN 1024
[44f32fb]714    if (retnotice->z_recipient == NULL
[60c2e1e]715        || *retnotice->z_recipient == 0
[44f32fb]716        || *retnotice->z_recipient == '@') {
[1151f0b]717      char buff[BUFFLEN];
[44f32fb]718      owl_function_error("No one subscribed to class %s", retnotice->z_class);
[1151f0b]719      snprintf(buff, BUFFLEN, "Could not send message to class %s: no one subscribed.\n", retnotice->z_class);
[9119a47]720      owl_function_adminmsg("", buff);
[7d4fbcd]721    } else {
[1151f0b]722      char buff[BUFFLEN];
[4b464a4]723      tmp = short_zuser(retnotice->z_recipient);
[44f32fb]724      owl_function_error("%s: Not logged in or subscribing.", tmp);
725      if(strcmp(retnotice->z_class, "message")) {
[1151f0b]726        snprintf(buff, BUFFLEN,
[10e3963]727                 "Could not send message to %s: "
728                 "not logged in or subscribing to class %s, instance %s.\n", 
729                 tmp,
[1151f0b]730                 retnotice->z_class,
731                 retnotice->z_class_inst);
[44f32fb]732      } else {
[1151f0b]733        snprintf(buff, BUFFLEN,
[10e3963]734                 "Could not send message to %s: "
735                 "not logged in or subscribing to messages.\n",
736                 tmp);
[44f32fb]737      }
[9119a47]738      owl_function_adminmsg("", buff);
[180cd15]739      owl_log_outgoing_zephyr_error(tmp, buff);
[1c6c4d3]740      owl_free(tmp);
[7d4fbcd]741    }
742  } else {
[ec6ff52]743    owl_function_error("Internal error on ack (%s)", retnotice->z_message);
[7d4fbcd]744  }
745}
[09489b89]746#else
747void owl_zephyr_handle_ack(void *retnotice)
748{
749}
[be0a79f]750#endif
[7d4fbcd]751
[be0a79f]752#ifdef HAVE_LIBZEPHYR
[31e48a3]753int owl_zephyr_notice_is_ack(ZNotice_t *n)
754{
[7d4fbcd]755  if (n->z_kind == SERVNAK || n->z_kind == SERVACK || n->z_kind == HMACK) {
756    if (!strcasecmp(n->z_class, LOGIN_CLASS)) return(0);
757    return(1);
758  }
759  return(0);
760}
[09489b89]761#else
762int owl_zephyr_notice_is_ack(void *n)
763{
764  return(0);
765}
[be0a79f]766#endif
[7d4fbcd]767 
[31e48a3]768void owl_zephyr_zaway(owl_message *m)
769{
[be0a79f]770#ifdef HAVE_LIBZEPHYR
[7c8060d0]771  char *tmpbuff, *myuser, *to;
[15b34fd]772  owl_message *mout;
[7d4fbcd]773 
[aa2f6364]774  /* bail if it doesn't look like a message we should reply to.  Some
[2de4f20]775   * of this defined by the way zaway(1) works
776   */
[7d4fbcd]777  if (strcasecmp(owl_message_get_class(m), "message")) return;
778  if (strcasecmp(owl_message_get_recipient(m), ZGetSender())) return;
779  if (!strcasecmp(owl_message_get_sender(m), "")) return;
780  if (!strcasecmp(owl_message_get_opcode(m), "ping")) return;
781  if (!strcasecmp(owl_message_get_opcode(m), "auto")) return;
[d023c25]782  if (!strcasecmp(owl_message_get_zsig(m), "Automated reply:")) return;
[7d4fbcd]783  if (!strcasecmp(owl_message_get_sender(m), ZGetSender())) return;
[9854278]784  if (owl_message_get_attribute_value(m, "isauto")) return;
[7d4fbcd]785
[7c8060d0]786  if (owl_global_is_smartstrip(&g)) {
[e3d9c77]787    to=owl_zephyr_smartstripped_user(owl_message_get_sender(m));
[7c8060d0]788  } else {
789    to=owl_strdup(owl_message_get_sender(m));
790  }
791
[7d4fbcd]792  send_zephyr("",
793              "Automated reply:",
794              owl_message_get_class(m),
795              owl_message_get_instance(m),
[7c8060d0]796              to,
[7d4fbcd]797              owl_global_get_zaway_msg(&g));
798
[7c8060d0]799  myuser=short_zuser(to);
[aa2f6364]800  if (!strcasecmp(owl_message_get_instance(m), "personal")) {
801    tmpbuff = owl_sprintf("zwrite %s", myuser);
802  } else {
803    tmpbuff = owl_sprintf("zwrite -i %s %s", owl_message_get_instance(m), myuser);
804  }
805  owl_free(myuser);
[7c8060d0]806  owl_free(to);
[aa2f6364]807
[7d4fbcd]808  /* display the message as an admin message in the receive window */
[15b34fd]809  mout=owl_function_make_outgoing_zephyr(owl_global_get_zaway_msg(&g), tmpbuff, "Automated reply:");
[13a3c1db]810  owl_global_messagequeue_addmsg(&g, mout);
[7d4fbcd]811  owl_free(tmpbuff);
[be0a79f]812#endif
[7d4fbcd]813}
814
[be0a79f]815#ifdef HAVE_LIBZEPHYR
[31e48a3]816void owl_zephyr_hackaway_cr(ZNotice_t *n)
817{
[7d4fbcd]818  /* replace \r's with ' '.  Gross-ish */
819  int i;
820
821  for (i=0; i<n->z_message_len; i++) {
822    if (n->z_message[i]=='\r') {
823      n->z_message[i]=' ';
824    }
825  }
826}
[be0a79f]827#endif
[7d4fbcd]828
[31e48a3]829void owl_zephyr_zlocate(char *user, char *out, int auth)
830{
[be0a79f]831#ifdef HAVE_LIBZEPHYR
[7d4fbcd]832  int ret, numlocs;
833  int one = 1;
834  ZLocations_t locations;
835  char *myuser;
836 
837  strcpy(out, "");
[8262340]838  ZResetAuthentication();
[7d4fbcd]839  ret=ZLocateUser(user,&numlocs,auth?ZAUTH:ZNOAUTH);
840  if (ret != ZERR_NONE) {
[667a1b6]841    sprintf(out, "Error locating user %s\n", user);
842    return;
[7d4fbcd]843  }
844
845  if (numlocs==0) {
[2527615]846    myuser=short_zuser(user);
[451db9e]847    sprintf(out, "%s: Hidden or not logged in\n", myuser);
[2527615]848    owl_free(myuser);
[7d4fbcd]849    return;
850  }
851   
852  for (;numlocs;numlocs--) {
853    ZGetLocations(&locations,&one);
[4b464a4]854    myuser=short_zuser(user);
[b9cb41b]855    sprintf(out + strlen(out), "%s: %s\t%s\t%s\n", myuser,
[667a1b6]856            locations.host ? locations.host : "?",
857            locations.tty ? locations.tty : "?",
858            locations.time ? locations.time : "?");
[7d4fbcd]859    owl_free(myuser);
860  }
[be0a79f]861#endif
[7d4fbcd]862}
[bde7714]863
[31e48a3]864void owl_zephyr_addsub(char *filename, char *class, char *inst, char *recip)
865{
[be0a79f]866#ifdef HAVE_LIBZEPHYR
[bde7714]867  char *line, subsfile[LINE], buff[LINE];
868  FILE *file;
869
870  line=owl_zephyr_makesubline(class, inst, recip);
871
872  if (filename==NULL) {
873    sprintf(subsfile, "%s/%s", owl_global_get_homedir(&g), ".zephyr.subs");
874  } else {
875    strcpy(subsfile, filename);
876  }
877
[74037d9]878  /* if the file already exists, check to see if the sub is already there */
[bde7714]879  file=fopen(subsfile, "r");
[74037d9]880  if (file) {
881    while (fgets(buff, LINE, file)!=NULL) {
882      if (!strcasecmp(buff, line)) {
883        owl_function_error("Subscription already present in %s", subsfile);
884        owl_free(line);
[e78397d]885        fclose(file);
[74037d9]886        return;
887      }
[bde7714]888    }
[99dabee]889    fclose(file);
[bde7714]890  }
891
892  /* if we get here then we didn't find it */
893  file=fopen(subsfile, "a");
894  if (!file) {
[ec6ff52]895    owl_function_error("Error opening file %s for writing", subsfile);
[bde7714]896    owl_free(line);
897    return;
898  }
899  fputs(line, file);
900  fclose(file);
901  owl_function_makemsg("Subscription added");
902 
903  owl_free(line);
[be0a79f]904#endif
[bde7714]905}
906
[31e48a3]907void owl_zephyr_delsub(char *filename, char *class, char *inst, char *recip)
908{
[be0a79f]909#ifdef HAVE_LIBZEPHYR
[b2a91b6]910  char *line, *subsfile;
[bde7714]911 
912  line=owl_zephyr_makesubline(class, inst, recip);
[b2a91b6]913  line[strlen(line)-1]='\0';
[bde7714]914
[b2a91b6]915  if (!filename) {
916    subsfile=owl_sprintf("%s/.zephyr.subs", owl_global_get_homedir(&g));
[bde7714]917  } else {
[b2a91b6]918    subsfile=owl_strdup(filename);
[bde7714]919  }
[b2a91b6]920 
921  owl_util_file_deleteline(subsfile, line, 1);
922  owl_free(subsfile);
[bde7714]923  owl_free(line);
924  owl_function_makemsg("Subscription removed");
[be0a79f]925#endif
[bde7714]926}
927
[b2a91b6]928/* caller must free the return */
[31e48a3]929char *owl_zephyr_makesubline(char *class, char *inst, char *recip)
930{
[bde7714]931  char *out;
932
933  out=owl_malloc(strlen(class)+strlen(inst)+strlen(recip)+30);
934  sprintf(out, "%s,%s,%s\n", class, inst, !strcmp(recip, "") ? "*" : recip);
935  return(out);
936}
[31e48a3]937
938
939void owl_zephyr_zlog_in(void)
940{
[be0a79f]941#ifdef HAVE_LIBZEPHYR
[31e48a3]942  char *exposure, *eset;
943  int ret;
944
945  ZResetAuthentication();
946   
947  eset=EXPOSE_REALMVIS;
948  exposure=ZGetVariable("exposure");
949  if (exposure==NULL) {
950    eset=EXPOSE_REALMVIS;
951  } else if (!strcasecmp(exposure,EXPOSE_NONE)) {
952    eset = EXPOSE_NONE;
953  } else if (!strcasecmp(exposure,EXPOSE_OPSTAFF)) {
954    eset = EXPOSE_OPSTAFF;
955  } else if (!strcasecmp(exposure,EXPOSE_REALMVIS)) {
956    eset = EXPOSE_REALMVIS;
957  } else if (!strcasecmp(exposure,EXPOSE_REALMANN)) {
958    eset = EXPOSE_REALMANN;
959  } else if (!strcasecmp(exposure,EXPOSE_NETVIS)) {
960    eset = EXPOSE_NETVIS;
961  } else if (!strcasecmp(exposure,EXPOSE_NETANN)) {
962    eset = EXPOSE_NETANN;
963  }
964   
965  ret=ZSetLocation(eset);
966  if (ret != ZERR_NONE) {
967    /*
968      char buff[LINE];
969      sprintf(buff, "Error setting location: %s", error_message(ret));
970      owl_function_makemsg(buff);
971    */
972  }
[be0a79f]973#endif
[31e48a3]974}
975
976void owl_zephyr_zlog_out(void)
977{
[be0a79f]978#ifdef HAVE_LIBZEPHYR
[31e48a3]979  int ret;
980
981  ZResetAuthentication();
982  ret=ZUnsetLocation();
983  if (ret != ZERR_NONE) {
984    /*
985      char buff[LINE];
986      sprintf(buff, "Error unsetting location: %s", error_message(ret));
987      owl_function_makemsg(buff);
988    */
989  }
[be0a79f]990#endif
[31e48a3]991}
992
[65ad073]993void owl_zephyr_addbuddy(char *name)
994{
995  char *filename;
996  FILE *file;
997 
998  filename=owl_sprintf("%s/.anyone", owl_global_get_homedir(&g));
999  file=fopen(filename, "a");
1000  owl_free(filename);
1001  if (!file) {
[ec6ff52]1002    owl_function_error("Error opening zephyr buddy file for append");
[65ad073]1003    return;
1004  }
1005  fprintf(file, "%s\n", name);
1006  fclose(file);
1007}
1008
1009void owl_zephyr_delbuddy(char *name)
1010{
1011  char *filename;
1012
1013  filename=owl_sprintf("%s/.anyone", owl_global_get_homedir(&g));
1014  owl_util_file_deleteline(filename, name, 0);
1015  owl_free(filename);
1016}
[9381782]1017
1018/* return auth string */
[09489b89]1019#ifdef HAVE_LIBZEPHYR
[9381782]1020char *owl_zephyr_get_authstr(ZNotice_t *n)
1021{
1022
1023  if (!n) return("UNKNOWN");
1024
1025  if (n->z_auth == ZAUTH_FAILED) {
1026    return ("FAILED");
1027  } else if (n->z_auth == ZAUTH_NO) {
1028    return ("NO");
1029  } else if (n->z_auth == ZAUTH_YES) {
1030    return ("YES");
1031  } else {
1032    return ("UNKNOWN");
1033  }           
1034}
[09489b89]1035#else
1036char *owl_zephyr_get_authstr(void *n)
1037{
1038  return("");
1039}
1040#endif
[9381782]1041
[2de4f20]1042/* Returns a buffer of subscriptions or an error message.  Caller must
1043 * free the return.
[09489b89]1044 */
1045char *owl_zephyr_getsubs()
1046{
1047#ifdef HAVE_LIBZEPHYR
1048  int ret, num, i, one;
[ddacb9c]1049  int buffsize;
[09489b89]1050  ZSubscription_t sub;
[ddacb9c]1051  char *out;
[09489b89]1052  one=1;
1053
1054  ret=ZRetrieveSubscriptions(0, &num);
1055  if (ret==ZERR_TOOMANYSUBS) {
[c8735aa]1056    return(owl_strdup("Zephyr: too many subscriptions\n"));
[ddacb9c]1057  } else if (ret || (num <= 0)) {
[c8735aa]1058    return(owl_strdup("Zephyr: error retriving subscriptions\n"));
[09489b89]1059  }
1060
[ddacb9c]1061  buffsize = (num + 1) * 50;
1062  out=owl_malloc(buffsize);
[09489b89]1063  strcpy(out, "");
1064  for (i=0; i<num; i++) {
1065    if ((ret = ZGetSubscriptions(&sub, &one)) != ZERR_NONE) {
1066      owl_free(out);
1067      ZFlushSubscriptions();
1068      out=owl_strdup("Error while getting subscriptions\n");
1069      return(out);
1070    } else {
[ddacb9c]1071      int tmpbufflen;
1072      char *tmpbuff;
1073      tmpbuff = owl_sprintf("<%s,%s,%s>\n%s", sub.zsub_class, sub.zsub_classinst, sub.zsub_recipient, out);
1074      tmpbufflen = strlen(tmpbuff) + 1;
1075      if (tmpbufflen > buffsize) {
1076        char *out2;
1077        buffsize = tmpbufflen * 2;
1078        out2 = owl_realloc(out, buffsize);
1079        if (out2 == NULL) {
1080          owl_free(out);
1081          owl_free(tmpbuff);
1082          ZFlushSubscriptions();
1083          out=owl_strdup("Realloc error while getting subscriptions\n");
1084          return(out);   
1085        }
1086        out = out2;
1087      }
[09489b89]1088      strcpy(out, tmpbuff);
[ddacb9c]1089      owl_free(tmpbuff);
[09489b89]1090    }
1091  }
1092
1093  ZFlushSubscriptions();
1094  return(out);
1095#else
[12c35df]1096  return(owl_strdup("Zephyr not available"));
[09489b89]1097#endif
1098}
1099
1100char *owl_zephyr_get_variable(char *var)
1101{
1102#ifdef HAVE_LIBZEPHYR
1103  return(ZGetVariable(var));
1104#else
1105  return("");
1106#endif
1107}
1108
1109void owl_zephyr_set_locationinfo(char *host, char *val)
1110{
1111#ifdef HAVE_LIBZEPHYR
1112  ZInitLocationInfo(host, val);
1113#endif
1114}
1115 
[e3d9c77]1116/* Strip a local realm fron the zephyr user name.
1117 * The caller must free the return
1118 */
1119char *short_zuser(char *in)
1120{
1121  char *out, *ptr;
1122
1123  out=owl_strdup(in);
1124  ptr=strchr(out, '@');
1125  if (ptr) {
1126    if (!strcasecmp(ptr+1, owl_zephyr_get_realm())) {
1127      *ptr='\0';
1128    }
1129  }
1130  return(out);
1131}
1132
1133/* Append a local realm to the zephyr user name if necessary.
1134 * The caller must free the return.
1135 */
1136char *long_zuser(char *in)
1137{
[1971b59]1138  if (strchr(in, '@')) {
1139    return(owl_strdup(in));
[e3d9c77]1140  }
[1971b59]1141  return(owl_sprintf("%s@%s", in, owl_zephyr_get_realm()));
[e3d9c77]1142}
1143
1144/* strip out the instance from a zsender's principal.  Preserves the
1145 * realm if present.  daemon.webzephyr is a special case.  The
1146 * caller must free the return
1147 */
1148char *owl_zephyr_smartstripped_user(char *in)
1149{
1150  char *ptr, *realm, *out;
1151
1152  out=owl_strdup(in);
1153
1154  /* bail immeaditly if we don't have to do any work */
1155  ptr=strchr(in, '.');
1156  if (!strchr(in, '/') && !ptr) {
1157    /* no '/' and no '.' */
1158    return(out);
1159  }
1160  if (ptr && strchr(in, '@') && (ptr > strchr(in, '@'))) {
1161    /* There's a '.' but it's in the realm */
1162    return(out);
1163  }
1164  if (!strncasecmp(in, OWL_WEBZEPHYR_PRINCIPAL, strlen(OWL_WEBZEPHYR_PRINCIPAL))) {
1165    return(out);
1166  }
1167
1168  /* remove the realm from ptr, but hold on to it */
1169  realm=strchr(out, '@');
1170  if (realm) realm[0]='\0';
1171
1172  /* strip */
1173  ptr=strchr(out, '.');
1174  if (!ptr) ptr=strchr(out, '/');
1175  ptr[0]='\0';
1176
1177  /* reattach the realm if we had one */
1178  if (realm) {
1179    strcat(out, "@");
1180    strcat(out, realm+1);
1181  }
1182
1183  return(out);
1184}
[5a95b69]1185
1186/* read the list of users in 'filename' as a .anyone file, and put the
1187 * names of the zephyr users in the list 'in'.  If 'filename' is NULL,
1188 * use the default .anyone file in the users home directory.  Returns
1189 * -1 on failure, 0 on success.
1190 */
1191int owl_zephyr_get_anyone_list(owl_list *in, char *filename)
1192{
1193#ifdef HAVE_LIBZEPHYR
1194  char *ourfile, *tmp, buff[LINE];
1195  FILE *f;
1196
1197  if (filename==NULL) {
1198    tmp=owl_global_get_homedir(&g);
1199    ourfile=owl_sprintf("%s/.anyone", owl_global_get_homedir(&g));
1200  } else {
1201    ourfile=owl_strdup(filename);
1202  }
1203 
1204  f=fopen(ourfile, "r");
1205  if (!f) {
1206    owl_function_error("Error opening file %s: %s", ourfile, strerror(errno) ? strerror(errno) : "");
1207    owl_free(ourfile);
1208    return(-1);
1209  }
1210
1211  while (fgets(buff, LINE, f)!=NULL) {
1212    /* ignore comments, blank lines etc. */
1213    if (buff[0]=='#') continue;
1214    if (buff[0]=='\n') continue;
1215    if (buff[0]=='\0') continue;
1216   
1217    /* strip the \n */
1218    buff[strlen(buff)-1]='\0';
1219   
1220    /* ingore from # on */
1221    tmp=strchr(buff, '#');
1222    if (tmp) tmp[0]='\0';
1223   
1224    /* ingore from SPC */
1225    tmp=strchr(buff, ' ');
1226    if (tmp) tmp[0]='\0';
1227   
1228    /* stick on the local realm. */
1229    if (!strchr(buff, '@')) {
1230      strcat(buff, "@");
1231      strcat(buff, ZGetRealm());
1232    }
1233    owl_list_append_element(in, owl_strdup(buff));
1234  }
1235  fclose(f);
1236  owl_free(ourfile);
1237  return(0);
1238#else
1239  return(-1);
1240#endif
1241}
[13a3c1db]1242
1243#ifdef HAVE_LIBZEPHYR
[f36cd97]1244void owl_zephyr_process_events(owl_dispatch *d) {
[13a3c1db]1245  int zpendcount=0;
1246  ZNotice_t notice;
1247  struct sockaddr_in from;
1248  owl_message *m=NULL;
1249
1250  while(owl_zephyr_zpending() && zpendcount < 20) {
1251    if (owl_zephyr_zpending()) {
1252      ZReceiveNotice(&notice, &from);
1253      zpendcount++;
1254
1255      /* is this an ack from a zephyr we sent? */
1256      if (owl_zephyr_notice_is_ack(&notice)) {
1257        owl_zephyr_handle_ack(&notice);
1258        continue;
1259      }
1260
1261      /* if it's a ping and we're not viewing pings then skip it */
1262      if (!owl_global_is_rxping(&g) && !strcasecmp(notice.z_opcode, "ping")) {
1263        continue;
1264      }
1265
1266      /* create the new message */
1267      m=owl_malloc(sizeof(owl_message));
1268      owl_message_create_from_znotice(m, &notice);
1269
1270      owl_global_messagequeue_addmsg(&g, m);
1271    }
1272  }
1273}
1274
1275#else
[f36cd97]1276void owl_zephyr_process_events(owl_dispatch *d) {
[13a3c1db]1277 
1278}
1279#endif
Note: See TracBrowser for help on using the repository browser.