source: owl.c @ fd93b41

barnowl_perlaimdebianowlrelease-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since fd93b41 was 3abf28b, checked in by James M. Kretchmar <kretch@mit.edu>, 18 years ago
make smartnarrow work for AIM (though it will crash on names with spaces) don't set an away message by default better default format bold them like personal zephyrs same with terminal bell do some basic HTML stripping (buggy, in progress)
  • Property mode set to 100644
File size: 14.2 KB
Line 
1/* Written by James Kretchmar, MIT
2 *
3 * Copyright 2001 Massachusetts Institute of Technology
4 *
5 * Permission to use, copy, modify, and distribute this software and
6 * its documentation for any purpose and without fee is hereby
7 * granted, provided that the above copyright notice and this
8 * permission notice appear in all copies and in supporting
9 * documentation.  No representation is made about the suitability of
10 * this software for any purpose.  It is provided "as is" without
11 * express or implied warranty.
12 */
13
14#include <stdio.h>
15#include <unistd.h>
16#include <stdlib.h>
17#include <string.h>
18#include <zephyr/zephyr.h>
19#include <com_err.h>
20#include <signal.h>
21#include <time.h>
22#include <sys/param.h>
23#include <sys/types.h>
24#include "owl.h"
25
26static const char fileIdent[] = "$Id$";
27
28int main(int argc, char **argv, char **env) {
29  WINDOW *recwin, *sepwin, *typwin, *msgwin;
30  owl_editwin *tw;
31  owl_popwin *pw;
32  int j, ret, initialsubs, debug, argcsave, followlast;
33  int newmsgs, zpendcount, nexttimediff;
34  struct sigaction sigact;
35  char *configfile, *tty, *perlout, **argvsave, buff[LINE], startupmsg[LINE];
36  owl_filter *f;
37  time_t nexttime, now;
38  struct tm *today;
39
40  argcsave=argc;
41  argvsave=argv;
42  configfile=NULL;
43  tty=NULL;
44  debug=0;
45  if (argc>0) {
46    argv++;
47    argc--;
48  }
49  while (argc>0) {
50    if (!strcmp(argv[0], "-n")) {
51      initialsubs=0;
52      argv++;
53      argc--;
54    } else if (!strcmp(argv[0], "-c")) {
55      if (argc<2) {
56        fprintf(stderr, "Too few arguments to -c\n");
57        usage();
58        exit(1);
59      }
60      configfile=argv[1];
61      argv+=2;
62      argc-=2;
63    } else if (!strcmp(argv[0], "-t")) {
64      if (argc<2) {
65        fprintf(stderr, "Too few arguments to -t\n");
66        usage();
67        exit(1);
68      }
69      tty=argv[1];
70      argv+=2;
71      argc-=2;
72    } else if (!strcmp(argv[0], "-d")) {
73      debug=1;
74      argv++;
75      argc--;
76    } else if (!strcmp(argv[0], "-v")) {
77      printf("This is owl version %s\n", OWL_VERSION_STRING);
78      exit(0);
79    } else {
80      fprintf(stderr, "Uknown argument\n");
81      usage();       
82      exit(1);
83    }
84  }
85
86  /* zephyr init */
87  if ((ret = ZInitialize()) != ZERR_NONE) {
88    com_err("owl",ret,"while initializing");
89    exit(1);
90  }
91  if ((ret = ZOpenPort(NULL)) != ZERR_NONE) {
92    com_err("owl",ret,"while opening port");
93    exit(1);
94  }
95
96  /* signal handler */
97  sigact.sa_handler=sig_handler;
98  sigemptyset(&sigact.sa_mask);
99  sigact.sa_flags=0;
100  sigaction(SIGWINCH, &sigact, NULL);
101  sigaction(SIGALRM, &sigact, NULL);
102
103  /* screen init */
104  sprintf(buff, "TERMINFO=%s", TERMINFO);
105  putenv(buff);
106  initscr();
107  start_color();
108#ifdef HAVE_USE_DEFAULT_COLORS
109  use_default_colors();
110#endif
111  raw();
112  noecho();
113
114  /* define simple color pairs */
115  if (has_colors() && COLOR_PAIRS>=8) {
116    init_pair(OWL_COLOR_BLACK,   COLOR_BLACK,   -1);
117    init_pair(OWL_COLOR_RED,     COLOR_RED,     -1);
118    init_pair(OWL_COLOR_GREEN,   COLOR_GREEN,   -1);
119    init_pair(OWL_COLOR_YELLOW,  COLOR_YELLOW,  -1);
120    init_pair(OWL_COLOR_BLUE,    COLOR_BLUE,    -1);
121    init_pair(OWL_COLOR_MAGENTA, COLOR_MAGENTA, -1);
122    init_pair(OWL_COLOR_CYAN,    COLOR_CYAN,    -1);
123    init_pair(OWL_COLOR_WHITE,   COLOR_WHITE,   -1);
124  }
125   
126  /* owl init */
127  owl_global_init(&g);
128  if (debug) owl_global_set_debug_on(&g);
129  owl_global_set_startupargs(&g, argcsave, argvsave);
130  owl_context_set_readconfig(owl_global_get_context(&g));
131
132  /* set the tty, either from the command line, or by figuring it out */
133  if (tty) {
134    owl_global_set_tty(&g, tty);
135  } else {
136    owl_global_set_tty(&g, owl_util_get_default_tty());
137  }
138
139  /* setup the default filters */
140
141  /* the personal filter will need to change again when AIM chat's are
142   *  included.  Also, there should be an %aimme% */
143  f=malloc(sizeof(owl_filter));
144  owl_filter_init_fromstring(f, "personal", "( type ^zephyr$ "
145                             "and class ^message$ and instance ^personal$ "
146                             "and ( recipient ^%me%$ or sender ^%me%$ ) ) "
147                             "or ( type ^aim$ )");
148  owl_list_append_element(owl_global_get_filterlist(&g), f);
149
150  f=malloc(sizeof(owl_filter));
151  owl_filter_init_fromstring(f, "trash", "class ^mail$ or opcode ^ping$ or type ^admin$ or class ^login$");
152  owl_list_append_element(owl_global_get_filterlist(&g), f);
153
154  f=malloc(sizeof(owl_filter));
155  owl_filter_init_fromstring(f, "ping", "opcode ^ping$");
156  owl_list_append_element(owl_global_get_filterlist(&g), f);
157
158  f=malloc(sizeof(owl_filter));
159  owl_filter_init_fromstring(f, "auto", "opcode ^auto$");
160  owl_list_append_element(owl_global_get_filterlist(&g), f);
161
162  f=malloc(sizeof(owl_filter));
163  owl_filter_init_fromstring(f, "login", "class ^login$");
164  owl_list_append_element(owl_global_get_filterlist(&g), f);
165
166  f=malloc(sizeof(owl_filter));
167  owl_filter_init_fromstring(f, "reply-lockout", "class ^noc or class ^mail$");
168  owl_list_append_element(owl_global_get_filterlist(&g), f);
169
170  f=malloc(sizeof(owl_filter));
171  owl_filter_init_fromstring(f, "out", "direction ^out$");
172  owl_list_append_element(owl_global_get_filterlist(&g), f);
173
174  f=malloc(sizeof(owl_filter));
175  owl_filter_init_fromstring(f, "aim", "type ^aim$");
176  owl_list_append_element(owl_global_get_filterlist(&g), f);
177
178  f=malloc(sizeof(owl_filter));
179  owl_filter_init_fromstring(f, "zephyr", "type ^zephyr$");
180  owl_list_append_element(owl_global_get_filterlist(&g), f);
181
182  f=malloc(sizeof(owl_filter));
183  owl_filter_init_fromstring(f, "none", "false");
184  owl_list_append_element(owl_global_get_filterlist(&g), f);
185
186  f=malloc(sizeof(owl_filter));
187  owl_filter_init_fromstring(f, "all", "true");
188  owl_list_append_element(owl_global_get_filterlist(&g), f);
189
190  /* set the current view */
191  owl_view_create(owl_global_get_current_view(&g), f);
192
193  /* read the config file */
194  ret=owl_readconfig(configfile);
195  if (ret) {
196    endwin();
197    printf("\nError parsing configfile\n");
198    exit(1);
199  }
200
201  /* execute the startup function in the configfile */
202  perlout = owl_config_execute("owl::startup();");
203  if (perlout) owl_free(perlout);
204  owl_function_debugmsg("-- Owl Startup --");
205 
206  /* hold on to the window names for convenience */
207  msgwin=owl_global_get_curs_msgwin(&g);
208  recwin=owl_global_get_curs_recwin(&g);
209  sepwin=owl_global_get_curs_sepwin(&g);
210  typwin=owl_global_get_curs_typwin(&g);
211  tw=owl_global_get_typwin(&g);
212
213  wrefresh(sepwin);
214
215  /* load zephyr subs */
216  ret=owl_zephyr_loadsubs(NULL);
217  if (ret!=-1) {
218    owl_global_add_userclue(&g, OWL_USERCLUE_CLASSES);
219  }
220
221  /* load login subs */
222  if (owl_global_is_loginsubs(&g)) {
223    owl_function_loadloginsubs(NULL);
224  }
225
226  /* zlog in if we need to */
227  if (owl_global_is_startuplogin(&g)) {
228    owl_zephyr_zlog_in();
229  }
230
231  /* AIM init */
232  owl_aim_init();
233
234  /* welcome message */
235  strcpy(startupmsg, "-------------------------------------------------------------------------\n");
236  sprintf(buff,      "Welcome to owl version %s.  Press 'h' for on line help. \n", OWL_VERSION_STRING);
237  strcat(startupmsg, buff);
238  strcat(startupmsg, "                                                                         \n");
239  strcat(startupmsg, "If you would like to receive release announcments about owl you can join \n");
240  strcat(startupmsg, "the owl-users@mit.edu mailing list.  MIT users can add themselves,       \n");
241  strcat(startupmsg, "otherwise send a request to owner-owl-users@mit.edu.               ^ ^   \n");
242  strcat(startupmsg, "                                                                   OvO   \n");
243  strcat(startupmsg, "Please report any bugs or suggestions to bug-owl@mit.edu          (   )  \n");
244  strcat(startupmsg, "-------------------------------------------------------------------m-m---\n");
245  owl_function_adminmsg("", startupmsg);
246  sepbar(NULL);
247 
248  owl_context_set_interactive(owl_global_get_context(&g));
249
250  nexttimediff=10;
251  nexttime=time(NULL);
252
253  /* main loop */
254  while (1) {
255
256    /* if a resize has been scheduled, deal with it */
257    owl_global_resize(&g, 0, 0);
258
259    /* these are here in case a resize changes the windows */
260    msgwin=owl_global_get_curs_msgwin(&g);
261    recwin=owl_global_get_curs_recwin(&g);
262    sepwin=owl_global_get_curs_sepwin(&g);
263    typwin=owl_global_get_curs_typwin(&g);
264
265    followlast=owl_global_should_followlast(&g);
266
267    /* little hack */
268    now=time(NULL);
269    today=localtime(&now);
270    if (today->tm_mon==9 && today->tm_mday==31 && owl_global_get_runtime(&g)<600) {
271      if (time(NULL)>nexttime) {
272        if (nexttimediff==1) {
273          nexttimediff=10;
274        } else {
275          nexttimediff=1;
276        }
277        nexttime+=nexttimediff;
278        owl_hack_animate();
279      }
280    }
281
282    /* grab incoming zephyrs */
283    newmsgs=0;
284    zpendcount=0;
285    while(ZPending() || owl_global_messagequeue_pending(&g)) {
286      ZNotice_t notice;
287      struct sockaddr_in from;
288      owl_message *m;
289      owl_filter *f;
290
291      if (ZPending()) {
292        /* grab a zephyr notice, but if we've done 20 without stopping,
293           take a break to process keystrokes etc. */
294        if (zpendcount>20) break;
295        ZReceiveNotice(&notice, &from);
296        zpendcount++;
297       
298        /* is this an ack from a zephyr we sent? */
299        if (owl_zephyr_notice_is_ack(&notice)) {
300          owl_zephyr_handle_ack(&notice);
301          continue;
302        }
303       
304        /* if it's a ping and we're not viewing pings then skip it */
305        if (!owl_global_is_rxping(&g) && !strcasecmp(notice.z_opcode, "ping")) {
306          continue;
307        }
308
309        /* create the new message */
310        m=owl_malloc(sizeof(owl_message));
311        owl_message_create_from_znotice(m, &notice);
312      } else if (owl_global_messagequeue_pending(&g)) {
313        m=owl_global_messageuque_popmsg(&g);
314      }
315     
316      /* if it's on the puntlist then, nuke it and continue */
317      if (owl_global_message_is_puntable(&g, m)) {
318        owl_message_free(m);
319        continue;
320      }
321
322      /* otherwise add it to the global list */
323      owl_messagelist_append_element(owl_global_get_msglist(&g), m);
324      newmsgs=1;
325
326      /* let the config know the new message has been received */
327      owl_config_getmsg(m, 0);
328
329      /* add it to any necessary views; right now there's only the current view */
330      owl_view_consider_message(owl_global_get_current_view(&g), m);
331
332      /* do we need to autoreply? */
333      if (owl_global_is_zaway(&g)) {
334        owl_zephyr_zaway(m);
335      }
336
337      /* ring the bell if it's a personal */
338      if (owl_global_is_personalbell(&g) &&
339          (owl_message_is_personal(m) ||
340          (owl_message_is_type_aim(m) && owl_message_is_to_me(m)))) {
341        owl_function_beep();
342      }
343
344      /* if it matches the alert filter, do the alert action */
345      f=owl_global_get_filter(&g, owl_global_get_alert_filter(&g));
346      if (f && owl_filter_message_match(f, m)) {
347        owl_function_command(owl_global_get_alert_action(&g));
348      }
349
350      /* check for burning ears message */
351      /* this is an unsupported feature */
352      if (owl_global_is_burningears(&g) && owl_message_is_burningears(m)) {
353        char *buff;
354        buff = owl_sprintf("@i(Burning ears message on class %s)", owl_message_get_class(m));
355        /* owl_function_makemsg(buff); */
356        owl_function_adminmsg(buff, "");
357        owl_free(buff);
358        owl_function_beep();
359      }
360
361      /* log the message if we need to */
362      if (owl_global_is_logging(&g) || owl_global_is_classlogging(&g)) {
363        owl_log_incoming(m);
364      }
365    }
366
367    /* If we're logged into AIM, do AIM stuff */
368    if (owl_global_is_aimloggedin(&g)) {
369      owl_function_debugmsg("Doing aim processing");
370      owl_aim_process_events();
371    }
372
373    /* follow the last message if we're supposed to */
374    if (newmsgs && followlast) {
375      owl_function_lastmsg_noredisplay();
376    }
377
378    /* do the newmsgproc thing */
379    if (newmsgs) {
380      owl_function_do_newmsgproc();
381    }
382   
383    /* redisplay if necessary */
384    /* this should be optimized to not run if the new messages won't be displayed */
385    if (newmsgs) {
386      owl_mainwin_redisplay(owl_global_get_mainwin(&g));
387      sepbar(NULL);
388      if (owl_popwin_is_active(owl_global_get_popwin(&g))) {
389        owl_popwin_refresh(owl_global_get_popwin(&g));
390        /* TODO: this is a broken kludge */
391        if (owl_global_get_viewwin(&g)) {
392          owl_viewwin_redisplay(owl_global_get_viewwin(&g), 0);
393        }
394      }
395      owl_global_set_needrefresh(&g);
396    }
397
398    /* if a popwin just came up, refresh it */
399    pw=owl_global_get_popwin(&g);
400    if (owl_popwin_is_active(pw) && owl_popwin_needs_first_refresh(pw)) {
401      owl_popwin_refresh(pw);
402      owl_popwin_no_needs_first_refresh(pw);
403      owl_global_set_needrefresh(&g);
404      /* TODO: this is a broken kludge */
405      if (owl_global_get_viewwin(&g)) {
406        owl_viewwin_redisplay(owl_global_get_viewwin(&g), 0);
407      }
408    }
409
410    /* update the terminal if we need to */
411    if (owl_global_is_needrefresh(&g)) {
412      /* leave the cursor in the appropriate window */
413      if (owl_global_is_typwin_active(&g)) {
414        owl_function_set_cursor(typwin);
415      } else {
416        owl_function_set_cursor(sepwin);
417      }
418      doupdate();
419      owl_global_set_noneedrefresh(&g);
420    }
421
422    /* Handle all keypresses.
423     * If no key has been pressed sleep for a little bit, but
424     * otherwise do not, this lets input be grabbed as quickly
425     * as possbile */
426    j=wgetch(typwin);
427    if (j==ERR) {
428      usleep(10);
429      continue;
430    }
431    /* find and activate the current keymap.
432     * TODO: this should really get fixed by activating
433     * keymaps as we switch between windows...
434     */
435    if (pw && owl_popwin_is_active(pw) && owl_global_get_viewwin(&g)) {
436      owl_context_set_popless(owl_global_get_context(&g), 
437                              owl_global_get_viewwin(&g));
438      owl_function_activate_keymap("popless");
439    } else if (owl_global_is_typwin_active(&g) 
440               && owl_editwin_get_style(tw)==OWL_EDITWIN_STYLE_ONELINE) {
441      owl_context_set_editline(owl_global_get_context(&g), tw);
442      owl_function_activate_keymap("editline");
443    } else if (owl_global_is_typwin_active(&g) 
444               && owl_editwin_get_style(tw)==OWL_EDITWIN_STYLE_MULTILINE) {
445      owl_context_set_editmulti(owl_global_get_context(&g), tw);
446      owl_function_activate_keymap("editmulti");
447    } else {
448      owl_context_set_recv(owl_global_get_context(&g));
449      owl_function_activate_keymap("recv");
450    }
451    /* now actually handle the keypress */
452    ret = owl_keyhandler_process(owl_global_get_keyhandler(&g), j);
453    if (ret!=0 && ret!=1) {
454      owl_function_makemsg("Unable to handle keypress");
455    }
456  }
457}
458
459void sig_handler(int sig) {
460  if (sig==SIGWINCH) {
461    /* we can't inturrupt a malloc here, so it just sets a flag */
462    owl_function_resize();
463  }
464}
465
466void usage() {
467  fprintf(stderr, "Usage: owl [-n] [-d] [-v] [-c <configfile>] [-t <ttyname>]\n");
468}
Note: See TracBrowser for help on using the repository browser.