source: owl.c @ 8fa9562

barnowl_perlaimdebianrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 8fa9562 was 8fa9562, checked in by Alejandro R. Sedeño <asedeno@mit.edu>, 17 years ago
Added background color support to owl. If we run out of color pairs during a painting of the screen, further background colors will be silently dropped. I'm hoping this doesn't happen often. The used pair list is reset with each draw, so only what's actually on screen matters.
  • Property mode set to 100644
File size: 25.5 KB
Line 
1/*  Copyright (c) 2004 James Kretchmar. All rights reserved.
2 *
3 *  Redistribution and use in source and binary forms, with or without
4 *  modification, are permitted provided that the following conditions are
5 *  met:
6 * 
7 *    * Redistributions of source code must retain the above copyright
8 *      notice, this list of conditions and the following disclaimer.
9 * 
10 *    * Redistributions in binary form must reproduce the above copyright
11 *      notice, this list of conditions and the following disclaimer in
12 *      the documentation and/or other materials provided with the
13 *      distribution.
14 * 
15 *    * Redistributions in any form must be accompanied by information on
16 *      how to obtain complete source code for the Owl software and any
17 *      accompanying software that uses the Owl software. The source code
18 *      must either be included in the distribution or be available for no
19 *      more than the cost of distribution plus a nominal fee, and must be
20 *      freely redistributable under reasonable conditions. For an
21 *      executable file, complete source code means the source code for
22 *      all modules it contains. It does not include source code for
23 *      modules or files that typically accompany the major components of
24 *      the operating system on which the executable file runs.
25 * 
26 *
27 *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28 *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29 *  WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
30 *  NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
31 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
34 *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
36 *  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
37 *  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 */
39
40#include <stdio.h>
41#include <unistd.h>
42#include <stdlib.h>
43#include <string.h>
44#include <signal.h>
45#include <time.h>
46#include <sys/param.h>
47#include <sys/types.h>
48#include <termios.h>
49#include <sys/stat.h>
50#include "owl.h"
51
52#if OWL_STDERR_REDIR
53#ifdef HAVE_SYS_IOCTL_H
54#include <sys/ioctl.h>
55#endif
56#ifdef HAVE_SYS_FILIO_H
57#include <sys/filio.h>
58#endif
59int stderr_replace(void);
60#endif
61
62static const char fileIdent[] = "$Id$";
63
64owl_global g;
65
66int main(int argc, char **argv, char **env)
67{
68  WINDOW *recwin, *sepwin, *typwin, *msgwin;
69  owl_editwin *tw;
70  owl_popwin *pw;
71  int j, ret, initialsubs, debug, argcsave, followlast;
72  int newmsgs, zpendcount, nexttimediff;
73  struct sigaction sigact;
74  char *configfile, *tty, *perlout, *perlerr, **argvsave, buff[LINE], startupmsg[LINE];
75  owl_filter *f;
76  owl_style *s;
77  time_t nexttime, now;
78  struct tm *today;
79  char *dir;
80  struct termios tio;
81#ifdef HAVE_LIBZEPHYR
82  ZNotice_t notice;
83#endif
84#if OWL_STDERR_REDIR
85  int newstderr;
86#endif
87
88  argcsave=argc;
89  argvsave=argv;
90  configfile=NULL;
91  tty=NULL;
92  debug=0;
93  initialsubs=1;
94  if (argc>0) {
95    argv++;
96    argc--;
97  }
98  while (argc>0) {
99    if (!strcmp(argv[0], "-n")) {
100      initialsubs=0;
101      argv++;
102      argc--;
103    } else if (!strcmp(argv[0], "-c")) {
104      if (argc<2) {
105        fprintf(stderr, "Too few arguments to -c\n");
106        usage();
107        exit(1);
108      }
109      configfile=argv[1];
110      argv+=2;
111      argc-=2;
112    } else if (!strcmp(argv[0], "-t")) {
113      if (argc<2) {
114        fprintf(stderr, "Too few arguments to -t\n");
115        usage();
116        exit(1);
117      }
118      tty=argv[1];
119      argv+=2;
120      argc-=2;
121    } else if (!strcmp(argv[0], "-d")) {
122      debug=1;
123      argv++;
124      argc--;
125    } else if (!strcmp(argv[0], "-D")) {
126      debug=1;
127      unlink(OWL_DEBUG_FILE);
128      argv++;
129      argc--;
130    } else if (!strcmp(argv[0], "-v")) {
131      printf("This is owl version %s\n", OWL_VERSION_STRING);
132      exit(0);
133    } else {
134      fprintf(stderr, "Uknown argument\n");
135      usage();       
136      exit(1);
137    }
138  }
139
140  owl_function_debugmsg("startup: Finished parsing arguments");
141
142  /* signal handler */
143  /*sigact.sa_handler=sig_handler;*/
144  sigact.sa_sigaction=sig_handler;
145  sigemptyset(&sigact.sa_mask);
146  sigact.sa_flags=SA_SIGINFO;
147  sigaction(SIGWINCH, &sigact, NULL);
148  sigaction(SIGALRM, &sigact, NULL);
149  sigaction(SIGPIPE, &sigact, NULL);
150  sigaction(SIGTERM, &sigact, NULL);
151  sigaction(SIGHUP, &sigact, NULL);
152
153  /* save initial terminal settings */
154  tcgetattr(0, owl_global_get_startup_tio(&g));
155
156  /* turn ISTRIP off */
157  tcgetattr(0, &tio);
158  tio.c_iflag &= ~ISTRIP;
159  tcsetattr(0, TCSAFLUSH, &tio);
160
161  /* screen init */
162  if (!getenv("TERMINFO")) {
163    sprintf(buff, "TERMINFO=%s", TERMINFO);
164    putenv(buff);
165    owl_function_debugmsg("startup: setting TERMINFO to %s", TERMINFO);
166  } else {
167    owl_function_debugmsg("startup: leaving TERMINFO as %s from envrionment", getenv("TERMINFO"));
168  }
169  initscr();
170  start_color();
171#ifdef HAVE_USE_DEFAULT_COLORS
172  use_default_colors();
173#endif
174  raw();
175  noecho();
176
177  /* define simple color pairs */
178  if (has_colors() && COLOR_PAIRS>=8) {
179    int bg = COLOR_BLACK;
180#ifdef HAVE_USE_DEFAULT_COLORS
181    bg = -1;
182#endif
183    init_pair(OWL_COLOR_BLACK,   COLOR_BLACK,   bg);
184    init_pair(OWL_COLOR_RED,     COLOR_RED,     bg);
185    init_pair(OWL_COLOR_GREEN,   COLOR_GREEN,   bg);
186    init_pair(OWL_COLOR_YELLOW,  COLOR_YELLOW,  bg);
187    init_pair(OWL_COLOR_BLUE,    COLOR_BLUE,    bg);
188    init_pair(OWL_COLOR_MAGENTA, COLOR_MAGENTA, bg);
189    init_pair(OWL_COLOR_CYAN,    COLOR_CYAN,    bg);
190    init_pair(OWL_COLOR_WHITE,   COLOR_WHITE,   bg);
191  }
192
193  /* owl global init */
194  owl_global_init(&g);
195    if (debug) owl_global_set_debug_on(&g);
196  owl_function_debugmsg("startup: first available debugging message");
197  owl_global_set_startupargs(&g, argcsave, argvsave);
198  owl_global_set_haveaim(&g);
199
200#ifdef HAVE_LIBZEPHYR
201  /* zephyr init */
202  ret=owl_zephyr_initialize();
203  if (!ret)
204      owl_global_set_havezephyr(&g);
205#endif
206
207#if OWL_STDERR_REDIR
208  /* Do this only after we've started curses up... */
209  owl_function_debugmsg("startup: doing stderr redirection");
210  newstderr = stderr_replace();
211  owl_muxevents_add(owl_global_get_muxevents(&g), newstderr, OWL_MUX_READ,
212                    stderr_redirect_handler, NULL);
213#endif   
214
215  /* create the owl directory, in case it does not exist */
216  owl_function_debugmsg("startup: creating owl directory, if not present");
217  dir=owl_sprintf("%s/%s", owl_global_get_homedir(&g), OWL_CONFIG_DIR);
218  mkdir(dir, S_IRWXU);
219  owl_free(dir);
220
221  /* set the tty, either from the command line, or by figuring it out */
222  owl_function_debugmsg("startup: setting tty name");
223  if (tty) {
224    owl_global_set_tty(&g, tty);
225  } else {
226    owl_global_set_tty(&g, owl_util_get_default_tty());
227  }
228
229  /* setup the built-in styles */
230  owl_function_debugmsg("startup: creating built-in styles");
231  s=owl_malloc(sizeof(owl_style));
232  owl_style_create_internal(s, "default", &owl_stylefunc_default, "Default message formatting");
233  owl_global_add_style(&g, s);
234
235  s=owl_malloc(sizeof(owl_style));
236  owl_style_create_internal(s, "basic", &owl_stylefunc_basic, "Basic message formatting.");
237  owl_global_add_style(&g, s);
238#if 0
239  s=owl_malloc(sizeof(owl_style));
240  owl_style_create_internal(s, "vt", &owl_stylefunc_vt, "VT message formatting.");
241  owl_global_add_style(&g, s);
242#endif
243  s=owl_malloc(sizeof(owl_style));
244  owl_style_create_internal(s, "oneline", &owl_stylefunc_oneline, "Formats for one-line-per-message");
245  owl_global_add_style(&g, s);
246
247  /* setup the default filters */
248  /* the personal filter will need to change again when AIM chat's are
249   *  included.  Also, there should be an %aimme% */
250  owl_function_debugmsg("startup: creating default filters");
251  f=owl_malloc(sizeof(owl_filter));
252  owl_filter_init_fromstring(f, "personal", "isprivate ^true$");
253  owl_list_append_element(owl_global_get_filterlist(&g), f);
254
255  f=owl_malloc(sizeof(owl_filter));
256  owl_filter_init_fromstring(f, "wordwrap", "not ( type ^admin$ or type ^zephyr$ ) ");
257  owl_list_append_element(owl_global_get_filterlist(&g), f);
258
259  f=owl_malloc(sizeof(owl_filter));
260  owl_filter_init_fromstring(f, "trash", "class ^mail$ or opcode ^ping$ or type ^admin$ or ( not login ^none$ )");
261  owl_list_append_element(owl_global_get_filterlist(&g), f);
262
263  f=owl_malloc(sizeof(owl_filter));
264  owl_filter_init_fromstring(f, "ping", "opcode ^ping$");
265  owl_list_append_element(owl_global_get_filterlist(&g), f);
266
267  f=owl_malloc(sizeof(owl_filter));
268  owl_filter_init_fromstring(f, "auto", "opcode ^auto$");
269  owl_list_append_element(owl_global_get_filterlist(&g), f);
270
271  f=owl_malloc(sizeof(owl_filter));
272  owl_filter_init_fromstring(f, "login", "not login ^none$");
273  owl_list_append_element(owl_global_get_filterlist(&g), f);
274
275  f=owl_malloc(sizeof(owl_filter));
276  owl_filter_init_fromstring(f, "reply-lockout", "class ^noc or class ^mail$");
277  owl_list_append_element(owl_global_get_filterlist(&g), f);
278
279  f=owl_malloc(sizeof(owl_filter));
280  owl_filter_init_fromstring(f, "out", "direction ^out$");
281  owl_list_append_element(owl_global_get_filterlist(&g), f);
282
283  f=owl_malloc(sizeof(owl_filter));
284  owl_filter_init_fromstring(f, "aim", "type ^aim$");
285  owl_list_append_element(owl_global_get_filterlist(&g), f);
286
287  f=owl_malloc(sizeof(owl_filter));
288  owl_filter_init_fromstring(f, "zephyr", "type ^zephyr$");
289  owl_list_append_element(owl_global_get_filterlist(&g), f);
290
291  f=owl_malloc(sizeof(owl_filter));
292  owl_filter_init_fromstring(f, "none", "false");
293  owl_list_append_element(owl_global_get_filterlist(&g), f);
294
295  f=owl_malloc(sizeof(owl_filter));
296  owl_filter_init_fromstring(f, "all", "true");
297  owl_list_append_element(owl_global_get_filterlist(&g), f);
298
299  /* set the current view */
300  owl_function_debugmsg("startup: setting the current view");
301  owl_view_create(owl_global_get_current_view(&g), "main", f, owl_global_get_style_by_name(&g, "default"));
302
303  /* AIM init */
304  owl_function_debugmsg("startup: doing AIM initialization");
305  owl_aim_init();
306
307  /* read the config file */
308  owl_function_debugmsg("startup: processing config file");
309  owl_context_set_readconfig(owl_global_get_context(&g));
310  perlerr=owl_perlconfig_readconfig(configfile);
311  if (perlerr) {
312    endwin();
313    owl_function_error("Error parsing configfile: %s\n", perlerr);
314    fprintf(stderr, "\nError parsing configfile: %s\n", perlerr);
315    fflush(stderr);
316    printf("\nError parsing configfile: %s\n", perlerr);
317    fflush(stdout);
318    exit(1);
319  }
320
321  /* if the config defines a formatting function, add 'perl' as a style */
322  if (owl_global_is_config_format(&g)) {
323    owl_function_debugmsg("Found perl formatting");
324    s=owl_malloc(sizeof(owl_style));
325    owl_style_create_perl(s, "perl", "BarnOwl::_format_msg_legacy_wrap",
326                          "User-defined perl style that calls BarnOwl::format_msg"
327                          "with legacy global variable support");
328    owl_global_add_style(&g, s);
329    owl_global_set_default_style(&g, "perl");
330  }
331
332  /* execute the startup function in the configfile */
333  owl_function_debugmsg("startup: executing perl startup, if applicable");
334  perlout = owl_perlconfig_execute("BarnOwl::Hooks::startup();");
335  if (perlout) owl_free(perlout);
336
337    /* process the startup file */
338  owl_function_debugmsg("startup: processing startup file");
339  owl_function_source(NULL);
340
341  /* hold on to the window names for convenience */
342  msgwin=owl_global_get_curs_msgwin(&g);
343  recwin=owl_global_get_curs_recwin(&g);
344  sepwin=owl_global_get_curs_sepwin(&g);
345  typwin=owl_global_get_curs_typwin(&g);
346  tw=owl_global_get_typwin(&g);
347
348  /* welcome message */
349  owl_function_debugmsg("startup: creating splash message");
350  strcpy(startupmsg, "-----------------------------------------------------------------------\n");
351  sprintf(buff,      "Welcome to Owl version %s.  Press 'h' for on-line help. \n", OWL_VERSION_STRING);
352  strcat(startupmsg, buff);
353  strcat(startupmsg, "                                                                       \n");
354  strcat(startupmsg, "This is an UNOFFICIAL DEVELOPMENT BUILD of owl. If you are using this  \n");
355  strcat(startupmsg, "build regularly, please add yourself to dirty-owl-hackers@mit.edu      \n");
356  strcat(startupmsg, "                                                                 ^ ^   \n");
357  strcat(startupmsg, "Any bugs should be reported to dirty-owl-hackers@mit.edu         OvO   \n");
358  strcat(startupmsg, "Do not seek help with this build from bug-owl or ktools.        (   )  \n");
359  strcat(startupmsg, "-----------------------------------------------------------------m-m---\n");
360  owl_function_adminmsg("", startupmsg);
361  sepbar(NULL);
362
363  wrefresh(sepwin);
364
365  /* load zephyr subs */
366  if (initialsubs) {
367    int ret2;
368    owl_function_debugmsg("startup: loading initial zephyr subs");
369
370    /* load default subscriptions */
371    ret=owl_zephyr_loaddefaultsubs();
372   
373    /* load subscriptions from subs file */
374    ret2=owl_zephyr_loadsubs(NULL, 0);
375
376    if (ret || ret2) {
377      owl_function_adminmsg("", "Error loading zephyr subscriptions");
378    } else if (ret2!=-1) {
379      owl_global_add_userclue(&g, OWL_USERCLUE_CLASSES);
380    }
381
382    /* load login subscriptions */
383    if (owl_global_is_loginsubs(&g)) {
384      owl_function_debugmsg("startup: loading login subs");
385      owl_function_loadloginsubs(NULL);
386    }
387  }
388
389  /* First buddy check to sync the list without notifications */
390  owl_function_debugmsg("startup: doing initial zephyr buddy check");
391  /* owl_function_zephyr_buddy_check(0); */
392
393  /* set the startup and default style, based on userclue and presence of a
394   * formatting function */
395  owl_function_debugmsg("startup: setting startup and default style");
396  if (0 != strcmp(owl_global_get_default_style(&g), "__unspecified__")) {
397    /* the style was set by the user: leave it alone */
398  } else if (owl_global_is_config_format(&g)) {
399    owl_global_set_default_style(&g, "perl");
400  } else if (owl_global_is_userclue(&g, OWL_USERCLUE_CLASSES)) {
401    owl_global_set_default_style(&g, "default");
402  } else {
403    owl_global_set_default_style(&g, "basic");
404  }
405
406  /* zlog in if we need to */
407  if (owl_global_is_startuplogin(&g)) {
408    owl_function_debugmsg("startup: doing zlog in");
409    owl_zephyr_zlog_in();
410  }
411
412  owl_function_debugmsg("startup: set style for the view");
413  owl_view_set_style(owl_global_get_current_view(&g), 
414                     owl_global_get_style_by_name(&g, owl_global_get_default_style(&g)));   
415
416  owl_function_debugmsg("startup: setting context interactive");
417  owl_context_set_interactive(owl_global_get_context(&g));
418
419  nexttimediff=10;
420  nexttime=time(NULL);
421
422  owl_function_debugmsg("startup: entering main loop");
423  /* main loop */
424  while (1) {
425
426    /* if a resize has been scheduled, deal with it */
427    owl_global_resize(&g, 0, 0);
428
429    /* these are here in case a resize changes the windows */
430    msgwin=owl_global_get_curs_msgwin(&g);
431    recwin=owl_global_get_curs_recwin(&g);
432    sepwin=owl_global_get_curs_sepwin(&g);
433    typwin=owl_global_get_curs_typwin(&g);
434
435    followlast=owl_global_should_followlast(&g);
436   
437    /* Do AIM stuff */
438    if (owl_global_is_doaimevents(&g)) {
439      owl_aim_process_events();
440
441      if (owl_global_is_aimloggedin(&g)) {
442        if (owl_timer_is_expired(owl_global_get_aim_buddyinfo_timer(&g))) {
443          /* owl_buddylist_request_idletimes(owl_global_get_buddylist(&g)); */
444          owl_timer_reset(owl_global_get_aim_buddyinfo_timer(&g));
445        }
446      }
447    }
448
449    owl_perlconfig_mainloop();
450
451    /* little hack */
452    now=time(NULL);
453    today=localtime(&now);
454    if (today->tm_mon==9 && today->tm_mday==31 && owl_global_get_runtime(&g)<600) {
455      if (time(NULL)>nexttime) {
456        if (nexttimediff==1) {
457          nexttimediff=10;
458        } else {
459          nexttimediff=1;
460        }
461        nexttime+=nexttimediff;
462        owl_hack_animate();
463      }
464    }
465
466    /* Grab incoming messages. */
467    newmsgs=0;
468    zpendcount=0;
469    while(owl_zephyr_zpending() || owl_global_messagequeue_pending(&g)) {
470#ifdef HAVE_LIBZEPHYR
471      struct sockaddr_in from;
472#endif
473      owl_message *m=NULL;
474      owl_filter *f;
475
476      /* grab the new message, stick it in 'm' */
477      if (owl_zephyr_zpending()) {
478#ifdef HAVE_LIBZEPHYR
479        /* grab a zephyr notice, but if we've done 20 without stopping,
480           take a break to process keystrokes etc. */
481        if (zpendcount>20) break;
482        ZReceiveNotice(&notice, &from);
483        zpendcount++;
484       
485        /* is this an ack from a zephyr we sent? */
486        if (owl_zephyr_notice_is_ack(&notice)) {
487          owl_zephyr_handle_ack(&notice);
488          continue;
489        }
490       
491        /* if it's a ping and we're not viewing pings then skip it */
492        if (!owl_global_is_rxping(&g) && !strcasecmp(notice.z_opcode, "ping")) {
493          continue;
494        }
495
496        /* create the new message */
497        m=owl_malloc(sizeof(owl_message));
498        owl_message_create_from_znotice(m, &notice);
499#endif
500      } else if (owl_global_messagequeue_pending(&g)) {
501        /* pick up the non-zephyr message in the message queue */
502        m=owl_global_messageuque_popmsg(&g);
503      } else {
504        /* Not supposed to happen, but we seem to get here on resizes */
505        owl_function_debugmsg("Bottomed out looking for zephyr");
506      }
507
508      /* If we didn't pick up a message for some reason, don't go on */
509      if (m==NULL) {
510        owl_function_debugmsg("m is null in main loop");
511        continue;
512      }
513     
514      /* if this message it on the puntlist, nuke it and continue */
515      if (owl_global_message_is_puntable(&g, m)) {
516        owl_message_free(m);
517        continue;
518      }
519
520      /*  login or logout that should be ignored? */
521      if (owl_global_is_ignorelogins(&g) && owl_message_is_loginout(m)) {
522        owl_message_free(m);
523        continue;
524      }
525
526      /* otherwise add it to the global list */
527      owl_messagelist_append_element(owl_global_get_msglist(&g), m);
528      newmsgs=1;
529
530      /* let the config know the new message has been received */
531      owl_perlconfig_getmsg(m, 0, NULL);
532
533      /* add it to any necessary views; right now there's only the current view */
534      owl_view_consider_message(owl_global_get_current_view(&g), m);
535
536      /* do we need to autoreply? */
537      if (owl_global_is_zaway(&g) && !owl_message_get_attribute_value(m, "isauto")) {
538        if (owl_message_is_type_zephyr(m)) {
539          owl_zephyr_zaway(m);
540        } else if (owl_message_is_type_aim(m)) {
541          if (owl_message_is_private(m)) {
542            owl_function_send_aimawymsg(owl_message_get_sender(m), owl_global_get_zaway_msg(&g));
543          }
544        }
545      }
546
547      /* ring the bell if it's a personal */
548      if (!strcmp(owl_global_get_personalbell(&g), "on")) {
549          if (!owl_message_is_loginout(m) &&
550              !owl_message_is_mail(m) &&
551              owl_message_is_private(m)) {
552            owl_function_beep();
553          }
554      } else if (!strcmp(owl_global_get_personalbell(&g), "off")) {
555        /* do nothing */
556      } else {
557        f=owl_global_get_filter(&g, owl_global_get_personalbell(&g));
558        if (f && owl_filter_message_match(f, m)) {
559          owl_function_beep();
560        }
561      }
562
563
564      /* if it matches the alert filter, do the alert action */
565      f=owl_global_get_filter(&g, owl_global_get_alert_filter(&g));
566      if (f && owl_filter_message_match(f, m)) {
567        owl_function_command(owl_global_get_alert_action(&g));
568      }
569
570      /* if it's a zephyr login or logout, update the zbuddylist */
571      if (owl_message_is_type_zephyr(m) && owl_message_is_loginout(m)) {
572        if (owl_message_is_login(m)) {
573          owl_zbuddylist_adduser(owl_global_get_zephyr_buddylist(&g), owl_message_get_sender(m));
574        } else if (owl_message_is_logout(m)) {
575          owl_zbuddylist_deluser(owl_global_get_zephyr_buddylist(&g), owl_message_get_sender(m));
576        } else {
577          owl_function_error("Internal error: received login notice that is neither login nor logout");
578        }
579      }
580
581      /* check for burning ears message */
582      /* this is an unsupported feature */
583      if (owl_global_is_burningears(&g) && owl_message_is_burningears(m)) {
584        char *buff;
585        buff = owl_sprintf("@i(Burning ears message on class %s)", owl_message_get_class(m));
586        owl_function_adminmsg(buff, "");
587        owl_free(buff);
588        owl_function_beep();
589      }
590
591      /* log the message if we need to */
592      owl_log_message(m);
593    }
594
595    /* is it time to check zbuddies? */
596    if (owl_global_is_pseudologins(&g)) {
597      if (owl_timer_is_expired(owl_global_get_zephyr_buddycheck_timer(&g))) {
598        owl_function_debugmsg("Doing zephyr buddy check");
599        owl_function_zephyr_buddy_check(1);
600        owl_timer_reset(owl_global_get_zephyr_buddycheck_timer(&g));
601      }
602    }
603
604    /* dispatch any muxevents */
605    owl_muxevents_dispatch(owl_global_get_muxevents(&g), 0);
606
607    /* follow the last message if we're supposed to */
608    if (newmsgs && followlast) {
609      owl_function_lastmsg_noredisplay();
610    }
611
612    /* do the newmsgproc thing */
613    if (newmsgs) {
614      owl_function_do_newmsgproc();
615    }
616   
617    /* redisplay if necessary */
618    /* this should be optimized to not run if the new messages won't be displayed */
619    if (newmsgs) {
620      owl_mainwin_redisplay(owl_global_get_mainwin(&g));
621      sepbar(NULL);
622      if (owl_popwin_is_active(owl_global_get_popwin(&g))) {
623        owl_popwin_refresh(owl_global_get_popwin(&g));
624        /* TODO: this is a broken kludge */
625        if (owl_global_get_viewwin(&g)) {
626          owl_viewwin_redisplay(owl_global_get_viewwin(&g), 0);
627        }
628      }
629      owl_global_set_needrefresh(&g);
630    }
631
632    /* if a popwin just came up, refresh it */
633    pw=owl_global_get_popwin(&g);
634    if (owl_popwin_is_active(pw) && owl_popwin_needs_first_refresh(pw)) {
635      owl_popwin_refresh(pw);
636      owl_popwin_no_needs_first_refresh(pw);
637      owl_global_set_needrefresh(&g);
638      /* TODO: this is a broken kludge */
639      if (owl_global_get_viewwin(&g)) {
640        owl_viewwin_redisplay(owl_global_get_viewwin(&g), 0);
641      }
642    }
643
644    /* update the terminal if we need to */
645    if (owl_global_is_needrefresh(&g)) {
646      /* leave the cursor in the appropriate window */
647      if (owl_global_is_typwin_active(&g)) {
648        owl_function_set_cursor(typwin);
649      } else {
650        owl_function_set_cursor(sepwin);
651      }
652      doupdate();
653      owl_global_set_noneedrefresh(&g);
654    }
655
656    /* Handle all keypresses.  If no key has been pressed, sleep for a
657     * little bit, but otherwise do not.  This lets input be grabbed
658     * as quickly as possbile */
659    j=wgetch(typwin);
660    if (j==ERR) {
661      usleep(10);
662    } else {
663      /* find and activate the current keymap.
664       * TODO: this should really get fixed by activating
665       * keymaps as we switch between windows...
666       */
667      if (pw && owl_popwin_is_active(pw) && owl_global_get_viewwin(&g)) {
668        owl_context_set_popless(owl_global_get_context(&g), 
669                                owl_global_get_viewwin(&g));
670        owl_function_activate_keymap("popless");
671      } else if (owl_global_is_typwin_active(&g) 
672                 && owl_editwin_get_style(tw)==OWL_EDITWIN_STYLE_ONELINE) {
673        /*
674          owl_context_set_editline(owl_global_get_context(&g), tw);
675          owl_function_activate_keymap("editline");
676        */
677      } else if (owl_global_is_typwin_active(&g) 
678                 && owl_editwin_get_style(tw)==OWL_EDITWIN_STYLE_MULTILINE) {
679        owl_context_set_editmulti(owl_global_get_context(&g), tw);
680        owl_function_activate_keymap("editmulti");
681      } else {
682        owl_context_set_recv(owl_global_get_context(&g));
683        owl_function_activate_keymap("recv");
684      }
685      /* now actually handle the keypress */
686      ret = owl_keyhandler_process(owl_global_get_keyhandler(&g), j);
687      if (ret!=0 && ret!=1) {
688        owl_function_makemsg("Unable to handle keypress");
689      }
690    }
691
692    /* Log any error signals */
693    {
694      siginfo_t si;
695      int signum;
696      if ((signum = owl_global_get_errsignal_and_clear(&g, &si)) > 0) {
697        owl_function_error("Got unexpected signal: %d %s  (code: %d band: %d  errno: %d)", 
698                           signum, signum==SIGPIPE?"SIGPIPE":"SIG????",
699                           si.si_code, si.si_band, si.si_errno);
700      }
701    }
702
703  }
704}
705
706void sig_handler(int sig, siginfo_t *si, void *data)
707{
708  if (sig==SIGWINCH) {
709    /* we can't inturrupt a malloc here, so it just sets a flag
710     * schedulding a resize for later
711     */
712    owl_function_resize();
713  } else if (sig==SIGPIPE || sig==SIGCHLD) {
714    /* Set a flag and some info that we got the sigpipe
715     * so we can record that we got it and why... */
716    owl_global_set_errsignal(&g, sig, si);
717  } else if (sig==SIGTERM || sig==SIGHUP) {
718    owl_function_quit();
719  }
720
721}
722
723void usage()
724{
725  fprintf(stderr, "Owl version %s\n", OWL_VERSION_STRING);
726  fprintf(stderr, "Usage: owl [-n] [-d] [-D] [-v] [-h] [-c <configfile>] [-t <ttyname>]\n");
727  fprintf(stderr, "  -n      don't load zephyr subscriptions\n");
728  fprintf(stderr, "  -d      enable debugging\n");
729  fprintf(stderr, "  -D      enable debugging and delete previous debug file\n");
730  fprintf(stderr, "  -v      print the Owl version number and exit\n");
731  fprintf(stderr, "  -h      print this help message\n");
732  fprintf(stderr, "  -c      specify an alternate config file\n");
733  fprintf(stderr, "  -t      set the tty name\n");
734}
735
736#if OWL_STDERR_REDIR
737
738/* Replaces stderr with a pipe so that we can read from it.
739 * Returns the fd of the pipe from which stderr can be read. */
740int stderr_replace(void)
741{
742  int pipefds[2];
743  if (0 != pipe(pipefds)) {
744    perror("pipe");
745    owl_function_debugmsg("stderr_replace: pipe FAILED\n");
746    return -1;
747  }
748    owl_function_debugmsg("stderr_replace: pipe: %d,%d\n", pipefds[0], pipefds[1]);
749  if (-1 == dup2(pipefds[1], 2 /*stderr*/)) {
750    owl_function_debugmsg("stderr_replace: dup2 FAILED (%s)\n", strerror(errno));
751    perror("dup2");
752    return -1;
753  }
754  return pipefds[0];
755}
756
757/* Sends stderr (read from rfd) messages to the error console */
758void stderr_redirect_handler(int handle, int rfd, int eventmask, void *data) 
759{
760  int navail, bread;
761  char *buf;
762  /*owl_function_debugmsg("stderr_redirect: called with rfd=%d\n", rfd);*/
763  if (rfd<0) return;
764  if (-1 == ioctl(rfd, FIONREAD, (void*)&navail)) {
765    return;
766  }
767  /*owl_function_debugmsg("stderr_redirect: navail = %d\n", navail);*/
768  if (navail<=0) return;
769  if (navail>256) { navail = 256; }
770  buf = owl_malloc(navail+1);
771  bread = read(rfd, buf, navail);
772  if (buf[navail-1] != '\0') {
773    buf[navail] = '\0';
774  }
775  owl_function_error("Err: %s", buf);
776  owl_free(buf);
777}
778
779#endif /* OWL_STDERR_REDIR */
Note: See TracBrowser for help on using the repository browser.