source: zephyr.c @ c73a22d

release-1.8release-1.9
Last change on this file since c73a22d was c73a22d, checked in by Karl Ramm <kcr@1ts.org>, 11 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
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
[fea7992]9#ifdef HAVE_LIBZEPHYR
[a5e7ed6]10static GList *deferred_subs = NULL;
[79d7d98]11
[a5e7ed6]12typedef struct _owl_sub_list {                            /* noproto */
13  ZSubscription_t *subs;
14  int nsubs;
15} owl_sub_list;
16
[c79a047]17Code_t ZResetAuthentication(void);
[09489b89]18#endif
[8262340]19
[02f55dc]20#define HM_SVC_FALLBACK         htons((unsigned short) 2104)
21
[6ea3890]22static char *owl_zephyr_dotfile(const char *name, const char *input)
23{
24  if (input != NULL)
[d4927a7]25    return g_strdup(input);
[6ea3890]26  else
[3472845]27    return g_strdup_printf("%s/%s", owl_global_get_homedir(&g), name);
[6ea3890]28}
29
[52a0f14]30#ifdef HAVE_LIBZEPHYR
[c79a047]31void owl_zephyr_initialize(void)
[52a0f14]32{
[488913a]33  Code_t ret;
[02f55dc]34  struct servent *sp;
35  struct sockaddr_in sin;
36  ZNotice_t req;
[52a0f14]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  }
[02f55dc]49
[4d86e06]50  (void) memset(&sin, 0, sizeof(struct sockaddr_in));
[02f55dc]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
[4d86e06]59  (void) memset(&req, 0, sizeof(req));
[02f55dc]60  req.z_kind = STAT;
61  req.z_port = 0;
[712caac]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("");
[02f55dc]68  req.z_message_len = 0;
[52a0f14]69
[488913a]70  if ((ret = ZSetDestAddr(&sin)) != ZERR_NONE) {
71    owl_function_error("Initializing Zephyr: %s", error_message(ret));
[52a0f14]72    return;
73  }
74
[488913a]75  if ((ret = ZSendNotice(&req, ZNOAUTH)) != ZERR_NONE) {
76    owl_function_error("Initializing Zephyr: %s", error_message(ret));
[52a0f14]77    return;
78  }
79
[18fdd5f9]80  owl_select_add_io_dispatch(ZGetFD(), OWL_IO_READ|OWL_IO_EXCEPT, &owl_zephyr_finish_initialization, NULL, NULL);
[02f55dc]81}
82
[18fdd5f9]83void owl_zephyr_finish_initialization(const owl_io_dispatch *d, void *data) {
[52a0f14]84  Code_t code;
[df569c5]85  char *perl;
[52a0f14]86
[18fdd5f9]87  owl_select_remove_io_dispatch(d);
[52a0f14]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
[18fdd5f9]101  owl_select_add_io_dispatch(ZGetFD(), OWL_IO_READ|OWL_IO_EXCEPT, &owl_zephyr_process_events, NULL, NULL);
102
[52a0f14]103  owl_global_set_havezephyr(&g);
104
105  if(g.load_initial_subs) {
106    owl_zephyr_load_initial_subs();
107  }
[a5e7ed6]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);
[ddbbcffa]113    g_free(subs);
[a5e7ed6]114  }
[619d864]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  }
[27964fe]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  }
[df569c5]126
[12e291a]127  perl = owl_perlconfig_execute("BarnOwl::Zephyr::_zephyr_startup()");
[ddbbcffa]128  g_free(perl);
[12e291a]129
130  owl_select_add_pre_select_action(owl_zephyr_pre_select_action, NULL, NULL);
[52a0f14]131}
132
[c79a047]133void owl_zephyr_load_initial_subs(void) {
[7451af9]134  int ret_sd, ret_bd, ret_u;
[52a0f14]135
136  owl_function_debugmsg("startup: loading initial zephyr subs");
137
138  /* load default subscriptions */
[7451af9]139  ret_sd = owl_zephyr_loaddefaultsubs();
140
141  /* load Barnowl default subscriptions */
142  ret_bd = owl_zephyr_loadbarnowldefaultsubs();
[52a0f14]143
144  /* load subscriptions from subs file */
[7451af9]145  ret_u = owl_zephyr_loadsubs(NULL, 0);
[52a0f14]146
[7451af9]147  if (ret_sd || ret_bd || ret_u) {
[52a0f14]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
[c79a047]158void owl_zephyr_initialize(void)
[52a0f14]159{
160}
[02f55dc]161#endif
162
[52a0f14]163
[c79a047]164int owl_zephyr_shutdown(void)
[09489b89]165{
166#ifdef HAVE_LIBZEPHYR
[bfbf590]167  if(owl_global_is_havezephyr(&g)) {
168    unsuball();
169    ZClosePort();
170  }
[09489b89]171#endif
[32ad44d]172  return 0;
[be0a79f]173}
174
[c79a047]175int owl_zephyr_zpending(void)
[be0a79f]176{
177#ifdef HAVE_LIBZEPHYR
[8ab1f28]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  }
[be0a79f]187#endif
[32ad44d]188  return 0;
[be0a79f]189}
190
[c79a047]191const char *owl_zephyr_get_realm(void)
[09489b89]192{
193#ifdef HAVE_LIBZEPHYR
[32ad44d]194  if (owl_global_is_havezephyr(&g))
195    return(ZGetRealm());
[09489b89]196#endif
[32ad44d]197  return "";
[09489b89]198}
199
[c79a047]200const char *owl_zephyr_get_sender(void)
[09489b89]201{
202#ifdef HAVE_LIBZEPHYR
[32ad44d]203  if (owl_global_is_havezephyr(&g))
204    return(ZGetSender());
[09489b89]205#endif
[32ad44d]206  return "";
[09489b89]207}
208
[f6050ee]209#ifdef HAVE_LIBZEPHYR
[93e883d]210int owl_zephyr_loadsubs_helper(ZSubscription_t subs[], int count)
211{
[18105584]212  int ret = 0;
[c73a22d]213  Code_t code;
214
[a5e7ed6]215  if (owl_global_is_havezephyr(&g)) {
216    int i;
217    /* sub without defaults */
[c73a22d]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));
[a5e7ed6]222      ret=-2;
223    }
[93e883d]224
[a5e7ed6]225    /* free stuff */
226    for (i=0; i<count; i++) {
[ddbbcffa]227      g_free(subs[i].zsub_class);
228      g_free(subs[i].zsub_classinst);
229      g_free(subs[i].zsub_recipient);
[a5e7ed6]230    }
[bb2c60d]231
[ddbbcffa]232    g_free(subs);
[a5e7ed6]233  } else {
[96828e4]234    owl_sub_list *s = g_new(owl_sub_list, 1);
[a5e7ed6]235    s->subs = subs;
236    s->nsubs = count;
237    deferred_subs = g_list_append(deferred_subs, s);
238  }
[d21efbc]239
[93e883d]240  return ret;
241}
[f6050ee]242#endif
[93e883d]243
[7451af9]244/* Load zephyr subscriptions from 'filename'.  If 'filename' is NULL,
[95474d7]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.
[2de4f20]251 */
[e19eb97]252int owl_zephyr_loadsubs(const char *filename, int error_on_nofile)
[31e48a3]253{
[be0a79f]254#ifdef HAVE_LIBZEPHYR
[7d4fbcd]255  FILE *file;
256  char *tmp, *start;
[b7ee89b]257  char *buffer = NULL;
258  char *subsfile;
[bb2c60d]259  ZSubscription_t *subs;
260  int subSize = 1024;
[b7ee89b]261  int count;
[4357be8]262  struct stat statbuff;
[7d4fbcd]263
[96828e4]264  subs = g_new(ZSubscription_t, subSize);
[6ea3890]265  subsfile = owl_zephyr_dotfile(".zephyr.subs", filename);
[b7ee89b]266
267  if (stat(subsfile, &statbuff) != 0) {
[ddbbcffa]268    g_free(subsfile);
[b7ee89b]269    if (error_on_nofile == 1)
270      return -1;
271    return 0;
[95474d7]272  }
[4357be8]273
[8262340]274  ZResetAuthentication();
[b7ee89b]275  count = 0;
276  file = fopen(subsfile, "r");
[ddbbcffa]277  g_free(subsfile);
[b7ee89b]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
[bb2c60d]289    if (count >= subSize) {
[d21efbc]290      subSize *= 2;
[35b6eb9]291      subs = g_renew(ZSubscription_t, subs, subSize);
[93e883d]292    }
[95474d7]293   
294    /* add it to the list of subs */
[b7ee89b]295    if ((tmp = strtok(start, ",\n\r")) == NULL)
296      continue;
[d4927a7]297    subs[count].zsub_class = g_strdup(tmp);
[b7ee89b]298    if ((tmp=strtok(NULL, ",\n\r")) == NULL)
299      continue;
[d4927a7]300    subs[count].zsub_classinst = g_strdup(tmp);
[b7ee89b]301    if ((tmp = strtok(NULL, " \t\n\r")) == NULL)
302      continue;
[d4927a7]303    subs[count].zsub_recipient = g_strdup(tmp);
[b7ee89b]304
[bb2c60d]305    /* if it started with '-' then add it to the global punt list, and
306     * remove it from the list of subs. */
[b7ee89b]307    if (buffer[0] == '-') {
[95474d7]308      owl_function_zpunt(subs[count].zsub_class, subs[count].zsub_classinst, subs[count].zsub_recipient, 0);
[ddbbcffa]309      g_free(subs[count].zsub_class);
310      g_free(subs[count].zsub_classinst);
311      g_free(subs[count].zsub_recipient);
[b7ee89b]312    } else {
[bb2c60d]313      count++;
[95474d7]314    }
[7d4fbcd]315  }
[95474d7]316  fclose(file);
[b7ee89b]317  if (buffer)
[ddbbcffa]318    g_free(buffer);
[7d4fbcd]319
[b7ee89b]320  return owl_zephyr_loadsubs_helper(subs, count);
[7451af9]321#else
[b7ee89b]322  return 0;
[7451af9]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 */
[c79a047]331int owl_zephyr_loadbarnowldefaultsubs(void)
[7451af9]332{
333#ifdef HAVE_LIBZEPHYR
334  ZSubscription_t *subs;
335  int subSize = 10; /* Max Barnowl default subs we allow */
336  int count, ret;
337
[96828e4]338  subs = g_new(ZSubscription_t, subSize);
[7451af9]339  ZResetAuthentication();
340  count=0;
341
[d4927a7]342  subs[count].zsub_class=g_strdup("message");
343  subs[count].zsub_classinst=g_strdup("*");
344  subs[count].zsub_recipient=g_strdup("%me%");
[7451af9]345  count++;
346
347  ret = owl_zephyr_loadsubs_helper(subs, count);
[7d4fbcd]348  return(ret);
[be0a79f]349#else
350  return(0);
351#endif
[7d4fbcd]352}
353
[c79a047]354int owl_zephyr_loaddefaultsubs(void)
[4357be8]355{
[40d834a]356#ifdef HAVE_LIBZEPHYR
[c73a22d]357  Code_t ret;
358
[2c5ee3e]359  if (owl_global_is_havezephyr(&g)) {
360    ZSubscription_t subs[10];
[c73a22d]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));
[2c5ee3e]366      return(-1);
367    }
[4357be8]368  }
369  return(0);
[40d834a]370#else
371  return(0);
372#endif
[4357be8]373}
374
[e19eb97]375int owl_zephyr_loadloginsubs(const char *filename)
[31e48a3]376{
[be0a79f]377#ifdef HAVE_LIBZEPHYR
[7d4fbcd]378  FILE *file;
[d21efbc]379  ZSubscription_t *subs;
380  int numSubs = 100;
[b7ee89b]381  char *subsfile;
382  char *buffer = NULL;
383  int count;
[4357be8]384  struct stat statbuff;
[7d4fbcd]385
[96828e4]386  subs = g_new(ZSubscription_t, numSubs);
[6ea3890]387  subsfile = owl_zephyr_dotfile(".anyone", filename);
[4357be8]388
[922f589]389  if (stat(subsfile, &statbuff) == -1) {
[ddbbcffa]390    g_free(subs);
391    g_free(subsfile);
[b7ee89b]392    return 0;
[922f589]393  }
[7d4fbcd]394
[8262340]395  ZResetAuthentication();
[b7ee89b]396  count = 0;
397  file = fopen(subsfile, "r");
[ddbbcffa]398  g_free(subsfile);
[7d4fbcd]399  if (file) {
[b7ee89b]400    while (owl_getline_chomp(&buffer, file)) {
401      if (buffer[0] == '\0' || buffer[0] == '#')
402        continue;
403
[d21efbc]404      if (count == numSubs) {
405        numSubs *= 2;
[35b6eb9]406        subs = g_renew(ZSubscription_t, subs, numSubs);
[d21efbc]407      }
[7d4fbcd]408
[d4927a7]409      subs[count].zsub_class = g_strdup("login");
410      subs[count].zsub_recipient = g_strdup("*");
[b7ee89b]411      subs[count].zsub_classinst = long_zuser(buffer);
[7d4fbcd]412
413      count++;
414    }
415    fclose(file);
416  } else {
[b7ee89b]417    return 0;
[7d4fbcd]418  }
[b7ee89b]419  if (buffer)
[ddbbcffa]420    g_free(buffer);
[7d4fbcd]421
[b7ee89b]422  return owl_zephyr_loadsubs_helper(subs, count);
[be0a79f]423#else
[b7ee89b]424  return 0;
[be0a79f]425#endif
[7d4fbcd]426}
427
[c79a047]428void unsuball(void)
[31e48a3]429{
[be0a79f]430#if HAVE_LIBZEPHYR
[7d4fbcd]431  int ret;
[8262340]432
433  ZResetAuthentication();
[7d4fbcd]434  ret=ZCancelSubscriptions(0);
435  if (ret != ZERR_NONE) {
436    com_err("owl",ret,"while unsubscribing");
437  }
[be0a79f]438#endif
[7d4fbcd]439}
440
[e19eb97]441int owl_zephyr_sub(const char *class, const char *inst, const char *recip)
[31e48a3]442{
[be0a79f]443#ifdef HAVE_LIBZEPHYR
[7d4fbcd]444  ZSubscription_t subs[5];
[c73a22d]445  Code_t ret;
[7d4fbcd]446
[712caac]447  subs[0].zsub_class=zstr(class);
448  subs[0].zsub_classinst=zstr(inst);
449  subs[0].zsub_recipient=zstr(recip);
[7d4fbcd]450
[8262340]451  ZResetAuthentication();
[c73a22d]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));
[97cd00be]457    return(-2);
[7d4fbcd]458  }
459  return(0);
[be0a79f]460#else
461  return(0);
462#endif
[7d4fbcd]463}
464
465
[e19eb97]466int owl_zephyr_unsub(const char *class, const char *inst, const char *recip)
[31e48a3]467{
[be0a79f]468#ifdef HAVE_LIBZEPHYR
[7d4fbcd]469  ZSubscription_t subs[5];
[c73a22d]470  Code_t ret;
[7d4fbcd]471
[712caac]472  subs[0].zsub_class=zstr(class);
473  subs[0].zsub_classinst=zstr(inst);
474  subs[0].zsub_recipient=zstr(recip);
[7d4fbcd]475
[8262340]476  ZResetAuthentication();
[c73a22d]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));
[97cd00be]482    return(-2);
[7d4fbcd]483  }
484  return(0);
[be0a79f]485#else
486  return(0);
487#endif
[7d4fbcd]488}
489
[b0430a6]490/* return a pointer to the data in the Jth field, (NULL terminated by
491 * definition).  Caller must free the return.
492 */
[be0a79f]493#ifdef HAVE_LIBZEPHYR
[1077891a]494char *owl_zephyr_get_field(const ZNotice_t *n, int j)
[31e48a3]495{
[7d4fbcd]496  int i, count, save;
497
[128171a]498  /* If there's no message here, just run along now */
499  if (n->z_message_len == 0)
[d4927a7]500    return(g_strdup(""));
[128171a]501
[7d4fbcd]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 */
[d4927a7]508        return(g_strdup(n->z_message+save));
[7d4fbcd]509      } else {
510        save=i+1;
511      }
512    }
513  }
[b0430a6]514  /* catch the last field, which might not be null terminated */
[7d4fbcd]515  if (count==j-1) {
[fc7481a]516    return g_strndup(n->z_message + save, n->z_message_len - save);
[7d4fbcd]517  }
[b0430a6]518
[d4927a7]519  return(g_strdup(""));
[7d4fbcd]520}
[5376a95]521
[1077891a]522char *owl_zephyr_get_field_as_utf8(const ZNotice_t *n, int j)
[5376a95]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)
[d4927a7]528    return(g_strdup(""));
[5376a95]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 */
[6201646]536        return(owl_validate_or_convert(n->z_message + save));
[5376a95]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) {
[6201646]544    char *tmp, *out;
[fc7481a]545    tmp = g_strndup(n->z_message + save, n->z_message_len - save);
[6201646]546    out = owl_validate_or_convert(tmp);
[ddbbcffa]547    g_free(tmp);
[6201646]548    return out;
[5376a95]549  }
550
[d4927a7]551  return(g_strdup(""));
[5376a95]552}
[09489b89]553#else
[701a184]554char *owl_zephyr_get_field(void *n, int j)
[09489b89]555{
[d4927a7]556  return(g_strdup(""));
[09489b89]557}
[5577606]558char *owl_zephyr_get_field_as_utf8(void *n, int j)
[5376a95]559{
560  return owl_zephyr_get_field(n, j);
561}
[be0a79f]562#endif
[7d4fbcd]563
[b0430a6]564
[be0a79f]565#ifdef HAVE_LIBZEPHYR
[1077891a]566int owl_zephyr_get_num_fields(const ZNotice_t *n)
[31e48a3]567{
[7d4fbcd]568  int i, fields;
569
[50e29e3]570  if(n->z_message_len == 0)
571    return 0;
572
[7d4fbcd]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}
[09489b89]580#else
[1077891a]581int owl_zephyr_get_num_fields(const void *n)
[09489b89]582{
583  return(0);
584}
[be0a79f]585#endif
[7d4fbcd]586
[be0a79f]587#ifdef HAVE_LIBZEPHYR
[bf73bdd]588/* return a pointer to the message, place the message length in k
589 * caller must free the return
590 */
[c08c70a]591char *owl_zephyr_get_message(const ZNotice_t *n, const owl_message *m)
[31e48a3]592{
[405d5e6]593  /* don't let ping messages have a body */
[7d4fbcd]594  if (!strcasecmp(n->z_opcode, "ping")) {
[d4927a7]595    return(g_strdup(""));
[7d4fbcd]596  }
597
[a1bb198]598  /* deal with MIT NOC messages */
[85d1795]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;
[a1bb198]601
602    field3 = owl_zephyr_get_field(n, 3);
603    field4 = owl_zephyr_get_field(n, 4);
604
[3472845]605    msg = g_strdup_printf("%s service on %s %s\n%s", n->z_opcode, n->z_class_inst, field3, field4);
[ddbbcffa]606    g_free(field3);
607    g_free(field4);
[a1bb198]608    if (msg) {
609      return msg;
610    }
611  }
[fba0f96]612  /* deal with MIT Discuss messages */
[e2a620b]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")) {
[fba0f96]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   
[3472845]623    msg = g_strdup_printf("New transaction [%s] entered in %s\nFrom: %s (%s)\nSubject: %s", field1, field2, field3, field5, field4);
[ddbbcffa]624    g_free(field1);
625    g_free(field2);
626    g_free(field3);
627    g_free(field4);
628    g_free(field5);
[fba0f96]629    if (msg) {
630      return msg;
631    }
632  }
[85d1795]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   
[3472845]639    msg = g_strdup_printf("MOIRA %s on %s: %s", n->z_class_inst, owl_message_get_hostname(m), field1);
[ddbbcffa]640    g_free(field1);
[85d1795]641    if (msg) {
642      return msg;
643    }
644  }
[405d5e6]645
[85d1795]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  }
[7d4fbcd]652}
[be0a79f]653#endif
[7d4fbcd]654
[be0a79f]655#ifdef HAVE_LIBZEPHYR
[1077891a]656const char *owl_zephyr_get_zsig(const ZNotice_t *n, int *k)
[31e48a3]657{
[7d4fbcd]658  /* return a pointer to the zsig if there is one */
659
[405d5e6]660  /* message length 0? No zsig */
[7d4fbcd]661  if (n->z_message_len==0) {
662    *k=0;
663    return("");
664  }
[405d5e6]665
[85d1795]666  /* If there's only one field, no zsig */
667  if (owl_zephyr_get_num_fields(n) == 1) {
668    *k=0;
[405d5e6]669    return("");
670  }
671
672  /* Everything else is field 1 */
[7d4fbcd]673  *k=strlen(n->z_message);
674  return(n->z_message);
675}
[09489b89]676#else
[1077891a]677const char *owl_zephyr_get_zsig(const void *n, int *k)
[09489b89]678{
679  return("");
680}
[be0a79f]681#endif
[7d4fbcd]682
[e19eb97]683int send_zephyr(const char *opcode, const char *zsig, const char *class, const char *instance, const char *recipient, const char *message)
[31e48a3]684{
[be0a79f]685#ifdef HAVE_LIBZEPHYR
[c73a22d]686  Code_t ret;
[7d4fbcd]687  ZNotice_t notice;
688   
689  memset(&notice, 0, sizeof(notice));
690
[8262340]691  ZResetAuthentication();
[8ba37ec]692
693  if (!zsig) zsig="";
[8262340]694 
[7d4fbcd]695  notice.z_kind=ACKED;
696  notice.z_port=0;
[712caac]697  notice.z_class=zstr(class);
698  notice.z_class_inst=zstr(instance);
[21882032]699  notice.z_sender=NULL;
[7d4fbcd]700  if (!strcmp(recipient, "*") || !strcmp(recipient, "@")) {
[712caac]701    notice.z_recipient=zstr("");
[21882032]702    if (*owl_global_get_zsender(&g))
[712caac]703        notice.z_sender=zstr(owl_global_get_zsender(&g));
[7d4fbcd]704  } else {
[712caac]705    notice.z_recipient=zstr(recipient);
[7d4fbcd]706  }
[712caac]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);
[7d4fbcd]709
[56330ff]710  notice.z_message_len=strlen(zsig)+1+strlen(message);
[96828e4]711  notice.z_message=g_new(char, notice.z_message_len+10);
[56330ff]712  strcpy(notice.z_message, zsig);
713  memcpy(notice.z_message+strlen(zsig)+1, message, strlen(message));
[7d4fbcd]714
715  /* ret=ZSendNotice(&notice, ZAUTH); */
716  ret=ZSrvSendNotice(&notice, ZAUTH, send_zephyr_helper);
717 
718  /* free then check the return */
[ddbbcffa]719  g_free(notice.z_message);
[7d4fbcd]720  ZFreeNotice(&notice);
[c73a22d]721  if (ret != ZERR_NONE) {
722    owl_function_error("Error sending zephyr: %s", error_message(ret));
[7d4fbcd]723    return(ret);
724  }
725  return(0);
[be0a79f]726#else
727  return(0);
728#endif
[7d4fbcd]729}
730
[be0a79f]731#ifdef HAVE_LIBZEPHYR
[31e48a3]732Code_t send_zephyr_helper(ZNotice_t *notice, char *buf, int len, int wait)
733{
[7d4fbcd]734  return(ZSendPacket(buf, len, 0));
735}
[be0a79f]736#endif
[7d4fbcd]737
[e19eb97]738void send_ping(const char *to, const char *zclass, const char *zinstance)
[31e48a3]739{
[be0a79f]740#ifdef HAVE_LIBZEPHYR
[3ef779b]741  send_zephyr("PING", "", zclass, zinstance, to, "");
[be0a79f]742#endif
[7d4fbcd]743}
744
[be0a79f]745#ifdef HAVE_LIBZEPHYR
[1077891a]746void owl_zephyr_handle_ack(const ZNotice_t *retnotice)
[31e48a3]747{
[7d4fbcd]748  char *tmp;
749 
750  /* if it's an HMACK ignore it */
751  if (retnotice->z_kind == HMACK) return;
[aecf3e6]752
[7d4fbcd]753  if (retnotice->z_kind == SERVNAK) {
[ec6ff52]754    owl_function_error("Authorization failure sending zephyr");
[7d4fbcd]755  } else if ((retnotice->z_kind != SERVACK) || !retnotice->z_message_len) {
[ec6ff52]756    owl_function_error("Detected server failure while receiving acknowledgement");
[7d4fbcd]757  } else if (!strcmp(retnotice->z_message, ZSRVACK_SENT)) {
758    if (!strcasecmp(retnotice->z_opcode, "ping")) {
759      return;
760    } else {
[d73e3af]761      if (strcasecmp(retnotice->z_recipient, ""))
[1e550b2]762      { /* personal */
[d73e3af]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);
[1e550b2]767        } else if(!strcasecmp(retnotice->z_class, "message")) { /* instanced, but not classed, personal */
[d73e3af]768          owl_function_makemsg("Message sent to %s on -i %s\n", tmp, retnotice->z_class_inst);
[1e550b2]769        } else { /* classed personal */
[d73e3af]770          owl_function_makemsg("Message sent to %s on -c %s -i %s\n", tmp, retnotice->z_class, retnotice->z_class_inst);
771        }
[ddbbcffa]772        g_free(tmp);
[d73e3af]773      } else {
[1e550b2]774        /* class / instance message */
[d73e3af]775          owl_function_makemsg("Message sent to -c %s -i %s\n", retnotice->z_class, retnotice->z_class_inst);
776      }
[7d4fbcd]777    }
778  } else if (!strcmp(retnotice->z_message, ZSRVACK_NOTSENT)) {
[44f32fb]779    if (retnotice->z_recipient == NULL
[60c2e1e]780        || *retnotice->z_recipient == 0
[44f32fb]781        || *retnotice->z_recipient == '@') {
[e3a75ed]782      char *buff;
[44f32fb]783      owl_function_error("No one subscribed to class %s", retnotice->z_class);
[e3a75ed]784      buff = g_strdup_printf("Could not send message to class %s: no one subscribed.\n", retnotice->z_class);
[9119a47]785      owl_function_adminmsg("", buff);
[e3a75ed]786      g_free(buff);
[7d4fbcd]787    } else {
[e3a75ed]788      char *buff;
[24ccc01]789      owl_zwrite zw;
790      char *realm;
791
[4b464a4]792      tmp = short_zuser(retnotice->z_recipient);
[44f32fb]793      owl_function_error("%s: Not logged in or subscribing.", tmp);
[3ef779b]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")) {
[e3a75ed]800        buff = g_strdup_printf(
[10e3963]801                 "Could not send message to %s: "
[3ef779b]802                 "not logged in or subscribing to class %s, instance %s.\n",
[10e3963]803                 tmp,
[1151f0b]804                 retnotice->z_class,
805                 retnotice->z_class_inst);
[3ef779b]806      } else if(strcasecmp(retnotice->z_class_inst, "personal")) {
[e3a75ed]807        buff = g_strdup_printf(
[3ef779b]808                 "Could not send message to %s: "
809                 "not logged in or subscribing to instance %s.\n",
810                 tmp,
811                 retnotice->z_class_inst);
[44f32fb]812      } else {
[e3a75ed]813        buff = g_strdup_printf(
[10e3963]814                 "Could not send message to %s: "
815                 "not logged in or subscribing to messages.\n",
816                 tmp);
[44f32fb]817      }
[9119a47]818      owl_function_adminmsg("", buff);
[24ccc01]819
820      memset(&zw, 0, sizeof(zw));
[d4927a7]821      zw.class = g_strdup(retnotice->z_class);
822      zw.inst  = g_strdup(retnotice->z_class_inst);
[24ccc01]823      realm = strchr(retnotice->z_recipient, '@');
824      if(realm) {
[d4927a7]825        zw.realm = g_strdup(realm + 1);
[24ccc01]826      } else {
[d4927a7]827        zw.realm = g_strdup(owl_zephyr_get_realm());
[24ccc01]828      }
[d4927a7]829      zw.opcode = g_strdup(retnotice->z_opcode);
830      zw.zsig   = g_strdup("");
[24ccc01]831      owl_list_create(&(zw.recips));
[d4927a7]832      owl_list_append_element(&(zw.recips), g_strdup(tmp));
[24ccc01]833
834      owl_log_outgoing_zephyr_error(&zw, buff);
835
[c230bc1]836      owl_zwrite_cleanup(&zw);
[e3a75ed]837      g_free(buff);
[ddbbcffa]838      g_free(tmp);
[7d4fbcd]839    }
840  } else {
[ec6ff52]841    owl_function_error("Internal error on ack (%s)", retnotice->z_message);
[7d4fbcd]842  }
843}
[09489b89]844#else
[1077891a]845void owl_zephyr_handle_ack(const void *retnotice)
[09489b89]846{
847}
[be0a79f]848#endif
[7d4fbcd]849
[be0a79f]850#ifdef HAVE_LIBZEPHYR
[1077891a]851int owl_zephyr_notice_is_ack(const ZNotice_t *n)
[31e48a3]852{
[7d4fbcd]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}
[09489b89]859#else
[1077891a]860int owl_zephyr_notice_is_ack(const void *n)
[09489b89]861{
862  return(0);
863}
[be0a79f]864#endif
[7d4fbcd]865 
[c08c70a]866void owl_zephyr_zaway(const owl_message *m)
[31e48a3]867{
[be0a79f]868#ifdef HAVE_LIBZEPHYR
[7c8060d0]869  char *tmpbuff, *myuser, *to;
[15b34fd]870  owl_message *mout;
[987cf3f]871  owl_zwrite *z;
[7d4fbcd]872 
[aa2f6364]873  /* bail if it doesn't look like a message we should reply to.  Some
[2de4f20]874   * of this defined by the way zaway(1) works
875   */
[7d4fbcd]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;
[d023c25]881  if (!strcasecmp(owl_message_get_zsig(m), "Automated reply:")) return;
[7d4fbcd]882  if (!strcasecmp(owl_message_get_sender(m), ZGetSender())) return;
[9854278]883  if (owl_message_get_attribute_value(m, "isauto")) return;
[7d4fbcd]884
[7c8060d0]885  if (owl_global_is_smartstrip(&g)) {
[e3d9c77]886    to=owl_zephyr_smartstripped_user(owl_message_get_sender(m));
[7c8060d0]887  } else {
[d4927a7]888    to=g_strdup(owl_message_get_sender(m));
[7c8060d0]889  }
890
[7d4fbcd]891  send_zephyr("",
892              "Automated reply:",
893              owl_message_get_class(m),
894              owl_message_get_instance(m),
[7c8060d0]895              to,
[7d4fbcd]896              owl_global_get_zaway_msg(&g));
897
[7c8060d0]898  myuser=short_zuser(to);
[aa2f6364]899  if (!strcasecmp(owl_message_get_instance(m), "personal")) {
[eb8d9c1]900    tmpbuff = owl_string_build_quoted("zwrite %q", myuser);
[aa2f6364]901  } else {
[eb8d9c1]902    tmpbuff = owl_string_build_quoted("zwrite -i %q %q", owl_message_get_instance(m), myuser);
[aa2f6364]903  }
[ddbbcffa]904  g_free(myuser);
905  g_free(to);
[aa2f6364]906
[987cf3f]907  z = owl_zwrite_new(tmpbuff);
[bb85767]908  g_free(tmpbuff);
909  if (z == NULL) {
910    owl_function_error("Error creating outgoing zephyr.");
911    return;
912  }
[987cf3f]913  owl_zwrite_set_message(z, owl_global_get_zaway_msg(&g));
914  owl_zwrite_set_zsig(z, "Automated reply:");
915
[7d4fbcd]916  /* display the message as an admin message in the receive window */
[987cf3f]917  mout=owl_function_make_outgoing_zephyr(z);
[13a3c1db]918  owl_global_messagequeue_addmsg(&g, mout);
[987cf3f]919  owl_zwrite_delete(z);
[be0a79f]920#endif
[7d4fbcd]921}
922
[be0a79f]923#ifdef HAVE_LIBZEPHYR
[31e48a3]924void owl_zephyr_hackaway_cr(ZNotice_t *n)
925{
[7d4fbcd]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}
[be0a79f]935#endif
[7d4fbcd]936
[dca3b27]937char *owl_zephyr_zlocate(const char *user, int auth)
[31e48a3]938{
[be0a79f]939#ifdef HAVE_LIBZEPHYR
[7d4fbcd]940  int ret, numlocs;
941  int one = 1;
942  ZLocations_t locations;
943  char *myuser;
[dca3b27]944  char *p, *result;
945
[8262340]946  ZResetAuthentication();
[dca3b27]947  ret = ZLocateUser(zstr(user), &numlocs, auth ? ZAUTH : ZNOAUTH);
948  if (ret != ZERR_NONE)
[3472845]949    return g_strdup_printf("Error locating user %s: %s\n",
950                           user, error_message(ret));
[dca3b27]951
952  myuser = short_zuser(user);
953  if (numlocs == 0) {
[3472845]954    result = g_strdup_printf("%s: Hidden or not logged in\n", myuser);
[dca3b27]955  } else {
[d4927a7]956    result = g_strdup("");
[dca3b27]957    for (; numlocs; numlocs--) {
958      ZGetLocations(&locations, &one);
[3472845]959      p = g_strdup_printf("%s%s: %s\t%s\t%s\n",
[dca3b27]960                          result, myuser,
961                          locations.host ? locations.host : "?",
962                          locations.tty ? locations.tty : "?",
963                          locations.time ? locations.time : "?");
[ddbbcffa]964      g_free(result);
[dca3b27]965      result = p;
966    }
[7d4fbcd]967  }
[ddbbcffa]968  g_free(myuser);
[7d4fbcd]969
[dca3b27]970  return result;
971#else
[d4927a7]972  return g_strdup("");
[be0a79f]973#endif
[7d4fbcd]974}
[bde7714]975
[e19eb97]976void owl_zephyr_addsub(const char *filename, const char *class, const char *inst, const char *recip)
[31e48a3]977{
[be0a79f]978#ifdef HAVE_LIBZEPHYR
[b7ee89b]979  char *line, *subsfile, *s = NULL;
[bde7714]980  FILE *file;
[b7ee89b]981  int duplicate = 0;
[bde7714]982
[b7ee89b]983  line = owl_zephyr_makesubline(class, inst, recip);
[6ea3890]984  subsfile = owl_zephyr_dotfile(".zephyr.subs", filename);
[bde7714]985
[74037d9]986  /* if the file already exists, check to see if the sub is already there */
[b7ee89b]987  file = fopen(subsfile, "r");
[74037d9]988  if (file) {
[b7ee89b]989    while (owl_getline(&s, file)) {
990      if (strcasecmp(s, line) == 0) {
[74037d9]991        owl_function_error("Subscription already present in %s", subsfile);
[b7ee89b]992        duplicate++;
[74037d9]993      }
[bde7714]994    }
[99dabee]995    fclose(file);
[ddbbcffa]996    g_free(s);
[bde7714]997  }
998
[b7ee89b]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    }
[bde7714]1008  }
[b7ee89b]1009
[ddbbcffa]1010  g_free(line);
[be0a79f]1011#endif
[bde7714]1012}
1013
[e19eb97]1014void owl_zephyr_delsub(const char *filename, const char *class, const char *inst, const char *recip)
[31e48a3]1015{
[be0a79f]1016#ifdef HAVE_LIBZEPHYR
[b2a91b6]1017  char *line, *subsfile;
[da60ba9]1018  int linesdeleted;
[bde7714]1019 
1020  line=owl_zephyr_makesubline(class, inst, recip);
[b2a91b6]1021  line[strlen(line)-1]='\0';
[bde7714]1022
[6ea3890]1023  subsfile = owl_zephyr_dotfile(".zephyr.subs", filename);
[b2a91b6]1024 
[da60ba9]1025  linesdeleted = owl_util_file_deleteline(subsfile, line, 1);
1026  if (linesdeleted > 0) {
1027    owl_function_makemsg("Subscription removed");
[5fca55f]1028  } else if (linesdeleted == 0) {
[da60ba9]1029    owl_function_error("No subscription present in %s", subsfile);
1030  }
[ddbbcffa]1031  g_free(subsfile);
1032  g_free(line);
[be0a79f]1033#endif
[bde7714]1034}
1035
[b2a91b6]1036/* caller must free the return */
[e19eb97]1037char *owl_zephyr_makesubline(const char *class, const char *inst, const char *recip)
[31e48a3]1038{
[3472845]1039  return g_strdup_printf("%s,%s,%s\n", class, inst, !strcmp(recip, "") ? "*" : recip);
[bde7714]1040}
[31e48a3]1041
1042
1043void owl_zephyr_zlog_in(void)
1044{
[be0a79f]1045#ifdef HAVE_LIBZEPHYR
[e19eb97]1046  const char *exposure, *eset;
[31e48a3]1047  int ret;
1048
1049  ZResetAuthentication();
1050   
1051  eset=EXPOSE_REALMVIS;
[712caac]1052  exposure=ZGetVariable(zstr("exposure"));
[31e48a3]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   
[712caac]1069  ret=ZSetLocation(zstr(eset));
[31e48a3]1070  if (ret != ZERR_NONE) {
1071    /*
[e440602]1072      owl_function_makemsg("Error setting location: %s", error_message(ret));
[31e48a3]1073    */
1074  }
[be0a79f]1075#endif
[31e48a3]1076}
1077
1078void owl_zephyr_zlog_out(void)
1079{
[be0a79f]1080#ifdef HAVE_LIBZEPHYR
[31e48a3]1081  int ret;
1082
1083  ZResetAuthentication();
1084  ret=ZUnsetLocation();
1085  if (ret != ZERR_NONE) {
1086    /*
[e440602]1087      owl_function_makemsg("Error unsetting location: %s", error_message(ret));
[31e48a3]1088    */
1089  }
[be0a79f]1090#endif
[31e48a3]1091}
1092
[e19eb97]1093void owl_zephyr_addbuddy(const char *name)
[65ad073]1094{
1095  char *filename;
1096  FILE *file;
1097 
[6ea3890]1098  filename = owl_zephyr_dotfile(".anyone", NULL);
1099  file = fopen(filename, "a");
[ddbbcffa]1100  g_free(filename);
[65ad073]1101  if (!file) {
[ec6ff52]1102    owl_function_error("Error opening zephyr buddy file for append");
[65ad073]1103    return;
1104  }
1105  fprintf(file, "%s\n", name);
1106  fclose(file);
1107}
1108
[e19eb97]1109void owl_zephyr_delbuddy(const char *name)
[65ad073]1110{
1111  char *filename;
1112
[6ea3890]1113  filename = owl_zephyr_dotfile(".anyone", NULL);
[65ad073]1114  owl_util_file_deleteline(filename, name, 0);
[ddbbcffa]1115  g_free(filename);
[65ad073]1116}
[9381782]1117
1118/* return auth string */
[09489b89]1119#ifdef HAVE_LIBZEPHYR
[1077891a]1120const char *owl_zephyr_get_authstr(const ZNotice_t *n)
[9381782]1121{
1122
[f12d199]1123  if (!n) return("UNKNOWN");
1124
1125  if (n->z_auth == ZAUTH_FAILED) {
[9381782]1126    return ("FAILED");
[f12d199]1127  } else if (n->z_auth == ZAUTH_NO) {
[9381782]1128    return ("NO");
[f12d199]1129  } else if (n->z_auth == ZAUTH_YES) {
[9381782]1130    return ("YES");
1131  } else {
1132    return ("UNKNOWN");
[f12d199]1133  }           
[9381782]1134}
[09489b89]1135#else
[1077891a]1136const char *owl_zephyr_get_authstr(const void *n)
[09489b89]1137{
1138  return("");
1139}
1140#endif
[9381782]1141
[2de4f20]1142/* Returns a buffer of subscriptions or an error message.  Caller must
1143 * free the return.
[09489b89]1144 */
[c79a047]1145char *owl_zephyr_getsubs(void)
[09489b89]1146{
1147#ifdef HAVE_LIBZEPHYR
[c73a22d]1148  Code_t ret;
1149  int num, i, one;
[09489b89]1150  ZSubscription_t sub;
[df3a1f4]1151  GString *buf;
[09489b89]1152
[c73a22d]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");
[09489b89]1158
[df3a1f4]1159  buf = g_string_new("");
[09489b89]1160  for (i=0; i<num; i++) {
[df3a1f4]1161    one = 1;
[09489b89]1162    if ((ret = ZGetSubscriptions(&sub, &one)) != ZERR_NONE) {
1163      ZFlushSubscriptions();
[df3a1f4]1164      g_string_free(buf, true);
[c73a22d]1165      return g_strdup_printf("Zephyr: Getting subscriptions: %s\n", error_message(ret));
[09489b89]1166    } else {
[df3a1f4]1167      /* g_string_append_printf would be backwards. */
[3472845]1168      char *tmp = g_strdup_printf("<%s,%s,%s>\n",
1169                                  sub.zsub_class,
1170                                  sub.zsub_classinst,
1171                                  sub.zsub_recipient);
[df3a1f4]1172      g_string_prepend(buf, tmp);
[ddbbcffa]1173      g_free(tmp);
[09489b89]1174    }
1175  }
1176
1177  ZFlushSubscriptions();
[df3a1f4]1178  return g_string_free(buf, false);
[09489b89]1179#else
[d4927a7]1180  return(g_strdup("Zephyr not available"));
[09489b89]1181#endif
1182}
1183
[e19eb97]1184const char *owl_zephyr_get_variable(const char *var)
[09489b89]1185{
1186#ifdef HAVE_LIBZEPHYR
[712caac]1187  return(ZGetVariable(zstr(var)));
[09489b89]1188#else
1189  return("");
1190#endif
1191}
1192
[e19eb97]1193void owl_zephyr_set_locationinfo(const char *host, const char *val)
[09489b89]1194{
1195#ifdef HAVE_LIBZEPHYR
[712caac]1196  ZInitLocationInfo(zstr(host), zstr(val));
[09489b89]1197#endif
1198}
1199 
[e3d9c77]1200/* Strip a local realm fron the zephyr user name.
1201 * The caller must free the return
1202 */
[e19eb97]1203char *short_zuser(const char *in)
[e3d9c77]1204{
1205  char *out, *ptr;
1206
[d4927a7]1207  out=g_strdup(in);
[e3d9c77]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 */
[e19eb97]1220char *long_zuser(const char *in)
[e3d9c77]1221{
[1971b59]1222  if (strchr(in, '@')) {
[d4927a7]1223    return(g_strdup(in));
[e3d9c77]1224  }
[3472845]1225  return(g_strdup_printf("%s@%s", in, owl_zephyr_get_realm()));
[e3d9c77]1226}
1227
1228/* strip out the instance from a zsender's principal.  Preserves the
[9d21120]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.
[e3d9c77]1232 */
[e19eb97]1233char *owl_zephyr_smartstripped_user(const char *in)
[e3d9c77]1234{
[9d21120]1235  char *slash, *dot, *realm, *out;
[e3d9c77]1236
[d4927a7]1237  out = g_strdup(in);
[e3d9c77]1238
1239  /* bail immeaditly if we don't have to do any work */
[9d21120]1240  slash = strchr(out, '/');
1241  dot = strchr(out, '.');
1242  if (!slash && !dot) {
[e3d9c77]1243    return(out);
1244  }
[9d21120]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))) {
[e3d9c77]1250    return(out);
1251  }
[9d21120]1252
1253  realm = strchr(out, '@');
1254  if (!slash && dot && realm && (dot > realm)) {
1255    /* There's no '/', and the first '.' is in the realm */
[e3d9c77]1256    return(out);
1257  }
1258
[fa4562c]1259  /* remove the realm from out, but hold on to it */
[e3d9c77]1260  if (realm) realm[0]='\0';
1261
1262  /* strip */
[9d21120]1263  if (slash) slash[0] = '\0';  /* krb5 style user/instance */
1264  else if (dot) dot[0] = '\0'; /* krb4 style user.instance */
[e3d9c77]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}
[5a95b69]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 */
[e19eb97]1280int owl_zephyr_get_anyone_list(owl_list *in, const char *filename)
[5a95b69]1281{
1282#ifdef HAVE_LIBZEPHYR
[b7ee89b]1283  char *ourfile, *tmp, *s = NULL;
[5a95b69]1284  FILE *f;
1285
[6ea3890]1286  ourfile = owl_zephyr_dotfile(".anyone", filename);
[b7ee89b]1287
1288  f = fopen(ourfile, "r");
[5a95b69]1289  if (!f) {
1290    owl_function_error("Error opening file %s: %s", ourfile, strerror(errno) ? strerror(errno) : "");
[ddbbcffa]1291    g_free(ourfile);
[b7ee89b]1292    return -1;
[5a95b69]1293  }
[ddbbcffa]1294  g_free(ourfile);
[5a95b69]1295
[b7ee89b]1296  while (owl_getline_chomp(&s, f)) {
[5a95b69]1297    /* ignore comments, blank lines etc. */
[b7ee89b]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));
[5a95b69]1312  }
[ddbbcffa]1313  g_free(s);
[5a95b69]1314  fclose(f);
[b7ee89b]1315  return 0;
[5a95b69]1316#else
[b7ee89b]1317  return -1;
[5a95b69]1318#endif
1319}
[13a3c1db]1320
[f25812b]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! */
[96828e4]1355            m = g_new(owl_message, 1);
[f25812b]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) {
[96828e4]1368          m = g_new(owl_message, 1);
[f25812b]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);
[ddbbcffa]1377    g_free(zald);
[f25812b]1378  }
1379}
1380#else
1381void owl_zephyr_process_pseudologin(void *n)
1382{
1383}
1384#endif
1385
[3687413]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
[12e291a]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
[e9c6fc8]1405static int _owl_zephyr_process_events(void)
[12e291a]1406{
[13a3c1db]1407  int zpendcount=0;
[12e291a]1408#ifdef HAVE_LIBZEPHYR
[13a3c1db]1409  ZNotice_t notice;
[8ab1f28]1410  Code_t code;
[13a3c1db]1411  owl_message *m=NULL;
1412
[12e291a]1413  while(owl_zephyr_zpending() && zpendcount < OWL_MAX_ZEPHYRGRAMS_TO_PROCESS) {
[13a3c1db]1414    if (owl_zephyr_zpending()) {
[8ab1f28]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      }
[13a3c1db]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);
[46c7f5b]1425        ZFreeNotice(&notice);
[13a3c1db]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")) {
[46c7f5b]1431        ZFreeNotice(&notice);
[13a3c1db]1432        continue;
1433      }
1434
[f25812b]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
[13a3c1db]1442      /* create the new message */
[96828e4]1443      m=g_new(owl_message, 1);
[13a3c1db]1444      owl_message_create_from_znotice(m, &notice);
1445
1446      owl_global_messagequeue_addmsg(&g, m);
1447    }
1448  }
[12e291a]1449#endif
1450  return zpendcount;
[13a3c1db]1451}
1452
[18fdd5f9]1453void owl_zephyr_process_events(const owl_io_dispatch *d, void *data)
[12e291a]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();
[13a3c1db]1461}
Note: See TracBrowser for help on using the repository browser.