source: owl.c @ 1fd0b25

barnowl_perlaimdebianowlrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 1fd0b25 was 1c6c4d3, checked in by Erik Nygren <nygren@mit.edu>, 22 years ago
Added owl_sprintf which returns the formatted string, or NULL. The caller must free this string. This will allocate enough memory and thus avoid potential some buffer overrun situations. Started fixing some potential buffer overrun situations. Simple implementation of 'zwrite -m' (doesn't yet log an outgoing message as having been sent.) The "Not logged in or subscribing to messages" error now includes the name of the recipient.
  • Property mode set to 100644
File size: 11.0 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 <sys/param.h>
22#include "owl.h"
23
24static const char fileIdent[] = "$Id$";
25
26int main(int argc, char **argv, char **env) {
27  WINDOW *recwin, *sepwin, *typwin, *msgwin;
28  owl_editwin *tw;
29  owl_popwin *pw;
30  int j, ret, initialsubs, debug, newzephyrs, argcsave, followlast;
31  struct sigaction sigact;
32  char *configfile, *tty, *perlout;
33  char buff[LINE], startupmsg[LINE];
34  char **argvsave;
35  owl_filter *f;
36
37  argcsave=argc;
38  argvsave=argv;
39  configfile=NULL;
40  tty=NULL;
41  debug=0;
42  if (argc>0) {
43    argv++;
44    argc--;
45  }
46  while (argc>0) {
47    if (!strcmp(argv[0], "-n")) {
48      initialsubs=0;
49      argv++;
50      argc--;
51    } else if (!strcmp(argv[0], "-c")) {
52      if (argc<2) {
53        fprintf(stderr, "Too few arguments to -c\n");
54        usage();
55        exit(1);
56      }
57      configfile=argv[1];
58      argv+=2;
59      argc-=2;
60    } else if (!strcmp(argv[0], "-t")) {
61      if (argc<2) {
62        fprintf(stderr, "Too few arguments to -t\n");
63        usage();
64        exit(1);
65      }
66      tty=argv[1];
67      argv+=2;
68      argc-=2;
69    } else if (!strcmp(argv[0], "-d")) {
70      debug=1;
71      argv++;
72      argc--;
73    } else if (!strcmp(argv[0], "-v")) {
74      printf("This is owl version %s\n", OWL_VERSION_STRING);
75      exit(0);
76    } else {
77      fprintf(stderr, "Uknown argument\n");
78      usage();       
79      exit(1);
80    }
81  }
82
83  /* zephyr init */
84  if ((ret = ZInitialize()) != ZERR_NONE) {
85    com_err("owl",ret,"while initializing");
86    exit(1);
87  }
88  if ((ret = ZOpenPort(NULL)) != ZERR_NONE) {
89    com_err("owl",ret,"while opening port");
90    exit(1);
91  }
92
93  /* signal handler */
94  sigact.sa_handler=sig_handler;
95  sigemptyset(&sigact.sa_mask);
96  sigact.sa_flags=0;
97  sigaction(SIGWINCH, &sigact, NULL);
98  sigaction(SIGALRM, &sigact, NULL);
99
100  /* screen init */
101  sprintf(buff, "TERMINFO=%s", TERMINFO);
102  putenv(buff);
103  initscr();
104  start_color();
105  use_default_colors();
106  raw();
107  noecho();
108
109#if 0 /* Removed to prevent flashing of popwin */
110  intrflush(stdscr,FALSE);
111  keypad(stdscr,TRUE);
112  nodelay(stdscr,1);
113  meta(stdscr,TRUE);
114#endif /*0*/
115
116  /* define simple color pairs */
117  if (has_colors() && COLOR_PAIRS>=8) {
118    init_pair(OWL_COLOR_BLACK,   COLOR_BLACK,   -1);
119    init_pair(OWL_COLOR_RED,     COLOR_RED,     -1);
120    init_pair(OWL_COLOR_GREEN,   COLOR_GREEN,   -1);
121    init_pair(OWL_COLOR_YELLOW,  COLOR_YELLOW,  -1);
122    init_pair(OWL_COLOR_BLUE,    COLOR_BLUE,    -1);
123    init_pair(OWL_COLOR_MAGENTA, COLOR_MAGENTA, -1);
124    init_pair(OWL_COLOR_CYAN,    COLOR_CYAN,    -1);
125    init_pair(OWL_COLOR_WHITE,   COLOR_WHITE,   -1);
126  }
127   
128  /* owl init */
129  owl_global_init(&g);
130  if (debug) owl_global_set_debug_on(&g);
131  owl_global_set_startupargs(&g, argcsave, argvsave);
132  owl_global_set_tty(&g, tty);
133  owl_context_set_readconfig(owl_global_get_context(&g));
134
135  /* setup the default filters */
136  f=malloc(sizeof(owl_filter));
137  owl_filter_init_fromstring(f, "personal", "( class ^message$ and instance ^personal$ ) or ( type ^admin$ and recipient .+ )"); /* fix to use admintype */
138  owl_list_append_element(owl_global_get_filterlist(&g), f);
139
140  f=malloc(sizeof(owl_filter));
141  owl_filter_init_fromstring(f, "trash", "class ^mail$ or opcode ^ping$ or type ^admin$ or class ^login$");
142  owl_list_append_element(owl_global_get_filterlist(&g), f);
143
144  f=malloc(sizeof(owl_filter));
145  owl_filter_init_fromstring(f, "reply-lockout", "class ^noc or class ^mail$");
146  owl_list_append_element(owl_global_get_filterlist(&g), f);
147
148  f=malloc(sizeof(owl_filter));
149  owl_filter_init_fromstring(f, "all", "class .*");
150  owl_list_append_element(owl_global_get_filterlist(&g), f);
151
152  /* set the current view */
153  owl_view_create(owl_global_get_current_view(&g), f);
154
155  /* read the config file */
156  ret=owl_readconfig(configfile);
157  if (ret) {
158    endwin();
159    printf("\nError parsing configfile\n");
160    exit(1);
161  }
162  perlout = owl_config_execute("owl::startup();");
163  if (perlout) owl_free(perlout);
164  owl_function_debugmsg("-- Owl Startup --");
165 
166  /* hold on to the window names for convenience */
167  msgwin=owl_global_get_curs_msgwin(&g);
168  recwin=owl_global_get_curs_recwin(&g);
169  sepwin=owl_global_get_curs_sepwin(&g);
170  typwin=owl_global_get_curs_typwin(&g);
171
172  tw=owl_global_get_typwin(&g);
173
174  wrefresh(sepwin);
175
176  /* load zephyr subs */
177  ret=owl_zephyr_loadsubs(NULL);
178  if (ret!=-1) {
179    owl_global_add_userclue(&g, OWL_USERCLUE_CLASSES);
180  }
181
182  /* load login subs */
183  if (owl_global_is_loginsubs(&g)) {
184    loadloginsubs(NULL);
185  }
186
187  /* zlog in if we need to */
188  if (owl_global_is_startuplogin(&g)) {
189    owl_function_zlog_in();
190  }
191
192  /* welcome message */
193  sprintf(buff, "Welcome to owl version %s.\n", OWL_VERSION_STRING);
194  strcpy(startupmsg, "-------------------------------------------------------------------------\n");
195  strcat(startupmsg, buff);
196  strcat(startupmsg, "Press 'h' for on line help.                                   ^ ^        \n");
197  strcat(startupmsg, "                                                              OvO        \n");
198  strcat(startupmsg, "Please report any bugs or suggestions to bug-owl@mit.edu     (   )       \n");
199  strcat(startupmsg, "--------------------------------------------------------------m-m--------\n");
200 
201  owl_function_adminmsg("", startupmsg);
202  /* owl_function_makemsg(buff); */
203  sepbar(NULL);
204 
205  owl_context_set_interactive(owl_global_get_context(&g));
206
207  /* main loop */
208  while (1) {
209
210    /* if a resize has been scheduled, deal with it */
211    owl_global_resize(&g, 0, 0);
212
213    /* these are here in case a resize changes the windows */
214    msgwin=owl_global_get_curs_msgwin(&g);
215    recwin=owl_global_get_curs_recwin(&g);
216    sepwin=owl_global_get_curs_sepwin(&g);
217    typwin=owl_global_get_curs_typwin(&g);
218
219    followlast=owl_global_should_followlast(&g);
220
221    /* grab incoming zephyrs */
222    newzephyrs=0;
223    while(ZPending()) {
224      ZNotice_t notice;
225      struct sockaddr_in from;
226      owl_message *m;
227
228      ZReceiveNotice(&notice, &from);
229
230      /* is this an ack from a zephyr we sent? */
231      if (owl_zephyr_notice_is_ack(&notice)) {
232        owl_zephyr_handle_ack(&notice);
233        continue;
234      }
235     
236      /* if it's a ping and we're not viewing pings then skip it */
237      if (!owl_global_is_rxping(&g) && !strcasecmp(notice.z_opcode, "ping")) {
238        continue;
239      }
240
241      /* create the new message */
242      m=owl_malloc(sizeof(owl_message));
243      owl_message_create_from_zephyr(m, &notice);
244     
245      /* if it's on the puntlist then, nuke it and continue */
246      if (owl_global_message_is_puntable(&g, m)) {
247        owl_message_free(m);
248        continue;
249      }
250
251      /* otherwise add it to the global list */
252      owl_messagelist_append_element(owl_global_get_msglist(&g), m);
253      newzephyrs=1;
254
255      /* let the config know the new message has been received */
256      owl_config_getmsg(m, 0);
257
258      /* add it to any necessary views; right now there's only the current view */
259      owl_view_consider_message(owl_global_get_current_view(&g), m);
260
261      /* do we need to autoreply? */
262      if (owl_global_is_zaway(&g)) {
263        owl_zephyr_zaway(m);
264      }
265
266      /* ring the bell if it's a personal */
267      if (owl_global_is_personalbell(&g) && owl_message_is_personal(m)) {
268        owl_function_beep();
269        owl_global_set_needrefresh(&g);
270      }
271
272      /* check for burning ears message */
273      /* this is an unsupported feature */
274      if (owl_global_is_burningears(&g) && owl_message_is_burningears(m)) {
275        char *buff;
276        buff = owl_sprintf("@i(Burning ears message on class %s)", owl_message_get_class(m));
277        /* owl_function_makemsg(buff); */
278        owl_function_adminmsg(buff, "");
279        owl_free(buff);
280        owl_function_beep();
281      }
282
283      /* log the zephyr if we need to */
284      if (owl_global_is_logging(&g) || owl_global_is_classlogging(&g)) {
285        owl_log_incoming(m);
286      }
287    }
288
289    /* follow the last message if we're supposed to */
290    if (newzephyrs && followlast) {
291      owl_function_lastmsg_noredisplay();
292    }
293   
294    /* redisplay if necessary */
295    if (newzephyrs) {
296      owl_mainwin_redisplay(owl_global_get_mainwin(&g));
297      sepbar(NULL);
298      if (owl_popwin_is_active(owl_global_get_popwin(&g))) {
299        owl_popwin_refresh(owl_global_get_popwin(&g));
300        /* TODO: this is a broken kludge */
301        if (owl_global_get_viewwin(&g)) {
302          owl_viewwin_redisplay(owl_global_get_viewwin(&g), 0);
303        }
304      }
305      owl_global_set_needrefresh(&g);
306    }
307
308    /* if a popwin just came up, refresh it */
309    pw=owl_global_get_popwin(&g);
310    if (owl_popwin_is_active(pw) && owl_popwin_needs_first_refresh(pw)) {
311      owl_popwin_refresh(pw);
312      owl_popwin_no_needs_first_refresh(pw);
313      owl_global_set_needrefresh(&g);
314      /* TODO: this is a broken kludge */
315      if (owl_global_get_viewwin(&g)) {
316        owl_viewwin_redisplay(owl_global_get_viewwin(&g), 0);
317      }
318    }
319
320    /* update the terminal if we need to */
321    if (owl_global_is_needrefresh(&g)) {
322      /* leave the cursor in the appropriate window */
323      if (owl_global_is_typwin_active(&g)) {
324        owl_function_set_cursor(typwin);
325      } else {
326        owl_function_set_cursor(sepwin);
327      }
328      doupdate();
329      owl_global_set_noneedrefresh(&g);
330    }
331
332    /* handle all keypresses */
333    j=wgetch(typwin);
334    if (j==ERR) {
335      usleep(10);
336      continue;
337    }
338    /* find and activate the current keymap.
339     * TODO: this should really get fixed by activating
340     * keymaps as we switch between windows...
341     */
342    if (pw && owl_popwin_is_active(pw) && owl_global_get_viewwin(&g)) {
343      owl_context_set_popless(owl_global_get_context(&g), 
344                              owl_global_get_viewwin(&g));
345      owl_function_activate_keymap("popless");
346    } else if (owl_global_is_typwin_active(&g) 
347               && owl_editwin_get_style(tw)==OWL_EDITWIN_STYLE_ONELINE) {
348      owl_context_set_editline(owl_global_get_context(&g), tw);
349      owl_function_activate_keymap("editline");
350    } else if (owl_global_is_typwin_active(&g) 
351               && owl_editwin_get_style(tw)==OWL_EDITWIN_STYLE_MULTILINE) {
352      owl_context_set_editmulti(owl_global_get_context(&g), tw);
353      owl_function_activate_keymap("editmulti");
354    } else {
355      owl_context_set_recv(owl_global_get_context(&g));
356      owl_function_activate_keymap("recv");
357    }
358    /* now actually handle the keypress */
359    ret = owl_keyhandler_process(owl_global_get_keyhandler(&g), j);
360    if (ret!=0 && ret!=1) {
361      owl_function_makemsg("Unable to handle keypress");
362    }
363  }
364
365}
366
367void sig_handler(int sig) {
368  if (sig==SIGWINCH) {
369    /* we can't inturrupt a malloc here, so it just sets a flag */
370    owl_function_resize();
371  }
372}
373
374void usage() {
375  fprintf(stderr, "Usage: owl [-n] [-d] [-v] [-c <configfile>] [-t <ttyname>]\n");
376}
Note: See TracBrowser for help on using the repository browser.