Changeset 7655e08


Ignore:
Timestamp:
May 3, 2011, 5:23:55 PM (10 years ago)
Author:
GitHub Merge Button <merge-button@github.com>
Parents:
4fd211f (diff), f578d18 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:
Merge f578d1880dfdaae710755e0db5c3101e89cb0440 into 4fd211f3a533efcedaf4d0dc7c01e02087ad2e39
Files:
1 added
16 edited

Legend:

Unmodified
Added
Removed
  • Makefile.am

    rce35060 rfafb842  
    4545     aim.c buddy.c buddylist.c style.c errqueue.c \
    4646     zbuddylist.c popexec.c select.c wcwidth.c \
    47      glib_compat.c mainpanel.c msgwin.c sepbar.c editcontext.c
     47     glib_compat.c mainpanel.c msgwin.c sepbar.c editcontext.c signal.c
    4848
    4949NORMAL_SRCS = filterproc.c window.c windowcb.c
  • aim.c

    r3472845 r0af5f9d  
    446446}
    447447
    448 int owl_aim_process_events(void)
    449 {
    450   aim_session_t *aimsess;
     448int owl_aim_process_events(aim_session_t *aimsess)
     449{
    451450  aim_conn_t *waitingconn = NULL;
    452451  struct timeval tv;
     
    454453  struct owlfaim_priv *priv;
    455454
    456   aimsess=owl_global_get_aimsess(&g);
    457455  priv = aimsess->aux_data;
    458456
     
    17951793}
    17961794
    1797 void owl_process_aim(void)
    1798 {
    1799   if (owl_global_is_doaimevents(&g)) {
    1800     owl_aim_process_events();
    1801   }
    1802 }
     1795typedef struct _owl_aim_event_source { /*noproto*/
     1796  GSource source;
     1797  aim_session_t *sess;
     1798  GPtrArray *fds;
     1799} owl_aim_event_source;
     1800
     1801static void truncate_pollfd_list(owl_aim_event_source *event_source, int len)
     1802{
     1803  GPollFD *fd;
     1804  int i;
     1805  if (len < event_source->fds->len)
     1806    owl_function_debugmsg("Truncating AIM PollFDs to %d, was %d", len, event_source->fds->len);
     1807  for (i = len; i < event_source->fds->len; i++) {
     1808    fd = event_source->fds->pdata[i];
     1809    g_source_remove_poll(&event_source->source, fd);
     1810    g_free(fd);
     1811  }
     1812  g_ptr_array_remove_range(event_source->fds, len, event_source->fds->len - len);
     1813}
     1814
     1815static gboolean owl_aim_event_source_prepare(GSource *source, int *timeout)
     1816{
     1817  owl_aim_event_source *event_source = (owl_aim_event_source*)source;
     1818  aim_conn_t *cur;
     1819  GPollFD *fd;
     1820  int i;
     1821
     1822  /* AIM HACK:
     1823   *
     1824   *  The problem - I'm not sure where to hook into the owl/faim
     1825   *  interface to keep track of when the AIM socket(s) open and
     1826   *  close. In particular, the bosconn thing throws me off. So,
     1827   *  rather than register particular dispatchers for AIM, I look up
     1828   *  the relevant FDs and add them to select's watch lists, then
     1829   *  check for them individually before moving on to the other
     1830   *  dispatchers. --asedeno
     1831   */
     1832  i = 0;
     1833  for (cur = event_source->sess->connlist; cur; cur = cur->next) {
     1834    if (cur->fd != -1) {
     1835      /* Add new GPollFDs as necessary. */
     1836      if (i == event_source->fds->len) {
     1837        fd = g_new0(GPollFD, 1);
     1838        g_ptr_array_add(event_source->fds, fd);
     1839        g_source_add_poll(source, fd);
     1840        owl_function_debugmsg("Allocated new AIM PollFD, len = %d", event_source->fds->len);
     1841      }
     1842      fd = event_source->fds->pdata[i];
     1843      fd->fd = cur->fd;
     1844      fd->events |= G_IO_IN | G_IO_HUP | G_IO_ERR;
     1845      if (cur->status & AIM_CONN_STATUS_INPROGRESS) {
     1846        /* Yes, we're checking writable sockets here. Without it, AIM
     1847           login is really slow. */
     1848        fd->events |= G_IO_OUT;
     1849      }
     1850      i++;
     1851    }
     1852  }
     1853  /* If the number of GPollFDs went down, clean up. */
     1854  truncate_pollfd_list(event_source, i);
     1855
     1856  *timeout = -1;
     1857  return FALSE;
     1858}
     1859
     1860static gboolean owl_aim_event_source_check(GSource *source)
     1861{
     1862  owl_aim_event_source *event_source = (owl_aim_event_source*)source;
     1863  int i;
     1864
     1865  for (i = 0; i < event_source->fds->len; i++) {
     1866    GPollFD *fd = event_source->fds->pdata[i];
     1867    if (fd->revents & fd->events)
     1868      return TRUE;
     1869  }
     1870  return FALSE;
     1871}
     1872
     1873static gboolean owl_aim_event_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
     1874{
     1875  owl_aim_event_source *event_source = (owl_aim_event_source*)source;
     1876  owl_aim_process_events(event_source->sess);
     1877  return TRUE;
     1878}
     1879
     1880static void owl_aim_event_source_finalize(GSource *source)
     1881{
     1882  owl_aim_event_source *event_source = (owl_aim_event_source*)source;
     1883  truncate_pollfd_list(event_source, 0);
     1884  g_ptr_array_free(event_source->fds, TRUE);
     1885}
     1886
     1887static GSourceFuncs aim_event_funcs = {
     1888  owl_aim_event_source_prepare,
     1889  owl_aim_event_source_check,
     1890  owl_aim_event_source_dispatch,
     1891  owl_aim_event_source_finalize,
     1892};
     1893
     1894GSource *owl_aim_event_source_new(aim_session_t *sess)
     1895{
     1896  GSource *source;
     1897  owl_aim_event_source *event_source;
     1898
     1899  source = g_source_new(&aim_event_funcs, sizeof(owl_aim_event_source));
     1900  event_source = (owl_aim_event_source *)source;
     1901  event_source->sess = sess;
     1902  /* TODO: When we depend on glib 2.22+, use g_ptr_array_new_with_free_func. */
     1903  event_source->fds = g_ptr_array_new();
     1904  return source;
     1905}
  • configure.ac

    r4479497 re9b037f  
    115115
    116116dnl Add CFLAGS and LIBS for glib-2.0
    117 PKG_CHECK_MODULES(GLIB,[glib-2.0 gobject-2.0])
     117PKG_CHECK_MODULES(GLIB,[glib-2.0 gobject-2.0 gthread-2.0])
    118118
    119119AC_MSG_NOTICE([Adding glib-2.0 CFLAGS ${GLIB_CFLAGS}])
  • filterproc.c

    rd564c3d rb9c7424  
    1717  int err = 0;
    1818  struct pollfd fds[2];
    19   struct sigaction sig = {.sa_handler = SIG_IGN}, old;
    2019
    2120  fcntl(rfd, F_SETFL, O_NONBLOCK | fcntl(rfd, F_GETFL));
     
    2726  fds[1].events = POLLOUT;
    2827
    29   sigaction(SIGPIPE, &sig, &old);
    30  
    3128  while(1) {
    3229    if(out && *out) {
     
    6764
    6865  *in = g_string_free(str, err < 0);
    69   sigaction(SIGPIPE, &old, NULL);
    7066  return err;
    7167}
  • functions.c

    r4fd211f r7655e08  
    29952995      i--;
    29962996    }
    2997     owl_function_mask_sigint(NULL);
    2998     if(owl_global_is_interrupted(&g)) {
    2999       owl_global_unset_interrupted(&g);
    3000       owl_function_unmask_sigint(NULL);
     2997    if (owl_global_take_interrupt(&g)) {
    30012998      owl_function_makemsg("Search interrupted!");
    30022999      owl_mainwin_redisplay(owl_global_get_mainwin(&g));
    30033000      return;
    30043001    }
    3005     owl_function_unmask_sigint(NULL);
    30063002  }
    30073003  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
     
    30863082          ret=ZLocateUser(zstr(user), &numlocs, ZAUTH);
    30873083
    3088           owl_function_mask_sigint(NULL);
    3089           if(owl_global_is_interrupted(&g)) {
     3084          if (owl_global_take_interrupt(&g)) {
    30903085            interrupted = 1;
    3091             owl_global_unset_interrupted(&g);
    3092             owl_function_unmask_sigint(NULL);
    30933086            owl_function_makemsg("Interrupted!");
    30943087            break;
    30953088          }
    3096 
    3097           owl_function_unmask_sigint(NULL);
    30983089
    30993090          if (ret!=ZERR_NONE) {
     
    35003491}
    35013492
    3502 void owl_function_mask_sigint(sigset_t *oldmask) {
    3503   sigset_t intr;
    3504 
    3505   sigemptyset(&intr);
    3506   sigaddset(&intr, SIGINT);
    3507   sigprocmask(SIG_BLOCK, &intr, oldmask);
    3508 }
    3509 
    3510 void owl_function_unmask_sigint(sigset_t *oldmask) {
    3511   sigset_t intr;
    3512 
    3513   sigemptyset(&intr);
    3514   sigaddset(&intr, SIGINT);
    3515   sigprocmask(SIG_UNBLOCK, &intr, oldmask);
    3516 }
    3517 
    35183493void _owl_function_mark_message(const owl_message *m)
    35193494{
  • global.c

    r47e0a6a rf578d18  
    1616
    1717  g_type_init();
     18  g_thread_init(NULL);
     19
     20  owl_select_init();
    1821
    1922  g->lines=LINES;
     
    99102
    100103  owl_errqueue_init(&(g->errqueue));
    101   g->got_err_signal=0;
    102104
    103105  owl_zbuddylist_create(&(g->zbuddies));
     
    108110  owl_message_init_fmtext_cache();
    109111  owl_list_create(&(g->io_dispatch_list));
    110   owl_list_create(&(g->psa_list));
    111112  g->timerlist = NULL;
    112   g->interrupted = FALSE;
    113113  g->kill_buffer = NULL;
     114
     115  g->interrupt_count = 0;
     116  g->interrupt_lock = g_mutex_new();
    114117}
    115118
     
    348351
    349352void owl_global_set_resize_pending(owl_global *g) {
    350   g->resizepending=1;
     353  g->resizepending = true;
    351354}
    352355
     
    448451  /* resize the screen.  If lines or cols is 0 use the terminal size */
    449452  if (!g->resizepending) return;
    450   g->resizepending = 0;
     453  g->resizepending = false;
    451454
    452455  owl_global_get_terminal_size(&g->lines, &g->cols);
     
    693696}
    694697
    695 int owl_global_is_doaimevents(const owl_global *g)
    696 {
    697   if (g->aim_doprocessing) return(1);
    698   return(0);
     698bool owl_global_is_doaimevents(const owl_global *g)
     699{
     700  return g->aim_event_source != NULL;
    699701}
    700702
    701703void owl_global_set_doaimevents(owl_global *g)
    702704{
    703   g->aim_doprocessing=1;
     705  if (g->aim_event_source)
     706    return;
     707  g->aim_event_source = owl_aim_event_source_new(owl_global_get_aimsess(g));
     708  g_source_attach(g->aim_event_source, NULL);
    704709}
    705710
    706711void owl_global_set_no_doaimevents(owl_global *g)
    707712{
    708   g->aim_doprocessing=0;
     713  if (!g->aim_event_source)
     714    return;
     715  g_source_destroy(g->aim_event_source);
     716  g_source_unref(g->aim_event_source);
     717  g->aim_event_source = NULL;
    709718}
    710719
     
    824833}
    825834
    826 void owl_global_set_errsignal(owl_global *g, int signum, siginfo_t *siginfo)
    827 {
    828   g->got_err_signal = signum;
    829   if (siginfo) {
    830     g->err_signal_info = *siginfo;
    831   } else {
    832     siginfo_t si;
    833     memset(&si, 0, sizeof(si));
    834     g->err_signal_info = si;
    835   }
    836 }
    837 
    838 int owl_global_get_errsignal_and_clear(owl_global *g, siginfo_t *siginfo)
    839 {
    840   int signum;
    841   if (siginfo && g->got_err_signal) {
    842     *siginfo = g->err_signal_info;
    843   }
    844   signum = g->got_err_signal;
    845   g->got_err_signal = 0;
    846   return signum;
    847 }
    848 
    849 
    850835owl_zbuddylist *owl_global_get_zephyr_buddylist(owl_global *g)
    851836{
     
    878863}
    879864
    880 owl_list *owl_global_get_psa_list(owl_global *g)
    881 {
    882   return &(g->psa_list);
    883 }
    884 
    885865GList **owl_global_get_timerlist(owl_global *g)
    886866{
    887867  return &(g->timerlist);
    888 }
    889 
    890 int owl_global_is_interrupted(const owl_global *g) {
    891   return g->interrupted;
    892 }
    893 
    894 void owl_global_set_interrupted(owl_global *g) {
    895   g->interrupted = 1;
    896 }
    897 
    898 void owl_global_unset_interrupted(owl_global *g) {
    899   g->interrupted = 0;
    900868}
    901869
     
    965933  g->kill_buffer = g_strndup(kill, len);
    966934}
     935
     936void owl_global_add_interrupt(owl_global *g) {
     937  /* TODO: This can almost certainly be done with atomic
     938   * operations. Whatever. */
     939  g_mutex_lock(g->interrupt_lock);
     940  g->interrupt_count++;
     941  g_mutex_unlock(g->interrupt_lock);
     942}
     943
     944bool owl_global_take_interrupt(owl_global *g) {
     945  bool ans = false;
     946  g_mutex_lock(g->interrupt_lock);
     947  if (g->interrupt_count > 0) {
     948    ans = true;
     949    g->interrupt_count--;
     950  }
     951  g_mutex_unlock(g->interrupt_lock);
     952  return ans;
     953}
  • owl.c

    ra2a8833 r7655e08  
    160160 * was ignored due to user settings or otherwise.
    161161 */
    162 int owl_process_message(owl_message *m) {
     162static int owl_process_message(owl_message *m) {
    163163  const owl_filter *f;
    164164  /* if this message it on the puntlist, nuke it and continue */
     
    245245}
    246246
     247static gboolean owl_process_messages_prepare(GSource *source, int *timeout) {
     248  *timeout = -1;
     249  return owl_global_messagequeue_pending(&g);
     250}
     251
     252static gboolean owl_process_messages_check(GSource *source) {
     253  return owl_global_messagequeue_pending(&g);
     254}
     255
    247256/*
    248257 * Process any new messages we have waiting in the message queue.
    249  * Returns 1 if any messages were added to the message list, and 0 otherwise.
    250258 */
    251 int owl_process_messages(owl_ps_action *d, void *p)
    252 {
     259static gboolean owl_process_messages_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) {
    253260  int newmsgs=0;
    254261  int followlast = owl_global_should_followlast(&g);
     
    274281    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
    275282  }
    276   return newmsgs;
     283  return TRUE;
     284}
     285
     286static GSourceFuncs owl_process_messages_funcs = {
     287  owl_process_messages_prepare,
     288  owl_process_messages_check,
     289  owl_process_messages_dispatch,
     290  NULL
     291};
     292
     293void owl_process_input_char(owl_input j)
     294{
     295  int ret;
     296
     297  owl_global_set_lastinputtime(&g, time(NULL));
     298  ret = owl_keyhandler_process(owl_global_get_keyhandler(&g), j);
     299  if (ret!=0 && ret!=1) {
     300    owl_function_makemsg("Unable to handle keypress");
     301  }
    277302}
    278303
     
    334359}
    335360
    336 void sig_handler(int sig, siginfo_t *si, void *data)
    337 {
    338   if (sig==SIGWINCH) {
    339     /* we can't inturrupt a malloc here, so it just sets a flag
    340      * schedulding a resize for later
    341      */
     361static void sig_handler_main_thread(void *data) {
     362  int sig = GPOINTER_TO_INT(data);
     363
     364  owl_function_debugmsg("Got signal %d", sig);
     365  if (sig == SIGWINCH) {
    342366    owl_function_resize();
    343   } else if (sig==SIGPIPE || sig==SIGCHLD) {
    344     /* Set a flag and some info that we got the sigpipe
    345      * so we can record that we got it and why... */
    346     owl_global_set_errsignal(&g, sig, si);
    347   } else if (sig==SIGTERM || sig==SIGHUP) {
     367  } else if (sig == SIGTERM || sig == SIGHUP) {
    348368    owl_function_quit();
    349   }
    350 }
    351 
    352 void sigint_handler(int sig, siginfo_t *si, void *data)
    353 {
    354   owl_global_set_interrupted(&g);
    355 }
    356 
    357 static int owl_errsignal_pre_select_action(owl_ps_action *a, void *data)
    358 {
    359   siginfo_t si;
    360   int signum;
    361   if ((signum = owl_global_get_errsignal_and_clear(&g, &si)) > 0) {
    362     owl_function_error("Got unexpected signal: %d %s  (code: %d band: %ld  errno: %d)",
    363         signum, signum==SIGPIPE?"SIGPIPE":"SIG????",
    364         si.si_code, si.si_band, si.si_errno);
    365   }
    366   return 0;
    367 }
     369  } else if (sig == SIGINT && owl_global_take_interrupt(&g)) {
     370    owl_input in;
     371    in.ch = in.uch = owl_global_get_startup_tio(&g)->c_cc[VINTR];
     372    owl_process_input_char(in);
     373  }
     374}
     375
     376static void sig_handler(const siginfo_t *siginfo, void *data) {
     377  /* If it was an interrupt, set a flag so we can handle it earlier if
     378   * needbe. sig_handler_main_thread will check the flag to make sure
     379   * no one else took it. */
     380  if (siginfo->si_signo == SIGINT) {
     381    owl_global_add_interrupt(&g);
     382  }
     383  /* Send a message to the main thread. */
     384  owl_select_post_task(sig_handler_main_thread,
     385                       GINT_TO_POINTER(siginfo->si_signo), NULL);
     386}
     387
     388#define CHECK_RESULT(s, syscall) \
     389  G_STMT_START {                 \
     390    if ((syscall) != 0) {        \
     391      perror((s));               \
     392      exit(1);                   \
     393    }                            \
     394  } G_STMT_END
    368395
    369396void owl_register_signal_handlers(void) {
    370   struct sigaction sigact;
    371 
    372   /* signal handler */
    373   /*sigact.sa_handler=sig_handler;*/
    374   sigact.sa_sigaction=sig_handler;
    375   sigemptyset(&sigact.sa_mask);
    376   sigact.sa_flags=SA_SIGINFO;
    377   sigaction(SIGWINCH, &sigact, NULL);
    378   sigaction(SIGALRM, &sigact, NULL);
    379   sigaction(SIGPIPE, &sigact, NULL);
    380   sigaction(SIGTERM, &sigact, NULL);
    381   sigaction(SIGHUP, &sigact, NULL);
    382 
    383   sigact.sa_sigaction=sigint_handler;
    384   sigaction(SIGINT, &sigact, NULL);
     397  struct sigaction sig_ignore = { .sa_handler = SIG_IGN };
     398  struct sigaction sig_default = { .sa_handler = SIG_DFL };
     399  sigset_t sigset;
     400  int ret, i;
     401  const int signals[] = { SIGABRT, SIGBUS, SIGCHLD, SIGFPE, SIGHUP, SIGILL,
     402                          SIGINT, SIGQUIT, SIGSEGV, SIGTERM, SIGWINCH };
     403
     404  /* Sanitize our signals; the mask and dispositions from our parent
     405   * aren't really useful. Signal list taken from equivalent code in
     406   * Chromium. */
     407  CHECK_RESULT("sigemptyset", sigemptyset(&sigset));
     408  if ((ret = pthread_sigmask(SIG_SETMASK, &sigset, NULL)) != 0) {
     409    errno = ret;
     410    perror("pthread_sigmask");
     411  }
     412  for (i = 0; i < G_N_ELEMENTS(signals); i++) {
     413    CHECK_RESULT("sigaction", sigaction(signals[i], &sig_default, NULL));
     414  }
     415
     416  /* Turn off SIGPIPE; we check the return value of write. */
     417  CHECK_RESULT("sigaction", sigaction(SIGPIPE, &sig_ignore, NULL));
     418
     419  /* Register some signals with the signal thread. */
     420  CHECK_RESULT("sigaddset", sigaddset(&sigset, SIGWINCH));
     421  CHECK_RESULT("sigaddset", sigaddset(&sigset, SIGTERM));
     422  CHECK_RESULT("sigaddset", sigaddset(&sigset, SIGHUP));
     423  CHECK_RESULT("sigaddset", sigaddset(&sigset, SIGINT));
     424  owl_signal_init(&sigset, sig_handler, NULL);
    385425}
    386426
     
    436476#endif /* OWL_STDERR_REDIR */
    437477
    438 static int owl_refresh_pre_select_action(owl_ps_action *a, void *data)
    439 {
    440   owl_colorpair_mgr *cpmgr;
    441 
    442   /* if a resize has been scheduled, deal with it */
    443   owl_global_check_resize(&g);
    444   /* update the terminal if we need to */
    445   owl_window_redraw_scheduled();
    446   /* On colorpair shortage, reset and redraw /everything/. NOTE: if
    447    * the current screen uses too many colorpairs, this draws
    448    * everything twice. But this is unlikely; COLOR_PAIRS is 64 with
    449    * 8+1 colors, and 256^2 with 256+1 colors. (+1 for default.) */
    450   cpmgr = owl_global_get_colorpair_mgr(&g);
    451   if (cpmgr->overflow) {
    452     owl_function_debugmsg("colorpairs: color shortage; reset pairs and redraw. COLOR_PAIRS = %d", COLOR_PAIRS);
    453     owl_fmtext_reset_colorpairs(cpmgr);
    454     owl_function_full_redisplay();
    455     owl_window_redraw_scheduled();
    456   }
    457   return 0;
    458 }
    459 
    460 
    461478int main(int argc, char **argv, char **env)
    462479{
     
    467484  const char *dir;
    468485  owl_options opts;
     486  GSource *source;
    469487
    470488  if (!GLIB_CHECK_VERSION (2, 12, 0))
     
    481499  g.load_initial_subs = opts.load_initial_subs;
    482500
    483   owl_register_signal_handlers();
    484501  owl_start_curses();
    485502
     
    492509  g_strfreev(argv_copy);
    493510  owl_global_set_haveaim(&g);
     511
     512  owl_register_signal_handlers();
    494513
    495514  /* register STDIN dispatch; throw away return, we won't need it */
     
    584603  owl_global_push_context(&g, OWL_CTX_INTERACTIVE|OWL_CTX_RECV, NULL, "recv", NULL);
    585604
    586   owl_select_add_pre_select_action(owl_refresh_pre_select_action, NULL, NULL);
    587   owl_select_add_pre_select_action(owl_process_messages, NULL, NULL);
    588   owl_select_add_pre_select_action(owl_errsignal_pre_select_action, NULL, NULL);
     605  source = owl_window_redraw_source_new();
     606  g_source_attach(source, NULL);
     607  g_source_unref(source);
     608
     609  source = g_source_new(&owl_process_messages_funcs, sizeof(GSource));
     610  g_source_attach(source, NULL);
     611  g_source_unref(source);
    589612
    590613  owl_function_debugmsg("startup: entering main loop");
     
    593616  /* Shut down everything. */
    594617  owl_zephyr_shutdown();
     618  owl_signal_shutdown();
    595619  owl_shutdown_curses();
    596620  return 0;
  • owl.h

    r283ff1e rf578d18  
    550550  void (*destroy)(const struct _owl_io_dispatch *);  /* Destructor */
    551551  void *data;
     552  GPollFD pollfd;
    552553} owl_io_dispatch;
    553 
    554 typedef struct _owl_ps_action {
    555   int needs_gc;
    556   int (*callback)(struct _owl_ps_action *, void *);
    557   void (*destroy)(struct _owl_ps_action *);
    558   void *data;
    559 } owl_ps_action;
    560554
    561555typedef struct _owl_popexec {
     
    566560  const owl_io_dispatch *dispatch;
    567561} owl_popexec;
    568 
    569 typedef struct _OwlGlobalNotifier OwlGlobalNotifier;
    570562
    571563typedef struct _owl_global {
     
    593585  gulong typwin_erase_id;
    594586  int rightshift;
    595   volatile sig_atomic_t resizepending;
     587  bool resizepending;
    596588  char *homedir;
    597589  char *confdir;
     
    618610  aim_conn_t bosconn;
    619611  int aim_loggedin;         /* true if currently logged into AIM */
    620   int aim_doprocessing;     /* true if we should process AIM events (like pending login) */
     612  GSource *aim_event_source; /* where we get our AIM events from */
    621613  char *aim_screenname;     /* currently logged in AIM screen name */
    622614  char *aim_screenname_for_filters;     /* currently logged in AIM screen name */
     
    628620  int haveaim;
    629621  int ignoreaimlogin;
    630   volatile sig_atomic_t got_err_signal; /* 1 if we got an unexpected signal */
    631   volatile siginfo_t err_signal_info;
    632622  owl_zbuddylist zbuddies;
    633623  GList *zaldlist;
     
    635625  struct termios startup_tio;
    636626  owl_list io_dispatch_list;
    637   owl_list psa_list;
    638627  GList *timerlist;
    639628  owl_timer *aim_nop_timer;
    640629  int load_initial_subs;
    641   volatile sig_atomic_t interrupted;
    642630  FILE *debug_file;
    643631  char *kill_buffer;
     632  int interrupt_count;
     633  GMutex *interrupt_lock;
    644634} owl_global;
    645635
  • select.c

    rd4927a7 r111850c  
    11#include "owl.h"
    22
     3static GMainLoop *loop = NULL;
     4static GMainContext *context;
    35static int dispatch_active = 0;
    4 static int psa_active = 0;
    5 static int loop_active = 0;
    6 
    7 int _owl_select_timer_cmp(const owl_timer *t1, const owl_timer *t2) {
     6
     7static GSource *owl_timer_source;
     8static GSource *owl_io_dispatch_source;
     9
     10static int _owl_select_timer_cmp(const owl_timer *t1, const owl_timer *t2);
     11static void owl_select_io_dispatch_gc(void);
     12
     13static gboolean owl_timer_prepare(GSource *source, int *timeout) {
     14  GList **timers = owl_global_get_timerlist(&g);
     15  GTimeVal now;
     16
     17  /* TODO: In the far /far/ future, g_source_get_time is what the cool
     18   * kids use to get system monotonic time. */
     19  g_source_get_current_time(source, &now);
     20
     21  /* FIXME: bother with millisecond accuracy now that we can? */
     22  if (*timers) {
     23    owl_timer *t = (*timers)->data;
     24    *timeout = t->time - now.tv_sec;
     25    if (*timeout <= 0) {
     26      *timeout = 0;
     27      return TRUE;
     28    }
     29    if (*timeout > 60 * 1000)
     30      *timeout = 60 * 1000;
     31  } else {
     32    *timeout = 60 * 1000;
     33  }
     34  return FALSE;
     35}
     36
     37static gboolean owl_timer_check(GSource *source) {
     38  GList **timers = owl_global_get_timerlist(&g);
     39  GTimeVal now;
     40
     41  /* TODO: In the far /far/ future, g_source_get_time is what the cool
     42   * kids use to get system monotonic time. */
     43  g_source_get_current_time(source, &now);
     44
     45  /* FIXME: bother with millisecond accuracy now that we can? */
     46  if (*timers) {
     47    owl_timer *t = (*timers)->data;
     48    return t->time >= now.tv_sec;
     49  }
     50  return FALSE;
     51}
     52
     53
     54static gboolean owl_timer_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) {
     55  GList **timers = owl_global_get_timerlist(&g);
     56  GTimeVal now;
     57
     58  /* TODO: In the far /far/ future, g_source_get_time is what the cool
     59   * kids use to get system monotonic time. */
     60  g_source_get_current_time(source, &now);
     61
     62  /* FIXME: bother with millisecond accuracy now that we can? */
     63  while(*timers) {
     64    owl_timer *t = (*timers)->data;
     65    int remove = 0;
     66
     67    if(t->time > now.tv_sec)
     68      break;
     69
     70    /* Reschedule if appropriate */
     71    if(t->interval > 0) {
     72      t->time = now.tv_sec + t->interval;
     73      *timers = g_list_remove(*timers, t);
     74      *timers = g_list_insert_sorted(*timers, t,
     75                                     (GCompareFunc)_owl_select_timer_cmp);
     76    } else {
     77      remove = 1;
     78    }
     79
     80    /* Do the callback */
     81    t->callback(t, t->data);
     82    if(remove) {
     83      owl_select_remove_timer(t);
     84    }
     85  }
     86  return TRUE;
     87}
     88
     89static GSourceFuncs owl_timer_funcs = {
     90  owl_timer_prepare,
     91  owl_timer_check,
     92  owl_timer_dispatch,
     93  NULL
     94};
     95
     96static int _owl_select_timer_cmp(const owl_timer *t1, const owl_timer *t2) {
    897  return t1->time - t2->time;
    9 }
    10 
    11 int _owl_select_timer_eq(const owl_timer *t1, const owl_timer *t2) {
    12   return t1 == t2;
    1398}
    1499
     
    43128}
    44129
    45 void owl_select_process_timers(struct timespec *timeout)
    46 {
    47   time_t now = time(NULL);
    48   GList **timers = owl_global_get_timerlist(&g);
    49 
    50   while(*timers) {
    51     owl_timer *t = (*timers)->data;
    52     int remove = 0;
    53 
    54     if(t->time > now)
    55       break;
    56 
    57     /* Reschedule if appropriate */
    58     if(t->interval > 0) {
    59       t->time = now + t->interval;
    60       *timers = g_list_remove(*timers, t);
    61       *timers = g_list_insert_sorted(*timers, t,
    62                                      (GCompareFunc)_owl_select_timer_cmp);
    63     } else {
    64       remove = 1;
    65     }
    66 
    67     /* Do the callback */
    68     t->callback(t, t->data);
    69     if(remove) {
    70       owl_select_remove_timer(t);
    71     }
    72   }
    73 
    74   if(*timers) {
    75     owl_timer *t = (*timers)->data;
    76     timeout->tv_sec = t->time - now;
    77     if (timeout->tv_sec > 60)
    78       timeout->tv_sec = 60;
    79   } else {
    80     timeout->tv_sec = 60;
    81   }
    82 
    83   timeout->tv_nsec = 0;
    84 }
     130
     131static gboolean owl_io_dispatch_prepare(GSource *source, int *timeout) {
     132  *timeout = -1;
     133  return FALSE;
     134}
     135
     136static gboolean owl_io_dispatch_check(GSource *source) {
     137  int i, len;
     138  const owl_list *dl;
     139
     140  dl = owl_global_get_io_dispatch_list(&g);
     141  len = owl_list_get_size(dl);
     142  for(i = 0; i < len; i++) {
     143    const owl_io_dispatch *d = owl_list_get_element(dl, i);
     144    if (d->pollfd.revents & d->pollfd.events)
     145      return TRUE;
     146  }
     147  return FALSE;
     148}
     149
     150static gboolean owl_io_dispatch_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) {
     151  int i, len;
     152  const owl_list *dl;
     153 
     154  dispatch_active = 1;
     155  dl = owl_global_get_io_dispatch_list(&g);
     156  len = owl_list_get_size(dl);
     157  for (i = 0; i < len; i++) {
     158    owl_io_dispatch *d = owl_list_get_element(dl, i);
     159    if ((d->pollfd.revents & d->pollfd.events) && d->callback != NULL) {
     160      d->callback(d, d->data);
     161    }
     162  }
     163  dispatch_active = 0;
     164  owl_select_io_dispatch_gc();
     165
     166  return TRUE;
     167}
     168
     169static GSourceFuncs owl_io_dispatch_funcs = {
     170  owl_io_dispatch_prepare,
     171  owl_io_dispatch_check,
     172  owl_io_dispatch_dispatch,
     173  NULL
     174};
    85175
    86176static const owl_io_dispatch *owl_select_find_io_dispatch_by_fd(const int fd)
     
    128218        if (d->destroy)
    129219          d->destroy(d);
     220        g_source_remove_poll(owl_io_dispatch_source, &d->pollfd);
    130221        g_free(d);
    131222      }
     
    134225}
    135226
    136 void owl_select_io_dispatch_gc(void)
     227static void owl_select_io_dispatch_gc(void)
    137228{
    138229  int i;
     
    169260  d->data = data;
    170261
     262  /* TODO: Allow changing fd and mode in the middle? Probably don't care... */
     263  d->pollfd.fd = fd;
     264  d->pollfd.events = 0;
     265  if (d->mode & OWL_IO_READ)
     266    d->pollfd.events |= G_IO_IN | G_IO_HUP | G_IO_ERR;
     267  if (d->mode & OWL_IO_WRITE)
     268    d->pollfd.events |= G_IO_OUT | G_IO_ERR;
     269  if (d->mode & OWL_IO_EXCEPT)
     270    d->pollfd.events |= G_IO_PRI | G_IO_ERR;
     271  g_source_add_poll(owl_io_dispatch_source, &d->pollfd);
     272
     273
    171274  owl_select_remove_io_dispatch(owl_select_find_io_dispatch_by_fd(fd));
    172275  owl_list_append_element(dl, d);
    173276
    174277  return d;
    175 }
    176 
    177 int owl_select_prepare_io_dispatch_fd_sets(fd_set *rfds, fd_set *wfds, fd_set *efds) {
    178   int i, len, max_fd;
    179   owl_io_dispatch *d;
    180   owl_list *dl = owl_global_get_io_dispatch_list(&g);
    181 
    182   max_fd = 0;
    183   len = owl_list_get_size(dl);
    184   for (i = 0; i < len; i++) {
    185     d = owl_list_get_element(dl, i);
    186     if (d->mode & (OWL_IO_READ | OWL_IO_WRITE | OWL_IO_EXCEPT)) {
    187       if (max_fd < d->fd) max_fd = d->fd;
    188       if (d->mode & OWL_IO_READ) FD_SET(d->fd, rfds);
    189       if (d->mode & OWL_IO_WRITE) FD_SET(d->fd, wfds);
    190       if (d->mode & OWL_IO_EXCEPT) FD_SET(d->fd, efds);
    191     }
    192   }
    193   return max_fd + 1;
    194 }
    195 
    196 void owl_select_io_dispatch(const fd_set *rfds, const fd_set *wfds, const fd_set *efds, const int max_fd)
    197 {
    198   int i, len;
    199   owl_io_dispatch *d;
    200   owl_list *dl = owl_global_get_io_dispatch_list(&g);
    201 
    202   dispatch_active = 1;
    203   len = owl_list_get_size(dl);
    204   for (i = 0; i < len; i++) {
    205     d = owl_list_get_element(dl, i);
    206     if (d->fd < max_fd && d->callback != NULL &&
    207         ((d->mode & OWL_IO_READ && FD_ISSET(d->fd, rfds)) ||
    208          (d->mode & OWL_IO_WRITE && FD_ISSET(d->fd, wfds)) ||
    209          (d->mode & OWL_IO_EXCEPT && FD_ISSET(d->fd, efds)))) {
    210       d->callback(d, d->data);
    211     }
    212   }
    213   dispatch_active = 0;
    214   owl_select_io_dispatch_gc();
    215278}
    216279
     
    237300}
    238301
    239 int owl_select_aim_hack(fd_set *rfds, fd_set *wfds)
    240 {
    241   aim_conn_t *cur;
    242   aim_session_t *sess;
    243   int max_fd;
    244 
    245   max_fd = 0;
    246   sess = owl_global_get_aimsess(&g);
    247   for (cur = sess->connlist; cur; cur = cur->next) {
    248     if (cur->fd != -1) {
    249       FD_SET(cur->fd, rfds);
    250       if (cur->status & AIM_CONN_STATUS_INPROGRESS) {
    251         /* Yes, we're checking writable sockets here. Without it, AIM
    252            login is really slow. */
    253         FD_SET(cur->fd, wfds);
    254       }
    255      
    256       if (cur->fd > max_fd)
    257         max_fd = cur->fd;
    258     }
    259   }
    260   return max_fd;
    261 }
    262 
    263 void owl_process_input_char(owl_input j)
    264 {
    265   int ret;
    266 
    267   owl_global_set_lastinputtime(&g, time(NULL));
    268   ret = owl_keyhandler_process(owl_global_get_keyhandler(&g), j);
    269   if (ret!=0 && ret!=1) {
    270     owl_function_makemsg("Unable to handle keypress");
    271   }
    272 }
    273 
    274 void owl_select_mask_signals(sigset_t *oldmask) {
    275   sigset_t set;
    276 
    277   sigemptyset(&set);
    278   sigaddset(&set, SIGWINCH);
    279   sigaddset(&set, SIGALRM);
    280   sigaddset(&set, SIGPIPE);
    281   sigaddset(&set, SIGTERM);
    282   sigaddset(&set, SIGHUP);
    283   sigaddset(&set, SIGINT);
    284   sigprocmask(SIG_BLOCK, &set, oldmask);
    285 }
    286 
    287 void owl_select_handle_intr(sigset_t *restore)
    288 {
    289   owl_input in;
    290 
    291   owl_global_unset_interrupted(&g);
    292 
    293   sigprocmask(SIG_SETMASK, restore, NULL);
    294 
    295   in.ch = in.uch = owl_global_get_startup_tio(&g)->c_cc[VINTR];
    296   owl_process_input_char(in);
    297 }
    298 
    299 owl_ps_action *owl_select_add_pre_select_action(int (*cb)(owl_ps_action *, void *), void (*destroy)(owl_ps_action *), void *data)
    300 {
    301   owl_ps_action *a = g_new(owl_ps_action, 1);
    302   owl_list *psa_list = owl_global_get_psa_list(&g);
    303   a->needs_gc = 0;
    304   a->callback = cb;
    305   a->destroy = destroy;
    306   a->data = data;
    307   owl_list_append_element(psa_list, a);
    308   return a;
    309 }
    310 
    311 void owl_select_psa_gc(void)
    312 {
    313   int i;
    314   owl_list *psa_list;
    315   owl_ps_action *a;
    316 
    317   psa_list = owl_global_get_psa_list(&g);
    318   for (i = owl_list_get_size(psa_list) - 1; i >= 0; i--) {
    319     a = owl_list_get_element(psa_list, i);
    320     if (a->needs_gc) {
    321       owl_list_remove_element(psa_list, i);
    322       if (a->destroy) {
    323         a->destroy(a);
    324       }
    325       g_free(a);
    326     }
    327   }
    328 }
    329 
    330 void owl_select_remove_pre_select_action(owl_ps_action *a)
    331 {
    332   a->needs_gc = 1;
    333   if (!psa_active)
    334     owl_select_psa_gc();
    335 }
    336 
    337 int owl_select_do_pre_select_actions(void)
    338 {
    339   int i, len, ret;
    340   owl_list *psa_list;
    341 
    342   psa_active = 1;
    343   ret = 0;
    344   psa_list = owl_global_get_psa_list(&g);
    345   len = owl_list_get_size(psa_list);
    346   for (i = 0; i < len; i++) {
    347     owl_ps_action *a = owl_list_get_element(psa_list, i);
    348     if (a->callback != NULL && a->callback(a, a->data)) {
    349       ret = 1;
    350     }
    351   }
    352   psa_active = 0;
    353   owl_select_psa_gc();
    354   return ret;
    355 }
    356 
    357 void owl_select(void)
    358 {
    359   int i, max_fd, max_fd2, aim_done, ret;
    360   fd_set r;
    361   fd_set w;
    362   fd_set e;
    363   fd_set aim_rfds, aim_wfds;
    364   struct timespec timeout;
    365   sigset_t mask;
    366 
    367   owl_select_process_timers(&timeout);
    368 
    369   owl_select_mask_signals(&mask);
    370 
    371   if(owl_global_is_interrupted(&g)) {
    372     owl_select_handle_intr(&mask);
    373     return;
    374   }
    375   FD_ZERO(&r);
    376   FD_ZERO(&w);
    377   FD_ZERO(&e);
    378 
    379   max_fd = owl_select_prepare_io_dispatch_fd_sets(&r, &w, &e);
    380 
    381   /* AIM HACK:
    382    *
    383    *  The problem - I'm not sure where to hook into the owl/faim
    384    *  interface to keep track of when the AIM socket(s) open and
    385    *  close. In particular, the bosconn thing throws me off. So,
    386    *  rather than register particular dispatchers for AIM, I look up
    387    *  the relevant FDs and add them to select's watch lists, then
    388    *  check for them individually before moving on to the other
    389    *  dispatchers. --asedeno
    390    */
    391   aim_done = 1;
    392   FD_ZERO(&aim_rfds);
    393   FD_ZERO(&aim_wfds);
    394   if (owl_global_is_doaimevents(&g)) {
    395     aim_done = 0;
    396     max_fd2 = owl_select_aim_hack(&aim_rfds, &aim_wfds);
    397     if (max_fd < max_fd2) max_fd = max_fd2;
    398     for(i = 0; i <= max_fd2; i++) {
    399       if (FD_ISSET(i, &aim_rfds)) {
    400         FD_SET(i, &r);
    401         FD_SET(i, &e);
    402       }
    403       if (FD_ISSET(i, &aim_wfds)) {
    404         FD_SET(i, &w);
    405         FD_SET(i, &e);
    406       }
    407     }
    408   }
    409   /* END AIM HACK */
    410 
    411   if (owl_select_do_pre_select_actions()) {
    412     timeout.tv_sec = 0;
    413     timeout.tv_nsec = 0;
    414   }
    415 
    416   ret = pselect(max_fd+1, &r, &w, &e, &timeout, &mask);
    417 
    418   if(ret < 0 && errno == EINTR) {
    419     if(owl_global_is_interrupted(&g)) {
    420       owl_select_handle_intr(NULL);
    421     }
    422     sigprocmask(SIG_SETMASK, &mask, NULL);
    423     return;
    424   }
    425 
    426   sigprocmask(SIG_SETMASK, &mask, NULL);
    427 
    428   if(ret > 0) {
    429     /* AIM HACK: process all AIM events at once. */
    430     for(i = 0; !aim_done && i <= max_fd; i++) {
    431       if (FD_ISSET(i, &r) || FD_ISSET(i, &w) || FD_ISSET(i, &e)) {
    432         if (FD_ISSET(i, &aim_rfds) || FD_ISSET(i, &aim_wfds)) {
    433           owl_process_aim();
    434           aim_done = 1;
    435         }
    436       }
    437     }
    438     owl_select_io_dispatch(&r, &w, &e, max_fd);
    439   }
     302void owl_select_init(void)
     303{
     304  owl_timer_source = g_source_new(&owl_timer_funcs, sizeof(GSource));
     305  g_source_attach(owl_timer_source, NULL);
     306
     307  owl_io_dispatch_source = g_source_new(&owl_io_dispatch_funcs, sizeof(GSource));
     308  g_source_attach(owl_io_dispatch_source, NULL);
    440309}
    441310
    442311void owl_select_run_loop(void)
    443312{
    444   loop_active = 1;
    445   while (loop_active) {
    446     owl_select();
    447   }
     313  context = g_main_context_default();
     314  loop = g_main_loop_new(context, FALSE);
     315  g_main_loop_run(loop);
    448316}
    449317
    450318void owl_select_quit_loop(void)
    451319{
    452   loop_active = 0;
    453 }
     320  if (loop) {
     321    g_main_loop_quit(loop);
     322    loop = NULL;
     323  }
     324}
     325
     326typedef struct _owl_task { /*noproto*/
     327  void (*cb)(void *);
     328  void *cbdata;
     329  void (*destroy_cbdata)(void *);
     330} owl_task;
     331
     332static gboolean _run_task(gpointer data)
     333{
     334  owl_task *t = data;
     335  if (t->cb)
     336    t->cb(t->cbdata);
     337  return FALSE;
     338}
     339
     340static void _destroy_task(void *data)
     341{
     342  owl_task *t = data;
     343  if (t->destroy_cbdata)
     344    t->destroy_cbdata(t->cbdata);
     345  g_free(t);
     346}
     347
     348void owl_select_post_task(void (*cb)(void*), void *cbdata, void (*destroy_cbdata)(void*))
     349{
     350  GSource *source = g_idle_source_new();
     351  owl_task *t = g_new0(owl_task, 1);
     352  t->cb = cb;
     353  t->cbdata = cbdata;
     354  t->destroy_cbdata = destroy_cbdata;
     355  g_source_set_priority(source, G_PRIORITY_DEFAULT);
     356  g_source_set_callback(source, _run_task, t, _destroy_task);
     357  g_source_attach(source, context);
     358  g_source_unref(source);
     359}
  • window.c

    rb31f1c9 r7b2686d  
    524524  owl_window_set_position(w, nlines, ncols, w->begin_y, w->begin_x);
    525525}
     526
     527/** Redrawing main loop hooks **/
     528
     529static bool _owl_window_should_redraw(void) {
     530  return g.resizepending || owl_window_get_screen()->dirty_subtree;
     531}
     532
     533static gboolean _owl_window_redraw_prepare(GSource *source, int *timeout) {
     534  *timeout = -1;
     535  return _owl_window_should_redraw();
     536}
     537
     538static gboolean _owl_window_redraw_check(GSource *source) {
     539  return _owl_window_should_redraw();
     540}
     541
     542static gboolean _owl_window_redraw_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) {
     543  owl_colorpair_mgr *cpmgr;
     544
     545  /* if a resize has been scheduled, deal with it */
     546  owl_global_check_resize(&g);
     547  /* update the terminal if we need to */
     548  owl_window_redraw_scheduled();
     549  /* On colorpair shortage, reset and redraw /everything/. NOTE: if
     550   * the current screen uses too many colorpairs, this draws
     551   * everything twice. But this is unlikely; COLOR_PAIRS is 64 with
     552   * 8+1 colors, and 256^2 with 256+1 colors. (+1 for default.) */
     553  cpmgr = owl_global_get_colorpair_mgr(&g);
     554  if (cpmgr->overflow) {
     555    owl_function_debugmsg("colorpairs: color shortage; reset pairs and redraw. COLOR_PAIRS = %d", COLOR_PAIRS);
     556    owl_fmtext_reset_colorpairs(cpmgr);
     557    owl_function_full_redisplay();
     558    owl_window_redraw_scheduled();
     559  }
     560  return TRUE;
     561}
     562
     563static GSourceFuncs redraw_funcs = {
     564  _owl_window_redraw_prepare,
     565  _owl_window_redraw_check,
     566  _owl_window_redraw_dispatch,
     567  NULL
     568};
     569
     570GSource *owl_window_redraw_source_new(void) {
     571  GSource *source;
     572  source = g_source_new(&redraw_funcs, sizeof(GSource));
     573  /* TODO: priority?? */
     574  return source;
     575}
  • window.h

    r38e2250 r7b2686d  
    7272void owl_window_resize(owl_window *w, int nlines, int ncols);
    7373
     74GSource *owl_window_redraw_source_new(void);
     75
    7476/* Standard callback functions in windowcb.c */
    7577
  • zephyr.c

    rf203cad r7655e08  
    77#include "owl.h"
    88
     9static GSource *owl_zephyr_event_source_new(int fd);
     10
     11static gboolean owl_zephyr_event_prepare(GSource *source, int *timeout);
     12static gboolean owl_zephyr_event_check(GSource *source);
     13static gboolean owl_zephyr_event_dispatch(GSource *source, GSourceFunc callback, gpointer user_data);
     14
    915#ifdef HAVE_LIBZEPHYR
    1016static GList *deferred_subs = NULL;
     
    1622
    1723Code_t ZResetAuthentication(void);
     24
     25static GSourceFuncs zephyr_event_funcs = {
     26  owl_zephyr_event_prepare,
     27  owl_zephyr_event_check,
     28  owl_zephyr_event_dispatch,
     29  NULL
     30};
    1831#endif
    1932
     
    8497  Code_t code;
    8598  char *perl;
     99  GSource *event_source;
    86100
    87101  owl_select_remove_io_dispatch(d);
     
    99113  }
    100114
    101   owl_select_add_io_dispatch(ZGetFD(), OWL_IO_READ|OWL_IO_EXCEPT, &owl_zephyr_process_events, NULL, NULL);
     115  event_source = owl_zephyr_event_source_new(ZGetFD());
     116  g_source_attach(event_source, NULL);
     117  g_source_unref(event_source);
    102118
    103119  owl_global_set_havezephyr(&g);
     
    127143  perl = owl_perlconfig_execute("BarnOwl::Zephyr::_zephyr_startup()");
    128144  g_free(perl);
    129 
    130   owl_select_add_pre_select_action(owl_zephyr_pre_select_action, NULL, NULL);
    131145}
    132146
     
    180194    if((code = ZPending()) < 0) {
    181195      owl_function_debugmsg("Error (%s) in ZPending()\n",
     196                            error_message(code));
     197      return 0;
     198    }
     199    return code;
     200  }
     201#endif
     202  return 0;
     203}
     204
     205int owl_zephyr_zqlength(void)
     206{
     207#ifdef HAVE_LIBZEPHYR
     208  Code_t code;
     209  if(owl_global_is_havezephyr(&g)) {
     210    if((code = ZQLength()) < 0) {
     211      owl_function_debugmsg("Error (%s) in ZQLength()\n",
    182212                            error_message(code));
    183213      return 0;
     
    14701500}
    14711501
    1472 void owl_zephyr_process_events(const owl_io_dispatch *d, void *data)
    1473 {
     1502typedef struct { /*noproto*/
     1503  GSource source;
     1504  GPollFD poll_fd;
     1505} owl_zephyr_event_source;
     1506
     1507static GSource *owl_zephyr_event_source_new(int fd) {
     1508  GSource *source;
     1509  owl_zephyr_event_source *event_source;
     1510
     1511  source = g_source_new(&zephyr_event_funcs, sizeof(owl_zephyr_event_source));
     1512  event_source = (owl_zephyr_event_source*) source;
     1513  event_source->poll_fd.fd = fd;
     1514  event_source->poll_fd.events = G_IO_IN | G_IO_HUP | G_IO_PRI | G_IO_ERR;
     1515  g_source_add_poll(source, &event_source->poll_fd);
     1516
     1517  return source;
     1518}
     1519
     1520static gboolean owl_zephyr_event_prepare(GSource *source, int *timeout) {
     1521  *timeout = -1;
     1522  return owl_zephyr_zqlength() > 0;
     1523}
     1524
     1525static gboolean owl_zephyr_event_check(GSource *source) {
     1526  owl_zephyr_event_source *event_source = (owl_zephyr_event_source*)source;
     1527  if (event_source->poll_fd.revents & event_source->poll_fd.events)
     1528    return owl_zephyr_zpending() > 0;
     1529  return FALSE;
     1530}
     1531
     1532static gboolean owl_zephyr_event_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) {
    14741533  _owl_zephyr_process_events();
    1475 }
    1476 
    1477 int owl_zephyr_pre_select_action(owl_ps_action *a, void *p)
    1478 {
    1479   return _owl_zephyr_process_events();
    1480 }
     1534  return TRUE;
     1535}
  • cmd.c

    rf25df21 r6a71113  
    9999
    100100char *owl_cmddict_execute_argv(const owl_cmddict *cd, const owl_context *ctx, const char *const *argv, int argc) {
    101   GString *buf = g_string_new("");
    102   int i;
    103   char *retval;
    104 
    105   /* We weren't given a command line, so fabricate a valid one. */
    106   for(i = 0; i < argc; i++) {
    107     if (i != 0)
    108       g_string_append_c(buf, ' ');
    109     owl_string_append_quoted_arg(buf, argv[i]);
    110   }
    111 
    112   retval = _owl_cmddict_execute(cd, ctx, argv, argc, buf->str);
    113 
    114   g_string_free(buf, true);
     101  char *buff;
     102  char *retval = NULL;
     103
     104  buff = g_strjoinv(" ", (char**)argv);
     105  retval = _owl_cmddict_execute(cd, ctx, argv, argc, buff);
     106  g_free(buff);
     107
    115108  return retval;
    116109}
  • perlglue.xs

    rf25df21 r6a71113  
    4343                        rv = owl_function_command(cmd);
    4444                } else {
    45                         argv = g_new(const char *, items + 1);
     45                        /* Ensure this is NULL-terminated. */
     46                        argv = g_new0(const char *, items + 1);
    4647                        argv[0] = cmd;
    4748                        for(i = 1; i < items; i++) {
  • variable.c

    rf25df21 rf203cad  
    3030        NULL, NULL, NULL, NULL, NULL, NULL }
    3131
    32 #define OWLVAR_STRING_FULL(name,default,summary,description,validate,set,get) \
    33         { name, OWL_VARIABLE_STRING, default, 0, "<string>", summary,description, NULL, \
     32#define OWLVAR_STRING_FULL(name,default,validset,summary,description,validate,set,get) \
     33        { name, OWL_VARIABLE_STRING, default, 0, validset, summary,description, NULL, \
    3434        validate, set, NULL, get, NULL, NULL }
    3535
     
    266266                 "" ),
    267267
    268   OWLVAR_STRING_FULL( "tty" /* %OwlVarStub */, "", "tty name for zephyr location", "",
     268  OWLVAR_STRING_FULL( "tty" /* %OwlVarStub */, "", "<string>", "tty name for zephyr location", "",
    269269                      NULL, owl_variable_tty_set, NULL),
    270270
     
    370370               "delete a message right as it came in.\n" ),
    371371
     372  OWLVAR_STRING_FULL( "default_exposure" /* %OwlVarStub */, "",
     373                      "none,opstaff,realm-visible,realm-announced,net-visible,net-announced",
     374                      "controls the persistent value for exposure",
     375                      "The default exposure level corresponds to the Zephyr exposure value\n"
     376                      "in ~/.zephyr.vars.  Defaults to realm-visible if there is no value in\n"
     377                      "~/.zephyr.vars.\n"
     378                      "See the description of exposure for the values this can be.",
     379                      NULL, owl_variable_default_exposure_set, owl_variable_default_exposure_get ),
     380
     381  OWLVAR_STRING_FULL( "exposure" /* %OwlVarStub */, "",
     382                      "none,opstaff,realm-visible,realm-announced,net-visible,net-announced",
     383                      "controls who can zlocate you",
     384                      "The exposure level, defaulting to the value of default_exposure,\n"
     385                      "can be one of the following (from least exposure to widest exposure,\n"
     386                      "as listed in zctl(1)):\n"
     387                      "\n"
     388                      "   none            - This completely disables Zephyr for the user. \n"
     389                      "                     The user is not registered with Zephyr.  No user\n"
     390                      "                     location information is retained by Zephyr.  No\n"
     391                      "                     login or logout announcements will be sent.  No\n"
     392                      "                     subscriptions will be entered for the user, and\n"
     393                      "                     no notices will be displayed by zwgc(1).\n"
     394                      "   opstaff         - The user is registered with Zephyr.  No login or\n"
     395                      "                     logout announcements will be sent, and location\n"
     396                      "                     information will only be visible to Operations\n"
     397                      "                     staff.  Default subscriptions and any additional\n"
     398                      "                     personal subscriptions will be entered for the\n"
     399                      "                     user.\n"
     400                      "   realm-visible   - The user is registered with Zephyr.  User\n"
     401                      "                     location information is retained by Zephyr and\n"
     402                      "                     made available only to users within the user’s\n"
     403                      "                     Kerberos realm.  No login or logout\n"
     404                      "                     announcements will be sent.  This is the system\n"
     405                      "                     default.  Default subscriptions and any\n"
     406                      "                     additional personal subscriptions will be\n"
     407                      "                     entered for the user.\n"
     408                      "   realm-announced - The user is registered with Zephyr.  User\n"
     409                      "                     location information is retained by Zephyr and\n"
     410                      "                     made available only to users authenticated\n"
     411                      "                     within the user’s Kerberos realm.  Login and\n"
     412                      "                     logout announcements will be sent, but only to\n"
     413                      "                     users within the user’s Kerberos realm who have\n"
     414                      "                     explicitly requested such via subscriptions. \n"
     415                      "                     Default subscriptions and any additional\n"
     416                      "                     personal subscriptions will be entered for the\n"
     417                      "                     user.\n"
     418                      "   net-visible     - The user is registered with Zephyr.  User\n"
     419                      "                     location information is retained by Zephyr and\n"
     420                      "                     made available to any authenticated user who\n"
     421                      "                     requests such.  Login and logout announcements\n"
     422                      "                     will be sent only to users within the user’s\n"
     423                      "                     Kerberos realm who have explicitly requested\n"
     424                      "                     such via subscriptions.  Default subscriptions\n"
     425                      "                     and any additional personal subscriptions will\n"
     426                      "                     be entered for the user.\n"
     427                      "   net-announced   - The user is registered with Zephyr.  User\n"
     428                      "                     location information is retained by Zephyr and\n"
     429                      "                     made available to any authenticated user who\n"
     430                      "                     requests such.  Login and logout announcements\n"
     431                      "                     will be sent to any user has requested such. \n"
     432                      "                     Default subscriptions and any additional\n"
     433                      "                     personal subscriptions will be entered for the\n"
     434                      "                     user.\n",
     435                      NULL, owl_variable_exposure_set, NULL /* use default for get */ ),
     436
    372437  /* This MUST be last... */
    373438  { NULL, 0, NULL, 0, NULL, NULL, NULL, NULL,
     
    470535}
    471536
     537int owl_variable_default_exposure_set(owl_variable *v, const void *newval)
     538{
     539  return owl_zephyr_set_default_exposure(newval);
     540}
     541
     542const void *owl_variable_default_exposure_get(const owl_variable *v)
     543{
     544  return owl_zephyr_get_default_exposure();
     545}
     546
     547int owl_variable_exposure_set(owl_variable *v, const void *newval)
     548{
     549  int ret = owl_zephyr_set_exposure(newval);
     550  if (ret != 0)
     551    return ret;
     552  return owl_variable_string_set_default(v, owl_zephyr_normalize_exposure(newval));
     553}
    472554
    473555/**************************************************************************/
     
    688770  }
    689771  if (msg && v->get_tostring_fn) {
    690     tostring = v->get_tostring_fn(v, v->val);
     772    tostring = v->get_tostring_fn(v, v->get_fn(v));
    691773    owl_function_makemsg("%s = '%s'", name, tostring);
    692774    g_free(tostring);
     
    726808  v = owl_dict_find_element(d, name);
    727809  if (v == NULL || !v->get_tostring_fn) return NULL;
    728   return v->get_tostring_fn(v, v->val);
     810  return v->get_tostring_fn(v, v->get_fn(v));
    729811}
    730812
  • viewwin.c

    r237d02c r4fd211f  
    150150
    151151  if (!owl_viewwin_search(v, owl_global_get_search_re(&g), consider_current, direction))
    152     owl_function_error("No more matches");
     152    owl_function_makemsg("No more matches");
    153153  return NULL;
    154154}
     
    172172  if (!owl_viewwin_search(data->v, owl_global_get_search_re(&g),
    173173                          consider_current, data->direction))
    174     owl_function_error("No matches");
     174    owl_function_makemsg("No matches");
    175175}
    176176
Note: See TracChangeset for help on using the changeset viewer.