Changes in / [f97c1a6:4c7c21f]
- Files:
-
- 1 deleted
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
Makefile.am
r3535a6e rce35060 45 45 aim.c buddy.c buddylist.c style.c errqueue.c \ 46 46 zbuddylist.c popexec.c select.c wcwidth.c \ 47 glib_compat.c mainpanel.c msgwin.c sepbar.c editcontext.c signal.c47 glib_compat.c mainpanel.c msgwin.c sepbar.c editcontext.c 48 48 49 49 NORMAL_SRCS = filterproc.c window.c windowcb.c -
aim.c
rdc1edbd r3472845 446 446 } 447 447 448 int owl_aim_process_events(aim_session_t *aimsess) 449 { 448 int owl_aim_process_events(void) 449 { 450 aim_session_t *aimsess; 450 451 aim_conn_t *waitingconn = NULL; 451 452 struct timeval tv; … … 453 454 struct owlfaim_priv *priv; 454 455 456 aimsess=owl_global_get_aimsess(&g); 455 457 priv = aimsess->aux_data; 456 458 … … 1793 1795 } 1794 1796 1795 typedef struct _owl_aim_event_source { /*noproto*/ 1796 GSource source; 1797 aim_session_t *sess; 1798 GPtrArray *fds; 1799 } owl_aim_event_source; 1800 1801 static 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 1815 static 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 1860 static 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 1873 static 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 1880 static 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 1887 static 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 1894 GSource *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 } 1797 void owl_process_aim(void) 1798 { 1799 if (owl_global_is_doaimevents(&g)) { 1800 owl_aim_process_events(); 1801 } 1802 } -
configure.ac
r1255365 r64c829a 115 115 116 116 dnl Add CFLAGS and LIBS for glib-2.0 117 PKG_CHECK_MODULES(GLIB,[glib-2.0 >= 2.12 gobject-2.0 gthread-2.0])117 PKG_CHECK_MODULES(GLIB,[glib-2.0 >= 2.12 gobject-2.0]) 118 118 119 119 AC_MSG_NOTICE([Adding glib-2.0 CFLAGS ${GLIB_CFLAGS}]) -
filterproc.c
re2cc848 r8bd190d 17 17 int err = 0; 18 18 struct pollfd fds[2]; 19 struct sigaction sig = {.sa_handler = SIG_IGN}, old; 19 20 20 21 fcntl(rfd, F_SETFL, O_NONBLOCK | fcntl(rfd, F_GETFL)); … … 26 27 fds[1].events = POLLOUT; 27 28 29 sigaction(SIGPIPE, &sig, &old); 30 28 31 while(1) { 29 32 if(out && *out) { … … 64 67 65 68 *in = g_string_free(str, err < 0); 69 sigaction(SIGPIPE, &old, NULL); 66 70 return err; 67 71 } -
functions.c
r47128d9 r3b8a563 2991 2991 i--; 2992 2992 } 2993 if (owl_global_take_interrupt(&g)) { 2993 owl_function_mask_sigint(NULL); 2994 if(owl_global_is_interrupted(&g)) { 2995 owl_global_unset_interrupted(&g); 2996 owl_function_unmask_sigint(NULL); 2994 2997 owl_function_makemsg("Search interrupted!"); 2995 2998 owl_mainwin_redisplay(owl_global_get_mainwin(&g)); 2996 2999 return; 2997 3000 } 3001 owl_function_unmask_sigint(NULL); 2998 3002 } 2999 3003 owl_mainwin_redisplay(owl_global_get_mainwin(&g)); … … 3078 3082 ret=ZLocateUser(zstr(user), &numlocs, ZAUTH); 3079 3083 3080 if (owl_global_take_interrupt(&g)) { 3084 owl_function_mask_sigint(NULL); 3085 if(owl_global_is_interrupted(&g)) { 3081 3086 interrupted = 1; 3087 owl_global_unset_interrupted(&g); 3088 owl_function_unmask_sigint(NULL); 3082 3089 owl_function_makemsg("Interrupted!"); 3083 3090 break; 3084 3091 } 3092 3093 owl_function_unmask_sigint(NULL); 3085 3094 3086 3095 if (ret!=ZERR_NONE) { … … 3487 3496 } 3488 3497 3498 void owl_function_mask_sigint(sigset_t *oldmask) { 3499 sigset_t intr; 3500 3501 sigemptyset(&intr); 3502 sigaddset(&intr, SIGINT); 3503 sigprocmask(SIG_BLOCK, &intr, oldmask); 3504 } 3505 3506 void owl_function_unmask_sigint(sigset_t *oldmask) { 3507 sigset_t intr; 3508 3509 sigemptyset(&intr); 3510 sigaddset(&intr, SIGINT); 3511 sigprocmask(SIG_UNBLOCK, &intr, oldmask); 3512 } 3513 3489 3514 void _owl_function_mark_message(const owl_message *m) 3490 3515 { -
global.c
rdc1edbd r351c535 16 16 17 17 g_type_init(); 18 g_thread_init(NULL);19 20 owl_select_init();21 18 22 19 g->lines=LINES; … … 98 95 99 96 owl_errqueue_init(&(g->errqueue)); 97 g->got_err_signal=0; 100 98 101 99 owl_zbuddylist_create(&(g->zbuddies)); … … 106 104 owl_message_init_fmtext_cache(); 107 105 owl_list_create(&(g->io_dispatch_list)); 106 owl_list_create(&(g->psa_list)); 108 107 g->timerlist = NULL; 108 g->interrupted = FALSE; 109 109 g->kill_buffer = NULL; 110 111 g->interrupt_count = 0;112 g->interrupt_lock = g_mutex_new();113 110 } 114 111 … … 347 344 348 345 void owl_global_set_resize_pending(owl_global *g) { 349 g->resizepending = true;346 g->resizepending=1; 350 347 } 351 348 … … 447 444 /* resize the screen. If lines or cols is 0 use the terminal size */ 448 445 if (!g->resizepending) return; 449 g->resizepending = false;446 g->resizepending = 0; 450 447 451 448 owl_global_get_terminal_size(&g->lines, &g->cols); … … 679 676 } 680 677 681 bool owl_global_is_doaimevents(const owl_global *g) 682 { 683 return g->aim_event_source != NULL; 678 int owl_global_is_doaimevents(const owl_global *g) 679 { 680 if (g->aim_doprocessing) return(1); 681 return(0); 684 682 } 685 683 686 684 void owl_global_set_doaimevents(owl_global *g) 687 685 { 688 if (g->aim_event_source) 689 return; 690 g->aim_event_source = owl_aim_event_source_new(owl_global_get_aimsess(g)); 691 g_source_attach(g->aim_event_source, NULL); 686 g->aim_doprocessing=1; 692 687 } 693 688 694 689 void owl_global_set_no_doaimevents(owl_global *g) 695 690 { 696 if (!g->aim_event_source) 697 return; 698 g_source_destroy(g->aim_event_source); 699 g_source_unref(g->aim_event_source); 700 g->aim_event_source = NULL; 691 g->aim_doprocessing=0; 701 692 } 702 693 … … 816 807 } 817 808 809 void owl_global_set_errsignal(owl_global *g, int signum, siginfo_t *siginfo) 810 { 811 g->got_err_signal = signum; 812 if (siginfo) { 813 g->err_signal_info = *siginfo; 814 } else { 815 siginfo_t si; 816 memset(&si, 0, sizeof(si)); 817 g->err_signal_info = si; 818 } 819 } 820 821 int owl_global_get_errsignal_and_clear(owl_global *g, siginfo_t *siginfo) 822 { 823 int signum; 824 if (siginfo && g->got_err_signal) { 825 *siginfo = g->err_signal_info; 826 } 827 signum = g->got_err_signal; 828 g->got_err_signal = 0; 829 return signum; 830 } 831 832 818 833 owl_zbuddylist *owl_global_get_zephyr_buddylist(owl_global *g) 819 834 { … … 846 861 } 847 862 863 owl_list *owl_global_get_psa_list(owl_global *g) 864 { 865 return &(g->psa_list); 866 } 867 848 868 GList **owl_global_get_timerlist(owl_global *g) 849 869 { 850 870 return &(g->timerlist); 871 } 872 873 int owl_global_is_interrupted(const owl_global *g) { 874 return g->interrupted; 875 } 876 877 void owl_global_set_interrupted(owl_global *g) { 878 g->interrupted = 1; 879 } 880 881 void owl_global_unset_interrupted(owl_global *g) { 882 g->interrupted = 0; 851 883 } 852 884 … … 916 948 g->kill_buffer = g_strndup(kill, len); 917 949 } 918 919 void owl_global_add_interrupt(owl_global *g) {920 /* TODO: This can almost certainly be done with atomic921 * operations. Whatever. */922 g_mutex_lock(g->interrupt_lock);923 g->interrupt_count++;924 g_mutex_unlock(g->interrupt_lock);925 }926 927 bool owl_global_take_interrupt(owl_global *g) {928 bool ans = false;929 g_mutex_lock(g->interrupt_lock);930 if (g->interrupt_count > 0) {931 ans = true;932 g->interrupt_count--;933 }934 g_mutex_unlock(g->interrupt_lock);935 return ans;936 } -
owl.c
r1d21d9f r3b8a563 160 160 * was ignored due to user settings or otherwise. 161 161 */ 162 staticint owl_process_message(owl_message *m) {162 int owl_process_message(owl_message *m) { 163 163 const owl_filter *f; 164 164 /* if this message it on the puntlist, nuke it and continue */ … … 245 245 } 246 246 247 static gboolean owl_process_messages_prepare(GSource *source, int *timeout) {248 *timeout = -1;249 return owl_global_messagequeue_pending(&g);250 }251 252 static gboolean owl_process_messages_check(GSource *source) {253 return owl_global_messagequeue_pending(&g);254 }255 256 247 /* 257 248 * 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. 258 250 */ 259 static gboolean owl_process_messages_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { 251 int owl_process_messages(owl_ps_action *d, void *p) 252 { 260 253 int newmsgs=0; 261 254 int followlast = owl_global_should_followlast(&g); … … 281 274 owl_mainwin_redisplay(owl_global_get_mainwin(&g)); 282 275 } 283 return TRUE; 284 } 285 286 static GSourceFuncs owl_process_messages_funcs = { 287 owl_process_messages_prepare, 288 owl_process_messages_check, 289 owl_process_messages_dispatch, 290 NULL 291 }; 292 293 void 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 } 276 return newmsgs; 302 277 } 303 278 … … 359 334 } 360 335 361 static 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) { 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 */ 366 342 owl_function_resize(); 367 } else if (sig == SIGTERM || sig == SIGHUP) { 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) { 368 348 owl_function_quit(); 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 376 static 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 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 } 395 368 396 369 void owl_register_signal_handlers(void) { 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); 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); 425 385 } 426 386 … … 475 435 476 436 #endif /* OWL_STDERR_REDIR */ 437 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 we 447 * still overflow, this be useless work. With 8-colors, we get 64 448 * pairs. With 256-colors, we get 32768 pairs with ext-colors 449 * support and 256 otherwise. */ 450 cpmgr = owl_global_get_colorpair_mgr(&g); 451 if (cpmgr->overflow) { 452 owl_function_debugmsg("colorpairs: used all %d pairs; reset pairs and redraw.", 453 owl_util_get_colorpairs()); 454 owl_fmtext_reset_colorpairs(cpmgr); 455 owl_function_full_redisplay(); 456 owl_window_redraw_scheduled(); 457 } 458 return 0; 459 } 460 477 461 478 462 int main(int argc, char **argv, char **env) … … 484 468 const char *dir; 485 469 owl_options opts; 486 GSource *source;487 470 488 471 if (!GLIB_CHECK_VERSION (2, 12, 0)) … … 499 482 g.load_initial_subs = opts.load_initial_subs; 500 483 484 owl_register_signal_handlers(); 501 485 owl_start_curses(); 502 486 … … 509 493 g_strfreev(argv_copy); 510 494 owl_global_set_haveaim(&g); 511 512 owl_register_signal_handlers();513 495 514 496 /* register STDIN dispatch; throw away return, we won't need it */ … … 603 585 owl_global_push_context(&g, OWL_CTX_INTERACTIVE|OWL_CTX_RECV, NULL, "recv", NULL); 604 586 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); 587 owl_select_add_pre_select_action(owl_refresh_pre_select_action, NULL, NULL); 588 owl_select_add_pre_select_action(owl_process_messages, NULL, NULL); 589 owl_select_add_pre_select_action(owl_errsignal_pre_select_action, NULL, NULL); 612 590 613 591 owl_function_debugmsg("startup: entering main loop"); … … 616 594 /* Shut down everything. */ 617 595 owl_zephyr_shutdown(); 618 owl_signal_shutdown();619 596 owl_shutdown_curses(); 620 597 return 0; -
owl.h
rdc1edbd rede073c 552 552 void (*destroy)(const struct _owl_io_dispatch *); /* Destructor */ 553 553 void *data; 554 GPollFD pollfd;555 554 } owl_io_dispatch; 555 556 typedef struct _owl_ps_action { 557 int needs_gc; 558 int (*callback)(struct _owl_ps_action *, void *); 559 void (*destroy)(struct _owl_ps_action *); 560 void *data; 561 } owl_ps_action; 556 562 557 563 typedef struct _owl_popexec { … … 562 568 const owl_io_dispatch *dispatch; 563 569 } owl_popexec; 570 571 typedef struct _OwlGlobalNotifier OwlGlobalNotifier; 564 572 565 573 typedef struct _owl_global { … … 587 595 gulong typwin_erase_id; 588 596 int rightshift; 589 boolresizepending;597 volatile sig_atomic_t resizepending; 590 598 char *homedir; 591 599 char *confdir; … … 610 618 aim_conn_t bosconn; 611 619 int aim_loggedin; /* true if currently logged into AIM */ 612 GSource *aim_event_source; /* where we get our AIM events from*/620 int aim_doprocessing; /* true if we should process AIM events (like pending login) */ 613 621 char *aim_screenname; /* currently logged in AIM screen name */ 614 622 char *aim_screenname_for_filters; /* currently logged in AIM screen name */ … … 620 628 int haveaim; 621 629 int ignoreaimlogin; 630 volatile sig_atomic_t got_err_signal; /* 1 if we got an unexpected signal */ 631 volatile siginfo_t err_signal_info; 622 632 owl_zbuddylist zbuddies; 623 633 GList *zaldlist; … … 625 635 struct termios startup_tio; 626 636 owl_list io_dispatch_list; 637 owl_list psa_list; 627 638 GList *timerlist; 628 639 owl_timer *aim_nop_timer; 629 640 int load_initial_subs; 641 volatile sig_atomic_t interrupted; 630 642 FILE *debug_file; 631 643 char *kill_buffer; 632 int interrupt_count;633 GMutex *interrupt_lock;634 644 } owl_global; 635 645 -
select.c
rba12b44 rfb96152 1 1 #include "owl.h" 2 3 static GMainLoop *loop = NULL; 4 static GMainContext *context; 2 #include <sys/stat.h> 3 5 4 static int dispatch_active = 0; 6 7 static GSource *owl_timer_source; 8 static GSource *owl_io_dispatch_source; 9 10 static int _owl_select_timer_cmp(const owl_timer *t1, const owl_timer *t2) { 5 static int psa_active = 0; 6 static int loop_active = 0; 7 8 int _owl_select_timer_cmp(const owl_timer *t1, const owl_timer *t2) { 11 9 return t1->time - t2->time; 10 } 11 12 int _owl_select_timer_eq(const owl_timer *t1, const owl_timer *t2) { 13 return t1 == t2; 12 14 } 13 15 … … 42 44 } 43 45 44 static gboolean owl_timer_prepare(GSource *source, int *timeout) { 46 void owl_select_process_timers(struct timespec *timeout) 47 { 48 time_t now = time(NULL); 45 49 GList **timers = owl_global_get_timerlist(&g); 46 GTimeVal now; 47 48 /* TODO: In the far /far/ future, g_source_get_time is what the cool 49 * kids use to get system monotonic time. */ 50 g_source_get_current_time(source, &now); 51 52 /* FIXME: bother with millisecond accuracy now that we can? */ 53 if (*timers) { 54 owl_timer *t = (*timers)->data; 55 *timeout = t->time - now.tv_sec; 56 if (*timeout <= 0) { 57 *timeout = 0; 58 return TRUE; 59 } 60 if (*timeout > 60 * 1000) 61 *timeout = 60 * 1000; 62 } else { 63 *timeout = 60 * 1000; 64 } 65 return FALSE; 66 } 67 68 static gboolean owl_timer_check(GSource *source) { 69 GList **timers = owl_global_get_timerlist(&g); 70 GTimeVal now; 71 72 /* TODO: In the far /far/ future, g_source_get_time is what the cool 73 * kids use to get system monotonic time. */ 74 g_source_get_current_time(source, &now); 75 76 /* FIXME: bother with millisecond accuracy now that we can? */ 77 if (*timers) { 78 owl_timer *t = (*timers)->data; 79 return t->time >= now.tv_sec; 80 } 81 return FALSE; 82 } 83 84 85 static gboolean owl_timer_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { 86 GList **timers = owl_global_get_timerlist(&g); 87 GTimeVal now; 88 89 /* TODO: In the far /far/ future, g_source_get_time is what the cool 90 * kids use to get system monotonic time. */ 91 g_source_get_current_time(source, &now); 92 93 /* FIXME: bother with millisecond accuracy now that we can? */ 50 94 51 while(*timers) { 95 52 owl_timer *t = (*timers)->data; 96 53 int remove = 0; 97 54 98 if(t->time > now .tv_sec)55 if(t->time > now) 99 56 break; 100 57 101 58 /* Reschedule if appropriate */ 102 59 if(t->interval > 0) { 103 t->time = now .tv_sec+ t->interval;60 t->time = now + t->interval; 104 61 *timers = g_list_remove(*timers, t); 105 62 *timers = g_list_insert_sorted(*timers, t, … … 115 72 } 116 73 } 117 return TRUE; 118 } 119 120 static GSourceFuncs owl_timer_funcs = { 121 owl_timer_prepare, 122 owl_timer_check, 123 owl_timer_dispatch, 124 NULL 125 }; 126 74 75 if(*timers) { 76 owl_timer *t = (*timers)->data; 77 timeout->tv_sec = t->time - now; 78 if (timeout->tv_sec > 60) 79 timeout->tv_sec = 60; 80 } else { 81 timeout->tv_sec = 60; 82 } 83 84 timeout->tv_nsec = 0; 85 } 127 86 128 87 static const owl_io_dispatch *owl_select_find_io_dispatch_by_fd(const int fd) … … 170 129 if (d->destroy) 171 130 d->destroy(d); 172 g_source_remove_poll(owl_io_dispatch_source, &d->pollfd);173 131 g_free(d); 174 132 } … … 177 135 } 178 136 179 staticvoid owl_select_io_dispatch_gc(void)137 void owl_select_io_dispatch_gc(void) 180 138 { 181 139 int i; … … 212 170 d->data = data; 213 171 214 /* TODO: Allow changing fd and mode in the middle? Probably don't care... */215 d->pollfd.fd = fd;216 d->pollfd.events = 0;217 if (d->mode & OWL_IO_READ)218 d->pollfd.events |= G_IO_IN | G_IO_HUP | G_IO_ERR;219 if (d->mode & OWL_IO_WRITE)220 d->pollfd.events |= G_IO_OUT | G_IO_ERR;221 if (d->mode & OWL_IO_EXCEPT)222 d->pollfd.events |= G_IO_PRI | G_IO_ERR;223 g_source_add_poll(owl_io_dispatch_source, &d->pollfd);224 225 226 172 owl_select_remove_io_dispatch(owl_select_find_io_dispatch_by_fd(fd)); 227 173 owl_list_append_element(dl, d); … … 230 176 } 231 177 232 static gboolean owl_io_dispatch_prepare(GSource *source, int *timeout) { 233 *timeout = -1; 234 return FALSE; 235 } 236 237 static gboolean owl_io_dispatch_check(GSource *source) { 238 int i, len; 239 const owl_list *dl; 240 241 dl = owl_global_get_io_dispatch_list(&g); 242 len = owl_list_get_size(dl); 243 for(i = 0; i < len; i++) { 244 const owl_io_dispatch *d = owl_list_get_element(dl, i); 245 if (d->pollfd.revents & d->pollfd.events) 246 return TRUE; 247 } 248 return FALSE; 249 } 250 251 static gboolean owl_io_dispatch_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { 252 int i, len; 253 const owl_list *dl; 254 255 dispatch_active = 1; 256 dl = owl_global_get_io_dispatch_list(&g); 178 int owl_select_prepare_io_dispatch_fd_sets(fd_set *rfds, fd_set *wfds, fd_set *efds) { 179 int i, len, max_fd; 180 owl_io_dispatch *d; 181 owl_list *dl = owl_global_get_io_dispatch_list(&g); 182 183 max_fd = 0; 257 184 len = owl_list_get_size(dl); 258 185 for (i = 0; i < len; i++) { 259 owl_io_dispatch *d = owl_list_get_element(dl, i); 260 if ((d->pollfd.revents & d->pollfd.events) && d->callback != NULL) { 186 d = owl_list_get_element(dl, i); 187 if (d->mode & (OWL_IO_READ | OWL_IO_WRITE | OWL_IO_EXCEPT)) { 188 if (max_fd < d->fd) max_fd = d->fd; 189 if (d->mode & OWL_IO_READ) FD_SET(d->fd, rfds); 190 if (d->mode & OWL_IO_WRITE) FD_SET(d->fd, wfds); 191 if (d->mode & OWL_IO_EXCEPT) FD_SET(d->fd, efds); 192 } 193 } 194 return max_fd + 1; 195 } 196 197 void owl_select_io_dispatch(const fd_set *rfds, const fd_set *wfds, const fd_set *efds, const int max_fd) 198 { 199 int i, len; 200 owl_io_dispatch *d; 201 owl_list *dl = owl_global_get_io_dispatch_list(&g); 202 203 dispatch_active = 1; 204 len = owl_list_get_size(dl); 205 for (i = 0; i < len; i++) { 206 d = owl_list_get_element(dl, i); 207 if (d->fd < max_fd && d->callback != NULL && 208 ((d->mode & OWL_IO_READ && FD_ISSET(d->fd, rfds)) || 209 (d->mode & OWL_IO_WRITE && FD_ISSET(d->fd, wfds)) || 210 (d->mode & OWL_IO_EXCEPT && FD_ISSET(d->fd, efds)))) { 261 211 d->callback(d, d->data); 262 212 } … … 264 214 dispatch_active = 0; 265 215 owl_select_io_dispatch_gc(); 266 267 return TRUE; 268 } 269 270 static GSourceFuncs owl_io_dispatch_funcs = { 271 owl_io_dispatch_prepare, 272 owl_io_dispatch_check, 273 owl_io_dispatch_dispatch, 274 NULL 275 }; 216 } 276 217 277 218 int owl_select_add_perl_io_dispatch(int fd, int mode, SV *cb) … … 297 238 } 298 239 299 void owl_select_init(void) 300 { 301 owl_timer_source = g_source_new(&owl_timer_funcs, sizeof(GSource)); 302 g_source_attach(owl_timer_source, NULL); 303 304 owl_io_dispatch_source = g_source_new(&owl_io_dispatch_funcs, sizeof(GSource)); 305 g_source_attach(owl_io_dispatch_source, NULL); 306 } 307 308 void owl_select_run_loop(void) 309 { 310 context = g_main_context_default(); 311 loop = g_main_loop_new(context, FALSE); 312 g_main_loop_run(loop); 313 } 314 315 void owl_select_quit_loop(void) 316 { 317 if (loop) { 318 g_main_loop_quit(loop); 319 loop = NULL; 320 } 321 } 322 323 #if 0 324 /* FIXME: Reimplement this check in the glib world. */ 240 int owl_select_aim_hack(fd_set *rfds, fd_set *wfds) 241 { 242 aim_conn_t *cur; 243 aim_session_t *sess; 244 int max_fd; 245 246 max_fd = 0; 247 sess = owl_global_get_aimsess(&g); 248 for (cur = sess->connlist; cur; cur = cur->next) { 249 if (cur->fd != -1) { 250 FD_SET(cur->fd, rfds); 251 if (cur->status & AIM_CONN_STATUS_INPROGRESS) { 252 /* Yes, we're checking writable sockets here. Without it, AIM 253 login is really slow. */ 254 FD_SET(cur->fd, wfds); 255 } 256 257 if (cur->fd > max_fd) 258 max_fd = cur->fd; 259 } 260 } 261 return max_fd; 262 } 263 264 void owl_process_input_char(owl_input j) 265 { 266 int ret; 267 268 owl_global_set_lastinputtime(&g, time(NULL)); 269 ret = owl_keyhandler_process(owl_global_get_keyhandler(&g), j); 270 if (ret!=0 && ret!=1) { 271 owl_function_makemsg("Unable to handle keypress"); 272 } 273 } 274 275 void owl_select_mask_signals(sigset_t *oldmask) { 276 sigset_t set; 277 278 sigemptyset(&set); 279 sigaddset(&set, SIGWINCH); 280 sigaddset(&set, SIGALRM); 281 sigaddset(&set, SIGPIPE); 282 sigaddset(&set, SIGTERM); 283 sigaddset(&set, SIGHUP); 284 sigaddset(&set, SIGINT); 285 sigprocmask(SIG_BLOCK, &set, oldmask); 286 } 287 288 void owl_select_handle_intr(sigset_t *restore) 289 { 290 owl_input in; 291 292 owl_global_unset_interrupted(&g); 293 294 sigprocmask(SIG_SETMASK, restore, NULL); 295 296 in.ch = in.uch = owl_global_get_startup_tio(&g)->c_cc[VINTR]; 297 owl_process_input_char(in); 298 } 299 300 owl_ps_action *owl_select_add_pre_select_action(int (*cb)(owl_ps_action *, void *), void (*destroy)(owl_ps_action *), void *data) 301 { 302 owl_ps_action *a = g_new(owl_ps_action, 1); 303 owl_list *psa_list = owl_global_get_psa_list(&g); 304 a->needs_gc = 0; 305 a->callback = cb; 306 a->destroy = destroy; 307 a->data = data; 308 owl_list_append_element(psa_list, a); 309 return a; 310 } 311 312 void owl_select_psa_gc(void) 313 { 314 int i; 315 owl_list *psa_list; 316 owl_ps_action *a; 317 318 psa_list = owl_global_get_psa_list(&g); 319 for (i = owl_list_get_size(psa_list) - 1; i >= 0; i--) { 320 a = owl_list_get_element(psa_list, i); 321 if (a->needs_gc) { 322 owl_list_remove_element(psa_list, i); 323 if (a->destroy) { 324 a->destroy(a); 325 } 326 g_free(a); 327 } 328 } 329 } 330 331 void owl_select_remove_pre_select_action(owl_ps_action *a) 332 { 333 a->needs_gc = 1; 334 if (!psa_active) 335 owl_select_psa_gc(); 336 } 337 338 int owl_select_do_pre_select_actions(void) 339 { 340 int i, len, ret; 341 owl_list *psa_list; 342 343 psa_active = 1; 344 ret = 0; 345 psa_list = owl_global_get_psa_list(&g); 346 len = owl_list_get_size(psa_list); 347 for (i = 0; i < len; i++) { 348 owl_ps_action *a = owl_list_get_element(psa_list, i); 349 if (a->callback != NULL && a->callback(a, a->data)) { 350 ret = 1; 351 } 352 } 353 psa_active = 0; 354 owl_select_psa_gc(); 355 return ret; 356 } 357 325 358 static void owl_select_prune_bad_fds(void) { 326 359 owl_list *dl = owl_global_get_io_dispatch_list(&g); … … 339 372 owl_select_io_dispatch_gc(); 340 373 } 341 #endif 342 343 typedef struct _owl_task { /*noproto*/ 344 void (*cb)(void *); 345 void *cbdata; 346 void (*destroy_cbdata)(void *); 347 } owl_task; 348 349 static gboolean _run_task(gpointer data) 350 { 351 owl_task *t = data; 352 if (t->cb) 353 t->cb(t->cbdata); 354 return FALSE; 355 } 356 357 static void _destroy_task(void *data) 358 { 359 owl_task *t = data; 360 if (t->destroy_cbdata) 361 t->destroy_cbdata(t->cbdata); 362 g_free(t); 363 } 364 365 void owl_select_post_task(void (*cb)(void*), void *cbdata, void (*destroy_cbdata)(void*)) 366 { 367 GSource *source = g_idle_source_new(); 368 owl_task *t = g_new0(owl_task, 1); 369 t->cb = cb; 370 t->cbdata = cbdata; 371 t->destroy_cbdata = destroy_cbdata; 372 g_source_set_priority(source, G_PRIORITY_DEFAULT); 373 g_source_set_callback(source, _run_task, t, _destroy_task); 374 g_source_attach(source, context); 375 g_source_unref(source); 376 } 374 375 void owl_select(void) 376 { 377 int i, max_fd, max_fd2, aim_done, ret; 378 fd_set r; 379 fd_set w; 380 fd_set e; 381 fd_set aim_rfds, aim_wfds; 382 struct timespec timeout; 383 sigset_t mask; 384 385 owl_select_process_timers(&timeout); 386 387 owl_select_mask_signals(&mask); 388 389 if(owl_global_is_interrupted(&g)) { 390 owl_select_handle_intr(&mask); 391 return; 392 } 393 FD_ZERO(&r); 394 FD_ZERO(&w); 395 FD_ZERO(&e); 396 397 max_fd = owl_select_prepare_io_dispatch_fd_sets(&r, &w, &e); 398 399 /* AIM HACK: 400 * 401 * The problem - I'm not sure where to hook into the owl/faim 402 * interface to keep track of when the AIM socket(s) open and 403 * close. In particular, the bosconn thing throws me off. So, 404 * rather than register particular dispatchers for AIM, I look up 405 * the relevant FDs and add them to select's watch lists, then 406 * check for them individually before moving on to the other 407 * dispatchers. --asedeno 408 */ 409 aim_done = 1; 410 FD_ZERO(&aim_rfds); 411 FD_ZERO(&aim_wfds); 412 if (owl_global_is_doaimevents(&g)) { 413 aim_done = 0; 414 max_fd2 = owl_select_aim_hack(&aim_rfds, &aim_wfds); 415 if (max_fd < max_fd2) max_fd = max_fd2; 416 for(i = 0; i <= max_fd2; i++) { 417 if (FD_ISSET(i, &aim_rfds)) { 418 FD_SET(i, &r); 419 FD_SET(i, &e); 420 } 421 if (FD_ISSET(i, &aim_wfds)) { 422 FD_SET(i, &w); 423 FD_SET(i, &e); 424 } 425 } 426 } 427 /* END AIM HACK */ 428 429 if (owl_select_do_pre_select_actions()) { 430 timeout.tv_sec = 0; 431 timeout.tv_nsec = 0; 432 } 433 434 ret = pselect(max_fd+1, &r, &w, &e, &timeout, &mask); 435 436 if(ret < 0) { 437 if (errno == EINTR) { 438 if(owl_global_is_interrupted(&g)) { 439 owl_select_handle_intr(NULL); 440 } 441 } else if (errno == EBADF) { 442 /* Perl must have closed an fd on us without removing it first. */ 443 owl_select_prune_bad_fds(); 444 } 445 sigprocmask(SIG_SETMASK, &mask, NULL); 446 return; 447 } 448 449 sigprocmask(SIG_SETMASK, &mask, NULL); 450 451 if(ret > 0) { 452 /* AIM HACK: process all AIM events at once. */ 453 for(i = 0; !aim_done && i <= max_fd; i++) { 454 if (FD_ISSET(i, &r) || FD_ISSET(i, &w) || FD_ISSET(i, &e)) { 455 if (FD_ISSET(i, &aim_rfds) || FD_ISSET(i, &aim_wfds)) { 456 owl_process_aim(); 457 aim_done = 1; 458 } 459 } 460 } 461 owl_select_io_dispatch(&r, &w, &e, max_fd); 462 } 463 } 464 465 void owl_select_run_loop(void) 466 { 467 loop_active = 1; 468 while (loop_active) { 469 owl_select(); 470 } 471 } 472 473 void owl_select_quit_loop(void) 474 { 475 loop_active = 0; 476 } -
window.c
r4cc49bc rb31f1c9 524 524 owl_window_set_position(w, nlines, ncols, w->begin_y, w->begin_x); 525 525 } 526 527 /** Redrawing main loop hooks **/528 529 static bool _owl_window_should_redraw(void) {530 return g.resizepending || owl_window_get_screen()->dirty_subtree;531 }532 533 static gboolean _owl_window_redraw_prepare(GSource *source, int *timeout) {534 *timeout = -1;535 return _owl_window_should_redraw();536 }537 538 static gboolean _owl_window_redraw_check(GSource *source) {539 return _owl_window_should_redraw();540 }541 542 static 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 we550 * still overflow, this be useless work. With 8-colors, we get 64551 * pairs. With 256-colors, we get 32768 pairs with ext-colors552 * support and 256 otherwise. */553 cpmgr = owl_global_get_colorpair_mgr(&g);554 if (cpmgr->overflow) {555 owl_function_debugmsg("colorpairs: used all %d pairs; reset pairs and redraw.",556 owl_util_get_colorpairs());557 owl_fmtext_reset_colorpairs(cpmgr);558 owl_function_full_redisplay();559 owl_window_redraw_scheduled();560 }561 return TRUE;562 }563 564 static GSourceFuncs redraw_funcs = {565 _owl_window_redraw_prepare,566 _owl_window_redraw_check,567 _owl_window_redraw_dispatch,568 NULL569 };570 571 GSource *owl_window_redraw_source_new(void) {572 GSource *source;573 source = g_source_new(&redraw_funcs, sizeof(GSource));574 /* TODO: priority?? */575 return source;576 } -
window.h
r4cc49bc r38e2250 72 72 void owl_window_resize(owl_window *w, int nlines, int ncols); 73 73 74 GSource *owl_window_redraw_source_new(void);75 76 74 /* Standard callback functions in windowcb.c */ 77 75 -
zephyr.c
r959cb85 r3b8a563 7 7 #include "owl.h" 8 8 9 static GSource *owl_zephyr_event_source_new(int fd);10 11 static gboolean owl_zephyr_event_prepare(GSource *source, int *timeout);12 static gboolean owl_zephyr_event_check(GSource *source);13 static gboolean owl_zephyr_event_dispatch(GSource *source, GSourceFunc callback, gpointer user_data);14 15 9 #ifdef HAVE_LIBZEPHYR 16 10 static GList *deferred_subs = NULL; … … 22 16 23 17 Code_t ZResetAuthentication(void); 24 25 static GSourceFuncs zephyr_event_funcs = {26 owl_zephyr_event_prepare,27 owl_zephyr_event_check,28 owl_zephyr_event_dispatch,29 NULL30 };31 18 #endif 32 19 … … 97 84 Code_t code; 98 85 char *perl; 99 GSource *event_source;100 86 101 87 owl_select_remove_io_dispatch(d); … … 113 99 } 114 100 115 event_source = owl_zephyr_event_source_new(ZGetFD()); 116 g_source_attach(event_source, NULL); 117 g_source_unref(event_source); 101 owl_select_add_io_dispatch(ZGetFD(), OWL_IO_READ|OWL_IO_EXCEPT, &owl_zephyr_process_events, NULL, NULL); 118 102 119 103 owl_global_set_havezephyr(&g); … … 143 127 perl = owl_perlconfig_execute("BarnOwl::Zephyr::_zephyr_startup()"); 144 128 g_free(perl); 129 130 owl_select_add_pre_select_action(owl_zephyr_pre_select_action, NULL, NULL); 145 131 } 146 132 … … 194 180 if((code = ZPending()) < 0) { 195 181 owl_function_debugmsg("Error (%s) in ZPending()\n", 196 error_message(code));197 return 0;198 }199 return code;200 }201 #endif202 return 0;203 }204 205 int owl_zephyr_zqlength(void)206 {207 #ifdef HAVE_LIBZEPHYR208 Code_t code;209 if(owl_global_is_havezephyr(&g)) {210 if((code = ZQLength()) < 0) {211 owl_function_debugmsg("Error (%s) in ZQLength()\n",212 182 error_message(code)); 213 183 return 0; … … 1499 1469 } 1500 1470 1501 typedef struct { /*noproto*/ 1502 GSource source; 1503 GPollFD poll_fd; 1504 } owl_zephyr_event_source; 1505 1506 static GSource *owl_zephyr_event_source_new(int fd) { 1507 GSource *source; 1508 owl_zephyr_event_source *event_source; 1509 1510 source = g_source_new(&zephyr_event_funcs, sizeof(owl_zephyr_event_source)); 1511 event_source = (owl_zephyr_event_source*) source; 1512 event_source->poll_fd.fd = fd; 1513 event_source->poll_fd.events = G_IO_IN | G_IO_HUP | G_IO_PRI | G_IO_ERR; 1514 g_source_add_poll(source, &event_source->poll_fd); 1515 1516 return source; 1517 } 1518 1519 static gboolean owl_zephyr_event_prepare(GSource *source, int *timeout) { 1520 *timeout = -1; 1521 return owl_zephyr_zqlength() > 0; 1522 } 1523 1524 static gboolean owl_zephyr_event_check(GSource *source) { 1525 owl_zephyr_event_source *event_source = (owl_zephyr_event_source*)source; 1526 if (event_source->poll_fd.revents & event_source->poll_fd.events) 1527 return owl_zephyr_zpending() > 0; 1528 return FALSE; 1529 } 1530 1531 static gboolean owl_zephyr_event_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { 1471 void owl_zephyr_process_events(const owl_io_dispatch *d, void *data) 1472 { 1532 1473 _owl_zephyr_process_events(); 1533 return TRUE; 1534 } 1474 } 1475 1476 int owl_zephyr_pre_select_action(owl_ps_action *a, void *p) 1477 { 1478 return _owl_zephyr_process_events(); 1479 }
Note: See TracChangeset
for help on using the changeset viewer.